GrDrawState.h revision 8f9cbd62ec108d410b91155dcf6a4789c641246f
1/* 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" 13#include "GrNoncopyable.h" 14#include "GrSamplerState.h" 15#include "GrStencil.h" 16 17#include "SkXfermode.h" 18 19class GrRenderTarget; 20class GrTexture; 21 22struct GrDrawState { 23 24 /** 25 * Number of texture stages. Each stage takes as input a color and 26 * 2D texture coordinates. The color input to the first enabled stage is the 27 * per-vertex color or the constant color (setColor/setAlpha) if there are 28 * no per-vertex colors. For subsequent stages the input color is the output 29 * color from the previous enabled stage. The output color of each stage is 30 * the input color modulated with the result of a texture lookup. Texture 31 * lookups are specified by a texture a sampler (setSamplerState). Texture 32 * coordinates for each stage come from the vertices based on a 33 * GrVertexLayout bitfield. The output fragment color is the output color of 34 * the last enabled stage. The presence or absence of texture coordinates 35 * for each stage in the vertex layout indicates whether a stage is enabled 36 * or not. 37 */ 38 enum { 39 kNumStages = 3, 40 kMaxTexCoords = kNumStages 41 }; 42 43 /** 44 * Bitfield used to indicate a set of stages. 45 */ 46 typedef uint32_t StageMask; 47 GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages); 48 49 GrDrawState() { 50 // make sure any pad is zero for memcmp 51 // all GrDrawState members should default to something 52 // valid by the memset 53 memset(this, 0, sizeof(GrDrawState)); 54 55 // memset exceptions 56 fColorFilterMode = SkXfermode::kDstIn_Mode; 57 fFirstCoverageStage = kNumStages; 58 59 // pedantic assertion that our ptrs will 60 // be NULL (0 ptr is mem addr 0) 61 GrAssert((intptr_t)(void*)NULL == 0LL); 62 63 GrAssert(fStencilSettings.isDisabled()); 64 fFirstCoverageStage = kNumStages; 65 } 66 67 /////////////////////////////////////////////////////////////////////////// 68 /// @name Color 69 //// 70 71 /** 72 * Sets color for next draw to a premultiplied-alpha color. 73 * 74 * @param color the color to set. 75 */ 76 void setColor(GrColor color) { fColor = color; } 77 78 GrColor getColor() const { return fColor; } 79 80 /** 81 * Sets the color to be used for the next draw to be 82 * (r,g,b,a) = (alpha, alpha, alpha, alpha). 83 * 84 * @param alpha The alpha value to set as the color. 85 */ 86 void setAlpha(uint8_t a) { 87 this->setColor((a << 24) | (a << 16) | (a << 8) | a); 88 } 89 90 /** 91 * Add a color filter that can be represented by a color and a mode. Applied 92 * after color-computing texture stages. 93 */ 94 void setColorFilter(GrColor c, SkXfermode::Mode mode) { 95 fColorFilterColor = c; 96 fColorFilterMode = mode; 97 } 98 99 GrColor getColorFilterColor() const { return fColorFilterColor; } 100 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; } 101 102 /// @} 103 104 /////////////////////////////////////////////////////////////////////////// 105 /// @name Textures 106 //// 107 108 /** 109 * Sets the texture used at the next drawing call 110 * 111 * @param stage The texture stage for which the texture will be set 112 * 113 * @param texture The texture to set. Can be NULL though there is no 114 * advantage to settings a NULL texture if doing non-textured drawing 115 */ 116 void setTexture(int stage, GrTexture* texture) { 117 GrAssert((unsigned)stage < kNumStages); 118 fTextures[stage] = texture; 119 } 120 121 /** 122 * Retrieves the currently set texture. 123 * 124 * @return The currently set texture. The return value will be NULL if no 125 * texture has been set, NULL was most recently passed to 126 * setTexture, or the last setTexture was destroyed. 127 */ 128 const GrTexture* getTexture(int stage) const { 129 GrAssert((unsigned)stage < kNumStages); 130 return fTextures[stage]; 131 } 132 GrTexture* getTexture(int stage) { 133 GrAssert((unsigned)stage < kNumStages); 134 return fTextures[stage]; 135 } 136 137 /// @} 138 139 /////////////////////////////////////////////////////////////////////////// 140 /// @name Samplers 141 //// 142 143 /** 144 * Returns the current sampler for a stage. 145 */ 146 const GrSamplerState& getSampler(int stage) const { 147 GrAssert((unsigned)stage < kNumStages); 148 return fSamplerStates[stage]; 149 } 150 151 /** 152 * Sets the sampler. This will be removed soon in favor of direct access. 153 */ 154 void setSampler(int stage, const GrSamplerState& sampler) { 155 GrAssert((unsigned)stage < kNumStages); 156 fSamplerStates[stage] = sampler; 157 } 158 159 /** 160 * Writable pointer to a stage's sampler. 161 */ 162 GrSamplerState* sampler(int stage) { 163 GrAssert((unsigned)stage < kNumStages); 164 return fSamplerStates + stage; 165 } 166 167 /** 168 * Preconcats the matrix of all samplers in the mask with the same matrix. 169 */ 170 void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) { 171 GrAssert(!(stageMask & kIllegalStageMaskBits)); 172 for (int i = 0; i < kNumStages; ++i) { 173 if ((1 << i) & stageMask) { 174 fSamplerStates[i].preConcatMatrix(matrix); 175 } 176 } 177 } 178 179 /// @} 180 181 /////////////////////////////////////////////////////////////////////////// 182 /// @name Coverage / Color Stages 183 //// 184 185 /** 186 * A common pattern is to compute a color with the initial stages and then 187 * modulate that color by a coverage value in later stage(s) (AA, mask- 188 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be 189 * computed based on the pre-coverage-modulated color. The division of 190 * stages between color-computing and coverage-computing is specified by 191 * this method. Initially this is kNumStages (all stages 192 * are color-computing). 193 */ 194 void setFirstCoverageStage(int firstCoverageStage) { 195 GrAssert((unsigned)firstCoverageStage <= kNumStages); 196 fFirstCoverageStage = firstCoverageStage; 197 } 198 199 /** 200 * Gets the index of the first coverage-computing stage. 201 */ 202 int getFirstCoverageStage() const { 203 return fFirstCoverageStage; 204 } 205 206 ///@} 207 208 /////////////////////////////////////////////////////////////////////////// 209 /// @name Blending 210 //// 211 212 /** 213 * Sets the blending function coeffecients. 214 * 215 * The blend function will be: 216 * D' = sat(S*srcCoef + D*dstCoef) 217 * 218 * where D is the existing destination color, S is the incoming source 219 * color, and D' is the new destination color that will be written. sat() 220 * is the saturation function. 221 * 222 * @param srcCoef coeffecient applied to the src color. 223 * @param dstCoef coeffecient applied to the dst color. 224 */ 225 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 226 fSrcBlend = srcCoeff; 227 fDstBlend = dstCoeff; 228 #if GR_DEBUG 229 switch (dstCoeff) { 230 case kDC_BlendCoeff: 231 case kIDC_BlendCoeff: 232 case kDA_BlendCoeff: 233 case kIDA_BlendCoeff: 234 GrPrintf("Unexpected dst blend coeff. Won't work correctly with" 235 "coverage stages.\n"); 236 break; 237 default: 238 break; 239 } 240 switch (srcCoeff) { 241 case kSC_BlendCoeff: 242 case kISC_BlendCoeff: 243 case kSA_BlendCoeff: 244 case kISA_BlendCoeff: 245 GrPrintf("Unexpected src blend coeff. Won't work correctly with" 246 "coverage stages.\n"); 247 break; 248 default: 249 break; 250 } 251 #endif 252 } 253 254 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; } 255 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; } 256 257 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff, 258 GrBlendCoeff* dstBlendCoeff) const { 259 *srcBlendCoeff = fSrcBlend; 260 *dstBlendCoeff = fDstBlend; 261 } 262 263 /** 264 * Sets the blending function constant referenced by the following blending 265 * coeffecients: 266 * kConstC_BlendCoeff 267 * kIConstC_BlendCoeff 268 * kConstA_BlendCoeff 269 * kIConstA_BlendCoeff 270 * 271 * @param constant the constant to set 272 */ 273 void setBlendConstant(GrColor constant) { fBlendConstant = constant; } 274 275 /** 276 * Retrieves the last value set by setBlendConstant() 277 * @return the blending constant value 278 */ 279 GrColor getBlendConstant() const { return fBlendConstant; } 280 281 /// @} 282 283 /////////////////////////////////////////////////////////////////////////// 284 /// @name View Matrix 285 //// 286 287 /** 288 * Sets the matrix applied to veretx positions. 289 * 290 * In the post-view-matrix space the rectangle [0,w]x[0,h] 291 * fully covers the render target. (w and h are the width and height of the 292 * the rendertarget.) 293 */ 294 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; } 295 296 /** 297 * Gets a writable pointer to the view matrix. 298 */ 299 GrMatrix* viewMatrix() { return &fViewMatrix; } 300 301 /** 302 * Multiplies the current view matrix by a matrix 303 * 304 * After this call V' = V*m where V is the old view matrix, 305 * m is the parameter to this function, and V' is the new view matrix. 306 * (We consider positions to be column vectors so position vector p is 307 * transformed by matrix X as p' = X*p.) 308 * 309 * @param m the matrix used to modify the view matrix. 310 */ 311 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); } 312 313 /** 314 * Multiplies the current view matrix by a matrix 315 * 316 * After this call V' = m*V where V is the old view matrix, 317 * m is the parameter to this function, and V' is the new view matrix. 318 * (We consider positions to be column vectors so position vector p is 319 * transformed by matrix X as p' = X*p.) 320 * 321 * @param m the matrix used to modify the view matrix. 322 */ 323 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); } 324 325 /** 326 * Retrieves the current view matrix 327 * @return the current view matrix. 328 */ 329 const GrMatrix& getViewMatrix() const { return fViewMatrix; } 330 331 /** 332 * Retrieves the inverse of the current view matrix. 333 * 334 * If the current view matrix is invertible, return true, and if matrix 335 * is non-null, copy the inverse into it. If the current view matrix is 336 * non-invertible, return false and ignore the matrix parameter. 337 * 338 * @param matrix if not null, will receive a copy of the current inverse. 339 */ 340 bool getViewInverse(GrMatrix* matrix) const { 341 // TODO: determine whether we really need to leave matrix unmodified 342 // at call sites when inversion fails. 343 GrMatrix inverse; 344 if (fViewMatrix.invert(&inverse)) { 345 if (matrix) { 346 *matrix = inverse; 347 } 348 return true; 349 } 350 return false; 351 } 352 353 class AutoViewMatrixRestore : public ::GrNoncopyable { 354 public: 355 AutoViewMatrixRestore() : fDrawState(NULL) {} 356 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) { 357 fDrawState = NULL; 358 this->set(ds, newMatrix); 359 } 360 AutoViewMatrixRestore(GrDrawState* ds) { 361 fDrawState = NULL; 362 this->set(ds); 363 } 364 ~AutoViewMatrixRestore() { 365 this->set(NULL, GrMatrix::I()); 366 } 367 void set(GrDrawState* ds, const GrMatrix& newMatrix) { 368 if (NULL != fDrawState) { 369 fDrawState->setViewMatrix(fSavedMatrix); 370 } 371 if (NULL != ds) { 372 fSavedMatrix = ds->getViewMatrix(); 373 ds->setViewMatrix(newMatrix); 374 } 375 fDrawState = ds; 376 } 377 void set(GrDrawState* ds) { 378 if (NULL != fDrawState) { 379 fDrawState->setViewMatrix(fSavedMatrix); 380 } 381 if (NULL != ds) { 382 fSavedMatrix = ds->getViewMatrix(); 383 } 384 fDrawState = ds; 385 } 386 private: 387 GrDrawState* fDrawState; 388 GrMatrix fSavedMatrix; 389 }; 390 391 /// @} 392 393 /////////////////////////////////////////////////////////////////////////// 394 /// @name Render Target 395 //// 396 397 /** 398 * Sets the rendertarget used at the next drawing call 399 * 400 * @param target The render target to set. 401 */ 402 void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; } 403 404 /** 405 * Retrieves the currently set rendertarget. 406 * 407 * @return The currently set render target. 408 */ 409 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; } 410 GrRenderTarget* getRenderTarget() { return fRenderTarget; } 411 412 class AutoRenderTargetRestore : public ::GrNoncopyable { 413 public: 414 AutoRenderTargetRestore() : fDrawState(NULL) {} 415 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) { 416 fDrawState = NULL; 417 this->set(ds, newTarget); 418 } 419 ~AutoRenderTargetRestore() { this->set(NULL, NULL); } 420 void set(GrDrawState* ds, GrRenderTarget* newTarget) { 421 if (NULL != fDrawState) { 422 fDrawState->setRenderTarget(fSavedTarget); 423 } 424 if (NULL != ds) { 425 fSavedTarget = ds->getRenderTarget(); 426 ds->setRenderTarget(newTarget); 427 } 428 fDrawState = ds; 429 } 430 private: 431 GrDrawState* fDrawState; 432 GrRenderTarget* fSavedTarget; 433 }; 434 435 /// @} 436 437 /////////////////////////////////////////////////////////////////////////// 438 /// @name Stencil 439 //// 440 441 /** 442 * Sets the stencil settings to use for the next draw. 443 * Changing the clip has the side-effect of possibly zeroing 444 * out the client settable stencil bits. So multipass algorithms 445 * using stencil should not change the clip between passes. 446 * @param settings the stencil settings to use. 447 */ 448 void setStencil(const GrStencilSettings& settings) { 449 fStencilSettings = settings; 450 } 451 452 /** 453 * Shortcut to disable stencil testing and ops. 454 */ 455 void disableStencil() { 456 fStencilSettings.setDisabled(); 457 } 458 459 const GrStencilSettings& getStencil() const { return fStencilSettings; } 460 461 GrStencilSettings* stencil() { return &fStencilSettings; } 462 463 /// @} 464 465 /////////////////////////////////////////////////////////////////////////// 466 // @name Edge AA 467 // There are two ways to perform antialiasing using edge equations. One 468 // is to specify an (linear or quadratic) edge eq per-vertex. This requires 469 // splitting vertices shared by primitives. 470 // 471 // The other is via setEdgeAAData which sets a set of edges and each 472 // is tested against all the edges. 473 //// 474 475 /** 476 * When specifying edges as vertex data this enum specifies what type of 477 * edges are in use. The edges are always 4 GrScalars in memory, even when 478 * the edge type requires fewer than 4. 479 */ 480 enum VertexEdgeType { 481 /* 1-pixel wide line 482 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */ 483 kHairLine_EdgeType, 484 /* 1-pixel wide quadratic 485 u^2-v canonical coords (only 2 components used) */ 486 kHairQuad_EdgeType 487 }; 488 489 /** 490 * Determines the interpretation per-vertex edge data when the 491 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges 492 * are not specified the value of this setting has no effect. 493 */ 494 void setVertexEdgeType(VertexEdgeType type) { 495 fVertexEdgeType = type; 496 } 497 498 VertexEdgeType getVertexEdgeType() const { 499 return fVertexEdgeType; 500 } 501 502 /** 503 * The absolute maximum number of edges that may be specified for 504 * a single draw call when performing edge antialiasing. This is used for 505 * the size of several static buffers, so implementations of getMaxEdges() 506 * (below) should clamp to this value. 507 */ 508 enum { 509 // TODO: this should be 32 when GrTesselatedPathRenderer is used 510 // Visual Studio 2010 does not permit a member array of size 0. 511 kMaxEdges = 1 512 }; 513 514 class Edge { 515 public: 516 Edge() {} 517 Edge(float x, float y, float z) : fX(x), fY(y), fZ(z) {} 518 GrPoint intersect(const Edge& other) { 519 return GrPoint::Make( 520 SkFloatToScalar((fY * other.fZ - other.fY * fZ) / 521 (fX * other.fY - other.fX * fY)), 522 SkFloatToScalar((fX * other.fZ - other.fX * fZ) / 523 (other.fX * fY - fX * other.fY))); 524 } 525 float fX, fY, fZ; 526 }; 527 528 /** 529 * Sets the edge data required for edge antialiasing. 530 * 531 * @param edges 3 * numEdges float values, representing the edge 532 * equations in Ax + By + C form 533 */ 534 void setEdgeAAData(const Edge* edges, int numEdges) { 535 GrAssert(numEdges <= GrDrawState::kMaxEdges); 536 memcpy(fEdgeAAEdges, edges, numEdges * sizeof(GrDrawState::Edge)); 537 fEdgeAANumEdges = numEdges; 538 } 539 540 int getNumAAEdges() const { return fEdgeAANumEdges; } 541 542 const Edge* getAAEdges() const { return fEdgeAAEdges; } 543 544 /// @} 545 546 /////////////////////////////////////////////////////////////////////////// 547 /// @name State Flags 548 //// 549 550 /** 551 * Flags that affect rendering. Controlled using enable/disableState(). All 552 * default to disabled. 553 */ 554 enum StateBits { 555 /** 556 * Perform dithering. TODO: Re-evaluate whether we need this bit 557 */ 558 kDither_StateBit = 0x01, 559 /** 560 * Perform HW anti-aliasing. This means either HW FSAA, if supported 561 * by the render target, or smooth-line rendering if a line primitive 562 * is drawn and line smoothing is supported by the 3D API. 563 */ 564 kHWAntialias_StateBit = 0x02, 565 /** 566 * Draws will respect the clip, otherwise the clip is ignored. 567 */ 568 kClip_StateBit = 0x04, 569 /** 570 * Disables writing to the color buffer. Useful when performing stencil 571 * operations. 572 */ 573 kNoColorWrites_StateBit = 0x08, 574 /** 575 * Modifies the behavior of edge AA specified by setEdgeAA. If set, 576 * will test edge pairs for convexity when rasterizing. Set this if the 577 * source polygon is non-convex. 578 */ 579 kEdgeAAConcave_StateBit = 0x10, 580 581 // Users of the class may add additional bits to the vector 582 kDummyStateBit, 583 kLastPublicStateBit = kDummyStateBit-1, 584 }; 585 586 void resetStateFlags() { 587 fFlagBits = 0; 588 } 589 590 /** 591 * Enable render state settings. 592 * 593 * @param flags bitfield of StateBits specifing the states to enable 594 */ 595 void enableState(uint32_t stateBits) { 596 fFlagBits |= stateBits; 597 } 598 599 /** 600 * Disable render state settings. 601 * 602 * @param flags bitfield of StateBits specifing the states to disable 603 */ 604 void disableState(uint32_t stateBits) { 605 fFlagBits &= ~(stateBits); 606 } 607 608 bool isDitherState() const { 609 return 0 != (fFlagBits & kDither_StateBit); 610 } 611 612 bool isHWAntialiasState() const { 613 return 0 != (fFlagBits & kHWAntialias_StateBit); 614 } 615 616 bool isClipState() const { 617 return 0 != (fFlagBits & kClip_StateBit); 618 } 619 620 bool isColorWriteDisabled() const { 621 return 0 != (fFlagBits & kNoColorWrites_StateBit); 622 } 623 624 bool isConcaveEdgeAAState() const { 625 return 0 != (fFlagBits & kEdgeAAConcave_StateBit); 626 } 627 628 bool isStateFlagEnabled(uint32_t stateBit) const { 629 return 0 != (stateBit & fFlagBits); 630 } 631 632 void copyStateFlags(const GrDrawState& ds) { 633 fFlagBits = ds.fFlagBits; 634 } 635 636 /// @} 637 638 /////////////////////////////////////////////////////////////////////////// 639 /// @name Face Culling 640 //// 641 642 enum DrawFace { 643 kBoth_DrawFace, 644 kCCW_DrawFace, 645 kCW_DrawFace, 646 }; 647 648 /** 649 * Controls whether clockwise, counterclockwise, or both faces are drawn. 650 * @param face the face(s) to draw. 651 */ 652 void setDrawFace(DrawFace face) { 653 fDrawFace = face; 654 } 655 656 /** 657 * Gets whether the target is drawing clockwise, counterclockwise, 658 * or both faces. 659 * @return the current draw face(s). 660 */ 661 DrawFace getDrawFace() const { 662 return fDrawFace; 663 } 664 665 /// @} 666 667 /////////////////////////////////////////////////////////////////////////// 668 669 // Most stages are usually not used, so conditionals here 670 // reduce the expected number of bytes touched by 50%. 671 bool operator ==(const GrDrawState& s) const { 672 if (memcmp(this, &s, this->leadingBytes())) return false; 673 674 for (int i = 0; i < kNumStages; i++) { 675 if (fTextures[i] && 676 memcmp(&this->fSamplerStates[i], &s.fSamplerStates[i], 677 sizeof(GrSamplerState))) { 678 return false; 679 } 680 } 681 682 return true; 683 } 684 bool operator !=(const GrDrawState& s) const { return !(*this == s); } 685 686 // Most stages are usually not used, so conditionals here 687 // reduce the expected number of bytes touched by 50%. 688 GrDrawState& operator =(const GrDrawState& s) { 689 memcpy(this, &s, this->leadingBytes()); 690 691 for (int i = 0; i < kNumStages; i++) { 692 if (s.fTextures[i]) { 693 memcpy(&this->fSamplerStates[i], &s.fSamplerStates[i], 694 sizeof(GrSamplerState)); 695 } 696 } 697 698 return *this; 699 } 700 701private: 702 static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1); 703 uint8_t fFlagBits; 704 GrBlendCoeff fSrcBlend : 8; 705 GrBlendCoeff fDstBlend : 8; 706 DrawFace fDrawFace : 8; 707 uint8_t fFirstCoverageStage; 708 SkXfermode::Mode fColorFilterMode : 8; 709 GrColor fBlendConstant; 710 GrTexture* fTextures[kNumStages]; 711 GrRenderTarget* fRenderTarget; 712 GrColor fColor; 713 GrColor fColorFilterColor; 714 GrStencilSettings fStencilSettings; 715 GrMatrix fViewMatrix; 716 // @{ Data for GrTesselatedPathRenderer 717 // TODO: currently ignored in copying & comparison for performance. 718 // Must be considered if GrTesselatedPathRenderer is being used. 719 720 VertexEdgeType fVertexEdgeType; 721 int fEdgeAANumEdges; 722 Edge fEdgeAAEdges[kMaxEdges]; 723 724 // @} 725 // This field must be last; it will not be copied or compared 726 // if the corresponding fTexture[] is NULL. 727 GrSamplerState fSamplerStates[kNumStages]; 728 729 size_t leadingBytes() const { 730 // Can't use offsetof() with non-POD types, so stuck with pointer math. 731 // TODO: ignores GrTesselatedPathRenderer data structures. We don't 732 // have a compile-time flag that lets us know if it's being used, and 733 // checking at runtime seems to cost 5% performance. 734 return (size_t) ((unsigned char*)&fEdgeAANumEdges - 735 (unsigned char*)&fFlagBits); 736 } 737 738}; 739 740#endif 741