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