Add in shader blending for CoverageSetOp XP

BUG=skia:

Review URL: https://codereview.chromium.org/1488213002
This commit is contained in:
egdaniel 2015-12-01 13:54:06 -08:00 committed by Commit bot
parent 7bceedc550
commit f34b293681
8 changed files with 191 additions and 14 deletions

View File

@ -213,8 +213,10 @@ private:
void emitBlendCodeForDstRead(GrGLSLXPBuilder* pb,
GrGLSLXPFragmentBuilder* fragBuilder,
const char* srcColor,
const char* srcCoverage,
const char* dstColor,
const char* outColor,
const char* outColorSecondary,
const GrXferProcessor& proc) override {
fKUni = pb->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, kDefault_GrSLPrecision,
@ -222,6 +224,19 @@ private:
const char* kUni = pb->getUniformCStr(fKUni);
add_arithmetic_code(fragBuilder, srcColor, dstColor, outColor, kUni, fEnforcePMColor);
// Apply coverage.
if (proc.dstReadUsesMixedSamples()) {
if (srcCoverage) {
fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage);
fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCoverage);
} else {
fragBuilder->codeAppendf("%s = vec4(1.0);", outColorSecondary);
}
} else if (srcCoverage) {
fragBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;",
outColor, srcCoverage, outColor, srcCoverage, dstColor);
}
}
void onSetData(const GrGLSLProgramDataManager& pdman,

View File

@ -11,6 +11,7 @@
#include "GrColor.h"
#include "GrProcessor.h"
#include "GrProcOptInfo.h"
#include "glsl/GrGLSLBlend.h"
#include "glsl/GrGLSLProgramBuilder.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLXferProcessor.h"
@ -146,6 +147,96 @@ void CoverageSetOpXP::onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) cons
///////////////////////////////////////////////////////////////////////////////
class ShaderCSOXferProcessor : public GrXferProcessor {
public:
ShaderCSOXferProcessor(const DstTexture* dstTexture,
bool hasMixedSamples,
SkXfermode::Mode xfermode,
SkRegion::Op regionOp,
bool invertCoverage)
: INHERITED(dstTexture, true, hasMixedSamples)
, fRegionOp(regionOp)
, fInvertCoverage(invertCoverage) {
this->initClassID<ShaderCSOXferProcessor>();
}
const char* name() const override { return "Coverage Set Op Shader"; }
GrGLSLXferProcessor* createGLSLInstance() const override;
SkRegion::Op regionOp() const { return fRegionOp; }
bool invertCoverage() const { return fInvertCoverage; }
private:
GrXferProcessor::OptFlags onGetOptimizations(const GrPipelineOptimizations&, bool, GrColor*,
const GrCaps&) const override {
// We never look at the color input
return GrXferProcessor::kIgnoreColor_OptFlag;
}
void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override;
bool onIsEqual(const GrXferProcessor& xpBase) const override {
const ShaderCSOXferProcessor& xp = xpBase.cast<ShaderCSOXferProcessor>();
return (fRegionOp == xp.fRegionOp &&
fInvertCoverage == xp.fInvertCoverage);
}
SkRegion::Op fRegionOp;
bool fInvertCoverage;
typedef GrXferProcessor INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
class GLShaderCSOXferProcessor : public GrGLSLXferProcessor {
public:
static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
const ShaderCSOXferProcessor& xp = processor.cast<ShaderCSOXferProcessor>();
b->add32(xp.regionOp());
uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
b->add32(key);
}
private:
void emitBlendCodeForDstRead(GrGLSLXPBuilder* pb,
GrGLSLXPFragmentBuilder* fragBuilder,
const char* srcColor,
const char* srcCoverage,
const char* dstColor,
const char* outColor,
const char* outColorSecondary,
const GrXferProcessor& proc) override {
const ShaderCSOXferProcessor& xp = proc.cast<ShaderCSOXferProcessor>();
if (xp.invertCoverage()) {
fragBuilder->codeAppendf("%s = 1.0 - %s;", outColor, srcCoverage);
} else {
fragBuilder->codeAppendf("%s = %s;", outColor, srcCoverage);
}
GrGLSLBlend::AppendRegionOp(fragBuilder, outColor, dstColor, outColor, xp.regionOp());
}
void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
typedef GrGLSLXferProcessor INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
void ShaderCSOXferProcessor::onGetGLSLProcessorKey(const GrGLSLCaps&,
GrProcessorKeyBuilder* b) const {
GLShaderCSOXferProcessor::GenKey(*this, b);
}
GrGLSLXferProcessor* ShaderCSOXferProcessor::createGLSLInstance() const {
return new GLShaderCSOXferProcessor;
}
///////////////////////////////////////////////////////////////////////////////
//
GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
: fRegionOp(regionOp)
, fInvertCoverage(invertCoverage) {

View File

@ -161,13 +161,28 @@ private:
void emitBlendCodeForDstRead(GrGLSLXPBuilder* pb,
GrGLSLXPFragmentBuilder* fragBuilder,
const char* srcColor,
const char* srcCoverage,
const char* dstColor,
const char* outColor,
const char* outColorSecondary,
const GrXferProcessor& proc) override {
const CustomXP& xp = proc.cast<CustomXP>();
SkASSERT(!xp.hasHWBlendEquation());
GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.mode());
// Apply coverage.
if (xp.dstReadUsesMixedSamples()) {
if (srcCoverage) {
fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage);
fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCoverage);
} else {
fragBuilder->codeAppendf("%s = vec4(1.0);", outColorSecondary);
}
} else if (srcCoverage) {
fragBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;",
outColor, srcCoverage, outColor, srcCoverage, dstColor);
}
}
void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}

