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