diff options
-rw-r--r-- | include/gpu/GrPaint.h | 6 | ||||
-rw-r--r-- | include/gpu/GrProcessor.h | 45 | ||||
-rw-r--r-- | src/core/SkXfermode.cpp | 2 | ||||
-rw-r--r-- | src/effects/SkArithmeticMode.cpp | 2 | ||||
-rw-r--r-- | src/effects/SkColorCubeFilter.cpp | 2 | ||||
-rw-r--r-- | src/effects/SkColorFilters.cpp | 24 | ||||
-rw-r--r-- | src/effects/SkColorMatrixFilter.cpp | 5 | ||||
-rw-r--r-- | src/effects/SkDisplacementMapEffect.cpp | 3 | ||||
-rw-r--r-- | src/effects/SkLumaColorFilter.cpp | 3 | ||||
-rw-r--r-- | src/effects/SkPerlinNoiseShader.cpp | 3 | ||||
-rw-r--r-- | src/effects/SkTableColorFilter.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrOptDrawState.cpp | 13 | ||||
-rw-r--r-- | src/gpu/GrProcessor.cpp | 3 | ||||
-rw-r--r-- | src/gpu/effects/GrConvexPolyEffect.cpp | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrDitherEffect.cpp | 2 | ||||
-rw-r--r-- | src/gpu/effects/GrYUVtoRGBEffect.cpp | 4 | ||||
-rw-r--r-- | tests/GpuColorFilterTest.cpp | 3 |
17 files changed, 77 insertions, 47 deletions
diff --git a/include/gpu/GrPaint.h b/include/gpu/GrPaint.h index ff37fcfee8..c5563f00fa 100644 --- a/include/gpu/GrPaint.h +++ b/include/gpu/GrPaint.h @@ -89,9 +89,6 @@ public: */ const GrFragmentProcessor* addColorProcessor(const GrFragmentProcessor* fp) { SkASSERT(fp); - if (!fp->willUseInputColor()) { - fColorStages.reset(); - } SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (fp)); return fp; } @@ -101,9 +98,6 @@ public: */ const GrFragmentProcessor* addCoverageProcessor(const GrFragmentProcessor* fp) { SkASSERT(fp); - if (!fp->willUseInputColor()) { - fCoverageStages.reset(); - } SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrFragmentStage, (fp)); return fp; } diff --git a/include/gpu/GrProcessor.h b/include/gpu/GrProcessor.h index c860b32c1b..ee1266359f 100644 --- a/include/gpu/GrProcessor.h +++ b/include/gpu/GrProcessor.h @@ -13,6 +13,7 @@ #include "GrProcessorUnitTest.h" #include "GrProgramElement.h" #include "GrTextureAccess.h" +#include "SkMath.h" class GrContext; class GrCoordTransform; @@ -32,7 +33,12 @@ public: struct InvariantOutput{ InvariantOutput() : fColor(0), fValidFlags(0), fIsSingleComponent(false), - fNonMulStageFound(false) {} + fNonMulStageFound(false), fWillUseInputColor(true) {} + + enum ReadInput { + kWill_ReadInput, + kWillNot_ReadInput, + }; void mulByUnknownOpaqueColor() { if (this->isOpaque()) { @@ -62,26 +68,44 @@ public: } } - void invalidateComponents(uint8_t invalidateFlags) { - fValidFlags &= ~invalidateFlags; - fIsSingleComponent = false; + void mulByKnownAlpha(uint8_t alpha) { + if (this->hasZeroAlpha() || 0 == alpha) { + this->internalSetToTransparentBlack(); + } else { + if (alpha != 255) { + // Multiply color by alpha + fColor = GrColorPackRGBA(SkMulDiv255Round(GrColorUnpackR(fColor), alpha), + SkMulDiv255Round(GrColorUnpackG(fColor), alpha), + SkMulDiv255Round(GrColorUnpackB(fColor), alpha), + SkMulDiv255Round(GrColorUnpackA(fColor), alpha)); + } + } } - void setToTransparentBlack() { - this->internalSetToTransparentBlack(); - fNonMulStageFound = true; + void invalidateComponents(uint8_t invalidateFlags, ReadInput readsInput) { + fValidFlags &= ~invalidateFlags; + fIsSingleComponent = false; + if (kWillNot_ReadInput == readsInput) { + fWillUseInputColor = false; + } } - void setToOther(uint8_t validFlags, GrColor color) { + void setToOther(uint8_t validFlags, GrColor color, ReadInput readsInput) { fValidFlags = validFlags; fColor = color; fIsSingleComponent = false; fNonMulStageFound = true; + if (kWillNot_ReadInput == readsInput) { + fWillUseInputColor = false; + } } - void setToUnknown() { + void setToUnknown(ReadInput readsInput) { this->internalSetToUnknown(); fNonMulStageFound= true; + if (kWillNot_ReadInput == readsInput) { + fWillUseInputColor = false; + } } bool isOpaque() const { @@ -129,11 +153,13 @@ public: friend class GrDrawState; friend class GrOptDrawState; friend class GrPaint; + friend class GrProcessor; GrColor fColor; uint32_t fValidFlags; bool fIsSingleComponent; bool fNonMulStageFound; + bool fWillUseInputColor; }; /** @@ -145,6 +171,7 @@ public: * meaning if the corresponding bit in validFlags is set. */ void computeInvariantOutput(InvariantOutput* inout) const { + inout->fWillUseInputColor = true; this->onComputeInvariantOutput(inout); #ifdef SK_DEBUG inout->validate(); diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp index 8a8c622082..616a361b81 100644 --- a/src/core/SkXfermode.cpp +++ b/src/core/SkXfermode.cpp @@ -1213,7 +1213,7 @@ private: } virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE { - inout->setToUnknown(); + inout->setToUnknown(InvariantOutput::kWill_ReadInput); } SkXfermode::Mode fMode; diff --git a/src/effects/SkArithmeticMode.cpp b/src/effects/SkArithmeticMode.cpp index d337603329..06a602ac01 100644 --- a/src/effects/SkArithmeticMode.cpp +++ b/src/effects/SkArithmeticMode.cpp @@ -346,7 +346,7 @@ const GrBackendFragmentProcessorFactory& GrArithmeticEffect::getFactory() const void GrArithmeticEffect::onComputeInvariantOutput(InvariantOutput* inout) const { // TODO: optimize this - inout->setToUnknown(); + inout->setToUnknown(InvariantOutput::kWill_ReadInput); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/effects/SkColorCubeFilter.cpp b/src/effects/SkColorCubeFilter.cpp index 2908d08b94..325d7de780 100644 --- a/src/effects/SkColorCubeFilter.cpp +++ b/src/effects/SkColorCubeFilter.cpp @@ -264,7 +264,7 @@ const GrBackendFragmentProcessorFactory& GrColorCubeEffect::getFactory() const { } void GrColorCubeEffect::onComputeInvariantOutput(InvariantOutput* inout) const { - inout->setToUnknown(); + inout->setToUnknown(InvariantOutput::kWill_ReadInput); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp index d96aadfed7..4c6474a9c3 100644 --- a/src/effects/SkColorFilters.cpp +++ b/src/effects/SkColorFilters.cpp @@ -274,17 +274,7 @@ public: private: ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode) : fMode(mode), - fColor(color) { - - SkXfermode::Coeff dstCoeff; - SkXfermode::Coeff srcCoeff; - SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff)); - // These could be calculated from the blend equation with template trickery.. - if (SkXfermode::kZero_Coeff == dstCoeff && - !GrBlendCoeffRefsDst(sk_blend_to_grblend(srcCoeff))) { - this->setWillNotUseInputColor(); - } - } + fColor(color) {} virtual bool onIsEqual(const GrFragmentProcessor& other) const SK_OVERRIDE { const ModeColorFilterEffect& s = other.cast<ModeColorFilterEffect>(); @@ -392,7 +382,17 @@ void ModeColorFilterEffect::onComputeInvariantOutput(InvariantOutput* inout) con MaskedColorExpr(filterColor, kRGBA_GrColorComponentFlags), MaskedColorExpr(inputColor, inout->validFlags())); - inout->setToOther(result.getValidComponents(), result.getColor()); + // Check if we will use the input color + SkXfermode::Coeff dstCoeff; + SkXfermode::Coeff srcCoeff; + SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff)); + InvariantOutput::ReadInput readInput = InvariantOutput::kWill_ReadInput; + // These could be calculated from the blend equation with template trickery.. + if (SkXfermode::kZero_Coeff == dstCoeff && + !GrBlendCoeffRefsDst(sk_blend_to_grblend(srcCoeff))) { + readInput = InvariantOutput::kWillNot_ReadInput; + } + inout->setToOther(result.getValidComponents(), result.getColor(), readInput); } GR_DEFINE_FRAGMENT_PROCESSOR_TEST(ModeColorFilterEffect); diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp index 4aee11aa5b..844a37638c 100644 --- a/src/effects/SkColorMatrixFilter.cpp +++ b/src/effects/SkColorMatrixFilter.cpp @@ -453,7 +453,7 @@ private: // then we can't know the final result. if (0 != fMatrix.fMat[kAlphaRowStartIdx + i]) { if (!(inout->validFlags() & kRGBAFlags[i])) { - inout->setToUnknown(); + inout->setToUnknown(InvariantOutput::kWill_ReadInput); return; } else { uint32_t component = (inout->color() >> kShifts[i]) & 0xFF; @@ -467,7 +467,8 @@ private: // underflow this may deviate from the actual result. Maybe the effect should pin its // result if the matrix could over/underflow for any component? inout->setToOther(kA_GrColorComponentFlag, - static_cast<uint8_t>(SkScalarPin(outputA, 0, 255)) << GrColor_SHIFT_A); + static_cast<uint8_t>(SkScalarPin(outputA, 0, 255)) << GrColor_SHIFT_A, + InvariantOutput::kWill_ReadInput); } SkColorMatrix fMatrix; diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp index 2e6a2c872e..bc35752c0e 100644 --- a/src/effects/SkDisplacementMapEffect.cpp +++ b/src/effects/SkDisplacementMapEffect.cpp @@ -473,7 +473,6 @@ GrDisplacementMapEffect::GrDisplacementMapEffect( this->addTextureAccess(&fDisplacementAccess); this->addCoordTransform(&fColorTransform); this->addTextureAccess(&fColorAccess); - this->setWillNotUseInputColor(); } GrDisplacementMapEffect::~GrDisplacementMapEffect() { @@ -498,7 +497,7 @@ void GrDisplacementMapEffect::onComputeInvariantOutput(InvariantOutput* inout) c // and no displacement offset push any texture coordinates out of bounds OR if the constant // alpha is 0. Since this isn't trivial to compute at this point, let's assume the output is // not of constant color when a displacement effect is applied. - inout->setToUnknown(); + inout->setToUnknown(InvariantOutput::kWillNot_ReadInput); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/effects/SkLumaColorFilter.cpp b/src/effects/SkLumaColorFilter.cpp index d06a2132f4..7750f04d72 100644 --- a/src/effects/SkLumaColorFilter.cpp +++ b/src/effects/SkLumaColorFilter.cpp @@ -115,7 +115,8 @@ private: virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE { // The output is always black. The alpha value for the color passed in is arbitrary. - inout->setToOther(kRGB_GrColorComponentFlags, GrColorPackRGBA(0, 0, 0, 0)); + inout->setToOther(kRGB_GrColorComponentFlags, GrColorPackRGBA(0, 0, 0, 0), + InvariantOutput::kWill_ReadInput); } }; diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp index 3dd161cb78..de1780622f 100644 --- a/src/effects/SkPerlinNoiseShader.cpp +++ b/src/effects/SkPerlinNoiseShader.cpp @@ -587,7 +587,7 @@ private: } void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE { - inout->setToUnknown(); + inout->setToUnknown(InvariantOutput::kWillNot_ReadInput); } GrPerlinNoiseEffect(SkPerlinNoiseShader::Type type, @@ -606,7 +606,6 @@ private: this->addTextureAccess(&fNoiseAccess); fCoordTransform.reset(kLocal_GrCoordSet, matrix); this->addCoordTransform(&fCoordTransform); - this->setWillNotUseInputColor(); } GR_DECLARE_FRAGMENT_PROCESSOR_TEST; diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp index 1da6c554d5..fb177b2b40 100644 --- a/src/effects/SkTableColorFilter.cpp +++ b/src/effects/SkTableColorFilter.cpp @@ -417,7 +417,7 @@ void ColorTableEffect::onComputeInvariantOutput(InvariantOutput* inout) const { if (fFlags & SkTable_ColorFilter::kA_Flag) { invalidateFlags |= kA_GrColorComponentFlag; } - inout->invalidateComponents(invalidateFlags); + inout->invalidateComponents(invalidateFlags, InvariantOutput::kWill_ReadInput); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/GrOptDrawState.cpp b/src/gpu/GrOptDrawState.cpp index 7c8710f7d6..40e0c6ce1f 100644 --- a/src/gpu/GrOptDrawState.cpp +++ b/src/gpu/GrOptDrawState.cpp @@ -244,16 +244,19 @@ void GrOptDrawState::computeEffectiveColorStages(const GrDrawState& ds, int* fir for (int i = 0; i < ds.numColorStages(); ++i) { const GrFragmentProcessor* fp = ds.getColorStage(i).getProcessor(); - if (!fp->willUseInputColor()) { + fp->computeInvariantOutput(&inout); + if (!inout.fWillUseInputColor) { *firstColorStageIdx = i; fInputColorIsUsed = false; } - fp->computeInvariantOutput(&inout); if (kRGBA_GrColorComponentFlags == inout.fValidFlags) { *firstColorStageIdx = i + 1; fColor = inout.fColor; fInputColorIsUsed = true; *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.fNonMulStageFound = false; } } } @@ -267,9 +270,11 @@ void GrOptDrawState::computeEffectiveCoverageStages(const GrDrawState& ds, // Don't do any optimizations on coverage stages. It should not be the case where we do not use // input coverage in an effect #ifdef OptCoverageStages + GrProcessor::InvariantOutput inout; for (int i = 0; i < ds.numCoverageStages(); ++i) { - const GrProcessor* processor = ds.getCoverageStage(i).getProcessor(); - if (!processor->willUseInputColor()) { + const GrFragmentProcessor* fp = ds.getCoverageStage(i).getProcessor(); + fp->computeInvariantOutput(&inout); + if (!inout.fWillUseInputColor) { *firstCoverageStageIdx = i; fInputCoverageIsUsed = false; } diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp index bf65cb0fb9..04401c8adf 100644 --- a/src/gpu/GrProcessor.cpp +++ b/src/gpu/GrProcessor.cpp @@ -133,6 +133,9 @@ void GrProcessor::InvariantOutput::validate() const { } SkASSERT(this->validPreMulColor()); + + // If we claim that we are not using the input color we must not be modulating the input. + SkASSERT(fNonMulStageFound || fWillUseInputColor); } bool GrProcessor::InvariantOutput::colorComponentsAllEqual() const { diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp index bafa64d13a..c84b540850 100644 --- a/src/gpu/effects/GrConvexPolyEffect.cpp +++ b/src/gpu/effects/GrConvexPolyEffect.cpp @@ -46,7 +46,7 @@ private: virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE { if (fRect.isEmpty()) { // An empty rect will have no coverage anywhere. - inout->setToTransparentBlack(); + inout->mulByKnownAlpha(0); } else { inout->mulByUnknownAlpha(); } diff --git a/src/gpu/effects/GrDitherEffect.cpp b/src/gpu/effects/GrDitherEffect.cpp index 068a23eae7..643829b848 100644 --- a/src/gpu/effects/GrDitherEffect.cpp +++ b/src/gpu/effects/GrDitherEffect.cpp @@ -50,7 +50,7 @@ private: }; void DitherEffect::onComputeInvariantOutput(InvariantOutput* inout) const { - inout->setToUnknown(); + inout->setToUnknown(InvariantOutput::kWill_ReadInput); } ////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/effects/GrYUVtoRGBEffect.cpp b/src/gpu/effects/GrYUVtoRGBEffect.cpp index f280d1bdd4..b18bd7fa01 100644 --- a/src/gpu/effects/GrYUVtoRGBEffect.cpp +++ b/src/gpu/effects/GrYUVtoRGBEffect.cpp @@ -99,7 +99,6 @@ private: this->addTextureAccess(&fYAccess); this->addTextureAccess(&fUAccess); this->addTextureAccess(&fVAccess); - this->setWillNotUseInputColor(); } virtual bool onIsEqual(const GrFragmentProcessor& sBase) const { @@ -112,7 +111,8 @@ private: virtual void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE { // YUV is opaque - inout->setToOther(kA_GrColorComponentFlag, 0xFF << GrColor_SHIFT_A); + inout->setToOther(kA_GrColorComponentFlag, 0xFF << GrColor_SHIFT_A, + InvariantOutput::kWill_ReadInput); } GrCoordTransform fCoordTransform; diff --git a/tests/GpuColorFilterTest.cpp b/tests/GpuColorFilterTest.cpp index c8f563069f..82f5f31b3e 100644 --- a/tests/GpuColorFilterTest.cpp +++ b/tests/GpuColorFilterTest.cpp @@ -100,7 +100,8 @@ static void test_getConstantColorComponents(skiatest::Reporter* reporter, GrCont SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(test.filterColor, test.filterMode)); SkAutoTUnref<GrFragmentProcessor> effect(cf->asFragmentProcessor(grContext)); GrProcessor::InvariantOutput inout; - inout.setToOther(test.inputComponents, test.inputColor); + inout.setToOther(test.inputComponents, test.inputColor, + GrProcessor::InvariantOutput::kWill_ReadInput); effect->computeInvariantOutput(&inout); REPORTER_ASSERT(reporter, filterColor(inout.color(), inout.validFlags()) == test.outputColor); |