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