GrDrawState.h revision 972265db219ce25b5159879c75e6c62efaf0fa79
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 "GrRefCnt.h" 15#include "GrSamplerState.h" 16#include "GrStencil.h" 17#include "GrTexture.h" 18 19#include "SkXfermode.h" 20 21class GrRenderTarget; 22class GrTexture; 23 24class GrDrawState : public GrRefCnt { 25 26public: 27 /** 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. 40 * 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. 45 */ 46 enum { 47 kNumStages = 4, 48 kMaxTexCoords = kNumStages 49 }; 50 51 /** 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 57 GrDrawState() { 58 this->reset(); 59 } 60 61 GrDrawState(const GrDrawState& state) { 62 *this = state; 63 } 64 65 /** 66 * Resets to the default state. Sampler states will not be modified. 67 */ 68 void reset() { 69 // make sure any pad is zero for memcmp 70 // 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. 73 memset(this->podStart(), 0, this->memsetSize()); 74 75 // pedantic assertion that our ptrs will 76 // be NULL (0 ptr is mem addr 0) 77 GrAssert((intptr_t)(void*)NULL == 0LL); 78 GR_STATIC_ASSERT(0 == kBoth_DrawFace); 79 GrAssert(fStencilSettings.isDisabled()); 80 81 // memset exceptions 82 fColor = 0xffffffff; 83 fCoverage = 0xffffffff; 84 fFirstCoverageStage = kNumStages; 85 fColorFilterMode = SkXfermode::kDst_Mode; 86 fSrcBlend = kOne_GrBlendCoeff; 87 fDstBlend = kZero_GrBlendCoeff; 88 fViewMatrix.reset(); 89 fBehaviorBits = 0; 90 91 // ensure values that will be memcmp'ed in == but not memset in reset() 92 // are tightly packed 93 GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) + 94 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) + 95 sizeof(fSrcBlend) + sizeof(fDstBlend) == 96 this->podSize()); 97 } 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 /////////////////////////////////////////////////////////////////////////// 137 /// @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 /////////////////////////////////////////////////////////////////////////// 164 /// @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); 177 178 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; 184 185 SkSafeRef(texture); 186 SkSafeUnref(temp); 187 } 188 189 fTextures[stage] = texture; 190 } 191 192 /** 193 * Retrieves the currently set texture. 194 * 195 * @return The currently set texture. The return value will be NULL if no 196 * texture has been set, NULL was most recently passed to 197 * setTexture, or the last setTexture was destroyed. 198 */ 199 const GrTexture* getTexture(int stage) const { 200 GrAssert((unsigned)stage < kNumStages); 201 return fTextures[stage]; 202 } 203 GrTexture* getTexture(int stage) { 204 GrAssert((unsigned)stage < kNumStages); 205 return fTextures[stage]; 206 } 207 208 /** 209 * 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 229 /// @} 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 /** 244 * 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) { 314 case kDC_GrBlendCoeff: 315 case kIDC_GrBlendCoeff: 316 case kDA_GrBlendCoeff: 317 case kIDA_GrBlendCoeff: 318 GrPrintf("Unexpected dst blend coeff. Won't work correctly with" 319 "coverage stages.\n"); 320 break; 321 default: 322 break; 323 } 324 switch (srcCoeff) { 325 case kSC_GrBlendCoeff: 326 case kISC_GrBlendCoeff: 327 case kSA_GrBlendCoeff: 328 case kISA_GrBlendCoeff: 329 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: 350 * kConstC_GrBlendCoeff 351 * kIConstC_GrBlendCoeff 352 * kConstA_GrBlendCoeff 353 * kIConstA_GrBlendCoeff 354 * 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 /** 372 * Sets the matrix applied to vertex positions. 373 * 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; 473 }; 474 475 /// @} 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 */ 486 void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; } 487 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: 498 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {} 499 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) { 500 fDrawState = NULL; 501 fSavedTarget = NULL; 502 this->set(ds, newTarget); 503 } 504 ~AutoRenderTargetRestore() { this->set(NULL, NULL); } 505 void set(GrDrawState* ds, GrRenderTarget* newTarget) { 506 if (NULL != fDrawState) { 507 fDrawState->setRenderTarget(fSavedTarget); 508 } 509 if (NULL != ds) { 510 fSavedTarget = ds->getRenderTarget(); 511 ds->setRenderTarget(newTarget); 512 } 513 fDrawState = ds; 514 } 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 /////////////////////////////////////////////////////////////////////////// 551 /// @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 /////////////////////////////////////////////////////////////////////////// 567 // @name Edge AA 568 // 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. 571 // 572 //// 573 574 /** 575 * 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. 578 * 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) 581 */ 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, 586 /* Quadratic specified by u^2-v canonical coords (only 2 587 components used). Coverage based on signed distance with negative 588 being inside, positive outside. Edge specified in window space 589 (y-down) */ 590 kQuad_EdgeType, 591 /* Same as above but for hairline quadratics. Uses unsigned distance. 592 Coverage is min(0, 1-distance). */ 593 kHairQuad_EdgeType, 594 /* Circle specified as center_x, center_y, outer_radius, inner_radius 595 all in window space (y-down). */ 596 kCircle_EdgeType, 597 598 kVertexEdgeTypeCnt 599 }; 600 601 /** 602 * 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) { 607 GrAssert(type >=0 && type < kVertexEdgeTypeCnt); 608 fVertexEdgeType = type; 609 } 610 611 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; } 612 613 /// @} 614 615 /////////////////////////////////////////////////////////////////////////// 616 /// @name State Flags 617 //// 618 619 /** 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 /** 644 * Draws will apply the color matrix, otherwise the color matrix is 645 * ignored. 646 */ 647 kColorMatrix_StateBit = 0x20, 648 649 // 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 692 bool isStateFlagEnabled(uint32_t stateBit) const { 693 return 0 != (stateBit & fFlagBits); 694 } 695 696 /** 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 718 /// @} 719 720 /////////////////////////////////////////////////////////////////////////// 721 /// @name Face Culling 722 //// 723 724 enum DrawFace { 725 kInvalid_DrawFace = -1, 726 727 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) { 737 GrAssert(kInvalid_DrawFace != face); 738 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 */ 746 DrawFace getDrawFace() const { return fDrawFace; } 747 748 /// @} 749 750 /////////////////////////////////////////////////////////////////////////// 751 752 // 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 { 755 if (memcmp(this->podStart(), s.podStart(), this->podSize())) { 756 return false; 757 } 758 759 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) { 760 return false; 761 } 762 763 // 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 771 for (int i = 0; i < kNumStages; i++) { 772 if (fTextures[i] && 773 this->fSamplerStates[i] != s.fSamplerStates[i]) { 774 return false; 775 } 776 } 777 if (kColorMatrix_StateBit & s.fFlagBits) { 778 if (memcmp(fColorMatrix, 779 s.fColorMatrix, 780 sizeof(fColorMatrix))) { 781 return false; 782 } 783 } 784 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) { 792 memcpy(this->podStart(), s.podStart(), this->podSize()); 793 794 fViewMatrix = s.fViewMatrix; 795 fBehaviorBits = s.fBehaviorBits; 796 797 for (int i = 0; i < kNumStages; i++) { 798 if (s.fTextures[i]) { 799 this->fSamplerStates[i] = s.fSamplerStates[i]; 800 } 801 } 802 if (kColorMatrix_StateBit & s.fFlagBits) { 803 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix)); 804 } 805 806 return *this; 807 } 808 809private: 810 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. 824 return reinterpret_cast<size_t>(&fPodEndMarker) - 825 reinterpret_cast<size_t>(&fPodStartMarker) + 826 sizeof(fPodEndMarker); 827 } 828 829 static const StageMask kIllegalStageMaskBits = ~((1U << kNumStages)-1); 830 // @{ these fields can be initialized with memset to 0 831 union { 832 GrColor fBlendConstant; 833 GrColor fPodStartMarker; 834 }; 835 GrTexture* fTextures[kNumStages]; 836 GrColor fColorFilterColor; 837 uint32_t fFlagBits; 838 DrawFace fDrawFace; 839 VertexEdgeType fVertexEdgeType; 840 GrStencilSettings fStencilSettings; 841 union { 842 GrRenderTarget* fRenderTarget; 843 GrRenderTarget* fMemsetEndMarker; 844 }; 845 // @} 846 847 // @{ Initialized to values other than zero, but memcmp'ed in operator== 848 // and memcpy'ed in operator=. 849 GrColor fColor; 850 GrColor fCoverage; 851 int fFirstCoverageStage; 852 SkXfermode::Mode fColorFilterMode; 853 GrBlendCoeff fSrcBlend; 854 union { 855 GrBlendCoeff fDstBlend; 856 GrBlendCoeff fPodEndMarker; 857 }; 858 // @} 859 860 uint32_t fBehaviorBits; 861 GrMatrix fViewMatrix; 862 863 // This field must be last; it will not be copied or compared 864 // if the corresponding fTexture[] is NULL. 865 GrSamplerState fSamplerStates[kNumStages]; 866 // only compared if the color matrix enable flag is set 867 float fColorMatrix[20]; // 5 x 4 matrix 868 869}; 870 871#endif 872