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