diff options
author | egdaniel <egdaniel@google.com> | 2014-11-13 11:00:34 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-13 11:00:34 -0800 |
commit | b6cbc38702dc4a1540a17181cbdab71060c92ce7 (patch) | |
tree | b56dcff4da761070b2291fa01c64097c232af14a /src | |
parent | bc415389855888af5a1282ca4b6bee30afa3d69d (diff) |
Add GrProcOptInfo class to track various output information for color and coverage stages.
BUG=skia:
Review URL: https://codereview.chromium.org/719203002
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrDrawState.cpp | 152 | ||||
-rw-r--r-- | src/gpu/GrDrawState.h | 23 | ||||
-rw-r--r-- | src/gpu/GrInvariantOutput.cpp | 1 | ||||
-rw-r--r-- | src/gpu/GrOptDrawState.cpp | 25 | ||||
-rw-r--r-- | src/gpu/GrPaint.cpp | 33 | ||||
-rw-r--r-- | src/gpu/GrProcOptInfo.cpp | 56 | ||||
-rw-r--r-- | src/gpu/GrProcOptInfo.h | 85 | ||||
-rw-r--r-- | src/gpu/GrProcessor.cpp | 4 |
8 files changed, 260 insertions, 119 deletions
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp index 513c3bf9e9..6558b0d5fa 100644 --- a/src/gpu/GrDrawState.cpp +++ b/src/gpu/GrDrawState.cpp @@ -8,9 +8,9 @@ #include "GrDrawState.h" #include "GrBlend.h" -#include "GrInvariantOutput.h" #include "GrOptDrawState.h" #include "GrPaint.h" +#include "GrProcOptInfo.h" //////////////////////////////////////////////////////////////////////////////s @@ -151,6 +151,15 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) { fHints = that.fHints; + fColorProcInfoValid = that.fColorProcInfoValid; + fCoverageProcInfoValid = that.fCoverageProcInfoValid; + if (fColorProcInfoValid) { + fColorProcInfo = that.fColorProcInfo; + } + if (fCoverageProcInfoValid) { + fCoverageProcInfo = that.fCoverageProcInfo; + } + memcpy(fFixedFunctionVertexAttribIndices, that.fFixedFunctionVertexAttribIndices, sizeof(fFixedFunctionVertexAttribIndices)); @@ -184,6 +193,9 @@ void GrDrawState::onReset(const SkMatrix* initialViewMatrix) { fDrawFace = kBoth_DrawFace; fHints = 0; + + fColorProcInfoValid = false; + fCoverageProcInfoValid = false; } bool GrDrawState::setIdentityViewMatrix() { @@ -239,6 +251,8 @@ void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRende this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff()); this->setCoverage(0xFF); + fColorProcInfoValid = false; + fCoverageProcInfoValid = false; } //////////////////////////////////////////////////////////////////////////////// @@ -336,6 +350,8 @@ void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int co overlapCheck |= (mask << offsetShift); #endif } + fColorProcInfoValid = false; + fCoverageProcInfoValid = false; // Positions must be specified. SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]); } @@ -355,6 +371,8 @@ void GrDrawState::setDefaultVertexAttribs() { 0xff, sizeof(fFixedFunctionVertexAttribIndices)); fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0; + fColorProcInfoValid = false; + fCoverageProcInfoValid = false; } //////////////////////////////////////////////////////////////////////////////// @@ -384,24 +402,8 @@ bool GrDrawState::hasSolidCoverage() const { return false; } - GrColor color; - GrColorComponentFlags flags; - // Initialize to an unknown starting coverage if per-vertex coverage is specified. - if (this->hasCoverageVertexAttribute()) { - color = 0; - flags = static_cast<GrColorComponentFlags>(0); - } else { - color = this->getCoverageColor(); - flags = kRGBA_GrColorComponentFlags; - } - GrInvariantOutput inout(color, flags, true); - - // check the coverage output from the GP - if (this->hasGeometryProcessor()) { - fGeometryProcessor->computeInvariantOutput(&inout); - } - - return inout.isSolidWhite(); + this->calcCoverageInvariantOutput(); + return fCoverageProcInfo.isSolidWhite(); } ////////////////////////////////////////////////////////////////////////////// @@ -419,18 +421,13 @@ GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawS bool GrDrawState::willEffectReadDstColor() const { if (!this->isColorWriteDisabled()) { - for (int s = 0; s < this->numColorStages(); ++s) { - if (this->getColorStage(s).getProcessor()->willReadDstColor()) { - return true; - } - } - } - for (int s = 0; s < this->numCoverageStages(); ++s) { - if (this->getCoverageStage(s).getProcessor()->willReadDstColor()) { + this->calcColorInvariantOutput(); + if (fColorProcInfo.readsDst()) { return true; } } - return false; + this->calcCoverageInvariantOutput(); + return fCoverageProcInfo.readsDst(); } void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) { @@ -451,6 +448,10 @@ void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) { int n = fDrawState->numCoverageStages() - fCoverageEffectCnt; SkASSERT(n >= 0); fDrawState->fCoverageStages.pop_back_n(n); + if (m + n > 0) { + fDrawState->fColorProcInfoValid = false; + fDrawState->fCoverageProcInfoValid = false; + } SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;) } fDrawState = ds; @@ -689,60 +690,13 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage, return kNone_BlendOpt; } - bool GrDrawState::srcAlphaWillBeOne() const { - GrColor color; - GrColorComponentFlags flags; - // Check if per-vertex or constant color may have partial alpha - if (this->hasColorVertexAttribute()) { - if (fHints & kVertexColorsAreOpaque_Hint) { - flags = kA_GrColorComponentFlag; - color = 0xFF << GrColor_SHIFT_A; - } else { - flags = static_cast<GrColorComponentFlags>(0); - color = 0; - } - } else { - flags = kRGBA_GrColorComponentFlags; - color = this->getColor(); - } - GrInvariantOutput inoutColor(color, flags, false); - - // Run through the color stages - for (int s = 0; s < this->numColorStages(); ++s) { - const GrProcessor* processor = this->getColorStage(s).getProcessor(); - processor->computeInvariantOutput(&inoutColor); - } - - // Check whether coverage is treated as color. If so we run through the coverage computation. + this->calcColorInvariantOutput(); if (this->isCoverageDrawing()) { - // The shader generated for coverage drawing runs the full coverage computation and then - // makes the shader output be the multiplication of color and coverage. We mirror that here. - if (this->hasCoverageVertexAttribute()) { - flags = static_cast<GrColorComponentFlags>(0); - color = 0; - } else { - flags = kRGBA_GrColorComponentFlags; - color = this->getCoverageColor(); - } - GrInvariantOutput inoutCoverage(color, flags, true); - - if (this->hasGeometryProcessor()) { - fGeometryProcessor->computeInvariantOutput(&inoutCoverage); - } - - // Run through the coverage stages - for (int s = 0; s < this->numCoverageStages(); ++s) { - const GrProcessor* processor = this->getCoverageStage(s).getProcessor(); - processor->computeInvariantOutput(&inoutCoverage); - } - - // Since the shader will multiply coverage and color, the only way the final A==1 is if - // coverage and color both have A==1. - return (inoutColor.isOpaque() && inoutCoverage.isOpaque()); + this->calcCoverageInvariantOutput(); + return (fColorProcInfo.isOpaque() && fCoverageProcInfo.isOpaque()); } - - return inoutColor.isOpaque(); + return fColorProcInfo.isOpaque(); } bool GrDrawState::willBlendWithDst() const { @@ -767,3 +721,43 @@ bool GrDrawState::willBlendWithDst() const { return false; } +void GrDrawState::calcColorInvariantOutput() const { + if (!fColorProcInfoValid) { + GrColor color; + GrColorComponentFlags flags; + if (this->hasColorVertexAttribute()) { + if (fHints & kVertexColorsAreOpaque_Hint) { + flags = kA_GrColorComponentFlag; + color = 0xFF << GrColor_SHIFT_A; + } else { + flags = static_cast<GrColorComponentFlags>(0); + color = 0; + } + } else { + flags = kRGBA_GrColorComponentFlags; + color = this->getColor(); + } + fColorProcInfo.calcWithInitialValues(fColorStages.begin(), this->numColorStages(), + color, flags, false); + fColorProcInfoValid = true; + } +} + +void GrDrawState::calcCoverageInvariantOutput() const { + if (!fCoverageProcInfoValid) { + GrColor color; + GrColorComponentFlags flags; + // Check if per-vertex or constant color may have partial alpha + if (this->hasCoverageVertexAttribute()) { + flags = static_cast<GrColorComponentFlags>(0); + color = 0; + } else { + flags = kRGBA_GrColorComponentFlags; + color = this->getCoverageColor(); + } + fCoverageProcInfo.calcWithInitialValues(fCoverageStages.begin(), this->numCoverageStages(), + color, flags, true, fGeometryProcessor.get()); + fCoverageProcInfoValid = true; + } +} + diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index 5c76aed6a3..454390cfbc 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -14,6 +14,7 @@ #include "GrGeometryProcessor.h" #include "GrGpuResourceRef.h" #include "GrProcessorStage.h" +#include "GrProcOptInfo.h" #include "GrRenderTarget.h" #include "GrStencil.h" #include "SkMatrix.h" @@ -181,6 +182,7 @@ public: void setColor(GrColor color) { if (color != fColor) { fColor = color; + fColorProcInfoValid = false; } } @@ -212,6 +214,7 @@ public: void setCoverage(uint8_t coverage) { if (coverage != fCoverage) { fCoverage = coverage; + fCoverageProcInfoValid = false; } } @@ -227,6 +230,7 @@ public: SkASSERT(geometryProcessor); SkASSERT(!this->hasGeometryProcessor()); fGeometryProcessor.reset(SkRef(geometryProcessor)); + fCoverageProcInfoValid = false; return geometryProcessor; } @@ -270,12 +274,14 @@ public: const GrFragmentProcessor* addColorProcessor(const GrFragmentProcessor* effect) { SkASSERT(effect); SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (effect)); + fColorProcInfoValid = false; return effect; } const GrFragmentProcessor* addCoverageProcessor(const GrFragmentProcessor* effect) { SkASSERT(effect); SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrFragmentStage, (effect)); + fCoverageProcInfoValid = false; return effect; } @@ -802,6 +808,18 @@ private: */ bool srcAlphaWillBeOne() const; + /** + * If fColorProcInfoValid is false, function calculates the invariant output for the color + * stages and results are stored in fColorProcInfo. + */ + void calcColorInvariantOutput() const; + + /** + * If fCoverageProcInfoValid is false, function calculates the invariant output for the coverage + * stages and results are stored in fCoverageProcInfo. + */ + void calcCoverageInvariantOutput() const; + void onReset(const SkMatrix* initialViewMatrix); // Some of the auto restore objects assume that no effects are removed during their lifetime. @@ -838,6 +856,11 @@ private: // not need to be compared in op==. int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt]; + mutable GrProcOptInfo fColorProcInfo; + mutable GrProcOptInfo fCoverageProcInfo; + mutable bool fColorProcInfoValid; + mutable bool fCoverageProcInfoValid; + friend class GrOptDrawState; typedef SkRefCnt INHERITED; diff --git a/src/gpu/GrInvariantOutput.cpp b/src/gpu/GrInvariantOutput.cpp index 6f9a9d1ac9..4c77df32f4 100644 --- a/src/gpu/GrInvariantOutput.cpp +++ b/src/gpu/GrInvariantOutput.cpp @@ -52,5 +52,6 @@ bool GrInvariantOutput::validPreMulColor() const { } return true; } + #endif // end DEBUG diff --git a/src/gpu/GrOptDrawState.cpp b/src/gpu/GrOptDrawState.cpp index 7d8b06c129..0f2fcf070b 100644 --- a/src/gpu/GrOptDrawState.cpp +++ b/src/gpu/GrOptDrawState.cpp @@ -11,7 +11,7 @@ #include "GrDrawState.h" #include "GrDrawTargetCaps.h" #include "GrGpu.h" -#include "GrInvariantOutput.h" +#include "GrProcOptInfo.h" GrOptDrawState::GrOptDrawState(const GrDrawState& drawState, BlendOptFlags blendOptFlags, @@ -239,23 +239,14 @@ void GrOptDrawState::computeEffectiveColorStages(const GrDrawState& ds, color = 0; } } - GrInvariantOutput inout(color, flags, false); - - for (int i = 0; i < ds.numColorStages(); ++i) { - const GrFragmentProcessor* fp = ds.getColorStage(i).getProcessor(); - fp->computeInvariantOutput(&inout); - if (!inout.willUseInputColor()) { - *firstColorStageIdx = i; - descInfo->fInputColorIsUsed = false; - } - if (kRGBA_GrColorComponentFlags == inout.validFlags()) { - *firstColorStageIdx = i + 1; - fColor = inout.color(); - descInfo->fInputColorIsUsed = true; + GrProcOptInfo poi; + if (ds.numColorStages() > 0) { + poi.calcWithInitialValues(&ds.getColorStage(0), ds.numColorStages(), color, flags, false); + *firstColorStageIdx = poi.firstEffectiveStageIndex(); + descInfo->fInputColorIsUsed = poi.inputColorIsUsed(); + fColor = poi.inputColorToEffectiveStage(); + if (poi.removeVertexAttrib()) { *fixedFunctionVAToRemove |= 0x1 << kColor_GrVertexAttribBinding; - // Since we are clearing all previous color stages we are in a state where we have found - // zero stages that don't multiply the inputColor. - inout.resetNonMulStageFound(); } } } diff --git a/src/gpu/GrPaint.cpp b/src/gpu/GrPaint.cpp index 366378751d..7d89535a11 100644 --- a/src/gpu/GrPaint.cpp +++ b/src/gpu/GrPaint.cpp @@ -9,7 +9,7 @@ #include "GrPaint.h" #include "GrBlend.h" -#include "GrInvariantOutput.h" +#include "GrProcOptInfo.h" #include "effects/GrSimpleTextureEffect.h" void GrPaint::addColorTextureProcessor(GrTexture* texture, const SkMatrix& matrix) { @@ -37,8 +37,8 @@ bool GrPaint::isOpaque() const { } bool GrPaint::isOpaqueAndConstantColor(GrColor* color) const { - GrColor tempColor; - uint32_t colorComps; + GrColor tempColor = 0; + uint32_t colorComps = 0; if (this->getOpaqueAndKnownColor(&tempColor, &colorComps)) { if (kRGBA_GrColorComponentFlags == colorComps) { *color = tempColor; @@ -52,29 +52,24 @@ bool GrPaint::getOpaqueAndKnownColor(GrColor* solidColor, uint32_t* solidColorKnownComponents) const { // TODO: Share this implementation with GrDrawState + + GrProcOptInfo coverageProcInfo; + coverageProcInfo.calcWithInitialValues(fCoverageStages.begin(), this->numCoverageStages(), + 0xFFFFFFFF, kRGBA_GrColorComponentFlags, true); - GrInvariantOutput inoutCoverage(0xFFFFFFFF, - kRGBA_GrColorComponentFlags, - true); - int count = fCoverageStages.count(); - for (int i = 0; i < count; ++i) { - fCoverageStages[i].getProcessor()->computeInvariantOutput(&inoutCoverage); - } - if (!inoutCoverage.isSolidWhite()) { + if (!coverageProcInfo.isSolidWhite()) { return false; } - GrInvariantOutput inout(fColor, kRGBA_GrColorComponentFlags, false); - count = fColorStages.count(); - for (int i = 0; i < count; ++i) { - fColorStages[i].getProcessor()->computeInvariantOutput(&inout); - } + GrProcOptInfo colorProcInfo; + colorProcInfo.calcWithInitialValues(fColorStages.begin(), this->numColorStages(), fColor, + kRGBA_GrColorComponentFlags, false); SkASSERT((NULL == solidColor) == (NULL == solidColorKnownComponents)); GrBlendCoeff srcCoeff = fSrcBlendCoeff; GrBlendCoeff dstCoeff = fDstBlendCoeff; - GrSimplifyBlend(&srcCoeff, &dstCoeff, inout.color(), inout.validFlags(), + GrSimplifyBlend(&srcCoeff, &dstCoeff, colorProcInfo.color(), colorProcInfo.validFlags(), 0, 0, 0); bool opaque = kZero_GrBlendCoeff == dstCoeff && !GrBlendCoeffRefsDst(srcCoeff); @@ -87,8 +82,8 @@ bool GrPaint::getOpaqueAndKnownColor(GrColor* solidColor, break; case kOne_GrBlendCoeff: - *solidColor = inout.color(); - *solidColorKnownComponents = inout.validFlags(); + *solidColor = colorProcInfo.color(); + *solidColorKnownComponents = colorProcInfo.validFlags(); break; // The src coeff should never refer to the src and if it refers to dst then opaque diff --git a/src/gpu/GrProcOptInfo.cpp b/src/gpu/GrProcOptInfo.cpp new file mode 100644 index 0000000000..c3ca100b61 --- /dev/null +++ b/src/gpu/GrProcOptInfo.cpp @@ -0,0 +1,56 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrProcOptInfo.h" + +#include "GrGeometryProcessor.h" +#include "GrProcessorStage.h" + +void GrProcOptInfo::calcWithInitialValues(const GrFragmentStage* stages, + int stageCount, + GrColor startColor, + GrColorComponentFlags flags, + bool areCoverageStages, + const GrGeometryProcessor* gp) { + fInOut.reset(startColor, flags, areCoverageStages); + fFirstEffectStageIndex = 0; + fInputColorIsUsed = true; + fInputColor = startColor; + fRemoveVertexAttrib = false; + fReadsDst = false; + + if (areCoverageStages && gp) { + gp->computeInvariantOutput(&fInOut); + } + + for (int i = 0; i < stageCount; ++i) { + const GrFragmentProcessor* processor = stages[i].getProcessor(); + fInOut.resetWillUseInputColor(); + processor->computeInvariantOutput(&fInOut); + #ifdef SK_DEBUG + fInOut.validate(); + #endif + if (!fInOut.willUseInputColor()) { + fFirstEffectStageIndex = i; + fInputColorIsUsed = false; + fReadsDst = false; // Reset this since we don't care if previous stages read dst + } + if (processor->willReadDstColor()) { + fReadsDst = true; + } + if (kRGBA_GrColorComponentFlags == fInOut.validFlags()) { + fFirstEffectStageIndex = i + 1; + fInputColor = fInOut.color(); + fInputColorIsUsed = true; + fRemoveVertexAttrib = true; + // Since we are clearing all previous color stages we are in a state where we have found + // zero stages that don't multiply the inputColor. + fInOut.resetNonMulStageFound(); + fReadsDst = false; // Reset this since we don't care if previous stages read dst + } + } +} diff --git a/src/gpu/GrProcOptInfo.h b/src/gpu/GrProcOptInfo.h new file mode 100644 index 0000000000..5252e85354 --- /dev/null +++ b/src/gpu/GrProcOptInfo.h @@ -0,0 +1,85 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrProcOptInfo_DEFINED +#define GrProcOptInfo_DEFINED + +#include "GrColor.h" +#include "GrInvariantOutput.h" + +class GrFragmentStage; +class GrGeometryProcessor; + +/** + * GrProcOptInfo gathers invariant data from a set of processor stages.It is used to recognize + * optimizations related to eliminating stages and vertex attributes that aren't necessary for a + * draw. + */ +class GrProcOptInfo { +public: + GrProcOptInfo() + : fInOut(0, static_cast<GrColorComponentFlags>(0), false) + , fFirstEffectStageIndex(0) + , fInputColorIsUsed(true) + , fInputColor(0) + , fRemoveVertexAttrib(false) + , fReadsDst(false) {} + + void calcWithInitialValues(const GrFragmentStage*, int stageCount, GrColor startColor, + GrColorComponentFlags flags, bool areCoverageStages, + const GrGeometryProcessor* gp = NULL); + + bool isSolidWhite() const { return fInOut.isSolidWhite(); } + bool isOpaque() const { return fInOut.isOpaque(); } + + GrColor color() const { return fInOut.color(); } + uint8_t validFlags() const { return fInOut.validFlags(); } + + /** + * Returns the index of the first effective color stage. If an intermediate stage doesn't read + * its input or has a known output, then we can ignore all earlier stages since they will not + * affect the final output. Thus the first effective stage index is the index to the first stage + * that will have an effect on the final output. + * + * If stages before the firstEffectiveStageIndex are removed, corresponding values from + * inputColorIsUsed(), inputColorToEffectiveStage(), removeVertexAttribs(), and readsDst() must + * be used when setting up the draw to ensure correct drawing. + */ + int firstEffectiveStageIndex() const { return fFirstEffectStageIndex; } + + /** + * True if the first effective stage reads its input, false otherwise. + */ + bool inputColorIsUsed() const { return fInputColorIsUsed; } + + /** + * If input color is used and per-vertex colors are not used, this is the input color to the + * first effective stage. + */ + GrColor inputColorToEffectiveStage() const { return fInputColor; } + + /** + * Given the set of optimizations determined by GrProcOptInfo, should the caller remove the + * color/coverage vertex attribute that was input to the first stage. + */ + bool removeVertexAttrib() const { return fRemoveVertexAttrib; } + + /** + * Returns true if any of the stages preserved by GrProcOptInfo read the dst color. + */ + bool readsDst() const { return fReadsDst; } + +private: + GrInvariantOutput fInOut; + int fFirstEffectStageIndex; + bool fInputColorIsUsed; + GrColor fInputColor; + bool fRemoveVertexAttrib; + bool fReadsDst; +}; + +#endif diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp index 31f0004e68..01071dabfd 100644 --- a/src/gpu/GrProcessor.cpp +++ b/src/gpu/GrProcessor.cpp @@ -130,11 +130,7 @@ bool GrProcessor::hasSameTextureAccesses(const GrProcessor& that) const { } void GrProcessor::computeInvariantOutput(GrInvariantOutput* inout) const { - inout->resetWillUseInputColor(); this->onComputeInvariantOutput(inout); -#ifdef SK_DEBUG - inout->validate(); -#endif } /////////////////////////////////////////////////////////////////////////////////////////////////// |