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 "GrContext.h"
13#include "GrDrawTargetCaps.h"
14#include "GrPath.h"
15#include "GrRenderTarget.h"
16#include "GrTemplates.h"
17#include "GrTexture.h"
18#include "GrVertexBuffer.h"
19
20#include "SkStrokeRec.h"
21
22////////////////////////////////////////////////////////////////////////////////
23
24GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) {
25    fPrimitiveType  = di.fPrimitiveType;
26    fStartVertex    = di.fStartVertex;
27    fStartIndex     = di.fStartIndex;
28    fVertexCount    = di.fVertexCount;
29    fIndexCount     = di.fIndexCount;
30
31    fInstanceCount          = di.fInstanceCount;
32    fVerticesPerInstance    = di.fVerticesPerInstance;
33    fIndicesPerInstance     = di.fIndicesPerInstance;
34
35    if (di.fDevBounds) {
36        SkASSERT(di.fDevBounds == &di.fDevBoundsStorage);
37        fDevBoundsStorage = di.fDevBoundsStorage;
38        fDevBounds = &fDevBoundsStorage;
39    } else {
40        fDevBounds = NULL;
41    }
42
43    fDstCopy = di.fDstCopy;
44
45    return *this;
46}
47
48#ifdef SK_DEBUG
49bool GrDrawTarget::DrawInfo::isInstanced() const {
50    if (fInstanceCount > 0) {
51        SkASSERT(0 == fIndexCount % fIndicesPerInstance);
52        SkASSERT(0 == fVertexCount % fVerticesPerInstance);
53        SkASSERT(fIndexCount / fIndicesPerInstance == fInstanceCount);
54        SkASSERT(fVertexCount / fVerticesPerInstance == fInstanceCount);
55        // there is no way to specify a non-zero start index to drawIndexedInstances().
56        SkASSERT(0 == fStartIndex);
57        return true;
58    } else {
59        SkASSERT(!fVerticesPerInstance);
60        SkASSERT(!fIndicesPerInstance);
61        return false;
62    }
63}
64#endif
65
66void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) {
67    SkASSERT(this->isInstanced());
68    SkASSERT(instanceOffset + fInstanceCount >= 0);
69    fInstanceCount += instanceOffset;
70    fVertexCount = fVerticesPerInstance * fInstanceCount;
71    fIndexCount = fIndicesPerInstance * fInstanceCount;
72}
73
74void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
75    fStartVertex += vertexOffset;
76    SkASSERT(fStartVertex >= 0);
77}
78
79void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
80    SkASSERT(this->isIndexed());
81    fStartIndex += indexOffset;
82    SkASSERT(fStartIndex >= 0);
83}
84
85////////////////////////////////////////////////////////////////////////////////
86
87#define DEBUG_INVAL_BUFFER 0xdeadcafe
88#define DEBUG_INVAL_START_IDX -1
89
90GrDrawTarget::GrDrawTarget(GrContext* context)
91    : fClip(NULL)
92    , fContext(context)
93    , fGpuTraceMarkerCount(0) {
94    SkASSERT(context);
95
96    fDrawState = &fDefaultDrawState;
97    // We assume that fDrawState always owns a ref to the object it points at.
98    fDefaultDrawState.ref();
99    GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
100#ifdef SK_DEBUG
101    geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
102    geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
103    geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
104    geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
105#endif
106    geoSrc.fVertexSrc = kNone_GeometrySrcType;
107    geoSrc.fIndexSrc  = kNone_GeometrySrcType;
108}
109
110GrDrawTarget::~GrDrawTarget() {
111    SkASSERT(1 == fGeoSrcStateStack.count());
112    SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
113    SkASSERT(kNone_GeometrySrcType == geoSrc.fIndexSrc);
114    SkASSERT(kNone_GeometrySrcType == geoSrc.fVertexSrc);
115    fDrawState->unref();
116}
117
118void GrDrawTarget::releaseGeometry() {
119    int popCnt = fGeoSrcStateStack.count() - 1;
120    while (popCnt) {
121        this->popGeometrySource();
122        --popCnt;
123    }
124    this->resetVertexSource();
125    this->resetIndexSource();
126}
127
128void GrDrawTarget::setClip(const GrClipData* clip) {
129    clipWillBeSet(clip);
130    fClip = clip;
131}
132
133const GrClipData* GrDrawTarget::getClip() const {
134    return fClip;
135}
136
137void GrDrawTarget::setDrawState(GrDrawState*  drawState) {
138    SkASSERT(fDrawState);
139    if (NULL == drawState) {
140        drawState = &fDefaultDrawState;
141    }
142    if (fDrawState != drawState) {
143        fDrawState->unref();
144        drawState->ref();
145        fDrawState = drawState;
146    }
147}
148
149bool GrDrawTarget::reserveVertexSpace(size_t vertexSize,
150                                      int vertexCount,
151                                      void** vertices) {
152    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
153    bool acquired = false;
154    if (vertexCount > 0) {
155        SkASSERT(vertices);
156        this->releasePreviousVertexSource();
157        geoSrc.fVertexSrc = kNone_GeometrySrcType;
158
159        acquired = this->onReserveVertexSpace(vertexSize,
160                                              vertexCount,
161                                              vertices);
162    }
163    if (acquired) {
164        geoSrc.fVertexSrc = kReserved_GeometrySrcType;
165        geoSrc.fVertexCount = vertexCount;
166        geoSrc.fVertexSize = vertexSize;
167    } else if (vertices) {
168        *vertices = NULL;
169    }
170    return acquired;
171}
172
173bool GrDrawTarget::reserveIndexSpace(int indexCount,
174                                     void** indices) {
175    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
176    bool acquired = false;
177    if (indexCount > 0) {
178        SkASSERT(indices);
179        this->releasePreviousIndexSource();
180        geoSrc.fIndexSrc = kNone_GeometrySrcType;
181
182        acquired = this->onReserveIndexSpace(indexCount, indices);
183    }
184    if (acquired) {
185        geoSrc.fIndexSrc = kReserved_GeometrySrcType;
186        geoSrc.fIndexCount = indexCount;
187    } else if (indices) {
188        *indices = NULL;
189    }
190    return acquired;
191
192}
193
194bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount,
195                                              int indexCount,
196                                              void** vertices,
197                                              void** indices) {
198    size_t vertexStride = this->drawState()->getVertexStride();
199    this->willReserveVertexAndIndexSpace(vertexCount, indexCount);
200    if (vertexCount) {
201        if (!this->reserveVertexSpace(vertexStride, vertexCount, vertices)) {
202            if (indexCount) {
203                this->resetIndexSource();
204            }
205            return false;
206        }
207    }
208    if (indexCount) {
209        if (!this->reserveIndexSpace(indexCount, indices)) {
210            if (vertexCount) {
211                this->resetVertexSource();
212            }
213            return false;
214        }
215    }
216    return true;
217}
218
219bool GrDrawTarget::geometryHints(int32_t* vertexCount,
220                                 int32_t* indexCount) const {
221    if (vertexCount) {
222        *vertexCount = -1;
223    }
224    if (indexCount) {
225        *indexCount = -1;
226    }
227    return false;
228}
229
230void GrDrawTarget::releasePreviousVertexSource() {
231    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
232    switch (geoSrc.fVertexSrc) {
233        case kNone_GeometrySrcType:
234            break;
235        case kArray_GeometrySrcType:
236            this->releaseVertexArray();
237            break;
238        case kReserved_GeometrySrcType:
239            this->releaseReservedVertexSpace();
240            break;
241        case kBuffer_GeometrySrcType:
242            geoSrc.fVertexBuffer->unref();
243#ifdef SK_DEBUG
244            geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
245#endif
246            break;
247        default:
248            SkFAIL("Unknown Vertex Source Type.");
249            break;
250    }
251}
252
253void GrDrawTarget::releasePreviousIndexSource() {
254    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
255    switch (geoSrc.fIndexSrc) {
256        case kNone_GeometrySrcType:   // these two don't require
257            break;
258        case kArray_GeometrySrcType:
259            this->releaseIndexArray();
260            break;
261        case kReserved_GeometrySrcType:
262            this->releaseReservedIndexSpace();
263            break;
264        case kBuffer_GeometrySrcType:
265            geoSrc.fIndexBuffer->unref();
266#ifdef SK_DEBUG
267            geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
268#endif
269            break;
270        default:
271            SkFAIL("Unknown Index Source Type.");
272            break;
273    }
274}
275
276void GrDrawTarget::setVertexSourceToArray(const void* vertexArray,
277                                          int vertexCount) {
278    this->releasePreviousVertexSource();
279    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
280    geoSrc.fVertexSrc = kArray_GeometrySrcType;
281    geoSrc.fVertexSize = this->drawState()->getVertexStride();
282    geoSrc.fVertexCount = vertexCount;
283    this->onSetVertexSourceToArray(vertexArray, vertexCount);
284}
285
286void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
287                                         int indexCount) {
288    this->releasePreviousIndexSource();
289    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
290    geoSrc.fIndexSrc = kArray_GeometrySrcType;
291    geoSrc.fIndexCount = indexCount;
292    this->onSetIndexSourceToArray(indexArray, indexCount);
293}
294
295void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer) {
296    this->releasePreviousVertexSource();
297    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
298    geoSrc.fVertexSrc    = kBuffer_GeometrySrcType;
299    geoSrc.fVertexBuffer = buffer;
300    buffer->ref();
301    geoSrc.fVertexSize = this->drawState()->getVertexStride();
302}
303
304void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
305    this->releasePreviousIndexSource();
306    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
307    geoSrc.fIndexSrc     = kBuffer_GeometrySrcType;
308    geoSrc.fIndexBuffer  = buffer;
309    buffer->ref();
310}
311
312void GrDrawTarget::resetVertexSource() {
313    this->releasePreviousVertexSource();
314    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
315    geoSrc.fVertexSrc = kNone_GeometrySrcType;
316}
317
318void GrDrawTarget::resetIndexSource() {
319    this->releasePreviousIndexSource();
320    GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
321    geoSrc.fIndexSrc = kNone_GeometrySrcType;
322}
323
324void GrDrawTarget::pushGeometrySource() {
325    this->geometrySourceWillPush();
326    GeometrySrcState& newState = fGeoSrcStateStack.push_back();
327    newState.fIndexSrc = kNone_GeometrySrcType;
328    newState.fVertexSrc = kNone_GeometrySrcType;
329#ifdef SK_DEBUG
330    newState.fVertexCount  = ~0;
331    newState.fVertexBuffer = (GrVertexBuffer*)~0;
332    newState.fIndexCount   = ~0;
333    newState.fIndexBuffer = (GrIndexBuffer*)~0;
334#endif
335}
336
337void GrDrawTarget::popGeometrySource() {
338    // if popping last element then pops are unbalanced with pushes
339    SkASSERT(fGeoSrcStateStack.count() > 1);
340
341    this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
342    this->releasePreviousVertexSource();
343    this->releasePreviousIndexSource();
344    fGeoSrcStateStack.pop_back();
345}
346
347////////////////////////////////////////////////////////////////////////////////
348
349bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
350                             int startIndex, int vertexCount,
351                             int indexCount) const {
352    const GrDrawState& drawState = this->getDrawState();
353#ifdef SK_DEBUG
354    const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
355    int maxVertex = startVertex + vertexCount;
356    int maxValidVertex;
357    switch (geoSrc.fVertexSrc) {
358        case kNone_GeometrySrcType:
359            SkFAIL("Attempting to draw without vertex src.");
360        case kReserved_GeometrySrcType: // fallthrough
361        case kArray_GeometrySrcType:
362            maxValidVertex = geoSrc.fVertexCount;
363            break;
364        case kBuffer_GeometrySrcType:
365            maxValidVertex = static_cast<int>(geoSrc.fVertexBuffer->gpuMemorySize() / geoSrc.fVertexSize);
366            break;
367    }
368    if (maxVertex > maxValidVertex) {
369        SkFAIL("Drawing outside valid vertex range.");
370    }
371    if (indexCount > 0) {
372        int maxIndex = startIndex + indexCount;
373        int maxValidIndex;
374        switch (geoSrc.fIndexSrc) {
375            case kNone_GeometrySrcType:
376                SkFAIL("Attempting to draw indexed geom without index src.");
377            case kReserved_GeometrySrcType: // fallthrough
378            case kArray_GeometrySrcType:
379                maxValidIndex = geoSrc.fIndexCount;
380                break;
381            case kBuffer_GeometrySrcType:
382                maxValidIndex = static_cast<int>(geoSrc.fIndexBuffer->gpuMemorySize() / sizeof(uint16_t));
383                break;
384        }
385        if (maxIndex > maxValidIndex) {
386            SkFAIL("Index reads outside valid index range.");
387        }
388    }
389
390    SkASSERT(drawState.getRenderTarget());
391
392    if (drawState.hasGeometryProcessor()) {
393        const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getGeometryProcessor();
394        int numTextures = gp->numTextures();
395        for (int t = 0; t < numTextures; ++t) {
396            GrTexture* texture = gp->texture(t);
397            SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
398        }
399    }
400
401    for (int s = 0; s < drawState.numColorStages(); ++s) {
402        const GrProcessor* effect = drawState.getColorStage(s).getProcessor();
403        int numTextures = effect->numTextures();
404        for (int t = 0; t < numTextures; ++t) {
405            GrTexture* texture = effect->texture(t);
406            SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
407        }
408    }
409    for (int s = 0; s < drawState.numCoverageStages(); ++s) {
410        const GrProcessor* effect = drawState.getCoverageStage(s).getProcessor();
411        int numTextures = effect->numTextures();
412        for (int t = 0; t < numTextures; ++t) {
413            GrTexture* texture = effect->texture(t);
414            SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
415        }
416    }
417
418    SkASSERT(drawState.validateVertexAttribs());
419#endif
420    if (NULL == drawState.getRenderTarget()) {
421        return false;
422    }
423    return true;
424}
425
426bool GrDrawTarget::setupDstReadIfNecessary(GrDeviceCoordTexture* dstCopy, const SkRect* drawBounds) {
427    if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDstColor()) {
428        return true;
429    }
430    GrRenderTarget* rt = this->drawState()->getRenderTarget();
431    SkIRect copyRect;
432    const GrClipData* clip = this->getClip();
433    clip->getConservativeBounds(rt, &copyRect);
434
435    if (drawBounds) {
436        SkIRect drawIBounds;
437        drawBounds->roundOut(&drawIBounds);
438        if (!copyRect.intersect(drawIBounds)) {
439#ifdef SK_DEBUG
440            GrPrintf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n");
441#endif
442            return false;
443        }
444    } else {
445#ifdef SK_DEBUG
446        //GrPrintf("No dev bounds when dst copy is made.\n");
447#endif
448    }
449
450    // MSAA consideration: When there is support for reading MSAA samples in the shader we could
451    // have per-sample dst values by making the copy multisampled.
452    GrTextureDesc desc;
453    this->initCopySurfaceDstDesc(rt, &desc);
454    desc.fWidth = copyRect.width();
455    desc.fHeight = copyRect.height();
456
457    GrAutoScratchTexture ast(fContext, desc, GrContext::kApprox_ScratchTexMatch);
458
459    if (NULL == ast.texture()) {
460        GrPrintf("Failed to create temporary copy of destination texture.\n");
461        return false;
462    }
463    SkIPoint dstPoint = {0, 0};
464    if (this->copySurface(ast.texture(), rt, copyRect, dstPoint)) {
465        dstCopy->setTexture(ast.texture());
466        dstCopy->setOffset(copyRect.fLeft, copyRect.fTop);
467        return true;
468    } else {
469        return false;
470    }
471}
472
473void GrDrawTarget::drawIndexed(GrPrimitiveType type,
474                               int startVertex,
475                               int startIndex,
476                               int vertexCount,
477                               int indexCount,
478                               const SkRect* devBounds) {
479    if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
480        DrawInfo info;
481        info.fPrimitiveType = type;
482        info.fStartVertex   = startVertex;
483        info.fStartIndex    = startIndex;
484        info.fVertexCount   = vertexCount;
485        info.fIndexCount    = indexCount;
486
487        info.fInstanceCount         = 0;
488        info.fVerticesPerInstance   = 0;
489        info.fIndicesPerInstance    = 0;
490
491        if (devBounds) {
492            info.setDevBounds(*devBounds);
493        }
494        // TODO: We should continue with incorrect blending.
495        if (!this->setupDstReadIfNecessary(&info)) {
496            return;
497        }
498        this->onDraw(info);
499    }
500}
501
502void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
503                                  int startVertex,
504                                  int vertexCount,
505                                  const SkRect* devBounds) {
506    if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
507        DrawInfo info;
508        info.fPrimitiveType = type;
509        info.fStartVertex   = startVertex;
510        info.fStartIndex    = 0;
511        info.fVertexCount   = vertexCount;
512        info.fIndexCount    = 0;
513
514        info.fInstanceCount         = 0;
515        info.fVerticesPerInstance   = 0;
516        info.fIndicesPerInstance    = 0;
517
518        if (devBounds) {
519            info.setDevBounds(*devBounds);
520        }
521        // TODO: We should continue with incorrect blending.
522        if (!this->setupDstReadIfNecessary(&info)) {
523            return;
524        }
525        this->onDraw(info);
526    }
527}
528
529void GrDrawTarget::stencilPath(const GrPath* path, SkPath::FillType fill) {
530    // TODO: extract portions of checkDraw that are relevant to path stenciling.
531    SkASSERT(path);
532    SkASSERT(this->caps()->pathRenderingSupport());
533    SkASSERT(!SkPath::IsInverseFillType(fill));
534    this->onStencilPath(path, fill);
535}
536
537void GrDrawTarget::drawPath(const GrPath* path, SkPath::FillType fill) {
538    // TODO: extract portions of checkDraw that are relevant to path rendering.
539    SkASSERT(path);
540    SkASSERT(this->caps()->pathRenderingSupport());
541    const GrDrawState* drawState = &getDrawState();
542
543    SkRect devBounds;
544    if (SkPath::IsInverseFillType(fill)) {
545        devBounds = SkRect::MakeWH(SkIntToScalar(drawState->getRenderTarget()->width()),
546                                   SkIntToScalar(drawState->getRenderTarget()->height()));
547    } else {
548        devBounds = path->getBounds();
549    }
550    SkMatrix viewM = drawState->getViewMatrix();
551    viewM.mapRect(&devBounds);
552
553    GrDeviceCoordTexture dstCopy;
554    if (!this->setupDstReadIfNecessary(&dstCopy, &devBounds)) {
555        return;
556    }
557
558    this->onDrawPath(path, fill, dstCopy.texture() ? &dstCopy : NULL);
559}
560
561void GrDrawTarget::drawPaths(const GrPathRange* pathRange,
562                             const uint32_t indices[], int count,
563                             const float transforms[], PathTransformType transformsType,
564                             SkPath::FillType fill) {
565    SkASSERT(this->caps()->pathRenderingSupport());
566    SkASSERT(pathRange);
567    SkASSERT(indices);
568    SkASSERT(transforms);
569
570    // Don't compute a bounding box for setupDstReadIfNecessary(), we'll opt
571    // instead for it to just copy the entire dst. Realistically this is a moot
572    // point, because any context that supports NV_path_rendering will also
573    // support NV_blend_equation_advanced.
574    GrDeviceCoordTexture dstCopy;
575    if (!this->setupDstReadIfNecessary(&dstCopy, NULL)) {
576        return;
577    }
578
579    this->onDrawPaths(pathRange, indices, count, transforms, transformsType, fill,
580                      dstCopy.texture() ? &dstCopy : NULL);
581}
582
583typedef GrTraceMarkerSet::Iter TMIter;
584void GrDrawTarget::saveActiveTraceMarkers() {
585    if (this->caps()->gpuTracingSupport()) {
586        SkASSERT(0 == fStoredTraceMarkers.count());
587        fStoredTraceMarkers.addSet(fActiveTraceMarkers);
588        for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) {
589            this->removeGpuTraceMarker(&(*iter));
590        }
591    }
592}
593
594void GrDrawTarget::restoreActiveTraceMarkers() {
595    if (this->caps()->gpuTracingSupport()) {
596        SkASSERT(0 == fActiveTraceMarkers.count());
597        for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) {
598            this->addGpuTraceMarker(&(*iter));
599        }
600        for (TMIter iter = fActiveTraceMarkers.begin(); iter != fActiveTraceMarkers.end(); ++iter) {
601            this->fStoredTraceMarkers.remove(*iter);
602        }
603    }
604}
605
606void GrDrawTarget::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
607    if (this->caps()->gpuTracingSupport()) {
608        SkASSERT(fGpuTraceMarkerCount >= 0);
609        this->fActiveTraceMarkers.add(*marker);
610        this->didAddGpuTraceMarker();
611        ++fGpuTraceMarkerCount;
612    }
613}
614
615void GrDrawTarget::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
616    if (this->caps()->gpuTracingSupport()) {
617        SkASSERT(fGpuTraceMarkerCount >= 1);
618        this->fActiveTraceMarkers.remove(*marker);
619        this->didRemoveGpuTraceMarker();
620        --fGpuTraceMarkerCount;
621    }
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 (devBounds) {
649        info.setDevBounds(*devBounds);
650    }
651    // TODO: We should continue with incorrect blending.
652    if (!this->setupDstReadIfNecessary(&info)) {
653        return;
654    }
655
656    while (instanceCount) {
657        info.fInstanceCount = SkTMin(instanceCount, maxInstancesPerDraw);
658        info.fVertexCount = info.fInstanceCount * verticesPerInstance;
659        info.fIndexCount = info.fInstanceCount * indicesPerInstance;
660
661        if (this->checkDraw(type,
662                            info.fStartVertex,
663                            info.fStartIndex,
664                            info.fVertexCount,
665                            info.fIndexCount)) {
666            this->onDraw(info);
667        }
668        info.fStartVertex += info.fVertexCount;
669        instanceCount -= info.fInstanceCount;
670    }
671}
672
673////////////////////////////////////////////////////////////////////////////////
674
675namespace {
676
677// position + (optional) texture coord
678extern const GrVertexAttrib gBWRectPosUVAttribs[] = {
679    {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
680    {kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding}
681};
682
683void set_vertex_attributes(GrDrawState* drawState, bool hasUVs) {
684    if (hasUVs) {
685        drawState->setVertexAttribs<gBWRectPosUVAttribs>(2, 2 * sizeof(SkPoint));
686    } else {
687        drawState->setVertexAttribs<gBWRectPosUVAttribs>(1, sizeof(SkPoint));
688    }
689}
690
691};
692
693void GrDrawTarget::onDrawRect(const SkRect& rect,
694                              const SkRect* localRect,
695                              const SkMatrix* localMatrix) {
696
697    set_vertex_attributes(this->drawState(), SkToBool(localRect));
698
699    AutoReleaseGeometry geo(this, 4, 0);
700    if (!geo.succeeded()) {
701        GrPrintf("Failed to get space for vertices!\n");
702        return;
703    }
704
705    size_t vstride = this->drawState()->getVertexStride();
706    geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vstride);
707    if (localRect) {
708        SkPoint* coords = GrTCast<SkPoint*>(GrTCast<intptr_t>(geo.vertices()) +
709                                            sizeof(SkPoint));
710        coords->setRectFan(localRect->fLeft, localRect->fTop,
711                           localRect->fRight, localRect->fBottom,
712                           vstride);
713        if (localMatrix) {
714            localMatrix->mapPointsWithStride(coords, vstride, 4);
715        }
716    }
717    SkRect bounds;
718    this->getDrawState().getViewMatrix().mapRect(&bounds, rect);
719
720    this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, &bounds);
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                                                 const SkMatrix* vm) {
735    fDrawTarget = NULL;
736    this->set(target, init, vm);
737}
738
739GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
740    if (fDrawTarget) {
741        fDrawTarget->setDrawState(fSavedState);
742        fSavedState->unref();
743    }
744}
745
746void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init, const SkMatrix* vm) {
747    SkASSERT(NULL == fDrawTarget);
748    fDrawTarget = target;
749    fSavedState = target->drawState();
750    SkASSERT(fSavedState);
751    fSavedState->ref();
752    if (kReset_ASRInit == init) {
753        if (NULL == vm) {
754            // calls the default cons
755            fTempState.init();
756        } else {
757            SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*vm));
758        }
759    } else {
760        SkASSERT(kPreserve_ASRInit == init);
761        if (NULL == vm) {
762            fTempState.set(*fSavedState);
763        } else {
764            SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*fSavedState, *vm));
765        }
766    }
767    target->setDrawState(fTempState.get());
768}
769
770bool GrDrawTarget::AutoStateRestore::setIdentity(GrDrawTarget* target, ASRInit init) {
771    SkASSERT(NULL == fDrawTarget);
772    fDrawTarget = target;
773    fSavedState = target->drawState();
774    SkASSERT(fSavedState);
775    fSavedState->ref();
776    if (kReset_ASRInit == init) {
777        // calls the default cons
778        fTempState.init();
779    } else {
780        SkASSERT(kPreserve_ASRInit == init);
781        // calls the copy cons
782        fTempState.set(*fSavedState);
783        if (!fTempState.get()->setIdentityViewMatrix()) {
784            // let go of any resources held by the temp
785            fTempState.get()->reset();
786            fDrawTarget = NULL;
787            fSavedState->unref();
788            fSavedState = NULL;
789            return false;
790        }
791    }
792    target->setDrawState(fTempState.get());
793    return true;
794}
795
796////////////////////////////////////////////////////////////////////////////////
797
798GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
799                                         GrDrawTarget*  target,
800                                         int vertexCount,
801                                         int indexCount) {
802    fTarget = NULL;
803    this->set(target, vertexCount, indexCount);
804}
805
806GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
807    fTarget = NULL;
808}
809
810GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
811    this->reset();
812}
813
814bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget*  target,
815                                            int vertexCount,
816                                            int indexCount) {
817    this->reset();
818    fTarget = target;
819    bool success = true;
820    if (fTarget) {
821        success = target->reserveVertexAndIndexSpace(vertexCount,
822                                                     indexCount,
823                                                     &fVertices,
824                                                     &fIndices);
825        if (!success) {
826            fTarget = NULL;
827            this->reset();
828        }
829    }
830    SkASSERT(success == SkToBool(fTarget));
831    return success;
832}
833
834void GrDrawTarget::AutoReleaseGeometry::reset() {
835    if (fTarget) {
836        if (fVertices) {
837            fTarget->resetVertexSource();
838        }
839        if (fIndices) {
840            fTarget->resetIndexSource();
841        }
842        fTarget = NULL;
843    }
844    fVertices = NULL;
845    fIndices = NULL;
846}
847
848GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
849    fTarget = target;
850    fClip = fTarget->getClip();
851    fStack.init();
852    fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
853    fReplacementClip.fClipStack = fStack.get();
854    target->setClip(&fReplacementClip);
855}
856
857namespace {
858// returns true if the read/written rect intersects the src/dst and false if not.
859bool clip_srcrect_and_dstpoint(const GrSurface* dst,
860                               const GrSurface* src,
861                               const SkIRect& srcRect,
862                               const SkIPoint& dstPoint,
863                               SkIRect* clippedSrcRect,
864                               SkIPoint* clippedDstPoint) {
865    *clippedSrcRect = srcRect;
866    *clippedDstPoint = dstPoint;
867
868    // clip the left edge to src and dst bounds, adjusting dstPoint if necessary
869    if (clippedSrcRect->fLeft < 0) {
870        clippedDstPoint->fX -= clippedSrcRect->fLeft;
871        clippedSrcRect->fLeft = 0;
872    }
873    if (clippedDstPoint->fX < 0) {
874        clippedSrcRect->fLeft -= clippedDstPoint->fX;
875        clippedDstPoint->fX = 0;
876    }
877
878    // clip the top edge to src and dst bounds, adjusting dstPoint if necessary
879    if (clippedSrcRect->fTop < 0) {
880        clippedDstPoint->fY -= clippedSrcRect->fTop;
881        clippedSrcRect->fTop = 0;
882    }
883    if (clippedDstPoint->fY < 0) {
884        clippedSrcRect->fTop -= clippedDstPoint->fY;
885        clippedDstPoint->fY = 0;
886    }
887
888    // clip the right edge to the src and dst bounds.
889    if (clippedSrcRect->fRight > src->width()) {
890        clippedSrcRect->fRight = src->width();
891    }
892    if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) {
893        clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX;
894    }
895
896    // clip the bottom edge to the src and dst bounds.
897    if (clippedSrcRect->fBottom > src->height()) {
898        clippedSrcRect->fBottom = src->height();
899    }
900    if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) {
901        clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY;
902    }
903
904    // The above clipping steps may have inverted the rect if it didn't intersect either the src or
905    // dst bounds.
906    return !clippedSrcRect->isEmpty();
907}
908}
909
910bool GrDrawTarget::copySurface(GrSurface* dst,
911                               GrSurface* src,
912                               const SkIRect& srcRect,
913                               const SkIPoint& dstPoint) {
914    SkASSERT(dst);
915    SkASSERT(src);
916
917    SkIRect clippedSrcRect;
918    SkIPoint clippedDstPoint;
919    // If the rect is outside the src or dst then we've already succeeded.
920    if (!clip_srcrect_and_dstpoint(dst,
921                                   src,
922                                   srcRect,
923                                   dstPoint,
924                                   &clippedSrcRect,
925                                   &clippedDstPoint)) {
926        SkASSERT(this->canCopySurface(dst, src, srcRect, dstPoint));
927        return true;
928    }
929
930    bool result = this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
931    SkASSERT(result == this->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint));
932    return result;
933}
934
935bool GrDrawTarget::canCopySurface(GrSurface* dst,
936                                  GrSurface* src,
937                                  const SkIRect& srcRect,
938                                  const SkIPoint& dstPoint) {
939    SkASSERT(dst);
940    SkASSERT(src);
941
942    SkIRect clippedSrcRect;
943    SkIPoint clippedDstPoint;
944    // If the rect is outside the src or dst then we're guaranteed success
945    if (!clip_srcrect_and_dstpoint(dst,
946                                   src,
947                                   srcRect,
948                                   dstPoint,
949                                   &clippedSrcRect,
950                                   &clippedDstPoint)) {
951        return true;
952    }
953    return this->onCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
954}
955
956bool GrDrawTarget::onCanCopySurface(GrSurface* dst,
957                                    GrSurface* src,
958                                    const SkIRect& srcRect,
959                                    const SkIPoint& dstPoint) {
960    // Check that the read/write rects are contained within the src/dst bounds.
961    SkASSERT(!srcRect.isEmpty());
962    SkASSERT(SkIRect::MakeWH(src->width(), src->height()).contains(srcRect));
963    SkASSERT(dstPoint.fX >= 0 && dstPoint.fY >= 0);
964    SkASSERT(dstPoint.fX + srcRect.width() <= dst->width() &&
965             dstPoint.fY + srcRect.height() <= dst->height());
966
967    return !dst->isSameAs(src) && dst->asRenderTarget() && src->asTexture();
968}
969
970bool GrDrawTarget::onCopySurface(GrSurface* dst,
971                                 GrSurface* src,
972                                 const SkIRect& srcRect,
973                                 const SkIPoint& dstPoint) {
974    if (!GrDrawTarget::onCanCopySurface(dst, src, srcRect, dstPoint)) {
975        return false;
976    }
977
978    GrRenderTarget* rt = dst->asRenderTarget();
979    GrTexture* tex = src->asTexture();
980
981    GrDrawTarget::AutoStateRestore asr(this, kReset_ASRInit);
982    this->drawState()->setRenderTarget(rt);
983    SkMatrix matrix;
984    matrix.setTranslate(SkIntToScalar(srcRect.fLeft - dstPoint.fX),
985                        SkIntToScalar(srcRect.fTop - dstPoint.fY));
986    matrix.postIDiv(tex->width(), tex->height());
987    this->drawState()->addColorTextureProcessor(tex, matrix);
988    SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX,
989                                        dstPoint.fY,
990                                        srcRect.width(),
991                                        srcRect.height());
992    this->drawSimpleRect(dstRect);
993    return true;
994}
995
996void GrDrawTarget::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) {
997    // Make the dst of the copy be a render target because the default copySurface draws to the dst.
998    desc->fOrigin = kDefault_GrSurfaceOrigin;
999    desc->fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
1000    desc->fConfig = src->config();
1001}
1002
1003///////////////////////////////////////////////////////////////////////////////
1004
1005void GrDrawTargetCaps::reset() {
1006    fMipMapSupport = false;
1007    fNPOTTextureTileSupport = false;
1008    fTwoSidedStencilSupport = false;
1009    fStencilWrapOpsSupport = false;
1010    fHWAALineSupport = false;
1011    fShaderDerivativeSupport = false;
1012    fGeometryShaderSupport = false;
1013    fDualSourceBlendingSupport = false;
1014    fPathRenderingSupport = false;
1015    fDstReadInShaderSupport = false;
1016    fDiscardRenderTargetSupport = false;
1017    fReuseScratchTextures = true;
1018    fGpuTracingSupport = false;
1019    fCompressedTexSubImageSupport = false;
1020
1021    fMapBufferFlags = kNone_MapFlags;
1022
1023    fMaxRenderTargetSize = 0;
1024    fMaxTextureSize = 0;
1025    fMaxSampleCount = 0;
1026
1027    memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport));
1028    memset(fConfigTextureSupport, 0, sizeof(fConfigTextureSupport));
1029}
1030
1031GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
1032    fMipMapSupport = other.fMipMapSupport;
1033    fNPOTTextureTileSupport = other.fNPOTTextureTileSupport;
1034    fTwoSidedStencilSupport = other.fTwoSidedStencilSupport;
1035    fStencilWrapOpsSupport = other.fStencilWrapOpsSupport;
1036    fHWAALineSupport = other.fHWAALineSupport;
1037    fShaderDerivativeSupport = other.fShaderDerivativeSupport;
1038    fGeometryShaderSupport = other.fGeometryShaderSupport;
1039    fDualSourceBlendingSupport = other.fDualSourceBlendingSupport;
1040    fPathRenderingSupport = other.fPathRenderingSupport;
1041    fDstReadInShaderSupport = other.fDstReadInShaderSupport;
1042    fDiscardRenderTargetSupport = other.fDiscardRenderTargetSupport;
1043    fReuseScratchTextures = other.fReuseScratchTextures;
1044    fGpuTracingSupport = other.fGpuTracingSupport;
1045    fCompressedTexSubImageSupport = other.fCompressedTexSubImageSupport;
1046
1047    fMapBufferFlags = other.fMapBufferFlags;
1048
1049    fMaxRenderTargetSize = other.fMaxRenderTargetSize;
1050    fMaxTextureSize = other.fMaxTextureSize;
1051    fMaxSampleCount = other.fMaxSampleCount;
1052
1053    memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport));
1054    memcpy(fConfigTextureSupport, other.fConfigTextureSupport, sizeof(fConfigTextureSupport));
1055
1056    return *this;
1057}
1058
1059static SkString map_flags_to_string(uint32_t flags) {
1060    SkString str;
1061    if (GrDrawTargetCaps::kNone_MapFlags == flags) {
1062        str = "none";
1063    } else {
1064        SkASSERT(GrDrawTargetCaps::kCanMap_MapFlag & flags);
1065        SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kCanMap_MapFlag);
1066        str = "can_map";
1067
1068        if (GrDrawTargetCaps::kSubset_MapFlag & flags) {
1069            str.append(" partial");
1070        } else {
1071            str.append(" full");
1072        }
1073        SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kSubset_MapFlag);
1074    }
1075    SkASSERT(0 == flags); // Make sure we handled all the flags.
1076    return str;
1077}
1078
1079SkString GrDrawTargetCaps::dump() const {
1080    SkString r;
1081    static const char* gNY[] = {"NO", "YES"};
1082    r.appendf("MIP Map Support              : %s\n", gNY[fMipMapSupport]);
1083    r.appendf("NPOT Texture Tile Support    : %s\n", gNY[fNPOTTextureTileSupport]);
1084    r.appendf("Two Sided Stencil Support    : %s\n", gNY[fTwoSidedStencilSupport]);
1085    r.appendf("Stencil Wrap Ops  Support    : %s\n", gNY[fStencilWrapOpsSupport]);
1086    r.appendf("HW AA Lines Support          : %s\n", gNY[fHWAALineSupport]);
1087    r.appendf("Shader Derivative Support    : %s\n", gNY[fShaderDerivativeSupport]);
1088    r.appendf("Geometry Shader Support      : %s\n", gNY[fGeometryShaderSupport]);
1089    r.appendf("Dual Source Blending Support : %s\n", gNY[fDualSourceBlendingSupport]);
1090    r.appendf("Path Rendering Support       : %s\n", gNY[fPathRenderingSupport]);
1091    r.appendf("Dst Read In Shader Support   : %s\n", gNY[fDstReadInShaderSupport]);
1092    r.appendf("Discard Render Target Support: %s\n", gNY[fDiscardRenderTargetSupport]);
1093    r.appendf("Reuse Scratch Textures       : %s\n", gNY[fReuseScratchTextures]);
1094    r.appendf("Gpu Tracing Support          : %s\n", gNY[fGpuTracingSupport]);
1095    r.appendf("Compressed Update Support    : %s\n", gNY[fCompressedTexSubImageSupport]);
1096    r.appendf("Max Texture Size             : %d\n", fMaxTextureSize);
1097    r.appendf("Max Render Target Size       : %d\n", fMaxRenderTargetSize);
1098    r.appendf("Max Sample Count             : %d\n", fMaxSampleCount);
1099
1100    r.appendf("Map Buffer Support           : %s\n", map_flags_to_string(fMapBufferFlags).c_str());
1101
1102    static const char* kConfigNames[] = {
1103        "Unknown",  // kUnknown_GrPixelConfig
1104        "Alpha8",   // kAlpha_8_GrPixelConfig,
1105        "Index8",   // kIndex_8_GrPixelConfig,
1106        "RGB565",   // kRGB_565_GrPixelConfig,
1107        "RGBA444",  // kRGBA_4444_GrPixelConfig,
1108        "RGBA8888", // kRGBA_8888_GrPixelConfig,
1109        "BGRA8888", // kBGRA_8888_GrPixelConfig,
1110        "ETC1",     // kETC1_GrPixelConfig,
1111        "LATC",     // kLATC_GrPixelConfig,
1112        "R11EAC",   // kR11_EAC_GrPixelConfig,
1113        "ASTC12x12",// kASTC_12x12_GrPixelConfig,
1114        "RGBAFloat",  // kRGBA_float_GrPixelConfig
1115    };
1116    GR_STATIC_ASSERT(0  == kUnknown_GrPixelConfig);
1117    GR_STATIC_ASSERT(1  == kAlpha_8_GrPixelConfig);
1118    GR_STATIC_ASSERT(2  == kIndex_8_GrPixelConfig);
1119    GR_STATIC_ASSERT(3  == kRGB_565_GrPixelConfig);
1120    GR_STATIC_ASSERT(4  == kRGBA_4444_GrPixelConfig);
1121    GR_STATIC_ASSERT(5  == kRGBA_8888_GrPixelConfig);
1122    GR_STATIC_ASSERT(6  == kBGRA_8888_GrPixelConfig);
1123    GR_STATIC_ASSERT(7  == kETC1_GrPixelConfig);
1124    GR_STATIC_ASSERT(8  == kLATC_GrPixelConfig);
1125    GR_STATIC_ASSERT(9  == kR11_EAC_GrPixelConfig);
1126    GR_STATIC_ASSERT(10 == kASTC_12x12_GrPixelConfig);
1127    GR_STATIC_ASSERT(11 == kRGBA_float_GrPixelConfig);
1128    GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);
1129
1130    SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]);
1131    SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]);
1132
1133    for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
1134        r.appendf("%s is renderable: %s, with MSAA: %s\n",
1135                  kConfigNames[i],
1136                  gNY[fConfigRenderSupport[i][0]],
1137                  gNY[fConfigRenderSupport[i][1]]);
1138    }
1139
1140    SkASSERT(!fConfigTextureSupport[kUnknown_GrPixelConfig]);
1141
1142    for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
1143        r.appendf("%s is uploadable to a texture: %s\n",
1144                  kConfigNames[i],
1145                  gNY[fConfigTextureSupport[i]]);
1146    }
1147
1148    return r;
1149}
1150
1151uint32_t GrDrawTargetCaps::CreateUniqueID() {
1152    static int32_t gUniqueID = SK_InvalidUniqueID;
1153    uint32_t id;
1154    do {
1155        id = static_cast<uint32_t>(sk_atomic_inc(&gUniqueID) + 1);
1156    } while (id == SK_InvalidUniqueID);
1157    return id;
1158}
1159
1160