GrDrawTarget.cpp revision 009dfe2cabbf16840748bf7f3b565432b65641d0
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(GrVertexLayout vertexLayout,
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(GrDrawState::VertexSize(vertexLayout),
150                                              vertexCount,
151                                              vertices);
152    }
153    if (acquired) {
154        geoSrc.fVertexSrc = kReserved_GeometrySrcType;
155        geoSrc.fVertexCount = vertexCount;
156        geoSrc.fVertexLayout = vertexLayout;
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(GrVertexLayout vertexLayout,
185                                              int vertexCount,
186                                              int indexCount,
187                                              void** vertices,
188                                              void** indices) {
189    this->willReserveVertexAndIndexSpace(GrDrawState::VertexSize(vertexLayout), vertexCount, indexCount);
190    if (vertexCount) {
191        if (!this->reserveVertexSpace(vertexLayout, 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(size_t vertexSize,
210                                 int32_t* vertexCount,
211                                 int32_t* indexCount) const {
212    if (NULL != vertexCount) {
213        *vertexCount = -1;
214    }
215    if (NULL != indexCount) {
216        *indexCount = -1;
217    }
218    return false;
219}
220
221void GrDrawTarget::releasePreviousVertexSource() {
222    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
223    switch (geoSrc.fVertexSrc) {
224        case kNone_GeometrySrcType:
225            break;
226        case kArray_GeometrySrcType:
227            this->releaseVertexArray();
228            break;
229        case kReserved_GeometrySrcType:
230            this->releaseReservedVertexSpace();
231            break;
232        case kBuffer_GeometrySrcType:
233            geoSrc.fVertexBuffer->unref();
234#if GR_DEBUG
235            geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
236#endif
237            break;
238        default:
239            GrCrash("Unknown Vertex Source Type.");
240            break;
241    }
242}
243
244void GrDrawTarget::releasePreviousIndexSource() {
245    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
246    switch (geoSrc.fIndexSrc) {
247        case kNone_GeometrySrcType:   // these two don't require
248            break;
249        case kArray_GeometrySrcType:
250            this->releaseIndexArray();
251            break;
252        case kReserved_GeometrySrcType:
253            this->releaseReservedIndexSpace();
254            break;
255        case kBuffer_GeometrySrcType:
256            geoSrc.fIndexBuffer->unref();
257#if GR_DEBUG
258            geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
259#endif
260            break;
261        default:
262            GrCrash("Unknown Index Source Type.");
263            break;
264    }
265}
266
267void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
268                                          const void* vertexArray,
269                                          int vertexCount) {
270    this->releasePreviousVertexSource();
271    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
272    geoSrc.fVertexSrc = kArray_GeometrySrcType;
273    geoSrc.fVertexLayout = vertexLayout;
274    geoSrc.fVertexCount = vertexCount;
275    this->onSetVertexSourceToArray(vertexArray, vertexCount);
276}
277
278void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
279                                         int indexCount) {
280    this->releasePreviousIndexSource();
281    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
282    geoSrc.fIndexSrc = kArray_GeometrySrcType;
283    geoSrc.fIndexCount = indexCount;
284    this->onSetIndexSourceToArray(indexArray, indexCount);
285}
286
287void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
288                                           const GrVertexBuffer* buffer) {
289    this->releasePreviousVertexSource();
290    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
291    geoSrc.fVertexSrc    = kBuffer_GeometrySrcType;
292    geoSrc.fVertexBuffer = buffer;
293    buffer->ref();
294    geoSrc.fVertexLayout = vertexLayout;
295}
296
297void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
298    this->releasePreviousIndexSource();
299    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
300    geoSrc.fIndexSrc     = kBuffer_GeometrySrcType;
301    geoSrc.fIndexBuffer  = buffer;
302    buffer->ref();
303}
304
305void GrDrawTarget::resetVertexSource() {
306    this->releasePreviousVertexSource();
307    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
308    geoSrc.fVertexSrc = kNone_GeometrySrcType;
309}
310
311void GrDrawTarget::resetIndexSource() {
312    this->releasePreviousIndexSource();
313    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
314    geoSrc.fIndexSrc = kNone_GeometrySrcType;
315}
316
317void GrDrawTarget::pushGeometrySource() {
318    this->geometrySourceWillPush();
319    GeometrySrcState& newState = fGeoSrcStateStack.push_back();
320    newState.fIndexSrc = kNone_GeometrySrcType;
321    newState.fVertexSrc = kNone_GeometrySrcType;
322#if GR_DEBUG
323    newState.fVertexCount  = ~0;
324    newState.fVertexBuffer = (GrVertexBuffer*)~0;
325    newState.fIndexCount   = ~0;
326    newState.fIndexBuffer = (GrIndexBuffer*)~0;
327#endif
328}
329
330void GrDrawTarget::popGeometrySource() {
331    // if popping last element then pops are unbalanced with pushes
332    GrAssert(fGeoSrcStateStack.count() > 1);
333
334    this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
335    this->releasePreviousVertexSource();
336    this->releasePreviousIndexSource();
337    fGeoSrcStateStack.pop_back();
338}
339
340////////////////////////////////////////////////////////////////////////////////
341
342bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
343                             int startIndex, int vertexCount,
344                             int indexCount) const {
345    const GrDrawState& drawState = this->getDrawState();
346#if GR_DEBUG
347    const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
348    int maxVertex = startVertex + vertexCount;
349    int maxValidVertex;
350    switch (geoSrc.fVertexSrc) {
351        case kNone_GeometrySrcType:
352            GrCrash("Attempting to draw without vertex src.");
353        case kReserved_GeometrySrcType: // fallthrough
354        case kArray_GeometrySrcType:
355            maxValidVertex = geoSrc.fVertexCount;
356            break;
357        case kBuffer_GeometrySrcType:
358            maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / GrDrawState::VertexSize(geoSrc.fVertexLayout);
359            break;
360    }
361    if (maxVertex > maxValidVertex) {
362        GrCrash("Drawing outside valid vertex range.");
363    }
364    if (indexCount > 0) {
365        int maxIndex = startIndex + indexCount;
366        int maxValidIndex;
367        switch (geoSrc.fIndexSrc) {
368            case kNone_GeometrySrcType:
369                GrCrash("Attempting to draw indexed geom without index src.");
370            case kReserved_GeometrySrcType: // fallthrough
371            case kArray_GeometrySrcType:
372                maxValidIndex = geoSrc.fIndexCount;
373                break;
374            case kBuffer_GeometrySrcType:
375                maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
376                break;
377        }
378        if (maxIndex > maxValidIndex) {
379            GrCrash("Index reads outside valid index range.");
380        }
381    }
382
383    GrAssert(NULL != drawState.getRenderTarget());
384    for (int s = 0; s < GrDrawState::kNumStages; ++s) {
385        if (drawState.isStageEnabled(s)) {
386            const GrEffectRef& effect = *drawState.getStage(s).getEffect();
387            int numTextures = effect->numTextures();
388            for (int t = 0; t < numTextures; ++t) {
389                GrTexture* texture = effect->texture(t);
390                GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
391            }
392        }
393    }
394#endif
395    if (NULL == drawState.getRenderTarget()) {
396        return false;
397    }
398    return true;
399}
400
401void GrDrawTarget::drawIndexed(GrPrimitiveType type,
402                               int startVertex,
403                               int startIndex,
404                               int vertexCount,
405                               int indexCount,
406                               const SkRect* devBounds) {
407    if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
408        DrawInfo info;
409        info.fPrimitiveType = type;
410        info.fStartVertex   = startVertex;
411        info.fStartIndex    = startIndex;
412        info.fVertexCount   = vertexCount;
413        info.fIndexCount    = indexCount;
414
415        info.fInstanceCount         = 0;
416        info.fVerticesPerInstance   = 0;
417        info.fIndicesPerInstance    = 0;
418
419        if (NULL != devBounds) {
420            info.setDevBounds(*devBounds);
421        }
422        this->onDraw(info);
423    }
424}
425
426void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
427                                  int startVertex,
428                                  int vertexCount,
429                                  const SkRect* devBounds) {
430    if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
431        DrawInfo info;
432        info.fPrimitiveType = type;
433        info.fStartVertex   = startVertex;
434        info.fStartIndex    = 0;
435        info.fVertexCount   = vertexCount;
436        info.fIndexCount    = 0;
437
438        info.fInstanceCount         = 0;
439        info.fVerticesPerInstance   = 0;
440        info.fIndicesPerInstance    = 0;
441
442        if (NULL != devBounds) {
443            info.setDevBounds(*devBounds);
444        }
445        this->onDraw(info);
446    }
447}
448
449void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
450    // TODO: extract portions of checkDraw that are relevant to path stenciling.
451    GrAssert(NULL != path);
452    GrAssert(fCaps.pathStencilingSupport());
453    GrAssert(!stroke.isHairlineStyle());
454    GrAssert(!SkPath::IsInverseFillType(fill));
455    this->onStencilPath(path, stroke, fill);
456}
457
458////////////////////////////////////////////////////////////////////////////////
459
460// Some blend modes allow folding a partial coverage value into the color's
461// alpha channel, while others will blend incorrectly.
462bool GrDrawTarget::canTweakAlphaForCoverage() const {
463    /**
464     * The fractional coverage is f
465     * The src and dst coeffs are Cs and Cd
466     * The dst and src colors are S and D
467     * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
468     * By tweaking the source color's alpha we're replacing S with S'=fS. It's
469     * obvious that that first term will always be ok. The second term can be
470     * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
471     * for Cd we find that only 1, ISA, and ISC produce the correct depth
472     * coefficient in terms of S' and D.
473     */
474    GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
475    return kOne_GrBlendCoeff == dstCoeff ||
476           kISA_GrBlendCoeff == dstCoeff ||
477           kISC_GrBlendCoeff == dstCoeff ||
478           this->getDrawState().isCoverageDrawing();
479}
480
481namespace {
482GrVertexLayout default_blend_opts_vertex_layout() {
483    GrVertexLayout layout = 0;
484    return layout;
485}
486}
487
488GrDrawTarget::BlendOptFlags
489GrDrawTarget::getBlendOpts(bool forceCoverage,
490                           GrBlendCoeff* srcCoeff,
491                           GrBlendCoeff* dstCoeff) const {
492
493    GrVertexLayout layout;
494    if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
495        layout = default_blend_opts_vertex_layout();
496    } else {
497        layout = this->getVertexLayout();
498    }
499
500    const GrDrawState& drawState = this->getDrawState();
501
502    GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
503    if (NULL == srcCoeff) {
504        srcCoeff = &bogusSrcCoeff;
505    }
506    *srcCoeff = drawState.getSrcBlendCoeff();
507
508    if (NULL == dstCoeff) {
509        dstCoeff = &bogusDstCoeff;
510    }
511    *dstCoeff = drawState.getDstBlendCoeff();
512
513    if (drawState.isColorWriteDisabled()) {
514        *srcCoeff = kZero_GrBlendCoeff;
515        *dstCoeff = kOne_GrBlendCoeff;
516    }
517
518    bool srcAIsOne = drawState.srcAlphaWillBeOne(layout);
519    bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
520                         (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
521    bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
522                         (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
523
524    bool covIsZero = !drawState.isCoverageDrawing() &&
525                     !(layout & GrDrawState::kCoverage_VertexLayoutBit) &&
526                     0 == drawState.getCoverage();
527    // When coeffs are (0,1) there is no reason to draw at all, unless
528    // stenciling is enabled. Having color writes disabled is effectively
529    // (0,1). The same applies when coverage is known to be 0.
530    if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
531        if (drawState.getStencil().doesWrite()) {
532            return kDisableBlend_BlendOptFlag |
533                   kEmitTransBlack_BlendOptFlag;
534        } else {
535            return kSkipDraw_BlendOptFlag;
536        }
537    }
538
539    // check for coverage due to constant coverage, per-vertex coverage,
540    // edge aa or coverage stage
541    bool hasCoverage = forceCoverage ||
542                       0xffffffff != drawState.getCoverage() ||
543                       (layout & GrDrawState::kCoverage_VertexLayoutBit) ||
544                       (layout & GrDrawState::kEdge_VertexLayoutBit);
545    for (int s = drawState.getFirstCoverageStage();
546         !hasCoverage && s < GrDrawState::kNumStages;
547         ++s) {
548        if (drawState.isStageEnabled(s)) {
549            hasCoverage = true;
550        }
551    }
552
553    // if we don't have coverage we can check whether the dst
554    // has to read at all. If not, we'll disable blending.
555    if (!hasCoverage) {
556        if (dstCoeffIsZero) {
557            if (kOne_GrBlendCoeff == *srcCoeff) {
558                // if there is no coverage and coeffs are (1,0) then we
559                // won't need to read the dst at all, it gets replaced by src
560                return kDisableBlend_BlendOptFlag;
561            } else if (kZero_GrBlendCoeff == *srcCoeff) {
562                // if the op is "clear" then we don't need to emit a color
563                // or blend, just write transparent black into the dst.
564                *srcCoeff = kOne_GrBlendCoeff;
565                *dstCoeff = kZero_GrBlendCoeff;
566                return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
567            }
568        }
569    } else if (drawState.isCoverageDrawing()) {
570        // we have coverage but we aren't distinguishing it from alpha by request.
571        return kCoverageAsAlpha_BlendOptFlag;
572    } else {
573        // check whether coverage can be safely rolled into alpha
574        // of if we can skip color computation and just emit coverage
575        if (this->canTweakAlphaForCoverage()) {
576            return kCoverageAsAlpha_BlendOptFlag;
577        }
578        if (dstCoeffIsZero) {
579            if (kZero_GrBlendCoeff == *srcCoeff) {
580                // the source color is not included in the blend
581                // the dst coeff is effectively zero so blend works out to:
582                // (c)(0)D + (1-c)D = (1-c)D.
583                *dstCoeff = kISA_GrBlendCoeff;
584                return  kEmitCoverage_BlendOptFlag;
585            } else if (srcAIsOne) {
586                // the dst coeff is effectively zero so blend works out to:
587                // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
588                // If Sa is 1 then we can replace Sa with c
589                // and set dst coeff to 1-Sa.
590                *dstCoeff = kISA_GrBlendCoeff;
591                return  kCoverageAsAlpha_BlendOptFlag;
592            }
593        } else if (dstCoeffIsOne) {
594            // the dst coeff is effectively one so blend works out to:
595            // cS + (c)(1)D + (1-c)D = cS + D.
596            *dstCoeff = kOne_GrBlendCoeff;
597            return  kCoverageAsAlpha_BlendOptFlag;
598        }
599    }
600    return kNone_BlendOpt;
601}
602
603bool GrDrawTarget::willUseHWAALines() const {
604    // there is a conflict between using smooth lines and our use of
605    // premultiplied alpha. Smooth lines tweak the incoming alpha value
606    // but not in a premul-alpha way. So we only use them when our alpha
607    // is 0xff and tweaking the color for partial coverage is OK
608    if (!fCaps.hwAALineSupport() ||
609        !this->getDrawState().isHWAntialiasState()) {
610        return false;
611    }
612    BlendOptFlags opts = this->getBlendOpts();
613    return (kDisableBlend_BlendOptFlag & opts) &&
614           (kCoverageAsAlpha_BlendOptFlag & opts);
615}
616
617bool GrDrawTarget::canApplyCoverage() const {
618    // we can correctly apply coverage if a) we have dual source blending
619    // or b) one of our blend optimizations applies.
620    return this->getCaps().dualSourceBlendingSupport() ||
621           kNone_BlendOpt != this->getBlendOpts(true);
622}
623
624////////////////////////////////////////////////////////////////////////////////
625
626void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
627                                        int instanceCount,
628                                        int verticesPerInstance,
629                                        int indicesPerInstance,
630                                        const SkRect* devBounds) {
631    if (!verticesPerInstance || !indicesPerInstance) {
632        return;
633    }
634
635    int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
636    if (!maxInstancesPerDraw) {
637        return;
638    }
639
640    DrawInfo info;
641    info.fPrimitiveType = type;
642    info.fStartIndex = 0;
643    info.fStartVertex = 0;
644    info.fIndicesPerInstance = indicesPerInstance;
645    info.fVerticesPerInstance = verticesPerInstance;
646
647    // Set the same bounds for all the draws.
648    if (NULL != devBounds) {
649        info.setDevBounds(*devBounds);
650    }
651
652    while (instanceCount) {
653        info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
654        info.fVertexCount = info.fInstanceCount * verticesPerInstance;
655        info.fIndexCount = info.fInstanceCount * indicesPerInstance;
656
657        if (this->checkDraw(type,
658                            info.fStartVertex,
659                            info.fStartIndex,
660                            info.fVertexCount,
661                            info.fIndexCount)) {
662            this->onDraw(info);
663        }
664        info.fStartVertex += info.fVertexCount;
665        instanceCount -= info.fInstanceCount;
666    }
667}
668
669////////////////////////////////////////////////////////////////////////////////
670
671void GrDrawTarget::drawRect(const GrRect& rect,
672                            const SkMatrix* matrix,
673                            const GrRect* srcRects[],
674                            const SkMatrix* srcMatrices[]) {
675    GrVertexLayout layout = 0;
676    uint32_t explicitCoordMask = 0;
677
678    if (NULL != srcRects) {
679        for (int s = 0; s < GrDrawState::kNumStages; ++s) {
680            int numTC = 0;
681            if (NULL != srcRects[s]) {
682                layout |= GrDrawState::StageTexCoordVertexLayoutBit(s, numTC);
683                explicitCoordMask |= (1 << s);
684                ++numTC;
685            }
686        }
687    }
688
689    GrDrawState::AutoViewMatrixRestore avmr;
690    if (NULL != matrix) {
691        avmr.set(this->drawState(), *matrix, explicitCoordMask);
692    }
693
694    AutoReleaseGeometry geo(this, layout, 4, 0);
695    if (!geo.succeeded()) {
696        GrPrintf("Failed to get space for vertices!\n");
697        return;
698    }
699
700    int stageOffsets[GrDrawState::kNumStages];
701    int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets,  NULL, NULL, NULL);
702    geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
703
704    for (int i = 0; i < GrDrawState::kNumStages; ++i) {
705        if (explicitCoordMask & (1 << i)) {
706            GrAssert(0 != stageOffsets[i]);
707            GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
708                                                stageOffsets[i]);
709            coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
710                               srcRects[i]->fRight, srcRects[i]->fBottom,
711                               vsize);
712            if (NULL != srcMatrices && NULL != srcMatrices[i]) {
713                srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
714            }
715        } else {
716            GrAssert(0 == stageOffsets[i]);
717        }
718    }
719
720    this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
721}
722
723void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
724}
725
726////////////////////////////////////////////////////////////////////////////////
727
728GrDrawTarget::AutoStateRestore::AutoStateRestore() {
729    fDrawTarget = NULL;
730}
731
732GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
733                                                 ASRInit init) {
734    fDrawTarget = NULL;
735    this->set(target, init);
736}
737
738GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
739    if (NULL != fDrawTarget) {
740        fDrawTarget->setDrawState(fSavedState);
741        fSavedState->unref();
742    }
743}
744
745void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
746    GrAssert(NULL == fDrawTarget);
747    fDrawTarget = target;
748    fSavedState = target->drawState();
749    GrAssert(fSavedState);
750    fSavedState->ref();
751    if (kReset_ASRInit == init) {
752        // calls the default cons
753        fTempState.init();
754    } else {
755        GrAssert(kPreserve_ASRInit == init);
756        // calls the copy cons
757        fTempState.set(*fSavedState);
758    }
759    target->setDrawState(fTempState.get());
760}
761
762////////////////////////////////////////////////////////////////////////////////
763
764GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
765                                         GrDrawTarget*  target,
766                                         GrVertexLayout vertexLayout,
767                                         int vertexCount,
768                                         int indexCount) {
769    fTarget = NULL;
770    this->set(target, vertexLayout, vertexCount, indexCount);
771}
772
773GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
774    fTarget = NULL;
775}
776
777GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
778    this->reset();
779}
780
781bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget*  target,
782                                            GrVertexLayout vertexLayout,
783                                            int vertexCount,
784                                            int indexCount) {
785    this->reset();
786    fTarget = target;
787    bool success = true;
788    if (NULL != fTarget) {
789        fTarget = target;
790        success = target->reserveVertexAndIndexSpace(vertexLayout,
791                                                     vertexCount,
792                                                     indexCount,
793                                                     &fVertices,
794                                                     &fIndices);
795        if (!success) {
796            fTarget = NULL;
797            this->reset();
798        }
799    }
800    GrAssert(success == (NULL != fTarget));
801    return success;
802}
803
804void GrDrawTarget::AutoReleaseGeometry::reset() {
805    if (NULL != fTarget) {
806        if (NULL != fVertices) {
807            fTarget->resetVertexSource();
808        }
809        if (NULL != fIndices) {
810            fTarget->resetIndexSource();
811        }
812        fTarget = NULL;
813    }
814    fVertices = NULL;
815    fIndices = NULL;
816}
817
818GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
819    fTarget = target;
820    fClip = fTarget->getClip();
821    fStack.init();
822    fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
823    fReplacementClip.fClipStack = fStack.get();
824    target->setClip(&fReplacementClip);
825}
826
827void GrDrawTarget::Caps::print() const {
828    static const char* gNY[] = {"NO", "YES"};
829    GrPrintf("8 Bit Palette Support       : %s\n", gNY[fInternals.f8BitPaletteSupport]);
830    GrPrintf("NPOT Texture Tile Support   : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
831    GrPrintf("Two Sided Stencil Support   : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
832    GrPrintf("Stencil Wrap Ops  Support   : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
833    GrPrintf("HW AA Lines Support         : %s\n", gNY[fInternals.fHWAALineSupport]);
834    GrPrintf("Shader Derivative Support   : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
835    GrPrintf("Geometry Shader Support     : %s\n", gNY[fInternals.fGeometryShaderSupport]);
836    GrPrintf("FSAA Support                : %s\n", gNY[fInternals.fFSAASupport]);
837    GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
838    GrPrintf("Buffer Lock Support         : %s\n", gNY[fInternals.fBufferLockSupport]);
839    GrPrintf("Path Stenciling Support     : %s\n", gNY[fInternals.fPathStencilingSupport]);
840    GrPrintf("Max Texture Size            : %d\n", fInternals.fMaxTextureSize);
841    GrPrintf("Max Render Target Size      : %d\n", fInternals.fMaxRenderTargetSize);
842}
843