blob: a2b0818f9e3fb2a83c653b8cc884049c1893a841 [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.com837576b2012-05-25 11:45:40 +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.com837576b2012-05-25 11:45:40 +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.com837576b2012-05-25 11:45:40 +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.com837576b2012-05-25 11:45:40 +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.com837576b2012-05-25 11:45:40 +000086
87 for (int i = 0; i < kNumStages; ++i) {
88 GrSafeSetNull(fTextures[i]);
89 }
90 GrSafeSetNull(fRenderTarget);
91
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000092 // make sure any pad is zero for memcmp
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000093 // all GrDrawState members should default to something valid by the
94 // the memset except those initialized individually below. There should
95 // be no padding between the individually initialized members.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000096 memset(this->podStart(), 0, this->memsetSize());
97
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000098 // pedantic assertion that our ptrs will
99 // be NULL (0 ptr is mem addr 0)
100 GrAssert((intptr_t)(void*)NULL == 0LL);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000101 GR_STATIC_ASSERT(0 == kBoth_DrawFace);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000102 GrAssert(fStencilSettings.isDisabled());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000103
104 // memset exceptions
105 fColor = 0xffffffff;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000106 fCoverage = 0xffffffff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000107 fFirstCoverageStage = kNumStages;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000108 fColorFilterMode = SkXfermode::kDst_Mode;
109 fSrcBlend = kOne_BlendCoeff;
110 fDstBlend = kZero_BlendCoeff;
111 fViewMatrix.reset();
112
113 // ensure values that will be memcmp'ed in == but not memset in reset()
114 // are tightly packed
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000115 GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) +
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000116 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
robertphillips@google.com837576b2012-05-25 11:45:40 +0000117 sizeof(fSrcBlend) + sizeof(fDstBlend) + sizeof(fTextures) +
118 sizeof(fRenderTarget) == this->podSize());
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000119 }
120
121 ///////////////////////////////////////////////////////////////////////////
122 /// @name Color
123 ////
124
125 /**
126 * Sets color for next draw to a premultiplied-alpha color.
127 *
128 * @param color the color to set.
129 */
130 void setColor(GrColor color) { fColor = color; }
131
132 GrColor getColor() const { return fColor; }
133
134 /**
135 * Sets the color to be used for the next draw to be
136 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
137 *
138 * @param alpha The alpha value to set as the color.
139 */
140 void setAlpha(uint8_t a) {
141 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
142 }
143
144 /**
145 * Add a color filter that can be represented by a color and a mode. Applied
146 * after color-computing texture stages.
147 */
148 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
149 fColorFilterColor = c;
150 fColorFilterMode = mode;
151 }
152
153 GrColor getColorFilterColor() const { return fColorFilterColor; }
154 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
155
156 /// @}
157
158 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000159 /// @name Coverage
160 ////
161
162 /**
163 * Sets a constant fractional coverage to be applied to the draw. The
164 * initial value (after construction or reset()) is 0xff. The constant
165 * coverage is ignored when per-vertex coverage is provided.
166 */
167 void setCoverage(uint8_t coverage) {
168 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
169 }
170
171 /**
172 * Version of above that specifies 4 channel per-vertex color. The value
173 * should be premultiplied.
174 */
175 void setCoverage4(GrColor coverage) {
176 fCoverage = coverage;
177 }
178
179 GrColor getCoverage() const {
180 return fCoverage;
181 }
182
183 /// @}
184
185 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000186 /// @name Textures
187 ////
188
189 /**
190 * Sets the texture used at the next drawing call
191 *
192 * @param stage The texture stage for which the texture will be set
193 *
194 * @param texture The texture to set. Can be NULL though there is no
195 * advantage to settings a NULL texture if doing non-textured drawing
196 */
197 void setTexture(int stage, GrTexture* texture) {
198 GrAssert((unsigned)stage < kNumStages);
robertphillips@google.com1942c052012-05-03 17:58:27 +0000199
robertphillips@google.com837576b2012-05-25 11:45:40 +0000200 // If we don't clear out the current texture before unreffing
201 // it we can get into an infinite loop as the GrGLTexture's
202 // onRelease method recursively calls setTexture
203 GrTexture* temp = fTextures[stage];
204 fTextures[stage] = NULL;
robertphillips@google.com1942c052012-05-03 17:58:27 +0000205
robertphillips@google.com837576b2012-05-25 11:45:40 +0000206 SkSafeRef(texture);
207 SkSafeUnref(temp);
robertphillips@google.com1942c052012-05-03 17:58:27 +0000208
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000209 fTextures[stage] = texture;
210 }
211
212 /**
213 * Retrieves the currently set texture.
214 *
215 * @return The currently set texture. The return value will be NULL if no
216 * texture has been set, NULL was most recently passed to
217 * setTexture, or the last setTexture was destroyed.
218 */
219 const GrTexture* getTexture(int stage) const {
220 GrAssert((unsigned)stage < kNumStages);
221 return fTextures[stage];
222 }
223 GrTexture* getTexture(int stage) {
224 GrAssert((unsigned)stage < kNumStages);
225 return fTextures[stage];
226 }
227
228 /// @}
229
230 ///////////////////////////////////////////////////////////////////////////
231 /// @name Samplers
232 ////
233
234 /**
235 * Returns the current sampler for a stage.
236 */
237 const GrSamplerState& getSampler(int stage) const {
238 GrAssert((unsigned)stage < kNumStages);
239 return fSamplerStates[stage];
240 }
241
242 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000243 * Writable pointer to a stage's sampler.
244 */
245 GrSamplerState* sampler(int stage) {
246 GrAssert((unsigned)stage < kNumStages);
247 return fSamplerStates + stage;
248 }
249
250 /**
251 * Preconcats the matrix of all samplers in the mask with the same matrix.
252 */
253 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
254 GrAssert(!(stageMask & kIllegalStageMaskBits));
255 for (int i = 0; i < kNumStages; ++i) {
256 if ((1 << i) & stageMask) {
257 fSamplerStates[i].preConcatMatrix(matrix);
258 }
259 }
260 }
261
262 /// @}
263
264 ///////////////////////////////////////////////////////////////////////////
265 /// @name Coverage / Color Stages
266 ////
267
268 /**
269 * A common pattern is to compute a color with the initial stages and then
270 * modulate that color by a coverage value in later stage(s) (AA, mask-
271 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
272 * computed based on the pre-coverage-modulated color. The division of
273 * stages between color-computing and coverage-computing is specified by
274 * this method. Initially this is kNumStages (all stages
275 * are color-computing).
276 */
277 void setFirstCoverageStage(int firstCoverageStage) {
278 GrAssert((unsigned)firstCoverageStage <= kNumStages);
279 fFirstCoverageStage = firstCoverageStage;
280 }
281
282 /**
283 * Gets the index of the first coverage-computing stage.
284 */
285 int getFirstCoverageStage() const {
286 return fFirstCoverageStage;
287 }
288
289 ///@}
290
291 ///////////////////////////////////////////////////////////////////////////
292 /// @name Blending
293 ////
294
295 /**
296 * Sets the blending function coeffecients.
297 *
298 * The blend function will be:
299 * D' = sat(S*srcCoef + D*dstCoef)
300 *
301 * where D is the existing destination color, S is the incoming source
302 * color, and D' is the new destination color that will be written. sat()
303 * is the saturation function.
304 *
305 * @param srcCoef coeffecient applied to the src color.
306 * @param dstCoef coeffecient applied to the dst color.
307 */
308 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
309 fSrcBlend = srcCoeff;
310 fDstBlend = dstCoeff;
311 #if GR_DEBUG
312 switch (dstCoeff) {
313 case kDC_BlendCoeff:
314 case kIDC_BlendCoeff:
315 case kDA_BlendCoeff:
316 case kIDA_BlendCoeff:
317 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
318 "coverage stages.\n");
319 break;
320 default:
321 break;
322 }
323 switch (srcCoeff) {
324 case kSC_BlendCoeff:
325 case kISC_BlendCoeff:
326 case kSA_BlendCoeff:
327 case kISA_BlendCoeff:
328 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
329 "coverage stages.\n");
330 break;
331 default:
332 break;
333 }
334 #endif
335 }
336
337 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
338 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
339
340 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
341 GrBlendCoeff* dstBlendCoeff) const {
342 *srcBlendCoeff = fSrcBlend;
343 *dstBlendCoeff = fDstBlend;
344 }
345
346 /**
347 * Sets the blending function constant referenced by the following blending
348 * coeffecients:
349 * kConstC_BlendCoeff
350 * kIConstC_BlendCoeff
351 * kConstA_BlendCoeff
352 * kIConstA_BlendCoeff
353 *
354 * @param constant the constant to set
355 */
356 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
357
358 /**
359 * Retrieves the last value set by setBlendConstant()
360 * @return the blending constant value
361 */
362 GrColor getBlendConstant() const { return fBlendConstant; }
363
364 /// @}
365
366 ///////////////////////////////////////////////////////////////////////////
367 /// @name View Matrix
368 ////
369
370 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000371 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000372 *
373 * In the post-view-matrix space the rectangle [0,w]x[0,h]
374 * fully covers the render target. (w and h are the width and height of the
375 * the rendertarget.)
376 */
377 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
378
379 /**
380 * Gets a writable pointer to the view matrix.
381 */
382 GrMatrix* viewMatrix() { return &fViewMatrix; }
383
384 /**
385 * Multiplies the current view matrix by a matrix
386 *
387 * After this call V' = V*m where V is the old view matrix,
388 * m is the parameter to this function, and V' is the new view matrix.
389 * (We consider positions to be column vectors so position vector p is
390 * transformed by matrix X as p' = X*p.)
391 *
392 * @param m the matrix used to modify the view matrix.
393 */
394 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
395
396 /**
397 * Multiplies the current view matrix by a matrix
398 *
399 * After this call V' = m*V where V is the old view matrix,
400 * m is the parameter to this function, and V' is the new view matrix.
401 * (We consider positions to be column vectors so position vector p is
402 * transformed by matrix X as p' = X*p.)
403 *
404 * @param m the matrix used to modify the view matrix.
405 */
406 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
407
408 /**
409 * Retrieves the current view matrix
410 * @return the current view matrix.
411 */
412 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
413
414 /**
415 * Retrieves the inverse of the current view matrix.
416 *
417 * If the current view matrix is invertible, return true, and if matrix
418 * is non-null, copy the inverse into it. If the current view matrix is
419 * non-invertible, return false and ignore the matrix parameter.
420 *
421 * @param matrix if not null, will receive a copy of the current inverse.
422 */
423 bool getViewInverse(GrMatrix* matrix) const {
424 // TODO: determine whether we really need to leave matrix unmodified
425 // at call sites when inversion fails.
426 GrMatrix inverse;
427 if (fViewMatrix.invert(&inverse)) {
428 if (matrix) {
429 *matrix = inverse;
430 }
431 return true;
432 }
433 return false;
434 }
435
436 class AutoViewMatrixRestore : public ::GrNoncopyable {
437 public:
438 AutoViewMatrixRestore() : fDrawState(NULL) {}
439 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
440 fDrawState = NULL;
441 this->set(ds, newMatrix);
442 }
443 AutoViewMatrixRestore(GrDrawState* ds) {
444 fDrawState = NULL;
445 this->set(ds);
446 }
447 ~AutoViewMatrixRestore() {
448 this->set(NULL, GrMatrix::I());
449 }
450 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
451 if (NULL != fDrawState) {
452 fDrawState->setViewMatrix(fSavedMatrix);
453 }
454 if (NULL != ds) {
455 fSavedMatrix = ds->getViewMatrix();
456 ds->setViewMatrix(newMatrix);
457 }
458 fDrawState = ds;
459 }
460 void set(GrDrawState* ds) {
461 if (NULL != fDrawState) {
462 fDrawState->setViewMatrix(fSavedMatrix);
463 }
464 if (NULL != ds) {
465 fSavedMatrix = ds->getViewMatrix();
466 }
467 fDrawState = ds;
468 }
469 private:
470 GrDrawState* fDrawState;
471 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000472 };
473
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000474 /// @}
475
476 ///////////////////////////////////////////////////////////////////////////
477 /// @name Render Target
478 ////
479
480 /**
481 * Sets the rendertarget used at the next drawing call
482 *
483 * @param target The render target to set.
484 */
robertphillips@google.com837576b2012-05-25 11:45:40 +0000485 void setRenderTarget(GrRenderTarget* target) {
486
487 // If we don't clear out the current render target before unreffing
488 // it we can get into an infinite loop as the GrGLRenderTarget's
489 // onRelease method recursively calls setTexture
490 GrRenderTarget* temp = fRenderTarget;
491 fRenderTarget = NULL;
492
493 SkSafeRef(target);
494 SkSafeUnref(temp);
495 fRenderTarget = target;
496 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000497
498 /**
499 * Retrieves the currently set rendertarget.
500 *
501 * @return The currently set render target.
502 */
503 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
504 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
505
506 class AutoRenderTargetRestore : public ::GrNoncopyable {
507 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000508 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000509 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
510 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000511 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000512 this->set(ds, newTarget);
513 }
robertphillips@google.com837576b2012-05-25 11:45:40 +0000514 ~AutoRenderTargetRestore() { this->restore(); }
515
516 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000517 if (NULL != fDrawState) {
518 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com837576b2012-05-25 11:45:40 +0000519 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000520 }
robertphillips@google.com837576b2012-05-25 11:45:40 +0000521 GrSafeSetNull(fSavedTarget);
522 }
523
524 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
525 this->restore();
526
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000527 if (NULL != ds) {
robertphillips@google.com837576b2012-05-25 11:45:40 +0000528 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000529 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com837576b2012-05-25 11:45:40 +0000530 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000531 ds->setRenderTarget(newTarget);
robertphillips@google.com837576b2012-05-25 11:45:40 +0000532 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000533 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000534 }
535 private:
536 GrDrawState* fDrawState;
537 GrRenderTarget* fSavedTarget;
538 };
539
540 /// @}
541
542 ///////////////////////////////////////////////////////////////////////////
543 /// @name Stencil
544 ////
545
546 /**
547 * Sets the stencil settings to use for the next draw.
548 * Changing the clip has the side-effect of possibly zeroing
549 * out the client settable stencil bits. So multipass algorithms
550 * using stencil should not change the clip between passes.
551 * @param settings the stencil settings to use.
552 */
553 void setStencil(const GrStencilSettings& settings) {
554 fStencilSettings = settings;
555 }
556
557 /**
558 * Shortcut to disable stencil testing and ops.
559 */
560 void disableStencil() {
561 fStencilSettings.setDisabled();
562 }
563
564 const GrStencilSettings& getStencil() const { return fStencilSettings; }
565
566 GrStencilSettings* stencil() { return &fStencilSettings; }
567
568 /// @}
569
570 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000571 /// @name Color Matrix
572 ////
573
574 /**
575 * Sets the color matrix to use for the next draw.
576 * @param matrix the 5x4 matrix to apply to the incoming color
577 */
578 void setColorMatrix(const float matrix[20]) {
579 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
580 }
581
582 const float* getColorMatrix() const { return fColorMatrix; }
583
584 /// @}
585
586 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000587 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000588 // Edge equations can be specified to perform antialiasing. Because the
589 // edges are specified as per-vertex data, vertices that are shared by
590 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000591 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000592 ////
593
594 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000595 * When specifying edges as vertex data this enum specifies what type of
596 * edges are in use. The edges are always 4 GrScalars in memory, even when
597 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000598 *
599 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
600 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000601 */
602 enum VertexEdgeType {
603 /* 1-pixel wide line
604 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
605 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000606 /* Quadratic specified by u^2-v canonical coords (only 2
607 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000608 being inside, positive outside. Edge specified in window space
609 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000610 kQuad_EdgeType,
611 /* Same as above but for hairline quadratics. Uses unsigned distance.
612 Coverage is min(0, 1-distance). */
613 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000614 /* Circle specified as center_x, center_y, outer_radius, inner_radius
615 all in window space (y-down). */
616 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000617
618 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000619 };
620
621 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000622 * Determines the interpretation per-vertex edge data when the
623 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
624 * are not specified the value of this setting has no effect.
625 */
626 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000627 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000628 fVertexEdgeType = type;
629 }
630
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000631 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000632
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000633 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000634
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000635 ///////////////////////////////////////////////////////////////////////////
636 /// @name State Flags
637 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000638
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000639 /**
640 * Flags that affect rendering. Controlled using enable/disableState(). All
641 * default to disabled.
642 */
643 enum StateBits {
644 /**
645 * Perform dithering. TODO: Re-evaluate whether we need this bit
646 */
647 kDither_StateBit = 0x01,
648 /**
649 * Perform HW anti-aliasing. This means either HW FSAA, if supported
650 * by the render target, or smooth-line rendering if a line primitive
651 * is drawn and line smoothing is supported by the 3D API.
652 */
653 kHWAntialias_StateBit = 0x02,
654 /**
655 * Draws will respect the clip, otherwise the clip is ignored.
656 */
657 kClip_StateBit = 0x04,
658 /**
659 * Disables writing to the color buffer. Useful when performing stencil
660 * operations.
661 */
662 kNoColorWrites_StateBit = 0x08,
663 /**
664 * Modifies the behavior of edge AA specified by setEdgeAA. If set,
665 * will test edge pairs for convexity when rasterizing. Set this if the
666 * source polygon is non-convex.
667 */
668 kEdgeAAConcave_StateBit = 0x10,
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000669 /**
670 * Draws will apply the color matrix, otherwise the color matrix is
671 * ignored.
672 */
673 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000674
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000675 // Users of the class may add additional bits to the vector
676 kDummyStateBit,
677 kLastPublicStateBit = kDummyStateBit-1,
678 };
679
680 void resetStateFlags() {
681 fFlagBits = 0;
682 }
683
684 /**
685 * Enable render state settings.
686 *
687 * @param flags bitfield of StateBits specifing the states to enable
688 */
689 void enableState(uint32_t stateBits) {
690 fFlagBits |= stateBits;
691 }
692
693 /**
694 * Disable render state settings.
695 *
696 * @param flags bitfield of StateBits specifing the states to disable
697 */
698 void disableState(uint32_t stateBits) {
699 fFlagBits &= ~(stateBits);
700 }
701
702 bool isDitherState() const {
703 return 0 != (fFlagBits & kDither_StateBit);
704 }
705
706 bool isHWAntialiasState() const {
707 return 0 != (fFlagBits & kHWAntialias_StateBit);
708 }
709
710 bool isClipState() const {
711 return 0 != (fFlagBits & kClip_StateBit);
712 }
713
714 bool isColorWriteDisabled() const {
715 return 0 != (fFlagBits & kNoColorWrites_StateBit);
716 }
717
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000718 bool isStateFlagEnabled(uint32_t stateBit) const {
719 return 0 != (stateBit & fFlagBits);
720 }
721
722 void copyStateFlags(const GrDrawState& ds) {
723 fFlagBits = ds.fFlagBits;
724 }
725
726 /// @}
727
728 ///////////////////////////////////////////////////////////////////////////
729 /// @name Face Culling
730 ////
731
732 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000733 kInvalid_DrawFace = -1,
734
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000735 kBoth_DrawFace,
736 kCCW_DrawFace,
737 kCW_DrawFace,
738 };
739
740 /**
741 * Controls whether clockwise, counterclockwise, or both faces are drawn.
742 * @param face the face(s) to draw.
743 */
744 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000745 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000746 fDrawFace = face;
747 }
748
749 /**
750 * Gets whether the target is drawing clockwise, counterclockwise,
751 * or both faces.
752 * @return the current draw face(s).
753 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000754 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000755
756 /// @}
757
758 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000759
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000760 // Most stages are usually not used, so conditionals here
761 // reduce the expected number of bytes touched by 50%.
762 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000763 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000764 return false;
765 }
766
767 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
768 return false;
769 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000770
771 for (int i = 0; i < kNumStages; i++) {
772 if (fTextures[i] &&
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000773 this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000774 return false;
775 }
776 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000777 if (kColorMatrix_StateBit & s.fFlagBits) {
778 if (memcmp(fColorMatrix,
779 s.fColorMatrix,
780 sizeof(fColorMatrix))) {
781 return false;
782 }
783 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000784
785 return true;
786 }
787 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
788
789 // Most stages are usually not used, so conditionals here
790 // reduce the expected number of bytes touched by 50%.
791 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000792 memcpy(this->podStart(), s.podStart(), this->podSize());
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000793
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000794 fViewMatrix = s.fViewMatrix;
795
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000796 for (int i = 0; i < kNumStages; i++) {
robertphillips@google.com837576b2012-05-25 11:45:40 +0000797 SkSafeRef(fTextures[i]); // already copied by memcpy
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000798 if (s.fTextures[i]) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000799 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000800 }
801 }
robertphillips@google.com837576b2012-05-25 11:45:40 +0000802
803 SkSafeRef(fRenderTarget); // already copied by memcpy
804
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000805 if (kColorMatrix_StateBit & s.fFlagBits) {
806 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
807 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000808
809 return *this;
810 }
811
812private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000813
814 const void* podStart() const {
815 return reinterpret_cast<const void*>(&fPodStartMarker);
816 }
817 void* podStart() {
818 return reinterpret_cast<void*>(&fPodStartMarker);
819 }
820 size_t memsetSize() const {
821 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
822 reinterpret_cast<size_t>(&fPodStartMarker) +
823 sizeof(fMemsetEndMarker);
824 }
825 size_t podSize() const {
826 // Can't use offsetof() with non-POD types, so stuck with pointer math.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000827 return reinterpret_cast<size_t>(&fPodEndMarker) -
828 reinterpret_cast<size_t>(&fPodStartMarker) +
829 sizeof(fPodEndMarker);
830 }
831
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000832 static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000833 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000834 union {
835 GrColor fBlendConstant;
836 GrColor fPodStartMarker;
837 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000838 GrColor fColorFilterColor;
839 uint32_t fFlagBits;
840 DrawFace fDrawFace;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000841 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000842 union {
robertphillips@google.com837576b2012-05-25 11:45:40 +0000843 VertexEdgeType fVertexEdgeType;
844 VertexEdgeType fMemsetEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000845 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000846 // @}
847
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000848 // @{ Initialized to values other than zero, but memcmp'ed in operator==
849 // and memcpy'ed in operator=.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000850 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000851 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000852 int fFirstCoverageStage;
853 SkXfermode::Mode fColorFilterMode;
854 GrBlendCoeff fSrcBlend;
robertphillips@google.com837576b2012-05-25 11:45:40 +0000855 GrBlendCoeff fDstBlend;
856 GrTexture* fTextures[kNumStages];
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000857 union {
robertphillips@google.com837576b2012-05-25 11:45:40 +0000858 GrRenderTarget* fRenderTarget;
859 GrRenderTarget* fPodEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000860 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000861 // @}
862
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000863 GrMatrix fViewMatrix;
864
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000865 // This field must be last; it will not be copied or compared
866 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000867 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000868 // only compared if the color matrix enable flag is set
869 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000870
tomhudson@google.com93813632011-10-27 20:21:16 +0000871};
872
873#endif