Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2014 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 "GrRODrawState.h"
      9 
     10 #include "GrDrawTargetCaps.h"
     11 #include "GrRenderTarget.h"
     12 
     13 ////////////////////////////////////////////////////////////////////////////////
     14 
     15 GrRODrawState::GrRODrawState(const GrRODrawState& drawState) : INHERITED() {
     16     fRenderTarget.setResource(SkSafeRef(drawState.fRenderTarget.getResource()),
     17                               GrIORef::kWrite_IOType);
     18 }
     19 
     20 bool GrRODrawState::isEqual(const GrRODrawState& that) const {
     21     bool usingVertexColors = this->hasColorVertexAttribute();
     22     if (!usingVertexColors && this->fColor != that.fColor) {
     23         return false;
     24     }
     25 
     26     if (this->getRenderTarget() != that.getRenderTarget() ||
     27         this->fColorStages.count() != that.fColorStages.count() ||
     28         this->fCoverageStages.count() != that.fCoverageStages.count() ||
     29         !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
     30         this->fSrcBlend != that.fSrcBlend ||
     31         this->fDstBlend != that.fDstBlend ||
     32         this->fBlendConstant != that.fBlendConstant ||
     33         this->fFlagBits != that.fFlagBits ||
     34         this->fVACount != that.fVACount ||
     35         this->fVAStride != that.fVAStride ||
     36         memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
     37         this->fStencilSettings != that.fStencilSettings ||
     38         this->fDrawFace != that.fDrawFace) {
     39         return false;
     40     }
     41 
     42     bool usingVertexCoverage = this->hasCoverageVertexAttribute();
     43     if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
     44         return false;
     45     }
     46 
     47     bool explicitLocalCoords = this->hasLocalCoordAttribute();
     48     if (this->hasGeometryProcessor()) {
     49         if (!that.hasGeometryProcessor()) {
     50             return false;
     51         } else if (!GrProcessorStage::AreCompatible(*this->getGeometryProcessor(),
     52                                                     *that.getGeometryProcessor(),
     53                                                     explicitLocalCoords)) {
     54             return false;
     55         }
     56     } else if (that.hasGeometryProcessor()) {
     57         return false;
     58     }
     59 
     60     for (int i = 0; i < this->numColorStages(); i++) {
     61         if (!GrProcessorStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
     62                                              explicitLocalCoords)) {
     63             return false;
     64         }
     65     }
     66     for (int i = 0; i < this->numCoverageStages(); i++) {
     67         if (!GrProcessorStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
     68                                              explicitLocalCoords)) {
     69             return false;
     70         }
     71     }
     72 
     73     SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices,
     74                             that.fFixedFunctionVertexAttribIndices,
     75                             sizeof(this->fFixedFunctionVertexAttribIndices)));
     76 
     77     return true;
     78 }
     79 
     80 ////////////////////////////////////////////////////////////////////////////////
     81 
     82 bool GrRODrawState::validateVertexAttribs() const {
     83     // check consistency of effects and attributes
     84     GrSLType slTypes[kMaxVertexAttribCnt];
     85     for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
     86         slTypes[i] = static_cast<GrSLType>(-1);
     87     }
     88 
     89     if (this->hasGeometryProcessor()) {
     90         const GrGeometryStage& stage = *this->getGeometryProcessor();
     91         const GrGeometryProcessor* gp = stage.getGeometryProcessor();
     92         SkASSERT(gp);
     93         // make sure that any attribute indices have the correct binding type, that the attrib
     94         // type and effect's shader lang type are compatible, and that attributes shared by
     95         // multiple effects use the same shader lang type.
     96         const GrGeometryProcessor::VertexAttribArray& s = gp->getVertexAttribs();
     97 
     98         int effectIndex = 0;
     99         for (int index = 0; index < fVACount; index++) {
    100             if (kGeometryProcessor_GrVertexAttribBinding != fVAPtr[index].fBinding) {
    101                 // we only care about effect bindings
    102                 continue;
    103             }
    104             SkASSERT(effectIndex < s.count());
    105             GrSLType effectSLType = s[effectIndex].getType();
    106             GrVertexAttribType attribType = fVAPtr[index].fType;
    107             int slVecCount = GrSLTypeVectorCount(effectSLType);
    108             int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
    109             if (slVecCount != attribVecCount ||
    110                 (static_cast<GrSLType>(-1) != slTypes[index] && slTypes[index] != effectSLType)) {
    111                 return false;
    112             }
    113             slTypes[index] = effectSLType;
    114             effectIndex++;
    115         }
    116         // Make sure all attributes are consumed and we were able to find everything
    117         SkASSERT(s.count() == effectIndex);
    118     }
    119 
    120     return true;
    121 }
    122 
    123 bool GrRODrawState::hasSolidCoverage() const {
    124     // If we're drawing coverage directly then coverage is effectively treated as color.
    125     if (this->isCoverageDrawing()) {
    126         return true;
    127     }
    128 
    129     GrColor coverage;
    130     uint32_t validComponentFlags;
    131     // Initialize to an unknown starting coverage if per-vertex coverage is specified.
    132     if (this->hasCoverageVertexAttribute()) {
    133         validComponentFlags = 0;
    134     } else {
    135         coverage = fCoverage;
    136         validComponentFlags = kRGBA_GrColorComponentFlags;
    137     }
    138 
    139     // Run through the coverage stages and see if the coverage will be all ones at the end.
    140     if (this->hasGeometryProcessor()) {
    141         const GrGeometryProcessor* gp = fGeometryProcessor->getGeometryProcessor();
    142         gp->getConstantColorComponents(&coverage, &validComponentFlags);
    143     }
    144     for (int s = 0; s < this->numCoverageStages(); ++s) {
    145         const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
    146         processor->getConstantColorComponents(&coverage, &validComponentFlags);
    147     }
    148     return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
    149 }
    150 
    151 ////////////////////////////////////////////////////////////////////////////////
    152 
    153 bool GrRODrawState::willEffectReadDstColor() const {
    154     if (!this->isColorWriteDisabled()) {
    155         for (int s = 0; s < this->numColorStages(); ++s) {
    156             if (this->getColorStage(s).getFragmentProcessor()->willReadDstColor()) {
    157                 return true;
    158             }
    159         }
    160     }
    161     for (int s = 0; s < this->numCoverageStages(); ++s) {
    162         if (this->getCoverageStage(s).getFragmentProcessor()->willReadDstColor()) {
    163             return true;
    164         }
    165     }
    166     return false;
    167 }
    168 
    169 ////////////////////////////////////////////////////////////////////////////////
    170 
    171 GrRODrawState::BlendOptFlags GrRODrawState::getBlendOpts(bool forceCoverage,
    172                                                          GrBlendCoeff* srcCoeff,
    173                                                          GrBlendCoeff* dstCoeff) const {
    174     GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
    175     if (NULL == srcCoeff) {
    176         srcCoeff = &bogusSrcCoeff;
    177     }
    178     if (NULL == dstCoeff) {
    179         dstCoeff = &bogusDstCoeff;
    180     }
    181 
    182     *srcCoeff = this->getSrcBlendCoeff();
    183     *dstCoeff = this->getDstBlendCoeff();
    184 
    185     if (this->isColorWriteDisabled()) {
    186         *srcCoeff = kZero_GrBlendCoeff;
    187         *dstCoeff = kOne_GrBlendCoeff;
    188     }
    189 
    190     bool srcAIsOne = this->srcAlphaWillBeOne();
    191     bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
    192                          (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
    193     bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
    194                          (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
    195 
    196     // When coeffs are (0,1) there is no reason to draw at all, unless
    197     // stenciling is enabled. Having color writes disabled is effectively
    198     // (0,1).
    199     if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
    200         if (this->getStencil().doesWrite()) {
    201             return kEmitCoverage_BlendOptFlag;
    202         } else {
    203             *dstCoeff = kOne_GrBlendCoeff;
    204             return kSkipDraw_BlendOptFlag;
    205         }
    206     }
    207 
    208     bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
    209 
    210     // if we don't have coverage we can check whether the dst
    211     // has to read at all. If not, we'll disable blending.
    212     if (!hasCoverage) {
    213         if (dstCoeffIsZero) {
    214             if (kOne_GrBlendCoeff == *srcCoeff) {
    215                 // if there is no coverage and coeffs are (1,0) then we
    216                 // won't need to read the dst at all, it gets replaced by src
    217                 *dstCoeff = kZero_GrBlendCoeff;
    218                 return kNone_BlendOpt;
    219             } else if (kZero_GrBlendCoeff == *srcCoeff) {
    220                 // if the op is "clear" then we don't need to emit a color
    221                 // or blend, just write transparent black into the dst.
    222                 *srcCoeff = kOne_GrBlendCoeff;
    223                 *dstCoeff = kZero_GrBlendCoeff;
    224                 return kEmitTransBlack_BlendOptFlag;
    225             }
    226         }
    227     } else if (this->isCoverageDrawing()) {
    228         // we have coverage but we aren't distinguishing it from alpha by request.
    229         return kCoverageAsAlpha_BlendOptFlag;
    230     } else {
    231         // check whether coverage can be safely rolled into alpha
    232         // of if we can skip color computation and just emit coverage
    233         if (this->canTweakAlphaForCoverage()) {
    234             return kCoverageAsAlpha_BlendOptFlag;
    235         }
    236         if (dstCoeffIsZero) {
    237             if (kZero_GrBlendCoeff == *srcCoeff) {
    238                 // the source color is not included in the blend
    239                 // the dst coeff is effectively zero so blend works out to:
    240                 // (c)(0)D + (1-c)D = (1-c)D.
    241                 *dstCoeff = kISA_GrBlendCoeff;
    242                 return  kEmitCoverage_BlendOptFlag;
    243             } else if (srcAIsOne) {
    244                 // the dst coeff is effectively zero so blend works out to:
    245                 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
    246                 // If Sa is 1 then we can replace Sa with c
    247                 // and set dst coeff to 1-Sa.
    248                 *dstCoeff = kISA_GrBlendCoeff;
    249                 return  kCoverageAsAlpha_BlendOptFlag;
    250             }
    251         } else if (dstCoeffIsOne) {
    252             // the dst coeff is effectively one so blend works out to:
    253             // cS + (c)(1)D + (1-c)D = cS + D.
    254             *dstCoeff = kOne_GrBlendCoeff;
    255             return  kCoverageAsAlpha_BlendOptFlag;
    256         }
    257     }
    258 
    259     return kNone_BlendOpt;
    260 }
    261 
    262 ////////////////////////////////////////////////////////////////////////////////
    263 
    264 // Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
    265 // others will blend incorrectly.
    266 bool GrRODrawState::canTweakAlphaForCoverage() const {
    267     /*
    268      The fractional coverage is f.
    269      The src and dst coeffs are Cs and Cd.
    270      The dst and src colors are S and D.
    271      We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
    272      we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
    273      term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
    274      find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
    275      Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
    276      color by definition.
    277      */
    278     return kOne_GrBlendCoeff == fDstBlend ||
    279            kISA_GrBlendCoeff == fDstBlend ||
    280            kISC_GrBlendCoeff == fDstBlend ||
    281            this->isCoverageDrawing();
    282 }
    283 
    284 void GrRODrawState::convertToPendingExec() {
    285     fRenderTarget.markPendingIO();
    286     fRenderTarget.removeRef();
    287     for (int i = 0; i < fColorStages.count(); ++i) {
    288         fColorStages[i].convertToPendingExec();
    289     }
    290     if (fGeometryProcessor) {
    291         fGeometryProcessor->convertToPendingExec();
    292     }
    293     for (int i = 0; i < fCoverageStages.count(); ++i) {
    294         fCoverageStages[i].convertToPendingExec();
    295     }
    296 }
    297 
    298 bool GrRODrawState::srcAlphaWillBeOne() const {
    299     uint32_t validComponentFlags;
    300     GrColor color;
    301     // Check if per-vertex or constant color may have partial alpha
    302     if (this->hasColorVertexAttribute()) {
    303         if (fHints & kVertexColorsAreOpaque_Hint) {
    304             validComponentFlags = kA_GrColorComponentFlag;
    305             color = 0xFF << GrColor_SHIFT_A;
    306         } else {
    307             validComponentFlags = 0;
    308             color = 0; // not strictly necessary but we get false alarms from tools about uninit.
    309         }
    310     } else {
    311         validComponentFlags = kRGBA_GrColorComponentFlags;
    312         color = this->getColor();
    313     }
    314 
    315     // Run through the color stages
    316     for (int s = 0; s < this->numColorStages(); ++s) {
    317         const GrProcessor* processor = this->getColorStage(s).getProcessor();
    318         processor->getConstantColorComponents(&color, &validComponentFlags);
    319     }
    320 
    321     // Check whether coverage is treated as color. If so we run through the coverage computation.
    322     if (this->isCoverageDrawing()) {
    323         // The shader generated for coverage drawing runs the full coverage computation and then
    324         // makes the shader output be the multiplication of color and coverage. We mirror that here.
    325         GrColor coverage;
    326         uint32_t coverageComponentFlags;
    327         if (this->hasCoverageVertexAttribute()) {
    328             coverageComponentFlags = 0;
    329             coverage = 0; // suppresses any warnings.
    330         } else {
    331             coverageComponentFlags = kRGBA_GrColorComponentFlags;
    332             coverage = this->getCoverageColor();
    333         }
    334 
    335         // Run through the coverage stages
    336         for (int s = 0; s < this->numCoverageStages(); ++s) {
    337             const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
    338             processor->getConstantColorComponents(&coverage, &coverageComponentFlags);
    339         }
    340 
    341         // Since the shader will multiply coverage and color, the only way the final A==1 is if
    342         // coverage and color both have A==1.
    343         return (kA_GrColorComponentFlag & validComponentFlags & coverageComponentFlags) &&
    344                 0xFF == GrColorUnpackA(color) && 0xFF == GrColorUnpackA(coverage);
    345 
    346     }
    347 
    348     return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnpackA(color);
    349 }
    350 
    351