blob: 63134088af5455161999897fbd8220646ad8fd8a [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
20class GrRenderTarget;
21class GrTexture;
22
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.
39 */
40 enum {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000041 kNumStages = 4,
tomhudson@google.com93813632011-10-27 20:21:16 +000042 kMaxTexCoords = kNumStages
43 };
44
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +000045 /**
46 * Bitfield used to indicate a set of stages.
47 */
48 typedef uint32_t StageMask;
49 GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
50
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000051 GrDrawState() {
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000052 this->reset();
53 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000054
55 GrDrawState(const GrDrawState& state) {
56 *this = state;
57 }
58
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000059 /**
60 * Resets to the default state. Sampler states will not be modified.
61 */
62 void reset() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000063 // make sure any pad is zero for memcmp
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000064 // all GrDrawState members should default to something valid by the
65 // the memset except those initialized individually below. There should
66 // be no padding between the individually initialized members.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000067 memset(this->podStart(), 0, this->memsetSize());
68
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000069 // pedantic assertion that our ptrs will
70 // be NULL (0 ptr is mem addr 0)
71 GrAssert((intptr_t)(void*)NULL == 0LL);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000072 GR_STATIC_ASSERT(0 == kBoth_DrawFace);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000073 GrAssert(fStencilSettings.isDisabled());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000074
75 // memset exceptions
76 fColor = 0xffffffff;
bsalomon@google.com2401ae82012-01-17 21:03:05 +000077 fCoverage = 0xffffffff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000078 fFirstCoverageStage = kNumStages;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000079 fColorFilterMode = SkXfermode::kDst_Mode;
80 fSrcBlend = kOne_BlendCoeff;
81 fDstBlend = kZero_BlendCoeff;
82 fViewMatrix.reset();
83
84 // ensure values that will be memcmp'ed in == but not memset in reset()
85 // are tightly packed
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000086 GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) +
bsalomon@google.com2401ae82012-01-17 21:03:05 +000087 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
bsalomon@google.com8fe84b52012-03-26 15:24:27 +000088 sizeof(fSrcBlend) + sizeof(fDstBlend) ==
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000089 this->podSize());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000090
91 fEdgeAANumEdges = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000092 }
93
94 ///////////////////////////////////////////////////////////////////////////
95 /// @name Color
96 ////
97
98 /**
99 * Sets color for next draw to a premultiplied-alpha color.
100 *
101 * @param color the color to set.
102 */
103 void setColor(GrColor color) { fColor = color; }
104
105 GrColor getColor() const { return fColor; }
106
107 /**
108 * Sets the color to be used for the next draw to be
109 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
110 *
111 * @param alpha The alpha value to set as the color.
112 */
113 void setAlpha(uint8_t a) {
114 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
115 }
116
117 /**
118 * Add a color filter that can be represented by a color and a mode. Applied
119 * after color-computing texture stages.
120 */
121 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
122 fColorFilterColor = c;
123 fColorFilterMode = mode;
124 }
125
126 GrColor getColorFilterColor() const { return fColorFilterColor; }
127 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
128
129 /// @}
130
131 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000132 /// @name Coverage
133 ////
134
135 /**
136 * Sets a constant fractional coverage to be applied to the draw. The
137 * initial value (after construction or reset()) is 0xff. The constant
138 * coverage is ignored when per-vertex coverage is provided.
139 */
140 void setCoverage(uint8_t coverage) {
141 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
142 }
143
144 /**
145 * Version of above that specifies 4 channel per-vertex color. The value
146 * should be premultiplied.
147 */
148 void setCoverage4(GrColor coverage) {
149 fCoverage = coverage;
150 }
151
152 GrColor getCoverage() const {
153 return fCoverage;
154 }
155
156 /// @}
157
158 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000159 /// @name Textures
160 ////
161
162 /**
163 * Sets the texture used at the next drawing call
164 *
165 * @param stage The texture stage for which the texture will be set
166 *
167 * @param texture The texture to set. Can be NULL though there is no
168 * advantage to settings a NULL texture if doing non-textured drawing
169 */
170 void setTexture(int stage, GrTexture* texture) {
171 GrAssert((unsigned)stage < kNumStages);
robertphillips@google.com1942c052012-05-03 17:58:27 +0000172
173 if (isStateFlagEnabled(kTexturesNeedRef_StateBit)) {
174 // If we don't clear out the current texture before unreffing
175 // it we can get into an infinite loop as the GrGLTexture's
176 // onRelease method recursively calls setTexture
177 GrTexture* temp = fTextures[stage];
178 fTextures[stage] = NULL;
179
180 SkSafeRef(texture);
181 SkSafeUnref(temp);
182 }
183
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000184 fTextures[stage] = texture;
185 }
186
187 /**
188 * Retrieves the currently set texture.
189 *
190 * @return The currently set texture. The return value will be NULL if no
191 * texture has been set, NULL was most recently passed to
192 * setTexture, or the last setTexture was destroyed.
193 */
194 const GrTexture* getTexture(int stage) const {
195 GrAssert((unsigned)stage < kNumStages);
196 return fTextures[stage];
197 }
198 GrTexture* getTexture(int stage) {
199 GrAssert((unsigned)stage < kNumStages);
200 return fTextures[stage];
201 }
202
203 /// @}
204
205 ///////////////////////////////////////////////////////////////////////////
206 /// @name Samplers
207 ////
208
209 /**
210 * Returns the current sampler for a stage.
211 */
212 const GrSamplerState& getSampler(int stage) const {
213 GrAssert((unsigned)stage < kNumStages);
214 return fSamplerStates[stage];
215 }
216
217 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000218 * Writable pointer to a stage's sampler.
219 */
220 GrSamplerState* sampler(int stage) {
221 GrAssert((unsigned)stage < kNumStages);
222 return fSamplerStates + stage;
223 }
224
225 /**
226 * Preconcats the matrix of all samplers in the mask with the same matrix.
227 */
228 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
229 GrAssert(!(stageMask & kIllegalStageMaskBits));
230 for (int i = 0; i < kNumStages; ++i) {
231 if ((1 << i) & stageMask) {
232 fSamplerStates[i].preConcatMatrix(matrix);
233 }
234 }
235 }
236
237 /// @}
238
239 ///////////////////////////////////////////////////////////////////////////
240 /// @name Coverage / Color Stages
241 ////
242
243 /**
244 * A common pattern is to compute a color with the initial stages and then
245 * modulate that color by a coverage value in later stage(s) (AA, mask-
246 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
247 * computed based on the pre-coverage-modulated color. The division of
248 * stages between color-computing and coverage-computing is specified by
249 * this method. Initially this is kNumStages (all stages
250 * are color-computing).
251 */
252 void setFirstCoverageStage(int firstCoverageStage) {
253 GrAssert((unsigned)firstCoverageStage <= kNumStages);
254 fFirstCoverageStage = firstCoverageStage;
255 }
256
257 /**
258 * Gets the index of the first coverage-computing stage.
259 */
260 int getFirstCoverageStage() const {
261 return fFirstCoverageStage;
262 }
263
264 ///@}
265
266 ///////////////////////////////////////////////////////////////////////////
267 /// @name Blending
268 ////
269
270 /**
271 * Sets the blending function coeffecients.
272 *
273 * The blend function will be:
274 * D' = sat(S*srcCoef + D*dstCoef)
275 *
276 * where D is the existing destination color, S is the incoming source
277 * color, and D' is the new destination color that will be written. sat()
278 * is the saturation function.
279 *
280 * @param srcCoef coeffecient applied to the src color.
281 * @param dstCoef coeffecient applied to the dst color.
282 */
283 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
284 fSrcBlend = srcCoeff;
285 fDstBlend = dstCoeff;
286 #if GR_DEBUG
287 switch (dstCoeff) {
288 case kDC_BlendCoeff:
289 case kIDC_BlendCoeff:
290 case kDA_BlendCoeff:
291 case kIDA_BlendCoeff:
292 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
293 "coverage stages.\n");
294 break;
295 default:
296 break;
297 }
298 switch (srcCoeff) {
299 case kSC_BlendCoeff:
300 case kISC_BlendCoeff:
301 case kSA_BlendCoeff:
302 case kISA_BlendCoeff:
303 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
304 "coverage stages.\n");
305 break;
306 default:
307 break;
308 }
309 #endif
310 }
311
312 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
313 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
314
315 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
316 GrBlendCoeff* dstBlendCoeff) const {
317 *srcBlendCoeff = fSrcBlend;
318 *dstBlendCoeff = fDstBlend;
319 }
320
321 /**
322 * Sets the blending function constant referenced by the following blending
323 * coeffecients:
324 * kConstC_BlendCoeff
325 * kIConstC_BlendCoeff
326 * kConstA_BlendCoeff
327 * kIConstA_BlendCoeff
328 *
329 * @param constant the constant to set
330 */
331 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
332
333 /**
334 * Retrieves the last value set by setBlendConstant()
335 * @return the blending constant value
336 */
337 GrColor getBlendConstant() const { return fBlendConstant; }
338
339 /// @}
340
341 ///////////////////////////////////////////////////////////////////////////
342 /// @name View Matrix
343 ////
344
345 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000346 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000347 *
348 * In the post-view-matrix space the rectangle [0,w]x[0,h]
349 * fully covers the render target. (w and h are the width and height of the
350 * the rendertarget.)
351 */
352 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
353
354 /**
355 * Gets a writable pointer to the view matrix.
356 */
357 GrMatrix* viewMatrix() { return &fViewMatrix; }
358
359 /**
360 * Multiplies the current view matrix by a matrix
361 *
362 * After this call V' = V*m where V is the old view matrix,
363 * m is the parameter to this function, and V' is the new view matrix.
364 * (We consider positions to be column vectors so position vector p is
365 * transformed by matrix X as p' = X*p.)
366 *
367 * @param m the matrix used to modify the view matrix.
368 */
369 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
370
371 /**
372 * Multiplies the current view matrix by a matrix
373 *
374 * After this call V' = m*V where V is the old view matrix,
375 * m is the parameter to this function, and V' is the new view matrix.
376 * (We consider positions to be column vectors so position vector p is
377 * transformed by matrix X as p' = X*p.)
378 *
379 * @param m the matrix used to modify the view matrix.
380 */
381 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
382
383 /**
384 * Retrieves the current view matrix
385 * @return the current view matrix.
386 */
387 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
388
389 /**
390 * Retrieves the inverse of the current view matrix.
391 *
392 * If the current view matrix is invertible, return true, and if matrix
393 * is non-null, copy the inverse into it. If the current view matrix is
394 * non-invertible, return false and ignore the matrix parameter.
395 *
396 * @param matrix if not null, will receive a copy of the current inverse.
397 */
398 bool getViewInverse(GrMatrix* matrix) const {
399 // TODO: determine whether we really need to leave matrix unmodified
400 // at call sites when inversion fails.
401 GrMatrix inverse;
402 if (fViewMatrix.invert(&inverse)) {
403 if (matrix) {
404 *matrix = inverse;
405 }
406 return true;
407 }
408 return false;
409 }
410
411 class AutoViewMatrixRestore : public ::GrNoncopyable {
412 public:
413 AutoViewMatrixRestore() : fDrawState(NULL) {}
414 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
415 fDrawState = NULL;
416 this->set(ds, newMatrix);
417 }
418 AutoViewMatrixRestore(GrDrawState* ds) {
419 fDrawState = NULL;
420 this->set(ds);
421 }
422 ~AutoViewMatrixRestore() {
423 this->set(NULL, GrMatrix::I());
424 }
425 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
426 if (NULL != fDrawState) {
427 fDrawState->setViewMatrix(fSavedMatrix);
428 }
429 if (NULL != ds) {
430 fSavedMatrix = ds->getViewMatrix();
431 ds->setViewMatrix(newMatrix);
432 }
433 fDrawState = ds;
434 }
435 void set(GrDrawState* ds) {
436 if (NULL != fDrawState) {
437 fDrawState->setViewMatrix(fSavedMatrix);
438 }
439 if (NULL != ds) {
440 fSavedMatrix = ds->getViewMatrix();
441 }
442 fDrawState = ds;
443 }
444 private:
445 GrDrawState* fDrawState;
446 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000447 };
448
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000449 /// @}
450
451 ///////////////////////////////////////////////////////////////////////////
452 /// @name Render Target
453 ////
454
455 /**
456 * Sets the rendertarget used at the next drawing call
457 *
458 * @param target The render target to set.
459 */
460 void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; }
461
462 /**
463 * Retrieves the currently set rendertarget.
464 *
465 * @return The currently set render target.
466 */
467 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
468 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
469
470 class AutoRenderTargetRestore : public ::GrNoncopyable {
471 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000472 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000473 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
474 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000475 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000476 this->set(ds, newTarget);
477 }
478 ~AutoRenderTargetRestore() { this->set(NULL, NULL); }
479 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
480 if (NULL != fDrawState) {
481 fDrawState->setRenderTarget(fSavedTarget);
482 }
483 if (NULL != ds) {
484 fSavedTarget = ds->getRenderTarget();
485 ds->setRenderTarget(newTarget);
486 }
487 fDrawState = ds;
488 }
489 private:
490 GrDrawState* fDrawState;
491 GrRenderTarget* fSavedTarget;
492 };
493
494 /// @}
495
496 ///////////////////////////////////////////////////////////////////////////
497 /// @name Stencil
498 ////
499
500 /**
501 * Sets the stencil settings to use for the next draw.
502 * Changing the clip has the side-effect of possibly zeroing
503 * out the client settable stencil bits. So multipass algorithms
504 * using stencil should not change the clip between passes.
505 * @param settings the stencil settings to use.
506 */
507 void setStencil(const GrStencilSettings& settings) {
508 fStencilSettings = settings;
509 }
510
511 /**
512 * Shortcut to disable stencil testing and ops.
513 */
514 void disableStencil() {
515 fStencilSettings.setDisabled();
516 }
517
518 const GrStencilSettings& getStencil() const { return fStencilSettings; }
519
520 GrStencilSettings* stencil() { return &fStencilSettings; }
521
522 /// @}
523
524 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000525 /// @name Color Matrix
526 ////
527
528 /**
529 * Sets the color matrix to use for the next draw.
530 * @param matrix the 5x4 matrix to apply to the incoming color
531 */
532 void setColorMatrix(const float matrix[20]) {
533 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
534 }
535
536 const float* getColorMatrix() const { return fColorMatrix; }
537
538 /// @}
539
540 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000541 // @name Edge AA
542 // There are two ways to perform antialiasing using edge equations. One
543 // is to specify an (linear or quadratic) edge eq per-vertex. This requires
544 // splitting vertices shared by primitives.
545 //
546 // The other is via setEdgeAAData which sets a set of edges and each
547 // is tested against all the edges.
548 ////
549
550 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000551 * When specifying edges as vertex data this enum specifies what type of
552 * edges are in use. The edges are always 4 GrScalars in memory, even when
553 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000554 *
555 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
556 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000557 */
558 enum VertexEdgeType {
559 /* 1-pixel wide line
560 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
561 kHairLine_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000562 /* Quadratic specified by u^2-v canonical coords (only 2
563 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000564 being inside, positive outside. Edge specified in window space
565 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000566 kQuad_EdgeType,
567 /* Same as above but for hairline quadratics. Uses unsigned distance.
568 Coverage is min(0, 1-distance). */
569 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000570 /* Circle specified as center_x, center_y, outer_radius, inner_radius
571 all in window space (y-down). */
572 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000573
574 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000575 };
576
577 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000578 * Determines the interpretation per-vertex edge data when the
579 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
580 * are not specified the value of this setting has no effect.
581 */
582 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000583 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000584 fVertexEdgeType = type;
585 }
586
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000587 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000588
589 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000590 * The absolute maximum number of edges that may be specified for
591 * a single draw call when performing edge antialiasing. This is used for
592 * the size of several static buffers, so implementations of getMaxEdges()
593 * (below) should clamp to this value.
594 */
595 enum {
tomhudson@google.com62b09682011-11-09 16:39:17 +0000596 // TODO: this should be 32 when GrTesselatedPathRenderer is used
597 // Visual Studio 2010 does not permit a member array of size 0.
598 kMaxEdges = 1
tomhudson@google.com93813632011-10-27 20:21:16 +0000599 };
600
601 class Edge {
602 public:
603 Edge() {}
604 Edge(float x, float y, float z) : fX(x), fY(y), fZ(z) {}
605 GrPoint intersect(const Edge& other) {
606 return GrPoint::Make(
bsalomon@google.com72e49b82011-10-27 21:47:03 +0000607 SkFloatToScalar((fY * other.fZ - other.fY * fZ) /
608 (fX * other.fY - other.fX * fY)),
609 SkFloatToScalar((fX * other.fZ - other.fX * fZ) /
610 (other.fX * fY - fX * other.fY)));
tomhudson@google.com93813632011-10-27 20:21:16 +0000611 }
612 float fX, fY, fZ;
613 };
614
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000615 /**
616 * Sets the edge data required for edge antialiasing.
617 *
618 * @param edges 3 * numEdges float values, representing the edge
619 * equations in Ax + By + C form
620 */
621 void setEdgeAAData(const Edge* edges, int numEdges) {
622 GrAssert(numEdges <= GrDrawState::kMaxEdges);
623 memcpy(fEdgeAAEdges, edges, numEdges * sizeof(GrDrawState::Edge));
624 fEdgeAANumEdges = numEdges;
tomhudson@google.com93813632011-10-27 20:21:16 +0000625 }
626
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000627 int getNumAAEdges() const { return fEdgeAANumEdges; }
tomhudson@google.com93813632011-10-27 20:21:16 +0000628
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000629 const Edge* getAAEdges() const { return fEdgeAAEdges; }
tomhudson@google.com62b09682011-11-09 16:39:17 +0000630
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000631 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000632
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000633 ///////////////////////////////////////////////////////////////////////////
634 /// @name State Flags
635 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000636
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000637 /**
638 * Flags that affect rendering. Controlled using enable/disableState(). All
639 * default to disabled.
640 */
641 enum StateBits {
642 /**
643 * Perform dithering. TODO: Re-evaluate whether we need this bit
644 */
645 kDither_StateBit = 0x01,
646 /**
647 * Perform HW anti-aliasing. This means either HW FSAA, if supported
648 * by the render target, or smooth-line rendering if a line primitive
649 * is drawn and line smoothing is supported by the 3D API.
650 */
651 kHWAntialias_StateBit = 0x02,
652 /**
653 * Draws will respect the clip, otherwise the clip is ignored.
654 */
655 kClip_StateBit = 0x04,
656 /**
657 * Disables writing to the color buffer. Useful when performing stencil
658 * operations.
659 */
660 kNoColorWrites_StateBit = 0x08,
661 /**
662 * Modifies the behavior of edge AA specified by setEdgeAA. If set,
663 * will test edge pairs for convexity when rasterizing. Set this if the
664 * source polygon is non-convex.
665 */
666 kEdgeAAConcave_StateBit = 0x10,
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000667 /**
668 * Draws will apply the color matrix, otherwise the color matrix is
669 * ignored.
670 */
671 kColorMatrix_StateBit = 0x20,
robertphillips@google.com1942c052012-05-03 17:58:27 +0000672 /**
673 * Calls to setTexture will ref/unref the texture
674 */
675 kTexturesNeedRef_StateBit = 0x40,
tomhudson@google.com62b09682011-11-09 16:39:17 +0000676
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000677 // Users of the class may add additional bits to the vector
678 kDummyStateBit,
679 kLastPublicStateBit = kDummyStateBit-1,
680 };
681
682 void resetStateFlags() {
683 fFlagBits = 0;
684 }
685
686 /**
687 * Enable render state settings.
688 *
689 * @param flags bitfield of StateBits specifing the states to enable
690 */
691 void enableState(uint32_t stateBits) {
692 fFlagBits |= stateBits;
693 }
694
695 /**
696 * Disable render state settings.
697 *
698 * @param flags bitfield of StateBits specifing the states to disable
699 */
700 void disableState(uint32_t stateBits) {
701 fFlagBits &= ~(stateBits);
702 }
703
704 bool isDitherState() const {
705 return 0 != (fFlagBits & kDither_StateBit);
706 }
707
708 bool isHWAntialiasState() const {
709 return 0 != (fFlagBits & kHWAntialias_StateBit);
710 }
711
712 bool isClipState() const {
713 return 0 != (fFlagBits & kClip_StateBit);
714 }
715
716 bool isColorWriteDisabled() const {
717 return 0 != (fFlagBits & kNoColorWrites_StateBit);
718 }
719
720 bool isConcaveEdgeAAState() const {
721 return 0 != (fFlagBits & kEdgeAAConcave_StateBit);
722 }
723
724 bool isStateFlagEnabled(uint32_t stateBit) const {
725 return 0 != (stateBit & fFlagBits);
726 }
727
728 void copyStateFlags(const GrDrawState& ds) {
729 fFlagBits = ds.fFlagBits;
730 }
731
732 /// @}
733
734 ///////////////////////////////////////////////////////////////////////////
735 /// @name Face Culling
736 ////
737
738 enum DrawFace {
739 kBoth_DrawFace,
740 kCCW_DrawFace,
741 kCW_DrawFace,
742 };
743
744 /**
745 * Controls whether clockwise, counterclockwise, or both faces are drawn.
746 * @param face the face(s) to draw.
747 */
748 void setDrawFace(DrawFace face) {
749 fDrawFace = face;
750 }
751
752 /**
753 * Gets whether the target is drawing clockwise, counterclockwise,
754 * or both faces.
755 * @return the current draw face(s).
756 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000757 DrawFace getDrawFace() const { return fDrawFace; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000758
759 /// @}
760
761 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000762
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000763 // Most stages are usually not used, so conditionals here
764 // reduce the expected number of bytes touched by 50%.
765 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000766 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000767 return false;
768 }
769
770 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
771 return false;
772 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000773
774 for (int i = 0; i < kNumStages; i++) {
775 if (fTextures[i] &&
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000776 this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000777 return false;
778 }
779 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000780 if (kColorMatrix_StateBit & s.fFlagBits) {
781 if (memcmp(fColorMatrix,
782 s.fColorMatrix,
783 sizeof(fColorMatrix))) {
784 return false;
785 }
786 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000787
788 return true;
789 }
790 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
791
792 // Most stages are usually not used, so conditionals here
793 // reduce the expected number of bytes touched by 50%.
794 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000795 memcpy(this->podStart(), s.podStart(), this->podSize());
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000796
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000797 fViewMatrix = s.fViewMatrix;
798
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000799 GrAssert(0 == s.fEdgeAANumEdges);
800 fEdgeAANumEdges = 0;
801
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000802 for (int i = 0; i < kNumStages; i++) {
803 if (s.fTextures[i]) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000804 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000805 }
806 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000807 if (kColorMatrix_StateBit & s.fFlagBits) {
808 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
809 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000810
811 return *this;
812 }
813
814private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000815
816 const void* podStart() const {
817 return reinterpret_cast<const void*>(&fPodStartMarker);
818 }
819 void* podStart() {
820 return reinterpret_cast<void*>(&fPodStartMarker);
821 }
822 size_t memsetSize() const {
823 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
824 reinterpret_cast<size_t>(&fPodStartMarker) +
825 sizeof(fMemsetEndMarker);
826 }
827 size_t podSize() const {
828 // Can't use offsetof() with non-POD types, so stuck with pointer math.
829 // TODO: ignores GrTesselatedPathRenderer data structures. We don't
830 // have a compile-time flag that lets us know if it's being used, and
831 // checking at runtime seems to cost 5% performance.
832 return reinterpret_cast<size_t>(&fPodEndMarker) -
833 reinterpret_cast<size_t>(&fPodStartMarker) +
834 sizeof(fPodEndMarker);
835 }
836
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000837 static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000838 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000839 union {
840 GrColor fBlendConstant;
841 GrColor fPodStartMarker;
842 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000843 GrTexture* fTextures[kNumStages];
844 GrColor fColorFilterColor;
845 uint32_t fFlagBits;
846 DrawFace fDrawFace;
847 VertexEdgeType fVertexEdgeType;
848 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000849 union {
850 GrRenderTarget* fRenderTarget;
851 GrRenderTarget* fMemsetEndMarker;
852 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000853 // @}
854
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000855 // @{ Initialized to values other than zero, but memcmp'ed in operator==
856 // and memcpy'ed in operator=.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000857 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000858 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000859 int fFirstCoverageStage;
860 SkXfermode::Mode fColorFilterMode;
861 GrBlendCoeff fSrcBlend;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000862 union {
863 GrBlendCoeff fDstBlend;
864 GrBlendCoeff fPodEndMarker;
865 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000866 // @}
867
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000868 GrMatrix fViewMatrix;
869
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000870 // @{ Data for GrTesselatedPathRenderer
871 // TODO: currently ignored in copying & comparison for performance.
872 // Must be considered if GrTesselatedPathRenderer is being used.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000873 int fEdgeAANumEdges;
874 Edge fEdgeAAEdges[kMaxEdges];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000875 // @}
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000876
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000877 // This field must be last; it will not be copied or compared
878 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000879 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000880 // only compared if the color matrix enable flag is set
881 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000882
tomhudson@google.com93813632011-10-27 20:21:16 +0000883};
884
885#endif