Home | History | Annotate | Download | only in src
      1 /*
      2     Copyright 2010 Google Inc.
      3 
      4     Licensed under the Apache License, Version 2.0 (the "License");
      5     you may not use this file except in compliance with the License.
      6     You may obtain a copy of the License at
      7 
      8          http://www.apache.org/licenses/LICENSE-2.0
      9 
     10     Unless required by applicable law or agreed to in writing, software
     11     distributed under the License is distributed on an "AS IS" BASIS,
     12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13     See the License for the specific language governing permissions and
     14     limitations under the License.
     15  */
     16 
     17 
     18 #include "GrDrawTarget.h"
     19 #include "GrGpuVertex.h"
     20 #include "GrTexture.h"
     21 
     22 namespace {
     23 
     24 // recursive helper for creating mask with all the tex coord bits set for
     25 // one stage
     26 template <int N>
     27 int stage_mask_recur(int stage) {
     28     return GrDrawTarget::StageTexCoordVertexLayoutBit(stage, N) |
     29            stage_mask_recur<N+1>(stage);
     30 }
     31 template<>
     32 int stage_mask_recur<GrDrawTarget::kNumStages>(int) { return 0; }
     33 
     34 // mask of all tex coord indices for one stage
     35 int stage_tex_coord_mask(int stage) {
     36     return stage_mask_recur<0>(stage);
     37 }
     38 
     39 // mask of all bits relevant to one stage
     40 int stage_mask(int stage) {
     41     return stage_tex_coord_mask(stage) |
     42            GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(stage);
     43 }
     44 
     45 // recursive helper for creating mask of with all bits set relevant to one
     46 // texture coordinate index
     47 template <int N>
     48 int tex_coord_mask_recur(int texCoordIdx) {
     49     return GrDrawTarget::StageTexCoordVertexLayoutBit(N, texCoordIdx) |
     50            tex_coord_mask_recur<N+1>(texCoordIdx);
     51 }
     52 template<>
     53 int tex_coord_mask_recur<GrDrawTarget::kMaxTexCoords>(int) { return 0; }
     54 
     55 // mask of all bits relevant to one texture coordinate index
     56 int tex_coord_idx_mask(int texCoordIdx) {
     57     return tex_coord_mask_recur<0>(texCoordIdx);
     58 }
     59 
     60 bool check_layout(GrVertexLayout layout) {
     61     // can only have 1 or 0 bits set for each stage.
     62     for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
     63         int stageBits = layout & stage_mask(s);
     64         if (stageBits && !GrIsPow2(stageBits)) {
     65             return false;
     66         }
     67     }
     68     return true;
     69 }
     70 
     71 } //unnamed namespace
     72 
     73 size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
     74     GrAssert(check_layout(vertexLayout));
     75 
     76     size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
     77                         sizeof(GrGpuTextVertex) :
     78                         sizeof(GrPoint);
     79 
     80     size_t size = vecSize; // position
     81     for (int t = 0; t < kMaxTexCoords; ++t) {
     82         if (tex_coord_idx_mask(t) & vertexLayout) {
     83             size += vecSize;
     84         }
     85     }
     86     if (vertexLayout & kColor_VertexLayoutBit) {
     87         size += sizeof(GrColor);
     88     }
     89     return size;
     90 }
     91 
     92 int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
     93     GrAssert(check_layout(vertexLayout));
     94     if (StagePosAsTexCoordVertexLayoutBit(stage) & vertexLayout) {
     95         return 0;
     96     }
     97     int tcIdx = VertexTexCoordsForStage(stage, vertexLayout);
     98     if (tcIdx >= 0) {
     99 
    100         int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
    101                                     sizeof(GrGpuTextVertex) :
    102                                     sizeof(GrPoint);
    103         int offset = vecSize; // position
    104         // figure out how many tex coordinates are present and precede this one.
    105         for (int t = 0; t < tcIdx; ++t) {
    106             if (tex_coord_idx_mask(t) & vertexLayout) {
    107                 offset += vecSize;
    108             }
    109         }
    110         return offset;
    111     }
    112 
    113     return -1;
    114 }
    115 
    116 int  GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
    117     GrAssert(check_layout(vertexLayout));
    118 
    119     if (vertexLayout & kColor_VertexLayoutBit) {
    120         int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
    121                                     sizeof(GrGpuTextVertex) :
    122                                     sizeof(GrPoint);
    123         int offset = vecSize; // position
    124         // figure out how many tex coordinates are present and precede this one.
    125         for (int t = 0; t < kMaxTexCoords; ++t) {
    126             if (tex_coord_idx_mask(t) & vertexLayout) {
    127                 offset += vecSize;
    128             }
    129         }
    130         return offset;
    131     }
    132     return -1;
    133 }
    134 
    135 int GrDrawTarget::VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
    136                                              int texCoordOffsetsByIdx[kMaxTexCoords],
    137                                              int* colorOffset) {
    138     GrAssert(check_layout(vertexLayout));
    139 
    140     GrAssert(NULL != texCoordOffsetsByIdx);
    141     GrAssert(NULL != colorOffset);
    142 
    143     int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
    144                                                     sizeof(GrGpuTextVertex) :
    145                                                     sizeof(GrPoint);
    146     int size = vecSize; // position
    147 
    148     for (int t = 0; t < kMaxTexCoords; ++t) {
    149         if (tex_coord_idx_mask(t) & vertexLayout) {
    150             texCoordOffsetsByIdx[t] = size;
    151             size += vecSize;
    152         } else {
    153             texCoordOffsetsByIdx[t] = -1;
    154         }
    155     }
    156     if (kColor_VertexLayoutBit & vertexLayout) {
    157         *colorOffset = size;
    158         size += sizeof(GrColor);
    159     } else {
    160         *colorOffset = -1;
    161     }
    162     return size;
    163 }
    164 
    165 int GrDrawTarget::VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,
    166                                               int texCoordOffsetsByStage[kNumStages],
    167                                               int* colorOffset) {
    168     GrAssert(check_layout(vertexLayout));
    169 
    170     GrAssert(NULL != texCoordOffsetsByStage);
    171     GrAssert(NULL != colorOffset);
    172 
    173     int texCoordOffsetsByIdx[kMaxTexCoords];
    174     int size = VertexSizeAndOffsetsByIdx(vertexLayout,
    175                                          texCoordOffsetsByIdx,
    176                                          colorOffset);
    177     for (int s = 0; s < kNumStages; ++s) {
    178         int tcIdx;
    179         if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) {
    180             texCoordOffsetsByStage[s] = 0;
    181         } else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) {
    182             texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx];
    183         } else {
    184             texCoordOffsetsByStage[s] = -1;
    185         }
    186     }
    187     return size;
    188 }
    189 
    190 bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) {
    191     GrAssert(stage < kNumStages);
    192     GrAssert(check_layout(vertexLayout));
    193     return !!(stage_mask(stage) & vertexLayout);
    194 }
    195 
    196 bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
    197                                          GrVertexLayout vertexLayout) {
    198     GrAssert(coordIndex < kMaxTexCoords);
    199     GrAssert(check_layout(vertexLayout));
    200     return !!(tex_coord_idx_mask(coordIndex) & vertexLayout);
    201 }
    202 
    203 int GrDrawTarget::VertexTexCoordsForStage(int stage, GrVertexLayout vertexLayout) {
    204     GrAssert(stage < kNumStages);
    205     GrAssert(check_layout(vertexLayout));
    206     int bit = vertexLayout & stage_tex_coord_mask(stage);
    207     if (bit) {
    208         // figure out which set of texture coordates is used
    209         // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
    210         // and start at bit 0.
    211         GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
    212         return (32 - Gr_clz(bit) - 1) / kNumStages;
    213     }
    214     return -1;
    215 }
    216 
    217 void GrDrawTarget::VertexLayoutUnitTest() {
    218     // not necessarily exhaustive
    219     static bool run;
    220     if (!run) {
    221         run = true;
    222         for (int s = 0; s < kNumStages; ++s) {
    223 
    224             GrAssert(!VertexUsesStage(s, 0));
    225             GrAssert(-1 == VertexStageCoordOffset(s, 0));
    226             GrVertexLayout stageMask = 0;
    227             for (int t = 0; t < kMaxTexCoords; ++t) {
    228                 stageMask |= StageTexCoordVertexLayoutBit(s,t);
    229             }
    230             GrAssert(1 == kMaxTexCoords || !check_layout(stageMask));
    231             GrAssert(stage_tex_coord_mask(s) == stageMask);
    232             stageMask |= StagePosAsTexCoordVertexLayoutBit(s);
    233             GrAssert(stage_mask(s) == stageMask);
    234             GrAssert(!check_layout(stageMask));
    235         }
    236         for (int t = 0; t < kMaxTexCoords; ++t) {
    237             GrVertexLayout tcMask = 0;
    238             GrAssert(!VertexUsesTexCoordIdx(t, 0));
    239             for (int s = 0; s < kNumStages; ++s) {
    240                 tcMask |= StageTexCoordVertexLayoutBit(s,t);
    241                 GrAssert(VertexUsesStage(s, tcMask));
    242                 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
    243                 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
    244                 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
    245                 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
    246                 for (int s2 = s + 1; s2 < kNumStages; ++s2) {
    247                     GrAssert(-1 == VertexStageCoordOffset(s2, tcMask));
    248                     GrAssert(!VertexUsesStage(s2, tcMask));
    249                     GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
    250 
    251                 #if GR_DEBUG
    252                     GrVertexLayout posAsTex = tcMask | StagePosAsTexCoordVertexLayoutBit(s2);
    253                 #endif
    254                     GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
    255                     GrAssert(VertexUsesStage(s2, posAsTex));
    256                     GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
    257                     GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
    258                 }
    259             #if GR_DEBUG
    260                 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
    261             #endif
    262                 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
    263                 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
    264             }
    265             GrAssert(tex_coord_idx_mask(t) == tcMask);
    266             GrAssert(check_layout(tcMask));
    267 
    268             int stageOffsets[kNumStages];
    269             int colorOffset;
    270             int size;
    271             size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset);
    272             GrAssert(2*sizeof(GrPoint) == size);
    273             GrAssert(-1 == colorOffset);
    274             for (int s = 0; s < kNumStages; ++s) {
    275                 GrAssert(VertexUsesStage(s, tcMask));
    276                 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
    277                 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
    278             }
    279         }
    280     }
    281 }
    282 
    283 ////////////////////////////////////////////////////////////////////////////////
    284 
    285 GrDrawTarget::GrDrawTarget() {
    286 #if GR_DEBUG
    287     VertexLayoutUnitTest();
    288 #endif
    289     fReservedGeometry.fLocked = false;
    290 #if GR_DEBUG
    291     fReservedGeometry.fVertexCount  = ~0;
    292     fReservedGeometry.fIndexCount   = ~0;
    293 #endif
    294     fGeometrySrc.fVertexSrc = kReserved_GeometrySrcType;
    295     fGeometrySrc.fIndexSrc  = kReserved_GeometrySrcType;
    296 }
    297 
    298 void GrDrawTarget::setClip(const GrClip& clip) {
    299     clipWillBeSet(clip);
    300     fClip = clip;
    301 }
    302 
    303 const GrClip& GrDrawTarget::getClip() const {
    304     return fClip;
    305 }
    306 
    307 void GrDrawTarget::setTexture(int stage, GrTexture* tex) {
    308     GrAssert(stage >= 0 && stage < kNumStages);
    309     fCurrDrawState.fTextures[stage] = tex;
    310 }
    311 
    312 const GrTexture* GrDrawTarget::getTexture(int stage) const {
    313     GrAssert(stage >= 0 && stage < kNumStages);
    314     return fCurrDrawState.fTextures[stage];
    315 }
    316 
    317 GrTexture* GrDrawTarget::getTexture(int stage) {
    318     GrAssert(stage >= 0 && stage < kNumStages);
    319     return fCurrDrawState.fTextures[stage];
    320 }
    321 
    322 void GrDrawTarget::setRenderTarget(GrRenderTarget* target) {
    323     fCurrDrawState.fRenderTarget = target;
    324 }
    325 
    326 const GrRenderTarget* GrDrawTarget::getRenderTarget() const {
    327     return fCurrDrawState.fRenderTarget;
    328 }
    329 
    330 GrRenderTarget* GrDrawTarget::getRenderTarget() {
    331     return fCurrDrawState.fRenderTarget;
    332 }
    333 
    334 void GrDrawTarget::setViewMatrix(const GrMatrix& m) {
    335     fCurrDrawState.fViewMatrix = m;
    336 }
    337 
    338 void GrDrawTarget::preConcatViewMatrix(const GrMatrix& matrix) {
    339     fCurrDrawState.fViewMatrix.preConcat(matrix);
    340 }
    341 
    342 void GrDrawTarget::postConcatViewMatrix(const GrMatrix& matrix) {
    343     fCurrDrawState.fViewMatrix.postConcat(matrix);
    344 }
    345 
    346 const GrMatrix& GrDrawTarget::getViewMatrix() const {
    347     return fCurrDrawState.fViewMatrix;
    348 }
    349 
    350 bool GrDrawTarget::getViewInverse(GrMatrix* matrix) const {
    351     // Mike:  Can we cache this somewhere?
    352     // Brian: Sure, do we use it often?
    353 
    354     GrMatrix inverse;
    355     if (fCurrDrawState.fViewMatrix.invert(&inverse)) {
    356         if (matrix) {
    357             *matrix = inverse;
    358         }
    359         return true;
    360     }
    361     return false;
    362 }
    363 
    364 void GrDrawTarget::setSamplerState(int stage, const GrSamplerState& state) {
    365     GrAssert(stage >= 0 && stage < kNumStages);
    366     fCurrDrawState.fSamplerStates[stage] = state;
    367 }
    368 
    369 void GrDrawTarget::enableState(uint32_t bits) {
    370     fCurrDrawState.fFlagBits |= bits;
    371 }
    372 
    373 void GrDrawTarget::disableState(uint32_t bits) {
    374     fCurrDrawState.fFlagBits &= ~(bits);
    375 }
    376 
    377 void GrDrawTarget::setBlendFunc(GrBlendCoeff srcCoeff,
    378                                 GrBlendCoeff dstCoeff) {
    379     fCurrDrawState.fSrcBlend = srcCoeff;
    380     fCurrDrawState.fDstBlend = dstCoeff;
    381 #if GR_DEBUG
    382     switch (dstCoeff) {
    383     case kDC_BlendCoeff:
    384     case kIDC_BlendCoeff:
    385     case kDA_BlendCoeff:
    386     case kIDA_BlendCoeff:
    387         GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
    388                  "coverage stages.\n");
    389         break;
    390     default:
    391         break;
    392     }
    393     switch (srcCoeff) {
    394     case kSC_BlendCoeff:
    395     case kISC_BlendCoeff:
    396     case kSA_BlendCoeff:
    397     case kISA_BlendCoeff:
    398         GrPrintf("Unexpected src blend coeff. Won't work correctly with"
    399                  "coverage stages.\n");
    400         break;
    401     default:
    402         break;
    403     }
    404 #endif
    405 }
    406 
    407 void GrDrawTarget::setColor(GrColor c) {
    408     fCurrDrawState.fColor = c;
    409 }
    410 
    411 void GrDrawTarget::setColorFilter(GrColor c, SkXfermode::Mode mode) {
    412     fCurrDrawState.fColorFilterColor = c;
    413     fCurrDrawState.fColorFilterXfermode = mode;
    414 }
    415 
    416 void GrDrawTarget::setAlpha(uint8_t a) {
    417     this->setColor((a << 24) | (a << 16) | (a << 8) | a);
    418 }
    419 
    420 void GrDrawTarget::saveCurrentDrawState(SavedDrawState* state) const {
    421     state->fState = fCurrDrawState;
    422 }
    423 
    424 void GrDrawTarget::restoreDrawState(const SavedDrawState& state) {
    425     fCurrDrawState = state.fState;
    426 }
    427 
    428 void GrDrawTarget::copyDrawState(const GrDrawTarget& srcTarget) {
    429     fCurrDrawState = srcTarget.fCurrDrawState;
    430 }
    431 
    432 
    433 bool GrDrawTarget::reserveAndLockGeometry(GrVertexLayout    vertexLayout,
    434                                           uint32_t          vertexCount,
    435                                           uint32_t          indexCount,
    436                                           void**            vertices,
    437                                           void**            indices) {
    438     GrAssert(!fReservedGeometry.fLocked);
    439     fReservedGeometry.fVertexCount  = vertexCount;
    440     fReservedGeometry.fIndexCount   = indexCount;
    441 
    442     fReservedGeometry.fLocked = this->onAcquireGeometry(vertexLayout,
    443                                                         vertices,
    444                                                         indices);
    445     if (fReservedGeometry.fLocked) {
    446         if (vertexCount) {
    447             fGeometrySrc.fVertexSrc = kReserved_GeometrySrcType;
    448             fGeometrySrc.fVertexLayout = vertexLayout;
    449         } else if (NULL != vertices) {
    450             *vertices = NULL;
    451         }
    452         if (indexCount) {
    453             fGeometrySrc.fIndexSrc = kReserved_GeometrySrcType;
    454         } else if (NULL != indices) {
    455             *indices = NULL;
    456         }
    457     }
    458     return fReservedGeometry.fLocked;
    459 }
    460 
    461 bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
    462                                  int32_t* vertexCount,
    463                                  int32_t* indexCount) const {
    464     GrAssert(!fReservedGeometry.fLocked);
    465     if (NULL != vertexCount) {
    466         *vertexCount = -1;
    467     }
    468     if (NULL != indexCount) {
    469         *indexCount = -1;
    470     }
    471     return false;
    472 }
    473 
    474 void GrDrawTarget::releaseReservedGeometry() {
    475     GrAssert(fReservedGeometry.fLocked);
    476     this->onReleaseGeometry();
    477     fReservedGeometry.fLocked = false;
    478 }
    479 
    480 void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
    481                                           const void* vertexArray,
    482                                           int vertexCount) {
    483     fGeometrySrc.fVertexSrc = kArray_GeometrySrcType;
    484     fGeometrySrc.fVertexLayout = vertexLayout;
    485     this->onSetVertexSourceToArray(vertexArray, vertexCount);
    486 }
    487 
    488 void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
    489                                          int indexCount) {
    490     fGeometrySrc.fIndexSrc = kArray_GeometrySrcType;
    491     this->onSetIndexSourceToArray(indexArray, indexCount);
    492 }
    493 
    494 void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
    495                                            const GrVertexBuffer* buffer) {
    496     fGeometrySrc.fVertexSrc    = kBuffer_GeometrySrcType;
    497     fGeometrySrc.fVertexBuffer = buffer;
    498     fGeometrySrc.fVertexLayout = vertexLayout;
    499 }
    500 
    501 void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
    502     fGeometrySrc.fIndexSrc     = kBuffer_GeometrySrcType;
    503     fGeometrySrc.fIndexBuffer  = buffer;
    504 }
    505 
    506 ///////////////////////////////////////////////////////////////////////////////
    507 
    508 bool GrDrawTarget::canDisableBlend() const {
    509     // If we compute a coverage value (using edge AA or a coverage stage) then
    510     // we can't force blending off.
    511     if (fCurrDrawState.fEdgeAANumEdges > 0) {
    512         return false;
    513     }
    514     for (int s = fCurrDrawState.fFirstCoverageStage; s < kNumStages; ++s) {
    515         if (this->isStageEnabled(s)) {
    516             return false;
    517         }
    518     }
    519 
    520     if ((kOne_BlendCoeff == fCurrDrawState.fSrcBlend) &&
    521         (kZero_BlendCoeff == fCurrDrawState.fDstBlend)) {
    522             return true;
    523     }
    524 
    525     // If we have vertex color without alpha then we can't force blend off
    526     if ((fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) ||
    527          0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
    528         return false;
    529     }
    530 
    531     // If the src coef will always be 1...
    532     if (kSA_BlendCoeff != fCurrDrawState.fSrcBlend &&
    533         kOne_BlendCoeff != fCurrDrawState.fSrcBlend) {
    534         return false;
    535     }
    536 
    537     // ...and the dst coef is always 0...
    538     if (kISA_BlendCoeff != fCurrDrawState.fDstBlend &&
    539         kZero_BlendCoeff != fCurrDrawState.fDstBlend) {
    540         return false;
    541     }
    542 
    543     // ...and there isn't a texture stage with an alpha channel...
    544     for (int s = 0; s < fCurrDrawState.fFirstCoverageStage; ++s) {
    545         if (this->isStageEnabled(s)) {
    546             GrAssert(NULL != fCurrDrawState.fTextures[s]);
    547 
    548             GrPixelConfig config = fCurrDrawState.fTextures[s]->config();
    549 
    550             if (!GrPixelConfigIsOpaque(config)) {
    551                 return false;
    552             }
    553         }
    554     }
    555 
    556     // ...and there isn't an interesting color filter...
    557     // TODO: Consider being more aggressive with regards to disabling
    558     // blending when a color filter is used.
    559     if (SkXfermode::kDst_Mode != fCurrDrawState.fColorFilterXfermode) {
    560         return false;
    561     }
    562 
    563     // ...then we disable blend.
    564     return true;
    565 }
    566 
    567 ///////////////////////////////////////////////////////////////////////////////
    568 void GrDrawTarget::setEdgeAAData(const Edge* edges, int numEdges) {
    569     GrAssert(numEdges <= kMaxEdges);
    570     memcpy(fCurrDrawState.fEdgeAAEdges, edges, numEdges * sizeof(Edge));
    571     fCurrDrawState.fEdgeAANumEdges = numEdges;
    572 }
    573 
    574 
    575 ///////////////////////////////////////////////////////////////////////////////
    576 void GrDrawTarget::drawRect(const GrRect& rect,
    577                             const GrMatrix* matrix,
    578                             StageBitfield stageEnableBitfield,
    579                             const GrRect* srcRects[],
    580                             const GrMatrix* srcMatrices[]) {
    581     GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects);
    582 
    583     AutoReleaseGeometry geo(this, layout, 4, 0);
    584 
    585     SetRectVertices(rect, matrix, srcRects,
    586                     srcMatrices, layout, geo.vertices());
    587 
    588     drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
    589 }
    590 
    591 GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageBitfield stageEnableBitfield,
    592                                                  const GrRect* srcRects[]) {
    593     GrVertexLayout layout = 0;
    594 
    595     for (int i = 0; i < kNumStages; ++i) {
    596         int numTC = 0;
    597         if (stageEnableBitfield & (1 << i)) {
    598             if (NULL != srcRects && NULL != srcRects[i]) {
    599                 layout |= StageTexCoordVertexLayoutBit(i, numTC);
    600                 ++numTC;
    601             } else {
    602                 layout |= StagePosAsTexCoordVertexLayoutBit(i);
    603             }
    604         }
    605     }
    606     return layout;
    607 }
    608 void GrDrawTarget::SetRectVertices(const GrRect& rect,
    609                                    const GrMatrix* matrix,
    610                                    const GrRect* srcRects[],
    611                                    const GrMatrix* srcMatrices[],
    612                                    GrVertexLayout layout,
    613                                    void* vertices) {
    614 #if GR_DEBUG
    615     // check that the layout and srcRects agree
    616     for (int i = 0; i < kNumStages; ++i) {
    617         if (VertexTexCoordsForStage(i, layout) >= 0) {
    618             GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
    619         } else {
    620             GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
    621         }
    622     }
    623 #endif
    624 
    625     int stageOffsets[kNumStages];
    626     int colorOffset;
    627     int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets, &colorOffset);
    628     GrAssert(-1 == colorOffset);
    629 
    630     GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
    631                                             rect.fRight, rect.fBottom,
    632                                             vsize);
    633     if (NULL != matrix) {
    634         matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
    635     }
    636 
    637     for (int i = 0; i < kNumStages; ++i) {
    638         if (stageOffsets[i] > 0) {
    639             GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
    640                                                 stageOffsets[i]);
    641             coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
    642                                srcRects[i]->fRight, srcRects[i]->fBottom,
    643                                vsize);
    644             if (NULL != srcMatrices && NULL != srcMatrices[i]) {
    645                 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
    646             }
    647         }
    648     }
    649 }
    650 
    651 ///////////////////////////////////////////////////////////////////////////////
    652 GrDrawTarget::AutoStateRestore::AutoStateRestore() {
    653     fDrawTarget = NULL;
    654 }
    655 
    656 GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target) {
    657     fDrawTarget = target;
    658     if (NULL != fDrawTarget) {
    659         fDrawTarget->saveCurrentDrawState(&fDrawState);
    660     }
    661 }
    662 
    663 GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
    664     if (NULL != fDrawTarget) {
    665         fDrawTarget->restoreDrawState(fDrawState);
    666     }
    667 }
    668 
    669 void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target) {
    670     if (target != fDrawTarget) {
    671         if (NULL != fDrawTarget) {
    672             fDrawTarget->restoreDrawState(fDrawState);
    673         }
    674         if (NULL != target) {
    675             fDrawTarget->saveCurrentDrawState(&fDrawState);
    676         }
    677         fDrawTarget = target;
    678     }
    679 }
    680