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 "GrOptDrawState.h"
      9 
     10 #include "GrDrawState.h"
     11 #include "GrDrawTargetCaps.h"
     12 #include "GrGpu.h"
     13 
     14 GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
     15                                BlendOptFlags blendOptFlags,
     16                                GrBlendCoeff optSrcCoeff,
     17                                GrBlendCoeff optDstCoeff,
     18                                const GrDrawTargetCaps& caps) : INHERITED(drawState) {
     19     fColor = drawState.getColor();
     20     fCoverage = drawState.getCoverage();
     21     fViewMatrix = drawState.getViewMatrix();
     22     fBlendConstant = drawState.getBlendConstant();
     23     fFlagBits = drawState.getFlagBits();
     24     fVAPtr = drawState.getVertexAttribs();
     25     fVACount = drawState.getVertexAttribCount();
     26     fVAStride = drawState.getVertexStride();
     27     fStencilSettings = drawState.getStencil();
     28     fDrawFace = drawState.getDrawFace();
     29     fBlendOptFlags = blendOptFlags;
     30     fSrcBlend = optSrcCoeff;
     31     fDstBlend = optDstCoeff;
     32 
     33     memcpy(fFixedFunctionVertexAttribIndices,
     34             drawState.getFixedFunctionVertexAttribIndices(),
     35             sizeof(fFixedFunctionVertexAttribIndices));
     36 
     37 
     38     fInputColorIsUsed = true;
     39     fInputCoverageIsUsed = true;
     40 
     41     if (drawState.hasGeometryProcessor()) {
     42         fGeometryProcessor.reset(SkNEW_ARGS(GrGeometryStage, (*drawState.getGeometryProcessor())));
     43     } else {
     44         fGeometryProcessor.reset(NULL);
     45     }
     46 
     47     this->copyEffectiveColorStages(drawState);
     48     this->copyEffectiveCoverageStages(drawState);
     49     this->adjustFromBlendOpts();
     50     this->getStageStats();
     51     this->setOutputStateInfo(caps);
     52 };
     53 
     54 void GrOptDrawState::setOutputStateInfo(const GrDrawTargetCaps& caps) {
     55     // Set this default and then possibly change our mind if there is coverage.
     56     fPrimaryOutputType = kModulate_PrimaryOutputType;
     57     fSecondaryOutputType = kNone_SecondaryOutputType;
     58 
     59     // If we do have coverage determine whether it matters.
     60     bool separateCoverageFromColor = this->hasGeometryProcessor();
     61     if (!this->isCoverageDrawing() &&
     62         (this->numCoverageStages() > 0 ||
     63          this->hasGeometryProcessor() ||
     64          this->hasCoverageVertexAttribute())) {
     65 
     66         if (caps.dualSourceBlendingSupport()) {
     67             if (kZero_GrBlendCoeff == fDstBlend) {
     68                 // write the coverage value to second color
     69                 fSecondaryOutputType =  kCoverage_SecondaryOutputType;
     70                 separateCoverageFromColor = true;
     71                 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
     72             } else if (kSA_GrBlendCoeff == fDstBlend) {
     73                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
     74                 fSecondaryOutputType = kCoverageISA_SecondaryOutputType;
     75                 separateCoverageFromColor = true;
     76                 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
     77             } else if (kSC_GrBlendCoeff == fDstBlend) {
     78                 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
     79                 fSecondaryOutputType = kCoverageISC_SecondaryOutputType;
     80                 separateCoverageFromColor = true;
     81                 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
     82             }
     83         } else if (fReadsDst &&
     84                    kOne_GrBlendCoeff == fSrcBlend &&
     85                    kZero_GrBlendCoeff == fDstBlend) {
     86             fPrimaryOutputType = kCombineWithDst_PrimaryOutputType;
     87             separateCoverageFromColor = true;
     88         }
     89     }
     90 
     91     // TODO: Once we have flag to know if we only multiply on stages, only push coverage into color
     92     // stages if everything is multipy
     93     if (!separateCoverageFromColor) {
     94         for (int s = 0; s < this->numCoverageStages(); ++s) {
     95             fColorStages.push_back(this->getCoverageStage(s));
     96         }
     97         fCoverageStages.reset();
     98     }
     99 }
    100 
    101 void GrOptDrawState::adjustFromBlendOpts() {
    102 
    103     switch (fBlendOptFlags) {
    104         case kNone_BlendOpt:
    105         case kSkipDraw_BlendOptFlag:
    106             break;
    107         case kCoverageAsAlpha_BlendOptFlag:
    108             fFlagBits |= kCoverageDrawing_StateBit;
    109             break;
    110         case kEmitCoverage_BlendOptFlag:
    111             fColor = 0xffffffff;
    112             fInputColorIsUsed = true;
    113             fColorStages.reset();
    114             this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding);
    115             break;
    116         case kEmitTransBlack_BlendOptFlag:
    117             fColor = 0;
    118             fCoverage = 0xff;
    119             fInputColorIsUsed = true;
    120             fInputCoverageIsUsed = true;
    121             fColorStages.reset();
    122             fCoverageStages.reset();
    123             this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding |
    124                                                    0x1 << kCoverage_GrVertexAttribBinding);
    125             break;
    126         default:
    127             SkFAIL("Unknown BlendOptFlag");
    128 
    129     }
    130 }
    131 
    132 void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) {
    133     int numToRemove = 0;
    134     uint8_t maskCheck = 0x1;
    135     // Count the number of vertex attributes that we will actually remove
    136     for (int i = 0; i < kGrFixedFunctionVertexAttribBindingCnt; ++i) {
    137         if ((maskCheck & removeVAFlag) && -1 != fFixedFunctionVertexAttribIndices[i]) {
    138             ++numToRemove;
    139         }
    140         maskCheck <<= 1;
    141     }
    142 
    143     fOptVA.reset(fVACount - numToRemove);
    144 
    145     GrVertexAttrib* dst = fOptVA.get();
    146     const GrVertexAttrib* src = fVAPtr;
    147 
    148     for (int i = 0, newIdx = 0; i < fVACount; ++i, ++src) {
    149         const GrVertexAttrib& currAttrib = *src;
    150         if (currAttrib.fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
    151             uint8_t maskCheck = 0x1 << currAttrib.fBinding;
    152             if (maskCheck & removeVAFlag) {
    153                 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[currAttrib.fBinding]);
    154                 fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = -1;
    155                 continue;
    156             }
    157             fFixedFunctionVertexAttribIndices[currAttrib.fBinding] = newIdx;
    158         }
    159         memcpy(dst, src, sizeof(GrVertexAttrib));
    160         ++newIdx;
    161         ++dst;
    162     }
    163     fVACount -= numToRemove;
    164     fVAPtr = fOptVA.get();
    165 }
    166 
    167 void GrOptDrawState::copyEffectiveColorStages(const GrDrawState& ds) {
    168     int firstColorStage = 0;
    169 
    170     // Set up color and flags for ConstantColorComponent checks
    171     GrColor color;
    172     uint32_t validComponentFlags;
    173     if (!this->hasColorVertexAttribute()) {
    174         color = ds.getColor();
    175         validComponentFlags = kRGBA_GrColorComponentFlags;
    176     } else {
    177         if (ds.vertexColorsAreOpaque()) {
    178             color = 0xFF << GrColor_SHIFT_A;
    179             validComponentFlags = kA_GrColorComponentFlag;
    180         } else {
    181             validComponentFlags = 0;
    182             color = 0; // not strictly necessary but we get false alarms from tools about uninit.
    183         }
    184     }
    185 
    186     for (int i = 0; i < ds.numColorStages(); ++i) {
    187         const GrFragmentProcessor* fp = ds.getColorStage(i).getFragmentProcessor();
    188         if (!fp->willUseInputColor()) {
    189             firstColorStage = i;
    190             fInputColorIsUsed = false;
    191         }
    192         fp->getConstantColorComponents(&color, &validComponentFlags);
    193         if (kRGBA_GrColorComponentFlags == validComponentFlags) {
    194             firstColorStage = i + 1;
    195             fColor = color;
    196             fInputColorIsUsed = true;
    197             this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding);
    198         }
    199     }
    200     if (firstColorStage < ds.numColorStages()) {
    201         fColorStages.reset(&ds.getColorStage(firstColorStage),
    202                            ds.numColorStages() - firstColorStage);
    203     } else {
    204         fColorStages.reset();
    205     }
    206 }
    207 
    208 void GrOptDrawState::copyEffectiveCoverageStages(const GrDrawState& ds) {
    209     int firstCoverageStage = 0;
    210 
    211     // We do not try to optimize out constantColor coverage effects here. It is extremely rare
    212     // to have a coverage effect that returns a constant value for all four channels. Thus we
    213     // save having to make extra virtual calls by not checking for it.
    214 
    215     // Don't do any optimizations on coverage stages. It should not be the case where we do not use
    216     // input coverage in an effect
    217 #ifdef OptCoverageStages
    218     for (int i = 0; i < ds.numCoverageStages(); ++i) {
    219         const GrProcessor* processor = ds.getCoverageStage(i).getProcessor();
    220         if (!processor->willUseInputColor()) {
    221             firstCoverageStage = i;
    222             fInputCoverageIsUsed = false;
    223         }
    224     }
    225 #endif
    226     if (ds.numCoverageStages() > 0) {
    227         fCoverageStages.reset(&ds.getCoverageStage(firstCoverageStage),
    228                               ds.numCoverageStages() - firstCoverageStage);
    229     } else {
    230         fCoverageStages.reset();
    231     }
    232 }
    233 
    234 static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
    235     if (stage.getFragmentProcessor()->willReadDstColor()) {
    236         *readsDst = true;
    237     }
    238     if (stage.getFragmentProcessor()->willReadFragmentPosition()) {
    239         *readsFragPosition = true;
    240     }
    241 }
    242 
    243 void GrOptDrawState::getStageStats() {
    244     // We will need a local coord attrib if there is one currently set on the optState and we are
    245     // actually generating some effect code
    246     fRequiresLocalCoordAttrib = this->hasLocalCoordAttribute() && this->numTotalStages() > 0;
    247 
    248     fReadsDst = false;
    249     fReadsFragPosition = false;
    250 
    251     for (int s = 0; s < this->numColorStages(); ++s) {
    252         const GrFragmentStage& stage = this->getColorStage(s);
    253         get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
    254     }
    255     for (int s = 0; s < this->numCoverageStages(); ++s) {
    256         const GrFragmentStage& stage = this->getCoverageStage(s);
    257         get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
    258     }
    259     if (this->hasGeometryProcessor()) {
    260         const GrGeometryStage& stage = *this->getGeometryProcessor();
    261         fReadsFragPosition = fReadsFragPosition || stage.getProcessor()->willReadFragmentPosition();
    262     }
    263 }
    264 
    265 bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
    266     return this->isEqual(that);
    267 }
    268 
    269