| 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..cddbbfb49e7f1665ba54b7e3c2069006db69f545
|
| --- /dev/null
|
| +++ b/src/gpu/effects/GrCoverageSetOpXP.cpp
|
| @@ -0,0 +1,235 @@
|
| +
|
| +/*
|
| + * 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&) {}
|
| +
|
| + ~GrGLCoverageSetOpXP() SK_OVERRIDE {}
|
| +
|
| + 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);
|
| + }
|
| + }
|
| +
|
| + void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {};
|
| +
|
| + 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;
|
| + }
|
| + 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 {
|
| + return GrCoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
|
| +}
|
| +
|
| +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,
|
| + 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);
|
| +}
|
| +
|
|
|