GrDrawTarget.cpp revision cb8979d088a66ebaf41f10ba6f5c830615aa0e03
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 "GrBufferAllocPool.h"
13#include "GrContext.h"
14#include "GrDrawTargetCaps.h"
15#include "GrPath.h"
16#include "GrPipeline.h"
17#include "GrMemoryPool.h"
18#include "GrRenderTarget.h"
19#include "GrRenderTargetPriv.h"
20#include "GrSurfacePriv.h"
21#include "GrTemplates.h"
22#include "GrTexture.h"
23#include "GrVertexBuffer.h"
24
25#include "SkStrokeRec.h"
26
27////////////////////////////////////////////////////////////////////////////////
28
29#define DEBUG_INVAL_BUFFER 0xdeadcafe
30#define DEBUG_INVAL_START_IDX -1
31
32GrDrawTarget::GrDrawTarget(GrContext* context,
33                           GrVertexBufferAllocPool* vpool,
34                           GrIndexBufferAllocPool* ipool)
35    : fContext(context)
36    , fCaps(SkRef(context->getGpu()->caps()))
37    , fGpuTraceMarkerCount(0)
38    , fVertexPool(vpool)
39    , fIndexPool(ipool)
40    , fFlushing(false) {
41    SkASSERT(context);
42}
43
44////////////////////////////////////////////////////////////////////////////////
45
46bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
47                                           const GrProcOptInfo& colorPOI,
48                                           const GrProcOptInfo& coveragePOI,
49                                           GrDeviceCoordTexture* dstCopy,
50                                           const SkRect* drawBounds) {
51    if (!pipelineBuilder.willXPNeedDstCopy(*this->caps(), colorPOI, coveragePOI)) {
52        return true;
53    }
54
55    GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
56
57    if (this->caps()->textureBarrierSupport()) {
58        if (GrTexture* rtTex = rt->asTexture()) {
59            // The render target is a texture, se we can read from it directly in the shader. The XP
60            // will be responsible to detect this situation and request a texture barrier.
61            dstCopy->setTexture(rtTex);
62            dstCopy->setOffset(0, 0);
63            return true;
64        }
65    }
66
67    SkIRect copyRect;
68    pipelineBuilder.clip().getConservativeBounds(rt, &copyRect);
69
70    if (drawBounds) {
71        SkIRect drawIBounds;
72        drawBounds->roundOut(&drawIBounds);
73        if (!copyRect.intersect(drawIBounds)) {
74#ifdef SK_DEBUG
75            SkDebugf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n");
76#endif
77            return false;
78        }
79    } else {
80#ifdef SK_DEBUG
81        //SkDebugf("No dev bounds when dst copy is made.\n");
82#endif
83    }
84
85    // MSAA consideration: When there is support for reading MSAA samples in the shader we could
86    // have per-sample dst values by making the copy multisampled.
87    GrSurfaceDesc desc;
88    if (!this->getGpu()->initCopySurfaceDstDesc(rt, &desc)) {
89        desc.fOrigin = kDefault_GrSurfaceOrigin;
90        desc.fFlags = kRenderTarget_GrSurfaceFlag;
91        desc.fConfig = rt->config();
92    }
93
94
95    desc.fWidth = copyRect.width();
96    desc.fHeight = copyRect.height();
97
98    SkAutoTUnref<GrTexture> copy(fContext->textureProvider()->refScratchTexture(desc,
99        GrTextureProvider::kApprox_ScratchTexMatch));
100
101    if (!copy) {
102        SkDebugf("Failed to create temporary copy of destination texture.\n");
103        return false;
104    }
105    SkIPoint dstPoint = {0, 0};
106    if (this->copySurface(copy, rt, copyRect, dstPoint)) {
107        dstCopy->setTexture(copy);
108        dstCopy->setOffset(copyRect.fLeft, copyRect.fTop);
109        return true;
110    } else {
111        return false;
112    }
113}
114
115void GrDrawTarget::reset() {
116    fVertexPool->reset();
117    fIndexPool->reset();
118
119    this->onReset();
120}
121
122void GrDrawTarget::flush() {
123    if (fFlushing) {
124        return;
125    }
126    fFlushing = true;
127
128    this->getGpu()->saveActiveTraceMarkers();
129
130    this->onFlush();
131
132    this->getGpu()->restoreActiveTraceMarkers();
133
134    fFlushing = false;
135    this->reset();
136}
137
138void GrDrawTarget::drawBatch(GrPipelineBuilder* pipelineBuilder,
139                             GrBatch* batch) {
140    SkASSERT(pipelineBuilder);
141    // TODO some kind of checkdraw, but not at this level
142
143    // Setup clip
144    GrScissorState scissorState;
145    GrPipelineBuilder::AutoRestoreFragmentProcessors arfp;
146    GrPipelineBuilder::AutoRestoreStencil ars;
147    if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, &batch->bounds())) {
148        return;
149    }
150
151    // Batch bounds are tight, so for dev copies
152    // TODO move this into setupDstReadIfNecessary when paths are in batch
153    SkRect bounds = batch->bounds();
154    bounds.outset(0.5f, 0.5f);
155
156    GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, batch, &bounds,
157                                            this);
158    if (pipelineInfo.mustSkipDraw()) {
159        return;
160    }
161
162    this->onDrawBatch(batch, pipelineInfo);
163}
164
165static const GrStencilSettings& winding_path_stencil_settings() {
166    GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
167        kIncClamp_StencilOp,
168        kIncClamp_StencilOp,
169        kAlwaysIfInClip_StencilFunc,
170        0xFFFF, 0xFFFF, 0xFFFF);
171    return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
172}
173
174static const GrStencilSettings& even_odd_path_stencil_settings() {
175    GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
176        kInvert_StencilOp,
177        kInvert_StencilOp,
178        kAlwaysIfInClip_StencilFunc,
179        0xFFFF, 0xFFFF, 0xFFFF);
180    return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
181}
182
183void GrDrawTarget::getPathStencilSettingsForFilltype(GrPathRendering::FillType fill,
184                                                     const GrStencilAttachment* sb,
185                                                     GrStencilSettings* outStencilSettings) {
186
187    switch (fill) {
188        default:
189            SkFAIL("Unexpected path fill.");
190        case GrPathRendering::kWinding_FillType:
191            *outStencilSettings = winding_path_stencil_settings();
192            break;
193        case GrPathRendering::kEvenOdd_FillType:
194            *outStencilSettings = even_odd_path_stencil_settings();
195            break;
196    }
197    this->clipMaskManager()->adjustPathStencilParams(sb, outStencilSettings);
198}
199
200void GrDrawTarget::stencilPath(GrPipelineBuilder* pipelineBuilder,
201                               const GrPathProcessor* pathProc,
202                               const GrPath* path,
203                               GrPathRendering::FillType fill) {
204    // TODO: extract portions of checkDraw that are relevant to path stenciling.
205    SkASSERT(path);
206    SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
207    SkASSERT(pipelineBuilder);
208
209    // Setup clip
210    GrScissorState scissorState;
211    GrPipelineBuilder::AutoRestoreFragmentProcessors arfp;
212    GrPipelineBuilder::AutoRestoreStencil ars;
213    if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, NULL)) {
214        return;
215    }
216
217    // set stencil settings for path
218    GrStencilSettings stencilSettings;
219    GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
220    GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment();
221    this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
222
223    this->onStencilPath(*pipelineBuilder, pathProc, path, scissorState, stencilSettings);
224}
225
226void GrDrawTarget::drawPath(GrPipelineBuilder* pipelineBuilder,
227                            const GrPathProcessor* pathProc,
228                            const GrPath* path,
229                            GrPathRendering::FillType fill) {
230    // TODO: extract portions of checkDraw that are relevant to path rendering.
231    SkASSERT(path);
232    SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
233    SkASSERT(pipelineBuilder);
234
235    SkRect devBounds = path->getBounds();
236    pathProc->viewMatrix().mapRect(&devBounds);
237
238    // Setup clip
239    GrScissorState scissorState;
240    GrPipelineBuilder::AutoRestoreFragmentProcessors arfp;
241    GrPipelineBuilder::AutoRestoreStencil ars;
242    if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, &devBounds)) {
243       return;
244    }
245
246    // set stencil settings for path
247    GrStencilSettings stencilSettings;
248    GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
249    GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment();
250    this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
251
252    GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, pathProc, &devBounds,
253                                            this);
254    if (pipelineInfo.mustSkipDraw()) {
255        return;
256    }
257
258    this->onDrawPath(pathProc, path, stencilSettings, pipelineInfo);
259}
260
261void GrDrawTarget::drawPaths(GrPipelineBuilder* pipelineBuilder,
262                             const GrPathProcessor* pathProc,
263                             const GrPathRange* pathRange,
264                             const void* indices,
265                             PathIndexType indexType,
266                             const float transformValues[],
267                             PathTransformType transformType,
268                             int count,
269                             GrPathRendering::FillType fill) {
270    SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
271    SkASSERT(pathRange);
272    SkASSERT(indices);
273    SkASSERT(0 == reinterpret_cast<long>(indices) % GrPathRange::PathIndexSizeInBytes(indexType));
274    SkASSERT(transformValues);
275    SkASSERT(pipelineBuilder);
276
277    // Setup clip
278    GrScissorState scissorState;
279    GrPipelineBuilder::AutoRestoreFragmentProcessors arfp;
280    GrPipelineBuilder::AutoRestoreStencil ars;
281
282    if (!this->setupClip(pipelineBuilder, &arfp, &ars, &scissorState, NULL)) {
283        return;
284    }
285
286    // set stencil settings for path
287    GrStencilSettings stencilSettings;
288    GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
289    GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment();
290    this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
291
292    // Don't compute a bounding box for dst copy texture, we'll opt
293    // instead for it to just copy the entire dst. Realistically this is a moot
294    // point, because any context that supports NV_path_rendering will also
295    // support NV_blend_equation_advanced.
296    GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, pathProc, NULL, this);
297    if (pipelineInfo.mustSkipDraw()) {
298        return;
299    }
300
301    this->onDrawPaths(pathProc, pathRange, indices, indexType, transformValues,
302                      transformType, count, stencilSettings, pipelineInfo);
303}
304
305void GrDrawTarget::clear(const SkIRect* rect,
306                         GrColor color,
307                         bool canIgnoreRect,
308                         GrRenderTarget* renderTarget) {
309    if (fCaps->useDrawInsteadOfClear()) {
310        // This works around a driver bug with clear by drawing a rect instead.
311        // The driver will ignore a clear if it is the only thing rendered to a
312        // target before the target is read.
313        SkIRect rtRect = SkIRect::MakeWH(renderTarget->width(), renderTarget->height());
314        if (NULL == rect || canIgnoreRect || rect->contains(rtRect)) {
315            rect = &rtRect;
316            // We first issue a discard() since that may help tilers.
317            this->discard(renderTarget);
318        }
319
320        GrPipelineBuilder pipelineBuilder;
321        pipelineBuilder.setRenderTarget(renderTarget);
322
323        this->drawSimpleRect(&pipelineBuilder, color, SkMatrix::I(), *rect);
324    } else {
325        this->onClear(rect, color, canIgnoreRect, renderTarget);
326    }
327}
328
329typedef GrTraceMarkerSet::Iter TMIter;
330void GrDrawTarget::saveActiveTraceMarkers() {
331    if (this->caps()->gpuTracingSupport()) {
332        SkASSERT(0 == fStoredTraceMarkers.count());
333        fStoredTraceMarkers.addSet(fActiveTraceMarkers);
334        for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) {
335            this->removeGpuTraceMarker(&(*iter));
336        }
337    }
338}
339
340void GrDrawTarget::restoreActiveTraceMarkers() {
341    if (this->caps()->gpuTracingSupport()) {
342        SkASSERT(0 == fActiveTraceMarkers.count());
343        for (TMIter iter = fStoredTraceMarkers.begin(); iter != fStoredTraceMarkers.end(); ++iter) {
344            this->addGpuTraceMarker(&(*iter));
345        }
346        for (TMIter iter = fActiveTraceMarkers.begin(); iter != fActiveTraceMarkers.end(); ++iter) {
347            this->fStoredTraceMarkers.remove(*iter);
348        }
349    }
350}
351
352void GrDrawTarget::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
353    if (this->caps()->gpuTracingSupport()) {
354        SkASSERT(fGpuTraceMarkerCount >= 0);
355        this->fActiveTraceMarkers.add(*marker);
356        ++fGpuTraceMarkerCount;
357    }
358}
359
360void GrDrawTarget::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
361    if (this->caps()->gpuTracingSupport()) {
362        SkASSERT(fGpuTraceMarkerCount >= 1);
363        this->fActiveTraceMarkers.remove(*marker);
364        --fGpuTraceMarkerCount;
365    }
366}
367
368////////////////////////////////////////////////////////////////////////////////
369
370namespace {
371// returns true if the read/written rect intersects the src/dst and false if not.
372bool clip_srcrect_and_dstpoint(const GrSurface* dst,
373                               const GrSurface* src,
374                               const SkIRect& srcRect,
375                               const SkIPoint& dstPoint,
376                               SkIRect* clippedSrcRect,
377                               SkIPoint* clippedDstPoint) {
378    *clippedSrcRect = srcRect;
379    *clippedDstPoint = dstPoint;
380
381    // clip the left edge to src and dst bounds, adjusting dstPoint if necessary
382    if (clippedSrcRect->fLeft < 0) {
383        clippedDstPoint->fX -= clippedSrcRect->fLeft;
384        clippedSrcRect->fLeft = 0;
385    }
386    if (clippedDstPoint->fX < 0) {
387        clippedSrcRect->fLeft -= clippedDstPoint->fX;
388        clippedDstPoint->fX = 0;
389    }
390
391    // clip the top edge to src and dst bounds, adjusting dstPoint if necessary
392    if (clippedSrcRect->fTop < 0) {
393        clippedDstPoint->fY -= clippedSrcRect->fTop;
394        clippedSrcRect->fTop = 0;
395    }
396    if (clippedDstPoint->fY < 0) {
397        clippedSrcRect->fTop -= clippedDstPoint->fY;
398        clippedDstPoint->fY = 0;
399    }
400
401    // clip the right edge to the src and dst bounds.
402    if (clippedSrcRect->fRight > src->width()) {
403        clippedSrcRect->fRight = src->width();
404    }
405    if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) {
406        clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX;
407    }
408
409    // clip the bottom edge to the src and dst bounds.
410    if (clippedSrcRect->fBottom > src->height()) {
411        clippedSrcRect->fBottom = src->height();
412    }
413    if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) {
414        clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY;
415    }
416
417    // The above clipping steps may have inverted the rect if it didn't intersect either the src or
418    // dst bounds.
419    return !clippedSrcRect->isEmpty();
420}
421}
422
423bool GrDrawTarget::copySurface(GrSurface* dst,
424                               GrSurface* src,
425                               const SkIRect& srcRect,
426                               const SkIPoint& dstPoint) {
427    SkASSERT(dst);
428    SkASSERT(src);
429
430    SkIRect clippedSrcRect;
431    SkIPoint clippedDstPoint;
432    // If the rect is outside the src or dst then we've already succeeded.
433    if (!clip_srcrect_and_dstpoint(dst,
434                                   src,
435                                   srcRect,
436                                   dstPoint,
437                                   &clippedSrcRect,
438                                   &clippedDstPoint)) {
439        return true;
440    }
441
442    if (this->getGpu()->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint)) {
443        this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
444        return true;
445    }
446
447    GrRenderTarget* rt = dst->asRenderTarget();
448    GrTexture* tex = src->asTexture();
449
450    if ((dst == src) || !rt || !tex) {
451        return false;
452    }
453
454    GrPipelineBuilder pipelineBuilder;
455    pipelineBuilder.setRenderTarget(rt);
456    SkMatrix matrix;
457    matrix.setTranslate(SkIntToScalar(clippedSrcRect.fLeft - clippedDstPoint.fX),
458                        SkIntToScalar(clippedSrcRect.fTop - clippedDstPoint.fY));
459    matrix.postIDiv(tex->width(), tex->height());
460    pipelineBuilder.addColorTextureProcessor(tex, matrix);
461    SkIRect dstRect = SkIRect::MakeXYWH(clippedDstPoint.fX,
462                                        clippedDstPoint.fY,
463                                        clippedSrcRect.width(),
464                                        clippedSrcRect.height());
465    this->drawSimpleRect(&pipelineBuilder, GrColor_WHITE, SkMatrix::I(), dstRect);
466    return true;
467}
468
469bool GrDrawTarget::canCopySurface(const GrSurface* dst,
470                                  const GrSurface* src,
471                                  const SkIRect& srcRect,
472                                  const SkIPoint& dstPoint) {
473    SkASSERT(dst);
474    SkASSERT(src);
475
476    SkIRect clippedSrcRect;
477    SkIPoint clippedDstPoint;
478    // If the rect is outside the src or dst then we're guaranteed success
479    if (!clip_srcrect_and_dstpoint(dst,
480                                   src,
481                                   srcRect,
482                                   dstPoint,
483                                   &clippedSrcRect,
484                                   &clippedDstPoint)) {
485        return true;
486    }
487    return ((dst != src) && dst->asRenderTarget() && src->asTexture()) ||
488           this->getGpu()->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
489}
490
491void GrDrawTarget::setupPipeline(const PipelineInfo& pipelineInfo,
492                                 GrPipeline* pipeline) {
493    SkNEW_PLACEMENT_ARGS(pipeline, GrPipeline, (*pipelineInfo.fPipelineBuilder,
494                                                pipelineInfo.fColorPOI,
495                                                pipelineInfo.fCoveragePOI,
496                                                *this->caps(),
497                                                *pipelineInfo.fScissor,
498                                                &pipelineInfo.fDstCopy));
499}
500///////////////////////////////////////////////////////////////////////////////
501
502GrDrawTarget::PipelineInfo::PipelineInfo(GrPipelineBuilder* pipelineBuilder,
503                                         GrScissorState* scissor,
504                                         const GrPrimitiveProcessor* primProc,
505                                         const SkRect* devBounds,
506                                         GrDrawTarget* target)
507    : fPipelineBuilder(pipelineBuilder)
508    , fScissor(scissor) {
509    fColorPOI = fPipelineBuilder->colorProcInfo(primProc);
510    fCoveragePOI = fPipelineBuilder->coverageProcInfo(primProc);
511    if (!target->setupDstReadIfNecessary(*fPipelineBuilder, fColorPOI, fCoveragePOI,
512                                         &fDstCopy, devBounds)) {
513        fPipelineBuilder = NULL;
514    }
515}
516
517GrDrawTarget::PipelineInfo::PipelineInfo(GrPipelineBuilder* pipelineBuilder,
518                                         GrScissorState* scissor,
519                                         const GrBatch* batch,
520                                         const SkRect* devBounds,
521                                         GrDrawTarget* target)
522    : fPipelineBuilder(pipelineBuilder)
523    , fScissor(scissor) {
524    fColorPOI = fPipelineBuilder->colorProcInfo(batch);
525    fCoveragePOI = fPipelineBuilder->coverageProcInfo(batch);
526    if (!target->setupDstReadIfNecessary(*fPipelineBuilder, fColorPOI, fCoveragePOI,
527                                         &fDstCopy, devBounds)) {
528        fPipelineBuilder = NULL;
529    }
530}
531
532///////////////////////////////////////////////////////////////////////////////
533
534void GrShaderCaps::reset() {
535    fShaderDerivativeSupport = false;
536    fGeometryShaderSupport = false;
537    fPathRenderingSupport = false;
538    fDstReadInShaderSupport = false;
539    fDualSourceBlendingSupport = false;
540
541    fShaderPrecisionVaries = false;
542}
543
544GrShaderCaps& GrShaderCaps::operator=(const GrShaderCaps& other) {
545    fShaderDerivativeSupport = other.fShaderDerivativeSupport;
546    fGeometryShaderSupport = other.fGeometryShaderSupport;
547    fPathRenderingSupport = other.fPathRenderingSupport;
548    fDstReadInShaderSupport = other.fDstReadInShaderSupport;
549    fDualSourceBlendingSupport = other.fDualSourceBlendingSupport;
550
551    fShaderPrecisionVaries = other.fShaderPrecisionVaries;
552    for (int s = 0; s < kGrShaderTypeCount; ++s) {
553        for (int p = 0; p < kGrSLPrecisionCount; ++p) {
554            fFloatPrecisions[s][p] = other.fFloatPrecisions[s][p];
555        }
556    }
557    return *this;
558}
559
560static const char* shader_type_to_string(GrShaderType type) {
561    switch (type) {
562    case kVertex_GrShaderType:
563        return "vertex";
564    case kGeometry_GrShaderType:
565        return "geometry";
566    case kFragment_GrShaderType:
567        return "fragment";
568    }
569    return "";
570}
571
572static const char* precision_to_string(GrSLPrecision p) {
573    switch (p) {
574    case kLow_GrSLPrecision:
575        return "low";
576    case kMedium_GrSLPrecision:
577        return "medium";
578    case kHigh_GrSLPrecision:
579        return "high";
580    }
581    return "";
582}
583
584SkString GrShaderCaps::dump() const {
585    SkString r;
586    static const char* gNY[] = { "NO", "YES" };
587    r.appendf("Shader Derivative Support          : %s\n", gNY[fShaderDerivativeSupport]);
588    r.appendf("Geometry Shader Support            : %s\n", gNY[fGeometryShaderSupport]);
589    r.appendf("Path Rendering Support             : %s\n", gNY[fPathRenderingSupport]);
590    r.appendf("Dst Read In Shader Support         : %s\n", gNY[fDstReadInShaderSupport]);
591    r.appendf("Dual Source Blending Support       : %s\n", gNY[fDualSourceBlendingSupport]);
592
593    r.appendf("Shader Float Precisions (varies: %s):\n", gNY[fShaderPrecisionVaries]);
594
595    for (int s = 0; s < kGrShaderTypeCount; ++s) {
596        GrShaderType shaderType = static_cast<GrShaderType>(s);
597        r.appendf("\t%s:\n", shader_type_to_string(shaderType));
598        for (int p = 0; p < kGrSLPrecisionCount; ++p) {
599            if (fFloatPrecisions[s][p].supported()) {
600                GrSLPrecision precision = static_cast<GrSLPrecision>(p);
601                r.appendf("\t\t%s: log_low: %d log_high: %d bits: %d\n",
602                    precision_to_string(precision),
603                    fFloatPrecisions[s][p].fLogRangeLow,
604                    fFloatPrecisions[s][p].fLogRangeHigh,
605                    fFloatPrecisions[s][p].fBits);
606            }
607        }
608    }
609
610    return r;
611}
612
613///////////////////////////////////////////////////////////////////////////////
614
615void GrDrawTargetCaps::reset() {
616    fMipMapSupport = false;
617    fNPOTTextureTileSupport = false;
618    fTwoSidedStencilSupport = false;
619    fStencilWrapOpsSupport = false;
620    fDiscardRenderTargetSupport = false;
621    fReuseScratchTextures = true;
622    fGpuTracingSupport = false;
623    fCompressedTexSubImageSupport = false;
624    fOversizedStencilSupport = false;
625    fTextureBarrierSupport = false;
626
627    fUseDrawInsteadOfClear = false;
628
629    fMapBufferFlags = kNone_MapFlags;
630
631    fMaxRenderTargetSize = 0;
632    fMaxTextureSize = 0;
633    fMaxSampleCount = 0;
634
635    memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport));
636    memset(fConfigTextureSupport, 0, sizeof(fConfigTextureSupport));
637}
638
639GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
640    fMipMapSupport = other.fMipMapSupport;
641    fNPOTTextureTileSupport = other.fNPOTTextureTileSupport;
642    fTwoSidedStencilSupport = other.fTwoSidedStencilSupport;
643    fStencilWrapOpsSupport = other.fStencilWrapOpsSupport;
644    fDiscardRenderTargetSupport = other.fDiscardRenderTargetSupport;
645    fReuseScratchTextures = other.fReuseScratchTextures;
646    fGpuTracingSupport = other.fGpuTracingSupport;
647    fCompressedTexSubImageSupport = other.fCompressedTexSubImageSupport;
648    fOversizedStencilSupport = other.fOversizedStencilSupport;
649    fTextureBarrierSupport = other.fTextureBarrierSupport;
650
651    fUseDrawInsteadOfClear = other.fUseDrawInsteadOfClear;
652
653    fMapBufferFlags = other.fMapBufferFlags;
654
655    fMaxRenderTargetSize = other.fMaxRenderTargetSize;
656    fMaxTextureSize = other.fMaxTextureSize;
657    fMaxSampleCount = other.fMaxSampleCount;
658
659    memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport));
660    memcpy(fConfigTextureSupport, other.fConfigTextureSupport, sizeof(fConfigTextureSupport));
661
662    return *this;
663}
664
665static SkString map_flags_to_string(uint32_t flags) {
666    SkString str;
667    if (GrDrawTargetCaps::kNone_MapFlags == flags) {
668        str = "none";
669    } else {
670        SkASSERT(GrDrawTargetCaps::kCanMap_MapFlag & flags);
671        SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kCanMap_MapFlag);
672        str = "can_map";
673
674        if (GrDrawTargetCaps::kSubset_MapFlag & flags) {
675            str.append(" partial");
676        } else {
677            str.append(" full");
678        }
679        SkDEBUGCODE(flags &= ~GrDrawTargetCaps::kSubset_MapFlag);
680    }
681    SkASSERT(0 == flags); // Make sure we handled all the flags.
682    return str;
683}
684
685SkString GrDrawTargetCaps::dump() const {
686    SkString r;
687    static const char* gNY[] = {"NO", "YES"};
688    r.appendf("MIP Map Support                    : %s\n", gNY[fMipMapSupport]);
689    r.appendf("NPOT Texture Tile Support          : %s\n", gNY[fNPOTTextureTileSupport]);
690    r.appendf("Two Sided Stencil Support          : %s\n", gNY[fTwoSidedStencilSupport]);
691    r.appendf("Stencil Wrap Ops  Support          : %s\n", gNY[fStencilWrapOpsSupport]);
692    r.appendf("Discard Render Target Support      : %s\n", gNY[fDiscardRenderTargetSupport]);
693    r.appendf("Reuse Scratch Textures             : %s\n", gNY[fReuseScratchTextures]);
694    r.appendf("Gpu Tracing Support                : %s\n", gNY[fGpuTracingSupport]);
695    r.appendf("Compressed Update Support          : %s\n", gNY[fCompressedTexSubImageSupport]);
696    r.appendf("Oversized Stencil Support          : %s\n", gNY[fOversizedStencilSupport]);
697    r.appendf("Texture Barrier Support            : %s\n", gNY[fTextureBarrierSupport]);
698    r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]);
699
700    r.appendf("Max Texture Size                   : %d\n", fMaxTextureSize);
701    r.appendf("Max Render Target Size             : %d\n", fMaxRenderTargetSize);
702    r.appendf("Max Sample Count                   : %d\n", fMaxSampleCount);
703
704    r.appendf("Map Buffer Support                 : %s\n",
705              map_flags_to_string(fMapBufferFlags).c_str());
706
707    static const char* kConfigNames[] = {
708        "Unknown",  // kUnknown_GrPixelConfig
709        "Alpha8",   // kAlpha_8_GrPixelConfig,
710        "Index8",   // kIndex_8_GrPixelConfig,
711        "RGB565",   // kRGB_565_GrPixelConfig,
712        "RGBA444",  // kRGBA_4444_GrPixelConfig,
713        "RGBA8888", // kRGBA_8888_GrPixelConfig,
714        "BGRA8888", // kBGRA_8888_GrPixelConfig,
715        "SRGBA8888",// kSRGBA_8888_GrPixelConfig,
716        "ETC1",     // kETC1_GrPixelConfig,
717        "LATC",     // kLATC_GrPixelConfig,
718        "R11EAC",   // kR11_EAC_GrPixelConfig,
719        "ASTC12x12",// kASTC_12x12_GrPixelConfig,
720        "RGBAFloat",// kRGBA_float_GrPixelConfig
721        "AlphaHalf",// kAlpha_half_GrPixelConfig
722    };
723    GR_STATIC_ASSERT(0  == kUnknown_GrPixelConfig);
724    GR_STATIC_ASSERT(1  == kAlpha_8_GrPixelConfig);
725    GR_STATIC_ASSERT(2  == kIndex_8_GrPixelConfig);
726    GR_STATIC_ASSERT(3  == kRGB_565_GrPixelConfig);
727    GR_STATIC_ASSERT(4  == kRGBA_4444_GrPixelConfig);
728    GR_STATIC_ASSERT(5  == kRGBA_8888_GrPixelConfig);
729    GR_STATIC_ASSERT(6  == kBGRA_8888_GrPixelConfig);
730    GR_STATIC_ASSERT(7  == kSRGBA_8888_GrPixelConfig);
731    GR_STATIC_ASSERT(8  == kETC1_GrPixelConfig);
732    GR_STATIC_ASSERT(9  == kLATC_GrPixelConfig);
733    GR_STATIC_ASSERT(10  == kR11_EAC_GrPixelConfig);
734    GR_STATIC_ASSERT(11 == kASTC_12x12_GrPixelConfig);
735    GR_STATIC_ASSERT(12 == kRGBA_float_GrPixelConfig);
736    GR_STATIC_ASSERT(13 == kAlpha_half_GrPixelConfig);
737    GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);
738
739    SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]);
740    SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]);
741
742    for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
743        r.appendf("%s is renderable: %s, with MSAA: %s\n",
744                  kConfigNames[i],
745                  gNY[fConfigRenderSupport[i][0]],
746                  gNY[fConfigRenderSupport[i][1]]);
747    }
748
749    SkASSERT(!fConfigTextureSupport[kUnknown_GrPixelConfig]);
750
751    for (size_t i = 1; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
752        r.appendf("%s is uploadable to a texture: %s\n",
753                  kConfigNames[i],
754                  gNY[fConfigTextureSupport[i]]);
755    }
756
757    return r;
758}
759
760///////////////////////////////////////////////////////////////////////////////////////////////////
761
762bool GrClipTarget::setupClip(GrPipelineBuilder* pipelineBuilder,
763                             GrPipelineBuilder::AutoRestoreFragmentProcessors* arfp,
764                             GrPipelineBuilder::AutoRestoreStencil* ars,
765                             GrScissorState* scissorState,
766                             const SkRect* devBounds) {
767    return fClipMaskManager.setupClipping(pipelineBuilder,
768                                          arfp,
769                                          ars,
770                                          scissorState,
771                                          devBounds);
772}
773