'<(skia_src_path)/gpu/GrProgramDesc.h',
'<(skia_src_path)/gpu/GrProgramElement.cpp',
'<(skia_src_path)/gpu/GrProcessor.cpp',
+ '<(skia_src_path)/gpu/GrProcOptInfo.cpp',
+ '<(skia_src_path)/gpu/GrProcOptInfo.h',
'<(skia_src_path)/gpu/GrGpuResourceRef.cpp',
'<(skia_src_path)/gpu/GrPlotMgr.h',
'<(skia_src_path)/gpu/GrRecordReplaceDraw.cpp',
}
}
- bool isOpaque() const {
- return ((fValidFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(fColor));
- }
-
- bool isSolidWhite() const {
- return (fValidFlags == kRGBA_GrColorComponentFlags && 0xFFFFFFFF == fColor);
- }
-
GrColor color() const { return fColor; }
uint8_t validFlags() const { return fValidFlags; }
- bool willUseInputColor() const { return fWillUseInputColor; }
- void resetWillUseInputColor() { fWillUseInputColor = true; }
-
- void resetNonMulStageFound() { fNonMulStageFound = false; }
-
/**
* If isSingleComponent is true, then the flag values for r, g, b, and a must all be the
* same. If the flags are all set then all color components must be equal.
bool fWillUseInputColor;
private:
+ friend class GrProcOptInfo;
+
+ void reset(GrColor color, GrColorComponentFlags flags, bool isSingleComponent) {
+ fColor = color;
+ fValidFlags = flags;
+ fIsSingleComponent = isSingleComponent;
+ fNonMulStageFound = false;
+ fWillUseInputColor = true;
+ }
+
void internalSetToTransparentBlack() {
fValidFlags = kRGBA_GrColorComponentFlags;
fColor = 0;
return ((fValidFlags & kA_GrColorComponentFlag) && 0 == GrColorUnpackA(fColor));
}
+ bool isOpaque() const {
+ return ((fValidFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(fColor));
+ }
+
+ bool isSolidWhite() const {
+ return (fValidFlags == kRGBA_GrColorComponentFlags && 0xFFFFFFFF == fColor);
+ }
+
+ bool willUseInputColor() const { return fWillUseInputColor; }
+ void resetWillUseInputColor() { fWillUseInputColor = true; }
+
+ void resetNonMulStageFound() { fNonMulStageFound = false; }
+
SkDEBUGCODE(bool colorComponentsAllEqual() const;)
/**
* If alpha is valid, check that any valid R,G,B values are <= A
#include "GrDrawState.h"
#include "GrBlend.h"
-#include "GrInvariantOutput.h"
#include "GrOptDrawState.h"
#include "GrPaint.h"
+#include "GrProcOptInfo.h"
//////////////////////////////////////////////////////////////////////////////s
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));
fDrawFace = kBoth_DrawFace;
fHints = 0;
+
+ fColorProcInfoValid = false;
+ fCoverageProcInfoValid = false;
}
bool GrDrawState::setIdentityViewMatrix() {
this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
this->setCoverage(0xFF);
+ fColorProcInfoValid = false;
+ fCoverageProcInfoValid = false;
}
////////////////////////////////////////////////////////////////////////////////
overlapCheck |= (mask << offsetShift);
#endif
}
+ fColorProcInfoValid = false;
+ fCoverageProcInfoValid = false;
// Positions must be specified.
SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
}
0xff,
sizeof(fFixedFunctionVertexAttribIndices));
fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
+ fColorProcInfoValid = false;
+ fCoverageProcInfoValid = false;
}
////////////////////////////////////////////////////////////////////////////////
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();
}
//////////////////////////////////////////////////////////////////////////////
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) {
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;
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 {
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;
+ }
+}
+
#include "GrGeometryProcessor.h"
#include "GrGpuResourceRef.h"
#include "GrProcessorStage.h"
+#include "GrProcOptInfo.h"
#include "GrRenderTarget.h"
#include "GrStencil.h"
#include "SkMatrix.h"
void setColor(GrColor color) {
if (color != fColor) {
fColor = color;
+ fColorProcInfoValid = false;
}
}
void setCoverage(uint8_t coverage) {
if (coverage != fCoverage) {
fCoverage = coverage;
+ fCoverageProcInfoValid = false;
}
}
SkASSERT(geometryProcessor);
SkASSERT(!this->hasGeometryProcessor());
fGeometryProcessor.reset(SkRef(geometryProcessor));
+ fCoverageProcInfoValid = false;
return geometryProcessor;
}
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;
}
*/
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.
// 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;
}
return true;
}
+
#endif // end DEBUG
#include "GrDrawState.h"
#include "GrDrawTargetCaps.h"
#include "GrGpu.h"
-#include "GrInvariantOutput.h"
+#include "GrProcOptInfo.h"
GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
BlendOptFlags blendOptFlags,
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();
}
}
}
#include "GrPaint.h"
#include "GrBlend.h"
-#include "GrInvariantOutput.h"
+#include "GrProcOptInfo.h"
#include "effects/GrSimpleTextureEffect.h"
void GrPaint::addColorTextureProcessor(GrTexture* texture, const SkMatrix& matrix) {
}
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;
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);
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
--- /dev/null
+/*
+ * 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
+ }
+ }
+}
--- /dev/null
+/*
+ * 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
}
void GrProcessor::computeInvariantOutput(GrInvariantOutput* inout) const {
- inout->resetWillUseInputColor();
this->onComputeInvariantOutput(inout);
-#ifdef SK_DEBUG
- inout->validate();
-#endif
}
///////////////////////////////////////////////////////////////////////////////////////////////////