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