blob: 386aebdfe023776a0761d0fbbe887198b45a1a33 [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.
39 */
40 enum {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000041 kNumStages = 4,
tomhudson@google.com93813632011-10-27 20:21:16 +000042 kMaxTexCoords = kNumStages
43 };
44
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000045 /**
46 * Bitfield used to indicate a set of stages.
47 */
48 typedef uint32_t StageMask;
49 GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
50
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000051 GrDrawState() {
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000052 this->reset();
53 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000054
55 GrDrawState(const GrDrawState& state) {
56 *this = state;
57 }
58
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000059 /**
60 * Resets to the default state. Sampler states will not be modified.
61 */
62 void reset() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000063 // make sure any pad is zero for memcmp
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000064 // all GrDrawState members should default to something valid by the
65 // the memset except those initialized individually below. There should
66 // be no padding between the individually initialized members.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000067 memset(this->podStart(), 0, this->memsetSize());
68
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000069 // pedantic assertion that our ptrs will
70 // be NULL (0 ptr is mem addr 0)
71 GrAssert((intptr_t)(void*)NULL == 0LL);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000072 GR_STATIC_ASSERT(0 == kBoth_DrawFace);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000073 GrAssert(fStencilSettings.isDisabled());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000074
75 // memset exceptions
76 fColor = 0xffffffff;
bsalomon@google.com2401ae82012-01-17 21:03:05 +000077 fCoverage = 0xffffffff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000078 fFirstCoverageStage = kNumStages;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000079 fColorFilterMode = SkXfermode::kDst_Mode;
80 fSrcBlend = kOne_BlendCoeff;
81 fDstBlend = kZero_BlendCoeff;
82 fViewMatrix.reset();
robertphillips@google.com28b4bce2012-05-04 16:34:52 +000083 fBehaviorBits = 0;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000084
85 // ensure values that will be memcmp'ed in == but not memset in reset()
86 // are tightly packed
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000087 GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) +
bsalomon@google.com2401ae82012-01-17 21:03:05 +000088 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
bsalomon@google.com8fe84b52012-03-26 15:24:27 +000089 sizeof(fSrcBlend) + sizeof(fDstBlend) ==
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000090 this->podSize());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000091
92 fEdgeAANumEdges = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000093 }
94
95 ///////////////////////////////////////////////////////////////////////////
96 /// @name Color
97 ////
98
99 /**
100 * Sets color for next draw to a premultiplied-alpha color.
101 *
102 * @param color the color to set.
103 */
104 void setColor(GrColor color) { fColor = color; }
105
106 GrColor getColor() const { return fColor; }
107
108 /**
109 * Sets the color to be used for the next draw to be
110 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
111 *
112 * @param alpha The alpha value to set as the color.
113 */
114 void setAlpha(uint8_t a) {
115 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
116 }
117
118 /**
119 * Add a color filter that can be represented by a color and a mode. Applied
120 * after color-computing texture stages.
121 */
122 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
123 fColorFilterColor = c;
124 fColorFilterMode = mode;
125 }
126
127 GrColor getColorFilterColor() const { return fColorFilterColor; }
128 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
129
130 /// @}
131
132 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000133 /// @name Coverage
134 ////
135
136 /**
137 * Sets a constant fractional coverage to be applied to the draw. The
138 * initial value (after construction or reset()) is 0xff. The constant
139 * coverage is ignored when per-vertex coverage is provided.
140 */
141 void setCoverage(uint8_t coverage) {
142 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
143 }
144
145 /**
146 * Version of above that specifies 4 channel per-vertex color. The value
147 * should be premultiplied.
148 */
149 void setCoverage4(GrColor coverage) {
150 fCoverage = coverage;
151 }
152
153 GrColor getCoverage() const {
154 return fCoverage;
155 }
156
157 /// @}
158
159 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000160 /// @name Textures
161 ////
162
163 /**
164 * Sets the texture used at the next drawing call
165 *
166 * @param stage The texture stage for which the texture will be set
167 *
168 * @param texture The texture to set. Can be NULL though there is no
169 * advantage to settings a NULL texture if doing non-textured drawing
170 */
171 void setTexture(int stage, GrTexture* texture) {
172 GrAssert((unsigned)stage < kNumStages);
robertphillips@google.com1942c052012-05-03 17:58:27 +0000173
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000174 if (isBehaviorEnabled(kTexturesNeedRef_BehaviorBit)) {
robertphillips@google.com1942c052012-05-03 17:58:27 +0000175 // If we don't clear out the current texture before unreffing
176 // it we can get into an infinite loop as the GrGLTexture's
177 // onRelease method recursively calls setTexture
178 GrTexture* temp = fTextures[stage];
179 fTextures[stage] = NULL;
180
181 SkSafeRef(texture);
182 SkSafeUnref(temp);
183 }
184
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000185 fTextures[stage] = texture;
186 }
187
188 /**
189 * Retrieves the currently set texture.
190 *
191 * @return The currently set texture. The return value will be NULL if no
192 * texture has been set, NULL was most recently passed to
193 * setTexture, or the last setTexture was destroyed.
194 */
195 const GrTexture* getTexture(int stage) const {
196 GrAssert((unsigned)stage < kNumStages);
197 return fTextures[stage];
198 }
199 GrTexture* getTexture(int stage) {
200 GrAssert((unsigned)stage < kNumStages);
201 return fTextures[stage];
202 }
203
204 /// @}
205
206 ///////////////////////////////////////////////////////////////////////////
207 /// @name Samplers
208 ////
209
210 /**
211 * Returns the current sampler for a stage.
212 */
213 const GrSamplerState& getSampler(int stage) const {
214 GrAssert((unsigned)stage < kNumStages);
215 return fSamplerStates[stage];
216 }
217
218 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000219 * Writable pointer to a stage's sampler.
220 */
221 GrSamplerState* sampler(int stage) {
222 GrAssert((unsigned)stage < kNumStages);
223 return fSamplerStates + stage;
224 }
225
226 /**
227 * Preconcats the matrix of all samplers in the mask with the same matrix.
228 */
229 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
230 GrAssert(!(stageMask & kIllegalStageMaskBits));
231 for (int i = 0; i < kNumStages; ++i) {
232 if ((1 << i) & stageMask) {
233 fSamplerStates[i].preConcatMatrix(matrix);
234 }
235 }
236 }
237
238 /// @}
239
240 ///////////////////////////////////////////////////////////////////////////
241 /// @name Coverage / Color Stages
242 ////
243
244 /**
245 * A common pattern is to compute a color with the initial stages and then
246 * modulate that color by a coverage value in later stage(s) (AA, mask-
247 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
248 * computed based on the pre-coverage-modulated color. The division of
249 * stages between color-computing and coverage-computing is specified by
250 * this method. Initially this is kNumStages (all stages
251 * are color-computing).
252 */
253 void setFirstCoverageStage(int firstCoverageStage) {
254 GrAssert((unsigned)firstCoverageStage <= kNumStages);
255 fFirstCoverageStage = firstCoverageStage;
256 }
257
258 /**
259 * Gets the index of the first coverage-computing stage.
260 */
261 int getFirstCoverageStage() const {
262 return fFirstCoverageStage;
263 }
264
265 ///@}
266
267 ///////////////////////////////////////////////////////////////////////////
268 /// @name Blending
269 ////
270
271 /**
272 * Sets the blending function coeffecients.
273 *
274 * The blend function will be:
275 * D' = sat(S*srcCoef + D*dstCoef)
276 *
277 * where D is the existing destination color, S is the incoming source
278 * color, and D' is the new destination color that will be written. sat()
279 * is the saturation function.
280 *
281 * @param srcCoef coeffecient applied to the src color.
282 * @param dstCoef coeffecient applied to the dst color.
283 */
284 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
285 fSrcBlend = srcCoeff;
286 fDstBlend = dstCoeff;
287 #if GR_DEBUG
288 switch (dstCoeff) {
289 case kDC_BlendCoeff:
290 case kIDC_BlendCoeff:
291 case kDA_BlendCoeff:
292 case kIDA_BlendCoeff:
293 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
294 "coverage stages.\n");
295 break;
296 default:
297 break;
298 }
299 switch (srcCoeff) {
300 case kSC_BlendCoeff:
301 case kISC_BlendCoeff:
302 case kSA_BlendCoeff:
303 case kISA_BlendCoeff:
304 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
305 "coverage stages.\n");
306 break;
307 default:
308 break;
309 }
310 #endif
311 }
312
313 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
314 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
315
316 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
317 GrBlendCoeff* dstBlendCoeff) const {
318 *srcBlendCoeff = fSrcBlend;
319 *dstBlendCoeff = fDstBlend;
320 }
321
322 /**
323 * Sets the blending function constant referenced by the following blending
324 * coeffecients:
325 * kConstC_BlendCoeff
326 * kIConstC_BlendCoeff
327 * kConstA_BlendCoeff
328 * kIConstA_BlendCoeff
329 *
330 * @param constant the constant to set
331 */
332 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
333
334 /**
335 * Retrieves the last value set by setBlendConstant()
336 * @return the blending constant value
337 */
338 GrColor getBlendConstant() const { return fBlendConstant; }
339
340 /// @}
341
342 ///////////////////////////////////////////////////////////////////////////
343 /// @name View Matrix
344 ////
345
346 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000347 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000348 *
349 * In the post-view-matrix space the rectangle [0,w]x[0,h]
350 * fully covers the render target. (w and h are the width and height of the
351 * the rendertarget.)
352 */
353 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
354
355 /**
356 * Gets a writable pointer to the view matrix.
357 */
358 GrMatrix* viewMatrix() { return &fViewMatrix; }
359
360 /**
361 * Multiplies the current view matrix by a matrix
362 *
363 * After this call V' = V*m where V is the old view matrix,
364 * m is the parameter to this function, and V' is the new view matrix.
365 * (We consider positions to be column vectors so position vector p is
366 * transformed by matrix X as p' = X*p.)
367 *
368 * @param m the matrix used to modify the view matrix.
369 */
370 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
371
372 /**
373 * Multiplies the current view matrix by a matrix
374 *
375 * After this call V' = m*V where V is the old view matrix,
376 * m is the parameter to this function, and V' is the new view matrix.
377 * (We consider positions to be column vectors so position vector p is
378 * transformed by matrix X as p' = X*p.)
379 *
380 * @param m the matrix used to modify the view matrix.
381 */
382 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
383
384 /**
385 * Retrieves the current view matrix
386 * @return the current view matrix.
387 */
388 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
389
390 /**
391 * Retrieves the inverse of the current view matrix.
392 *
393 * If the current view matrix is invertible, return true, and if matrix
394 * is non-null, copy the inverse into it. If the current view matrix is
395 * non-invertible, return false and ignore the matrix parameter.
396 *
397 * @param matrix if not null, will receive a copy of the current inverse.
398 */
399 bool getViewInverse(GrMatrix* matrix) const {
400 // TODO: determine whether we really need to leave matrix unmodified
401 // at call sites when inversion fails.
402 GrMatrix inverse;
403 if (fViewMatrix.invert(&inverse)) {
404 if (matrix) {
405 *matrix = inverse;
406 }
407 return true;
408 }
409 return false;
410 }
411
412 class AutoViewMatrixRestore : public ::GrNoncopyable {
413 public:
414 AutoViewMatrixRestore() : fDrawState(NULL) {}
415 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
416 fDrawState = NULL;
417 this->set(ds, newMatrix);
418 }
419 AutoViewMatrixRestore(GrDrawState* ds) {
420 fDrawState = NULL;
421 this->set(ds);
422 }
423 ~AutoViewMatrixRestore() {
424 this->set(NULL, GrMatrix::I());
425 }
426 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
427 if (NULL != fDrawState) {
428 fDrawState->setViewMatrix(fSavedMatrix);
429 }
430 if (NULL != ds) {
431 fSavedMatrix = ds->getViewMatrix();
432 ds->setViewMatrix(newMatrix);
433 }
434 fDrawState = ds;
435 }
436 void set(GrDrawState* ds) {
437 if (NULL != fDrawState) {
438 fDrawState->setViewMatrix(fSavedMatrix);
439 }
440 if (NULL != ds) {
441 fSavedMatrix = ds->getViewMatrix();
442 }
443 fDrawState = ds;
444 }
445 private:
446 GrDrawState* fDrawState;
447 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000448 };
449
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000450 /// @}
451
452 ///////////////////////////////////////////////////////////////////////////
453 /// @name Render Target
454 ////
455
456 /**
457 * Sets the rendertarget used at the next drawing call
458 *
459 * @param target The render target to set.
460 */
461 void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; }
462
463 /**
464 * Retrieves the currently set rendertarget.
465 *
466 * @return The currently set render target.
467 */
468 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
469 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
470
471 class AutoRenderTargetRestore : public ::GrNoncopyable {
472 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000473 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000474 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
475 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000476 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000477 this->set(ds, newTarget);
478 }
479 ~AutoRenderTargetRestore() { this->set(NULL, NULL); }
480 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
481 if (NULL != fDrawState) {
482 fDrawState->setRenderTarget(fSavedTarget);
483 }
484 if (NULL != ds) {
485 fSavedTarget = ds->getRenderTarget();
486 ds->setRenderTarget(newTarget);
487 }
488 fDrawState = ds;
489 }
490 private:
491 GrDrawState* fDrawState;
492 GrRenderTarget* fSavedTarget;
493 };
494
495 /// @}
496
497 ///////////////////////////////////////////////////////////////////////////
498 /// @name Stencil
499 ////
500
501 /**
502 * Sets the stencil settings to use for the next draw.
503 * Changing the clip has the side-effect of possibly zeroing
504 * out the client settable stencil bits. So multipass algorithms
505 * using stencil should not change the clip between passes.
506 * @param settings the stencil settings to use.
507 */
508 void setStencil(const GrStencilSettings& settings) {
509 fStencilSettings = settings;
510 }
511
512 /**
513 * Shortcut to disable stencil testing and ops.
514 */
515 void disableStencil() {
516 fStencilSettings.setDisabled();
517 }
518
519 const GrStencilSettings& getStencil() const { return fStencilSettings; }
520
521 GrStencilSettings* stencil() { return &fStencilSettings; }
522
523 /// @}
524
525 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000526 /// @name Color Matrix
527 ////
528
529 /**
530 * Sets the color matrix to use for the next draw.
531 * @param matrix the 5x4 matrix to apply to the incoming color
532 */
533 void setColorMatrix(const float matrix[20]) {
534 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
535 }
536
537 const float* getColorMatrix() const { return fColorMatrix; }
538
539 /// @}
540
541 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000542 // @name Edge AA
543 // There are two ways to perform antialiasing using edge equations. One
544 // is to specify an (linear or quadratic) edge eq per-vertex. This requires
545 // splitting vertices shared by primitives.
546 //
547 // The other is via setEdgeAAData which sets a set of edges and each
548 // is tested against all the edges.
549 ////
550
551 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000552 * When specifying edges as vertex data this enum specifies what type of
553 * edges are in use. The edges are always 4 GrScalars in memory, even when
554 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000555 *
556 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
557 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000558 */
559 enum VertexEdgeType {
560 /* 1-pixel wide line
561 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
562 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000563 /* Quadratic specified by u^2-v canonical coords (only 2
564 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000565 being inside, positive outside. Edge specified in window space
566 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000567 kQuad_EdgeType,
568 /* Same as above but for hairline quadratics. Uses unsigned distance.
569 Coverage is min(0, 1-distance). */
570 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000571 /* Circle specified as center_x, center_y, outer_radius, inner_radius
572 all in window space (y-down). */
573 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000574
575 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000576 };
577
578 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000579 * Determines the interpretation per-vertex edge data when the
580 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
581 * are not specified the value of this setting has no effect.
582 */
583 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000584 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000585 fVertexEdgeType = type;
586 }
587
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000588 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000589
590 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000591 * The absolute maximum number of edges that may be specified for
592 * a single draw call when performing edge antialiasing. This is used for
593 * the size of several static buffers, so implementations of getMaxEdges()
594 * (below) should clamp to this value.
595 */
596 enum {
tomhudson@google.com62b09682011-11-09 16:39:17 +0000597 // TODO: this should be 32 when GrTesselatedPathRenderer is used
598 // Visual Studio 2010 does not permit a member array of size 0.
599 kMaxEdges = 1
tomhudson@google.com93813632011-10-27 20:21:16 +0000600 };
601
602 class Edge {
603 public:
604 Edge() {}
605 Edge(float x, float y, float z) : fX(x), fY(y), fZ(z) {}
606 GrPoint intersect(const Edge& other) {
607 return GrPoint::Make(
bsalomon@google.com72e49b82011-10-27 21:47:03 +0000608 SkFloatToScalar((fY * other.fZ - other.fY * fZ) /
609 (fX * other.fY - other.fX * fY)),
610 SkFloatToScalar((fX * other.fZ - other.fX * fZ) /
611 (other.fX * fY - fX * other.fY)));
tomhudson@google.com93813632011-10-27 20:21:16 +0000612 }
613 float fX, fY, fZ;
614 };
615
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000616 /**
617 * Sets the edge data required for edge antialiasing.
618 *
619 * @param edges 3 * numEdges float values, representing the edge
620 * equations in Ax + By + C form
621 */
622 void setEdgeAAData(const Edge* edges, int numEdges) {
623 GrAssert(numEdges <= GrDrawState::kMaxEdges);
624 memcpy(fEdgeAAEdges, edges, numEdges * sizeof(GrDrawState::Edge));
625 fEdgeAANumEdges = numEdges;
tomhudson@google.com93813632011-10-27 20:21:16 +0000626 }
627
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000628 int getNumAAEdges() const { return fEdgeAANumEdges; }
tomhudson@google.com93813632011-10-27 20:21:16 +0000629
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000630 const Edge* getAAEdges() const { return fEdgeAAEdges; }
tomhudson@google.com62b09682011-11-09 16:39:17 +0000631
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000632 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000633
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000634 ///////////////////////////////////////////////////////////////////////////
635 /// @name State Flags
636 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000637
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000638 /**
639 * Flags that affect rendering. Controlled using enable/disableState(). All
640 * default to disabled.
641 */
642 enum StateBits {
643 /**
644 * Perform dithering. TODO: Re-evaluate whether we need this bit
645 */
646 kDither_StateBit = 0x01,
647 /**
648 * Perform HW anti-aliasing. This means either HW FSAA, if supported
649 * by the render target, or smooth-line rendering if a line primitive
650 * is drawn and line smoothing is supported by the 3D API.
651 */
652 kHWAntialias_StateBit = 0x02,
653 /**
654 * Draws will respect the clip, otherwise the clip is ignored.
655 */
656 kClip_StateBit = 0x04,
657 /**
658 * Disables writing to the color buffer. Useful when performing stencil
659 * operations.
660 */
661 kNoColorWrites_StateBit = 0x08,
662 /**
663 * Modifies the behavior of edge AA specified by setEdgeAA. If set,
664 * will test edge pairs for convexity when rasterizing. Set this if the
665 * source polygon is non-convex.
666 */
667 kEdgeAAConcave_StateBit = 0x10,
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000668 /**
669 * Draws will apply the color matrix, otherwise the color matrix is
670 * ignored.
671 */
672 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000673
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000674 // Users of the class may add additional bits to the vector
675 kDummyStateBit,
676 kLastPublicStateBit = kDummyStateBit-1,
677 };
678
679 void resetStateFlags() {
680 fFlagBits = 0;
681 }
682
683 /**
684 * Enable render state settings.
685 *
686 * @param flags bitfield of StateBits specifing the states to enable
687 */
688 void enableState(uint32_t stateBits) {
689 fFlagBits |= stateBits;
690 }
691
692 /**
693 * Disable render state settings.
694 *
695 * @param flags bitfield of StateBits specifing the states to disable
696 */
697 void disableState(uint32_t stateBits) {
698 fFlagBits &= ~(stateBits);
699 }
700
701 bool isDitherState() const {
702 return 0 != (fFlagBits & kDither_StateBit);
703 }
704
705 bool isHWAntialiasState() const {
706 return 0 != (fFlagBits & kHWAntialias_StateBit);
707 }
708
709 bool isClipState() const {
710 return 0 != (fFlagBits & kClip_StateBit);
711 }
712
713 bool isColorWriteDisabled() const {
714 return 0 != (fFlagBits & kNoColorWrites_StateBit);
715 }
716
717 bool isConcaveEdgeAAState() const {
718 return 0 != (fFlagBits & kEdgeAAConcave_StateBit);
719 }
720
721 bool isStateFlagEnabled(uint32_t stateBit) const {
722 return 0 != (stateBit & fFlagBits);
723 }
724
725 void copyStateFlags(const GrDrawState& ds) {
726 fFlagBits = ds.fFlagBits;
727 }
728
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000729 /**
730 * Flags that do not affect rendering.
731 */
732 enum GrBehaviorBits {
733 /**
734 * Calls to setTexture will ref/unref the texture
735 */
736 kTexturesNeedRef_BehaviorBit = 0x01,
737 };
738
739 void enableBehavior(uint32_t behaviorBits) {
740 fBehaviorBits |= behaviorBits;
741 }
742
743 void disableBehavior(uint32_t behaviorBits) {
744 fBehaviorBits &= ~(behaviorBits);
745 }
746
747 bool isBehaviorEnabled(uint32_t behaviorBits) const {
748 return 0 != (behaviorBits & fBehaviorBits);
749 }
750
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000751 /// @}
752
753 ///////////////////////////////////////////////////////////////////////////
754 /// @name Face Culling
755 ////
756
757 enum DrawFace {
758 kBoth_DrawFace,
759 kCCW_DrawFace,
760 kCW_DrawFace,
761 };
762
763 /**
764 * Controls whether clockwise, counterclockwise, or both faces are drawn.
765 * @param face the face(s) to draw.
766 */
767 void setDrawFace(DrawFace face) {
768 fDrawFace = face;
769 }
770
771 /**
772 * Gets whether the target is drawing clockwise, counterclockwise,
773 * or both faces.
774 * @return the current draw face(s).
775 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000776 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000777
778 /// @}
779
780 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000781
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000782 // Most stages are usually not used, so conditionals here
783 // reduce the expected number of bytes touched by 50%.
784 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000785 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000786 return false;
787 }
788
789 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
790 return false;
791 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000792
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000793 // kTexturesNeedRef is an internal flag for altering the draw state's
794 // behavior rather than a property that will impact drawing - ignore it
795 // here
796 if ((fBehaviorBits & ~kTexturesNeedRef_BehaviorBit) !=
797 (s.fBehaviorBits & ~kTexturesNeedRef_BehaviorBit)) {
798 return false;
799 }
800
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000801 for (int i = 0; i < kNumStages; i++) {
802 if (fTextures[i] &&
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000803 this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000804 return false;
805 }
806 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000807 if (kColorMatrix_StateBit & s.fFlagBits) {
808 if (memcmp(fColorMatrix,
809 s.fColorMatrix,
810 sizeof(fColorMatrix))) {
811 return false;
812 }
813 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000814
815 return true;
816 }
817 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
818
819 // Most stages are usually not used, so conditionals here
820 // reduce the expected number of bytes touched by 50%.
821 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000822 memcpy(this->podStart(), s.podStart(), this->podSize());
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000823
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000824 fViewMatrix = s.fViewMatrix;
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000825 fBehaviorBits = s.fBehaviorBits;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000826
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000827 GrAssert(0 == s.fEdgeAANumEdges);
828 fEdgeAANumEdges = 0;
829
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000830 for (int i = 0; i < kNumStages; i++) {
831 if (s.fTextures[i]) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000832 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000833 }
834 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000835 if (kColorMatrix_StateBit & s.fFlagBits) {
836 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
837 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000838
839 return *this;
840 }
841
842private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000843
844 const void* podStart() const {
845 return reinterpret_cast<const void*>(&fPodStartMarker);
846 }
847 void* podStart() {
848 return reinterpret_cast<void*>(&fPodStartMarker);
849 }
850 size_t memsetSize() const {
851 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
852 reinterpret_cast<size_t>(&fPodStartMarker) +
853 sizeof(fMemsetEndMarker);
854 }
855 size_t podSize() const {
856 // Can't use offsetof() with non-POD types, so stuck with pointer math.
857 // TODO: ignores GrTesselatedPathRenderer data structures. We don't
858 // have a compile-time flag that lets us know if it's being used, and
859 // checking at runtime seems to cost 5% performance.
860 return reinterpret_cast<size_t>(&fPodEndMarker) -
861 reinterpret_cast<size_t>(&fPodStartMarker) +
862 sizeof(fPodEndMarker);
863 }
864
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000865 static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000866 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000867 union {
868 GrColor fBlendConstant;
869 GrColor fPodStartMarker;
870 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000871 GrTexture* fTextures[kNumStages];
872 GrColor fColorFilterColor;
873 uint32_t fFlagBits;
874 DrawFace fDrawFace;
875 VertexEdgeType fVertexEdgeType;
876 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000877 union {
878 GrRenderTarget* fRenderTarget;
879 GrRenderTarget* fMemsetEndMarker;
880 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000881 // @}
882
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000883 // @{ Initialized to values other than zero, but memcmp'ed in operator==
884 // and memcpy'ed in operator=.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000885 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000886 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000887 int fFirstCoverageStage;
888 SkXfermode::Mode fColorFilterMode;
889 GrBlendCoeff fSrcBlend;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000890 union {
891 GrBlendCoeff fDstBlend;
892 GrBlendCoeff fPodEndMarker;
893 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000894 // @}
895
robertphillips@google.com28b4bce2012-05-04 16:34:52 +0000896 uint32_t fBehaviorBits;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000897 GrMatrix fViewMatrix;
898
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000899 // @{ Data for GrTesselatedPathRenderer
900 // TODO: currently ignored in copying & comparison for performance.
901 // Must be considered if GrTesselatedPathRenderer is being used.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000902 int fEdgeAANumEdges;
903 Edge fEdgeAAEdges[kMaxEdges];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000904 // @}
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000905
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000906 // This field must be last; it will not be copied or compared
907 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000908 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000909 // only compared if the color matrix enable flag is set
910 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000911
tomhudson@google.com93813632011-10-27 20:21:16 +0000912};
913
914#endif