Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrDrawState.h"
      9 
     10 #include "GrOptDrawState.h"
     11 #include "GrPaint.h"
     12 
     13 //////////////////////////////////////////////////////////////////////////////s
     14 
     15 GrOptDrawState* GrDrawState::createOptState(const GrDrawTargetCaps& caps) const {
     16     if (NULL == fCachedOptState || caps.getUniqueID() != fCachedCapsID) {
     17         GrBlendCoeff srcCoeff;
     18         GrBlendCoeff dstCoeff;
     19         BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
     20         fCachedOptState = SkNEW_ARGS(GrOptDrawState, (*this, blendFlags, srcCoeff, dstCoeff, caps));
     21         fCachedCapsID = caps.getUniqueID();
     22     } else {
     23 #ifdef SK_DEBUG
     24         GrBlendCoeff srcCoeff;
     25         GrBlendCoeff dstCoeff;
     26         BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
     27         SkASSERT(GrOptDrawState(*this, blendFlags, srcCoeff, dstCoeff, caps) == *fCachedOptState);
     28 #endif
     29     }
     30     fCachedOptState->ref();
     31     return fCachedOptState;
     32 }
     33 
     34 //////////////////////////////////////////////////////////////////////////////s
     35 
     36 GrDrawState::CombinedState GrDrawState::CombineIfPossible(
     37     const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
     38 
     39     if (!a.isEqual(b)) {
     40         return kIncompatible_CombinedState;
     41     }
     42 
     43     // If the general draw states are equal (from check above) we know hasColorVertexAttribute()
     44     // is equivalent for both a and b
     45     if (a.hasColorVertexAttribute()) {
     46         // If one is opaque and the other is not then the combined state is not opaque. Moreover,
     47         // if the opaqueness affects the ability to get color/coverage blending correct then we
     48         // don't combine the draw states.
     49         bool aIsOpaque = (kVertexColorsAreOpaque_Hint & a.fHints);
     50         bool bIsOpaque = (kVertexColorsAreOpaque_Hint & b.fHints);
     51         if (aIsOpaque != bIsOpaque) {
     52             const GrDrawState* opaque;
     53             const GrDrawState* nonOpaque;
     54             if (aIsOpaque) {
     55                 opaque = &a;
     56                 nonOpaque = &b;
     57             } else {
     58                 opaque = &b;
     59                 nonOpaque = &a;
     60             }
     61             if (!opaque->hasSolidCoverage() && opaque->couldApplyCoverage(caps)) {
     62                 SkASSERT(!nonOpaque->hasSolidCoverage());
     63                 if (!nonOpaque->couldApplyCoverage(caps)) {
     64                     return kIncompatible_CombinedState;
     65                 }
     66             }
     67             return aIsOpaque ? kB_CombinedState : kA_CombinedState;
     68         }
     69     }
     70     return kAOrB_CombinedState;
     71 }
     72 
     73 //////////////////////////////////////////////////////////////////////////////s
     74 
     75 GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix)
     76     : fCachedOptState(NULL) {
     77     SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
     78     *this = state;
     79     if (!preConcatMatrix.isIdentity()) {
     80         if (this->hasGeometryProcessor()) {
     81             fGeometryProcessor->localCoordChange(preConcatMatrix);
     82         }
     83         for (int i = 0; i < this->numColorStages(); ++i) {
     84             fColorStages[i].localCoordChange(preConcatMatrix);
     85         }
     86         for (int i = 0; i < this->numCoverageStages(); ++i) {
     87             fCoverageStages[i].localCoordChange(preConcatMatrix);
     88         }
     89         this->invalidateOptState();
     90     }
     91 }
     92 
     93 GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
     94     SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
     95     SkASSERT(!that.fRenderTarget.ownsPendingIO());
     96     SkASSERT(!this->fRenderTarget.ownsPendingIO());
     97     this->setRenderTarget(that.getRenderTarget());
     98     fColor = that.fColor;
     99     fViewMatrix = that.fViewMatrix;
    100     fSrcBlend = that.fSrcBlend;
    101     fDstBlend = that.fDstBlend;
    102     fBlendConstant = that.fBlendConstant;
    103     fFlagBits = that.fFlagBits;
    104     fVACount = that.fVACount;
    105     fVAPtr = that.fVAPtr;
    106     fVAStride = that.fVAStride;
    107     fStencilSettings = that.fStencilSettings;
    108     fCoverage = that.fCoverage;
    109     fDrawFace = that.fDrawFace;
    110     if (that.hasGeometryProcessor()) {
    111         fGeometryProcessor.reset(SkNEW_ARGS(GrGeometryStage, (*that.fGeometryProcessor.get())));
    112     } else {
    113         fGeometryProcessor.reset(NULL);
    114     }
    115     fColorStages = that.fColorStages;
    116     fCoverageStages = that.fCoverageStages;
    117 
    118     fHints = that.fHints;
    119 
    120     SkRefCnt_SafeAssign(fCachedOptState, that.fCachedOptState);
    121 
    122     memcpy(fFixedFunctionVertexAttribIndices,
    123             that.fFixedFunctionVertexAttribIndices,
    124             sizeof(fFixedFunctionVertexAttribIndices));
    125     return *this;
    126 }
    127 
    128 void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
    129     SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
    130     SkASSERT(!fRenderTarget.ownsPendingIO());
    131 
    132     fGeometryProcessor.reset(NULL);
    133     fColorStages.reset();
    134     fCoverageStages.reset();
    135 
    136     fRenderTarget.reset();
    137 
    138     this->setDefaultVertexAttribs();
    139 
    140     fColor = 0xffffffff;
    141     if (NULL == initialViewMatrix) {
    142         fViewMatrix.reset();
    143     } else {
    144         fViewMatrix = *initialViewMatrix;
    145     }
    146     fSrcBlend = kOne_GrBlendCoeff;
    147     fDstBlend = kZero_GrBlendCoeff;
    148     fBlendConstant = 0x0;
    149     fFlagBits = 0x0;
    150     fStencilSettings.setDisabled();
    151     fCoverage = 0xff;
    152     fDrawFace = kBoth_DrawFace;
    153 
    154     fHints = 0;
    155 
    156     this->invalidateOptState();
    157 }
    158 
    159 bool GrDrawState::setIdentityViewMatrix()  {
    160     if (this->numTotalStages()) {
    161         SkMatrix invVM;
    162         if (!fViewMatrix.invert(&invVM)) {
    163             // sad trombone sound
    164             return false;
    165         }
    166         if (this->hasGeometryProcessor()) {
    167             fGeometryProcessor->localCoordChange(invVM);
    168         }
    169         for (int s = 0; s < this->numColorStages(); ++s) {
    170             fColorStages[s].localCoordChange(invVM);
    171         }
    172         for (int s = 0; s < this->numCoverageStages(); ++s) {
    173             fCoverageStages[s].localCoordChange(invVM);
    174         }
    175     }
    176     this->invalidateOptState();
    177     fViewMatrix.reset();
    178     return true;
    179 }
    180 
    181 void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
    182     SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
    183 
    184     fGeometryProcessor.reset(NULL);
    185     fColorStages.reset();
    186     fCoverageStages.reset();
    187 
    188     for (int i = 0; i < paint.numColorStages(); ++i) {
    189         fColorStages.push_back(paint.getColorStage(i));
    190     }
    191 
    192     for (int i = 0; i < paint.numCoverageStages(); ++i) {
    193         fCoverageStages.push_back(paint.getCoverageStage(i));
    194     }
    195 
    196     this->setRenderTarget(rt);
    197 
    198     fViewMatrix = vm;
    199 
    200     // These have no equivalent in GrPaint, set them to defaults
    201     fBlendConstant = 0x0;
    202     fDrawFace = kBoth_DrawFace;
    203     fStencilSettings.setDisabled();
    204     this->resetStateFlags();
    205     fHints = 0;
    206 
    207     // Enable the clip bit
    208     this->enableState(GrDrawState::kClip_StateBit);
    209 
    210     this->setColor(paint.getColor());
    211     this->setState(GrDrawState::kDither_StateBit, paint.isDither());
    212     this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
    213 
    214     this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
    215     this->setCoverage(paint.getCoverage());
    216     this->invalidateOptState();
    217 }
    218 
    219 ////////////////////////////////////////////////////////////////////////////////
    220 
    221 static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) {
    222     // this works as long as we're 4 byte-aligned
    223 #ifdef SK_DEBUG
    224     uint32_t overlapCheck = 0;
    225     SkASSERT(count <= GrRODrawState::kMaxVertexAttribCnt);
    226     for (int index = 0; index < count; ++index) {
    227         size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
    228         size_t attribOffset = attribs[index].fOffset;
    229         SkASSERT(attribOffset + attribSize <= stride);
    230         size_t dwordCount = attribSize >> 2;
    231         uint32_t mask = (1 << dwordCount)-1;
    232         size_t offsetShift = attribOffset >> 2;
    233         SkASSERT(!(overlapCheck & (mask << offsetShift)));
    234         overlapCheck |= (mask << offsetShift);
    235     }
    236 #endif
    237 }
    238 
    239 ////////////////////////////////////////////////////////////////////////////////
    240 
    241 void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int count,
    242                                            size_t stride) {
    243     SkASSERT(count <= kMaxVertexAttribCnt);
    244 
    245     fVAPtr = attribs;
    246     fVACount = count;
    247     fVAStride = stride;
    248     validate_vertex_attribs(fVAPtr, fVACount, fVAStride);
    249 
    250     // Set all the indices to -1
    251     memset(fFixedFunctionVertexAttribIndices,
    252            0xff,
    253            sizeof(fFixedFunctionVertexAttribIndices));
    254 #ifdef SK_DEBUG
    255     uint32_t overlapCheck = 0;
    256 #endif
    257     for (int i = 0; i < count; ++i) {
    258         if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
    259             // The fixed function attribs can only be specified once
    260             SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
    261             SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
    262                      GrVertexAttribTypeVectorCount(attribs[i].fType));
    263             fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
    264         }
    265 #ifdef SK_DEBUG
    266         size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
    267         uint32_t mask = (1 << dwordCount)-1;
    268         size_t offsetShift = attribs[i].fOffset >> 2;
    269         SkASSERT(!(overlapCheck & (mask << offsetShift)));
    270         overlapCheck |= (mask << offsetShift);
    271 #endif
    272     }
    273     this->invalidateOptState();
    274     // Positions must be specified.
    275     SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
    276 }
    277 
    278 ////////////////////////////////////////////////////////////////////////////////
    279 
    280 void GrDrawState::setDefaultVertexAttribs() {
    281     static const GrVertexAttrib kPositionAttrib =
    282         {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
    283 
    284     fVAPtr = &kPositionAttrib;
    285     fVACount = 1;
    286     fVAStride = GrVertexAttribTypeSize(kVec2f_GrVertexAttribType);
    287 
    288     // set all the fixed function indices to -1 except position.
    289     memset(fFixedFunctionVertexAttribIndices,
    290            0xff,
    291            sizeof(fFixedFunctionVertexAttribIndices));
    292     fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
    293     this->invalidateOptState();
    294 }
    295 
    296 ////////////////////////////////////////////////////////////////////////////////
    297 
    298 bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
    299     if (caps.dualSourceBlendingSupport()) {
    300         return true;
    301     }
    302     // we can correctly apply coverage if a) we have dual source blending
    303     // or b) one of our blend optimizations applies
    304     // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
    305     GrBlendCoeff srcCoeff;
    306     GrBlendCoeff dstCoeff;
    307     BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
    308     return GrRODrawState::kNone_BlendOpt != flag ||
    309            (this->willEffectReadDstColor() &&
    310             kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
    311 }
    312 
    313 //////////////////////////////////////////////////////////////////////////////
    314 
    315 GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) {
    316     SkASSERT(drawState);
    317     fDrawState = drawState;
    318     fVAPtr = drawState->fVAPtr;
    319     fVACount = drawState->fVACount;
    320     fVAStride = drawState->fVAStride;
    321     fDrawState->setDefaultVertexAttribs();
    322 }
    323 
    324 //////////////////////////////////////////////////////////////////////////////s
    325 
    326 void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
    327     if (fDrawState) {
    328         // See the big comment on the class definition about GPs.
    329         if (SK_InvalidUniqueID == fOriginalGPID) {
    330             fDrawState->fGeometryProcessor.reset(NULL);
    331         } else {
    332             SkASSERT(fDrawState->getGeometryProcessor()->getProcessor()->getUniqueID() ==
    333                      fOriginalGPID);
    334             fOriginalGPID = SK_InvalidUniqueID;
    335         }
    336 
    337         int m = fDrawState->numColorStages() - fColorEffectCnt;
    338         SkASSERT(m >= 0);
    339         fDrawState->fColorStages.pop_back_n(m);
    340 
    341         int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
    342         SkASSERT(n >= 0);
    343         fDrawState->fCoverageStages.pop_back_n(n);
    344         if (m + n > 0) {
    345             fDrawState->invalidateOptState();
    346         }
    347         SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
    348     }
    349     fDrawState = ds;
    350     if (NULL != ds) {
    351         SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
    352         if (NULL != ds->getGeometryProcessor()) {
    353             fOriginalGPID = ds->getGeometryProcessor()->getProcessor()->getUniqueID();
    354         }
    355         fColorEffectCnt = ds->numColorStages();
    356         fCoverageEffectCnt = ds->numCoverageStages();
    357         SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
    358     }
    359 }
    360 
    361 ////////////////////////////////////////////////////////////////////////////////
    362 
    363 void GrDrawState::AutoViewMatrixRestore::restore() {
    364     if (fDrawState) {
    365         SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
    366         fDrawState->fViewMatrix = fViewMatrix;
    367         SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
    368         int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
    369         SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
    370 
    371         int i = 0;
    372         if (fHasGeometryProcessor) {
    373             SkASSERT(fDrawState->hasGeometryProcessor());
    374             fDrawState->fGeometryProcessor->restoreCoordChange(fSavedCoordChanges[i++]);
    375         }
    376         for (int s = 0; s < fNumColorStages; ++s, ++i) {
    377             fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
    378         }
    379         for (int s = 0; s < numCoverageStages; ++s, ++i) {
    380             fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
    381         }
    382         fDrawState->invalidateOptState();
    383         fDrawState = NULL;
    384     }
    385 }
    386 
    387 void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
    388                                              const SkMatrix& preconcatMatrix) {
    389     this->restore();
    390 
    391     SkASSERT(NULL == fDrawState);
    392     if (NULL == drawState || preconcatMatrix.isIdentity()) {
    393         return;
    394     }
    395     fDrawState = drawState;
    396 
    397     fViewMatrix = drawState->getViewMatrix();
    398     drawState->fViewMatrix.preConcat(preconcatMatrix);
    399 
    400     this->doEffectCoordChanges(preconcatMatrix);
    401     SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
    402     drawState->invalidateOptState();
    403 }
    404 
    405 bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
    406     this->restore();
    407 
    408     if (NULL == drawState) {
    409         return false;
    410     }
    411 
    412     if (drawState->getViewMatrix().isIdentity()) {
    413         return true;
    414     }
    415 
    416     drawState->invalidateOptState();
    417     fViewMatrix = drawState->getViewMatrix();
    418     if (0 == drawState->numTotalStages()) {
    419         drawState->fViewMatrix.reset();
    420         fDrawState = drawState;
    421         fHasGeometryProcessor = false;
    422         fNumColorStages = 0;
    423         fSavedCoordChanges.reset(0);
    424         SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
    425         return true;
    426     } else {
    427         SkMatrix inv;
    428         if (!fViewMatrix.invert(&inv)) {
    429             return false;
    430         }
    431         drawState->fViewMatrix.reset();
    432         fDrawState = drawState;
    433         this->doEffectCoordChanges(inv);
    434         SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
    435         return true;
    436     }
    437 }
    438 
    439 void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
    440     fSavedCoordChanges.reset(fDrawState->numTotalStages());
    441     int i = 0;
    442 
    443     fHasGeometryProcessor = false;
    444     if (fDrawState->hasGeometryProcessor()) {
    445         fDrawState->fGeometryProcessor->saveCoordChange(&fSavedCoordChanges[i++]);
    446         fDrawState->fGeometryProcessor->localCoordChange(coordChangeMatrix);
    447         fHasGeometryProcessor = true;
    448     }
    449 
    450     fNumColorStages = fDrawState->numColorStages();
    451     for (int s = 0; s < fNumColorStages; ++s, ++i) {
    452         fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
    453         fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
    454     }
    455 
    456     int numCoverageStages = fDrawState->numCoverageStages();
    457     for (int s = 0; s < numCoverageStages; ++s, ++i) {
    458         fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
    459         fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
    460     }
    461 }
    462 
    463 ////////////////////////////////////////////////////////////////////////////////
    464 
    465 void GrDrawState::invalidateOptState() const {
    466     SkSafeSetNull(fCachedOptState);
    467 }
    468 
    469 ////////////////////////////////////////////////////////////////////////////////
    470 
    471 GrDrawState::~GrDrawState() {
    472     SkSafeUnref(fCachedOptState);
    473     SkASSERT(0 == fBlockEffectRemovalCnt);
    474 }
    475 
    476