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