Delay copying effects from DS or ODS till end of creating ODS

Also delay the removal of fixed function VA's until so we only have to do a single removal step

BUG=skia:

Review URL: https://codereview.chromium.org/634073002
This commit is contained in:
egdaniel 2014-10-08 06:49:10 -07:00 committed by Commit bot
parent 3d7d410ce5
commit 9cf45bf119
2 changed files with 87 additions and 73 deletions

View File

@ -35,21 +35,52 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
drawState.getFixedFunctionVertexAttribIndices(),
sizeof(fFixedFunctionVertexAttribIndices));
fInputColorIsUsed = true;
fInputCoverageIsUsed = true;
int firstColorStageIdx = 0;
int firstCoverageStageIdx = 0;
bool separateCoverageFromColor;
uint8_t fixedFunctionVAToRemove = 0;
this->computeEffectiveColorStages(drawState, &firstColorStageIdx, &fixedFunctionVAToRemove);
this->computeEffectiveCoverageStages(drawState, &firstCoverageStageIdx);
this->adjustFromBlendOpts(drawState, &firstColorStageIdx, &firstCoverageStageIdx,
&fixedFunctionVAToRemove);
// Should not be setting any more FFVA to be removed at this point
this->removeFixedFunctionVertexAttribs(fixedFunctionVAToRemove);
this->getStageStats(drawState, firstColorStageIdx, firstCoverageStageIdx);
this->setOutputStateInfo(drawState, caps, firstCoverageStageIdx, &separateCoverageFromColor);
// Copy GeometryProcesssor from DS or ODS
if (drawState.hasGeometryProcessor()) {
fGeometryProcessor.reset(SkNEW_ARGS(GrGeometryStage, (*drawState.getGeometryProcessor())));
} else {
fGeometryProcessor.reset(NULL);
}
this->copyEffectiveColorStages(drawState);
this->copyEffectiveCoverageStages(drawState);
this->adjustFromBlendOpts();
this->getStageStats();
this->setOutputStateInfo(caps);
// Copy Color Stages from DS to ODS
if (firstColorStageIdx < drawState.numColorStages()) {
fColorStages.reset(&drawState.getColorStage(firstColorStageIdx),
drawState.numColorStages() - firstColorStageIdx);
} else {
fColorStages.reset();
}
// Copy Coverage Stages from DS to ODS
if (drawState.numCoverageStages() > 0 && separateCoverageFromColor) {
fCoverageStages.reset(&drawState.getCoverageStage(firstCoverageStageIdx),
drawState.numCoverageStages() - firstCoverageStageIdx);
} else {
fCoverageStages.reset();
if (drawState.numCoverageStages() > 0) {
// TODO: Once we have flag to know if we only multiply on stages, only push coverage
// into color stages if everything is multiply
fColorStages.push_back_n(drawState.numCoverageStages() - firstCoverageStageIdx,
&drawState.getCoverageStage(firstCoverageStageIdx));
}
}
};
GrOptDrawState* GrOptDrawState::Create(const GrDrawState& drawState, const GrDrawTargetCaps& caps,
@ -88,55 +119,51 @@ GrOptDrawState* GrOptDrawState::Create(const GrDrawState& drawState, const GrDra
return drawState.fCachedOptState;
}
void GrOptDrawState::setOutputStateInfo(const GrDrawTargetCaps& caps) {
void GrOptDrawState::setOutputStateInfo(const GrDrawState& ds,
const GrDrawTargetCaps& caps,
int firstCoverageStageIdx,
bool* separateCoverageFromColor) {
// Set this default and then possibly change our mind if there is coverage.
fPrimaryOutputType = kModulate_PrimaryOutputType;
fSecondaryOutputType = kNone_SecondaryOutputType;
// If we do have coverage determine whether it matters.
bool separateCoverageFromColor = this->hasGeometryProcessor();
*separateCoverageFromColor = this->hasGeometryProcessor();
if (!this->isCoverageDrawing() &&
(this->numCoverageStages() > 0 ||
this->hasGeometryProcessor() ||
(ds.numCoverageStages() - firstCoverageStageIdx > 0 ||
ds.hasGeometryProcessor() ||
this->hasCoverageVertexAttribute())) {
if (caps.dualSourceBlendingSupport()) {
if (kZero_GrBlendCoeff == fDstBlend) {
// write the coverage value to second color
fSecondaryOutputType = kCoverage_SecondaryOutputType;
separateCoverageFromColor = true;
*separateCoverageFromColor = true;
fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
} else if (kSA_GrBlendCoeff == fDstBlend) {
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
fSecondaryOutputType = kCoverageISA_SecondaryOutputType;
separateCoverageFromColor = true;
*separateCoverageFromColor = true;
fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
} else if (kSC_GrBlendCoeff == fDstBlend) {
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
fSecondaryOutputType = kCoverageISC_SecondaryOutputType;
separateCoverageFromColor = true;
*separateCoverageFromColor = true;
fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
}
} else if (fReadsDst &&
kOne_GrBlendCoeff == fSrcBlend &&
kZero_GrBlendCoeff == fDstBlend) {
fPrimaryOutputType = kCombineWithDst_PrimaryOutputType;
separateCoverageFromColor = true;
*separateCoverageFromColor = true;
}
}
// TODO: Once we have flag to know if we only multiply on stages, only push coverage into color
// stages if everything is multipy
if (!separateCoverageFromColor) {
for (int s = 0; s < this->numCoverageStages(); ++s) {
fColorStages.push_back(this->getCoverageStage(s));
}
fCoverageStages.reset();
}
}
void GrOptDrawState::adjustFromBlendOpts() {
void GrOptDrawState::adjustFromBlendOpts(const GrDrawState& ds,
int* firstColorStageIdx,
int* firstCoverageStageIdx,
uint8_t* fixedFunctionVAToRemove) {
switch (fBlendOptFlags) {
case kNone_BlendOpt:
case kSkipDraw_BlendOptFlag:
@ -147,22 +174,21 @@ void GrOptDrawState::adjustFromBlendOpts() {
case kEmitCoverage_BlendOptFlag:
fColor = 0xffffffff;
fInputColorIsUsed = true;
fColorStages.reset();
this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding);
*firstColorStageIdx = ds.numColorStages();
*fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding;
break;
case kEmitTransBlack_BlendOptFlag:
fColor = 0;
fCoverage = 0xff;
fInputColorIsUsed = true;
fInputCoverageIsUsed = true;
fColorStages.reset();
fCoverageStages.reset();
this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding |
*firstColorStageIdx = ds.numColorStages();
*firstCoverageStageIdx = ds.numCoverageStages();
*fixedFunctionVAToRemove |= (0x1 << kColor_GrVertexAttribBinding |
0x1 << kCoverage_GrVertexAttribBinding);
break;
default:
SkFAIL("Unknown BlendOptFlag");
}
}
@ -201,9 +227,8 @@ void GrOptDrawState::removeFixedFunctionVertexAttribs(uint8_t removeVAFlag) {
fVAPtr = fOptVA.get();
}
void GrOptDrawState::copyEffectiveColorStages(const GrDrawState& ds) {
int firstColorStage = 0;
void GrOptDrawState::computeEffectiveColorStages(const GrDrawState& ds, int* firstColorStageIdx,
uint8_t* fixedFunctionVAToRemove) {
// Set up color and flags for ConstantColorComponent checks
GrProcessor::InvariantOutput inout;
inout.fIsSingleComponent = false;
@ -224,28 +249,21 @@ void GrOptDrawState::copyEffectiveColorStages(const GrDrawState& ds) {
for (int i = 0; i < ds.numColorStages(); ++i) {
const GrFragmentProcessor* fp = ds.getColorStage(i).getProcessor();
if (!fp->willUseInputColor()) {
firstColorStage = i;
*firstColorStageIdx = i;
fInputColorIsUsed = false;
}
fp->computeInvariantOutput(&inout);
if (kRGBA_GrColorComponentFlags == inout.fValidFlags) {
firstColorStage = i + 1;
*firstColorStageIdx = i + 1;
fColor = inout.fColor;
fInputColorIsUsed = true;
this->removeFixedFunctionVertexAttribs(0x1 << kColor_GrVertexAttribBinding);
*fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding;
}
}
if (firstColorStage < ds.numColorStages()) {
fColorStages.reset(&ds.getColorStage(firstColorStage),
ds.numColorStages() - firstColorStage);
} else {
fColorStages.reset();
}
}
void GrOptDrawState::copyEffectiveCoverageStages(const GrDrawState& ds) {
int firstCoverageStage = 0;
void GrOptDrawState::computeEffectiveCoverageStages(const GrDrawState& ds,
int* firstCoverageStageIdx) {
// We do not try to optimize out constantColor coverage effects here. It is extremely rare
// to have a coverage effect that returns a constant value for all four channels. Thus we
// save having to make extra virtual calls by not checking for it.
@ -256,17 +274,11 @@ void GrOptDrawState::copyEffectiveCoverageStages(const GrDrawState& ds) {
for (int i = 0; i < ds.numCoverageStages(); ++i) {
const GrProcessor* processor = ds.getCoverageStage(i).getProcessor();
if (!processor->willUseInputColor()) {
firstCoverageStage = i;
*firstCoverageStageIdx = i;
fInputCoverageIsUsed = false;
}
}
#endif
if (ds.numCoverageStages() > 0) {
fCoverageStages.reset(&ds.getCoverageStage(firstCoverageStage),
ds.numCoverageStages() - firstCoverageStage);
} else {
fCoverageStages.reset();
}
}
static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
@ -278,24 +290,26 @@ static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool*
}
}
void GrOptDrawState::getStageStats() {
void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx,
int firstCoverageStageIdx) {
// We will need a local coord attrib if there is one currently set on the optState and we are
// actually generating some effect code
fRequiresLocalCoordAttrib = this->hasLocalCoordAttribute() && this->numTotalStages() > 0;
fRequiresLocalCoordAttrib = this->hasLocalCoordAttribute() &&
ds.numTotalStages() - firstColorStageIdx - firstCoverageStageIdx > 0;
fReadsDst = false;
fReadsFragPosition = false;
for (int s = 0; s < this->numColorStages(); ++s) {
const GrFragmentStage& stage = this->getColorStage(s);
for (int s = firstColorStageIdx; s < ds.numColorStages(); ++s) {
const GrFragmentStage& stage = ds.getColorStage(s);
get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
}
for (int s = 0; s < this->numCoverageStages(); ++s) {
const GrFragmentStage& stage = this->getCoverageStage(s);
for (int s = firstCoverageStageIdx; s < ds.numCoverageStages(); ++s) {
const GrFragmentStage& stage = ds.getCoverageStage(s);
get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
}
if (this->hasGeometryProcessor()) {
const GrGeometryStage& stage = *this->getGeometryProcessor();
if (ds.hasGeometryProcessor()) {
const GrGeometryStage& stage = *ds.getGeometryProcessor();
fReadsFragPosition = fReadsFragPosition || stage.getProcessor()->willReadFragmentPosition();
}
}

View File

@ -375,19 +375,17 @@ private:
* Loops through all the color stage effects to check if the stage will ignore color input or
* always output a constant color. In the ignore color input case we can ignore all previous
* stages. In the constant color case, we can ignore all previous stages and
* the current one and set the state color to the constant color. Once we determine the so
* called first effective stage, we copy all the effective stages into our optimized
* state.
* the current one and set the state color to the constant color.
*/
void copyEffectiveColorStages(const GrDrawState& ds);
void computeEffectiveColorStages(const GrDrawState& ds, int* firstColorStageIdx,
uint8_t* fixFunctionVAToRemove);
/**
* Loops through all the coverage stage effects to check if the stage will ignore color input.
* If a coverage stage will ignore input, then we can ignore all coverage stages before it. We
* loop to determine the first effective coverage stage, and then copy all of our effective
* coverage stages into our optimized state.
* loop to determine the first effective coverage stage.
*/
void copyEffectiveCoverageStages(const GrDrawState& ds);
void computeEffectiveCoverageStages(const GrDrawState& ds, int* firstCoverageStageIdx);
/**
* This function takes in a flag and removes the corresponding fixed function vertex attributes.
@ -400,20 +398,22 @@ private:
* Alter the OptDrawState (adjusting stages, vertex attribs, flags, etc.) based on the
* BlendOptFlags.
*/
void adjustFromBlendOpts();
void adjustFromBlendOpts(const GrDrawState& ds, int* firstColorStageIdx,
int* firstCoverageStageIdx, uint8_t* fixedFunctionVAToRemove);
/**
* Loop over the effect stages to determine various info like what data they will read and what
* shaders they require.
*/
void getStageStats();
void getStageStats(const GrDrawState& ds, int firstColorStageIdx, int firstCoverageStageIdx);
/**
* Calculates the primary and secondary output types of the shader. For certain output types
* the function may adjust the blend coefficients. After this function is called the src and dst
* blend coeffs will represent those used by backend API.
*/
void setOutputStateInfo(const GrDrawTargetCaps&);
void setOutputStateInfo(const GrDrawState& ds, const GrDrawTargetCaps&,
int firstCoverageStageIdx, bool* separateCoverageFromColor);
bool isEqual(const GrOptDrawState& that) const;
@ -433,7 +433,7 @@ private:
GrBlendCoeff fSrcBlend;
GrBlendCoeff fDstBlend;
typedef SkSTArray<4, GrFragmentStage> FragmentStageArray;
typedef SkSTArray<8, GrFragmentStage> FragmentStageArray;
SkAutoTDelete<GrGeometryStage> fGeometryProcessor;
FragmentStageArray fColorStages;
FragmentStageArray fCoverageStages;