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