Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3  * Copyright 2010 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 
     11 #include "GrDrawTarget.h"
     12 #include "GrGpuVertex.h"
     13 #include "GrIndexBuffer.h"
     14 #include "GrRenderTarget.h"
     15 #include "GrTexture.h"
     16 #include "GrVertexBuffer.h"
     17 
     18 namespace {
     19 
     20 /**
     21  * This function generates some masks that we like to have known at compile
     22  * time. When the number of stages or tex coords is bumped or the way bits
     23  * are defined in GrDrawTarget.h changes this funcion should be rerun to
     24  * generate the new masks. (We attempted to force the compiler to generate the
     25  * masks using recursive templates but always wound up with static initializers
     26  * under gcc, even if they were just a series of immediate->memory moves.)
     27  *
     28  */
     29 void gen_mask_arrays(GrVertexLayout* stageTexCoordMasks,
     30                      GrVertexLayout* stageMasks,
     31                      GrVertexLayout* texCoordMasks) {
     32     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
     33         stageTexCoordMasks[s] = 0;
     34         for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
     35             stageTexCoordMasks[s] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
     36         }
     37         stageMasks[s] = stageTexCoordMasks[s] | GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
     38     }
     39     for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
     40         texCoordMasks[t] = 0;
     41         for (int s = 0; s < GrDrawState::kNumStages; ++s) {
     42             texCoordMasks[t] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
     43         }
     44     }
     45 }
     46 
     47 /**
     48  * Run this function to generate the code that declares the global masks.
     49  */
     50 void gen_globals() {
     51     GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
     52     GrVertexLayout stageMasks[GrDrawState::kNumStages];
     53     GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
     54     gen_mask_arrays(stageTexCoordMasks, stageMasks, texCoordMasks);
     55 
     56     GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n");
     57     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
     58         GrPrintf("    0x%x,\n", stageTexCoordMasks[s]);
     59     }
     60     GrPrintf("};\n");
     61     GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n");
     62     GrPrintf("const GrVertexLayout gStageMasks[] = {\n");
     63     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
     64         GrPrintf("    0x%x,\n", stageMasks[s]);
     65     }
     66     GrPrintf("};\n");
     67     GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageMasks));\n\n");
     68     GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n");
     69     for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
     70         GrPrintf("    0x%x,\n", texCoordMasks[t]);
     71     }
     72     GrPrintf("};\n");
     73     GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n");
     74 }
     75 
     76 /* These values were generated by the above function */
     77 const GrVertexLayout gStageTexCoordMasks[] = {
     78     0x49,
     79     0x92,
     80     0x124
     81 };
     82 
     83 GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
     84 const GrVertexLayout gStageMasks[] = {
     85     0x249,
     86     0x492,
     87     0x924
     88 };
     89 
     90 GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageMasks));
     91 const GrVertexLayout gTexCoordMasks[] = {
     92     0x7,
     93     0x38,
     94     0x1c0,
     95 };
     96 GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
     97 
     98 bool check_layout(GrVertexLayout layout) {
     99     // can only have 1 or 0 bits set for each stage.
    100     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
    101         int stageBits = layout & gStageMasks[s];
    102         if (stageBits && !GrIsPow2(stageBits)) {
    103             return false;
    104         }
    105     }
    106     return true;
    107 }
    108 
    109 int num_tex_coords(GrVertexLayout layout) {
    110     int cnt = 0;
    111     // figure out how many tex coordinates are present
    112     for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
    113         if (gTexCoordMasks[t] & layout) {
    114             ++cnt;
    115         }
    116     }
    117     return cnt;
    118 }
    119 
    120 } //unnamed namespace
    121 
    122 size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
    123     GrAssert(check_layout(vertexLayout));
    124 
    125     size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
    126                         sizeof(GrGpuTextVertex) :
    127                         sizeof(GrPoint);
    128 
    129     size_t size = vecSize; // position
    130     size += num_tex_coords(vertexLayout) * vecSize;
    131     if (vertexLayout & kColor_VertexLayoutBit) {
    132         size += sizeof(GrColor);
    133     }
    134     if (vertexLayout & kCoverage_VertexLayoutBit) {
    135         size += sizeof(GrColor);
    136     }
    137     if (vertexLayout & kEdge_VertexLayoutBit) {
    138         size += 4 * sizeof(GrScalar);
    139     }
    140     return size;
    141 }
    142 
    143 ////////////////////////////////////////////////////////////////////////////////
    144 
    145 /**
    146  * Functions for computing offsets of various components from the layout
    147  * bitfield.
    148  *
    149  * Order of vertex components:
    150  * Position
    151  * Tex Coord 0
    152  * ...
    153  * Tex Coord GrDrawState::kMaxTexCoords-1
    154  * Color
    155  * Coverage
    156  */
    157 
    158 int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
    159     GrAssert(check_layout(vertexLayout));
    160     if (StagePosAsTexCoordVertexLayoutBit(stage) & vertexLayout) {
    161         return 0;
    162     }
    163     int tcIdx = VertexTexCoordsForStage(stage, vertexLayout);
    164     if (tcIdx >= 0) {
    165 
    166         int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
    167                                     sizeof(GrGpuTextVertex) :
    168                                     sizeof(GrPoint);
    169         int offset = vecSize; // position
    170         // figure out how many tex coordinates are present and precede this one.
    171         for (int t = 0; t < tcIdx; ++t) {
    172             if (gTexCoordMasks[t] & vertexLayout) {
    173                 offset += vecSize;
    174             }
    175         }
    176         return offset;
    177     }
    178 
    179     return -1;
    180 }
    181 
    182 int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
    183     GrAssert(check_layout(vertexLayout));
    184 
    185     if (vertexLayout & kColor_VertexLayoutBit) {
    186         int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
    187                                     sizeof(GrGpuTextVertex) :
    188                                     sizeof(GrPoint);
    189         return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
    190     }
    191     return -1;
    192 }
    193 
    194 int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
    195     GrAssert(check_layout(vertexLayout));
    196 
    197     if (vertexLayout & kCoverage_VertexLayoutBit) {
    198         int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
    199                                     sizeof(GrGpuTextVertex) :
    200                                     sizeof(GrPoint);
    201 
    202         int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
    203         if (vertexLayout & kColor_VertexLayoutBit) {
    204             offset += sizeof(GrColor);
    205         }
    206         return offset;
    207     }
    208     return -1;
    209 }
    210 
    211 int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
    212     GrAssert(check_layout(vertexLayout));
    213 
    214     // edge pts are after the pos, tex coords, and color
    215     if (vertexLayout & kEdge_VertexLayoutBit) {
    216         int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
    217                                     sizeof(GrGpuTextVertex) :
    218                                     sizeof(GrPoint);
    219         int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
    220         if (vertexLayout & kColor_VertexLayoutBit) {
    221             offset += sizeof(GrColor);
    222         }
    223         if (vertexLayout & kCoverage_VertexLayoutBit) {
    224             offset += sizeof(GrColor);
    225         }
    226         return offset;
    227     }
    228     return -1;
    229 }
    230 
    231 int GrDrawTarget::VertexSizeAndOffsetsByIdx(
    232         GrVertexLayout vertexLayout,
    233         int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords],
    234         int* colorOffset,
    235         int* coverageOffset,
    236         int* edgeOffset) {
    237     GrAssert(check_layout(vertexLayout));
    238 
    239     int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
    240                                                     sizeof(GrGpuTextVertex) :
    241                                                     sizeof(GrPoint);
    242     int size = vecSize; // position
    243 
    244     for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
    245         if (gTexCoordMasks[t] & vertexLayout) {
    246             if (NULL != texCoordOffsetsByIdx) {
    247                 texCoordOffsetsByIdx[t] = size;
    248             }
    249             size += vecSize;
    250         } else {
    251             if (NULL != texCoordOffsetsByIdx) {
    252                 texCoordOffsetsByIdx[t] = -1;
    253             }
    254         }
    255     }
    256     if (kColor_VertexLayoutBit & vertexLayout) {
    257         if (NULL != colorOffset) {
    258             *colorOffset = size;
    259         }
    260         size += sizeof(GrColor);
    261     } else {
    262         if (NULL != colorOffset) {
    263             *colorOffset = -1;
    264         }
    265     }
    266     if (kCoverage_VertexLayoutBit & vertexLayout) {
    267         if (NULL != coverageOffset) {
    268             *coverageOffset = size;
    269         }
    270         size += sizeof(GrColor);
    271     } else {
    272         if (NULL != coverageOffset) {
    273             *coverageOffset = -1;
    274         }
    275     }
    276     if (kEdge_VertexLayoutBit & vertexLayout) {
    277         if (NULL != edgeOffset) {
    278             *edgeOffset = size;
    279         }
    280         size += 4 * sizeof(GrScalar);
    281     } else {
    282         if (NULL != edgeOffset) {
    283             *edgeOffset = -1;
    284         }
    285     }
    286     return size;
    287 }
    288 
    289 int GrDrawTarget::VertexSizeAndOffsetsByStage(
    290         GrVertexLayout vertexLayout,
    291         int texCoordOffsetsByStage[GrDrawState::kNumStages],
    292         int* colorOffset,
    293         int* coverageOffset,
    294         int* edgeOffset) {
    295     GrAssert(check_layout(vertexLayout));
    296 
    297     int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords];
    298     int size = VertexSizeAndOffsetsByIdx(vertexLayout,
    299                                          (NULL == texCoordOffsetsByStage) ?
    300                                                NULL :
    301                                                texCoordOffsetsByIdx,
    302                                          colorOffset,
    303                                          coverageOffset,
    304                                          edgeOffset);
    305     if (NULL != texCoordOffsetsByStage) {
    306         for (int s = 0; s < GrDrawState::kNumStages; ++s) {
    307             int tcIdx;
    308             if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) {
    309                 texCoordOffsetsByStage[s] = 0;
    310             } else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) {
    311                 texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx];
    312             } else {
    313                 texCoordOffsetsByStage[s] = -1;
    314             }
    315         }
    316     }
    317     return size;
    318 }
    319 
    320 ////////////////////////////////////////////////////////////////////////////////
    321 
    322 bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) {
    323     GrAssert(stage < GrDrawState::kNumStages);
    324     GrAssert(check_layout(vertexLayout));
    325     return !!(gStageMasks[stage] & vertexLayout);
    326 }
    327 
    328 bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
    329                                          GrVertexLayout vertexLayout) {
    330     GrAssert(coordIndex < GrDrawState::kMaxTexCoords);
    331     GrAssert(check_layout(vertexLayout));
    332     return !!(gTexCoordMasks[coordIndex] & vertexLayout);
    333 }
    334 
    335 int GrDrawTarget::VertexTexCoordsForStage(int stage,
    336                                           GrVertexLayout vertexLayout) {
    337     GrAssert(stage < GrDrawState::kNumStages);
    338     GrAssert(check_layout(vertexLayout));
    339     int bit = vertexLayout & gStageTexCoordMasks[stage];
    340     if (bit) {
    341         // figure out which set of texture coordates is used
    342         // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
    343         // and start at bit 0.
    344         GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
    345         return (32 - Gr_clz(bit) - 1) / GrDrawState::kNumStages;
    346     }
    347     return -1;
    348 }
    349 
    350 ////////////////////////////////////////////////////////////////////////////////
    351 
    352 void GrDrawTarget::VertexLayoutUnitTest() {
    353     // Ensure that our globals mask arrays are correct
    354     GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
    355     GrVertexLayout stageMasks[GrDrawState::kNumStages];
    356     GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
    357     gen_mask_arrays(stageTexCoordMasks, stageMasks, texCoordMasks);
    358     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
    359         GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
    360         GrAssert(stageMasks[s] == gStageMasks[s]);
    361     }
    362     for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
    363         GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
    364     }
    365 
    366     // not necessarily exhaustive
    367     static bool run;
    368     if (!run) {
    369         run = true;
    370         for (int s = 0; s < GrDrawState::kNumStages; ++s) {
    371 
    372             GrAssert(!VertexUsesStage(s, 0));
    373             GrAssert(-1 == VertexStageCoordOffset(s, 0));
    374             GrVertexLayout stageMask = 0;
    375             for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
    376                 stageMask |= StageTexCoordVertexLayoutBit(s,t);
    377             }
    378             GrAssert(1 == GrDrawState::kMaxTexCoords ||
    379                      !check_layout(stageMask));
    380             GrAssert(gStageTexCoordMasks[s] == stageMask);
    381             stageMask |= StagePosAsTexCoordVertexLayoutBit(s);
    382             GrAssert(gStageMasks[s] == stageMask);
    383             GrAssert(!check_layout(stageMask));
    384         }
    385         for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
    386             GrVertexLayout tcMask = 0;
    387             GrAssert(!VertexUsesTexCoordIdx(t, 0));
    388             for (int s = 0; s < GrDrawState::kNumStages; ++s) {
    389                 tcMask |= StageTexCoordVertexLayoutBit(s,t);
    390                 GrAssert(VertexUsesStage(s, tcMask));
    391                 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
    392                 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
    393                 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
    394                 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
    395                 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
    396                     GrAssert(-1 == VertexStageCoordOffset(s2, tcMask));
    397                     GrAssert(!VertexUsesStage(s2, tcMask));
    398                     GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
    399 
    400                 #if GR_DEBUG
    401                     GrVertexLayout posAsTex = tcMask | StagePosAsTexCoordVertexLayoutBit(s2);
    402                 #endif
    403                     GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
    404                     GrAssert(VertexUsesStage(s2, posAsTex));
    405                     GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
    406                     GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
    407                     GrAssert(-1 == VertexEdgeOffset(posAsTex));
    408                 }
    409                 GrAssert(-1 == VertexEdgeOffset(tcMask));
    410                 GrAssert(-1 == VertexColorOffset(tcMask));
    411                 GrAssert(-1 == VertexCoverageOffset(tcMask));
    412             #if GR_DEBUG
    413                 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
    414             #endif
    415                 GrAssert(-1 == VertexCoverageOffset(withColor));
    416                 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
    417                 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
    418             #if GR_DEBUG
    419                 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
    420             #endif
    421                 GrAssert(-1 == VertexColorOffset(withEdge));
    422                 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
    423                 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
    424             #if GR_DEBUG
    425                 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
    426             #endif
    427                 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
    428                 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
    429                 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
    430             #if GR_DEBUG
    431                 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
    432             #endif
    433                 GrAssert(-1 == VertexColorOffset(withCoverage));
    434                 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
    435                 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
    436             #if GR_DEBUG
    437                 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
    438                                                       kColor_VertexLayoutBit;
    439             #endif
    440                 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
    441                 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
    442                 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
    443             }
    444             GrAssert(gTexCoordMasks[t] == tcMask);
    445             GrAssert(check_layout(tcMask));
    446 
    447             int stageOffsets[GrDrawState::kNumStages];
    448             int colorOffset;
    449             int edgeOffset;
    450             int coverageOffset;
    451             int size;
    452             size = VertexSizeAndOffsetsByStage(tcMask,
    453                                                stageOffsets, &colorOffset,
    454                                                &coverageOffset, &edgeOffset);
    455             GrAssert(2*sizeof(GrPoint) == size);
    456             GrAssert(-1 == colorOffset);
    457             GrAssert(-1 == coverageOffset);
    458             GrAssert(-1 == edgeOffset);
    459             for (int s = 0; s < GrDrawState::kNumStages; ++s) {
    460                 GrAssert(VertexUsesStage(s, tcMask));
    461                 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
    462                 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
    463             }
    464         }
    465     }
    466 }
    467 
    468 ////////////////////////////////////////////////////////////////////////////////
    469 
    470 #define DEBUG_INVAL_BUFFER 0xdeadcafe
    471 #define DEBUG_INVAL_START_IDX -1
    472 
    473 GrDrawTarget::GrDrawTarget() {
    474 #if GR_DEBUG
    475     VertexLayoutUnitTest();
    476 #endif
    477     GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
    478 #if GR_DEBUG
    479     geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
    480     geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
    481     geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
    482     geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
    483 #endif
    484     geoSrc.fVertexSrc = kNone_GeometrySrcType;
    485     geoSrc.fIndexSrc  = kNone_GeometrySrcType;
    486 }
    487 
    488 GrDrawTarget::~GrDrawTarget() {
    489     GrAssert(1 == fGeoSrcStateStack.count());
    490     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    491     GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
    492     GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
    493 }
    494 
    495 void GrDrawTarget::releaseGeometry() {
    496     int popCnt = fGeoSrcStateStack.count() - 1;
    497     while (popCnt) {
    498         this->popGeometrySource();
    499         --popCnt;
    500     }
    501     this->resetVertexSource();
    502     this->resetIndexSource();
    503 }
    504 
    505 void GrDrawTarget::setClip(const GrClip& clip) {
    506     clipWillBeSet(clip);
    507     fClip = clip;
    508 }
    509 
    510 const GrClip& GrDrawTarget::getClip() const {
    511     return fClip;
    512 }
    513 
    514 void GrDrawTarget::saveCurrentDrawState(SavedDrawState* state) const {
    515     state->fState.set(fCurrDrawState);
    516 }
    517 
    518 void GrDrawTarget::restoreDrawState(const SavedDrawState& state) {
    519     fCurrDrawState = *state.fState.get();
    520 }
    521 
    522 void GrDrawTarget::copyDrawState(const GrDrawTarget& srcTarget) {
    523     fCurrDrawState = srcTarget.fCurrDrawState;
    524 }
    525 
    526 bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
    527                                       int vertexCount,
    528                                       void** vertices) {
    529     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    530     bool acquired = false;
    531     if (vertexCount > 0) {
    532         GrAssert(NULL != vertices);
    533         this->releasePreviousVertexSource();
    534         geoSrc.fVertexSrc = kNone_GeometrySrcType;
    535 
    536         acquired = this->onReserveVertexSpace(vertexLayout,
    537                                               vertexCount,
    538                                               vertices);
    539     }
    540     if (acquired) {
    541         geoSrc.fVertexSrc = kReserved_GeometrySrcType;
    542         geoSrc.fVertexCount = vertexCount;
    543         geoSrc.fVertexLayout = vertexLayout;
    544     } else if (NULL != vertices) {
    545         *vertices = NULL;
    546     }
    547     return acquired;
    548 }
    549 
    550 bool GrDrawTarget::reserveIndexSpace(int indexCount,
    551                                      void** indices) {
    552     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    553     bool acquired = false;
    554     if (indexCount > 0) {
    555         GrAssert(NULL != indices);
    556         this->releasePreviousIndexSource();
    557         geoSrc.fIndexSrc = kNone_GeometrySrcType;
    558 
    559         acquired = this->onReserveIndexSpace(indexCount, indices);
    560     }
    561     if (acquired) {
    562         geoSrc.fIndexSrc = kReserved_GeometrySrcType;
    563         geoSrc.fIndexCount = indexCount;
    564     } else if (NULL != indices) {
    565         *indices = NULL;
    566     }
    567     return acquired;
    568 
    569 }
    570 
    571 bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
    572                                  int32_t* vertexCount,
    573                                  int32_t* indexCount) const {
    574     if (NULL != vertexCount) {
    575         *vertexCount = -1;
    576     }
    577     if (NULL != indexCount) {
    578         *indexCount = -1;
    579     }
    580     return false;
    581 }
    582 
    583 void GrDrawTarget::releasePreviousVertexSource() {
    584     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    585     switch (geoSrc.fVertexSrc) {
    586         case kNone_GeometrySrcType:
    587             break;
    588         case kArray_GeometrySrcType:
    589             this->releaseVertexArray();
    590             break;
    591         case kReserved_GeometrySrcType:
    592             this->releaseReservedVertexSpace();
    593             break;
    594         case kBuffer_GeometrySrcType:
    595             geoSrc.fVertexBuffer->unref();
    596 #if GR_DEBUG
    597             geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
    598 #endif
    599             break;
    600         default:
    601             GrCrash("Unknown Vertex Source Type.");
    602             break;
    603     }
    604 }
    605 
    606 void GrDrawTarget::releasePreviousIndexSource() {
    607     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    608     switch (geoSrc.fIndexSrc) {
    609         case kNone_GeometrySrcType:   // these two don't require
    610             break;
    611         case kArray_GeometrySrcType:
    612             this->releaseIndexArray();
    613             break;
    614         case kReserved_GeometrySrcType:
    615             this->releaseReservedIndexSpace();
    616             break;
    617         case kBuffer_GeometrySrcType:
    618             geoSrc.fIndexBuffer->unref();
    619 #if GR_DEBUG
    620             geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
    621 #endif
    622             break;
    623         default:
    624             GrCrash("Unknown Index Source Type.");
    625             break;
    626     }
    627 }
    628 
    629 void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
    630                                           const void* vertexArray,
    631                                           int vertexCount) {
    632     this->releasePreviousVertexSource();
    633     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    634     geoSrc.fVertexSrc = kArray_GeometrySrcType;
    635     geoSrc.fVertexLayout = vertexLayout;
    636     geoSrc.fVertexCount = vertexCount;
    637     this->onSetVertexSourceToArray(vertexArray, vertexCount);
    638 }
    639 
    640 void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
    641                                          int indexCount) {
    642     this->releasePreviousIndexSource();
    643     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    644     geoSrc.fIndexSrc = kArray_GeometrySrcType;
    645     geoSrc.fIndexCount = indexCount;
    646     this->onSetIndexSourceToArray(indexArray, indexCount);
    647 }
    648 
    649 void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
    650                                            const GrVertexBuffer* buffer) {
    651     this->releasePreviousVertexSource();
    652     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    653     geoSrc.fVertexSrc    = kBuffer_GeometrySrcType;
    654     geoSrc.fVertexBuffer = buffer;
    655     buffer->ref();
    656     geoSrc.fVertexLayout = vertexLayout;
    657 }
    658 
    659 void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
    660     this->releasePreviousIndexSource();
    661     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    662     geoSrc.fIndexSrc     = kBuffer_GeometrySrcType;
    663     geoSrc.fIndexBuffer  = buffer;
    664     buffer->ref();
    665 }
    666 
    667 void GrDrawTarget::resetVertexSource() {
    668     this->releasePreviousVertexSource();
    669     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    670     geoSrc.fVertexSrc = kNone_GeometrySrcType;
    671 }
    672 
    673 void GrDrawTarget::resetIndexSource() {
    674     this->releasePreviousIndexSource();
    675     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    676     geoSrc.fIndexSrc = kNone_GeometrySrcType;
    677 }
    678 
    679 void GrDrawTarget::pushGeometrySource() {
    680     this->geometrySourceWillPush();
    681     GeometrySrcState& newState = fGeoSrcStateStack.push_back();
    682     newState.fIndexSrc = kNone_GeometrySrcType;
    683     newState.fVertexSrc = kNone_GeometrySrcType;
    684 #if GR_DEBUG
    685     newState.fVertexCount  = ~0;
    686     newState.fVertexBuffer = (GrVertexBuffer*)~0;
    687     newState.fIndexCount   = ~0;
    688     newState.fIndexBuffer = (GrIndexBuffer*)~0;
    689 #endif
    690 }
    691 
    692 void GrDrawTarget::popGeometrySource() {
    693     const GeometrySrcState& geoSrc = this->getGeomSrc();
    694     // if popping last element then pops are unbalanced with pushes
    695     GrAssert(fGeoSrcStateStack.count() > 1);
    696 
    697     this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
    698     this->releasePreviousVertexSource();
    699     this->releasePreviousIndexSource();
    700     fGeoSrcStateStack.pop_back();
    701 }
    702 
    703 ////////////////////////////////////////////////////////////////////////////////
    704 
    705 bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
    706                              int startIndex, int vertexCount,
    707                              int indexCount) const {
    708 #if GR_DEBUG
    709     const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
    710     int maxVertex = startVertex + vertexCount;
    711     int maxValidVertex;
    712     switch (geoSrc.fVertexSrc) {
    713         case kNone_GeometrySrcType:
    714             GrCrash("Attempting to draw without vertex src.");
    715         case kReserved_GeometrySrcType: // fallthrough
    716         case kArray_GeometrySrcType:
    717             maxValidVertex = geoSrc.fVertexCount;
    718             break;
    719         case kBuffer_GeometrySrcType:
    720             maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() /
    721                              VertexSize(geoSrc.fVertexLayout);
    722             break;
    723     }
    724     if (maxVertex > maxValidVertex) {
    725         GrCrash("Drawing outside valid vertex range.");
    726     }
    727     if (indexCount > 0) {
    728         int maxIndex = startIndex + indexCount;
    729         int maxValidIndex;
    730         switch (geoSrc.fIndexSrc) {
    731             case kNone_GeometrySrcType:
    732                 GrCrash("Attempting to draw indexed geom without index src.");
    733             case kReserved_GeometrySrcType: // fallthrough
    734             case kArray_GeometrySrcType:
    735                 maxValidIndex = geoSrc.fIndexCount;
    736                 break;
    737             case kBuffer_GeometrySrcType:
    738                 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
    739                 break;
    740         }
    741         if (maxIndex > maxValidIndex) {
    742             GrCrash("Index reads outside valid index range.");
    743         }
    744     }
    745 #endif
    746     const GrDrawState& drawState = this->getDrawState();
    747     if (NULL == drawState.getRenderTarget()) {
    748         return false;
    749     }
    750     if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
    751         if (kOne_BlendCoeff != drawState.getSrcBlendCoeff() ||
    752             kZero_BlendCoeff != drawState.getDstBlendCoeff()) {
    753             return false;
    754         }
    755     }
    756     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
    757         // We don't support using unpremultiplied textures with filters (other
    758         // than nearest). Alpha-premulling is not distributive WRT to filtering.
    759         // We'd have to filter each texel before filtering. We could do this for
    760         // our custom filters but we would also have to disable bilerp and do
    761         // a custom bilerp in the shader. Until Skia itself supports unpremul
    762         // configs there is no pressure to implement this.
    763         if (this->isStageEnabled(s) &&
    764             GrPixelConfigIsUnpremultiplied(drawState.getTexture(s)->config()) &&
    765             GrSamplerState::kNearest_Filter !=
    766             drawState.getSampler(s).getFilter()) {
    767             return false;
    768         }
    769     }
    770     return true;
    771 }
    772 
    773 void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
    774                                int startIndex, int vertexCount,
    775                                int indexCount) {
    776     if (indexCount > 0 &&
    777         this->checkDraw(type, startVertex, startIndex,
    778                         vertexCount, indexCount)) {
    779         this->onDrawIndexed(type, startVertex, startIndex,
    780                             vertexCount, indexCount);
    781     }
    782 }
    783 
    784 void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
    785                                   int startVertex,
    786                                   int vertexCount) {
    787     if (vertexCount > 0 &&
    788         this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
    789         this->onDrawNonIndexed(type, startVertex, vertexCount);
    790     }
    791 }
    792 
    793 ////////////////////////////////////////////////////////////////////////////////
    794 
    795 // Some blend modes allow folding a partial coverage value into the color's
    796 // alpha channel, while others will blend incorrectly.
    797 bool GrDrawTarget::canTweakAlphaForCoverage() const {
    798     /**
    799      * The fractional coverage is f
    800      * The src and dst coeffs are Cs and Cd
    801      * The dst and src colors are S and D
    802      * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
    803      * By tweaking the source color's alpha we're replacing S with S'=fS. It's
    804      * obvious that that first term will always be ok. The second term can be
    805      * rearranged as [1-(1-Cd)f]D. By substituing in the various possbilities
    806      * for Cd we find that only 1, ISA, and ISC produce the correct depth
    807      * coeffecient in terms of S' and D.
    808      */
    809     GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
    810     return kOne_BlendCoeff == dstCoeff ||
    811            kISA_BlendCoeff == dstCoeff ||
    812            kISC_BlendCoeff == dstCoeff;
    813 }
    814 
    815 
    816 bool GrDrawTarget::srcAlphaWillBeOne() const {
    817     const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout;
    818     const GrDrawState& drawState = this->getDrawState();
    819 
    820     // Check if per-vertex or constant color may have partial alpha
    821     if ((layout & kColor_VertexLayoutBit) ||
    822         0xff != GrColorUnpackA(drawState.getColor())) {
    823         return false;
    824     }
    825     // Check if color filter could introduce an alpha
    826     // (TODO: Consider being more aggressive with regards to detecting 0xff
    827     // final alpha from color filter).
    828     if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
    829         return false;
    830     }
    831     // Check if a color stage could create a partial alpha
    832     for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) {
    833         if (StageWillBeUsed(s, layout, fCurrDrawState)) {
    834             GrAssert(NULL != drawState.getTexture(s));
    835             GrPixelConfig config = drawState.getTexture(s)->config();
    836             if (!GrPixelConfigIsOpaque(config)) {
    837                 return false;
    838             }
    839         }
    840     }
    841     return true;
    842 }
    843 
    844 GrDrawTarget::BlendOptFlags
    845 GrDrawTarget::getBlendOpts(bool forceCoverage,
    846                            GrBlendCoeff* srcCoeff,
    847                            GrBlendCoeff* dstCoeff) const {
    848 
    849     const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout;
    850     const GrDrawState& drawState = this->getDrawState();
    851 
    852     GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
    853     if (NULL == srcCoeff) {
    854         srcCoeff = &bogusSrcCoeff;
    855     }
    856     *srcCoeff = drawState.getSrcBlendCoeff();
    857 
    858     if (NULL == dstCoeff) {
    859         dstCoeff = &bogusDstCoeff;
    860     }
    861     *dstCoeff = drawState.getDstBlendCoeff();
    862 
    863     // We don't ever expect source coeffecients to reference the source
    864     GrAssert(kSA_BlendCoeff != *srcCoeff &&
    865              kISA_BlendCoeff != *srcCoeff &&
    866              kSC_BlendCoeff != *srcCoeff &&
    867              kISC_BlendCoeff != *srcCoeff);
    868     // same for dst
    869     GrAssert(kDA_BlendCoeff != *dstCoeff &&
    870              kIDA_BlendCoeff != *dstCoeff &&
    871              kDC_BlendCoeff != *dstCoeff &&
    872              kIDC_BlendCoeff != *dstCoeff);
    873 
    874     if (drawState.isColorWriteDisabled()) {
    875         *srcCoeff = kZero_BlendCoeff;
    876         *dstCoeff = kOne_BlendCoeff;
    877     }
    878 
    879     bool srcAIsOne = this->srcAlphaWillBeOne();
    880     bool dstCoeffIsOne = kOne_BlendCoeff == *dstCoeff ||
    881                          (kSA_BlendCoeff == *dstCoeff && srcAIsOne);
    882     bool dstCoeffIsZero = kZero_BlendCoeff == *dstCoeff ||
    883                          (kISA_BlendCoeff == *dstCoeff && srcAIsOne);
    884 
    885 
    886     // When coeffs are (0,1) there is no reason to draw at all, unless
    887     // stenciling is enabled. Having color writes disabled is effectively
    888     // (0,1). The same applies when coverage is known to be 0.
    889     if ((kZero_BlendCoeff == *srcCoeff && dstCoeffIsOne) ||
    890         (!(layout & kCoverage_VertexLayoutBit) &&
    891          0 == drawState.getCoverage())) {
    892         if (drawState.getStencil().doesWrite()) {
    893             return kDisableBlend_BlendOptFlag |
    894                    kEmitTransBlack_BlendOptFlag;
    895         } else {
    896             return kSkipDraw_BlendOptFlag;
    897         }
    898     }
    899 
    900     // check for coverage due to constant coverage, per-vertex coverage,
    901     // edge aa or coverage texture stage
    902     bool hasCoverage = forceCoverage ||
    903                        0xffffffff != drawState.getCoverage() ||
    904                        drawState.getNumAAEdges() > 0 ||
    905                        (layout & kCoverage_VertexLayoutBit) ||
    906                        (layout & kEdge_VertexLayoutBit);
    907     for (int s = drawState.getFirstCoverageStage();
    908          !hasCoverage && s < GrDrawState::kNumStages;
    909          ++s) {
    910         if (StageWillBeUsed(s, layout, fCurrDrawState)) {
    911             hasCoverage = true;
    912         }
    913     }
    914 
    915     // if we don't have coverage we can check whether the dst
    916     // has to read at all. If not, we'll disable blending.
    917     if (!hasCoverage) {
    918         if (dstCoeffIsZero) {
    919             if (kOne_BlendCoeff == *srcCoeff) {
    920                 // if there is no coverage and coeffs are (1,0) then we
    921                 // won't need to read the dst at all, it gets replaced by src
    922                 return kDisableBlend_BlendOptFlag;
    923             } else if (kZero_BlendCoeff == *srcCoeff) {
    924                 // if the op is "clear" then we don't need to emit a color
    925                 // or blend, just write transparent black into the dst.
    926                 *srcCoeff = kOne_BlendCoeff;
    927                 *dstCoeff = kZero_BlendCoeff;
    928                 return kDisableBlend_BlendOptFlag |
    929                        kEmitTransBlack_BlendOptFlag;
    930             }
    931         }
    932     } else {
    933         // check whether coverage can be safely rolled into alpha
    934         // of if we can skip color computation and just emit coverage
    935         if (this->canTweakAlphaForCoverage()) {
    936             return kCoverageAsAlpha_BlendOptFlag;
    937         }
    938         if (dstCoeffIsZero) {
    939             if (kZero_BlendCoeff == *srcCoeff) {
    940                 // the source color is not included in the blend
    941                 // the dst coeff is effectively zero so blend works out to:
    942                 // (c)(0)D + (1-c)D = (1-c)D.
    943                 *dstCoeff = kISA_BlendCoeff;
    944                 return  kEmitCoverage_BlendOptFlag;
    945             } else if (srcAIsOne) {
    946                 // the dst coeff is effectively zero so blend works out to:
    947                 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
    948                 // If Sa is 1 then we can replace Sa with c
    949                 // and set dst coeff to 1-Sa.
    950                 *dstCoeff = kISA_BlendCoeff;
    951                 return  kCoverageAsAlpha_BlendOptFlag;
    952             }
    953         } else if (dstCoeffIsOne) {
    954             // the dst coeff is effectively one so blend works out to:
    955             // cS + (c)(1)D + (1-c)D = cS + D.
    956             *dstCoeff = kOne_BlendCoeff;
    957             return  kCoverageAsAlpha_BlendOptFlag;
    958         }
    959     }
    960     return kNone_BlendOpt;
    961 }
    962 
    963 bool GrDrawTarget::willUseHWAALines() const {
    964     // there is a conflict between using smooth lines and our use of
    965     // premultiplied alpha. Smooth lines tweak the incoming alpha value
    966     // but not in a premul-alpha way. So we only use them when our alpha
    967     // is 0xff and tweaking the color for partial coverage is OK
    968     if (!fCaps.fHWAALineSupport ||
    969         !this->getDrawState().isHWAntialiasState()) {
    970         return false;
    971     }
    972     BlendOptFlags opts = this->getBlendOpts();
    973     return (kDisableBlend_BlendOptFlag & opts) &&
    974            (kCoverageAsAlpha_BlendOptFlag & opts);
    975 }
    976 
    977 bool GrDrawTarget::canApplyCoverage() const {
    978     // we can correctly apply coverage if a) we have dual source blending
    979     // or b) one of our blend optimizations applies.
    980     return this->getCaps().fDualSourceBlendingSupport ||
    981            kNone_BlendOpt != this->getBlendOpts(true);
    982 }
    983 
    984 bool GrDrawTarget::drawWillReadDst() const {
    985     return SkToBool((kDisableBlend_BlendOptFlag | kSkipDraw_BlendOptFlag) &
    986                     this->getBlendOpts());
    987 }
    988 
    989 
    990 ////////////////////////////////////////////////////////////////////////////////
    991 
    992 void GrDrawTarget::drawRect(const GrRect& rect,
    993                             const GrMatrix* matrix,
    994                             StageMask stageMask,
    995                             const GrRect* srcRects[],
    996                             const GrMatrix* srcMatrices[]) {
    997     GrVertexLayout layout = GetRectVertexLayout(stageMask, srcRects);
    998 
    999     AutoReleaseGeometry geo(this, layout, 4, 0);
   1000     if (!geo.succeeded()) {
   1001         GrPrintf("Failed to get space for vertices!\n");
   1002         return;
   1003     }
   1004 
   1005     SetRectVertices(rect, matrix, srcRects,
   1006                     srcMatrices, layout, geo.vertices());
   1007 
   1008     drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
   1009 }
   1010 
   1011 GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask,
   1012                                                  const GrRect* srcRects[]) {
   1013     GrVertexLayout layout = 0;
   1014 
   1015     for (int i = 0; i < GrDrawState::kNumStages; ++i) {
   1016         int numTC = 0;
   1017         if (stageMask & (1 << i)) {
   1018             if (NULL != srcRects && NULL != srcRects[i]) {
   1019                 layout |= StageTexCoordVertexLayoutBit(i, numTC);
   1020                 ++numTC;
   1021             } else {
   1022                 layout |= StagePosAsTexCoordVertexLayoutBit(i);
   1023             }
   1024         }
   1025     }
   1026     return layout;
   1027 }
   1028 
   1029 void GrDrawTarget::clipWillBeSet(const GrClip& clip) {
   1030 }
   1031 
   1032 void GrDrawTarget::SetRectVertices(const GrRect& rect,
   1033                                    const GrMatrix* matrix,
   1034                                    const GrRect* srcRects[],
   1035                                    const GrMatrix* srcMatrices[],
   1036                                    GrVertexLayout layout,
   1037                                    void* vertices) {
   1038 #if GR_DEBUG
   1039     // check that the layout and srcRects agree
   1040     for (int i = 0; i < GrDrawState::kNumStages; ++i) {
   1041         if (VertexTexCoordsForStage(i, layout) >= 0) {
   1042             GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
   1043         } else {
   1044             GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
   1045         }
   1046     }
   1047 #endif
   1048 
   1049     int stageOffsets[GrDrawState::kNumStages];
   1050     int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
   1051                                             NULL, NULL, NULL);
   1052 
   1053     GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
   1054                                             rect.fRight, rect.fBottom,
   1055                                             vsize);
   1056     if (NULL != matrix) {
   1057         matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
   1058     }
   1059 
   1060     for (int i = 0; i < GrDrawState::kNumStages; ++i) {
   1061         if (stageOffsets[i] > 0) {
   1062             GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
   1063                                                 stageOffsets[i]);
   1064             coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
   1065                                srcRects[i]->fRight, srcRects[i]->fBottom,
   1066                                vsize);
   1067             if (NULL != srcMatrices && NULL != srcMatrices[i]) {
   1068                 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
   1069             }
   1070         }
   1071     }
   1072 }
   1073 
   1074 ////////////////////////////////////////////////////////////////////////////////
   1075 
   1076 GrDrawTarget::AutoStateRestore::AutoStateRestore() {
   1077     fDrawTarget = NULL;
   1078 }
   1079 
   1080 GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target) {
   1081     fDrawTarget = target;
   1082     if (NULL != fDrawTarget) {
   1083         fDrawTarget->saveCurrentDrawState(&fDrawState);
   1084     }
   1085 }
   1086 
   1087 GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
   1088     if (NULL != fDrawTarget) {
   1089         fDrawTarget->restoreDrawState(fDrawState);
   1090     }
   1091 }
   1092 
   1093 void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target) {
   1094     if (target != fDrawTarget) {
   1095         if (NULL != fDrawTarget) {
   1096             fDrawTarget->restoreDrawState(fDrawState);
   1097         }
   1098         if (NULL != target) {
   1099             target->saveCurrentDrawState(&fDrawState);
   1100         }
   1101         fDrawTarget = target;
   1102     }
   1103 }
   1104 
   1105 ////////////////////////////////////////////////////////////////////////////////
   1106 
   1107 GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(
   1108                                             GrDrawTarget* target,
   1109                                             GrDrawState::StageMask stageMask) {
   1110     GrAssert(NULL != target);
   1111     GrDrawState* drawState = target->drawState();
   1112 
   1113     fDrawTarget = target;
   1114     fViewMatrix = drawState->getViewMatrix();
   1115     fStageMask = stageMask;
   1116     if (fStageMask) {
   1117         GrMatrix invVM;
   1118         if (fViewMatrix.invert(&invVM)) {
   1119             for (int s = 0; s < GrDrawState::kNumStages; ++s) {
   1120                 if (fStageMask & (1 << s)) {
   1121                     fSamplerMatrices[s] = drawState->getSampler(s).getMatrix();
   1122                 }
   1123             }
   1124             drawState->preConcatSamplerMatrices(fStageMask, invVM);
   1125         } else {
   1126             // sad trombone sound
   1127             fStageMask = 0;
   1128         }
   1129     }
   1130     drawState->setViewMatrix(GrMatrix::I());
   1131 }
   1132 
   1133 GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() {
   1134     GrDrawState* drawState = fDrawTarget->drawState();
   1135     drawState->setViewMatrix(fViewMatrix);
   1136     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
   1137         if (fStageMask & (1 << s)) {
   1138             *drawState->sampler(s)->matrix() = fSamplerMatrices[s];
   1139         }
   1140     }
   1141 }
   1142 
   1143 ////////////////////////////////////////////////////////////////////////////////
   1144 
   1145 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
   1146                                          GrDrawTarget*  target,
   1147                                          GrVertexLayout vertexLayout,
   1148                                          int vertexCount,
   1149                                          int indexCount) {
   1150     fTarget = NULL;
   1151     this->set(target, vertexLayout, vertexCount, indexCount);
   1152 }
   1153 
   1154 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
   1155     fTarget = NULL;
   1156 }
   1157 
   1158 GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
   1159     this->reset();
   1160 }
   1161 
   1162 bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget*  target,
   1163                                             GrVertexLayout vertexLayout,
   1164                                             int vertexCount,
   1165                                             int indexCount) {
   1166     this->reset();
   1167     fTarget = target;
   1168     bool success = true;
   1169     if (NULL != fTarget) {
   1170         fTarget = target;
   1171         if (vertexCount > 0) {
   1172             success = target->reserveVertexSpace(vertexLayout,
   1173                                                  vertexCount,
   1174                                                  &fVertices);
   1175             if (!success) {
   1176                 this->reset();
   1177             }
   1178         }
   1179         if (success && indexCount > 0) {
   1180             success = target->reserveIndexSpace(indexCount, &fIndices);
   1181             if (!success) {
   1182                 this->reset();
   1183             }
   1184         }
   1185     }
   1186     GrAssert(success == (NULL != fTarget));
   1187     return success;
   1188 }
   1189 
   1190 void GrDrawTarget::AutoReleaseGeometry::reset() {
   1191     if (NULL != fTarget) {
   1192         if (NULL != fVertices) {
   1193             fTarget->resetVertexSource();
   1194         }
   1195         if (NULL != fIndices) {
   1196             fTarget->resetIndexSource();
   1197         }
   1198         fTarget = NULL;
   1199     }
   1200     fVertices = NULL;
   1201     fIndices = NULL;
   1202 }
   1203 
   1204 void GrDrawTarget::Caps::print() const {
   1205     static const char* gNY[] = {"NO", "YES"};
   1206     GrPrintf("8 Bit Palette Support       : %s\n", gNY[f8BitPaletteSupport]);
   1207     GrPrintf("NPOT Texture Tile Support   : %s\n", gNY[fNPOTTextureTileSupport]);
   1208     GrPrintf("Two Sided Stencil Support   : %s\n", gNY[fTwoSidedStencilSupport]);
   1209     GrPrintf("Stencil Wrap Ops  Support   : %s\n", gNY[fStencilWrapOpsSupport]);
   1210     GrPrintf("HW AA Lines Support         : %s\n", gNY[fHWAALineSupport]);
   1211     GrPrintf("Shader Derivative Support   : %s\n", gNY[fShaderDerivativeSupport]);
   1212     GrPrintf("Geometry Shader Support     : %s\n", gNY[fGeometryShaderSupport]);
   1213     GrPrintf("FSAA Support                : %s\n", gNY[fFSAASupport]);
   1214     GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
   1215     GrPrintf("Buffer Lock Support         : %s\n", gNY[fBufferLockSupport]);
   1216     GrPrintf("Max Texture Size            : %d\n", fMaxTextureSize);
   1217     GrPrintf("Max Render Target Size      : %d\n", fMaxRenderTargetSize);
   1218 }
   1219 
   1220