GrDrawTarget.cpp revision 2b446734cfa8201e5478648988de86b646cb9544
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 "GrRenderTarget.h"
13#include "GrTexture.h"
14#include "GrVertexBuffer.h"
15
16#include "SkStrokeRec.h"
17
18SK_DEFINE_INST_COUNT(GrDrawTarget)
19
20////////////////////////////////////////////////////////////////////////////////
21
22GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) {
23    fPrimitiveType  = di.fPrimitiveType;
24    fStartVertex    = di.fStartVertex;
25    fStartIndex     = di.fStartIndex;
26    fVertexCount    = di.fVertexCount;
27    fIndexCount     = di.fIndexCount;
28
29    fInstanceCount          = di.fInstanceCount;
30    fVerticesPerInstance    = di.fVerticesPerInstance;
31    fIndicesPerInstance     = di.fIndicesPerInstance;
32
33    if (NULL != di.fDevBounds) {
34        GrAssert(di.fDevBounds == &di.fDevBoundsStorage);
35        fDevBoundsStorage = di.fDevBoundsStorage;
36        fDevBounds = &fDevBoundsStorage;
37    } else {
38        fDevBounds = NULL;
39    }
40    return *this;
41}
42
43#if GR_DEBUG
44bool GrDrawTarget::DrawInfo::isInstanced() const {
45    if (fInstanceCount > 0) {
46        GrAssert(0 == fIndexCount % fIndicesPerInstance);
47        GrAssert(0 == fVertexCount % fVerticesPerInstance);
48        GrAssert(fIndexCount / fIndicesPerInstance == fInstanceCount);
49        GrAssert(fVertexCount / fVerticesPerInstance == fInstanceCount);
50        // there is no way to specify a non-zero start index to drawIndexedInstances().
51        GrAssert(0 == fStartIndex);
52        return true;
53    } else {
54        GrAssert(!fVerticesPerInstance);
55        GrAssert(!fIndicesPerInstance);
56        return false;
57    }
58}
59#endif
60
61void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) {
62    GrAssert(this->isInstanced());
63    GrAssert(instanceOffset + fInstanceCount >= 0);
64    fInstanceCount += instanceOffset;
65    fVertexCount = fVerticesPerInstance * fInstanceCount;
66    fIndexCount = fIndicesPerInstance * fInstanceCount;
67}
68
69void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
70    fStartVertex += vertexOffset;
71    GrAssert(fStartVertex >= 0);
72}
73
74void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
75    GrAssert(this->isIndexed());
76    fStartIndex += indexOffset;
77    GrAssert(fStartIndex >= 0);
78}
79
80////////////////////////////////////////////////////////////////////////////////
81
82#define DEBUG_INVAL_BUFFER 0xdeadcafe
83#define DEBUG_INVAL_START_IDX -1
84
85GrDrawTarget::GrDrawTarget() : fClip(NULL) {
86    fDrawState = &fDefaultDrawState;
87    // We assume that fDrawState always owns a ref to the object it points at.
88    fDefaultDrawState.ref();
89    GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
90#if GR_DEBUG
91    geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
92    geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
93    geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
94    geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
95#endif
96    geoSrc.fVertexSrc = kNone_GeometrySrcType;
97    geoSrc.fIndexSrc  = kNone_GeometrySrcType;
98}
99
100GrDrawTarget::~GrDrawTarget() {
101    GrAssert(1 == fGeoSrcStateStack.count());
102    SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
103    GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
104    GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
105    fDrawState->unref();
106}
107
108void GrDrawTarget::releaseGeometry() {
109    int popCnt = fGeoSrcStateStack.count() - 1;
110    while (popCnt) {
111        this->popGeometrySource();
112        --popCnt;
113    }
114    this->resetVertexSource();
115    this->resetIndexSource();
116}
117
118void GrDrawTarget::setClip(const GrClipData* clip) {
119    clipWillBeSet(clip);
120    fClip = clip;
121}
122
123const GrClipData* GrDrawTarget::getClip() const {
124    return fClip;
125}
126
127void GrDrawTarget::setDrawState(GrDrawState*  drawState) {
128    GrAssert(NULL != fDrawState);
129    if (NULL == drawState) {
130        drawState = &fDefaultDrawState;
131    }
132    if (fDrawState != drawState) {
133        fDrawState->unref();
134        drawState->ref();
135        fDrawState = drawState;
136    }
137}
138
139bool GrDrawTarget::reserveVertexSpace(size_t vertexSize,
140                                      int vertexCount,
141                                      void** vertices) {
142    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
143    bool acquired = false;
144    if (vertexCount > 0) {
145        GrAssert(NULL != vertices);
146        this->releasePreviousVertexSource();
147        geoSrc.fVertexSrc = kNone_GeometrySrcType;
148
149        acquired = this->onReserveVertexSpace(vertexSize,
150                                              vertexCount,
151                                              vertices);
152    }
153    if (acquired) {
154        geoSrc.fVertexSrc = kReserved_GeometrySrcType;
155        geoSrc.fVertexCount = vertexCount;
156        geoSrc.fVertexSize = vertexSize;
157    } else if (NULL != vertices) {
158        *vertices = NULL;
159    }
160    return acquired;
161}
162
163bool GrDrawTarget::reserveIndexSpace(int indexCount,
164                                     void** indices) {
165    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
166    bool acquired = false;
167    if (indexCount > 0) {
168        GrAssert(NULL != indices);
169        this->releasePreviousIndexSource();
170        geoSrc.fIndexSrc = kNone_GeometrySrcType;
171
172        acquired = this->onReserveIndexSpace(indexCount, indices);
173    }
174    if (acquired) {
175        geoSrc.fIndexSrc = kReserved_GeometrySrcType;
176        geoSrc.fIndexCount = indexCount;
177    } else if (NULL != indices) {
178        *indices = NULL;
179    }
180    return acquired;
181
182}
183
184bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount,
185                                              int indexCount,
186                                              void** vertices,
187                                              void** indices) {
188    size_t vertexSize = this->drawState()->getVertexSize();
189    this->willReserveVertexAndIndexSpace(vertexCount, indexCount);
190    if (vertexCount) {
191        if (!this->reserveVertexSpace(vertexSize, vertexCount, vertices)) {
192            if (indexCount) {
193                this->resetIndexSource();
194            }
195            return false;
196        }
197    }
198    if (indexCount) {
199        if (!this->reserveIndexSpace(indexCount, indices)) {
200            if (vertexCount) {
201                this->resetVertexSource();
202            }
203            return false;
204        }
205    }
206    return true;
207}
208
209bool GrDrawTarget::geometryHints(int32_t* vertexCount,
210                                 int32_t* indexCount) const {
211    if (NULL != vertexCount) {
212        *vertexCount = -1;
213    }
214    if (NULL != indexCount) {
215        *indexCount = -1;
216    }
217    return false;
218}
219
220void GrDrawTarget::releasePreviousVertexSource() {
221    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
222    switch (geoSrc.fVertexSrc) {
223        case kNone_GeometrySrcType:
224            break;
225        case kArray_GeometrySrcType:
226            this->releaseVertexArray();
227            break;
228        case kReserved_GeometrySrcType:
229            this->releaseReservedVertexSpace();
230            break;
231        case kBuffer_GeometrySrcType:
232            geoSrc.fVertexBuffer->unref();
233#if GR_DEBUG
234            geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
235#endif
236            break;
237        default:
238            GrCrash("Unknown Vertex Source Type.");
239            break;
240    }
241}
242
243void GrDrawTarget::releasePreviousIndexSource() {
244    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
245    switch (geoSrc.fIndexSrc) {
246        case kNone_GeometrySrcType:   // these two don't require
247            break;
248        case kArray_GeometrySrcType:
249            this->releaseIndexArray();
250            break;
251        case kReserved_GeometrySrcType:
252            this->releaseReservedIndexSpace();
253            break;
254        case kBuffer_GeometrySrcType:
255            geoSrc.fIndexBuffer->unref();
256#if GR_DEBUG
257            geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
258#endif
259            break;
260        default:
261            GrCrash("Unknown Index Source Type.");
262            break;
263    }
264}
265
266void GrDrawTarget::setVertexSourceToArray(const void* vertexArray,
267                                          int vertexCount) {
268    this->releasePreviousVertexSource();
269    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
270    geoSrc.fVertexSrc = kArray_GeometrySrcType;
271    geoSrc.fVertexSize = this->drawState()->getVertexSize();
272    geoSrc.fVertexCount = vertexCount;
273    this->onSetVertexSourceToArray(vertexArray, vertexCount);
274}
275
276void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
277                                         int indexCount) {
278    this->releasePreviousIndexSource();
279    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
280    geoSrc.fIndexSrc = kArray_GeometrySrcType;
281    geoSrc.fIndexCount = indexCount;
282    this->onSetIndexSourceToArray(indexArray, indexCount);
283}
284
285void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer) {
286    this->releasePreviousVertexSource();
287    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
288    geoSrc.fVertexSrc    = kBuffer_GeometrySrcType;
289    geoSrc.fVertexBuffer = buffer;
290    buffer->ref();
291    geoSrc.fVertexSize = this->drawState()->getVertexSize();
292}
293
294void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
295    this->releasePreviousIndexSource();
296    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
297    geoSrc.fIndexSrc     = kBuffer_GeometrySrcType;
298    geoSrc.fIndexBuffer  = buffer;
299    buffer->ref();
300}
301
302void GrDrawTarget::resetVertexSource() {
303    this->releasePreviousVertexSource();
304    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
305    geoSrc.fVertexSrc = kNone_GeometrySrcType;
306}
307
308void GrDrawTarget::resetIndexSource() {
309    this->releasePreviousIndexSource();
310    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
311    geoSrc.fIndexSrc = kNone_GeometrySrcType;
312}
313
314void GrDrawTarget::pushGeometrySource() {
315    this->geometrySourceWillPush();
316    GeometrySrcState& newState = fGeoSrcStateStack.push_back();
317    newState.fIndexSrc = kNone_GeometrySrcType;
318    newState.fVertexSrc = kNone_GeometrySrcType;
319#if GR_DEBUG
320    newState.fVertexCount  = ~0;
321    newState.fVertexBuffer = (GrVertexBuffer*)~0;
322    newState.fIndexCount   = ~0;
323    newState.fIndexBuffer = (GrIndexBuffer*)~0;
324#endif
325}
326
327void GrDrawTarget::popGeometrySource() {
328    // if popping last element then pops are unbalanced with pushes
329    GrAssert(fGeoSrcStateStack.count() > 1);
330
331    this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
332    this->releasePreviousVertexSource();
333    this->releasePreviousIndexSource();
334    fGeoSrcStateStack.pop_back();
335}
336
337////////////////////////////////////////////////////////////////////////////////
338
339bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
340                             int startIndex, int vertexCount,
341                             int indexCount) const {
342    const GrDrawState& drawState = this->getDrawState();
343#if GR_DEBUG
344    const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
345    int maxVertex = startVertex + vertexCount;
346    int maxValidVertex;
347    switch (geoSrc.fVertexSrc) {
348        case kNone_GeometrySrcType:
349            GrCrash("Attempting to draw without vertex src.");
350        case kReserved_GeometrySrcType: // fallthrough
351        case kArray_GeometrySrcType:
352            maxValidVertex = geoSrc.fVertexCount;
353            break;
354        case kBuffer_GeometrySrcType:
355            maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / geoSrc.fVertexSize;
356            break;
357    }
358    if (maxVertex > maxValidVertex) {
359        GrCrash("Drawing outside valid vertex range.");
360    }
361    if (indexCount > 0) {
362        int maxIndex = startIndex + indexCount;
363        int maxValidIndex;
364        switch (geoSrc.fIndexSrc) {
365            case kNone_GeometrySrcType:
366                GrCrash("Attempting to draw indexed geom without index src.");
367            case kReserved_GeometrySrcType: // fallthrough
368            case kArray_GeometrySrcType:
369                maxValidIndex = geoSrc.fIndexCount;
370                break;
371            case kBuffer_GeometrySrcType:
372                maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
373                break;
374        }
375        if (maxIndex > maxValidIndex) {
376            GrCrash("Index reads outside valid index range.");
377        }
378    }
379
380    GrAssert(NULL != drawState.getRenderTarget());
381    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
382        if (drawState.isStageEnabled(s)) {
383            const GrEffectRef& effect = *drawState.getStage(s).getEffect();
384            int numTextures = effect->numTextures();
385            for (int t = 0; t < numTextures; ++t) {
386                GrTexture* texture = effect->texture(t);
387                GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
388            }
389        }
390    }
391#endif
392    if (NULL == drawState.getRenderTarget()) {
393        return false;
394    }
395    return true;
396}
397
398void GrDrawTarget::drawIndexed(GrPrimitiveType type,
399                               int startVertex,
400                               int startIndex,
401                               int vertexCount,
402                               int indexCount,
403                               const SkRect* devBounds) {
404    if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
405        DrawInfo info;
406        info.fPrimitiveType = type;
407        info.fStartVertex   = startVertex;
408        info.fStartIndex    = startIndex;
409        info.fVertexCount   = vertexCount;
410        info.fIndexCount    = indexCount;
411
412        info.fInstanceCount         = 0;
413        info.fVerticesPerInstance   = 0;
414        info.fIndicesPerInstance    = 0;
415
416        if (NULL != devBounds) {
417            info.setDevBounds(*devBounds);
418        }
419        this->onDraw(info);
420    }
421}
422
423void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
424                                  int startVertex,
425                                  int vertexCount,
426                                  const SkRect* devBounds) {
427    if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
428        DrawInfo info;
429        info.fPrimitiveType = type;
430        info.fStartVertex   = startVertex;
431        info.fStartIndex    = 0;
432        info.fVertexCount   = vertexCount;
433        info.fIndexCount    = 0;
434
435        info.fInstanceCount         = 0;
436        info.fVerticesPerInstance   = 0;
437        info.fIndicesPerInstance    = 0;
438
439        if (NULL != devBounds) {
440            info.setDevBounds(*devBounds);
441        }
442        this->onDraw(info);
443    }
444}
445
446void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
447    // TODO: extract portions of checkDraw that are relevant to path stenciling.
448    GrAssert(NULL != path);
449    GrAssert(fCaps.pathStencilingSupport());
450    GrAssert(!stroke.isHairlineStyle());
451    GrAssert(!SkPath::IsInverseFillType(fill));
452    this->onStencilPath(path, stroke, fill);
453}
454
455////////////////////////////////////////////////////////////////////////////////
456
457bool GrDrawTarget::willUseHWAALines() const {
458    // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth
459    // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when
460    // our alpha is 0xff and tweaking the color for partial coverage is OK
461    if (!fCaps.hwAALineSupport() ||
462        !this->getDrawState().isHWAntialiasState()) {
463        return false;
464    }
465    GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts();
466    return (GrDrawState::kDisableBlend_BlendOptFlag & opts) &&
467           (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts);
468}
469
470bool GrDrawTarget::canApplyCoverage() const {
471    // we can correctly apply coverage if a) we have dual source blending
472    // or b) one of our blend optimizations applies.
473    return this->getCaps().dualSourceBlendingSupport() ||
474           GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true);
475}
476
477////////////////////////////////////////////////////////////////////////////////
478
479void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
480                                        int instanceCount,
481                                        int verticesPerInstance,
482                                        int indicesPerInstance,
483                                        const SkRect* devBounds) {
484    if (!verticesPerInstance || !indicesPerInstance) {
485        return;
486    }
487
488    int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
489    if (!maxInstancesPerDraw) {
490        return;
491    }
492
493    DrawInfo info;
494    info.fPrimitiveType = type;
495    info.fStartIndex = 0;
496    info.fStartVertex = 0;
497    info.fIndicesPerInstance = indicesPerInstance;
498    info.fVerticesPerInstance = verticesPerInstance;
499
500    // Set the same bounds for all the draws.
501    if (NULL != devBounds) {
502        info.setDevBounds(*devBounds);
503    }
504
505    while (instanceCount) {
506        info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
507        info.fVertexCount = info.fInstanceCount * verticesPerInstance;
508        info.fIndexCount = info.fInstanceCount * indicesPerInstance;
509
510        if (this->checkDraw(type,
511                            info.fStartVertex,
512                            info.fStartIndex,
513                            info.fVertexCount,
514                            info.fIndexCount)) {
515            this->onDraw(info);
516        }
517        info.fStartVertex += info.fVertexCount;
518        instanceCount -= info.fInstanceCount;
519    }
520}
521
522////////////////////////////////////////////////////////////////////////////////
523
524void GrDrawTarget::drawRect(const GrRect& rect,
525                            const SkMatrix* matrix,
526                            const GrRect* srcRects[],
527                            const SkMatrix* srcMatrices[]) {
528    GrVertexLayout layout = 0;
529    uint32_t explicitCoordMask = 0;
530
531    if (NULL != srcRects) {
532        for (int s = 0; s < GrDrawState::kNumStages; ++s) {
533            int numTC = 0;
534            if (NULL != srcRects[s]) {
535                layout |= GrDrawState::StageTexCoordVertexLayoutBit(s, numTC);
536                explicitCoordMask |= (1 << s);
537                ++numTC;
538            }
539        }
540    }
541
542    GrDrawState::AutoViewMatrixRestore avmr;
543    if (NULL != matrix) {
544        avmr.set(this->drawState(), *matrix, explicitCoordMask);
545    }
546
547    this->drawState()->setVertexLayout(layout);
548    AutoReleaseGeometry geo(this, 4, 0);
549    if (!geo.succeeded()) {
550        GrPrintf("Failed to get space for vertices!\n");
551        return;
552    }
553
554    int stageOffsets[GrDrawState::kNumStages];
555    int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets,  NULL, NULL, NULL);
556    geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
557
558    for (int i = 0; i < GrDrawState::kNumStages; ++i) {
559        if (explicitCoordMask & (1 << i)) {
560            GrAssert(0 != stageOffsets[i]);
561            GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
562                                                stageOffsets[i]);
563            coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
564                               srcRects[i]->fRight, srcRects[i]->fBottom,
565                               vsize);
566            if (NULL != srcMatrices && NULL != srcMatrices[i]) {
567                srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
568            }
569        } else {
570            GrAssert(0 == stageOffsets[i]);
571        }
572    }
573
574    this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
575}
576
577void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
578}
579
580////////////////////////////////////////////////////////////////////////////////
581
582GrDrawTarget::AutoStateRestore::AutoStateRestore() {
583    fDrawTarget = NULL;
584}
585
586GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
587                                                 ASRInit init) {
588    fDrawTarget = NULL;
589    this->set(target, init);
590}
591
592GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
593    if (NULL != fDrawTarget) {
594        fDrawTarget->setDrawState(fSavedState);
595        fSavedState->unref();
596    }
597}
598
599void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
600    GrAssert(NULL == fDrawTarget);
601    fDrawTarget = target;
602    fSavedState = target->drawState();
603    GrAssert(fSavedState);
604    fSavedState->ref();
605    if (kReset_ASRInit == init) {
606        // calls the default cons
607        fTempState.init();
608    } else {
609        GrAssert(kPreserve_ASRInit == init);
610        // calls the copy cons
611        fTempState.set(*fSavedState);
612    }
613    target->setDrawState(fTempState.get());
614}
615
616////////////////////////////////////////////////////////////////////////////////
617
618GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
619                                         GrDrawTarget*  target,
620                                         int vertexCount,
621                                         int indexCount) {
622    fTarget = NULL;
623    this->set(target, vertexCount, indexCount);
624}
625
626GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
627    fTarget = NULL;
628}
629
630GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
631    this->reset();
632}
633
634bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget*  target,
635                                            int vertexCount,
636                                            int indexCount) {
637    this->reset();
638    fTarget = target;
639    bool success = true;
640    if (NULL != fTarget) {
641        fTarget = target;
642        success = target->reserveVertexAndIndexSpace(vertexCount,
643                                                     indexCount,
644                                                     &fVertices,
645                                                     &fIndices);
646        if (!success) {
647            fTarget = NULL;
648            this->reset();
649        }
650    }
651    GrAssert(success == (NULL != fTarget));
652    return success;
653}
654
655void GrDrawTarget::AutoReleaseGeometry::reset() {
656    if (NULL != fTarget) {
657        if (NULL != fVertices) {
658            fTarget->resetVertexSource();
659        }
660        if (NULL != fIndices) {
661            fTarget->resetIndexSource();
662        }
663        fTarget = NULL;
664    }
665    fVertices = NULL;
666    fIndices = NULL;
667}
668
669GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
670    fTarget = target;
671    fClip = fTarget->getClip();
672    fStack.init();
673    fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
674    fReplacementClip.fClipStack = fStack.get();
675    target->setClip(&fReplacementClip);
676}
677
678void GrDrawTarget::Caps::print() const {
679    static const char* gNY[] = {"NO", "YES"};
680    GrPrintf("8 Bit Palette Support       : %s\n", gNY[fInternals.f8BitPaletteSupport]);
681    GrPrintf("NPOT Texture Tile Support   : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
682    GrPrintf("Two Sided Stencil Support   : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
683    GrPrintf("Stencil Wrap Ops  Support   : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
684    GrPrintf("HW AA Lines Support         : %s\n", gNY[fInternals.fHWAALineSupport]);
685    GrPrintf("Shader Derivative Support   : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
686    GrPrintf("Geometry Shader Support     : %s\n", gNY[fInternals.fGeometryShaderSupport]);
687    GrPrintf("FSAA Support                : %s\n", gNY[fInternals.fFSAASupport]);
688    GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
689    GrPrintf("Buffer Lock Support         : %s\n", gNY[fInternals.fBufferLockSupport]);
690    GrPrintf("Path Stenciling Support     : %s\n", gNY[fInternals.fPathStencilingSupport]);
691    GrPrintf("Max Texture Size            : %d\n", fInternals.fMaxTextureSize);
692    GrPrintf("Max Render Target Size      : %d\n", fInternals.fMaxRenderTargetSize);
693}
694