blob: e56b98fcd1a2edcef2b5b70a69101b5a676f8f9f [file] [log] [blame]
tomhudson@google.com93813632011-10-27 20:21:16 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrDrawState_DEFINED
9#define GrDrawState_DEFINED
10
11#include "GrColor.h"
12#include "GrMatrix.h"
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000013#include "GrNoncopyable.h"
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000014#include "GrRefCnt.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000015#include "GrSamplerState.h"
16#include "GrStencil.h"
17
18#include "SkXfermode.h"
19
robertphillips@google.comc077d1e2012-05-28 14:10:15 +000020class GrRenderTarget;
21class GrTexture;
tomhudson@google.com93813632011-10-27 20:21:16 +000022
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000023class GrDrawState : public GrRefCnt {
tomhudson@google.com93813632011-10-27 20:21:16 +000024
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000025public:
tomhudson@google.com93813632011-10-27 20:21:16 +000026 /**
27 * Number of texture stages. Each stage takes as input a color and
28 * 2D texture coordinates. The color input to the first enabled stage is the
29 * per-vertex color or the constant color (setColor/setAlpha) if there are
30 * no per-vertex colors. For subsequent stages the input color is the output
31 * color from the previous enabled stage. The output color of each stage is
32 * the input color modulated with the result of a texture lookup. Texture
33 * lookups are specified by a texture a sampler (setSamplerState). Texture
34 * coordinates for each stage come from the vertices based on a
35 * GrVertexLayout bitfield. The output fragment color is the output color of
36 * the last enabled stage. The presence or absence of texture coordinates
37 * for each stage in the vertex layout indicates whether a stage is enabled
38 * or not.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000039 *
40 * Stages 0 through GrPaint::kTotalStages-1 are reserved for setting up
41 * the draw (i.e., textures and filter masks). Stages GrPaint::kTotalStages
42 * through kNumStages-1 are earmarked for use by GrTextContext and
43 * GrPathRenderer-derived classes.
tomhudson@google.com93813632011-10-27 20:21:16 +000044 */
45 enum {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000046 kNumStages = 4,
tomhudson@google.com93813632011-10-27 20:21:16 +000047 kMaxTexCoords = kNumStages
48 };
49
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000050 /**
51 * Bitfield used to indicate a set of stages.
52 */
53 typedef uint32_t StageMask;
54 GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
55
robertphillips@google.comc077d1e2012-05-28 14:10:15 +000056 GrDrawState() {
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000057 this->reset();
58 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000059
robertphillips@google.comc077d1e2012-05-28 14:10:15 +000060 GrDrawState(const GrDrawState& state) {
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000061 *this = state;
62 }
63
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000064 /**
65 * Resets to the default state. Sampler states will not be modified.
66 */
67 void reset() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000068 // make sure any pad is zero for memcmp
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000069 // all GrDrawState members should default to something valid by the
70 // the memset except those initialized individually below. There should
71 // be no padding between the individually initialized members.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000072 memset(this->podStart(), 0, this->memsetSize());
73
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000074 // pedantic assertion that our ptrs will
75 // be NULL (0 ptr is mem addr 0)
76 GrAssert((intptr_t)(void*)NULL == 0LL);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000077 GR_STATIC_ASSERT(0 == kBoth_DrawFace);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000078 GrAssert(fStencilSettings.isDisabled());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000079
80 // memset exceptions
81 fColor = 0xffffffff;
bsalomon@google.com2401ae82012-01-17 21:03:05 +000082 fCoverage = 0xffffffff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000083 fFirstCoverageStage = kNumStages;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000084 fColorFilterMode = SkXfermode::kDst_Mode;
bsalomon@google.com47059542012-06-06 20:51:20 +000085 fSrcBlend = kOne_GrBlendCoeff;
86 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000087 fViewMatrix.reset();
robertphillips@google.comc077d1e2012-05-28 14:10:15 +000088 fBehaviorBits = 0;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000089
90 // ensure values that will be memcmp'ed in == but not memset in reset()
91 // are tightly packed
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000092 GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) +
bsalomon@google.com2401ae82012-01-17 21:03:05 +000093 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
robertphillips@google.comc077d1e2012-05-28 14:10:15 +000094 sizeof(fSrcBlend) + sizeof(fDstBlend) ==
95 this->podSize());
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000096 }
97
98 ///////////////////////////////////////////////////////////////////////////
99 /// @name Color
100 ////
101
102 /**
103 * Sets color for next draw to a premultiplied-alpha color.
104 *
105 * @param color the color to set.
106 */
107 void setColor(GrColor color) { fColor = color; }
108
109 GrColor getColor() const { return fColor; }
110
111 /**
112 * Sets the color to be used for the next draw to be
113 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
114 *
115 * @param alpha The alpha value to set as the color.
116 */
117 void setAlpha(uint8_t a) {
118 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
119 }
120
121 /**
122 * Add a color filter that can be represented by a color and a mode. Applied
123 * after color-computing texture stages.
124 */
125 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
126 fColorFilterColor = c;
127 fColorFilterMode = mode;
128 }
129
130 GrColor getColorFilterColor() const { return fColorFilterColor; }
131 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
132
133 /// @}
134
135 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000136 /// @name Coverage
137 ////
138
139 /**
140 * Sets a constant fractional coverage to be applied to the draw. The
141 * initial value (after construction or reset()) is 0xff. The constant
142 * coverage is ignored when per-vertex coverage is provided.
143 */
144 void setCoverage(uint8_t coverage) {
145 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
146 }
147
148 /**
149 * Version of above that specifies 4 channel per-vertex color. The value
150 * should be premultiplied.
151 */
152 void setCoverage4(GrColor coverage) {
153 fCoverage = coverage;
154 }
155
156 GrColor getCoverage() const {
157 return fCoverage;
158 }
159
160 /// @}
161
162 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000163 /// @name Textures
164 ////
165
166 /**
167 * Sets the texture used at the next drawing call
168 *
169 * @param stage The texture stage for which the texture will be set
170 *
171 * @param texture The texture to set. Can be NULL though there is no
172 * advantage to settings a NULL texture if doing non-textured drawing
173 */
174 void setTexture(int stage, GrTexture* texture) {
175 GrAssert((unsigned)stage < kNumStages);
robertphillips@google.com1942c052012-05-03 17:58:27 +0000176
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000177 if (isBehaviorEnabled(kTexturesNeedRef_BehaviorBit)) {
178 // If we don't clear out the current texture before unreffing
179 // it we can get into an infinite loop as the GrGLTexture's
180 // onRelease method recursively calls setTexture
181 GrTexture* temp = fTextures[stage];
182 fTextures[stage] = NULL;
robertphillips@google.com1942c052012-05-03 17:58:27 +0000183
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000184 SkSafeRef(texture);
185 SkSafeUnref(temp);
186 }
robertphillips@google.com1942c052012-05-03 17:58:27 +0000187
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000188 fTextures[stage] = texture;
189 }
190
191 /**
192 * Retrieves the currently set texture.
193 *
194 * @return The currently set texture. The return value will be NULL if no
195 * texture has been set, NULL was most recently passed to
196 * setTexture, or the last setTexture was destroyed.
197 */
198 const GrTexture* getTexture(int stage) const {
199 GrAssert((unsigned)stage < kNumStages);
200 return fTextures[stage];
201 }
202 GrTexture* getTexture(int stage) {
203 GrAssert((unsigned)stage < kNumStages);
204 return fTextures[stage];
205 }
206
207 /// @}
208
209 ///////////////////////////////////////////////////////////////////////////
210 /// @name Samplers
211 ////
212
213 /**
214 * Returns the current sampler for a stage.
215 */
216 const GrSamplerState& getSampler(int stage) const {
217 GrAssert((unsigned)stage < kNumStages);
218 return fSamplerStates[stage];
219 }
220
221 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000222 * Writable pointer to a stage's sampler.
223 */
224 GrSamplerState* sampler(int stage) {
225 GrAssert((unsigned)stage < kNumStages);
226 return fSamplerStates + stage;
227 }
228
229 /**
230 * Preconcats the matrix of all samplers in the mask with the same matrix.
231 */
232 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
233 GrAssert(!(stageMask & kIllegalStageMaskBits));
234 for (int i = 0; i < kNumStages; ++i) {
235 if ((1 << i) & stageMask) {
236 fSamplerStates[i].preConcatMatrix(matrix);
237 }
238 }
239 }
240
241 /// @}
242
243 ///////////////////////////////////////////////////////////////////////////
244 /// @name Coverage / Color Stages
245 ////
246
247 /**
248 * A common pattern is to compute a color with the initial stages and then
249 * modulate that color by a coverage value in later stage(s) (AA, mask-
250 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
251 * computed based on the pre-coverage-modulated color. The division of
252 * stages between color-computing and coverage-computing is specified by
253 * this method. Initially this is kNumStages (all stages
254 * are color-computing).
255 */
256 void setFirstCoverageStage(int firstCoverageStage) {
257 GrAssert((unsigned)firstCoverageStage <= kNumStages);
258 fFirstCoverageStage = firstCoverageStage;
259 }
260
261 /**
262 * Gets the index of the first coverage-computing stage.
263 */
264 int getFirstCoverageStage() const {
265 return fFirstCoverageStage;
266 }
267
268 ///@}
269
270 ///////////////////////////////////////////////////////////////////////////
271 /// @name Blending
272 ////
273
274 /**
275 * Sets the blending function coeffecients.
276 *
277 * The blend function will be:
278 * D' = sat(S*srcCoef + D*dstCoef)
279 *
280 * where D is the existing destination color, S is the incoming source
281 * color, and D' is the new destination color that will be written. sat()
282 * is the saturation function.
283 *
284 * @param srcCoef coeffecient applied to the src color.
285 * @param dstCoef coeffecient applied to the dst color.
286 */
287 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
288 fSrcBlend = srcCoeff;
289 fDstBlend = dstCoeff;
290 #if GR_DEBUG
291 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000292 case kDC_GrBlendCoeff:
293 case kIDC_GrBlendCoeff:
294 case kDA_GrBlendCoeff:
295 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000296 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
297 "coverage stages.\n");
298 break;
299 default:
300 break;
301 }
302 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000303 case kSC_GrBlendCoeff:
304 case kISC_GrBlendCoeff:
305 case kSA_GrBlendCoeff:
306 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000307 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
308 "coverage stages.\n");
309 break;
310 default:
311 break;
312 }
313 #endif
314 }
315
316 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
317 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
318
319 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
320 GrBlendCoeff* dstBlendCoeff) const {
321 *srcBlendCoeff = fSrcBlend;
322 *dstBlendCoeff = fDstBlend;
323 }
324
325 /**
326 * Sets the blending function constant referenced by the following blending
327 * coeffecients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000328 * kConstC_GrBlendCoeff
329 * kIConstC_GrBlendCoeff
330 * kConstA_GrBlendCoeff
331 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000332 *
333 * @param constant the constant to set
334 */
335 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
336
337 /**
338 * Retrieves the last value set by setBlendConstant()
339 * @return the blending constant value
340 */
341 GrColor getBlendConstant() const { return fBlendConstant; }
342
343 /// @}
344
345 ///////////////////////////////////////////////////////////////////////////
346 /// @name View Matrix
347 ////
348
349 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000350 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000351 *
352 * In the post-view-matrix space the rectangle [0,w]x[0,h]
353 * fully covers the render target. (w and h are the width and height of the
354 * the rendertarget.)
355 */
356 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
357
358 /**
359 * Gets a writable pointer to the view matrix.
360 */
361 GrMatrix* viewMatrix() { return &fViewMatrix; }
362
363 /**
364 * Multiplies the current view matrix by a matrix
365 *
366 * After this call V' = V*m where V is the old view matrix,
367 * m is the parameter to this function, and V' is the new view matrix.
368 * (We consider positions to be column vectors so position vector p is
369 * transformed by matrix X as p' = X*p.)
370 *
371 * @param m the matrix used to modify the view matrix.
372 */
373 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
374
375 /**
376 * Multiplies the current view matrix by a matrix
377 *
378 * After this call V' = m*V where V is the old view matrix,
379 * m is the parameter to this function, and V' is the new view matrix.
380 * (We consider positions to be column vectors so position vector p is
381 * transformed by matrix X as p' = X*p.)
382 *
383 * @param m the matrix used to modify the view matrix.
384 */
385 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
386
387 /**
388 * Retrieves the current view matrix
389 * @return the current view matrix.
390 */
391 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
392
393 /**
394 * Retrieves the inverse of the current view matrix.
395 *
396 * If the current view matrix is invertible, return true, and if matrix
397 * is non-null, copy the inverse into it. If the current view matrix is
398 * non-invertible, return false and ignore the matrix parameter.
399 *
400 * @param matrix if not null, will receive a copy of the current inverse.
401 */
402 bool getViewInverse(GrMatrix* matrix) const {
403 // TODO: determine whether we really need to leave matrix unmodified
404 // at call sites when inversion fails.
405 GrMatrix inverse;
406 if (fViewMatrix.invert(&inverse)) {
407 if (matrix) {
408 *matrix = inverse;
409 }
410 return true;
411 }
412 return false;
413 }
414
415 class AutoViewMatrixRestore : public ::GrNoncopyable {
416 public:
417 AutoViewMatrixRestore() : fDrawState(NULL) {}
418 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
419 fDrawState = NULL;
420 this->set(ds, newMatrix);
421 }
422 AutoViewMatrixRestore(GrDrawState* ds) {
423 fDrawState = NULL;
424 this->set(ds);
425 }
426 ~AutoViewMatrixRestore() {
427 this->set(NULL, GrMatrix::I());
428 }
429 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
430 if (NULL != fDrawState) {
431 fDrawState->setViewMatrix(fSavedMatrix);
432 }
433 if (NULL != ds) {
434 fSavedMatrix = ds->getViewMatrix();
435 ds->setViewMatrix(newMatrix);
436 }
437 fDrawState = ds;
438 }
439 void set(GrDrawState* ds) {
440 if (NULL != fDrawState) {
441 fDrawState->setViewMatrix(fSavedMatrix);
442 }
443 if (NULL != ds) {
444 fSavedMatrix = ds->getViewMatrix();
445 }
446 fDrawState = ds;
447 }
448 private:
449 GrDrawState* fDrawState;
450 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000451 };
452
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000453 /// @}
454
455 ///////////////////////////////////////////////////////////////////////////
456 /// @name Render Target
457 ////
458
459 /**
460 * Sets the rendertarget used at the next drawing call
461 *
462 * @param target The render target to set.
463 */
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000464 void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000465
466 /**
467 * Retrieves the currently set rendertarget.
468 *
469 * @return The currently set render target.
470 */
471 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
472 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
473
474 class AutoRenderTargetRestore : public ::GrNoncopyable {
475 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000476 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000477 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
478 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000479 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000480 this->set(ds, newTarget);
481 }
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000482 ~AutoRenderTargetRestore() { this->set(NULL, NULL); }
483 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000484 if (NULL != fDrawState) {
485 fDrawState->setRenderTarget(fSavedTarget);
486 }
487 if (NULL != ds) {
488 fSavedTarget = ds->getRenderTarget();
489 ds->setRenderTarget(newTarget);
490 }
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000491 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000492 }
493 private:
494 GrDrawState* fDrawState;
495 GrRenderTarget* fSavedTarget;
496 };
497
498 /// @}
499
500 ///////////////////////////////////////////////////////////////////////////
501 /// @name Stencil
502 ////
503
504 /**
505 * Sets the stencil settings to use for the next draw.
506 * Changing the clip has the side-effect of possibly zeroing
507 * out the client settable stencil bits. So multipass algorithms
508 * using stencil should not change the clip between passes.
509 * @param settings the stencil settings to use.
510 */
511 void setStencil(const GrStencilSettings& settings) {
512 fStencilSettings = settings;
513 }
514
515 /**
516 * Shortcut to disable stencil testing and ops.
517 */
518 void disableStencil() {
519 fStencilSettings.setDisabled();
520 }
521
522 const GrStencilSettings& getStencil() const { return fStencilSettings; }
523
524 GrStencilSettings* stencil() { return &fStencilSettings; }
525
526 /// @}
527
528 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000529 /// @name Color Matrix
530 ////
531
532 /**
533 * Sets the color matrix to use for the next draw.
534 * @param matrix the 5x4 matrix to apply to the incoming color
535 */
536 void setColorMatrix(const float matrix[20]) {
537 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
538 }
539
540 const float* getColorMatrix() const { return fColorMatrix; }
541
542 /// @}
543
544 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000545 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000546 // Edge equations can be specified to perform antialiasing. Because the
547 // edges are specified as per-vertex data, vertices that are shared by
548 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000549 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000550 ////
551
552 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000553 * When specifying edges as vertex data this enum specifies what type of
554 * edges are in use. The edges are always 4 GrScalars in memory, even when
555 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000556 *
557 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
558 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000559 */
560 enum VertexEdgeType {
561 /* 1-pixel wide line
562 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
563 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000564 /* Quadratic specified by u^2-v canonical coords (only 2
565 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000566 being inside, positive outside. Edge specified in window space
567 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000568 kQuad_EdgeType,
569 /* Same as above but for hairline quadratics. Uses unsigned distance.
570 Coverage is min(0, 1-distance). */
571 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000572 /* Circle specified as center_x, center_y, outer_radius, inner_radius
573 all in window space (y-down). */
574 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000575
576 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000577 };
578
579 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000580 * Determines the interpretation per-vertex edge data when the
581 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
582 * are not specified the value of this setting has no effect.
583 */
584 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000585 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000586 fVertexEdgeType = type;
587 }
588
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000589 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000590
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000591 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000592
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000593 ///////////////////////////////////////////////////////////////////////////
594 /// @name State Flags
595 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000596
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000597 /**
598 * Flags that affect rendering. Controlled using enable/disableState(). All
599 * default to disabled.
600 */
601 enum StateBits {
602 /**
603 * Perform dithering. TODO: Re-evaluate whether we need this bit
604 */
605 kDither_StateBit = 0x01,
606 /**
607 * Perform HW anti-aliasing. This means either HW FSAA, if supported
608 * by the render target, or smooth-line rendering if a line primitive
609 * is drawn and line smoothing is supported by the 3D API.
610 */
611 kHWAntialias_StateBit = 0x02,
612 /**
613 * Draws will respect the clip, otherwise the clip is ignored.
614 */
615 kClip_StateBit = 0x04,
616 /**
617 * Disables writing to the color buffer. Useful when performing stencil
618 * operations.
619 */
620 kNoColorWrites_StateBit = 0x08,
621 /**
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000622 * Draws will apply the color matrix, otherwise the color matrix is
623 * ignored.
624 */
625 kColorMatrix_StateBit = 0x20,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000626
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000627 // Users of the class may add additional bits to the vector
628 kDummyStateBit,
629 kLastPublicStateBit = kDummyStateBit-1,
630 };
631
632 void resetStateFlags() {
633 fFlagBits = 0;
634 }
635
636 /**
637 * Enable render state settings.
638 *
639 * @param flags bitfield of StateBits specifing the states to enable
640 */
641 void enableState(uint32_t stateBits) {
642 fFlagBits |= stateBits;
643 }
644
645 /**
646 * Disable render state settings.
647 *
648 * @param flags bitfield of StateBits specifing the states to disable
649 */
650 void disableState(uint32_t stateBits) {
651 fFlagBits &= ~(stateBits);
652 }
653
654 bool isDitherState() const {
655 return 0 != (fFlagBits & kDither_StateBit);
656 }
657
658 bool isHWAntialiasState() const {
659 return 0 != (fFlagBits & kHWAntialias_StateBit);
660 }
661
662 bool isClipState() const {
663 return 0 != (fFlagBits & kClip_StateBit);
664 }
665
666 bool isColorWriteDisabled() const {
667 return 0 != (fFlagBits & kNoColorWrites_StateBit);
668 }
669
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000670 bool isStateFlagEnabled(uint32_t stateBit) const {
671 return 0 != (stateBit & fFlagBits);
672 }
673
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000674 /**
675 * Flags that do not affect rendering.
676 */
677 enum GrBehaviorBits {
678 /**
679 * Calls to setTexture will ref/unref the texture
680 */
681 kTexturesNeedRef_BehaviorBit = 0x01,
682 };
683
684 void enableBehavior(uint32_t behaviorBits) {
685 fBehaviorBits |= behaviorBits;
686 }
687
688 void disableBehavior(uint32_t behaviorBits) {
689 fBehaviorBits &= ~(behaviorBits);
690 }
691
692 bool isBehaviorEnabled(uint32_t behaviorBits) const {
693 return 0 != (behaviorBits & fBehaviorBits);
694 }
695
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000696 /// @}
697
698 ///////////////////////////////////////////////////////////////////////////
699 /// @name Face Culling
700 ////
701
702 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000703 kInvalid_DrawFace = -1,
704
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000705 kBoth_DrawFace,
706 kCCW_DrawFace,
707 kCW_DrawFace,
708 };
709
710 /**
711 * Controls whether clockwise, counterclockwise, or both faces are drawn.
712 * @param face the face(s) to draw.
713 */
714 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000715 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000716 fDrawFace = face;
717 }
718
719 /**
720 * Gets whether the target is drawing clockwise, counterclockwise,
721 * or both faces.
722 * @return the current draw face(s).
723 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000724 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000725
726 /// @}
727
728 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000729
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000730 // Most stages are usually not used, so conditionals here
731 // reduce the expected number of bytes touched by 50%.
732 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000733 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000734 return false;
735 }
736
737 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
738 return false;
739 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000740
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000741 // kTexturesNeedRef is an internal flag for altering the draw state's
742 // behavior rather than a property that will impact drawing - ignore it
743 // here
744 if ((fBehaviorBits & ~kTexturesNeedRef_BehaviorBit) !=
745 (s.fBehaviorBits & ~kTexturesNeedRef_BehaviorBit)) {
746 return false;
747 }
748
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000749 for (int i = 0; i < kNumStages; i++) {
750 if (fTextures[i] &&
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000751 this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000752 return false;
753 }
754 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000755 if (kColorMatrix_StateBit & s.fFlagBits) {
756 if (memcmp(fColorMatrix,
757 s.fColorMatrix,
758 sizeof(fColorMatrix))) {
759 return false;
760 }
761 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000762
763 return true;
764 }
765 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
766
767 // Most stages are usually not used, so conditionals here
768 // reduce the expected number of bytes touched by 50%.
769 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000770 memcpy(this->podStart(), s.podStart(), this->podSize());
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000771
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000772 fViewMatrix = s.fViewMatrix;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000773 fBehaviorBits = s.fBehaviorBits;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000774
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000775 for (int i = 0; i < kNumStages; i++) {
776 if (s.fTextures[i]) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000777 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000778 }
779 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000780 if (kColorMatrix_StateBit & s.fFlagBits) {
781 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
782 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000783
784 return *this;
785 }
786
787private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000788
789 const void* podStart() const {
790 return reinterpret_cast<const void*>(&fPodStartMarker);
791 }
792 void* podStart() {
793 return reinterpret_cast<void*>(&fPodStartMarker);
794 }
795 size_t memsetSize() const {
796 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
797 reinterpret_cast<size_t>(&fPodStartMarker) +
798 sizeof(fMemsetEndMarker);
799 }
800 size_t podSize() const {
801 // Can't use offsetof() with non-POD types, so stuck with pointer math.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000802 return reinterpret_cast<size_t>(&fPodEndMarker) -
803 reinterpret_cast<size_t>(&fPodStartMarker) +
804 sizeof(fPodEndMarker);
805 }
806
caryclark@google.comcf6285b2012-06-06 12:09:01 +0000807 static const StageMask kIllegalStageMaskBits = ~((1U << kNumStages)-1);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000808 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000809 union {
810 GrColor fBlendConstant;
811 GrColor fPodStartMarker;
812 };
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000813 GrTexture* fTextures[kNumStages];
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000814 GrColor fColorFilterColor;
815 uint32_t fFlagBits;
816 DrawFace fDrawFace;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000817 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000818 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000819 union {
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000820 GrRenderTarget* fRenderTarget;
821 GrRenderTarget* fMemsetEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000822 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000823 // @}
824
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000825 // @{ Initialized to values other than zero, but memcmp'ed in operator==
826 // and memcpy'ed in operator=.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000827 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000828 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000829 int fFirstCoverageStage;
830 SkXfermode::Mode fColorFilterMode;
831 GrBlendCoeff fSrcBlend;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000832 union {
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000833 GrBlendCoeff fDstBlend;
834 GrBlendCoeff fPodEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000835 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000836 // @}
837
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000838 uint32_t fBehaviorBits;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000839 GrMatrix fViewMatrix;
840
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000841 // This field must be last; it will not be copied or compared
842 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000843 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000844 // only compared if the color matrix enable flag is set
845 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000846
tomhudson@google.com93813632011-10-27 20:21:16 +0000847};
848
849#endif