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