blob: e77b63ad812bfc1b2aa161699c4bc4b6f3154317 [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
robertphillips@google.com972265d2012-06-13 18:49:30 +0000208 /**
209 * Release all the textures referred to by this draw state
210 */
211 void releaseTextures() {
212 for (int i = 0; i < kNumStages; ++i) {
213 this->setTexture(i, NULL);
214 }
215 }
216
217 class AutoTextureRelease : public ::GrNoncopyable {
218 public:
219 AutoTextureRelease(GrDrawState* ds) : fDrawState(ds) {}
220 ~AutoTextureRelease() {
221 if (NULL != fDrawState) {
222 fDrawState->releaseTextures();
223 }
224 }
225 private:
226 GrDrawState* fDrawState;
227 };
228
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000229 /// @}
230
231 ///////////////////////////////////////////////////////////////////////////
232 /// @name Samplers
233 ////
234
235 /**
236 * Returns the current sampler for a stage.
237 */
238 const GrSamplerState& getSampler(int stage) const {
239 GrAssert((unsigned)stage < kNumStages);
240 return fSamplerStates[stage];
241 }
242
243 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000244 * Writable pointer to a stage's sampler.
245 */
246 GrSamplerState* sampler(int stage) {
247 GrAssert((unsigned)stage < kNumStages);
248 return fSamplerStates + stage;
249 }
250
251 /**
252 * Preconcats the matrix of all samplers in the mask with the same matrix.
253 */
254 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
255 GrAssert(!(stageMask & kIllegalStageMaskBits));
256 for (int i = 0; i < kNumStages; ++i) {
257 if ((1 << i) & stageMask) {
258 fSamplerStates[i].preConcatMatrix(matrix);
259 }
260 }
261 }
262
263 /// @}
264
265 ///////////////////////////////////////////////////////////////////////////
266 /// @name Coverage / Color Stages
267 ////
268
269 /**
270 * A common pattern is to compute a color with the initial stages and then
271 * modulate that color by a coverage value in later stage(s) (AA, mask-
272 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
273 * computed based on the pre-coverage-modulated color. The division of
274 * stages between color-computing and coverage-computing is specified by
275 * this method. Initially this is kNumStages (all stages
276 * are color-computing).
277 */
278 void setFirstCoverageStage(int firstCoverageStage) {
279 GrAssert((unsigned)firstCoverageStage <= kNumStages);
280 fFirstCoverageStage = firstCoverageStage;
281 }
282
283 /**
284 * Gets the index of the first coverage-computing stage.
285 */
286 int getFirstCoverageStage() const {
287 return fFirstCoverageStage;
288 }
289
290 ///@}
291
292 ///////////////////////////////////////////////////////////////////////////
293 /// @name Blending
294 ////
295
296 /**
297 * Sets the blending function coeffecients.
298 *
299 * The blend function will be:
300 * D' = sat(S*srcCoef + D*dstCoef)
301 *
302 * where D is the existing destination color, S is the incoming source
303 * color, and D' is the new destination color that will be written. sat()
304 * is the saturation function.
305 *
306 * @param srcCoef coeffecient applied to the src color.
307 * @param dstCoef coeffecient applied to the dst color.
308 */
309 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
310 fSrcBlend = srcCoeff;
311 fDstBlend = dstCoeff;
312 #if GR_DEBUG
313 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000314 case kDC_GrBlendCoeff:
315 case kIDC_GrBlendCoeff:
316 case kDA_GrBlendCoeff:
317 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000318 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
319 "coverage stages.\n");
320 break;
321 default:
322 break;
323 }
324 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000325 case kSC_GrBlendCoeff:
326 case kISC_GrBlendCoeff:
327 case kSA_GrBlendCoeff:
328 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000329 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
330 "coverage stages.\n");
331 break;
332 default:
333 break;
334 }
335 #endif
336 }
337
338 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
339 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
340
341 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
342 GrBlendCoeff* dstBlendCoeff) const {
343 *srcBlendCoeff = fSrcBlend;
344 *dstBlendCoeff = fDstBlend;
345 }
346
347 /**
348 * Sets the blending function constant referenced by the following blending
349 * coeffecients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000350 * kConstC_GrBlendCoeff
351 * kIConstC_GrBlendCoeff
352 * kConstA_GrBlendCoeff
353 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000354 *
355 * @param constant the constant to set
356 */
357 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
358
359 /**
360 * Retrieves the last value set by setBlendConstant()
361 * @return the blending constant value
362 */
363 GrColor getBlendConstant() const { return fBlendConstant; }
364
365 /// @}
366
367 ///////////////////////////////////////////////////////////////////////////
368 /// @name View Matrix
369 ////
370
371 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000372 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000373 *
374 * In the post-view-matrix space the rectangle [0,w]x[0,h]
375 * fully covers the render target. (w and h are the width and height of the
376 * the rendertarget.)
377 */
378 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
379
380 /**
381 * Gets a writable pointer to the view matrix.
382 */
383 GrMatrix* viewMatrix() { return &fViewMatrix; }
384
385 /**
386 * Multiplies the current view matrix by a matrix
387 *
388 * After this call V' = V*m where V is the old view matrix,
389 * m is the parameter to this function, and V' is the new view matrix.
390 * (We consider positions to be column vectors so position vector p is
391 * transformed by matrix X as p' = X*p.)
392 *
393 * @param m the matrix used to modify the view matrix.
394 */
395 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
396
397 /**
398 * Multiplies the current view matrix by a matrix
399 *
400 * After this call V' = m*V where V is the old view matrix,
401 * m is the parameter to this function, and V' is the new view matrix.
402 * (We consider positions to be column vectors so position vector p is
403 * transformed by matrix X as p' = X*p.)
404 *
405 * @param m the matrix used to modify the view matrix.
406 */
407 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
408
409 /**
410 * Retrieves the current view matrix
411 * @return the current view matrix.
412 */
413 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
414
415 /**
416 * Retrieves the inverse of the current view matrix.
417 *
418 * If the current view matrix is invertible, return true, and if matrix
419 * is non-null, copy the inverse into it. If the current view matrix is
420 * non-invertible, return false and ignore the matrix parameter.
421 *
422 * @param matrix if not null, will receive a copy of the current inverse.
423 */
424 bool getViewInverse(GrMatrix* matrix) const {
425 // TODO: determine whether we really need to leave matrix unmodified
426 // at call sites when inversion fails.
427 GrMatrix inverse;
428 if (fViewMatrix.invert(&inverse)) {
429 if (matrix) {
430 *matrix = inverse;
431 }
432 return true;
433 }
434 return false;
435 }
436
437 class AutoViewMatrixRestore : public ::GrNoncopyable {
438 public:
439 AutoViewMatrixRestore() : fDrawState(NULL) {}
440 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
441 fDrawState = NULL;
442 this->set(ds, newMatrix);
443 }
444 AutoViewMatrixRestore(GrDrawState* ds) {
445 fDrawState = NULL;
446 this->set(ds);
447 }
448 ~AutoViewMatrixRestore() {
449 this->set(NULL, GrMatrix::I());
450 }
451 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
452 if (NULL != fDrawState) {
453 fDrawState->setViewMatrix(fSavedMatrix);
454 }
455 if (NULL != ds) {
456 fSavedMatrix = ds->getViewMatrix();
457 ds->setViewMatrix(newMatrix);
458 }
459 fDrawState = ds;
460 }
461 void set(GrDrawState* ds) {
462 if (NULL != fDrawState) {
463 fDrawState->setViewMatrix(fSavedMatrix);
464 }
465 if (NULL != ds) {
466 fSavedMatrix = ds->getViewMatrix();
467 }
468 fDrawState = ds;
469 }
470 private:
471 GrDrawState* fDrawState;
472 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000473 };
474
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000475 /// @}
476
477 ///////////////////////////////////////////////////////////////////////////
478 /// @name Render Target
479 ////
480
481 /**
482 * Sets the rendertarget used at the next drawing call
483 *
484 * @param target The render target to set.
485 */
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000486 void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000487
488 /**
489 * Retrieves the currently set rendertarget.
490 *
491 * @return The currently set render target.
492 */
493 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
494 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
495
496 class AutoRenderTargetRestore : public ::GrNoncopyable {
497 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000498 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000499 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
500 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000501 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000502 this->set(ds, newTarget);
503 }
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000504 ~AutoRenderTargetRestore() { this->set(NULL, NULL); }
505 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000506 if (NULL != fDrawState) {
507 fDrawState->setRenderTarget(fSavedTarget);
508 }
509 if (NULL != ds) {
510 fSavedTarget = ds->getRenderTarget();
511 ds->setRenderTarget(newTarget);
512 }
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000513 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000514 }
515 private:
516 GrDrawState* fDrawState;
517 GrRenderTarget* fSavedTarget;
518 };
519
520 /// @}
521
522 ///////////////////////////////////////////////////////////////////////////
523 /// @name Stencil
524 ////
525
526 /**
527 * Sets the stencil settings to use for the next draw.
528 * Changing the clip has the side-effect of possibly zeroing
529 * out the client settable stencil bits. So multipass algorithms
530 * using stencil should not change the clip between passes.
531 * @param settings the stencil settings to use.
532 */
533 void setStencil(const GrStencilSettings& settings) {
534 fStencilSettings = settings;
535 }
536
537 /**
538 * Shortcut to disable stencil testing and ops.
539 */
540 void disableStencil() {
541 fStencilSettings.setDisabled();
542 }
543
544 const GrStencilSettings& getStencil() const { return fStencilSettings; }
545
546 GrStencilSettings* stencil() { return &fStencilSettings; }
547
548 /// @}
549
550 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000551 /// @name Color Matrix
552 ////
553
554 /**
555 * Sets the color matrix to use for the next draw.
556 * @param matrix the 5x4 matrix to apply to the incoming color
557 */
558 void setColorMatrix(const float matrix[20]) {
559 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
560 }
561
562 const float* getColorMatrix() const { return fColorMatrix; }
563
564 /// @}
565
566 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000567 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000568 // Edge equations can be specified to perform antialiasing. Because the
569 // edges are specified as per-vertex data, vertices that are shared by
570 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000571 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000572 ////
573
574 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000575 * When specifying edges as vertex data this enum specifies what type of
576 * edges are in use. The edges are always 4 GrScalars in memory, even when
577 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000578 *
579 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
580 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000581 */
582 enum VertexEdgeType {
583 /* 1-pixel wide line
584 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
585 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000586 /* Quadratic specified by u^2-v canonical coords (only 2
587 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000588 being inside, positive outside. Edge specified in window space
589 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000590 kQuad_EdgeType,
591 /* Same as above but for hairline quadratics. Uses unsigned distance.
592 Coverage is min(0, 1-distance). */
593 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000594 /* Circle specified as center_x, center_y, outer_radius, inner_radius
595 all in window space (y-down). */
596 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000597
598 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000599 };
600
601 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000602 * Determines the interpretation per-vertex edge data when the
603 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
604 * are not specified the value of this setting has no effect.
605 */
606 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000607 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000608 fVertexEdgeType = type;
609 }
610
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000611 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000612
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000613 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000614
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000615 ///////////////////////////////////////////////////////////////////////////
616 /// @name State Flags
617 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000618
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000619 /**
620 * Flags that affect rendering. Controlled using enable/disableState(). All
621 * default to disabled.
622 */
623 enum StateBits {
624 /**
625 * Perform dithering. TODO: Re-evaluate whether we need this bit
626 */
627 kDither_StateBit = 0x01,
628 /**
629 * Perform HW anti-aliasing. This means either HW FSAA, if supported
630 * by the render target, or smooth-line rendering if a line primitive
631 * is drawn and line smoothing is supported by the 3D API.
632 */
633 kHWAntialias_StateBit = 0x02,
634 /**
635 * Draws will respect the clip, otherwise the clip is ignored.
636 */
637 kClip_StateBit = 0x04,
638 /**
639 * Disables writing to the color buffer. Useful when performing stencil
640 * operations.
641 */
642 kNoColorWrites_StateBit = 0x08,
643 /**
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000644 * Draws will apply the color matrix, otherwise the color matrix is
645 * ignored.
646 */
647 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000648
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000649 // Users of the class may add additional bits to the vector
650 kDummyStateBit,
651 kLastPublicStateBit = kDummyStateBit-1,
652 };
653
654 void resetStateFlags() {
655 fFlagBits = 0;
656 }
657
658 /**
659 * Enable render state settings.
660 *
661 * @param flags bitfield of StateBits specifing the states to enable
662 */
663 void enableState(uint32_t stateBits) {
664 fFlagBits |= stateBits;
665 }
666
667 /**
668 * Disable render state settings.
669 *
670 * @param flags bitfield of StateBits specifing the states to disable
671 */
672 void disableState(uint32_t stateBits) {
673 fFlagBits &= ~(stateBits);
674 }
675
676 bool isDitherState() const {
677 return 0 != (fFlagBits & kDither_StateBit);
678 }
679
680 bool isHWAntialiasState() const {
681 return 0 != (fFlagBits & kHWAntialias_StateBit);
682 }
683
684 bool isClipState() const {
685 return 0 != (fFlagBits & kClip_StateBit);
686 }
687
688 bool isColorWriteDisabled() const {
689 return 0 != (fFlagBits & kNoColorWrites_StateBit);
690 }
691
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000692 bool isStateFlagEnabled(uint32_t stateBit) const {
693 return 0 != (stateBit & fFlagBits);
694 }
695
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000696 /**
697 * Flags that do not affect rendering.
698 */
699 enum GrBehaviorBits {
700 /**
701 * Calls to setTexture will ref/unref the texture
702 */
703 kTexturesNeedRef_BehaviorBit = 0x01,
704 };
705
706 void enableBehavior(uint32_t behaviorBits) {
707 fBehaviorBits |= behaviorBits;
708 }
709
710 void disableBehavior(uint32_t behaviorBits) {
711 fBehaviorBits &= ~(behaviorBits);
712 }
713
714 bool isBehaviorEnabled(uint32_t behaviorBits) const {
715 return 0 != (behaviorBits & fBehaviorBits);
716 }
717
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000718 /// @}
719
720 ///////////////////////////////////////////////////////////////////////////
721 /// @name Face Culling
722 ////
723
724 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000725 kInvalid_DrawFace = -1,
726
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000727 kBoth_DrawFace,
728 kCCW_DrawFace,
729 kCW_DrawFace,
730 };
731
732 /**
733 * Controls whether clockwise, counterclockwise, or both faces are drawn.
734 * @param face the face(s) to draw.
735 */
736 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000737 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000738 fDrawFace = face;
739 }
740
741 /**
742 * Gets whether the target is drawing clockwise, counterclockwise,
743 * or both faces.
744 * @return the current draw face(s).
745 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000746 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000747
748 /// @}
749
750 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000751
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000752 // Most stages are usually not used, so conditionals here
753 // reduce the expected number of bytes touched by 50%.
754 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000755 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000756 return false;
757 }
758
759 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
760 return false;
761 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000762
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000763 // kTexturesNeedRef is an internal flag for altering the draw state's
764 // behavior rather than a property that will impact drawing - ignore it
765 // here
766 if ((fBehaviorBits & ~kTexturesNeedRef_BehaviorBit) !=
767 (s.fBehaviorBits & ~kTexturesNeedRef_BehaviorBit)) {
768 return false;
769 }
770
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000771 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;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000795 fBehaviorBits = s.fBehaviorBits;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000796
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000797 for (int i = 0; i < kNumStages; i++) {
798 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 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000802 if (kColorMatrix_StateBit & s.fFlagBits) {
803 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
804 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000805
806 return *this;
807 }
808
809private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000810
811 const void* podStart() const {
812 return reinterpret_cast<const void*>(&fPodStartMarker);
813 }
814 void* podStart() {
815 return reinterpret_cast<void*>(&fPodStartMarker);
816 }
817 size_t memsetSize() const {
818 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
819 reinterpret_cast<size_t>(&fPodStartMarker) +
820 sizeof(fMemsetEndMarker);
821 }
822 size_t podSize() const {
823 // Can't use offsetof() with non-POD types, so stuck with pointer math.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000824 return reinterpret_cast<size_t>(&fPodEndMarker) -
825 reinterpret_cast<size_t>(&fPodStartMarker) +
826 sizeof(fPodEndMarker);
827 }
828
caryclark@google.comcf6285b2012-06-06 12:09:01 +0000829 static const StageMask kIllegalStageMaskBits = ~((1U << kNumStages)-1);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000830 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000831 union {
832 GrColor fBlendConstant;
833 GrColor fPodStartMarker;
834 };
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000835 GrTexture* fTextures[kNumStages];
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000836 GrColor fColorFilterColor;
837 uint32_t fFlagBits;
838 DrawFace fDrawFace;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000839 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000840 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000841 union {
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000842 GrRenderTarget* fRenderTarget;
843 GrRenderTarget* fMemsetEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000844 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000845 // @}
846
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000847 // @{ Initialized to values other than zero, but memcmp'ed in operator==
848 // and memcpy'ed in operator=.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000849 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000850 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000851 int fFirstCoverageStage;
852 SkXfermode::Mode fColorFilterMode;
853 GrBlendCoeff fSrcBlend;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000854 union {
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000855 GrBlendCoeff fDstBlend;
856 GrBlendCoeff fPodEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000857 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000858 // @}
859
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000860 uint32_t fBehaviorBits;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000861 GrMatrix fViewMatrix;
862
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000863 // This field must be last; it will not be copied or compared
864 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000865 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000866 // only compared if the color matrix enable flag is set
867 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000868
tomhudson@google.com93813632011-10-27 20:21:16 +0000869};
870
871#endif