gfx/skia/trunk/src/gpu/GrDrawTarget.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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  */
    11 #include "GrDrawTarget.h"
    12 #include "GrContext.h"
    13 #include "GrDrawTargetCaps.h"
    14 #include "GrPath.h"
    15 #include "GrRenderTarget.h"
    16 #include "GrTexture.h"
    17 #include "GrVertexBuffer.h"
    19 #include "SkStrokeRec.h"
    21 ////////////////////////////////////////////////////////////////////////////////
    23 GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) {
    24     fPrimitiveType  = di.fPrimitiveType;
    25     fStartVertex    = di.fStartVertex;
    26     fStartIndex     = di.fStartIndex;
    27     fVertexCount    = di.fVertexCount;
    28     fIndexCount     = di.fIndexCount;
    30     fInstanceCount          = di.fInstanceCount;
    31     fVerticesPerInstance    = di.fVerticesPerInstance;
    32     fIndicesPerInstance     = di.fIndicesPerInstance;
    34     if (NULL != di.fDevBounds) {
    35         SkASSERT(di.fDevBounds == &di.fDevBoundsStorage);
    36         fDevBoundsStorage = di.fDevBoundsStorage;
    37         fDevBounds = &fDevBoundsStorage;
    38     } else {
    39         fDevBounds = NULL;
    40     }
    42     fDstCopy = di.fDstCopy;
    44     return *this;
    45 }
    47 #ifdef SK_DEBUG
    48 bool GrDrawTarget::DrawInfo::isInstanced() const {
    49     if (fInstanceCount > 0) {
    50         SkASSERT(0 == fIndexCount % fIndicesPerInstance);
    51         SkASSERT(0 == fVertexCount % fVerticesPerInstance);
    52         SkASSERT(fIndexCount / fIndicesPerInstance == fInstanceCount);
    53         SkASSERT(fVertexCount / fVerticesPerInstance == fInstanceCount);
    54         // there is no way to specify a non-zero start index to drawIndexedInstances().
    55         SkASSERT(0 == fStartIndex);
    56         return true;
    57     } else {
    58         SkASSERT(!fVerticesPerInstance);
    59         SkASSERT(!fIndicesPerInstance);
    60         return false;
    61     }
    62 }
    63 #endif
    65 void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) {
    66     SkASSERT(this->isInstanced());
    67     SkASSERT(instanceOffset + fInstanceCount >= 0);
    68     fInstanceCount += instanceOffset;
    69     fVertexCount = fVerticesPerInstance * fInstanceCount;
    70     fIndexCount = fIndicesPerInstance * fInstanceCount;
    71 }
    73 void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
    74     fStartVertex += vertexOffset;
    75     SkASSERT(fStartVertex >= 0);
    76 }
    78 void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
    79     SkASSERT(this->isIndexed());
    80     fStartIndex += indexOffset;
    81     SkASSERT(fStartIndex >= 0);
    82 }
    84 ////////////////////////////////////////////////////////////////////////////////
    86 #define DEBUG_INVAL_BUFFER 0xdeadcafe
    87 #define DEBUG_INVAL_START_IDX -1
    89 GrDrawTarget::GrDrawTarget(GrContext* context)
    90     : fClip(NULL)
    91     , fContext(context)
    92     , fPushGpuTraceCount(0) {
    93     SkASSERT(NULL != context);
    95     fDrawState = &fDefaultDrawState;
    96     // We assume that fDrawState always owns a ref to the object it points at.
    97     fDefaultDrawState.ref();
    98     GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
    99 #ifdef SK_DEBUG
   100     geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
   101     geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
   102     geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
   103     geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
   104 #endif
   105     geoSrc.fVertexSrc = kNone_GeometrySrcType;
   106     geoSrc.fIndexSrc  = kNone_GeometrySrcType;
   107 }
   109 GrDrawTarget::~GrDrawTarget() {
   110     SkASSERT(1 == fGeoSrcStateStack.count());
   111     SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
   112     SkASSERT(kNone_GeometrySrcType == geoSrc.fIndexSrc);
   113     SkASSERT(kNone_GeometrySrcType == geoSrc.fVertexSrc);
   114     fDrawState->unref();
   115 }
   117 void GrDrawTarget::releaseGeometry() {
   118     int popCnt = fGeoSrcStateStack.count() - 1;
   119     while (popCnt) {
   120         this->popGeometrySource();
   121         --popCnt;
   122     }
   123     this->resetVertexSource();
   124     this->resetIndexSource();
   125 }
   127 void GrDrawTarget::setClip(const GrClipData* clip) {
   128     clipWillBeSet(clip);
   129     fClip = clip;
   130 }
   132 const GrClipData* GrDrawTarget::getClip() const {
   133     return fClip;
   134 }
   136 void GrDrawTarget::setDrawState(GrDrawState*  drawState) {
   137     SkASSERT(NULL != fDrawState);
   138     if (NULL == drawState) {
   139         drawState = &fDefaultDrawState;
   140     }
   141     if (fDrawState != drawState) {
   142         fDrawState->unref();
   143         drawState->ref();
   144         fDrawState = drawState;
   145     }
   146 }
   148 bool GrDrawTarget::reserveVertexSpace(size_t vertexSize,
   149                                       int vertexCount,
   150                                       void** vertices) {
   151     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
   152     bool acquired = false;
   153     if (vertexCount > 0) {
   154         SkASSERT(NULL != vertices);
   155         this->releasePreviousVertexSource();
   156         geoSrc.fVertexSrc = kNone_GeometrySrcType;
   158         acquired = this->onReserveVertexSpace(vertexSize,
   159                                               vertexCount,
   160                                               vertices);
   161     }
   162     if (acquired) {
   163         geoSrc.fVertexSrc = kReserved_GeometrySrcType;
   164         geoSrc.fVertexCount = vertexCount;
   165         geoSrc.fVertexSize = vertexSize;
   166     } else if (NULL != vertices) {
   167         *vertices = NULL;
   168     }
   169     return acquired;
   170 }
   172 bool GrDrawTarget::reserveIndexSpace(int indexCount,
   173                                      void** indices) {
   174     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
   175     bool acquired = false;
   176     if (indexCount > 0) {
   177         SkASSERT(NULL != indices);
   178         this->releasePreviousIndexSource();
   179         geoSrc.fIndexSrc = kNone_GeometrySrcType;
   181         acquired = this->onReserveIndexSpace(indexCount, indices);
   182     }
   183     if (acquired) {
   184         geoSrc.fIndexSrc = kReserved_GeometrySrcType;
   185         geoSrc.fIndexCount = indexCount;
   186     } else if (NULL != indices) {
   187         *indices = NULL;
   188     }
   189     return acquired;
   191 }
   193 bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount,
   194                                               int indexCount,
   195                                               void** vertices,
   196                                               void** indices) {
   197     size_t vertexSize = this->drawState()->getVertexSize();
   198     this->willReserveVertexAndIndexSpace(vertexCount, indexCount);
   199     if (vertexCount) {
   200         if (!this->reserveVertexSpace(vertexSize, vertexCount, vertices)) {
   201             if (indexCount) {
   202                 this->resetIndexSource();
   203             }
   204             return false;
   205         }
   206     }
   207     if (indexCount) {
   208         if (!this->reserveIndexSpace(indexCount, indices)) {
   209             if (vertexCount) {
   210                 this->resetVertexSource();
   211             }
   212             return false;
   213         }
   214     }
   215     return true;
   216 }
   218 bool GrDrawTarget::geometryHints(int32_t* vertexCount,
   219                                  int32_t* indexCount) const {
   220     if (NULL != vertexCount) {
   221         *vertexCount = -1;
   222     }
   223     if (NULL != indexCount) {
   224         *indexCount = -1;
   225     }
   226     return false;
   227 }
   229 void GrDrawTarget::releasePreviousVertexSource() {
   230     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
   231     switch (geoSrc.fVertexSrc) {
   232         case kNone_GeometrySrcType:
   233             break;
   234         case kArray_GeometrySrcType:
   235             this->releaseVertexArray();
   236             break;
   237         case kReserved_GeometrySrcType:
   238             this->releaseReservedVertexSpace();
   239             break;
   240         case kBuffer_GeometrySrcType:
   241             geoSrc.fVertexBuffer->unref();
   242 #ifdef SK_DEBUG
   243             geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
   244 #endif
   245             break;
   246         default:
   247             GrCrash("Unknown Vertex Source Type.");
   248             break;
   249     }
   250 }
   252 void GrDrawTarget::releasePreviousIndexSource() {
   253     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
   254     switch (geoSrc.fIndexSrc) {
   255         case kNone_GeometrySrcType:   // these two don't require
   256             break;
   257         case kArray_GeometrySrcType:
   258             this->releaseIndexArray();
   259             break;
   260         case kReserved_GeometrySrcType:
   261             this->releaseReservedIndexSpace();
   262             break;
   263         case kBuffer_GeometrySrcType:
   264             geoSrc.fIndexBuffer->unref();
   265 #ifdef SK_DEBUG
   266             geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
   267 #endif
   268             break;
   269         default:
   270             GrCrash("Unknown Index Source Type.");
   271             break;
   272     }
   273 }
   275 void GrDrawTarget::setVertexSourceToArray(const void* vertexArray,
   276                                           int vertexCount) {
   277     this->releasePreviousVertexSource();
   278     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
   279     geoSrc.fVertexSrc = kArray_GeometrySrcType;
   280     geoSrc.fVertexSize = this->drawState()->getVertexSize();
   281     geoSrc.fVertexCount = vertexCount;
   282     this->onSetVertexSourceToArray(vertexArray, vertexCount);
   283 }
   285 void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
   286                                          int indexCount) {
   287     this->releasePreviousIndexSource();
   288     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
   289     geoSrc.fIndexSrc = kArray_GeometrySrcType;
   290     geoSrc.fIndexCount = indexCount;
   291     this->onSetIndexSourceToArray(indexArray, indexCount);
   292 }
   294 void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer) {
   295     this->releasePreviousVertexSource();
   296     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
   297     geoSrc.fVertexSrc    = kBuffer_GeometrySrcType;
   298     geoSrc.fVertexBuffer = buffer;
   299     buffer->ref();
   300     geoSrc.fVertexSize = this->drawState()->getVertexSize();
   301 }
   303 void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
   304     this->releasePreviousIndexSource();
   305     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
   306     geoSrc.fIndexSrc     = kBuffer_GeometrySrcType;
   307     geoSrc.fIndexBuffer  = buffer;
   308     buffer->ref();
   309 }
   311 void GrDrawTarget::resetVertexSource() {
   312     this->releasePreviousVertexSource();
   313     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
   314     geoSrc.fVertexSrc = kNone_GeometrySrcType;
   315 }
   317 void GrDrawTarget::resetIndexSource() {
   318     this->releasePreviousIndexSource();
   319     GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
   320     geoSrc.fIndexSrc = kNone_GeometrySrcType;
   321 }
   323 void GrDrawTarget::pushGeometrySource() {
   324     this->geometrySourceWillPush();
   325     GeometrySrcState& newState = fGeoSrcStateStack.push_back();
   326     newState.fIndexSrc = kNone_GeometrySrcType;
   327     newState.fVertexSrc = kNone_GeometrySrcType;
   328 #ifdef SK_DEBUG
   329     newState.fVertexCount  = ~0;
   330     newState.fVertexBuffer = (GrVertexBuffer*)~0;
   331     newState.fIndexCount   = ~0;
   332     newState.fIndexBuffer = (GrIndexBuffer*)~0;
   333 #endif
   334 }
   336 void GrDrawTarget::popGeometrySource() {
   337     // if popping last element then pops are unbalanced with pushes
   338     SkASSERT(fGeoSrcStateStack.count() > 1);
   340     this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
   341     this->releasePreviousVertexSource();
   342     this->releasePreviousIndexSource();
   343     fGeoSrcStateStack.pop_back();
   344 }
   346 ////////////////////////////////////////////////////////////////////////////////
   348 bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
   349                              int startIndex, int vertexCount,
   350                              int indexCount) const {
   351     const GrDrawState& drawState = this->getDrawState();
   352 #ifdef SK_DEBUG
   353     const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
   354     int maxVertex = startVertex + vertexCount;
   355     int maxValidVertex;
   356     switch (geoSrc.fVertexSrc) {
   357         case kNone_GeometrySrcType:
   358             GrCrash("Attempting to draw without vertex src.");
   359         case kReserved_GeometrySrcType: // fallthrough
   360         case kArray_GeometrySrcType:
   361             maxValidVertex = geoSrc.fVertexCount;
   362             break;
   363         case kBuffer_GeometrySrcType:
   364             maxValidVertex = static_cast<int>(geoSrc.fVertexBuffer->sizeInBytes() / geoSrc.fVertexSize);
   365             break;
   366     }
   367     if (maxVertex > maxValidVertex) {
   368         GrCrash("Drawing outside valid vertex range.");
   369     }
   370     if (indexCount > 0) {
   371         int maxIndex = startIndex + indexCount;
   372         int maxValidIndex;
   373         switch (geoSrc.fIndexSrc) {
   374             case kNone_GeometrySrcType:
   375                 GrCrash("Attempting to draw indexed geom without index src.");
   376             case kReserved_GeometrySrcType: // fallthrough
   377             case kArray_GeometrySrcType:
   378                 maxValidIndex = geoSrc.fIndexCount;
   379                 break;
   380             case kBuffer_GeometrySrcType:
   381                 maxValidIndex = static_cast<int>(geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t));
   382                 break;
   383         }
   384         if (maxIndex > maxValidIndex) {
   385             GrCrash("Index reads outside valid index range.");
   386         }
   387     }
   389     SkASSERT(NULL != drawState.getRenderTarget());
   391     for (int s = 0; s < drawState.numColorStages(); ++s) {
   392         const GrEffectRef& effect = *drawState.getColorStage(s).getEffect();
   393         int numTextures = effect->numTextures();
   394         for (int t = 0; t < numTextures; ++t) {
   395             GrTexture* texture = effect->texture(t);
   396             SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
   397         }
   398     }
   399     for (int s = 0; s < drawState.numCoverageStages(); ++s) {
   400         const GrEffectRef& effect = *drawState.getCoverageStage(s).getEffect();
   401         int numTextures = effect->numTextures();
   402         for (int t = 0; t < numTextures; ++t) {
   403             GrTexture* texture = effect->texture(t);
   404             SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
   405         }
   406     }
   408     SkASSERT(drawState.validateVertexAttribs());
   409 #endif
   410     if (NULL == drawState.getRenderTarget()) {
   411         return false;
   412     }
   413     return true;
   414 }
   416 bool GrDrawTarget::setupDstReadIfNecessary(GrDeviceCoordTexture* dstCopy, const SkRect* drawBounds) {
   417     if (this->caps()->dstReadInShaderSupport() || !this->getDrawState().willEffectReadDstColor()) {
   418         return true;
   419     }
   420     GrRenderTarget* rt = this->drawState()->getRenderTarget();
   421     SkIRect copyRect;
   422     const GrClipData* clip = this->getClip();
   423     clip->getConservativeBounds(rt, &copyRect);
   425     if (NULL != drawBounds) {
   426         SkIRect drawIBounds;
   427         drawBounds->roundOut(&drawIBounds);
   428         if (!copyRect.intersect(drawIBounds)) {
   429 #ifdef SK_DEBUG
   430             GrPrintf("Missed an early reject. Bailing on draw from setupDstReadIfNecessary.\n");
   431 #endif
   432             return false;
   433         }
   434     } else {
   435 #ifdef SK_DEBUG
   436         //GrPrintf("No dev bounds when dst copy is made.\n");
   437 #endif
   438     }
   440     // MSAA consideration: When there is support for reading MSAA samples in the shader we could
   441     // have per-sample dst values by making the copy multisampled.
   442     GrTextureDesc desc;
   443     this->initCopySurfaceDstDesc(rt, &desc);
   444     desc.fWidth = copyRect.width();
   445     desc.fHeight = copyRect.height();
   447     GrAutoScratchTexture ast(fContext, desc, GrContext::kApprox_ScratchTexMatch);
   449     if (NULL == ast.texture()) {
   450         GrPrintf("Failed to create temporary copy of destination texture.\n");
   451         return false;
   452     }
   453     SkIPoint dstPoint = {0, 0};
   454     if (this->copySurface(ast.texture(), rt, copyRect, dstPoint)) {
   455         dstCopy->setTexture(ast.texture());
   456         dstCopy->setOffset(copyRect.fLeft, copyRect.fTop);
   457         return true;
   458     } else {
   459         return false;
   460     }
   461 }
   463 void GrDrawTarget::drawIndexed(GrPrimitiveType type,
   464                                int startVertex,
   465                                int startIndex,
   466                                int vertexCount,
   467                                int indexCount,
   468                                const SkRect* devBounds) {
   469     if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
   470         DrawInfo info;
   471         info.fPrimitiveType = type;
   472         info.fStartVertex   = startVertex;
   473         info.fStartIndex    = startIndex;
   474         info.fVertexCount   = vertexCount;
   475         info.fIndexCount    = indexCount;
   477         info.fInstanceCount         = 0;
   478         info.fVerticesPerInstance   = 0;
   479         info.fIndicesPerInstance    = 0;
   481         if (NULL != devBounds) {
   482             info.setDevBounds(*devBounds);
   483         }
   484         // TODO: We should continue with incorrect blending.
   485         if (!this->setupDstReadIfNecessary(&info)) {
   486             return;
   487         }
   488         this->onDraw(info);
   489     }
   490 }
   492 void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
   493                                   int startVertex,
   494                                   int vertexCount,
   495                                   const SkRect* devBounds) {
   496     if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
   497         DrawInfo info;
   498         info.fPrimitiveType = type;
   499         info.fStartVertex   = startVertex;
   500         info.fStartIndex    = 0;
   501         info.fVertexCount   = vertexCount;
   502         info.fIndexCount    = 0;
   504         info.fInstanceCount         = 0;
   505         info.fVerticesPerInstance   = 0;
   506         info.fIndicesPerInstance    = 0;
   508         if (NULL != devBounds) {
   509             info.setDevBounds(*devBounds);
   510         }
   511         // TODO: We should continue with incorrect blending.
   512         if (!this->setupDstReadIfNecessary(&info)) {
   513             return;
   514         }
   515         this->onDraw(info);
   516     }
   517 }
   519 void GrDrawTarget::stencilPath(const GrPath* path, SkPath::FillType fill) {
   520     // TODO: extract portions of checkDraw that are relevant to path stenciling.
   521     SkASSERT(NULL != path);
   522     SkASSERT(this->caps()->pathRenderingSupport());
   523     SkASSERT(!SkPath::IsInverseFillType(fill));
   524     this->onStencilPath(path, fill);
   525 }
   527 void GrDrawTarget::drawPath(const GrPath* path, SkPath::FillType fill) {
   528     // TODO: extract portions of checkDraw that are relevant to path rendering.
   529     SkASSERT(NULL != path);
   530     SkASSERT(this->caps()->pathRenderingSupport());
   531     const GrDrawState* drawState = &getDrawState();
   533     SkRect devBounds;
   534     if (SkPath::IsInverseFillType(fill)) {
   535         devBounds = SkRect::MakeWH(SkIntToScalar(drawState->getRenderTarget()->width()),
   536                                    SkIntToScalar(drawState->getRenderTarget()->height()));
   537     } else {
   538         devBounds = path->getBounds();
   539     }
   540     SkMatrix viewM = drawState->getViewMatrix();
   541     viewM.mapRect(&devBounds);
   543     GrDeviceCoordTexture dstCopy;
   544     if (!this->setupDstReadIfNecessary(&dstCopy, &devBounds)) {
   545         return;
   546     }
   548     this->onDrawPath(path, fill, dstCopy.texture() ? &dstCopy : NULL);
   549 }
   551 void GrDrawTarget::instantGpuTraceEvent(const char* marker) {
   552     if (this->caps()->gpuTracingSupport()) {
   553         this->onInstantGpuTraceEvent(marker);
   554     }
   555 }
   557 void GrDrawTarget::pushGpuTraceEvent(const char* marker) {
   558     SkASSERT(fPushGpuTraceCount >= 0);
   559     if (this->caps()->gpuTracingSupport()) {
   560         this->onPushGpuTraceEvent(marker);
   561         ++fPushGpuTraceCount;
   562     }
   563 }
   565 void GrDrawTarget::popGpuTraceEvent() {
   566     SkASSERT(fPushGpuTraceCount >= 1);
   567     if (this->caps()->gpuTracingSupport()) {
   568         this->onPopGpuTraceEvent();
   569         --fPushGpuTraceCount;
   570     }
   571 }
   573 ////////////////////////////////////////////////////////////////////////////////
   575 bool GrDrawTarget::willUseHWAALines() const {
   576     // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth
   577     // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when
   578     // our alpha is 0xff and tweaking the color for partial coverage is OK
   579     if (!this->caps()->hwAALineSupport() ||
   580         !this->getDrawState().isHWAntialiasState()) {
   581         return false;
   582     }
   583     GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts();
   584     return (GrDrawState::kDisableBlend_BlendOptFlag & opts) &&
   585            (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts);
   586 }
   588 bool GrDrawTarget::canApplyCoverage() const {
   589     // we can correctly apply coverage if a) we have dual source blending
   590     // or b) one of our blend optimizations applies.
   591     return this->caps()->dualSourceBlendingSupport() ||
   592            GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true);
   593 }
   595 ////////////////////////////////////////////////////////////////////////////////
   597 void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
   598                                         int instanceCount,
   599                                         int verticesPerInstance,
   600                                         int indicesPerInstance,
   601                                         const SkRect* devBounds) {
   602     if (!verticesPerInstance || !indicesPerInstance) {
   603         return;
   604     }
   606     int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
   607     if (!maxInstancesPerDraw) {
   608         return;
   609     }
   611     DrawInfo info;
   612     info.fPrimitiveType = type;
   613     info.fStartIndex = 0;
   614     info.fStartVertex = 0;
   615     info.fIndicesPerInstance = indicesPerInstance;
   616     info.fVerticesPerInstance = verticesPerInstance;
   618     // Set the same bounds for all the draws.
   619     if (NULL != devBounds) {
   620         info.setDevBounds(*devBounds);
   621     }
   622     // TODO: We should continue with incorrect blending.
   623     if (!this->setupDstReadIfNecessary(&info)) {
   624         return;
   625     }
   627     while (instanceCount) {
   628         info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
   629         info.fVertexCount = info.fInstanceCount * verticesPerInstance;
   630         info.fIndexCount = info.fInstanceCount * indicesPerInstance;
   632         if (this->checkDraw(type,
   633                             info.fStartVertex,
   634                             info.fStartIndex,
   635                             info.fVertexCount,
   636                             info.fIndexCount)) {
   637             this->onDraw(info);
   638         }
   639         info.fStartVertex += info.fVertexCount;
   640         instanceCount -= info.fInstanceCount;
   641     }
   642 }
   644 ////////////////////////////////////////////////////////////////////////////////
   646 namespace {
   648 // position + (optional) texture coord
   649 extern const GrVertexAttrib gBWRectPosUVAttribs[] = {
   650     {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
   651     {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
   652 };
   654 void set_vertex_attributes(GrDrawState* drawState, bool hasUVs) {
   655     if (hasUVs) {
   656         drawState->setVertexAttribs<gBWRectPosUVAttribs>(2);
   657     } else {
   658         drawState->setVertexAttribs<gBWRectPosUVAttribs>(1);
   659     }
   660 }
   662 };
   664 void GrDrawTarget::onDrawRect(const SkRect& rect,
   665                               const SkMatrix* matrix,
   666                               const SkRect* localRect,
   667                               const SkMatrix* localMatrix) {
   669     GrDrawState::AutoViewMatrixRestore avmr;
   670     if (NULL != matrix) {
   671         avmr.set(this->drawState(), *matrix);
   672     }
   674     set_vertex_attributes(this->drawState(), NULL != localRect);
   676     AutoReleaseGeometry geo(this, 4, 0);
   677     if (!geo.succeeded()) {
   678         GrPrintf("Failed to get space for vertices!\n");
   679         return;
   680     }
   682     size_t vsize = this->drawState()->getVertexSize();
   683     geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
   684     if (NULL != localRect) {
   685         GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
   686                                             sizeof(GrPoint));
   687         coords->setRectFan(localRect->fLeft, localRect->fTop,
   688                            localRect->fRight, localRect->fBottom,
   689                            vsize);
   690         if (NULL != localMatrix) {
   691             localMatrix->mapPointsWithStride(coords, vsize, 4);
   692         }
   693     }
   694     SkRect bounds;
   695     this->getDrawState().getViewMatrix().mapRect(&bounds, rect);
   697     this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4, &bounds);
   698 }
   700 void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
   701 }
   703 ////////////////////////////////////////////////////////////////////////////////
   705 GrDrawTarget::AutoStateRestore::AutoStateRestore() {
   706     fDrawTarget = NULL;
   707 }
   709 GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
   710                                                  ASRInit init,
   711                                                  const SkMatrix* vm) {
   712     fDrawTarget = NULL;
   713     this->set(target, init, vm);
   714 }
   716 GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
   717     if (NULL != fDrawTarget) {
   718         fDrawTarget->setDrawState(fSavedState);
   719         fSavedState->unref();
   720     }
   721 }
   723 void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init, const SkMatrix* vm) {
   724     SkASSERT(NULL == fDrawTarget);
   725     fDrawTarget = target;
   726     fSavedState = target->drawState();
   727     SkASSERT(fSavedState);
   728     fSavedState->ref();
   729     if (kReset_ASRInit == init) {
   730         if (NULL == vm) {
   731             // calls the default cons
   732             fTempState.init();
   733         } else {
   734             SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*vm));
   735         }
   736     } else {
   737         SkASSERT(kPreserve_ASRInit == init);
   738         if (NULL == vm) {
   739             fTempState.set(*fSavedState);
   740         } else {
   741             SkNEW_IN_TLAZY(&fTempState, GrDrawState, (*fSavedState, *vm));
   742         }
   743     }
   744     target->setDrawState(fTempState.get());
   745 }
   747 bool GrDrawTarget::AutoStateRestore::setIdentity(GrDrawTarget* target, ASRInit init) {
   748     SkASSERT(NULL == fDrawTarget);
   749     fDrawTarget = target;
   750     fSavedState = target->drawState();
   751     SkASSERT(fSavedState);
   752     fSavedState->ref();
   753     if (kReset_ASRInit == init) {
   754         // calls the default cons
   755         fTempState.init();
   756     } else {
   757         SkASSERT(kPreserve_ASRInit == init);
   758         // calls the copy cons
   759         fTempState.set(*fSavedState);
   760         if (!fTempState.get()->setIdentityViewMatrix()) {
   761             // let go of any resources held by the temp
   762             fTempState.get()->reset();
   763             fDrawTarget = NULL;
   764             fSavedState->unref();
   765             fSavedState = NULL;
   766             return false;
   767         }
   768     }
   769     target->setDrawState(fTempState.get());
   770     return true;
   771 }
   773 ////////////////////////////////////////////////////////////////////////////////
   775 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
   776                                          GrDrawTarget*  target,
   777                                          int vertexCount,
   778                                          int indexCount) {
   779     fTarget = NULL;
   780     this->set(target, vertexCount, indexCount);
   781 }
   783 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
   784     fTarget = NULL;
   785 }
   787 GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
   788     this->reset();
   789 }
   791 bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget*  target,
   792                                             int vertexCount,
   793                                             int indexCount) {
   794     this->reset();
   795     fTarget = target;
   796     bool success = true;
   797     if (NULL != fTarget) {
   798         fTarget = target;
   799         success = target->reserveVertexAndIndexSpace(vertexCount,
   800                                                      indexCount,
   801                                                      &fVertices,
   802                                                      &fIndices);
   803         if (!success) {
   804             fTarget = NULL;
   805             this->reset();
   806         }
   807     }
   808     SkASSERT(success == (NULL != fTarget));
   809     return success;
   810 }
   812 void GrDrawTarget::AutoReleaseGeometry::reset() {
   813     if (NULL != fTarget) {
   814         if (NULL != fVertices) {
   815             fTarget->resetVertexSource();
   816         }
   817         if (NULL != fIndices) {
   818             fTarget->resetIndexSource();
   819         }
   820         fTarget = NULL;
   821     }
   822     fVertices = NULL;
   823     fIndices = NULL;
   824 }
   826 GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
   827     fTarget = target;
   828     fClip = fTarget->getClip();
   829     fStack.init();
   830     fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
   831     fReplacementClip.fClipStack = fStack.get();
   832     target->setClip(&fReplacementClip);
   833 }
   835 namespace {
   836 // returns true if the read/written rect intersects the src/dst and false if not.
   837 bool clip_srcrect_and_dstpoint(const GrSurface* dst,
   838                                const GrSurface* src,
   839                                const SkIRect& srcRect,
   840                                const SkIPoint& dstPoint,
   841                                SkIRect* clippedSrcRect,
   842                                SkIPoint* clippedDstPoint) {
   843     *clippedSrcRect = srcRect;
   844     *clippedDstPoint = dstPoint;
   846     // clip the left edge to src and dst bounds, adjusting dstPoint if necessary
   847     if (clippedSrcRect->fLeft < 0) {
   848         clippedDstPoint->fX -= clippedSrcRect->fLeft;
   849         clippedSrcRect->fLeft = 0;
   850     }
   851     if (clippedDstPoint->fX < 0) {
   852         clippedSrcRect->fLeft -= clippedDstPoint->fX;
   853         clippedDstPoint->fX = 0;
   854     }
   856     // clip the top edge to src and dst bounds, adjusting dstPoint if necessary
   857     if (clippedSrcRect->fTop < 0) {
   858         clippedDstPoint->fY -= clippedSrcRect->fTop;
   859         clippedSrcRect->fTop = 0;
   860     }
   861     if (clippedDstPoint->fY < 0) {
   862         clippedSrcRect->fTop -= clippedDstPoint->fY;
   863         clippedDstPoint->fY = 0;
   864     }
   866     // clip the right edge to the src and dst bounds.
   867     if (clippedSrcRect->fRight > src->width()) {
   868         clippedSrcRect->fRight = src->width();
   869     }
   870     if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) {
   871         clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX;
   872     }
   874     // clip the bottom edge to the src and dst bounds.
   875     if (clippedSrcRect->fBottom > src->height()) {
   876         clippedSrcRect->fBottom = src->height();
   877     }
   878     if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) {
   879         clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY;
   880     }
   882     // The above clipping steps may have inverted the rect if it didn't intersect either the src or
   883     // dst bounds.
   884     return !clippedSrcRect->isEmpty();
   885 }
   886 }
   888 bool GrDrawTarget::copySurface(GrSurface* dst,
   889                                GrSurface* src,
   890                                const SkIRect& srcRect,
   891                                const SkIPoint& dstPoint) {
   892     SkASSERT(NULL != dst);
   893     SkASSERT(NULL != src);
   895     SkIRect clippedSrcRect;
   896     SkIPoint clippedDstPoint;
   897     // If the rect is outside the src or dst then we've already succeeded.
   898     if (!clip_srcrect_and_dstpoint(dst,
   899                                    src,
   900                                    srcRect,
   901                                    dstPoint,
   902                                    &clippedSrcRect,
   903                                    &clippedDstPoint)) {
   904         SkASSERT(this->canCopySurface(dst, src, srcRect, dstPoint));
   905         return true;
   906     }
   908     bool result = this->onCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
   909     SkASSERT(result == this->canCopySurface(dst, src, clippedSrcRect, clippedDstPoint));
   910     return result;
   911 }
   913 bool GrDrawTarget::canCopySurface(GrSurface* dst,
   914                                   GrSurface* src,
   915                                   const SkIRect& srcRect,
   916                                   const SkIPoint& dstPoint) {
   917     SkASSERT(NULL != dst);
   918     SkASSERT(NULL != src);
   920     SkIRect clippedSrcRect;
   921     SkIPoint clippedDstPoint;
   922     // If the rect is outside the src or dst then we're guaranteed success
   923     if (!clip_srcrect_and_dstpoint(dst,
   924                                    src,
   925                                    srcRect,
   926                                    dstPoint,
   927                                    &clippedSrcRect,
   928                                    &clippedDstPoint)) {
   929         return true;
   930     }
   931     return this->onCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
   932 }
   934 bool GrDrawTarget::onCanCopySurface(GrSurface* dst,
   935                                     GrSurface* src,
   936                                     const SkIRect& srcRect,
   937                                     const SkIPoint& dstPoint) {
   938     // Check that the read/write rects are contained within the src/dst bounds.
   939     SkASSERT(!srcRect.isEmpty());
   940     SkASSERT(SkIRect::MakeWH(src->width(), src->height()).contains(srcRect));
   941     SkASSERT(dstPoint.fX >= 0 && dstPoint.fY >= 0);
   942     SkASSERT(dstPoint.fX + srcRect.width() <= dst->width() &&
   943              dstPoint.fY + srcRect.height() <= dst->height());
   945     return !dst->isSameAs(src) && NULL != dst->asRenderTarget() && NULL != src->asTexture();
   946 }
   948 bool GrDrawTarget::onCopySurface(GrSurface* dst,
   949                                  GrSurface* src,
   950                                  const SkIRect& srcRect,
   951                                  const SkIPoint& dstPoint) {
   952     if (!GrDrawTarget::onCanCopySurface(dst, src, srcRect, dstPoint)) {
   953         return false;
   954     }
   956     GrRenderTarget* rt = dst->asRenderTarget();
   957     GrTexture* tex = src->asTexture();
   959     GrDrawTarget::AutoStateRestore asr(this, kReset_ASRInit);
   960     this->drawState()->setRenderTarget(rt);
   961     SkMatrix matrix;
   962     matrix.setTranslate(SkIntToScalar(srcRect.fLeft - dstPoint.fX),
   963                         SkIntToScalar(srcRect.fTop - dstPoint.fY));
   964     matrix.postIDiv(tex->width(), tex->height());
   965     this->drawState()->addColorTextureEffect(tex, matrix);
   966     SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX,
   967                                         dstPoint.fY,
   968                                         srcRect.width(),
   969                                         srcRect.height());
   970     this->drawSimpleRect(dstRect);
   971     return true;
   972 }
   974 void GrDrawTarget::initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) {
   975     // Make the dst of the copy be a render target because the default copySurface draws to the dst.
   976     desc->fOrigin = kDefault_GrSurfaceOrigin;
   977     desc->fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
   978     desc->fConfig = src->config();
   979 }
   981 ///////////////////////////////////////////////////////////////////////////////
   983 void GrDrawTargetCaps::reset() {
   984     f8BitPaletteSupport = false;
   985     fMipMapSupport = false;
   986     fNPOTTextureTileSupport = false;
   987     fTwoSidedStencilSupport = false;
   988     fStencilWrapOpsSupport = false;
   989     fHWAALineSupport = false;
   990     fShaderDerivativeSupport = false;
   991     fGeometryShaderSupport = false;
   992     fDualSourceBlendingSupport = false;
   993     fBufferLockSupport = false;
   994     fPathRenderingSupport = false;
   995     fDstReadInShaderSupport = false;
   996     fReuseScratchTextures = true;
   997     fGpuTracingSupport = false;
   999     fMaxRenderTargetSize = 0;
  1000     fMaxTextureSize = 0;
  1001     fMaxSampleCount = 0;
  1003     memset(fConfigRenderSupport, 0, sizeof(fConfigRenderSupport));
  1006 GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
  1007     f8BitPaletteSupport = other.f8BitPaletteSupport;
  1008     fMipMapSupport = other.fMipMapSupport;
  1009     fNPOTTextureTileSupport = other.fNPOTTextureTileSupport;
  1010     fTwoSidedStencilSupport = other.fTwoSidedStencilSupport;
  1011     fStencilWrapOpsSupport = other.fStencilWrapOpsSupport;
  1012     fHWAALineSupport = other.fHWAALineSupport;
  1013     fShaderDerivativeSupport = other.fShaderDerivativeSupport;
  1014     fGeometryShaderSupport = other.fGeometryShaderSupport;
  1015     fDualSourceBlendingSupport = other.fDualSourceBlendingSupport;
  1016     fBufferLockSupport = other.fBufferLockSupport;
  1017     fPathRenderingSupport = other.fPathRenderingSupport;
  1018     fDstReadInShaderSupport = other.fDstReadInShaderSupport;
  1019     fReuseScratchTextures = other.fReuseScratchTextures;
  1020     fGpuTracingSupport = other.fGpuTracingSupport;
  1022     fMaxRenderTargetSize = other.fMaxRenderTargetSize;
  1023     fMaxTextureSize = other.fMaxTextureSize;
  1024     fMaxSampleCount = other.fMaxSampleCount;
  1026     memcpy(fConfigRenderSupport, other.fConfigRenderSupport, sizeof(fConfigRenderSupport));
  1028     return *this;
  1031 SkString GrDrawTargetCaps::dump() const {
  1032     SkString r;
  1033     static const char* gNY[] = {"NO", "YES"};
  1034     r.appendf("8 Bit Palette Support       : %s\n", gNY[f8BitPaletteSupport]);
  1035     r.appendf("MIP Map Support             : %s\n", gNY[fMipMapSupport]);
  1036     r.appendf("NPOT Texture Tile Support   : %s\n", gNY[fNPOTTextureTileSupport]);
  1037     r.appendf("Two Sided Stencil Support   : %s\n", gNY[fTwoSidedStencilSupport]);
  1038     r.appendf("Stencil Wrap Ops  Support   : %s\n", gNY[fStencilWrapOpsSupport]);
  1039     r.appendf("HW AA Lines Support         : %s\n", gNY[fHWAALineSupport]);
  1040     r.appendf("Shader Derivative Support   : %s\n", gNY[fShaderDerivativeSupport]);
  1041     r.appendf("Geometry Shader Support     : %s\n", gNY[fGeometryShaderSupport]);
  1042     r.appendf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
  1043     r.appendf("Buffer Lock Support         : %s\n", gNY[fBufferLockSupport]);
  1044     r.appendf("Path Rendering Support      : %s\n", gNY[fPathRenderingSupport]);
  1045     r.appendf("Dst Read In Shader Support  : %s\n", gNY[fDstReadInShaderSupport]);
  1046     r.appendf("Reuse Scratch Textures      : %s\n", gNY[fReuseScratchTextures]);
  1047     r.appendf("Gpu Tracing Support         : %s\n", gNY[fGpuTracingSupport]);
  1048     r.appendf("Max Texture Size            : %d\n", fMaxTextureSize);
  1049     r.appendf("Max Render Target Size      : %d\n", fMaxRenderTargetSize);
  1050     r.appendf("Max Sample Count            : %d\n", fMaxSampleCount);
  1052     static const char* kConfigNames[] = {
  1053         "Unknown",  // kUnknown_GrPixelConfig
  1054         "Alpha8",   // kAlpha_8_GrPixelConfig,
  1055         "Index8",   // kIndex_8_GrPixelConfig,
  1056         "RGB565",   // kRGB_565_GrPixelConfig,
  1057         "RGBA444",  // kRGBA_4444_GrPixelConfig,
  1058         "RGBA8888", // kRGBA_8888_GrPixelConfig,
  1059         "BGRA8888", // kBGRA_8888_GrPixelConfig,
  1060     };
  1061     GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig);
  1062     GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig);
  1063     GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig);
  1064     GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig);
  1065     GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig);
  1066     GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig);
  1067     GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig);
  1068     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);
  1070     SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][0]);
  1071     SkASSERT(!fConfigRenderSupport[kUnknown_GrPixelConfig][1]);
  1072     for (size_t i = 0; i < SK_ARRAY_COUNT(kConfigNames); ++i)  {
  1073         if (i != kUnknown_GrPixelConfig) {
  1074             r.appendf("%s is renderable: %s, with MSAA: %s\n",
  1075                      kConfigNames[i],
  1076                      gNY[fConfigRenderSupport[i][0]],
  1077                      gNY[fConfigRenderSupport[i][1]]);
  1080     return r;

mercurial