Chromium Code Reviews| Index: src/gpu/effects/GrPorterDuffXferProcessor.cpp |
| diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp |
| index 52ef75572d099c2bc6c31dd48f3375ecdd16078a..0b3ef0f042ecc55ba675131b5694af4be631a558 100644 |
| --- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp |
| +++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp |
| @@ -9,11 +9,12 @@ |
| #include "GrBlend.h" |
| #include "GrDrawState.h" |
| +#include "GrDrawTargetCaps.h" |
| #include "GrInvariantOutput.h" |
| #include "GrProcessor.h" |
| #include "GrTypes.h" |
| #include "GrXferProcessor.h" |
| -#include "gl/GrGLProcessor.h" |
| +#include "gl/GrGLXferProcessor.h" |
| #include "gl/builders/GrGLFragmentShaderBuilder.h" |
| #include "gl/builders/GrGLProgramBuilder.h" |
| @@ -42,21 +43,43 @@ public: |
| virtual ~GrGLPorterDuffXferProcessor() {} |
| - virtual void emitCode(GrGLFPBuilder* builder, |
| - const GrFragmentProcessor& fp, |
| - const char* outputColor, |
| - const char* inputColor, |
| - const TransformedCoordsArray& coords, |
| - const TextureSamplerArray& samplers) SK_OVERRIDE { |
| - GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); |
| - fsBuilder->codeAppendf("%s = %s;", outputColor, inputColor); |
| + virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { |
| + const GrPorterDuffXferProcessor& xp = args.fXP.cast<GrPorterDuffXferProcessor>(); |
| + GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
| + if (xp.hasSecondaryOutput()) { |
| + switch(xp.secondaryOutputType()) { |
| + case GrPorterDuffXferProcessor::kCoverage_SecondaryOutputType: |
| + fsBuilder->codeAppendf("%s = %s;", args.fOutputSecondary, args.fInputCoverage); |
| + break; |
| + case GrPorterDuffXferProcessor::kCoverageISA_SecondaryOutputType: |
| + fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", |
| + args.fOutputSecondary, args.fInputColor, |
| + args.fInputCoverage); |
| + break; |
| + case GrPorterDuffXferProcessor::kCoverageISC_SecondaryOutputType: |
| + fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", |
| + args.fOutputSecondary, args.fInputColor, |
| + args.fInputCoverage); |
| + break; |
| + default: |
| + SkFAIL("Unexpected Secondary Output"); |
| + } |
| + } |
| + |
| + fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor, |
| + args.fInputCoverage); |
| } |
| - virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE {}; |
| + virtual void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {}; |
| - static void GenKey(const GrProcessor&, const GrGLCaps& caps, GrProcessorKeyBuilder* b) {}; |
| + static void GenKey(const GrProcessor& processor, const GrGLCaps& caps, |
| + GrProcessorKeyBuilder* b) { |
| + const GrPorterDuffXferProcessor& xp = processor.cast<GrPorterDuffXferProcessor>(); |
| + b->add32(xp.secondaryOutputType()); |
| + }; |
| private: |
| + |
|
joshualitt
2014/12/08 19:46:40
I'm not saying you HAVE to delete this space, but
egdaniel
2014/12/09 21:10:46
Done.
|
| typedef GrGLXferProcessor INHERITED; |
| }; |
| @@ -64,7 +87,10 @@ private: |
| GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, |
| GrColor constant) |
| - : fSrcBlend(srcBlend), fDstBlend(dstBlend), fBlendConstant(constant) { |
| + : fSrcBlend(srcBlend) |
| + , fDstBlend(dstBlend) |
| + , fBlendConstant(constant) |
| + , fSecondaryOutputType(kNone_SecondaryOutputType) { |
| this->initClassID<GrPorterDuffXferProcessor>(); |
| } |
| @@ -76,7 +102,7 @@ void GrPorterDuffXferProcessor::getGLProcessorKey(const GrGLCaps& caps, |
| GrGLPorterDuffXferProcessor::GenKey(*this, caps, b); |
| } |
| -GrGLFragmentProcessor* GrPorterDuffXferProcessor::createGLInstance() const { |
| +GrGLXferProcessor* GrPorterDuffXferProcessor::createGLInstance() const { |
| return SkNEW_ARGS(GrGLPorterDuffXferProcessor, (*this)); |
| } |
| @@ -90,7 +116,56 @@ GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI, |
| bool isCoverageDrawing, |
| bool colorWriteDisabled, |
| bool doesStencilWrite, |
| - GrColor* color, uint8_t* coverage) { |
| + GrColor* color, uint8_t* coverage, |
| + const GrDrawTargetCaps& caps) { |
| + GrXferProcessor::OptFlags optFlags = this->internalGetOptimizations(colorPOI, |
| + coveragePOI, |
| + isCoverageDrawing, |
| + colorWriteDisabled, |
| + doesStencilWrite, |
| + color, |
| + coverage); |
| + |
| + this->calcOutputTypes(optFlags, caps, isCoverageDrawing, |
| + colorPOI.readsDst() || coveragePOI.readsDst()); |
|
joshualitt
2014/12/08 19:46:41
I thought only xps read dst?
bsalomon
2014/12/08 19:58:59
AFACT that has to wait until XPs are written for t
egdaniel
2014/12/09 21:10:46
Yes this is correct.
|
| + return optFlags; |
| +} |
| + |
| +void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags, |
| + const GrDrawTargetCaps& caps, |
| + bool isCoverageDrawing, bool readsDst) { |
| + // If we do have coverage determine whether it matters. Dual source blending is expensive so |
| + // we don't do it if we are doing coverage drawing. If we aren't then We always do dual source |
| + // blending if we have any effective coverage stages OR the geometry processor doesn't emits |
| + // solid coverage. |
| + // TODO move the gp logic into the GP base class |
|
joshualitt
2014/12/08 19:46:41
remove todo
egdaniel
2014/12/09 21:10:46
Done.
|
| + |
| + if (!(optFlags & kSetCoverageDrawing_OptFlag) && !isCoverageDrawing) { |
| + if (caps.dualSourceBlendingSupport()) { |
| + if (kZero_GrBlendCoeff == fDstBlend) { |
| + // write the coverage value to second color |
| + fSecondaryOutputType = kCoverage_SecondaryOutputType; |
| + fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; |
| + } else if (kSA_GrBlendCoeff == fDstBlend) { |
| + // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. |
| + fSecondaryOutputType = kCoverageISA_SecondaryOutputType; |
| + fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; |
| + } else if (kSC_GrBlendCoeff == fDstBlend) { |
| + // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered. |
| + fSecondaryOutputType = kCoverageISC_SecondaryOutputType; |
| + fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; |
| + } |
| + } |
| + } |
| +} |
| + |
| +GrXferProcessor::OptFlags |
| +GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI, |
| + const GrProcOptInfo& coveragePOI, |
| + bool isCoverageDrawing, |
| + bool colorWriteDisabled, |
| + bool doesStencilWrite, |
| + GrColor* color, uint8_t* coverage) { |
| if (colorWriteDisabled) { |
| fSrcBlend = kZero_GrBlendCoeff; |
| fDstBlend = kOne_GrBlendCoeff; |
| @@ -192,6 +267,11 @@ GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI, |
| return GrXferProcessor::kNone_Opt; |
| } |
| + |
| +bool GrPorterDuffXferProcessor::hasSecondaryOutput() const { |
| + return kNone_SecondaryOutputType != fSecondaryOutputType; |
| +} |
| + |
| /////////////////////////////////////////////////////////////////////////////// |
| GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst) |
| @@ -450,4 +530,22 @@ bool GrPorterDuffXPFactory::getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI |
| return opaque; |
| } |
| +GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); |
| + |
| +GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, |
| + GrContext*, |
| + const GrDrawTargetCaps&, |
| + GrTexture*[]) { |
| + GrBlendCoeff src; |
| + do { |
| + src = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPublicGrBlendCoeff)); |
| + } while (GrBlendCoeffRefsSrc(src)); |
| + |
| + GrBlendCoeff dst; |
| + do { |
| + dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPublicGrBlendCoeff)); |
| + } while (GrBlendCoeffRefsDst(dst)); |
| + |
| + return GrPorterDuffXPFactory::Create(src, dst); |
| +} |