blob: 55bd04c87ef162c60e7249387f6abe95b0eee3b0 [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"
bsalomon@google.com64aef2b2012-06-11 15:36:13 +000017#include "GrTexture.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000018
19#include "SkXfermode.h"
20
robertphillips@google.comc077d1e2012-05-28 14:10:15 +000021class GrRenderTarget;
22class GrTexture;
tomhudson@google.com93813632011-10-27 20:21:16 +000023
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000024class GrDrawState : public GrRefCnt {
tomhudson@google.com93813632011-10-27 20:21:16 +000025
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000026public:
tomhudson@google.com93813632011-10-27 20:21:16 +000027 /**
28 * Number of texture stages. Each stage takes as input a color and
29 * 2D texture coordinates. The color input to the first enabled stage is the
30 * per-vertex color or the constant color (setColor/setAlpha) if there are
31 * no per-vertex colors. For subsequent stages the input color is the output
32 * color from the previous enabled stage. The output color of each stage is
33 * the input color modulated with the result of a texture lookup. Texture
34 * lookups are specified by a texture a sampler (setSamplerState). Texture
35 * coordinates for each stage come from the vertices based on a
36 * GrVertexLayout bitfield. The output fragment color is the output color of
37 * the last enabled stage. The presence or absence of texture coordinates
38 * for each stage in the vertex layout indicates whether a stage is enabled
39 * or not.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000040 *
41 * Stages 0 through GrPaint::kTotalStages-1 are reserved for setting up
42 * the draw (i.e., textures and filter masks). Stages GrPaint::kTotalStages
43 * through kNumStages-1 are earmarked for use by GrTextContext and
44 * GrPathRenderer-derived classes.
tomhudson@google.com93813632011-10-27 20:21:16 +000045 */
46 enum {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000047 kNumStages = 4,
tomhudson@google.com93813632011-10-27 20:21:16 +000048 kMaxTexCoords = kNumStages
49 };
50
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000051 /**
52 * Bitfield used to indicate a set of stages.
53 */
54 typedef uint32_t StageMask;
55 GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
56
robertphillips@google.comc077d1e2012-05-28 14:10:15 +000057 GrDrawState() {
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000058 this->reset();
59 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000060
robertphillips@google.comc077d1e2012-05-28 14:10:15 +000061 GrDrawState(const GrDrawState& state) {
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000062 *this = state;
63 }
64
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000065 /**
66 * Resets to the default state. Sampler states will not be modified.
67 */
68 void reset() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000069 // make sure any pad is zero for memcmp
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000070 // all GrDrawState members should default to something valid by the
71 // the memset except those initialized individually below. There should
72 // be no padding between the individually initialized members.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000073 memset(this->podStart(), 0, this->memsetSize());
74
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000075 // pedantic assertion that our ptrs will
76 // be NULL (0 ptr is mem addr 0)
77 GrAssert((intptr_t)(void*)NULL == 0LL);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000078 GR_STATIC_ASSERT(0 == kBoth_DrawFace);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000079 GrAssert(fStencilSettings.isDisabled());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000080
81 // memset exceptions
82 fColor = 0xffffffff;
bsalomon@google.com2401ae82012-01-17 21:03:05 +000083 fCoverage = 0xffffffff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000084 fFirstCoverageStage = kNumStages;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000085 fColorFilterMode = SkXfermode::kDst_Mode;
bsalomon@google.com47059542012-06-06 20:51:20 +000086 fSrcBlend = kOne_GrBlendCoeff;
87 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000088 fViewMatrix.reset();
robertphillips@google.comc077d1e2012-05-28 14:10:15 +000089 fBehaviorBits = 0;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000090
91 // ensure values that will be memcmp'ed in == but not memset in reset()
92 // are tightly packed
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000093 GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) +
bsalomon@google.com2401ae82012-01-17 21:03:05 +000094 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
robertphillips@google.comc077d1e2012-05-28 14:10:15 +000095 sizeof(fSrcBlend) + sizeof(fDstBlend) ==
96 this->podSize());
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000097 }
98
99 ///////////////////////////////////////////////////////////////////////////
100 /// @name Color
101 ////
102
103 /**
104 * Sets color for next draw to a premultiplied-alpha color.
105 *
106 * @param color the color to set.
107 */
108 void setColor(GrColor color) { fColor = color; }
109
110 GrColor getColor() const { return fColor; }
111
112 /**
113 * Sets the color to be used for the next draw to be
114 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
115 *
116 * @param alpha The alpha value to set as the color.
117 */
118 void setAlpha(uint8_t a) {
119 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
120 }
121
122 /**
123 * Add a color filter that can be represented by a color and a mode. Applied
124 * after color-computing texture stages.
125 */
126 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
127 fColorFilterColor = c;
128 fColorFilterMode = mode;
129 }
130
131 GrColor getColorFilterColor() const { return fColorFilterColor; }
132 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
133
134 /// @}
135
136 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000137 /// @name Coverage
138 ////
139
140 /**
141 * Sets a constant fractional coverage to be applied to the draw. The
142 * initial value (after construction or reset()) is 0xff. The constant
143 * coverage is ignored when per-vertex coverage is provided.
144 */
145 void setCoverage(uint8_t coverage) {
146 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
147 }
148
149 /**
150 * Version of above that specifies 4 channel per-vertex color. The value
151 * should be premultiplied.
152 */
153 void setCoverage4(GrColor coverage) {
154 fCoverage = coverage;
155 }
156
157 GrColor getCoverage() const {
158 return fCoverage;
159 }
160
161 /// @}
162
163 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000164 /// @name Textures
165 ////
166
167 /**
168 * Sets the texture used at the next drawing call
169 *
170 * @param stage The texture stage for which the texture will be set
171 *
172 * @param texture The texture to set. Can be NULL though there is no
173 * advantage to settings a NULL texture if doing non-textured drawing
174 */
175 void setTexture(int stage, GrTexture* texture) {
176 GrAssert((unsigned)stage < kNumStages);
robertphillips@google.com1942c052012-05-03 17:58:27 +0000177
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000178 if (isBehaviorEnabled(kTexturesNeedRef_BehaviorBit)) {
179 // If we don't clear out the current texture before unreffing
180 // it we can get into an infinite loop as the GrGLTexture's
181 // onRelease method recursively calls setTexture
182 GrTexture* temp = fTextures[stage];
183 fTextures[stage] = NULL;
robertphillips@google.com1942c052012-05-03 17:58:27 +0000184
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000185 SkSafeRef(texture);
186 SkSafeUnref(temp);
187 }
robertphillips@google.com1942c052012-05-03 17:58:27 +0000188
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000189 fTextures[stage] = texture;
190 }
191
192 /**
193 * Retrieves the currently set texture.
194 *
195 * @return The currently set texture. The return value will be NULL if no
196 * texture has been set, NULL was most recently passed to
197 * setTexture, or the last setTexture was destroyed.
198 */
199 const GrTexture* getTexture(int stage) const {
200 GrAssert((unsigned)stage < kNumStages);
201 return fTextures[stage];
202 }
203 GrTexture* getTexture(int stage) {
204 GrAssert((unsigned)stage < kNumStages);
205 return fTextures[stage];
206 }
207
208 /// @}
209
210 ///////////////////////////////////////////////////////////////////////////
211 /// @name Samplers
212 ////
213
214 /**
215 * Returns the current sampler for a stage.
216 */
217 const GrSamplerState& getSampler(int stage) const {
218 GrAssert((unsigned)stage < kNumStages);
219 return fSamplerStates[stage];
220 }
221
222 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000223 * Writable pointer to a stage's sampler.
224 */
225 GrSamplerState* sampler(int stage) {
226 GrAssert((unsigned)stage < kNumStages);
227 return fSamplerStates + stage;
228 }
229
230 /**
231 * Preconcats the matrix of all samplers in the mask with the same matrix.
232 */
233 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
234 GrAssert(!(stageMask & kIllegalStageMaskBits));
235 for (int i = 0; i < kNumStages; ++i) {
236 if ((1 << i) & stageMask) {
237 fSamplerStates[i].preConcatMatrix(matrix);
238 }
239 }
240 }
241
242 /// @}
243
244 ///////////////////////////////////////////////////////////////////////////
245 /// @name Coverage / Color Stages
246 ////
247
248 /**
249 * A common pattern is to compute a color with the initial stages and then
250 * modulate that color by a coverage value in later stage(s) (AA, mask-
251 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
252 * computed based on the pre-coverage-modulated color. The division of
253 * stages between color-computing and coverage-computing is specified by
254 * this method. Initially this is kNumStages (all stages
255 * are color-computing).
256 */
257 void setFirstCoverageStage(int firstCoverageStage) {
258 GrAssert((unsigned)firstCoverageStage <= kNumStages);
259 fFirstCoverageStage = firstCoverageStage;
260 }
261
262 /**
263 * Gets the index of the first coverage-computing stage.
264 */
265 int getFirstCoverageStage() const {
266 return fFirstCoverageStage;
267 }
268
269 ///@}
270
271 ///////////////////////////////////////////////////////////////////////////
272 /// @name Blending
273 ////
274
275 /**
276 * Sets the blending function coeffecients.
277 *
278 * The blend function will be:
279 * D' = sat(S*srcCoef + D*dstCoef)
280 *
281 * where D is the existing destination color, S is the incoming source
282 * color, and D' is the new destination color that will be written. sat()
283 * is the saturation function.
284 *
285 * @param srcCoef coeffecient applied to the src color.
286 * @param dstCoef coeffecient applied to the dst color.
287 */
288 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
289 fSrcBlend = srcCoeff;
290 fDstBlend = dstCoeff;
291 #if GR_DEBUG
292 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000293 case kDC_GrBlendCoeff:
294 case kIDC_GrBlendCoeff:
295 case kDA_GrBlendCoeff:
296 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000297 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
298 "coverage stages.\n");
299 break;
300 default:
301 break;
302 }
303 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000304 case kSC_GrBlendCoeff:
305 case kISC_GrBlendCoeff:
306 case kSA_GrBlendCoeff:
307 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000308 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
309 "coverage stages.\n");
310 break;
311 default:
312 break;
313 }
314 #endif
315 }
316
317 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
318 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
319
320 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
321 GrBlendCoeff* dstBlendCoeff) const {
322 *srcBlendCoeff = fSrcBlend;
323 *dstBlendCoeff = fDstBlend;
324 }
325
326 /**
327 * Sets the blending function constant referenced by the following blending
328 * coeffecients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000329 * kConstC_GrBlendCoeff
330 * kIConstC_GrBlendCoeff
331 * kConstA_GrBlendCoeff
332 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000333 *
334 * @param constant the constant to set
335 */
336 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
337
338 /**
339 * Retrieves the last value set by setBlendConstant()
340 * @return the blending constant value
341 */
342 GrColor getBlendConstant() const { return fBlendConstant; }
343
344 /// @}
345
346 ///////////////////////////////////////////////////////////////////////////
347 /// @name View Matrix
348 ////
349
350 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000351 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000352 *
353 * In the post-view-matrix space the rectangle [0,w]x[0,h]
354 * fully covers the render target. (w and h are the width and height of the
355 * the rendertarget.)
356 */
357 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
358
359 /**
360 * Gets a writable pointer to the view matrix.
361 */
362 GrMatrix* viewMatrix() { return &fViewMatrix; }
363
364 /**
365 * Multiplies the current view matrix by a matrix
366 *
367 * After this call V' = V*m where V is the old view matrix,
368 * m is the parameter to this function, and V' is the new view matrix.
369 * (We consider positions to be column vectors so position vector p is
370 * transformed by matrix X as p' = X*p.)
371 *
372 * @param m the matrix used to modify the view matrix.
373 */
374 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
375
376 /**
377 * Multiplies the current view matrix by a matrix
378 *
379 * After this call V' = m*V where V is the old view matrix,
380 * m is the parameter to this function, and V' is the new view matrix.
381 * (We consider positions to be column vectors so position vector p is
382 * transformed by matrix X as p' = X*p.)
383 *
384 * @param m the matrix used to modify the view matrix.
385 */
386 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
387
388 /**
389 * Retrieves the current view matrix
390 * @return the current view matrix.
391 */
392 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
393
394 /**
395 * Retrieves the inverse of the current view matrix.
396 *
397 * If the current view matrix is invertible, return true, and if matrix
398 * is non-null, copy the inverse into it. If the current view matrix is
399 * non-invertible, return false and ignore the matrix parameter.
400 *
401 * @param matrix if not null, will receive a copy of the current inverse.
402 */
403 bool getViewInverse(GrMatrix* matrix) const {
404 // TODO: determine whether we really need to leave matrix unmodified
405 // at call sites when inversion fails.
406 GrMatrix inverse;
407 if (fViewMatrix.invert(&inverse)) {
408 if (matrix) {
409 *matrix = inverse;
410 }
411 return true;
412 }
413 return false;
414 }
415
416 class AutoViewMatrixRestore : public ::GrNoncopyable {
417 public:
418 AutoViewMatrixRestore() : fDrawState(NULL) {}
419 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
420 fDrawState = NULL;
421 this->set(ds, newMatrix);
422 }
423 AutoViewMatrixRestore(GrDrawState* ds) {
424 fDrawState = NULL;
425 this->set(ds);
426 }
427 ~AutoViewMatrixRestore() {
428 this->set(NULL, GrMatrix::I());
429 }
430 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
431 if (NULL != fDrawState) {
432 fDrawState->setViewMatrix(fSavedMatrix);
433 }
434 if (NULL != ds) {
435 fSavedMatrix = ds->getViewMatrix();
436 ds->setViewMatrix(newMatrix);
437 }
438 fDrawState = ds;
439 }
440 void set(GrDrawState* ds) {
441 if (NULL != fDrawState) {
442 fDrawState->setViewMatrix(fSavedMatrix);
443 }
444 if (NULL != ds) {
445 fSavedMatrix = ds->getViewMatrix();
446 }
447 fDrawState = ds;
448 }
449 private:
450 GrDrawState* fDrawState;
451 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000452 };
453
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000454 /// @}
455
456 ///////////////////////////////////////////////////////////////////////////
457 /// @name Render Target
458 ////
459
460 /**
461 * Sets the rendertarget used at the next drawing call
462 *
463 * @param target The render target to set.
464 */
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000465 void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000466
467 /**
468 * Retrieves the currently set rendertarget.
469 *
470 * @return The currently set render target.
471 */
472 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
473 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
474
475 class AutoRenderTargetRestore : public ::GrNoncopyable {
476 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000477 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000478 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
479 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000480 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000481 this->set(ds, newTarget);
482 }
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000483 ~AutoRenderTargetRestore() { this->set(NULL, NULL); }
484 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000485 if (NULL != fDrawState) {
486 fDrawState->setRenderTarget(fSavedTarget);
487 }
488 if (NULL != ds) {
489 fSavedTarget = ds->getRenderTarget();
490 ds->setRenderTarget(newTarget);
491 }
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000492 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000493 }
494 private:
495 GrDrawState* fDrawState;
496 GrRenderTarget* fSavedTarget;
497 };
498
499 /// @}
500
501 ///////////////////////////////////////////////////////////////////////////
502 /// @name Stencil
503 ////
504
505 /**
506 * Sets the stencil settings to use for the next draw.
507 * Changing the clip has the side-effect of possibly zeroing
508 * out the client settable stencil bits. So multipass algorithms
509 * using stencil should not change the clip between passes.
510 * @param settings the stencil settings to use.
511 */
512 void setStencil(const GrStencilSettings& settings) {
513 fStencilSettings = settings;
514 }
515
516 /**
517 * Shortcut to disable stencil testing and ops.
518 */
519 void disableStencil() {
520 fStencilSettings.setDisabled();
521 }
522
523 const GrStencilSettings& getStencil() const { return fStencilSettings; }
524
525 GrStencilSettings* stencil() { return &fStencilSettings; }
526
527 /// @}
528
529 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000530 /// @name Color Matrix
531 ////
532
533 /**
534 * Sets the color matrix to use for the next draw.
535 * @param matrix the 5x4 matrix to apply to the incoming color
536 */
537 void setColorMatrix(const float matrix[20]) {
538 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
539 }
540
541 const float* getColorMatrix() const { return fColorMatrix; }
542
543 /// @}
544
545 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000546 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000547 // Edge equations can be specified to perform antialiasing. Because the
548 // edges are specified as per-vertex data, vertices that are shared by
549 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000550 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000551 ////
552
553 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000554 * When specifying edges as vertex data this enum specifies what type of
555 * edges are in use. The edges are always 4 GrScalars in memory, even when
556 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000557 *
558 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
559 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000560 */
561 enum VertexEdgeType {
562 /* 1-pixel wide line
563 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
564 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000565 /* Quadratic specified by u^2-v canonical coords (only 2
566 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000567 being inside, positive outside. Edge specified in window space
568 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000569 kQuad_EdgeType,
570 /* Same as above but for hairline quadratics. Uses unsigned distance.
571 Coverage is min(0, 1-distance). */
572 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000573 /* Circle specified as center_x, center_y, outer_radius, inner_radius
574 all in window space (y-down). */
575 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000576
577 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000578 };
579
580 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000581 * Determines the interpretation per-vertex edge data when the
582 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
583 * are not specified the value of this setting has no effect.
584 */
585 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000586 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000587 fVertexEdgeType = type;
588 }
589
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000590 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000591
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000592 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000593
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000594 ///////////////////////////////////////////////////////////////////////////
595 /// @name State Flags
596 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000597
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000598 /**
599 * Flags that affect rendering. Controlled using enable/disableState(). All
600 * default to disabled.
601 */
602 enum StateBits {
603 /**
604 * Perform dithering. TODO: Re-evaluate whether we need this bit
605 */
606 kDither_StateBit = 0x01,
607 /**
608 * Perform HW anti-aliasing. This means either HW FSAA, if supported
609 * by the render target, or smooth-line rendering if a line primitive
610 * is drawn and line smoothing is supported by the 3D API.
611 */
612 kHWAntialias_StateBit = 0x02,
613 /**
614 * Draws will respect the clip, otherwise the clip is ignored.
615 */
616 kClip_StateBit = 0x04,
617 /**
618 * Disables writing to the color buffer. Useful when performing stencil
619 * operations.
620 */
621 kNoColorWrites_StateBit = 0x08,
622 /**
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000623 * Draws will apply the color matrix, otherwise the color matrix is
624 * ignored.
625 */
626 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000627
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000628 // Users of the class may add additional bits to the vector
629 kDummyStateBit,
630 kLastPublicStateBit = kDummyStateBit-1,
631 };
632
633 void resetStateFlags() {
634 fFlagBits = 0;
635 }
636
637 /**
638 * Enable render state settings.
639 *
640 * @param flags bitfield of StateBits specifing the states to enable
641 */
642 void enableState(uint32_t stateBits) {
643 fFlagBits |= stateBits;
644 }
645
646 /**
647 * Disable render state settings.
648 *
649 * @param flags bitfield of StateBits specifing the states to disable
650 */
651 void disableState(uint32_t stateBits) {
652 fFlagBits &= ~(stateBits);
653 }
654
655 bool isDitherState() const {
656 return 0 != (fFlagBits & kDither_StateBit);
657 }
658
659 bool isHWAntialiasState() const {
660 return 0 != (fFlagBits & kHWAntialias_StateBit);
661 }
662
663 bool isClipState() const {
664 return 0 != (fFlagBits & kClip_StateBit);
665 }
666
667 bool isColorWriteDisabled() const {
668 return 0 != (fFlagBits & kNoColorWrites_StateBit);
669 }
670
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000671 bool isStateFlagEnabled(uint32_t stateBit) const {
672 return 0 != (stateBit & fFlagBits);
673 }
674
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000675 /**
676 * Flags that do not affect rendering.
677 */
678 enum GrBehaviorBits {
679 /**
680 * Calls to setTexture will ref/unref the texture
681 */
682 kTexturesNeedRef_BehaviorBit = 0x01,
683 };
684
685 void enableBehavior(uint32_t behaviorBits) {
686 fBehaviorBits |= behaviorBits;
687 }
688
689 void disableBehavior(uint32_t behaviorBits) {
690 fBehaviorBits &= ~(behaviorBits);
691 }
692
693 bool isBehaviorEnabled(uint32_t behaviorBits) const {
694 return 0 != (behaviorBits & fBehaviorBits);
695 }
696
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000697 /// @}
698
699 ///////////////////////////////////////////////////////////////////////////
700 /// @name Face Culling
701 ////
702
703 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000704 kInvalid_DrawFace = -1,
705
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000706 kBoth_DrawFace,
707 kCCW_DrawFace,
708 kCW_DrawFace,
709 };
710
711 /**
712 * Controls whether clockwise, counterclockwise, or both faces are drawn.
713 * @param face the face(s) to draw.
714 */
715 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000716 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000717 fDrawFace = face;
718 }
719
720 /**
721 * Gets whether the target is drawing clockwise, counterclockwise,
722 * or both faces.
723 * @return the current draw face(s).
724 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000725 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000726
727 /// @}
728
729 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000730
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000731 // Most stages are usually not used, so conditionals here
732 // reduce the expected number of bytes touched by 50%.
733 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000734 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000735 return false;
736 }
737
738 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
739 return false;
740 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000741
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000742 // kTexturesNeedRef is an internal flag for altering the draw state's
743 // behavior rather than a property that will impact drawing - ignore it
744 // here
745 if ((fBehaviorBits & ~kTexturesNeedRef_BehaviorBit) !=
746 (s.fBehaviorBits & ~kTexturesNeedRef_BehaviorBit)) {
747 return false;
748 }
749
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000750 for (int i = 0; i < kNumStages; i++) {
751 if (fTextures[i] &&
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000752 this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000753 return false;
754 }
755 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000756 if (kColorMatrix_StateBit & s.fFlagBits) {
757 if (memcmp(fColorMatrix,
758 s.fColorMatrix,
759 sizeof(fColorMatrix))) {
760 return false;
761 }
762 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000763
764 return true;
765 }
766 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
767
768 // Most stages are usually not used, so conditionals here
769 // reduce the expected number of bytes touched by 50%.
770 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000771 memcpy(this->podStart(), s.podStart(), this->podSize());
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000772
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000773 fViewMatrix = s.fViewMatrix;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000774 fBehaviorBits = s.fBehaviorBits;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000775
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000776 for (int i = 0; i < kNumStages; i++) {
777 if (s.fTextures[i]) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000778 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000779 }
780 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000781 if (kColorMatrix_StateBit & s.fFlagBits) {
782 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
783 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000784
785 return *this;
786 }
787
788private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000789
790 const void* podStart() const {
791 return reinterpret_cast<const void*>(&fPodStartMarker);
792 }
793 void* podStart() {
794 return reinterpret_cast<void*>(&fPodStartMarker);
795 }
796 size_t memsetSize() const {
797 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
798 reinterpret_cast<size_t>(&fPodStartMarker) +
799 sizeof(fMemsetEndMarker);
800 }
801 size_t podSize() const {
802 // Can't use offsetof() with non-POD types, so stuck with pointer math.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000803 return reinterpret_cast<size_t>(&fPodEndMarker) -
804 reinterpret_cast<size_t>(&fPodStartMarker) +
805 sizeof(fPodEndMarker);
806 }
807
caryclark@google.comcf6285b2012-06-06 12:09:01 +0000808 static const StageMask kIllegalStageMaskBits = ~((1U << kNumStages)-1);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000809 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000810 union {
811 GrColor fBlendConstant;
812 GrColor fPodStartMarker;
813 };
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000814 GrTexture* fTextures[kNumStages];
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000815 GrColor fColorFilterColor;
816 uint32_t fFlagBits;
817 DrawFace fDrawFace;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000818 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000819 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000820 union {
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000821 GrRenderTarget* fRenderTarget;
822 GrRenderTarget* fMemsetEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000823 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000824 // @}
825
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000826 // @{ Initialized to values other than zero, but memcmp'ed in operator==
827 // and memcpy'ed in operator=.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000828 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000829 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000830 int fFirstCoverageStage;
831 SkXfermode::Mode fColorFilterMode;
832 GrBlendCoeff fSrcBlend;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000833 union {
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000834 GrBlendCoeff fDstBlend;
835 GrBlendCoeff fPodEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000836 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000837 // @}
838
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000839 uint32_t fBehaviorBits;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000840 GrMatrix fViewMatrix;
841
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000842 // This field must be last; it will not be copied or compared
843 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000844 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000845 // only compared if the color matrix enable flag is set
846 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000847
tomhudson@google.com93813632011-10-27 20:21:16 +0000848};
849
850#endif