blob: a568ca776bccb30da07299285a24973051bcff92 [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"
robertphillips@google.comab303ef2012-05-28 13:37:25 +000017#include "GrRenderTarget.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000018
19#include "SkXfermode.h"
20
tomhudson@google.com93813632011-10-27 20:21:16 +000021
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000022class GrDrawState : public GrRefCnt {
tomhudson@google.com93813632011-10-27 20:21:16 +000023
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000024public:
tomhudson@google.com93813632011-10-27 20:21:16 +000025 /**
26 * Number of texture stages. Each stage takes as input a color and
27 * 2D texture coordinates. The color input to the first enabled stage is the
28 * per-vertex color or the constant color (setColor/setAlpha) if there are
29 * no per-vertex colors. For subsequent stages the input color is the output
30 * color from the previous enabled stage. The output color of each stage is
31 * the input color modulated with the result of a texture lookup. Texture
32 * lookups are specified by a texture a sampler (setSamplerState). Texture
33 * coordinates for each stage come from the vertices based on a
34 * GrVertexLayout bitfield. The output fragment color is the output color of
35 * the last enabled stage. The presence or absence of texture coordinates
36 * for each stage in the vertex layout indicates whether a stage is enabled
37 * or not.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000038 *
39 * Stages 0 through GrPaint::kTotalStages-1 are reserved for setting up
40 * the draw (i.e., textures and filter masks). Stages GrPaint::kTotalStages
41 * through kNumStages-1 are earmarked for use by GrTextContext and
42 * GrPathRenderer-derived classes.
tomhudson@google.com93813632011-10-27 20:21:16 +000043 */
44 enum {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000045 kNumStages = 4,
tomhudson@google.com93813632011-10-27 20:21:16 +000046 kMaxTexCoords = kNumStages
47 };
48
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000049 /**
50 * Bitfield used to indicate a set of stages.
51 */
52 typedef uint32_t StageMask;
53 GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
54
robertphillips@google.comab303ef2012-05-28 13:37:25 +000055 GrDrawState()
56 : fRenderTarget(NULL) {
57
58 for (int i = 0; i < kNumStages; ++i) {
59 fTextures[i] = NULL;
60 }
61
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000062 this->reset();
63 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000064
robertphillips@google.comab303ef2012-05-28 13:37:25 +000065 GrDrawState(const GrDrawState& state)
66 : fRenderTarget(NULL) {
67
68 for (int i = 0; i < kNumStages; ++i) {
69 fTextures[i] = NULL;
70 }
71
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000072 *this = state;
73 }
74
robertphillips@google.comab303ef2012-05-28 13:37:25 +000075 virtual ~GrDrawState() {
76 for (int i = 0; i < kNumStages; ++i) {
77 GrSafeSetNull(fTextures[i]);
78 }
79 GrSafeSetNull(fRenderTarget);
80 }
81
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000082 /**
83 * Resets to the default state. Sampler states will not be modified.
84 */
85 void reset() {
robertphillips@google.comab303ef2012-05-28 13:37:25 +000086
87 for (int i = 0; i < kNumStages; ++i) {
88 // just as in setTexture we have to detach the texture before
89 // unreffing it because, if a texture is actually freed here,
90 // GrGLTexture's onRelease method will try to remove it from all
91 // possible owner's (including this one) via setTexture(NULL)
92 GrTexture* temp = fTextures[i];
93 fTextures[i] = NULL;
94 GrSafeUnref(temp);
95 }
96
97 GrRenderTarget* temp = fRenderTarget;
98 fRenderTarget = NULL;
99 GrSafeUnref(temp);
100
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000101 // make sure any pad is zero for memcmp
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000102 // all GrDrawState members should default to something valid by the
103 // the memset except those initialized individually below. There should
104 // be no padding between the individually initialized members.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000105 memset(this->podStart(), 0, this->memsetSize());
106
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000107 // pedantic assertion that our ptrs will
108 // be NULL (0 ptr is mem addr 0)
109 GrAssert((intptr_t)(void*)NULL == 0LL);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000110 GR_STATIC_ASSERT(0 == kBoth_DrawFace);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000111 GrAssert(fStencilSettings.isDisabled());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000112
113 // memset exceptions
114 fColor = 0xffffffff;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000115 fCoverage = 0xffffffff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000116 fFirstCoverageStage = kNumStages;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000117 fColorFilterMode = SkXfermode::kDst_Mode;
118 fSrcBlend = kOne_BlendCoeff;
119 fDstBlend = kZero_BlendCoeff;
120 fViewMatrix.reset();
121
122 // ensure values that will be memcmp'ed in == but not memset in reset()
123 // are tightly packed
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000124 GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) +
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000125 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000126 sizeof(fSrcBlend) + sizeof(fDstBlend) + sizeof(fTextures) +
127 sizeof(fRenderTarget) == this->podSize());
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000128 }
129
130 ///////////////////////////////////////////////////////////////////////////
131 /// @name Color
132 ////
133
134 /**
135 * Sets color for next draw to a premultiplied-alpha color.
136 *
137 * @param color the color to set.
138 */
139 void setColor(GrColor color) { fColor = color; }
140
141 GrColor getColor() const { return fColor; }
142
143 /**
144 * Sets the color to be used for the next draw to be
145 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
146 *
147 * @param alpha The alpha value to set as the color.
148 */
149 void setAlpha(uint8_t a) {
150 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
151 }
152
153 /**
154 * Add a color filter that can be represented by a color and a mode. Applied
155 * after color-computing texture stages.
156 */
157 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
158 fColorFilterColor = c;
159 fColorFilterMode = mode;
160 }
161
162 GrColor getColorFilterColor() const { return fColorFilterColor; }
163 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
164
165 /// @}
166
167 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000168 /// @name Coverage
169 ////
170
171 /**
172 * Sets a constant fractional coverage to be applied to the draw. The
173 * initial value (after construction or reset()) is 0xff. The constant
174 * coverage is ignored when per-vertex coverage is provided.
175 */
176 void setCoverage(uint8_t coverage) {
177 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
178 }
179
180 /**
181 * Version of above that specifies 4 channel per-vertex color. The value
182 * should be premultiplied.
183 */
184 void setCoverage4(GrColor coverage) {
185 fCoverage = coverage;
186 }
187
188 GrColor getCoverage() const {
189 return fCoverage;
190 }
191
192 /// @}
193
194 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000195 /// @name Textures
196 ////
197
198 /**
199 * Sets the texture used at the next drawing call
200 *
201 * @param stage The texture stage for which the texture will be set
202 *
203 * @param texture The texture to set. Can be NULL though there is no
204 * advantage to settings a NULL texture if doing non-textured drawing
205 */
206 void setTexture(int stage, GrTexture* texture) {
207 GrAssert((unsigned)stage < kNumStages);
robertphillips@google.com1942c052012-05-03 17:58:27 +0000208
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000209 // If we don't clear out the current texture before unreffing
210 // it we can get into an infinite loop as the GrGLTexture's
211 // onRelease method recursively calls setTexture
212 GrTexture* temp = fTextures[stage];
213 fTextures[stage] = NULL;
robertphillips@google.com1942c052012-05-03 17:58:27 +0000214
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000215 SkSafeRef(texture);
216 SkSafeUnref(temp);
robertphillips@google.com1942c052012-05-03 17:58:27 +0000217
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000218 fTextures[stage] = texture;
219 }
220
221 /**
222 * Retrieves the currently set texture.
223 *
224 * @return The currently set texture. The return value will be NULL if no
225 * texture has been set, NULL was most recently passed to
226 * setTexture, or the last setTexture was destroyed.
227 */
228 const GrTexture* getTexture(int stage) const {
229 GrAssert((unsigned)stage < kNumStages);
230 return fTextures[stage];
231 }
232 GrTexture* getTexture(int stage) {
233 GrAssert((unsigned)stage < kNumStages);
234 return fTextures[stage];
235 }
236
237 /// @}
238
239 ///////////////////////////////////////////////////////////////////////////
240 /// @name Samplers
241 ////
242
243 /**
244 * Returns the current sampler for a stage.
245 */
246 const GrSamplerState& getSampler(int stage) const {
247 GrAssert((unsigned)stage < kNumStages);
248 return fSamplerStates[stage];
249 }
250
251 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000252 * Writable pointer to a stage's sampler.
253 */
254 GrSamplerState* sampler(int stage) {
255 GrAssert((unsigned)stage < kNumStages);
256 return fSamplerStates + stage;
257 }
258
259 /**
260 * Preconcats the matrix of all samplers in the mask with the same matrix.
261 */
262 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
263 GrAssert(!(stageMask & kIllegalStageMaskBits));
264 for (int i = 0; i < kNumStages; ++i) {
265 if ((1 << i) & stageMask) {
266 fSamplerStates[i].preConcatMatrix(matrix);
267 }
268 }
269 }
270
271 /// @}
272
273 ///////////////////////////////////////////////////////////////////////////
274 /// @name Coverage / Color Stages
275 ////
276
277 /**
278 * A common pattern is to compute a color with the initial stages and then
279 * modulate that color by a coverage value in later stage(s) (AA, mask-
280 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
281 * computed based on the pre-coverage-modulated color. The division of
282 * stages between color-computing and coverage-computing is specified by
283 * this method. Initially this is kNumStages (all stages
284 * are color-computing).
285 */
286 void setFirstCoverageStage(int firstCoverageStage) {
287 GrAssert((unsigned)firstCoverageStage <= kNumStages);
288 fFirstCoverageStage = firstCoverageStage;
289 }
290
291 /**
292 * Gets the index of the first coverage-computing stage.
293 */
294 int getFirstCoverageStage() const {
295 return fFirstCoverageStage;
296 }
297
298 ///@}
299
300 ///////////////////////////////////////////////////////////////////////////
301 /// @name Blending
302 ////
303
304 /**
305 * Sets the blending function coeffecients.
306 *
307 * The blend function will be:
308 * D' = sat(S*srcCoef + D*dstCoef)
309 *
310 * where D is the existing destination color, S is the incoming source
311 * color, and D' is the new destination color that will be written. sat()
312 * is the saturation function.
313 *
314 * @param srcCoef coeffecient applied to the src color.
315 * @param dstCoef coeffecient applied to the dst color.
316 */
317 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
318 fSrcBlend = srcCoeff;
319 fDstBlend = dstCoeff;
320 #if GR_DEBUG
321 switch (dstCoeff) {
322 case kDC_BlendCoeff:
323 case kIDC_BlendCoeff:
324 case kDA_BlendCoeff:
325 case kIDA_BlendCoeff:
326 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
327 "coverage stages.\n");
328 break;
329 default:
330 break;
331 }
332 switch (srcCoeff) {
333 case kSC_BlendCoeff:
334 case kISC_BlendCoeff:
335 case kSA_BlendCoeff:
336 case kISA_BlendCoeff:
337 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
338 "coverage stages.\n");
339 break;
340 default:
341 break;
342 }
343 #endif
344 }
345
346 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
347 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
348
349 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
350 GrBlendCoeff* dstBlendCoeff) const {
351 *srcBlendCoeff = fSrcBlend;
352 *dstBlendCoeff = fDstBlend;
353 }
354
355 /**
356 * Sets the blending function constant referenced by the following blending
357 * coeffecients:
358 * kConstC_BlendCoeff
359 * kIConstC_BlendCoeff
360 * kConstA_BlendCoeff
361 * kIConstA_BlendCoeff
362 *
363 * @param constant the constant to set
364 */
365 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
366
367 /**
368 * Retrieves the last value set by setBlendConstant()
369 * @return the blending constant value
370 */
371 GrColor getBlendConstant() const { return fBlendConstant; }
372
373 /// @}
374
375 ///////////////////////////////////////////////////////////////////////////
376 /// @name View Matrix
377 ////
378
379 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000380 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000381 *
382 * In the post-view-matrix space the rectangle [0,w]x[0,h]
383 * fully covers the render target. (w and h are the width and height of the
384 * the rendertarget.)
385 */
386 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
387
388 /**
389 * Gets a writable pointer to the view matrix.
390 */
391 GrMatrix* viewMatrix() { return &fViewMatrix; }
392
393 /**
394 * Multiplies the current view matrix by a matrix
395 *
396 * After this call V' = V*m where V is the old view matrix,
397 * m is the parameter to this function, and V' is the new view matrix.
398 * (We consider positions to be column vectors so position vector p is
399 * transformed by matrix X as p' = X*p.)
400 *
401 * @param m the matrix used to modify the view matrix.
402 */
403 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
404
405 /**
406 * Multiplies the current view matrix by a matrix
407 *
408 * After this call V' = m*V where V is the old view matrix,
409 * m is the parameter to this function, and V' is the new view matrix.
410 * (We consider positions to be column vectors so position vector p is
411 * transformed by matrix X as p' = X*p.)
412 *
413 * @param m the matrix used to modify the view matrix.
414 */
415 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
416
417 /**
418 * Retrieves the current view matrix
419 * @return the current view matrix.
420 */
421 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
422
423 /**
424 * Retrieves the inverse of the current view matrix.
425 *
426 * If the current view matrix is invertible, return true, and if matrix
427 * is non-null, copy the inverse into it. If the current view matrix is
428 * non-invertible, return false and ignore the matrix parameter.
429 *
430 * @param matrix if not null, will receive a copy of the current inverse.
431 */
432 bool getViewInverse(GrMatrix* matrix) const {
433 // TODO: determine whether we really need to leave matrix unmodified
434 // at call sites when inversion fails.
435 GrMatrix inverse;
436 if (fViewMatrix.invert(&inverse)) {
437 if (matrix) {
438 *matrix = inverse;
439 }
440 return true;
441 }
442 return false;
443 }
444
445 class AutoViewMatrixRestore : public ::GrNoncopyable {
446 public:
447 AutoViewMatrixRestore() : fDrawState(NULL) {}
448 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
449 fDrawState = NULL;
450 this->set(ds, newMatrix);
451 }
452 AutoViewMatrixRestore(GrDrawState* ds) {
453 fDrawState = NULL;
454 this->set(ds);
455 }
456 ~AutoViewMatrixRestore() {
457 this->set(NULL, GrMatrix::I());
458 }
459 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
460 if (NULL != fDrawState) {
461 fDrawState->setViewMatrix(fSavedMatrix);
462 }
463 if (NULL != ds) {
464 fSavedMatrix = ds->getViewMatrix();
465 ds->setViewMatrix(newMatrix);
466 }
467 fDrawState = ds;
468 }
469 void set(GrDrawState* ds) {
470 if (NULL != fDrawState) {
471 fDrawState->setViewMatrix(fSavedMatrix);
472 }
473 if (NULL != ds) {
474 fSavedMatrix = ds->getViewMatrix();
475 }
476 fDrawState = ds;
477 }
478 private:
479 GrDrawState* fDrawState;
480 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000481 };
482
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000483 /// @}
484
485 ///////////////////////////////////////////////////////////////////////////
486 /// @name Render Target
487 ////
488
489 /**
490 * Sets the rendertarget used at the next drawing call
491 *
492 * @param target The render target to set.
493 */
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000494 void setRenderTarget(GrRenderTarget* target) {
495
496 // If we don't clear out the current render target before unreffing
497 // it we can get into an infinite loop as the GrGLRenderTarget's
498 // onRelease method recursively calls setTexture
499 GrRenderTarget* temp = fRenderTarget;
500 fRenderTarget = NULL;
501
502 SkSafeRef(target);
503 SkSafeUnref(temp);
504 fRenderTarget = target;
505 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000506
507 /**
508 * Retrieves the currently set rendertarget.
509 *
510 * @return The currently set render target.
511 */
512 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
513 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
514
515 class AutoRenderTargetRestore : public ::GrNoncopyable {
516 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000517 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000518 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
519 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000520 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000521 this->set(ds, newTarget);
522 }
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000523 ~AutoRenderTargetRestore() { this->restore(); }
524
525 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000526 if (NULL != fDrawState) {
527 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000528 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000529 }
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000530 GrSafeSetNull(fSavedTarget);
531 }
532
533 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
534 this->restore();
535
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000536 if (NULL != ds) {
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000537 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000538 fSavedTarget = ds->getRenderTarget();
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000539 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000540 ds->setRenderTarget(newTarget);
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000541 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000542 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000543 }
544 private:
545 GrDrawState* fDrawState;
546 GrRenderTarget* fSavedTarget;
547 };
548
549 /// @}
550
551 ///////////////////////////////////////////////////////////////////////////
552 /// @name Stencil
553 ////
554
555 /**
556 * Sets the stencil settings to use for the next draw.
557 * Changing the clip has the side-effect of possibly zeroing
558 * out the client settable stencil bits. So multipass algorithms
559 * using stencil should not change the clip between passes.
560 * @param settings the stencil settings to use.
561 */
562 void setStencil(const GrStencilSettings& settings) {
563 fStencilSettings = settings;
564 }
565
566 /**
567 * Shortcut to disable stencil testing and ops.
568 */
569 void disableStencil() {
570 fStencilSettings.setDisabled();
571 }
572
573 const GrStencilSettings& getStencil() const { return fStencilSettings; }
574
575 GrStencilSettings* stencil() { return &fStencilSettings; }
576
577 /// @}
578
579 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000580 /// @name Color Matrix
581 ////
582
583 /**
584 * Sets the color matrix to use for the next draw.
585 * @param matrix the 5x4 matrix to apply to the incoming color
586 */
587 void setColorMatrix(const float matrix[20]) {
588 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
589 }
590
591 const float* getColorMatrix() const { return fColorMatrix; }
592
593 /// @}
594
595 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000596 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000597 // Edge equations can be specified to perform antialiasing. Because the
598 // edges are specified as per-vertex data, vertices that are shared by
599 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000600 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000601 ////
602
603 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000604 * When specifying edges as vertex data this enum specifies what type of
605 * edges are in use. The edges are always 4 GrScalars in memory, even when
606 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000607 *
608 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
609 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000610 */
611 enum VertexEdgeType {
612 /* 1-pixel wide line
613 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
614 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000615 /* Quadratic specified by u^2-v canonical coords (only 2
616 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000617 being inside, positive outside. Edge specified in window space
618 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000619 kQuad_EdgeType,
620 /* Same as above but for hairline quadratics. Uses unsigned distance.
621 Coverage is min(0, 1-distance). */
622 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000623 /* Circle specified as center_x, center_y, outer_radius, inner_radius
624 all in window space (y-down). */
625 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000626
627 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000628 };
629
630 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000631 * Determines the interpretation per-vertex edge data when the
632 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
633 * are not specified the value of this setting has no effect.
634 */
635 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000636 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000637 fVertexEdgeType = type;
638 }
639
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000640 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000641
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000642 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000643
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000644 ///////////////////////////////////////////////////////////////////////////
645 /// @name State Flags
646 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000647
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000648 /**
649 * Flags that affect rendering. Controlled using enable/disableState(). All
650 * default to disabled.
651 */
652 enum StateBits {
653 /**
654 * Perform dithering. TODO: Re-evaluate whether we need this bit
655 */
656 kDither_StateBit = 0x01,
657 /**
658 * Perform HW anti-aliasing. This means either HW FSAA, if supported
659 * by the render target, or smooth-line rendering if a line primitive
660 * is drawn and line smoothing is supported by the 3D API.
661 */
662 kHWAntialias_StateBit = 0x02,
663 /**
664 * Draws will respect the clip, otherwise the clip is ignored.
665 */
666 kClip_StateBit = 0x04,
667 /**
668 * Disables writing to the color buffer. Useful when performing stencil
669 * operations.
670 */
671 kNoColorWrites_StateBit = 0x08,
672 /**
673 * Modifies the behavior of edge AA specified by setEdgeAA. If set,
674 * will test edge pairs for convexity when rasterizing. Set this if the
675 * source polygon is non-convex.
676 */
677 kEdgeAAConcave_StateBit = 0x10,
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000678 /**
679 * Draws will apply the color matrix, otherwise the color matrix is
680 * ignored.
681 */
682 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000683
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000684 // Users of the class may add additional bits to the vector
685 kDummyStateBit,
686 kLastPublicStateBit = kDummyStateBit-1,
687 };
688
689 void resetStateFlags() {
690 fFlagBits = 0;
691 }
692
693 /**
694 * Enable render state settings.
695 *
696 * @param flags bitfield of StateBits specifing the states to enable
697 */
698 void enableState(uint32_t stateBits) {
699 fFlagBits |= stateBits;
700 }
701
702 /**
703 * Disable render state settings.
704 *
705 * @param flags bitfield of StateBits specifing the states to disable
706 */
707 void disableState(uint32_t stateBits) {
708 fFlagBits &= ~(stateBits);
709 }
710
711 bool isDitherState() const {
712 return 0 != (fFlagBits & kDither_StateBit);
713 }
714
715 bool isHWAntialiasState() const {
716 return 0 != (fFlagBits & kHWAntialias_StateBit);
717 }
718
719 bool isClipState() const {
720 return 0 != (fFlagBits & kClip_StateBit);
721 }
722
723 bool isColorWriteDisabled() const {
724 return 0 != (fFlagBits & kNoColorWrites_StateBit);
725 }
726
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000727 bool isStateFlagEnabled(uint32_t stateBit) const {
728 return 0 != (stateBit & fFlagBits);
729 }
730
731 void copyStateFlags(const GrDrawState& ds) {
732 fFlagBits = ds.fFlagBits;
733 }
734
735 /// @}
736
737 ///////////////////////////////////////////////////////////////////////////
738 /// @name Face Culling
739 ////
740
741 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000742 kInvalid_DrawFace = -1,
743
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000744 kBoth_DrawFace,
745 kCCW_DrawFace,
746 kCW_DrawFace,
747 };
748
749 /**
750 * Controls whether clockwise, counterclockwise, or both faces are drawn.
751 * @param face the face(s) to draw.
752 */
753 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000754 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000755 fDrawFace = face;
756 }
757
758 /**
759 * Gets whether the target is drawing clockwise, counterclockwise,
760 * or both faces.
761 * @return the current draw face(s).
762 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000763 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000764
765 /// @}
766
767 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000768
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000769 // Most stages are usually not used, so conditionals here
770 // reduce the expected number of bytes touched by 50%.
771 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000772 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000773 return false;
774 }
775
776 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
777 return false;
778 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000779
780 for (int i = 0; i < kNumStages; i++) {
781 if (fTextures[i] &&
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000782 this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000783 return false;
784 }
785 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000786 if (kColorMatrix_StateBit & s.fFlagBits) {
787 if (memcmp(fColorMatrix,
788 s.fColorMatrix,
789 sizeof(fColorMatrix))) {
790 return false;
791 }
792 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000793
794 return true;
795 }
796 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
797
798 // Most stages are usually not used, so conditionals here
799 // reduce the expected number of bytes touched by 50%.
800 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000801 memcpy(this->podStart(), s.podStart(), this->podSize());
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000802
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000803 fViewMatrix = s.fViewMatrix;
804
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000805 for (int i = 0; i < kNumStages; i++) {
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000806 SkSafeRef(fTextures[i]); // already copied by memcpy
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000807 if (s.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 }
810 }
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000811
812 SkSafeRef(fRenderTarget); // already copied by memcpy
813
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000814 if (kColorMatrix_StateBit & s.fFlagBits) {
815 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
816 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000817
818 return *this;
819 }
820
821private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000822
823 const void* podStart() const {
824 return reinterpret_cast<const void*>(&fPodStartMarker);
825 }
826 void* podStart() {
827 return reinterpret_cast<void*>(&fPodStartMarker);
828 }
829 size_t memsetSize() const {
830 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
831 reinterpret_cast<size_t>(&fPodStartMarker) +
832 sizeof(fMemsetEndMarker);
833 }
834 size_t podSize() const {
835 // Can't use offsetof() with non-POD types, so stuck with pointer math.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000836 return reinterpret_cast<size_t>(&fPodEndMarker) -
837 reinterpret_cast<size_t>(&fPodStartMarker) +
838 sizeof(fPodEndMarker);
839 }
840
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000841 static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000842 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000843 union {
844 GrColor fBlendConstant;
845 GrColor fPodStartMarker;
846 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000847 GrColor fColorFilterColor;
848 uint32_t fFlagBits;
849 DrawFace fDrawFace;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000850 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000851 union {
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000852 VertexEdgeType fVertexEdgeType;
853 VertexEdgeType fMemsetEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000854 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000855 // @}
856
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000857 // @{ Initialized to values other than zero, but memcmp'ed in operator==
858 // and memcpy'ed in operator=.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000859 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000860 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000861 int fFirstCoverageStage;
862 SkXfermode::Mode fColorFilterMode;
863 GrBlendCoeff fSrcBlend;
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000864 GrBlendCoeff fDstBlend;
865 GrTexture* fTextures[kNumStages];
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000866 union {
robertphillips@google.comab303ef2012-05-28 13:37:25 +0000867 GrRenderTarget* fRenderTarget;
868 GrRenderTarget* fPodEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000869 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000870 // @}
871
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000872 GrMatrix fViewMatrix;
873
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000874 // This field must be last; it will not be copied or compared
875 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000876 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000877 // only compared if the color matrix enable flag is set
878 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000879
tomhudson@google.com93813632011-10-27 20:21:16 +0000880};
881
882#endif