View File

@ -548,12 +548,27 @@ private:
void emitBlendCodeForDstRead(GrGLSLXPBuilder* pb,
GrGLSLXPFragmentBuilder* fragBuilder,
const char* srcColor,
const char* srcCoverage,
const char* dstColor,
const char* outColor,
const char* outColorSecondary,
const GrXferProcessor& proc) override {
const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>();
GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.getXfermode());
// Apply coverage.
if (xp.dstReadUsesMixedSamples()) {
if (srcCoverage) {
fragBuilder->codeAppendf("%s *= %s;", outColor, srcCoverage);
fragBuilder->codeAppendf("%s = %s;", outColorSecondary, srcCoverage);
} else {
fragBuilder->codeAppendf("%s = vec4(1.0);", outColorSecondary);
}
} else if (srcCoverage) {
fragBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;",
outColor, srcCoverage, outColor, srcCoverage, dstColor);
}
}
void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}

View File

@ -433,3 +433,50 @@ void GrGLSLBlend::AppendMode(GrGLSLFragmentBuilder* fsBuilder, const char* srcCo
emit_advanced_xfermode_code(fsBuilder, srcColor, dstColor, outColor, mode);
}
}
void GrGLSLBlend::AppendRegionOp(GrGLSLFragmentBuilder* fsBuilder, const char* srcColor,
const char* dstColor, const char* outColor,
SkRegion::Op regionOp) {
SkXfermode::Coeff srcCoeff, dstCoeff;
switch (regionOp) {
case SkRegion::kReplace_Op:
srcCoeff = SkXfermode::kOne_Coeff;
dstCoeff = SkXfermode::kZero_Coeff;
break;
case SkRegion::kIntersect_Op:
srcCoeff = SkXfermode::kDC_Coeff;
dstCoeff = SkXfermode::kZero_Coeff;
break;
case SkRegion::kUnion_Op:
srcCoeff = SkXfermode::kOne_Coeff;
dstCoeff = SkXfermode::kISC_Coeff;
break;
case SkRegion::kXOR_Op:
srcCoeff = SkXfermode::kIDC_Coeff;
dstCoeff = SkXfermode::kISC_Coeff;
break;
case SkRegion::kDifference_Op:
srcCoeff = SkXfermode::kZero_Coeff;
dstCoeff = SkXfermode::kISC_Coeff;
break;
case SkRegion::kReverseDifference_Op:
srcCoeff = SkXfermode::kIDC_Coeff;
dstCoeff = SkXfermode::kZero_Coeff;
break;
default:
SkFAIL("Unsupported Op");
// We should never get here but to make compiler happy
srcCoeff = SkXfermode::kZero_Coeff;
dstCoeff = SkXfermode::kZero_Coeff;
}
fsBuilder->codeAppendf("%s = ", outColor);
// append src blend
bool didAppend = append_porterduff_term(fsBuilder, srcCoeff, srcColor, srcColor, dstColor,
false);
// append dst blend
if(!append_porterduff_term(fsBuilder, dstCoeff, dstColor, srcColor, dstColor, didAppend)) {
fsBuilder->codeAppend("vec4(0, 0, 0, 0)");
}
fsBuilder->codeAppend(";");
}

View File

@ -8,6 +8,7 @@
#ifndef GrGLBlend_DEFINED
#define GrGLBlend_DEFINED
#include "SkRegion.h"
#include "SkXfermode.h"
class GrGLSLFragmentBuilder;
@ -19,6 +20,9 @@ namespace GrGLSLBlend {
*/
void AppendMode(GrGLSLFragmentBuilder* fsBuilder, const char* srcColor,
const char* dstColor, const char* outColor, SkXfermode::Mode mode);
void AppendRegionOp(GrGLSLFragmentBuilder* fsBuilder, const char* srcColor,
const char* dstColor, const char* outColor, SkRegion::Op regionOp);
};
#endif

View File

@ -63,23 +63,11 @@ void GrGLSLXferProcessor::emitCode(const EmitArgs& args) {
this->emitBlendCodeForDstRead(args.fPB,
fragBuilder,
args.fInputColor,
args.fInputCoverage,
dstColor,
args.fOutputPrimary,
args.fOutputSecondary,
args.fXP);
// Apply coverage.
if (args.fXP.dstReadUsesMixedSamples()) {
if (args.fInputCoverage) {
fragBuilder->codeAppendf("%s *= %s;", args.fOutputPrimary, args.fInputCoverage);
fragBuilder->codeAppendf("%s = %s;", args.fOutputSecondary, args.fInputCoverage);
} else {
fragBuilder->codeAppendf("%s = vec4(1.0);", args.fOutputSecondary);
}
} else if (args.fInputCoverage) {
fragBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;",
args.fOutputPrimary, args.fInputCoverage,
args.fOutputPrimary, args.fInputCoverage, dstColor);
}
}
void GrGLSLXferProcessor::setData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) {

View File

@ -85,8 +85,10 @@ private:
virtual void emitBlendCodeForDstRead(GrGLSLXPBuilder*,
GrGLSLXPFragmentBuilder*,
const char* srcColor,
const char* srcCoverage,
const char* dstColor,
const char* outColor,
const char* outColorSecondary,
const GrXferProcessor&) {
SkFAIL("emitBlendCodeForDstRead not implemented.");
}