blob: 357f864c15e26e7a8b8f036a1a1b71513f790729 [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.com52a5dcb2012-01-17 16:01:37 +000096
97 fEdgeAANumEdges = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000098 }
99
100 ///////////////////////////////////////////////////////////////////////////
101 /// @name Color
102 ////
103
104 /**
105 * Sets color for next draw to a premultiplied-alpha color.
106 *
107 * @param color the color to set.
108 */
109 void setColor(GrColor color) { fColor = color; }
110
111 GrColor getColor() const { return fColor; }
112
113 /**
114 * Sets the color to be used for the next draw to be
115 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
116 *
117 * @param alpha The alpha value to set as the color.
118 */
119 void setAlpha(uint8_t a) {
120 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
121 }
122
123 /**
124 * Add a color filter that can be represented by a color and a mode. Applied
125 * after color-computing texture stages.
126 */
127 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
128 fColorFilterColor = c;
129 fColorFilterMode = mode;
130 }
131
132 GrColor getColorFilterColor() const { return fColorFilterColor; }
133 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
134
135 /// @}
136
137 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000138 /// @name Coverage
139 ////
140
141 /**
142 * Sets a constant fractional coverage to be applied to the draw. The
143 * initial value (after construction or reset()) is 0xff. The constant
144 * coverage is ignored when per-vertex coverage is provided.
145 */
146 void setCoverage(uint8_t coverage) {
147 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
148 }
149
150 /**
151 * Version of above that specifies 4 channel per-vertex color. The value
152 * should be premultiplied.
153 */
154 void setCoverage4(GrColor coverage) {
155 fCoverage = coverage;
156 }
157
158 GrColor getCoverage() const {
159 return fCoverage;
160 }
161
162 /// @}
163
164 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000165 /// @name Textures
166 ////
167
168 /**
169 * Sets the texture used at the next drawing call
170 *
171 * @param stage The texture stage for which the texture will be set
172 *
173 * @param texture The texture to set. Can be NULL though there is no
174 * advantage to settings a NULL texture if doing non-textured drawing
175 */
176 void setTexture(int stage, GrTexture* texture) {
177 GrAssert((unsigned)stage < kNumStages);
robertphillips@google.com1942c052012-05-03 17:58:27 +0000178
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000179 if (isBehaviorEnabled(kTexturesNeedRef_BehaviorBit)) {
robertphillips@google.com1942c052012-05-03 17:58:27 +0000180 // If we don't clear out the current texture before unreffing
181 // it we can get into an infinite loop as the GrGLTexture's
182 // onRelease method recursively calls setTexture
183 GrTexture* temp = fTextures[stage];
184 fTextures[stage] = NULL;
185
186 SkSafeRef(texture);
187 SkSafeUnref(temp);
188 }
189
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000190 fTextures[stage] = texture;
191 }
192
193 /**
194 * Retrieves the currently set texture.
195 *
196 * @return The currently set texture. The return value will be NULL if no
197 * texture has been set, NULL was most recently passed to
198 * setTexture, or the last setTexture was destroyed.
199 */
200 const GrTexture* getTexture(int stage) const {
201 GrAssert((unsigned)stage < kNumStages);
202 return fTextures[stage];
203 }
204 GrTexture* getTexture(int stage) {
205 GrAssert((unsigned)stage < kNumStages);
206 return fTextures[stage];
207 }
208
209 /// @}
210
211 ///////////////////////////////////////////////////////////////////////////
212 /// @name Samplers
213 ////
214
215 /**
216 * Returns the current sampler for a stage.
217 */
218 const GrSamplerState& getSampler(int stage) const {
219 GrAssert((unsigned)stage < kNumStages);
220 return fSamplerStates[stage];
221 }
222
223 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000224 * Writable pointer to a stage's sampler.
225 */
226 GrSamplerState* sampler(int stage) {
227 GrAssert((unsigned)stage < kNumStages);
228 return fSamplerStates + stage;
229 }
230
231 /**
232 * Preconcats the matrix of all samplers in the mask with the same matrix.
233 */
234 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
235 GrAssert(!(stageMask & kIllegalStageMaskBits));
236 for (int i = 0; i < kNumStages; ++i) {
237 if ((1 << i) & stageMask) {
238 fSamplerStates[i].preConcatMatrix(matrix);
239 }
240 }
241 }
242
243 /// @}
244
245 ///////////////////////////////////////////////////////////////////////////
246 /// @name Coverage / Color Stages
247 ////
248
249 /**
250 * A common pattern is to compute a color with the initial stages and then
251 * modulate that color by a coverage value in later stage(s) (AA, mask-
252 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
253 * computed based on the pre-coverage-modulated color. The division of
254 * stages between color-computing and coverage-computing is specified by
255 * this method. Initially this is kNumStages (all stages
256 * are color-computing).
257 */
258 void setFirstCoverageStage(int firstCoverageStage) {
259 GrAssert((unsigned)firstCoverageStage <= kNumStages);
260 fFirstCoverageStage = firstCoverageStage;
261 }
262
263 /**
264 * Gets the index of the first coverage-computing stage.
265 */
266 int getFirstCoverageStage() const {
267 return fFirstCoverageStage;
268 }
269
270 ///@}
271
272 ///////////////////////////////////////////////////////////////////////////
273 /// @name Blending
274 ////
275
276 /**
277 * Sets the blending function coeffecients.
278 *
279 * The blend function will be:
280 * D' = sat(S*srcCoef + D*dstCoef)
281 *
282 * where D is the existing destination color, S is the incoming source
283 * color, and D' is the new destination color that will be written. sat()
284 * is the saturation function.
285 *
286 * @param srcCoef coeffecient applied to the src color.
287 * @param dstCoef coeffecient applied to the dst color.
288 */
289 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
290 fSrcBlend = srcCoeff;
291 fDstBlend = dstCoeff;
292 #if GR_DEBUG
293 switch (dstCoeff) {
294 case kDC_BlendCoeff:
295 case kIDC_BlendCoeff:
296 case kDA_BlendCoeff:
297 case kIDA_BlendCoeff:
298 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
299 "coverage stages.\n");
300 break;
301 default:
302 break;
303 }
304 switch (srcCoeff) {
305 case kSC_BlendCoeff:
306 case kISC_BlendCoeff:
307 case kSA_BlendCoeff:
308 case kISA_BlendCoeff:
309 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
310 "coverage stages.\n");
311 break;
312 default:
313 break;
314 }
315 #endif
316 }
317
318 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
319 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
320
321 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
322 GrBlendCoeff* dstBlendCoeff) const {
323 *srcBlendCoeff = fSrcBlend;
324 *dstBlendCoeff = fDstBlend;
325 }
326
327 /**
328 * Sets the blending function constant referenced by the following blending
329 * coeffecients:
330 * kConstC_BlendCoeff
331 * kIConstC_BlendCoeff
332 * kConstA_BlendCoeff
333 * kIConstA_BlendCoeff
334 *
335 * @param constant the constant to set
336 */
337 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
338
339 /**
340 * Retrieves the last value set by setBlendConstant()
341 * @return the blending constant value
342 */
343 GrColor getBlendConstant() const { return fBlendConstant; }
344
345 /// @}
346
347 ///////////////////////////////////////////////////////////////////////////
348 /// @name View Matrix
349 ////
350
351 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000352 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000353 *
354 * In the post-view-matrix space the rectangle [0,w]x[0,h]
355 * fully covers the render target. (w and h are the width and height of the
356 * the rendertarget.)
357 */
358 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
359
360 /**
361 * Gets a writable pointer to the view matrix.
362 */
363 GrMatrix* viewMatrix() { return &fViewMatrix; }
364
365 /**
366 * Multiplies the current view matrix by a matrix
367 *
368 * After this call V' = V*m where V is the old view matrix,
369 * m is the parameter to this function, and V' is the new view matrix.
370 * (We consider positions to be column vectors so position vector p is
371 * transformed by matrix X as p' = X*p.)
372 *
373 * @param m the matrix used to modify the view matrix.
374 */
375 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
376
377 /**
378 * Multiplies the current view matrix by a matrix
379 *
380 * After this call V' = m*V where V is the old view matrix,
381 * m is the parameter to this function, and V' is the new view matrix.
382 * (We consider positions to be column vectors so position vector p is
383 * transformed by matrix X as p' = X*p.)
384 *
385 * @param m the matrix used to modify the view matrix.
386 */
387 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
388
389 /**
390 * Retrieves the current view matrix
391 * @return the current view matrix.
392 */
393 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
394
395 /**
396 * Retrieves the inverse of the current view matrix.
397 *
398 * If the current view matrix is invertible, return true, and if matrix
399 * is non-null, copy the inverse into it. If the current view matrix is
400 * non-invertible, return false and ignore the matrix parameter.
401 *
402 * @param matrix if not null, will receive a copy of the current inverse.
403 */
404 bool getViewInverse(GrMatrix* matrix) const {
405 // TODO: determine whether we really need to leave matrix unmodified
406 // at call sites when inversion fails.
407 GrMatrix inverse;
408 if (fViewMatrix.invert(&inverse)) {
409 if (matrix) {
410 *matrix = inverse;
411 }
412 return true;
413 }
414 return false;
415 }
416
417 class AutoViewMatrixRestore : public ::GrNoncopyable {
418 public:
419 AutoViewMatrixRestore() : fDrawState(NULL) {}
420 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
421 fDrawState = NULL;
422 this->set(ds, newMatrix);
423 }
424 AutoViewMatrixRestore(GrDrawState* ds) {
425 fDrawState = NULL;
426 this->set(ds);
427 }
428 ~AutoViewMatrixRestore() {
429 this->set(NULL, GrMatrix::I());
430 }
431 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
432 if (NULL != fDrawState) {
433 fDrawState->setViewMatrix(fSavedMatrix);
434 }
435 if (NULL != ds) {
436 fSavedMatrix = ds->getViewMatrix();
437 ds->setViewMatrix(newMatrix);
438 }
439 fDrawState = ds;
440 }
441 void set(GrDrawState* ds) {
442 if (NULL != fDrawState) {
443 fDrawState->setViewMatrix(fSavedMatrix);
444 }
445 if (NULL != ds) {
446 fSavedMatrix = ds->getViewMatrix();
447 }
448 fDrawState = ds;
449 }
450 private:
451 GrDrawState* fDrawState;
452 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000453 };
454
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000455 /// @}
456
457 ///////////////////////////////////////////////////////////////////////////
458 /// @name Render Target
459 ////
460
461 /**
462 * Sets the rendertarget used at the next drawing call
463 *
464 * @param target The render target to set.
465 */
466 void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; }
467
468 /**
469 * Retrieves the currently set rendertarget.
470 *
471 * @return The currently set render target.
472 */
473 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
474 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
475
476 class AutoRenderTargetRestore : public ::GrNoncopyable {
477 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000478 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000479 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
480 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000481 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000482 this->set(ds, newTarget);
483 }
484 ~AutoRenderTargetRestore() { this->set(NULL, NULL); }
485 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
486 if (NULL != fDrawState) {
487 fDrawState->setRenderTarget(fSavedTarget);
488 }
489 if (NULL != ds) {
490 fSavedTarget = ds->getRenderTarget();
491 ds->setRenderTarget(newTarget);
492 }
493 fDrawState = ds;
494 }
495 private:
496 GrDrawState* fDrawState;
497 GrRenderTarget* fSavedTarget;
498 };
499
500 /// @}
501
502 ///////////////////////////////////////////////////////////////////////////
503 /// @name Stencil
504 ////
505
506 /**
507 * Sets the stencil settings to use for the next draw.
508 * Changing the clip has the side-effect of possibly zeroing
509 * out the client settable stencil bits. So multipass algorithms
510 * using stencil should not change the clip between passes.
511 * @param settings the stencil settings to use.
512 */
513 void setStencil(const GrStencilSettings& settings) {
514 fStencilSettings = settings;
515 }
516
517 /**
518 * Shortcut to disable stencil testing and ops.
519 */
520 void disableStencil() {
521 fStencilSettings.setDisabled();
522 }
523
524 const GrStencilSettings& getStencil() const { return fStencilSettings; }
525
526 GrStencilSettings* stencil() { return &fStencilSettings; }
527
528 /// @}
529
530 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000531 /// @name Color Matrix
532 ////
533
534 /**
535 * Sets the color matrix to use for the next draw.
536 * @param matrix the 5x4 matrix to apply to the incoming color
537 */
538 void setColorMatrix(const float matrix[20]) {
539 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
540 }
541
542 const float* getColorMatrix() const { return fColorMatrix; }
543
544 /// @}
545
546 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000547 // @name Edge AA
548 // There are two ways to perform antialiasing using edge equations. One
549 // is to specify an (linear or quadratic) edge eq per-vertex. This requires
550 // splitting vertices shared by primitives.
551 //
552 // The other is via setEdgeAAData which sets a set of edges and each
553 // is tested against all the edges.
554 ////
555
556 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000557 * When specifying edges as vertex data this enum specifies what type of
558 * edges are in use. The edges are always 4 GrScalars in memory, even when
559 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000560 *
561 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
562 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000563 */
564 enum VertexEdgeType {
565 /* 1-pixel wide line
566 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
567 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000568 /* Quadratic specified by u^2-v canonical coords (only 2
569 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000570 being inside, positive outside. Edge specified in window space
571 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000572 kQuad_EdgeType,
573 /* Same as above but for hairline quadratics. Uses unsigned distance.
574 Coverage is min(0, 1-distance). */
575 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000576 /* Circle specified as center_x, center_y, outer_radius, inner_radius
577 all in window space (y-down). */
578 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000579
580 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000581 };
582
583 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000584 * Determines the interpretation per-vertex edge data when the
585 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
586 * are not specified the value of this setting has no effect.
587 */
588 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000589 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000590 fVertexEdgeType = type;
591 }
592
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000593 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000594
595 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000596 * The absolute maximum number of edges that may be specified for
597 * a single draw call when performing edge antialiasing. This is used for
598 * the size of several static buffers, so implementations of getMaxEdges()
599 * (below) should clamp to this value.
600 */
601 enum {
tomhudson@google.com62b09682011-11-09 16:39:17 +0000602 // TODO: this should be 32 when GrTesselatedPathRenderer is used
603 // Visual Studio 2010 does not permit a member array of size 0.
604 kMaxEdges = 1
tomhudson@google.com93813632011-10-27 20:21:16 +0000605 };
606
607 class Edge {
608 public:
609 Edge() {}
610 Edge(float x, float y, float z) : fX(x), fY(y), fZ(z) {}
611 GrPoint intersect(const Edge& other) {
612 return GrPoint::Make(
bsalomon@google.com72e49b82011-10-27 21:47:03 +0000613 SkFloatToScalar((fY * other.fZ - other.fY * fZ) /
614 (fX * other.fY - other.fX * fY)),
615 SkFloatToScalar((fX * other.fZ - other.fX * fZ) /
616 (other.fX * fY - fX * other.fY)));
tomhudson@google.com93813632011-10-27 20:21:16 +0000617 }
618 float fX, fY, fZ;
619 };
620
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000621 /**
622 * Sets the edge data required for edge antialiasing.
623 *
624 * @param edges 3 * numEdges float values, representing the edge
625 * equations in Ax + By + C form
626 */
627 void setEdgeAAData(const Edge* edges, int numEdges) {
628 GrAssert(numEdges <= GrDrawState::kMaxEdges);
629 memcpy(fEdgeAAEdges, edges, numEdges * sizeof(GrDrawState::Edge));
630 fEdgeAANumEdges = numEdges;
tomhudson@google.com93813632011-10-27 20:21:16 +0000631 }
632
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000633 int getNumAAEdges() const { return fEdgeAANumEdges; }
tomhudson@google.com93813632011-10-27 20:21:16 +0000634
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000635 const Edge* getAAEdges() const { return fEdgeAAEdges; }
tomhudson@google.com62b09682011-11-09 16:39:17 +0000636
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000637 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000638
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000639 ///////////////////////////////////////////////////////////////////////////
640 /// @name State Flags
641 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000642
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000643 /**
644 * Flags that affect rendering. Controlled using enable/disableState(). All
645 * default to disabled.
646 */
647 enum StateBits {
648 /**
649 * Perform dithering. TODO: Re-evaluate whether we need this bit
650 */
651 kDither_StateBit = 0x01,
652 /**
653 * Perform HW anti-aliasing. This means either HW FSAA, if supported
654 * by the render target, or smooth-line rendering if a line primitive
655 * is drawn and line smoothing is supported by the 3D API.
656 */
657 kHWAntialias_StateBit = 0x02,
658 /**
659 * Draws will respect the clip, otherwise the clip is ignored.
660 */
661 kClip_StateBit = 0x04,
662 /**
663 * Disables writing to the color buffer. Useful when performing stencil
664 * operations.
665 */
666 kNoColorWrites_StateBit = 0x08,
667 /**
668 * Modifies the behavior of edge AA specified by setEdgeAA. If set,
669 * will test edge pairs for convexity when rasterizing. Set this if the
670 * source polygon is non-convex.
671 */
672 kEdgeAAConcave_StateBit = 0x10,
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000673 /**
674 * Draws will apply the color matrix, otherwise the color matrix is
675 * ignored.
676 */
677 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000678
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000679 // Users of the class may add additional bits to the vector
680 kDummyStateBit,
681 kLastPublicStateBit = kDummyStateBit-1,
682 };
683
684 void resetStateFlags() {
685 fFlagBits = 0;
686 }
687
688 /**
689 * Enable render state settings.
690 *
691 * @param flags bitfield of StateBits specifing the states to enable
692 */
693 void enableState(uint32_t stateBits) {
694 fFlagBits |= stateBits;
695 }
696
697 /**
698 * Disable render state settings.
699 *
700 * @param flags bitfield of StateBits specifing the states to disable
701 */
702 void disableState(uint32_t stateBits) {
703 fFlagBits &= ~(stateBits);
704 }
705
706 bool isDitherState() const {
707 return 0 != (fFlagBits & kDither_StateBit);
708 }
709
710 bool isHWAntialiasState() const {
711 return 0 != (fFlagBits & kHWAntialias_StateBit);
712 }
713
714 bool isClipState() const {
715 return 0 != (fFlagBits & kClip_StateBit);
716 }
717
718 bool isColorWriteDisabled() const {
719 return 0 != (fFlagBits & kNoColorWrites_StateBit);
720 }
721
722 bool isConcaveEdgeAAState() const {
723 return 0 != (fFlagBits & kEdgeAAConcave_StateBit);
724 }
725
726 bool isStateFlagEnabled(uint32_t stateBit) const {
727 return 0 != (stateBit & fFlagBits);
728 }
729
730 void copyStateFlags(const GrDrawState& ds) {
731 fFlagBits = ds.fFlagBits;
732 }
733
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000734 /**
735 * Flags that do not affect rendering.
736 */
737 enum GrBehaviorBits {
738 /**
739 * Calls to setTexture will ref/unref the texture
740 */
741 kTexturesNeedRef_BehaviorBit = 0x01,
742 };
743
744 void enableBehavior(uint32_t behaviorBits) {
745 fBehaviorBits |= behaviorBits;
746 }
747
748 void disableBehavior(uint32_t behaviorBits) {
749 fBehaviorBits &= ~(behaviorBits);
750 }
751
752 bool isBehaviorEnabled(uint32_t behaviorBits) const {
753 return 0 != (behaviorBits & fBehaviorBits);
754 }
755
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000756 /// @}
757
758 ///////////////////////////////////////////////////////////////////////////
759 /// @name Face Culling
760 ////
761
762 enum DrawFace {
763 kBoth_DrawFace,
764 kCCW_DrawFace,
765 kCW_DrawFace,
766 };
767
768 /**
769 * Controls whether clockwise, counterclockwise, or both faces are drawn.
770 * @param face the face(s) to draw.
771 */
772 void setDrawFace(DrawFace face) {
773 fDrawFace = face;
774 }
775
776 /**
777 * Gets whether the target is drawing clockwise, counterclockwise,
778 * or both faces.
779 * @return the current draw face(s).
780 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000781 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000782
783 /// @}
784
785 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000786
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000787 // Most stages are usually not used, so conditionals here
788 // reduce the expected number of bytes touched by 50%.
789 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000790 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000791 return false;
792 }
793
794 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
795 return false;
796 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000797
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000798 // kTexturesNeedRef is an internal flag for altering the draw state's
799 // behavior rather than a property that will impact drawing - ignore it
800 // here
801 if ((fBehaviorBits & ~kTexturesNeedRef_BehaviorBit) !=
802 (s.fBehaviorBits & ~kTexturesNeedRef_BehaviorBit)) {
803 return false;
804 }
805
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000806 for (int i = 0; i < kNumStages; i++) {
807 if (fTextures[i] &&
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000808 this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000809 return false;
810 }
811 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000812 if (kColorMatrix_StateBit & s.fFlagBits) {
813 if (memcmp(fColorMatrix,
814 s.fColorMatrix,
815 sizeof(fColorMatrix))) {
816 return false;
817 }
818 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000819
820 return true;
821 }
822 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
823
824 // Most stages are usually not used, so conditionals here
825 // reduce the expected number of bytes touched by 50%.
826 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000827 memcpy(this->podStart(), s.podStart(), this->podSize());
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000828
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000829 fViewMatrix = s.fViewMatrix;
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000830 fBehaviorBits = s.fBehaviorBits;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000831
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000832 GrAssert(0 == s.fEdgeAANumEdges);
833 fEdgeAANumEdges = 0;
834
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000835 for (int i = 0; i < kNumStages; i++) {
836 if (s.fTextures[i]) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000837 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000838 }
839 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000840 if (kColorMatrix_StateBit & s.fFlagBits) {
841 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
842 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000843
844 return *this;
845 }
846
847private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000848
849 const void* podStart() const {
850 return reinterpret_cast<const void*>(&fPodStartMarker);
851 }
852 void* podStart() {
853 return reinterpret_cast<void*>(&fPodStartMarker);
854 }
855 size_t memsetSize() const {
856 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
857 reinterpret_cast<size_t>(&fPodStartMarker) +
858 sizeof(fMemsetEndMarker);
859 }
860 size_t podSize() const {
861 // Can't use offsetof() with non-POD types, so stuck with pointer math.
862 // TODO: ignores GrTesselatedPathRenderer data structures. We don't
863 // have a compile-time flag that lets us know if it's being used, and
864 // checking at runtime seems to cost 5% performance.
865 return reinterpret_cast<size_t>(&fPodEndMarker) -
866 reinterpret_cast<size_t>(&fPodStartMarker) +
867 sizeof(fPodEndMarker);
868 }
869
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000870 static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000871 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000872 union {
873 GrColor fBlendConstant;
874 GrColor fPodStartMarker;
875 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000876 GrTexture* fTextures[kNumStages];
877 GrColor fColorFilterColor;
878 uint32_t fFlagBits;
879 DrawFace fDrawFace;
880 VertexEdgeType fVertexEdgeType;
881 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000882 union {
883 GrRenderTarget* fRenderTarget;
884 GrRenderTarget* fMemsetEndMarker;
885 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000886 // @}
887
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000888 // @{ Initialized to values other than zero, but memcmp'ed in operator==
889 // and memcpy'ed in operator=.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000890 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000891 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000892 int fFirstCoverageStage;
893 SkXfermode::Mode fColorFilterMode;
894 GrBlendCoeff fSrcBlend;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000895 union {
896 GrBlendCoeff fDstBlend;
897 GrBlendCoeff fPodEndMarker;
898 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000899 // @}
900
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000901 uint32_t fBehaviorBits;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000902 GrMatrix fViewMatrix;
903
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000904 // @{ Data for GrTesselatedPathRenderer
905 // TODO: currently ignored in copying & comparison for performance.
906 // Must be considered if GrTesselatedPathRenderer is being used.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000907 int fEdgeAANumEdges;
908 Edge fEdgeAAEdges[kMaxEdges];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000909 // @}
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000910
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000911 // This field must be last; it will not be copied or compared
912 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000913 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000914 // only compared if the color matrix enable flag is set
915 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000916
tomhudson@google.com93813632011-10-27 20:21:16 +0000917};
918
919#endif