| Index: src/gpu/gl/GrGLProgram.cpp
|
| ===================================================================
|
| --- src/gpu/gl/GrGLProgram.cpp (revision 8735)
|
| +++ src/gpu/gl/GrGLProgram.cpp (working copy)
|
| @@ -13,6 +13,7 @@
|
| #include "GrGLEffect.h"
|
| #include "GrGpuGL.h"
|
| #include "GrGLShaderVar.h"
|
| +#include "GrGLSL.h"
|
| #include "SkTrace.h"
|
| #include "SkXfermode.h"
|
|
|
| @@ -112,7 +113,6 @@
|
| }
|
|
|
| namespace {
|
| -
|
| // given two blend coeffecients determine whether the src
|
| // and/or dst computation can be omitted.
|
| inline void need_blend_inputs(SkXfermode::Coeff srcCoeff,
|
| @@ -211,12 +211,12 @@
|
| blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor);
|
|
|
| SkString sum;
|
| - GrGLSLAdd4f(&sum, colorStr.c_str(), constStr.c_str());
|
| + GrGLSLAddf<4>(&sum, colorStr.c_str(), constStr.c_str());
|
| builder->fsCodeAppendf("\t%s = %s;\n", outputVar, sum.c_str());
|
| }
|
| }
|
|
|
| -void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) {
|
| +GrSLConstantVec GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) {
|
| switch (fDesc.fColorInput) {
|
| case GrGLProgramDesc::kAttribute_ColorInput: {
|
| builder->addAttribute(kVec4f_GrSLType, COL_ATTR_NAME);
|
| @@ -224,54 +224,57 @@
|
| builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
|
| builder->vsCodeAppendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
|
| *inColor = fsName;
|
| - } break;
|
| + return kNone_GrSLConstantVec;
|
| + }
|
| case GrGLProgramDesc::kUniform_ColorInput: {
|
| const char* name;
|
| fUniformHandles.fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
| kVec4f_GrSLType, "Color", &name);
|
| *inColor = name;
|
| - break;
|
| + return kNone_GrSLConstantVec;
|
| }
|
| case GrGLProgramDesc::kTransBlack_ColorInput:
|
| - GrAssert(!"needComputedColor should be false.");
|
| - break;
|
| + inColor->reset();
|
| + return kZeros_GrSLConstantVec;
|
| case GrGLProgramDesc::kSolidWhite_ColorInput:
|
| - break;
|
| + inColor->reset();
|
| + return kOnes_GrSLConstantVec;
|
| default:
|
| GrCrash("Unknown color type.");
|
| - break;
|
| + return kNone_GrSLConstantVec;
|
| }
|
| }
|
|
|
| -void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOutCoverage) {
|
| - const char* covUniName;
|
| - fUniformHandles.fCoverageUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
| - kVec4f_GrSLType, "Coverage", &covUniName);
|
| - if (inOutCoverage->size()) {
|
| - builder->fsCodeAppendf("\tvec4 uniCoverage = %s * %s;\n",
|
| - covUniName, inOutCoverage->c_str());
|
| - *inOutCoverage = "uniCoverage";
|
| - } else {
|
| - *inOutCoverage = covUniName;
|
| +GrSLConstantVec GrGLProgram::genInputCoverage(GrGLShaderBuilder* builder, SkString* inCoverage) {
|
| + switch (fDesc.fCoverageInput) {
|
| + case GrGLProgramDesc::kAttribute_ColorInput: {
|
| + builder->addAttribute(kVec4f_GrSLType, COV_ATTR_NAME);
|
| + const char *vsName, *fsName;
|
| + builder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
|
| + builder->vsCodeAppendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
|
| + *inCoverage = fsName;
|
| + return kNone_GrSLConstantVec;
|
| + }
|
| + case GrGLProgramDesc::kUniform_ColorInput: {
|
| + const char* name;
|
| + fUniformHandles.fCoverageUni =
|
| + builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
| + kVec4f_GrSLType, "Coverage", &name);
|
| + *inCoverage = name;
|
| + return kNone_GrSLConstantVec;
|
| + }
|
| + case GrGLProgramDesc::kTransBlack_ColorInput:
|
| + inCoverage->reset();
|
| + return kZeros_GrSLConstantVec;
|
| + case GrGLProgramDesc::kSolidWhite_ColorInput:
|
| + inCoverage->reset();
|
| + return kOnes_GrSLConstantVec;
|
| + default:
|
| + GrCrash("Unknown color type.");
|
| + return kNone_GrSLConstantVec;
|
| }
|
| }
|
|
|
| -namespace {
|
| -void gen_attribute_coverage(GrGLShaderBuilder* builder,
|
| - SkString* inOutCoverage) {
|
| - builder->addAttribute(kVec4f_GrSLType, COV_ATTR_NAME);
|
| - const char *vsName, *fsName;
|
| - builder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
|
| - builder->vsCodeAppendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
|
| - if (inOutCoverage->size()) {
|
| - builder->fsCodeAppendf("\tvec4 attrCoverage = %s * %s;\n", fsName, inOutCoverage->c_str());
|
| - *inOutCoverage = "attrCoverage";
|
| - } else {
|
| - *inOutCoverage = fsName;
|
| - }
|
| -}
|
| -}
|
| -
|
| void GrGLProgram::genGeometryShader(GrGLShaderBuilder* builder) const {
|
| #if GR_GL_EXPERIMENTAL_GS
|
| // TODO: The builder should add all this glue code.
|
| @@ -420,45 +423,6 @@
|
|
|
| GrGLShaderBuilder builder(fContext.info(), fUniformManager, fDesc);
|
|
|
| - SkXfermode::Coeff colorCoeff, uniformCoeff;
|
| - // The rest of transfer mode color filters have not been implemented
|
| - if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) {
|
| - GR_DEBUGCODE(bool success =)
|
| - SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>
|
| - (fDesc.fColorFilterXfermode),
|
| - &uniformCoeff, &colorCoeff);
|
| - GR_DEBUGASSERT(success);
|
| - } else {
|
| - colorCoeff = SkXfermode::kOne_Coeff;
|
| - uniformCoeff = SkXfermode::kZero_Coeff;
|
| - }
|
| -
|
| - // no need to do the color filter if coverage is 0. The output color is scaled by the coverage.
|
| - // All the dual source outputs are scaled by the coverage as well.
|
| - if (GrGLProgramDesc::kTransBlack_ColorInput == fDesc.fCoverageInput) {
|
| - colorCoeff = SkXfermode::kZero_Coeff;
|
| - uniformCoeff = SkXfermode::kZero_Coeff;
|
| - }
|
| -
|
| - // If we know the final color is going to be all zeros then we can
|
| - // simplify the color filter coefficients. needComputedColor will then
|
| - // come out false below.
|
| - if (GrGLProgramDesc::kTransBlack_ColorInput == fDesc.fColorInput) {
|
| - colorCoeff = SkXfermode::kZero_Coeff;
|
| - if (SkXfermode::kDC_Coeff == uniformCoeff ||
|
| - SkXfermode::kDA_Coeff == uniformCoeff) {
|
| - uniformCoeff = SkXfermode::kZero_Coeff;
|
| - } else if (SkXfermode::kIDC_Coeff == uniformCoeff ||
|
| - SkXfermode::kIDA_Coeff == uniformCoeff) {
|
| - uniformCoeff = SkXfermode::kOne_Coeff;
|
| - }
|
| - }
|
| -
|
| - bool needColorFilterUniform;
|
| - bool needComputedColor;
|
| - need_blend_inputs(uniformCoeff, colorCoeff,
|
| - &needColorFilterUniform, &needComputedColor);
|
| -
|
| // the dual source output has no canonical var name, have to
|
| // declare an output, which is incompatible with gl_FragColor/gl_FragData.
|
| bool dualSourceOutputWritten = false;
|
| @@ -482,11 +446,8 @@
|
|
|
| // incoming color to current stage being processed.
|
| SkString inColor;
|
| + GrSLConstantVec knownColorValue = this->genInputColor(&builder, &inColor);
|
|
|
| - if (needComputedColor) {
|
| - this->genInputColor(&builder, &inColor);
|
| - }
|
| -
|
| // we output point size in the GS if present
|
| if (fDesc.fEmitsPointSize
|
| #if GR_GL_EXPERIMENTAL_GS
|
| @@ -496,15 +457,29 @@
|
| builder.vsCodeAppend("\tgl_PointSize = 1.0;\n");
|
| }
|
|
|
| - ///////////////////////////////////////////////////////////////////////////
|
| - // compute the final color
|
| + // Get the coeffs for the Mode-based color filter, determine if color is needed.
|
| + SkXfermode::Coeff colorCoeff;
|
| + SkXfermode::Coeff filterColorCoeff;
|
| + SkAssertResult(
|
| + SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>(fDesc.fColorFilterXfermode),
|
| + &filterColorCoeff,
|
| + &colorCoeff));
|
| + bool needColor, needFilterColor;
|
| + need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
|
|
|
| - // if we have color stages string them together, feeding the output color
|
| - // of each to the next and generating code for each stage.
|
| - if (needComputedColor) {
|
| + if (needColor) {
|
| + ///////////////////////////////////////////////////////////////////////////
|
| + // compute the color
|
| + // if we have color stages string them together, feeding the output color
|
| + // of each to the next and generating code for each stage.
|
| SkString outColor;
|
| for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) {
|
| if (GrGLEffect::kNoEffectKey != fDesc.fEffectKeys[s]) {
|
| + if (kZeros_GrSLConstantVec == knownColorValue) {
|
| + // Effects have no way to communicate zeros, they treat an empty string as ones.
|
| + inColor = "initialColor";
|
| + builder.fsCodeAppendf("\tvec4 %s = %s;\n", inColor.c_str(), GrGLSLZerosVecf(4));
|
| + }
|
| // create var to hold stage result
|
| outColor = "color";
|
| outColor.appendS32(s);
|
| @@ -518,137 +493,132 @@
|
| &fUniformHandles.fEffectSamplerUnis[s]);
|
| builder.setNonStage();
|
| inColor = outColor;
|
| + knownColorValue = kNone_GrSLConstantVec;
|
| }
|
| }
|
| }
|
|
|
| - // if have all ones or zeros for the "dst" input to the color filter then we
|
| - // may be able to make additional optimizations.
|
| - if (needColorFilterUniform && needComputedColor && !inColor.size()) {
|
| - GrAssert(GrGLProgramDesc::kSolidWhite_ColorInput == fDesc.fColorInput);
|
| - bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff ||
|
| - SkXfermode::kIDA_Coeff == uniformCoeff;
|
| - if (uniformCoeffIsZero) {
|
| - uniformCoeff = SkXfermode::kZero_Coeff;
|
| - bool bogus;
|
| - need_blend_inputs(SkXfermode::kZero_Coeff, colorCoeff,
|
| - &needColorFilterUniform, &bogus);
|
| - }
|
| - }
|
| - const char* colorFilterColorUniName = NULL;
|
| - if (needColorFilterUniform) {
|
| - fUniformHandles.fColorFilterUni = builder.addUniform(
|
| - GrGLShaderBuilder::kFragment_ShaderType,
|
| - kVec4f_GrSLType, "FilterColor",
|
| - &colorFilterColorUniName);
|
| - }
|
| - bool wroteFragColorZero = false;
|
| - if (SkXfermode::kZero_Coeff == uniformCoeff &&
|
| - SkXfermode::kZero_Coeff == colorCoeff) {
|
| - builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), GrGLSLZerosVecf(4));
|
| - wroteFragColorZero = true;
|
| - } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) {
|
| + // Insert the color filter. This will soon be replaced by a color effect.
|
| + if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) {
|
| + const char* colorFilterColorUniName = NULL;
|
| + fUniformHandles.fColorFilterUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
|
| + kVec4f_GrSLType, "FilterColor",
|
| + &colorFilterColorUniName);
|
| +
|
| builder.fsCodeAppend("\tvec4 filteredColor;\n");
|
| - const char* color = adjustInColor(inColor);
|
| - add_color_filter(&builder, "filteredColor", uniformCoeff,
|
| + const char* color;
|
| + // add_color_filter requires a real input string.
|
| + if (knownColorValue == kOnes_GrSLConstantVec) {
|
| + color = GrGLSLOnesVecf(4);
|
| + } else if (knownColorValue == kZeros_GrSLConstantVec) {
|
| + color = GrGLSLZerosVecf(4);
|
| + } else {
|
| + color = inColor.c_str();
|
| + }
|
| + add_color_filter(&builder, "filteredColor", filterColorCoeff,
|
| colorCoeff, colorFilterColorUniName, color);
|
| inColor = "filteredColor";
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////
|
| - // compute the partial coverage (coverage stages and edge aa)
|
| + // compute the partial coverage
|
|
|
| + // incoming coverage to current stage being processed.
|
| SkString inCoverage;
|
| - bool coverageIsZero = GrGLProgramDesc::kTransBlack_ColorInput == fDesc.fCoverageInput;
|
| - // we don't need to compute coverage at all if we know the final shader
|
| - // output will be zero and we don't have a dual src blend output.
|
| - if (!wroteFragColorZero || GrGLProgramDesc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
|
| -
|
| - if (!coverageIsZero) {
|
| - switch (fDesc.fCoverageInput) {
|
| - case GrGLProgramDesc::kSolidWhite_ColorInput:
|
| - // empty string implies solid white
|
| - break;
|
| - case GrGLProgramDesc::kAttribute_ColorInput:
|
| - gen_attribute_coverage(&builder, &inCoverage);
|
| - break;
|
| - case GrGLProgramDesc::kUniform_ColorInput:
|
| - this->genUniformCoverage(&builder, &inCoverage);
|
| - break;
|
| - default:
|
| - GrCrash("Unexpected input coverage.");
|
| + GrSLConstantVec knownCoverageValue = this->genInputCoverage(&builder, &inCoverage);
|
| +
|
| + SkString outCoverage;
|
| + const int& startStage = fDesc.fFirstCoverageStage;
|
| + for (int s = startStage; s < GrDrawState::kNumStages; ++s) {
|
| + if (fDesc.fEffectKeys[s]) {
|
| + if (kZeros_GrSLConstantVec == knownCoverageValue) {
|
| + // Effects have no way to communicate zeros, they treat an empty string as ones.
|
| + inCoverage = "initialCoverage";
|
| + builder.fsCodeAppendf("\tvec4 %s = %s;\n", inCoverage.c_str(), GrGLSLZerosVecf(4));
|
| }
|
| + // create var to hold stage output
|
| + outCoverage = "coverage";
|
| + outCoverage.appendS32(s);
|
| + builder.fsCodeAppendf("\tvec4 %s;\n", outCoverage.c_str());
|
|
|
| - SkString outCoverage;
|
| - const int& startStage = fDesc.fFirstCoverageStage;
|
| - for (int s = startStage; s < GrDrawState::kNumStages; ++s) {
|
| - if (fDesc.fEffectKeys[s]) {
|
| - // create var to hold stage output
|
| - outCoverage = "coverage";
|
| - outCoverage.appendS32(s);
|
| - builder.fsCodeAppendf("\tvec4 %s;\n", outCoverage.c_str());
|
| + builder.setCurrentStage(s);
|
| + fEffects[s] = builder.createAndEmitGLEffect(
|
| + *stages[s],
|
| + fDesc.fEffectKeys[s],
|
| + inCoverage.size() ? inCoverage.c_str() : NULL,
|
| + outCoverage.c_str(),
|
| + &fUniformHandles.fEffectSamplerUnis[s]);
|
| + builder.setNonStage();
|
| + inCoverage = outCoverage;
|
| + knownCoverageValue = kNone_GrSLConstantVec;
|
| + }
|
| + }
|
|
|
| - builder.setCurrentStage(s);
|
| - fEffects[s] = builder.createAndEmitGLEffect(
|
| - *stages[s],
|
| - fDesc.fEffectKeys[s],
|
| - inCoverage.size() ? inCoverage.c_str() : NULL,
|
| - outCoverage.c_str(),
|
| - &fUniformHandles.fEffectSamplerUnis[s]);
|
| - builder.setNonStage();
|
| - inCoverage = outCoverage;
|
| - }
|
| - }
|
| -
|
| - // discard if coverage is zero
|
| - if (fDesc.fDiscardIfZeroCoverage && !outCoverage.isEmpty()) {
|
| - builder.fsCodeAppendf(
|
| - "\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n",
|
| - outCoverage.c_str());
|
| - }
|
| + // discard if coverage is zero
|
| + if (fDesc.fDiscardIfZeroCoverage && knownCoverageValue != kOnes_GrSLConstantVec) {
|
| + if (kZeros_GrSLConstantVec == knownCoverageValue) {
|
| + // This is unfortunate.
|
| + builder.fsCodeAppend("\tdiscard;\n");
|
| + } else {
|
| + builder.fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n",
|
| + inCoverage.c_str());
|
| }
|
| + }
|
|
|
| - if (GrGLProgramDesc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
|
| - builder.fFSOutputs.push_back().set(kVec4f_GrSLType,
|
| - GrGLShaderVar::kOut_TypeModifier,
|
| - dual_source_output_name());
|
| - bool outputIsZero = coverageIsZero;
|
| - SkString coeff;
|
| - if (!outputIsZero &&
|
| - GrGLProgramDesc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) {
|
| - if (!inColor.size()) {
|
| - outputIsZero = true;
|
| - } else {
|
| - if (GrGLProgramDesc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) {
|
| - coeff.printf("(1 - %s.a)", inColor.c_str());
|
| - } else {
|
| - coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str());
|
| - }
|
| - }
|
| - }
|
| - if (outputIsZero) {
|
| - builder.fsCodeAppendf("\t%s = %s;\n", dual_source_output_name(), GrGLSLZerosVecf(4));
|
| - } else {
|
| - SkString modulate;
|
| - GrGLSLModulate4f(&modulate, coeff.c_str(), inCoverage.c_str());
|
| - builder.fsCodeAppendf("\t%s = %s;\n", dual_source_output_name(), modulate.c_str());
|
| - }
|
| - dualSourceOutputWritten = true;
|
| + if (GrGLProgramDesc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
|
| + builder.fFSOutputs.push_back().set(kVec4f_GrSLType,
|
| + GrGLShaderVar::kOut_TypeModifier,
|
| + dual_source_output_name());
|
| + // default coeff to ones for kCoverage_DualSrcOutput
|
| + SkString coeff;
|
| + GrSLConstantVec knownCoeffValue = kOnes_GrSLConstantVec;
|
| + if (GrGLProgramDesc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) {
|
| + // Get (1-A) into coeff
|
| + SkString inColorAlpha;
|
| + GrGLSLGetComponent4f(&inColorAlpha,
|
| + inColor.c_str(),
|
| + kA_GrColorComponentFlag,
|
| + knownColorValue,
|
| + true);
|
| + knownCoeffValue = GrGLSLSubtractf<1>(&coeff,
|
| + NULL,
|
| + inColorAlpha.c_str(),
|
| + kOnes_GrSLConstantVec,
|
| + knownColorValue,
|
| + true);
|
| + } else if (GrGLProgramDesc::kCoverageISC_DualSrcOutput == fDesc.fDualSrcOutput) {
|
| + // Get (1-RGBA) into coeff
|
| + knownCoeffValue = GrGLSLSubtractf<4>(&coeff,
|
| + NULL,
|
| + inColor.c_str(),
|
| + kOnes_GrSLConstantVec,
|
| + knownColorValue,
|
| + true);
|
| }
|
| + // Get coeff * coverage into modulate and then write that to the dual source output.
|
| + SkString modulate;
|
| + GrGLSLModulatef<4>(&modulate,
|
| + coeff.c_str(),
|
| + inCoverage.c_str(),
|
| + knownCoeffValue,
|
| + knownCoverageValue,
|
| + false);
|
| + builder.fsCodeAppendf("\t%s = %s;\n", dual_source_output_name(), modulate.c_str());
|
| + dualSourceOutputWritten = true;
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////
|
| // combine color and coverage as frag color
|
|
|
| - if (!wroteFragColorZero) {
|
| - if (coverageIsZero) {
|
| - builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), GrGLSLZerosVecf(4));
|
| - } else {
|
| - SkString modulate;
|
| - GrGLSLModulate4f(&modulate, inColor.c_str(), inCoverage.c_str());
|
| - builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), modulate.c_str());
|
| - }
|
| - }
|
| + // Get color * coverage into modulate and write that to frag shader's output.
|
| + SkString modulate;
|
| + GrGLSLModulatef<4>(&modulate,
|
| + inColor.c_str(),
|
| + inCoverage.c_str(),
|
| + knownColorValue,
|
| + knownCoverageValue,
|
| + false);
|
| + builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), modulate.c_str());
|
|
|
| ///////////////////////////////////////////////////////////////////////////
|
| // insert GS
|
| @@ -698,7 +668,7 @@
|
| GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name()));
|
| }
|
| if (bindDualSrcOut) {
|
| - GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name()));
|
| + //GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name()));
|
| }
|
|
|
| // Bind the attrib locations to same values for all shaders
|
|
|