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