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 #include "GrPaint.h"
     10 
     11 bool GrDrawState::setIdentityViewMatrix()  {
     12     if (fColorStages.count() || fCoverageStages.count()) {
     13         SkMatrix invVM;
     14         if (!fCommon.fViewMatrix.invert(&invVM)) {
     15             // sad trombone sound
     16             return false;
     17         }
     18         for (int s = 0; s < fColorStages.count(); ++s) {
     19             fColorStages[s].localCoordChange(invVM);
     20         }
     21         for (int s = 0; s < fCoverageStages.count(); ++s) {
     22             fCoverageStages[s].localCoordChange(invVM);
     23         }
     24     }
     25     fCommon.fViewMatrix.reset();
     26     return true;
     27 }
     28 
     29 void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
     30     SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
     31 
     32     fColorStages.reset();
     33     fCoverageStages.reset();
     34 
     35     for (int i = 0; i < paint.numColorStages(); ++i) {
     36         fColorStages.push_back(paint.getColorStage(i));
     37     }
     38 
     39     for (int i = 0; i < paint.numCoverageStages(); ++i) {
     40         fCoverageStages.push_back(paint.getCoverageStage(i));
     41     }
     42 
     43     this->setRenderTarget(rt);
     44 
     45     fCommon.fViewMatrix = vm;
     46 
     47     // These have no equivalent in GrPaint, set them to defaults
     48     fCommon.fBlendConstant = 0x0;
     49     fCommon.fDrawFace = kBoth_DrawFace;
     50     fCommon.fStencilSettings.setDisabled();
     51     this->resetStateFlags();
     52 
     53     // Enable the clip bit
     54     this->enableState(GrDrawState::kClip_StateBit);
     55 
     56     this->setColor(paint.getColor());
     57     this->setState(GrDrawState::kDither_StateBit, paint.isDither());
     58     this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
     59 
     60     this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
     61     this->setCoverage(paint.getCoverage());
     62 }
     63 
     64 ////////////////////////////////////////////////////////////////////////////////
     65 
     66 static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
     67     // this works as long as we're 4 byte-aligned
     68 #ifdef SK_DEBUG
     69     uint32_t overlapCheck = 0;
     70 #endif
     71     SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
     72     size_t size = 0;
     73     for (int index = 0; index < count; ++index) {
     74         size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
     75         size += attribSize;
     76 #ifdef SK_DEBUG
     77         size_t dwordCount = attribSize >> 2;
     78         uint32_t mask = (1 << dwordCount)-1;
     79         size_t offsetShift = attribs[index].fOffset >> 2;
     80         SkASSERT(!(overlapCheck & (mask << offsetShift)));
     81         overlapCheck |= (mask << offsetShift);
     82 #endif
     83     }
     84     return size;
     85 }
     86 
     87 size_t GrDrawState::getVertexSize() const {
     88     return vertex_size(fCommon.fVAPtr, fCommon.fVACount);
     89 }
     90 
     91 ////////////////////////////////////////////////////////////////////////////////
     92 
     93 void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
     94     SkASSERT(count <= kMaxVertexAttribCnt);
     95 
     96     fCommon.fVAPtr = attribs;
     97     fCommon.fVACount = count;
     98 
     99     // Set all the indices to -1
    100     memset(fCommon.fFixedFunctionVertexAttribIndices,
    101            0xff,
    102            sizeof(fCommon.fFixedFunctionVertexAttribIndices));
    103 #ifdef SK_DEBUG
    104     uint32_t overlapCheck = 0;
    105 #endif
    106     for (int i = 0; i < count; ++i) {
    107         if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
    108             // The fixed function attribs can only be specified once
    109             SkASSERT(-1 == fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
    110             SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
    111                      GrVertexAttribTypeVectorCount(attribs[i].fType));
    112             fCommon.fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
    113         }
    114 #ifdef SK_DEBUG
    115         size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
    116         uint32_t mask = (1 << dwordCount)-1;
    117         size_t offsetShift = attribs[i].fOffset >> 2;
    118         SkASSERT(!(overlapCheck & (mask << offsetShift)));
    119         overlapCheck |= (mask << offsetShift);
    120 #endif
    121     }
    122     // Positions must be specified.
    123     SkASSERT(-1 != fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
    124 }
    125 
    126 ////////////////////////////////////////////////////////////////////////////////
    127 
    128 void GrDrawState::setDefaultVertexAttribs() {
    129     static const GrVertexAttrib kPositionAttrib =
    130         {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
    131 
    132     fCommon.fVAPtr = &kPositionAttrib;
    133     fCommon.fVACount = 1;
    134 
    135     // set all the fixed function indices to -1 except position.
    136     memset(fCommon.fFixedFunctionVertexAttribIndices,
    137            0xff,
    138            sizeof(fCommon.fFixedFunctionVertexAttribIndices));
    139     fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
    140 }
    141 
    142 ////////////////////////////////////////////////////////////////////////////////
    143 
    144 bool GrDrawState::validateVertexAttribs() const {
    145     // check consistency of effects and attributes
    146     GrSLType slTypes[kMaxVertexAttribCnt];
    147     for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
    148         slTypes[i] = static_cast<GrSLType>(-1);
    149     }
    150     int totalStages = fColorStages.count() + fCoverageStages.count();
    151     for (int s = 0; s < totalStages; ++s) {
    152         int covIdx = s - fColorStages.count();
    153         const GrEffectStage& stage = covIdx < 0 ? fColorStages[s] : fCoverageStages[covIdx];
    154         const GrEffectRef* effect = stage.getEffect();
    155         SkASSERT(NULL != effect);
    156         // make sure that any attribute indices have the correct binding type, that the attrib
    157         // type and effect's shader lang type are compatible, and that attributes shared by
    158         // multiple effects use the same shader lang type.
    159         const int* attributeIndices = stage.getVertexAttribIndices();
    160         int numAttributes = stage.getVertexAttribIndexCount();
    161         for (int i = 0; i < numAttributes; ++i) {
    162             int attribIndex = attributeIndices[i];
    163             if (attribIndex >= fCommon.fVACount ||
    164                 kEffect_GrVertexAttribBinding != fCommon.fVAPtr[attribIndex].fBinding) {
    165                 return false;
    166             }
    167 
    168             GrSLType effectSLType = (*effect)->vertexAttribType(i);
    169             GrVertexAttribType attribType = fCommon.fVAPtr[attribIndex].fType;
    170             int slVecCount = GrSLTypeVectorCount(effectSLType);
    171             int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
    172             if (slVecCount != attribVecCount ||
    173                 (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
    174                     slTypes[attribIndex] != effectSLType)) {
    175                 return false;
    176             }
    177             slTypes[attribIndex] = effectSLType;
    178         }
    179     }
    180 
    181     return true;
    182 }
    183 
    184 bool GrDrawState::willEffectReadDstColor() const {
    185     if (!this->isColorWriteDisabled()) {
    186         for (int s = 0; s < fColorStages.count(); ++s) {
    187             if ((*fColorStages[s].getEffect())->willReadDstColor()) {
    188                 return true;
    189             }
    190         }
    191     }
    192     for (int s = 0; s < fCoverageStages.count(); ++s) {
    193         if ((*fCoverageStages[s].getEffect())->willReadDstColor()) {
    194             return true;
    195         }
    196     }
    197     return false;
    198 }
    199 
    200 ////////////////////////////////////////////////////////////////////////////////
    201 
    202 bool GrDrawState::srcAlphaWillBeOne() const {
    203     uint32_t validComponentFlags;
    204     GrColor color;
    205     // Check if per-vertex or constant color may have partial alpha
    206     if (this->hasColorVertexAttribute()) {
    207         validComponentFlags = 0;
    208         color = 0; // not strictly necessary but we get false alarms from tools about uninit.
    209     } else {
    210         validComponentFlags = kRGBA_GrColorComponentFlags;
    211         color = this->getColor();
    212     }
    213 
    214     // Run through the color stages
    215     for (int s = 0; s < fColorStages.count(); ++s) {
    216         const GrEffectRef* effect = fColorStages[s].getEffect();
    217         (*effect)->getConstantColorComponents(&color, &validComponentFlags);
    218     }
    219 
    220     // Check whether coverage is treated as color. If so we run through the coverage computation.
    221     if (this->isCoverageDrawing()) {
    222         GrColor coverageColor = this->getCoverageColor();
    223         GrColor oldColor = color;
    224         color = 0;
    225         for (int c = 0; c < 4; ++c) {
    226             if (validComponentFlags & (1 << c)) {
    227                 U8CPU a = (oldColor >> (c * 8)) & 0xff;
    228                 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
    229                 color |= (SkMulDiv255Round(a, b) << (c * 8));
    230             }
    231         }
    232         for (int s = 0; s < fCoverageStages.count(); ++s) {
    233             const GrEffectRef* effect = fCoverageStages[s].getEffect();
    234             (*effect)->getConstantColorComponents(&color, &validComponentFlags);
    235         }
    236     }
    237     return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
    238 }
    239 
    240 bool GrDrawState::hasSolidCoverage() const {
    241     // If we're drawing coverage directly then coverage is effectively treated as color.
    242     if (this->isCoverageDrawing()) {
    243         return true;
    244     }
    245 
    246     GrColor coverage;
    247     uint32_t validComponentFlags;
    248     // Initialize to an unknown starting coverage if per-vertex coverage is specified.
    249     if (this->hasCoverageVertexAttribute()) {
    250         validComponentFlags = 0;
    251     } else {
    252         coverage = fCommon.fCoverage;
    253         validComponentFlags = kRGBA_GrColorComponentFlags;
    254     }
    255 
    256     // Run through the coverage stages and see if the coverage will be all ones at the end.
    257     for (int s = 0; s < fCoverageStages.count(); ++s) {
    258         const GrEffectRef* effect = fCoverageStages[s].getEffect();
    259         (*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
    260     }
    261     return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
    262 }
    263 
    264 ////////////////////////////////////////////////////////////////////////////////
    265 
    266 // Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
    267 // others will blend incorrectly.
    268 bool GrDrawState::canTweakAlphaForCoverage() const {
    269     /*
    270      The fractional coverage is f.
    271      The src and dst coeffs are Cs and Cd.
    272      The dst and src colors are S and D.
    273      We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
    274      we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
    275      term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
    276      find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
    277      Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
    278      color by definition.
    279      */
    280     return kOne_GrBlendCoeff == fCommon.fDstBlend ||
    281            kISA_GrBlendCoeff == fCommon.fDstBlend ||
    282            kISC_GrBlendCoeff == fCommon.fDstBlend ||
    283            this->isCoverageDrawing();
    284 }
    285 
    286 GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
    287                                                      GrBlendCoeff* srcCoeff,
    288                                                      GrBlendCoeff* dstCoeff) const {
    289 
    290     GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
    291     if (NULL == srcCoeff) {
    292         srcCoeff = &bogusSrcCoeff;
    293     }
    294     *srcCoeff = this->getSrcBlendCoeff();
    295 
    296     if (NULL == dstCoeff) {
    297         dstCoeff = &bogusDstCoeff;
    298     }
    299     *dstCoeff = this->getDstBlendCoeff();
    300 
    301     if (this->isColorWriteDisabled()) {
    302         *srcCoeff = kZero_GrBlendCoeff;
    303         *dstCoeff = kOne_GrBlendCoeff;
    304     }
    305 
    306     bool srcAIsOne = this->srcAlphaWillBeOne();
    307     bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
    308                          (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
    309     bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
    310                          (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
    311 
    312     bool covIsZero = !this->isCoverageDrawing() &&
    313                      !this->hasCoverageVertexAttribute() &&
    314                      0 == this->getCoverageColor();
    315     // When coeffs are (0,1) there is no reason to draw at all, unless
    316     // stenciling is enabled. Having color writes disabled is effectively
    317     // (0,1). The same applies when coverage is known to be 0.
    318     if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
    319         if (this->getStencil().doesWrite()) {
    320             return kDisableBlend_BlendOptFlag |
    321                    kEmitCoverage_BlendOptFlag;
    322         } else {
    323             return kSkipDraw_BlendOptFlag;
    324         }
    325     }
    326 
    327     // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
    328     bool hasCoverage = forceCoverage ||
    329                        0xffffffff != this->getCoverageColor() ||
    330                        this->hasCoverageVertexAttribute() ||
    331                        fCoverageStages.count() > 0;
    332 
    333     // if we don't have coverage we can check whether the dst
    334     // has to read at all. If not, we'll disable blending.
    335     if (!hasCoverage) {
    336         if (dstCoeffIsZero) {
    337             if (kOne_GrBlendCoeff == *srcCoeff) {
    338                 // if there is no coverage and coeffs are (1,0) then we
    339                 // won't need to read the dst at all, it gets replaced by src
    340                 return kDisableBlend_BlendOptFlag;
    341             } else if (kZero_GrBlendCoeff == *srcCoeff) {
    342                 // if the op is "clear" then we don't need to emit a color
    343                 // or blend, just write transparent black into the dst.
    344                 *srcCoeff = kOne_GrBlendCoeff;
    345                 *dstCoeff = kZero_GrBlendCoeff;
    346                 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
    347             }
    348         }
    349     } else if (this->isCoverageDrawing()) {
    350         // we have coverage but we aren't distinguishing it from alpha by request.
    351         return kCoverageAsAlpha_BlendOptFlag;
    352     } else {
    353         // check whether coverage can be safely rolled into alpha
    354         // of if we can skip color computation and just emit coverage
    355         if (this->canTweakAlphaForCoverage()) {
    356             return kCoverageAsAlpha_BlendOptFlag;
    357         }
    358         if (dstCoeffIsZero) {
    359             if (kZero_GrBlendCoeff == *srcCoeff) {
    360                 // the source color is not included in the blend
    361                 // the dst coeff is effectively zero so blend works out to:
    362                 // (c)(0)D + (1-c)D = (1-c)D.
    363                 *dstCoeff = kISA_GrBlendCoeff;
    364                 return  kEmitCoverage_BlendOptFlag;
    365             } else if (srcAIsOne) {
    366                 // the dst coeff is effectively zero so blend works out to:
    367                 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
    368                 // If Sa is 1 then we can replace Sa with c
    369                 // and set dst coeff to 1-Sa.
    370                 *dstCoeff = kISA_GrBlendCoeff;
    371                 return  kCoverageAsAlpha_BlendOptFlag;
    372             }
    373         } else if (dstCoeffIsOne) {
    374             // the dst coeff is effectively one so blend works out to:
    375             // cS + (c)(1)D + (1-c)D = cS + D.
    376             *dstCoeff = kOne_GrBlendCoeff;
    377             return  kCoverageAsAlpha_BlendOptFlag;
    378         }
    379     }
    380     if (kOne_GrBlendCoeff == *srcCoeff &&
    381         kZero_GrBlendCoeff == *dstCoeff &&
    382         this->willEffectReadDstColor()) {
    383         // In this case the shader will fully resolve the color, coverage, and dst and we don't
    384         // need blending.
    385         return kDisableBlend_BlendOptFlag;
    386     }
    387     return kNone_BlendOpt;
    388 }
    389 
    390 ////////////////////////////////////////////////////////////////////////////////
    391 
    392 void GrDrawState::AutoViewMatrixRestore::restore() {
    393     if (NULL != fDrawState) {
    394         SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
    395         fDrawState->fCommon.fViewMatrix = fViewMatrix;
    396         SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
    397         int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
    398         SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
    399 
    400         int i = 0;
    401         for (int s = 0; s < fNumColorStages; ++s, ++i) {
    402             fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
    403         }
    404         for (int s = 0; s < numCoverageStages; ++s, ++i) {
    405             fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
    406         }
    407         fDrawState = NULL;
    408     }
    409 }
    410 
    411 void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
    412                                              const SkMatrix& preconcatMatrix) {
    413     this->restore();
    414 
    415     SkASSERT(NULL == fDrawState);
    416     if (NULL == drawState || preconcatMatrix.isIdentity()) {
    417         return;
    418     }
    419     fDrawState = drawState;
    420 
    421     fViewMatrix = drawState->getViewMatrix();
    422     drawState->fCommon.fViewMatrix.preConcat(preconcatMatrix);
    423 
    424     this->doEffectCoordChanges(preconcatMatrix);
    425     SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
    426 }
    427 
    428 bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
    429     this->restore();
    430 
    431     if (NULL == drawState) {
    432         return false;
    433     }
    434 
    435     if (drawState->getViewMatrix().isIdentity()) {
    436         return true;
    437     }
    438 
    439     fViewMatrix = drawState->getViewMatrix();
    440     if (0 == drawState->numTotalStages()) {
    441         drawState->fCommon.fViewMatrix.reset();
    442         fDrawState = drawState;
    443         fNumColorStages = 0;
    444         fSavedCoordChanges.reset(0);
    445         SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
    446         return true;
    447     } else {
    448         SkMatrix inv;
    449         if (!fViewMatrix.invert(&inv)) {
    450             return false;
    451         }
    452         drawState->fCommon.fViewMatrix.reset();
    453         fDrawState = drawState;
    454         this->doEffectCoordChanges(inv);
    455         SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
    456         return true;
    457     }
    458 }
    459 
    460 void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
    461     fSavedCoordChanges.reset(fDrawState->numTotalStages());
    462     int i = 0;
    463 
    464     fNumColorStages = fDrawState->numColorStages();
    465     for (int s = 0; s < fNumColorStages; ++s, ++i) {
    466         fDrawState->fColorStages[s].saveCoordChange(&fSavedCoordChanges[i]);
    467         fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
    468     }
    469 
    470     int numCoverageStages = fDrawState->numCoverageStages();
    471     for (int s = 0; s < numCoverageStages; ++s, ++i) {
    472         fDrawState->fCoverageStages[s].saveCoordChange(&fSavedCoordChanges[i]);
    473         fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
    474     }
    475 }
    476