Move helper functions out of header file, write new genProgram helpers.

Review: codereview.appspot.com/5304045/



git-svn-id: http://skia.googlecode.com/svn/trunk@2532 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
tomhudson@google.com 2011-10-25 19:51:09 +00:00
parent c32c999455
commit 2a2e3ef5b8
2 changed files with 244 additions and 259 deletions

View File

@ -16,6 +16,13 @@
namespace {
enum {
/// Used to mark a StageUniLocation field that should be bound
/// to a uniform during getUniformLocationsAndInitCache().
kUseUniform = 2000
};
const char* GrPrecision(const GrGLInterface* gl) {
if (gl->supportsES()) {
return "mediump";
@ -541,6 +548,53 @@ bool decl_and_get_fs_color_output(GrGLProgram::GLSLVersion v,
}
}
void genInputColor(GrGLProgram::ProgramDesc::ColorType colorType,
GrGLProgram::CachedData* programData,
ShaderCodeSegments* segments,
GrStringBuilder* inColor) {
switch (colorType) {
case GrGLProgram::ProgramDesc::kAttribute_ColorType: {
segments->fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type,
COL_ATTR_NAME);
const char *vsName, *fsName;
append_varying(GrGLShaderVar::kVec4f_Type, "Color", segments, &vsName, &fsName);
segments->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
*inColor = fsName;
} break;
case GrGLProgram::ProgramDesc::kUniform_ColorType:
segments->fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
COL_UNI_NAME);
programData->fUniLocations.fColorUni = kUseUniform;
*inColor = COL_UNI_NAME;
break;
case GrGLProgram::ProgramDesc::kTransBlack_ColorType:
GrAssert(!"needComputedColor should be false.");
break;
case GrGLProgram::ProgramDesc::kSolidWhite_ColorType:
break;
default:
GrCrash("Unknown color type.");
break;
}
}
void genPerVertexCoverage(ShaderCodeSegments* segments,
GrStringBuilder* inCoverage) {
segments->fVSAttrs.push_back().set(GrGLShaderVar::kFloat_Type,
COV_ATTR_NAME);
const char *vsName, *fsName;
append_varying(GrGLShaderVar::kFloat_Type, "Coverage",
segments, &vsName, &fsName);
segments->fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
if (inCoverage->size()) {
segments->fFSCode.appendf("\tfloat edgeAndAttrCov = %s * %s;\n",
fsName, inCoverage->c_str());
*inCoverage = "edgeAndAttrCov";
} else {
*inCoverage = fsName;
}
}
}
void GrGLProgram::genGeometryShader(const GrGLInterface* gl,
@ -644,30 +698,8 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
GrStringBuilder inColor;
if (needComputedColor) {
switch (fProgramDesc.fColorType) {
case ProgramDesc::kAttribute_ColorType: {
segments.fVSAttrs.push_back().set(GrGLShaderVar::kVec4f_Type,
COL_ATTR_NAME);
const char *vsName, *fsName;
append_varying(GrGLShaderVar::kVec4f_Type, "Color", &segments, &vsName, &fsName);
segments.fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
inColor = fsName;
} break;
case ProgramDesc::kUniform_ColorType:
segments.fFSUnis.push_back().set(GrGLShaderVar::kVec4f_Type,
COL_UNI_NAME);
programData->fUniLocations.fColorUni = kUseUniform;
inColor = COL_UNI_NAME;
break;
case ProgramDesc::kTransBlack_ColorType:
GrAssert(!"needComputedColor should be false.");
break;
case ProgramDesc::kSolidWhite_ColorType:
break;
default:
GrCrash("Unknown color type.");
break;
}
genInputColor((ProgramDesc::ColorType) fProgramDesc.fColorType,
programData, &segments, &inColor);
}
// we output point size in the GS if present
@ -714,7 +746,7 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
inCoords = texCoordAttrs[tcIdx].c_str();
}
genStageCode(gl,
this->genStageCode(gl,
s,
fProgramDesc.fStages[s],
inColor.size() ? inColor.c_str() : NULL,
@ -785,19 +817,7 @@ bool GrGLProgram::genProgram(const GrGLInterface* gl,
// include explicit per-vertex coverage if we have it
if (GrDrawTarget::kCoverage_VertexLayoutBit & layout) {
segments.fVSAttrs.push_back().set(GrGLShaderVar::kFloat_Type,
COV_ATTR_NAME);
const char *vsName, *fsName;
append_varying(GrGLShaderVar::kFloat_Type, "Coverage",
&segments, &vsName, &fsName);
segments.fVSCode.appendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
if (inCoverage.size()) {
segments.fFSCode.appendf("\tfloat edgeAndAttrCov = %s * %s;\n",
fsName, inCoverage.c_str());
inCoverage = "edgeAndAttrCov";
} else {
inCoverage = fsName;
}
genPerVertexCoverage(&segments, &inCoverage);
}
GrStringBuilder outCoverage;
@ -1287,7 +1307,52 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLInterface* gl,
// Stage code generation
//============================================================================
static bool genRadial2GradientCoordMapping(int stageNum,
namespace {
bool isRadialMapping(GrGLProgram::StageDesc::CoordMapping mapping) {
return
(GrGLProgram::StageDesc::kRadial2Gradient_CoordMapping == mapping ||
GrGLProgram::StageDesc::kRadial2GradientDegenerate_CoordMapping == mapping);
}
const char* genRadialVS(int stageNum,
ShaderCodeSegments* segments,
GrGLProgram::StageUniLocations* locations,
const char** radial2VaryingVSName,
const char** radial2VaryingFSName,
const char* varyingVSName,
int varyingDims, int coordDims) {
GrGLShaderVar* radial2FSParams = &segments->fFSUnis.push_back();
radial2FSParams->setType(GrGLShaderVar::kFloat_Type);
radial2FSParams->setArrayCount(6);
radial2_param_name(stageNum, radial2FSParams->accessName());
segments->fVSUnis.push_back(*radial2FSParams).setEmitPrecision(true);
locations->fRadial2Uni = kUseUniform;
// for radial grads without perspective we can pass the linear
// part of the quadratic as a varying.
if (varyingDims == coordDims) {
GrAssert(2 == coordDims);
append_varying(GrGLShaderVar::kFloat_Type,
"Radial2BCoeff",
stageNum,
segments,
radial2VaryingVSName,
radial2VaryingFSName);
// r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3])
const char* r2ParamName = radial2FSParams->getName().c_str();
segments->fVSCode.appendf("\t%s = 2.0 *(%s[2] * %s.x - %s[3]);\n",
*radial2VaryingVSName, r2ParamName,
varyingVSName, r2ParamName);
}
return radial2FSParams->getName().c_str();
}
bool genRadial2GradientCoordMapping(int stageNum,
ShaderCodeSegments* segments,
const char* radial2VaryingFSName,
const char* radial2ParamsName,
@ -1342,7 +1407,7 @@ static bool genRadial2GradientCoordMapping(int stageNum,
return true;
}
static bool genRadial2GradientDegenerateCoordMapping(int stageNum,
bool genRadial2GradientDegenerateCoordMapping(int stageNum,
ShaderCodeSegments* segments,
const char* radial2VaryingFSName,
const char* radial2ParamsName,
@ -1381,6 +1446,106 @@ static bool genRadial2GradientDegenerateCoordMapping(int stageNum,
return true;
}
void gen2x2FS(int stageNum,
ShaderCodeSegments* segments,
GrGLProgram::StageUniLocations* locations,
GrStringBuilder* sampleCoords,
const char* samplerName,
const char* texelSizeName,
const char* smear,
const char* fsOutColor,
GrStringBuilder& texFunc,
GrStringBuilder& modulate,
bool complexCoord,
int coordDims) {
locations->fNormalizedTexelSizeUni = kUseUniform;
if (complexCoord) {
// assign the coord to a var rather than compute 4x.
GrStringBuilder coordVar("tCoord");
coordVar.appendS32(stageNum);
segments->fFSCode.appendf("\t%s %s = %s;\n",
float_vector_type_str(coordDims),
coordVar.c_str(), sampleCoords->c_str());
*sampleCoords = coordVar;
}
GrAssert(2 == coordDims);
GrStringBuilder accumVar("accum");
accumVar.appendS32(stageNum);
segments->fFSCode.appendf("\tvec4 %s = %s(%s, %s + vec2(-%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(-%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
segments->fFSCode.appendf("\t%s = .25 * %s%s;\n", fsOutColor, accumVar.c_str(), modulate.c_str());
}
void genConvolutionVS(int stageNum,
const GrGLProgram::ProgramDesc::StageDesc& desc,
ShaderCodeSegments* segments,
GrGLProgram::StageUniLocations* locations,
const char** kernelName,
const char** imageIncrementName,
const char* varyingVSName) {
GrGLShaderVar* kernel = &segments->fFSUnis.push_back();
kernel->setType(GrGLShaderVar::kFloat_Type);
kernel->setArrayCount(desc.fKernelWidth);
GrGLShaderVar* imgInc = &segments->fFSUnis.push_back();
imgInc->setType(GrGLShaderVar::kVec2f_Type);
convolve_param_names(stageNum,
kernel->accessName(),
imgInc->accessName());
*kernelName = kernel->getName().c_str();
*imageIncrementName = imgInc->getName().c_str();
// need image increment in both VS and FS
segments->fVSUnis.push_back(*imgInc).setEmitPrecision(true);
locations->fKernelUni = kUseUniform;
locations->fImageIncrementUni = kUseUniform;
float scale = (desc.fKernelWidth - 1) * 0.5f;
segments->fVSCode.appendf("\t%s -= vec2(%g, %g) * %s;\n",
varyingVSName, scale, scale,
*imageIncrementName);
}
void genConvolutionFS(int stageNum,
const GrGLProgram::ProgramDesc::StageDesc& desc,
ShaderCodeSegments* segments,
const char* samplerName,
const char* kernelName,
const char* smear,
const char* imageIncrementName,
const char* fsOutColor,
GrStringBuilder& sampleCoords,
GrStringBuilder& texFunc,
GrStringBuilder& modulate) {
GrStringBuilder sumVar("sum");
sumVar.appendS32(stageNum);
GrStringBuilder coordVar("coord");
coordVar.appendS32(stageNum);
segments->fFSCode.appendf("\tvec4 %s = vec4(0, 0, 0, 0);\n",
sumVar.c_str());
segments->fFSCode.appendf("\tvec2 %s = %s;\n",
coordVar.c_str(),
sampleCoords.c_str());
segments->fFSCode.appendf("\tfor (int i = 0; i < %d; i++) {\n",
desc.fKernelWidth);
segments->fFSCode.appendf("\t\t%s += %s(%s, %s)%s * %s[i];\n",
sumVar.c_str(), texFunc.c_str(),
samplerName, coordVar.c_str(), smear,
kernelName);
segments->fFSCode.appendf("\t\t%s += %s;\n",
coordVar.c_str(),
imageIncrementName);
segments->fFSCode.appendf("\t}\n");
segments->fFSCode.appendf("\t%s = %s%s;\n", fsOutColor,
sumVar.c_str(), modulate.c_str());
}
}
void GrGLProgram::genStageCode(const GrGLInterface* gl,
int stageNum,
const GrGLProgram::StageDesc& desc,
@ -1458,9 +1623,8 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
const char *radial2VaryingVSName = NULL;
const char *radial2VaryingFSName = NULL;
if (StageDesc::kRadial2Gradient_CoordMapping == desc.fCoordMapping ||
StageDesc::kRadial2GradientDegenerate_CoordMapping == desc.fCoordMapping) {
radial2ParamsName = this->genRadialVS(stageNum, segments,
if (isRadialMapping((StageDesc::CoordMapping) desc.fCoordMapping)) {
radial2ParamsName = genRadialVS(stageNum, segments,
locations,
&radial2VaryingVSName,
&radial2VaryingFSName,
@ -1471,7 +1635,7 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
const char* kernelName = NULL;
const char* imageIncrementName = NULL;
if (ProgramDesc::StageDesc::kConvolution_FetchMode == desc.fFetchMode) {
this->genConvolutionVS(stageNum, desc, segments, locations,
genConvolutionVS(stageNum, desc, segments, locations,
&kernelName, &imageIncrementName, varyingVSName);
}
@ -1565,12 +1729,12 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
switch (desc.fFetchMode) {
case StageDesc::k2x2_FetchMode:
this->gen2x2FS(stageNum, segments, locations, &sampleCoords,
gen2x2FS(stageNum, segments, locations, &sampleCoords,
samplerName, texelSizeName, smear, fsOutColor,
texFunc, modulate, complexCoord, coordDims);
break;
case ProgramDesc::StageDesc::kConvolution_FetchMode:
this->genConvolutionFS(stageNum, desc, segments,
genConvolutionFS(stageNum, desc, segments,
samplerName, kernelName, smear, imageIncrementName, fsOutColor,
sampleCoords, texFunc, modulate);
break;
@ -1582,139 +1746,4 @@ void GrGLProgram::genStageCode(const GrGLInterface* gl,
}
}
const char* GrGLProgram::genRadialVS(int stageNum,
ShaderCodeSegments* segments,
StageUniLocations* locations,
const char** radial2VaryingVSName,
const char** radial2VaryingFSName,
const char* varyingVSName,
int varyingDims, int coordDims) const {
GrGLShaderVar* radial2FSParams = &segments->fFSUnis.push_back();
radial2FSParams->setType(GrGLShaderVar::kFloat_Type);
radial2FSParams->setArrayCount(6);
radial2_param_name(stageNum, radial2FSParams->accessName());
segments->fVSUnis.push_back(*radial2FSParams).setEmitPrecision(true);
locations->fRadial2Uni = kUseUniform;
// for radial grads without perspective we can pass the linear
// part of the quadratic as a varying.
if (varyingDims == coordDims) {
GrAssert(2 == coordDims);
append_varying(GrGLShaderVar::kFloat_Type,
"Radial2BCoeff",
stageNum,
segments,
radial2VaryingVSName,
radial2VaryingFSName);
// r2Var = 2 * (r2Parm[2] * varCoord.x - r2Param[3])
const char* r2ParamName = radial2FSParams->getName().c_str();
segments->fVSCode.appendf("\t%s = 2.0 *(%s[2] * %s.x - %s[3]);\n",
*radial2VaryingVSName, r2ParamName,
varyingVSName, r2ParamName);
}
return radial2FSParams->getName().c_str();
}
void GrGLProgram::gen2x2FS(int stageNum,
ShaderCodeSegments* segments,
StageUniLocations* locations,
GrStringBuilder* sampleCoords,
const char* samplerName,
const char* texelSizeName,
const char* smear,
const char* fsOutColor,
GrStringBuilder& texFunc,
GrStringBuilder& modulate,
bool complexCoord,
int coordDims) const {
locations->fNormalizedTexelSizeUni = kUseUniform;
if (complexCoord) {
// assign the coord to a var rather than compute 4x.
GrStringBuilder coordVar("tCoord");
coordVar.appendS32(stageNum);
segments->fFSCode.appendf("\t%s %s = %s;\n",
float_vector_type_str(coordDims),
coordVar.c_str(), sampleCoords->c_str());
*sampleCoords = coordVar;
}
GrAssert(2 == coordDims);
GrStringBuilder accumVar("accum");
accumVar.appendS32(stageNum);
segments->fFSCode.appendf("\tvec4 %s = %s(%s, %s + vec2(-%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,-%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(-%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
segments->fFSCode.appendf("\t%s += %s(%s, %s + vec2(+%s.x,+%s.y))%s;\n", accumVar.c_str(), texFunc.c_str(), samplerName, sampleCoords->c_str(), texelSizeName, texelSizeName, smear);
segments->fFSCode.appendf("\t%s = .25 * %s%s;\n", fsOutColor, accumVar.c_str(), modulate.c_str());
}
void GrGLProgram::genConvolutionVS(int stageNum,
const ProgramDesc::StageDesc& desc,
ShaderCodeSegments* segments,
StageUniLocations* locations,
const char** kernelName,
const char** imageIncrementName,
const char* varyingVSName) const {
GrGLShaderVar* kernel = &segments->fFSUnis.push_back();
kernel->setType(GrGLShaderVar::kFloat_Type);
kernel->setArrayCount(desc.fKernelWidth);
GrGLShaderVar* imgInc = &segments->fFSUnis.push_back();
imgInc->setType(GrGLShaderVar::kVec2f_Type);
convolve_param_names(stageNum,
kernel->accessName(),
imgInc->accessName());
*kernelName = kernel->getName().c_str();
*imageIncrementName = imgInc->getName().c_str();
// need image increment in both VS and FS
segments->fVSUnis.push_back(*imgInc).setEmitPrecision(true);
locations->fKernelUni = kUseUniform;
locations->fImageIncrementUni = kUseUniform;
float scale = (desc.fKernelWidth - 1) * 0.5f;
segments->fVSCode.appendf("\t%s -= vec2(%g, %g) * %s;\n",
varyingVSName, scale, scale,
*imageIncrementName);
}
void GrGLProgram::genConvolutionFS(int stageNum,
const ProgramDesc::StageDesc& desc,
ShaderCodeSegments* segments,
const char* samplerName,
const char* kernelName,
const char* smear,
const char* imageIncrementName,
const char* fsOutColor,
GrStringBuilder& sampleCoords,
GrStringBuilder& texFunc,
GrStringBuilder& modulate) const {
GrStringBuilder sumVar("sum");
sumVar.appendS32(stageNum);
GrStringBuilder coordVar("coord");
coordVar.appendS32(stageNum);
segments->fFSCode.appendf("\tvec4 %s = vec4(0, 0, 0, 0);\n",
sumVar.c_str());
segments->fFSCode.appendf("\tvec2 %s = %s;\n",
coordVar.c_str(),
sampleCoords.c_str());
segments->fFSCode.appendf("\tfor (int i = 0; i < %d; i++) {\n",
desc.fKernelWidth);
segments->fFSCode.appendf("\t\t%s += %s(%s, %s)%s * %s[i];\n",
sumVar.c_str(), texFunc.c_str(),
samplerName, coordVar.c_str(), smear,
kernelName);
segments->fFSCode.appendf("\t\t%s += %s;\n",
coordVar.c_str(),
imageIncrementName);
segments->fFSCode.appendf("\t}\n");
segments->fFSCode.appendf("\t%s = %s%s;\n", fsOutColor,
sumVar.c_str(), modulate.c_str());
}

View File

@ -89,7 +89,7 @@ public:
return 7 + GrDrawTarget::kMaxTexCoords + 3 * stage;
}
private:
public:
// Parameters that affect code generation
// These structs should be kept compact; they are the input to an
@ -199,11 +199,13 @@ private:
} fProgramDesc;
GR_STATIC_ASSERT(!(sizeof(ProgramDesc) % 4));
const ProgramDesc& getDesc() { return fProgramDesc; }
// for code readability
typedef ProgramDesc::StageDesc StageDesc;
private:
const ProgramDesc& getDesc() { return fProgramDesc; }
public:
enum {
kUnusedUniform = -1,
@ -300,12 +302,8 @@ public:
}
private:
enum {
kUseUniform = 2000
};
// should set all fields in locations var to kUseUniform if the
// corresponding uniform is required for the program.
// Determines which uniforms will need to be bound.
void genStageCode(const GrGLInterface* gl,
int stageNum,
const ProgramDesc::StageDesc& desc,
@ -347,52 +345,10 @@ private:
bool bindDualSrcOut,
CachedData* programData) const;
// Gets locations for all uniforms set to kUseUniform and initializes cache
// to invalid values.
// Binds uniforms; initializes cache to invalid values.
void getUniformLocationsAndInitCache(const GrGLInterface* gl,
CachedData* programData) const;
const char* genRadialVS(int stageNum, ShaderCodeSegments* segments,
StageUniLocations* locations,
const char** radial2VaryingVSName,
const char** radial2VaryingFSName,
const char* varyingVSName,
int varyingDims, int coordDims) const;
void gen2x2FS(int stageNum,
ShaderCodeSegments* segments,
StageUniLocations* locations,
GrStringBuilder* sampleCoords,
const char* samplerName,
const char* texelSizeName,
const char* smear,
const char* fsOutColor,
GrStringBuilder& texFunc,
GrStringBuilder& modulate,
bool complexCoord,
int coordDims) const;
void genConvolutionVS(int stageNum,
const ProgramDesc::StageDesc& desc,
ShaderCodeSegments* segments,
StageUniLocations* locations,
const char** kernelName,
const char** imageIncrementName,
const char* varyingVSName) const;
void genConvolutionFS(int stageNum,
const ProgramDesc::StageDesc& desc,
ShaderCodeSegments* segments,
const char* samplerName,
const char* kernelName,
const char* smear,
const char* imageIncrementName,
const char* fsOutColor,
GrStringBuilder& sampleCoords,
GrStringBuilder& texFunc,
GrStringBuilder& modulate) const;
friend class GrGpuGLShaders;
};