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