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