Chromium Code Reviews| Index: src/gpu/effects/GrCoverageSetOpXP.cpp |
| diff --git a/src/gpu/effects/GrCoverageSetOpXP.cpp b/src/gpu/effects/GrCoverageSetOpXP.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..cbce70ae6937ed487410aa8ae3eaf7ea553bcb7b |
| --- /dev/null |
| +++ b/src/gpu/effects/GrCoverageSetOpXP.cpp |
| @@ -0,0 +1,242 @@ |
| + |
| +/* |
| + * 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 "effects/GrCoverageSetOpXP.h" |
| +#include "GrColor.h" |
| +#include "GrDrawTargetCaps.h" |
| +#include "GrInvariantOutput.h" |
| +#include "GrProcessor.h" |
| +#include "GrProcOptInfo.h" |
| +#include "gl/GrGLXferProcessor.h" |
| +#include "gl/builders/GrGLFragmentShaderBuilder.h" |
| +#include "gl/builders/GrGLProgramBuilder.h" |
| + |
| +class GrGLCoverageSetOpXP : public GrGLXferProcessor { |
| +public: |
| + GrGLCoverageSetOpXP(const GrProcessor&) {} |
| + |
| + virtual ~GrGLCoverageSetOpXP() {} |
| + |
| + virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { |
| + const GrCoverageSetOpXP& xp = args.fXP.cast<GrCoverageSetOpXP>(); |
| + GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
| + |
| + if (xp.invertCoverage()) { |
| + fsBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage); |
| + } else { |
| + fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage); |
| + } |
| + } |
| + |
| + virtual void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {}; |
| + |
|
bsalomon
2014/12/16 17:35:56
don't need virtuals on these overrides. Also can d
egdaniel
2014/12/17 21:12:37
Done.
|
| + static void GenKey(const GrProcessor& processor, const GrGLCaps& caps, |
| + GrProcessorKeyBuilder* b) { |
| + const GrCoverageSetOpXP& xp = processor.cast<GrCoverageSetOpXP>(); |
| + uint32_t key = xp.invertCoverage() ? 0x0 : 0x1; |
| + b->add32(key); |
| + }; |
| + |
| +private: |
| + typedef GrGLXferProcessor INHERITED; |
| +}; |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +GrCoverageSetOpXP::GrCoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage) |
| + : fRegionOp(regionOp) |
| + , fInvertCoverage(invertCoverage) { |
| + this->initClassID<GrCoverageSetOpXP>(); |
| +} |
| + |
| +GrCoverageSetOpXP::~GrCoverageSetOpXP() { |
| +} |
| + |
| +void GrCoverageSetOpXP::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const { |
| + GrGLCoverageSetOpXP::GenKey(*this, caps, b); |
| +} |
| + |
| +GrGLXferProcessor* GrCoverageSetOpXP::createGLInstance() const { |
| + return SkNEW_ARGS(GrGLCoverageSetOpXP, (*this)); |
| +} |
| + |
| +GrXferProcessor::OptFlags |
| +GrCoverageSetOpXP::getOptimizations(const GrProcOptInfo& colorPOI, |
| + const GrProcOptInfo& coveragePOI, |
| + bool colorWriteDisabled, |
| + bool doesStencilWrite, |
| + GrColor* color, |
| + const GrDrawTargetCaps& caps) { |
| + // We never look at the color input |
| + return GrXferProcessor::kIgnoreColor_OptFlag; |
| +} |
| + |
| +void GrCoverageSetOpXP::getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const { |
| + switch (fRegionOp) { |
| + case SkRegion::kReplace_Op: |
| + blendInfo->fSrcBlend = kOne_GrBlendCoeff; |
| + blendInfo->fDstBlend = kZero_GrBlendCoeff; |
| + break; |
| + case SkRegion::kIntersect_Op: |
| + blendInfo->fSrcBlend = kDC_GrBlendCoeff; |
| + blendInfo->fDstBlend = kZero_GrBlendCoeff; |
| + break; |
| + case SkRegion::kUnion_Op: |
| + blendInfo->fSrcBlend = kOne_GrBlendCoeff; |
| + blendInfo->fDstBlend = kISC_GrBlendCoeff; |
| + break; |
| + case SkRegion::kXOR_Op: |
| + blendInfo->fSrcBlend = kIDC_GrBlendCoeff; |
| + blendInfo->fDstBlend = kISC_GrBlendCoeff; |
| + break; |
| + case SkRegion::kDifference_Op: |
| + blendInfo->fSrcBlend = kZero_GrBlendCoeff; |
| + blendInfo->fDstBlend = kISC_GrBlendCoeff; |
| + break; |
| + case SkRegion::kReverseDifference_Op: |
| + blendInfo->fSrcBlend = kIDC_GrBlendCoeff; |
| + blendInfo->fDstBlend = kZero_GrBlendCoeff; |
| + break; |
| + default: |
|
bsalomon
2014/12/16 17:35:56
If you've exhausted all the possible values for k*
egdaniel
2014/12/17 21:12:37
Done.
|
| + SkASSERT(false); |
| + break; |
| + } |
| + blendInfo->fBlendConstant = 0; |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage) |
| + : fRegionOp(regionOp) |
| + , fInvertCoverage(invertCoverage) { |
| + this->initClassID<GrCoverageSetOpXPFactory>(); |
| +} |
| + |
| +GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invertCoverage) { |
| + switch (regionOp) { |
| + case SkRegion::kReplace_Op: { |
| + if (invertCoverage) { |
| + static GrCoverageSetOpXPFactory gReplaceCDXPFI(regionOp, invertCoverage); |
| + return SkRef(&gReplaceCDXPFI); |
| + } else { |
| + static GrCoverageSetOpXPFactory gReplaceCDXPF(regionOp, invertCoverage); |
| + return SkRef(&gReplaceCDXPF); |
| + } |
| + break; |
| + } |
| + case SkRegion::kIntersect_Op: { |
| + if (invertCoverage) { |
| + static GrCoverageSetOpXPFactory gIntersectCDXPFI(regionOp, invertCoverage); |
| + return SkRef(&gIntersectCDXPFI); |
| + } else { |
| + static GrCoverageSetOpXPFactory gIntersectCDXPF(regionOp, invertCoverage); |
| + return SkRef(&gIntersectCDXPF); |
| + } |
| + break; |
| + } |
| + case SkRegion::kUnion_Op: { |
| + if (invertCoverage) { |
| + static GrCoverageSetOpXPFactory gUnionCDXPFI(regionOp, invertCoverage); |
| + return SkRef(&gUnionCDXPFI); |
| + } else { |
| + static GrCoverageSetOpXPFactory gUnionCDXPF(regionOp, invertCoverage); |
| + return SkRef(&gUnionCDXPF); |
| + } |
| + break; |
| + } |
| + case SkRegion::kXOR_Op: { |
| + if (invertCoverage) { |
| + static GrCoverageSetOpXPFactory gXORCDXPFI(regionOp, invertCoverage); |
| + return SkRef(&gXORCDXPFI); |
| + } else { |
| + static GrCoverageSetOpXPFactory gXORCDXPF(regionOp, invertCoverage); |
| + return SkRef(&gXORCDXPF); |
| + } |
| + break; |
| + } |
| + case SkRegion::kDifference_Op: { |
| + if (invertCoverage) { |
| + static GrCoverageSetOpXPFactory gDifferenceCDXPFI(regionOp, invertCoverage); |
| + return SkRef(&gDifferenceCDXPFI); |
| + } else { |
| + static GrCoverageSetOpXPFactory gDifferenceCDXPF(regionOp, invertCoverage); |
| + return SkRef(&gDifferenceCDXPF); |
| + } |
| + break; |
| + } |
| + case SkRegion::kReverseDifference_Op: { |
| + if (invertCoverage) { |
| + static GrCoverageSetOpXPFactory gRevDiffCDXPFI(regionOp, invertCoverage); |
| + return SkRef(&gRevDiffCDXPFI); |
| + } else { |
| + static GrCoverageSetOpXPFactory gRevDiffCDXPF(regionOp, invertCoverage); |
| + return SkRef(&gRevDiffCDXPF); |
| + } |
| + break; |
| + } |
| + default: |
| + return NULL; |
| + } |
| +} |
| + |
| +GrXferProcessor* GrCoverageSetOpXPFactory::createXferProcessor(const GrProcOptInfo& /* colorPOI*/, |
| + const GrProcOptInfo& covPOI) const { |
| + if (!covPOI.isFourChannelOutput()) { |
| + return GrCoverageSetOpXP::Create(fRegionOp, fInvertCoverage); |
| + } else { |
| + return NULL; |
| + } |
| +} |
| + |
| +bool GrCoverageSetOpXPFactory::willBlendWithDst(const GrProcOptInfo& colorPOI, |
| + const GrProcOptInfo& coveragePOI, |
| + bool colorWriteDisabled) const { |
| + // TODO: once all SkXferEffects are XP's then we will never reads dst here since only XP's |
| + // will readDst and this XP doesn't read dst. |
| + if (coveragePOI.readsDst()) { |
| + return true; |
| + } |
| + |
| + // Besides Replace all other SkRegion ops will either have a src coeff that references dst or a |
| + // non zero dst coeff |
| + return SkRegion::kReplace_Op != fRegionOp; |
| +} |
| + |
| +bool GrCoverageSetOpXPFactory::getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI, |
|
bsalomon
2014/12/16 17:35:56
This is kind of confusing now that we have a cover
egdaniel
2014/12/17 21:12:37
As per our conversation, I will clean up these fun
|
| + const GrProcOptInfo& coveragePOI, |
| + GrColor* solidColor, |
| + uint32_t* solidColorKnownComponents) const { |
| + if (!coveragePOI.isSolidWhite()) { |
| + return false; |
| + } |
| + |
| + SkASSERT((NULL == solidColor) == (NULL == solidColorKnownComponents)); |
| + |
| + bool opaque = SkRegion::kReplace_Op == fRegionOp; |
| + if (solidColor) { |
| + if (opaque) { |
| + *solidColor = GrColor_WHITE; |
| + *solidColorKnownComponents = kRGBA_GrColorComponentFlags; |
| + } else { |
| + solidColorKnownComponents = 0; |
| + } |
| + } |
| + return opaque; |
| +} |
| + |
| +GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory); |
| + |
| +GrXPFactory* GrCoverageSetOpXPFactory::TestCreate(SkRandom* random, |
| + GrContext*, |
| + const GrDrawTargetCaps&, |
| + GrTexture*[]) { |
| + SkRegion::Op regionOp = SkRegion::Op(random->nextULessThan(SkRegion::kLastOp + 1)); |
| + bool invertCoverage = random->nextBool(); |
| + return GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage); |
| +} |
| + |