#include "SkTrace.h"
#include "SkXfermode.h"
+SK_DEFINE_INST_COUNT(GrGLProgram)
+
namespace {
enum {
#define PRINT_SHADERS 0
-typedef GrGLProgram::ProgramDesc::StageDesc StageDesc;
+typedef GrGLProgram::Desc::StageDesc StageDesc;
#define VIEW_MATRIX_NAME "uViewM"
}
GrGLProgram::~GrGLProgram() {
+ for (int i = 0; i < GrDrawState::kNumStages; ++i) {
+ delete fProgramStage[i];
+ }
}
void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
GrBlendCoeff* dstCoeff) const {
- switch (fProgramDesc.fDualSrcOutput) {
- case ProgramDesc::kNone_DualSrcOutput:
+ switch (fDesc.fDualSrcOutput) {
+ case Desc::kNone_DualSrcOutput:
break;
// the prog will write a coverage value to the secondary
// output and the dst is blended by one minus that value.
- case ProgramDesc::kCoverage_DualSrcOutput:
- case ProgramDesc::kCoverageISA_DualSrcOutput:
- case ProgramDesc::kCoverageISC_DualSrcOutput:
+ case Desc::kCoverage_DualSrcOutput:
+ case Desc::kCoverageISA_DualSrcOutput:
+ case Desc::kCoverageISC_DualSrcOutput:
*dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
break;
default:
}
void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl,
- GrVertexLayout layout,
- CachedData* programData,
SkString* coverageVar,
GrGLShaderBuilder* segments) const {
- if (layout & GrDrawTarget::kEdge_VertexLayoutBit) {
+ if (fDesc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit) {
const char *vsName, *fsName;
segments->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName);
segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME);
segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
- switch (fProgramDesc.fVertexEdgeType) {
+ switch (fDesc.fVertexEdgeType) {
case GrDrawState::kHairLine_EdgeType:
segments->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), %s.xyz));\n", fsName);
segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
}
}
-namespace {
-
-void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput,
- GrGLProgram::CachedData* programData,
- GrGLShaderBuilder* segments,
- SkString* inColor) {
- switch (colorInput) {
- case GrGLProgram::ProgramDesc::kAttribute_ColorInput: {
- segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
+void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) {
+ switch (fDesc.fColorInput) {
+ case GrGLProgram::Desc::kAttribute_ColorInput: {
+ builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier,
COL_ATTR_NAME);
const char *vsName, *fsName;
- segments->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
- segments->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
+ builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
+ builder->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
*inColor = fsName;
} break;
- case GrGLProgram::ProgramDesc::kUniform_ColorInput:
- segments->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+ case GrGLProgram::Desc::kUniform_ColorInput:
+ builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
kVec4f_GrSLType, COL_UNI_NAME);
- programData->fUniLocations.fColorUni = kUseUniform;
+ fUniLocations.fColorUni = kUseUniform;
*inColor = COL_UNI_NAME;
break;
- case GrGLProgram::ProgramDesc::kTransBlack_ColorInput:
+ case GrGLProgram::Desc::kTransBlack_ColorInput:
GrAssert(!"needComputedColor should be false.");
break;
- case GrGLProgram::ProgramDesc::kSolidWhite_ColorInput:
+ case GrGLProgram::Desc::kSolidWhite_ColorInput:
break;
default:
GrCrash("Unknown color type.");
}
}
-void genAttributeCoverage(GrGLShaderBuilder* segments,
- SkString* inOutCoverage) {
+void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOutCoverage) {
+ builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+ kVec4f_GrSLType, COV_UNI_NAME);
+ fUniLocations.fCoverageUni = kUseUniform;
+ if (inOutCoverage->size()) {
+ builder->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n",
+ COV_UNI_NAME, inOutCoverage->c_str());
+ *inOutCoverage = "uniCoverage";
+ } else {
+ *inOutCoverage = COV_UNI_NAME;
+ }
+}
+
+namespace {
+void gen_attribute_coverage(GrGLShaderBuilder* segments,
+ SkString* inOutCoverage) {
segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier,
COV_ATTR_NAME);
*inOutCoverage = fsName;
}
}
-
-void genUniformCoverage(GrGLShaderBuilder* segments,
- GrGLProgram::CachedData* programData,
- SkString* inOutCoverage) {
- segments->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
- kVec4f_GrSLType, COV_UNI_NAME);
- programData->fUniLocations.fCoverageUni = kUseUniform;
- if (inOutCoverage->size()) {
- segments->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n",
- COV_UNI_NAME, inOutCoverage->c_str());
- *inOutCoverage = "uniCoverage";
- } else {
- *inOutCoverage = COV_UNI_NAME;
- }
-}
-
}
void GrGLProgram::genGeometryShader(const GrGLContextInfo& gl,
GrGLShaderBuilder* segments) const {
#if GR_GL_EXPERIMENTAL_GS
- if (fProgramDesc.fExperimentalGS) {
+ if (fDesc.fExperimentalGS) {
GrAssert(gl.glslGeneration() >= k150_GrGLSLGeneration);
segments->fGSHeader.append("layout(triangles) in;\n"
"layout(triangle_strip, max_vertices = 6) out;\n");
segments->fGSCode.append("void main() {\n"
"\tfor (int i = 0; i < 3; ++i) {\n"
"\t\tgl_Position = gl_in[i].gl_Position;\n");
- if (this->fProgramDesc.fEmitsPointSize) {
+ if (fDesc.fEmitsPointSize) {
segments->fGSCode.append("\t\tgl_PointSize = 1.0;\n");
}
GrAssert(segments->fGSInputs.count() == segments->fGSOutputs.count());
if (inColor.size()) {
return inColor.c_str();
} else {
- if (ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput) {
+ if (Desc::kSolidWhite_ColorInput == fDesc.fColorInput) {
return all_ones_vec(4);
} else {
return all_zeros_vec(4);
}
}
-// If this destructor is in the header file, we must include GrGLProgramStage
-// instead of just forward-declaring it.
-GrGLProgram::CachedData::~CachedData() {
- for (int i = 0; i < GrDrawState::kNumStages; ++i) {
- delete fCustomStage[i];
- }
-}
-
namespace {
#define GL_CALL(X) GR_GL_CALL(gl.interface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gl.interface(), R, X)
return compile_shader(gl, type, 1, &str, &length);
}
-// compiles all the shaders from builder and stores the shader IDs in programData.
-bool compile_shaders(const GrGLContextInfo& gl,
- const GrGLShaderBuilder& builder,
- GrGLProgram::CachedData* programData) {
+}
+
+// compiles all the shaders from builder and stores the shader IDs
+bool GrGLProgram::compileShaders(const GrGLContextInfo& gl,
+ const GrGLShaderBuilder& builder) {
SkString shader;
GrPrintf(shader.c_str());
GrPrintf("\n");
#endif
- if (!(programData->fVShaderID = compile_shader(gl, GR_GL_VERTEX_SHADER, shader))) {
+ if (!(fVShaderID = compile_shader(gl, GR_GL_VERTEX_SHADER, shader))) {
return false;
}
GrPrintf(shader.c_str());
GrPrintf("\n");
#endif
- if (!(programData->fGShaderID = compile_shader(gl, GR_GL_GEOMETRY_SHADER, shader))) {
+ if (!(fGShaderID = compile_shader(gl, GR_GL_GEOMETRY_SHADER, shader))) {
return false;
}
} else {
- programData->fGShaderID = 0;
+ fGShaderID = 0;
}
builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader);
GrPrintf(shader.c_str());
GrPrintf("\n");
#endif
- if (!(programData->fFShaderID = compile_shader(gl, GR_GL_FRAGMENT_SHADER, shader))) {
+ if (!(fFShaderID = compile_shader(gl, GR_GL_FRAGMENT_SHADER, shader))) {
return false;
}
return true;
}
-}
bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
- GrCustomStage** customStages,
- GrGLProgram::CachedData* programData) const {
+ const Desc& desc,
+ GrCustomStage** customStages) {
+ fDesc = desc;
GrGLShaderBuilder builder(gl);
- const uint32_t& layout = fProgramDesc.fVertexLayout;
+ const uint32_t& layout = fDesc.fVertexLayout;
- programData->fUniLocations.reset();
+ fUniLocations.reset();
#if GR_GL_EXPERIMENTAL_GS
- builder.fUsesGS = fProgramDesc.fExperimentalGS;
+ builder.fUsesGS = fDesc.fExperimentalGS;
#endif
SkXfermode::Coeff colorCoeff, uniformCoeff;
- bool applyColorMatrix = SkToBool(fProgramDesc.fColorMatrixEnabled);
+ bool applyColorMatrix = SkToBool(fDesc.fColorMatrixEnabled);
// The rest of transfer mode color filters have not been implemented
- if (fProgramDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) {
+ if (fDesc.fColorFilterXfermode < SkXfermode::kCoeffModesCnt) {
GR_DEBUGCODE(bool success =)
SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>
- (fProgramDesc.fColorFilterXfermode),
+ (fDesc.fColorFilterXfermode),
&uniformCoeff, &colorCoeff);
GR_DEBUGASSERT(success);
} else {
// no need to do the color filter / matrix at all 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 (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fCoverageInput) {
+ if (Desc::kTransBlack_ColorInput == fDesc.fCoverageInput) {
colorCoeff = SkXfermode::kZero_Coeff;
uniformCoeff = SkXfermode::kZero_Coeff;
applyColorMatrix = false;
// If we know the final color is going to be all zeros then we can
// simplify the color filter coeffecients. needComputedColor will then
// come out false below.
- if (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fColorInput) {
+ if (Desc::kTransBlack_ColorInput == fDesc.fColorInput) {
colorCoeff = SkXfermode::kZero_Coeff;
if (SkXfermode::kDC_Coeff == uniformCoeff ||
SkXfermode::kDA_Coeff == uniformCoeff) {
builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType,
kMat33f_GrSLType, VIEW_MATRIX_NAME);
- programData->fUniLocations.fViewMatrixUni = kUseUniform;
+ fUniLocations.fViewMatrixUni = kUseUniform;
builder.fVSAttrs.push_back().set(kVec2f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier,
SkString inColor;
if (needComputedColor) {
- genInputColor((ProgramDesc::ColorInput) fProgramDesc.fColorInput,
- programData, &builder, &inColor);
+ this->genInputColor(&builder, &inColor);
}
// we output point size in the GS if present
- if (fProgramDesc.fEmitsPointSize && !builder.fUsesGS){
+ if (fDesc.fEmitsPointSize && !builder.fUsesGS){
builder.fVSCode.append("\tgl_PointSize = 1.0;\n");
}
// uses of programData, but it's safest to do so below when we're *sure*
// we need them.
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
- programData->fCustomStage[s] = NULL;
+ fProgramStage[s] = NULL;
}
///////////////////////////////////////////////////////////////////////////
// of each to the next and generating code for each stage.
if (needComputedColor) {
SkString outColor;
- for (int s = 0; s < fProgramDesc.fFirstCoverageStage; ++s) {
- if (fProgramDesc.fStages[s].isEnabled()) {
+ for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) {
+ if (fDesc.fStages[s].isEnabled()) {
// create var to hold stage result
outColor = "color";
outColor.appendS32(s);
}
if (NULL != customStages[s]) {
- const GrProgramStageFactory& factory =
- customStages[s]->getFactory();
- programData->fCustomStage[s] =
- factory.createGLInstance(*customStages[s]);
+ const GrProgramStageFactory& factory = customStages[s]->getFactory();
+ fProgramStage[s] = factory.createGLInstance(*customStages[s]);
}
this->genStageCode(gl,
s,
- fProgramDesc.fStages[s],
inColor.size() ? inColor.c_str() : NULL,
outColor.c_str(),
inCoords,
- &builder,
- &programData->fUniLocations.fStages[s],
- programData->fCustomStage[s]);
+ &builder);
inColor = outColor;
}
}
// 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(ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput);
+ GrAssert(Desc::kSolidWhite_ColorInput == fDesc.fColorInput);
bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff ||
SkXfermode::kIDA_Coeff == uniformCoeff;
if (uniformCoeffIsZero) {
if (needColorFilterUniform) {
builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
kVec4f_GrSLType, COL_FILTER_UNI_NAME);
- programData->fUniLocations.fColorFilterUni = kUseUniform;
+ fUniLocations.fColorFilterUni = kUseUniform;
}
bool wroteFragColorZero = false;
if (SkXfermode::kZero_Coeff == uniformCoeff &&
colorOutput.getName().c_str(),
all_zeros_vec(4));
wroteFragColorZero = true;
- } else if (SkXfermode::kDst_Mode != fProgramDesc.fColorFilterXfermode) {
+ } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) {
builder.fFSCode.append("\tvec4 filteredColor;\n");
const char* color = adjustInColor(inColor);
addColorFilter(&builder.fFSCode, "filteredColor", uniformCoeff,
kMat44f_GrSLType, COL_MATRIX_UNI_NAME);
builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
kVec4f_GrSLType, COL_MATRIX_VEC_UNI_NAME);
- programData->fUniLocations.fColorMatrixUni = kUseUniform;
- programData->fUniLocations.fColorMatrixVecUni = kUseUniform;
+ fUniLocations.fColorMatrixUni = kUseUniform;
+ fUniLocations.fColorMatrixVecUni = kUseUniform;
builder.fFSCode.append("\tvec4 matrixedColor;\n");
const char* color = adjustInColor(inColor);
addColorMatrix(&builder.fFSCode, "matrixedColor", color);
// compute the partial coverage (coverage stages and edge aa)
SkString inCoverage;
- bool coverageIsZero = ProgramDesc::kTransBlack_ColorInput ==
- fProgramDesc.fCoverageInput;
+ bool coverageIsZero = Desc::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 ||
- ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
+ if (!wroteFragColorZero || Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
if (!coverageIsZero) {
- this->genEdgeCoverage(gl, layout, programData, &inCoverage, &builder);
+ this->genEdgeCoverage(gl, &inCoverage, &builder);
- switch (fProgramDesc.fCoverageInput) {
- case ProgramDesc::kSolidWhite_ColorInput:
+ switch (fDesc.fCoverageInput) {
+ case Desc::kSolidWhite_ColorInput:
// empty string implies solid white
break;
- case ProgramDesc::kAttribute_ColorInput:
- genAttributeCoverage(&builder, &inCoverage);
+ case Desc::kAttribute_ColorInput:
+ gen_attribute_coverage(&builder, &inCoverage);
break;
- case ProgramDesc::kUniform_ColorInput:
- genUniformCoverage(&builder, programData, &inCoverage);
+ case Desc::kUniform_ColorInput:
+ this->genUniformCoverage(&builder, &inCoverage);
break;
default:
GrCrash("Unexpected input coverage.");
}
SkString outCoverage;
- const int& startStage = fProgramDesc.fFirstCoverageStage;
+ const int& startStage = fDesc.fFirstCoverageStage;
for (int s = startStage; s < GrDrawState::kNumStages; ++s) {
- if (fProgramDesc.fStages[s].isEnabled()) {
+ if (fDesc.fStages[s].isEnabled()) {
// create var to hold stage output
outCoverage = "coverage";
outCoverage.appendS32(s);
}
if (NULL != customStages[s]) {
- const GrProgramStageFactory& factory =
- customStages[s]->getFactory();
- programData->fCustomStage[s] =
- factory.createGLInstance(*customStages[s]);
+ const GrProgramStageFactory& factory = customStages[s]->getFactory();
+ fProgramStage[s] = factory.createGLInstance(*customStages[s]);
}
- this->genStageCode(gl, s,
- fProgramDesc.fStages[s],
- inCoverage.size() ? inCoverage.c_str() : NULL,
- outCoverage.c_str(),
- inCoords,
- &builder,
- &programData->fUniLocations.fStages[s],
- programData->fCustomStage[s]);
+ this->genStageCode(gl,
+ s,
+ inCoverage.size() ? inCoverage.c_str() : NULL,
+ outCoverage.c_str(),
+ inCoords,
+ &builder);
inCoverage = outCoverage;
}
}
}
- if (ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
+ if (Desc::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 &&
- ProgramDesc::kCoverage_DualSrcOutput !=
- fProgramDesc.fDualSrcOutput && !wroteFragColorZero) {
+ Desc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) {
if (!inColor.size()) {
outputIsZero = true;
} else {
- if (fProgramDesc.fDualSrcOutput ==
- ProgramDesc::kCoverageISA_DualSrcOutput) {
+ if (Desc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) {
coeff.printf("(1 - %s.a)", inColor.c_str());
} else {
coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str());
inCoverage.c_str(),
&builder.fFSCode);
}
- if (ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig ==
- fProgramDesc.fOutputConfig) {
+ if (Desc::kUnpremultiplied_RoundDown_OutputConfig == fDesc.fOutputConfig) {
builder.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
colorOutput.getName().c_str(),
colorOutput.getName().c_str(),
colorOutput.getName().c_str(),
colorOutput.getName().c_str(),
colorOutput.getName().c_str());
- } else if (ProgramDesc::kUnpremultiplied_RoundUp_OutputConfig ==
- fProgramDesc.fOutputConfig) {
+ } else if (Desc::kUnpremultiplied_RoundUp_OutputConfig == fDesc.fOutputConfig) {
builder.fFSCode.appendf("\t%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.rgb / %s.a * 255.0)/255.0, %s.a);\n",
colorOutput.getName().c_str(),
colorOutput.getName().c_str(),
///////////////////////////////////////////////////////////////////////////
// compile and setup attribs and unis
- if (!compile_shaders(gl, builder, programData)) {
+ if (!this->compileShaders(gl, builder)) {
return false;
}
- if (!this->bindOutputsAttribsAndLinkProgram(gl, texCoordAttrs,
+ if (!this->bindOutputsAttribsAndLinkProgram(gl,
+ texCoordAttrs,
isColorDeclared,
- dualSourceOutputWritten,
- programData)) {
+ dualSourceOutputWritten)) {
return false;
}
- this->getUniformLocationsAndInitCache(builder, gl, programData);
+ this->getUniformLocationsAndInitCache(gl, builder);
return true;
}
bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLContextInfo& gl,
- SkString texCoordAttrNames[],
- bool bindColorOut,
- bool bindDualSrcOut,
- CachedData* programData) const {
- GL_CALL_RET(programData->fProgramID, CreateProgram());
- if (!programData->fProgramID) {
+ SkString texCoordAttrNames[],
+ bool bindColorOut,
+ bool bindDualSrcOut) {
+ GL_CALL_RET(fProgramID, CreateProgram());
+ if (!fProgramID) {
return false;
}
- const GrGLint& progID = programData->fProgramID;
- GL_CALL(AttachShader(progID, programData->fVShaderID));
- if (programData->fGShaderID) {
- GL_CALL(AttachShader(progID, programData->fGShaderID));
+ GL_CALL(AttachShader(fProgramID, fVShaderID));
+ if (fGShaderID) {
+ GL_CALL(AttachShader(fProgramID, fGShaderID));
}
- GL_CALL(AttachShader(progID, programData->fFShaderID));
+ GL_CALL(AttachShader(fProgramID, fFShaderID));
if (bindColorOut) {
- GL_CALL(BindFragDataLocation(programData->fProgramID,
- 0, declared_color_output_name()));
+ GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name()));
}
if (bindDualSrcOut) {
- GL_CALL(BindFragDataLocationIndexed(programData->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
- GL_CALL(BindAttribLocation(progID, PositionAttributeIdx(), POS_ATTR_NAME));
+ GL_CALL(BindAttribLocation(fProgramID, PositionAttributeIdx(), POS_ATTR_NAME));
for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
if (texCoordAttrNames[t].size()) {
- GL_CALL(BindAttribLocation(progID,
+ GL_CALL(BindAttribLocation(fProgramID,
TexCoordAttributeIdx(t),
texCoordAttrNames[t].c_str()));
}
}
- GL_CALL(BindAttribLocation(progID, ColorAttributeIdx(), COL_ATTR_NAME));
- GL_CALL(BindAttribLocation(progID, CoverageAttributeIdx(), COV_ATTR_NAME));
- GL_CALL(BindAttribLocation(progID, EdgeAttributeIdx(), EDGE_ATTR_NAME));
+ GL_CALL(BindAttribLocation(fProgramID, ColorAttributeIdx(), COL_ATTR_NAME));
+ GL_CALL(BindAttribLocation(fProgramID, CoverageAttributeIdx(), COV_ATTR_NAME));
+ GL_CALL(BindAttribLocation(fProgramID, EdgeAttributeIdx(), EDGE_ATTR_NAME));
- GL_CALL(LinkProgram(progID));
+ GL_CALL(LinkProgram(fProgramID));
GrGLint linked = GR_GL_INIT_ZERO;
- GL_CALL(GetProgramiv(progID, GR_GL_LINK_STATUS, &linked));
+ GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked));
if (!linked) {
GrGLint infoLen = GR_GL_INIT_ZERO;
- GL_CALL(GetProgramiv(progID, GR_GL_INFO_LOG_LENGTH, &infoLen));
+ GL_CALL(GetProgramiv(fProgramID, GR_GL_INFO_LOG_LENGTH, &infoLen));
SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
if (infoLen > 0) {
// retrieve length even though we don't need it to workaround
// bug in chrome cmd buffer param validation.
GrGLsizei length = GR_GL_INIT_ZERO;
- GL_CALL(GetProgramInfoLog(progID,
+ GL_CALL(GetProgramInfoLog(fProgramID,
infoLen+1,
&length,
(char*)log.get()));
GrPrintf((char*)log.get());
}
GrAssert(!"Error linking program");
- GL_CALL(DeleteProgram(progID));
- programData->fProgramID = 0;
+ GL_CALL(DeleteProgram(fProgramID));
+ fProgramID = 0;
return false;
}
return true;
}
-void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& builder,
- const GrGLContextInfo& gl,
- CachedData* programData) const {
- const GrGLint& progID = programData->fProgramID;
+void GrGLProgram::getUniformLocationsAndInitCache(const GrGLContextInfo& gl,
+ const GrGLShaderBuilder& builder) {
- if (kUseUniform == programData->fUniLocations.fViewMatrixUni) {
- GL_CALL_RET(programData->fUniLocations.fViewMatrixUni,
- GetUniformLocation(progID, VIEW_MATRIX_NAME));
- GrAssert(kUnusedUniform != programData->fUniLocations.fViewMatrixUni);
+ if (kUseUniform == fUniLocations.fViewMatrixUni) {
+ GL_CALL_RET(fUniLocations.fViewMatrixUni, GetUniformLocation(fProgramID, VIEW_MATRIX_NAME));
+ GrAssert(kUnusedUniform != fUniLocations.fViewMatrixUni);
}
- if (kUseUniform == programData->fUniLocations.fColorUni) {
- GL_CALL_RET(programData->fUniLocations.fColorUni,
- GetUniformLocation(progID, COL_UNI_NAME));
- GrAssert(kUnusedUniform != programData->fUniLocations.fColorUni);
+ if (kUseUniform == fUniLocations.fColorUni) {
+ GL_CALL_RET(fUniLocations.fColorUni, GetUniformLocation(fProgramID, COL_UNI_NAME));
+ GrAssert(kUnusedUniform != fUniLocations.fColorUni);
}
- if (kUseUniform == programData->fUniLocations.fColorFilterUni) {
- GL_CALL_RET(programData->fUniLocations.fColorFilterUni,
- GetUniformLocation(progID, COL_FILTER_UNI_NAME));
- GrAssert(kUnusedUniform != programData->fUniLocations.fColorFilterUni);
+ if (kUseUniform == fUniLocations.fColorFilterUni) {
+ GL_CALL_RET(fUniLocations.fColorFilterUni,
+ GetUniformLocation(fProgramID, COL_FILTER_UNI_NAME));
+ GrAssert(kUnusedUniform != fUniLocations.fColorFilterUni);
}
- if (kUseUniform == programData->fUniLocations.fColorMatrixUni) {
- GL_CALL_RET(programData->fUniLocations.fColorMatrixUni,
- GetUniformLocation(progID, COL_MATRIX_UNI_NAME));
+ if (kUseUniform == fUniLocations.fColorMatrixUni) {
+ GL_CALL_RET(fUniLocations.fColorMatrixUni,
+ GetUniformLocation(fProgramID, COL_MATRIX_UNI_NAME));
+ GrAssert(kUnusedUniform != fUniLocations.fColorMatrixUni);
}
- if (kUseUniform == programData->fUniLocations.fColorMatrixVecUni) {
- GL_CALL_RET(programData->fUniLocations.fColorMatrixVecUni,
- GetUniformLocation(progID, COL_MATRIX_VEC_UNI_NAME));
+ if (kUseUniform == fUniLocations.fColorMatrixVecUni) {
+ GL_CALL_RET(fUniLocations.fColorMatrixVecUni,
+ GetUniformLocation(fProgramID, COL_MATRIX_VEC_UNI_NAME));
+ GrAssert(kUnusedUniform != fUniLocations.fColorMatrixVecUni);
}
- if (kUseUniform == programData->fUniLocations.fCoverageUni) {
- GL_CALL_RET(programData->fUniLocations.fCoverageUni,
- GetUniformLocation(progID, COV_UNI_NAME));
- GrAssert(kUnusedUniform != programData->fUniLocations.fCoverageUni);
+ if (kUseUniform == fUniLocations.fCoverageUni) {
+ GrAssert(kUnusedUniform != fUniLocations.fCoverageUni);
}
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
- StageUniLocations& locations = programData->fUniLocations.fStages[s];
- if (fProgramDesc.fStages[s].isEnabled()) {
+ StageUniLocations& locations = fUniLocations.fStages[s];
+ if (fDesc.fStages[s].isEnabled()) {
if (kUseUniform == locations.fTextureMatrixUni) {
SkString texMName;
tex_matrix_name(s, &texMName);
GL_CALL_RET(locations.fTextureMatrixUni,
- GetUniformLocation(progID, texMName.c_str()));
+ GetUniformLocation(fProgramID, texMName.c_str()));
GrAssert(kUnusedUniform != locations.fTextureMatrixUni);
}
SkString samplerName;
sampler_name(s, &samplerName);
GL_CALL_RET(locations.fSamplerUni,
- GetUniformLocation(progID,samplerName.c_str()));
+ GetUniformLocation(fProgramID,samplerName.c_str()));
GrAssert(kUnusedUniform != locations.fSamplerUni);
}
SkString texDomName;
tex_domain_name(s, &texDomName);
GL_CALL_RET(locations.fTexDomUni,
- GetUniformLocation(progID, texDomName.c_str()));
+ GetUniformLocation(fProgramID, texDomName.c_str()));
GrAssert(kUnusedUniform != locations.fTexDomUni);
}
- if (NULL != programData->fCustomStage[s]) {
- programData->fCustomStage[s]->initUniforms(&builder, gl.interface(), progID);
+ if (NULL != fProgramStage[s]) {
+ fProgramStage[s]->initUniforms(&builder, gl.interface(), fProgramID);
}
}
}
- GL_CALL(UseProgram(progID));
+ GL_CALL(UseProgram(fProgramID));
// init sampler unis and set bogus values for state tracking
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
- if (kUnusedUniform != programData->fUniLocations.fStages[s].fSamplerUni) {
- GL_CALL(Uniform1i(programData->fUniLocations.fStages[s].fSamplerUni, s));
+ if (kUnusedUniform != fUniLocations.fStages[s].fSamplerUni) {
+ GL_CALL(Uniform1i(fUniLocations.fStages[s].fSamplerUni, s));
}
- programData->fTextureMatrices[s] = GrMatrix::InvalidMatrix();
- programData->fTextureDomain[s].setEmpty();
+ fTextureMatrices[s] = GrMatrix::InvalidMatrix();
+ fTextureDomain[s].setEmpty();
// this is arbitrary, just initialize to something
- programData->fTextureOrientation[s] =
- GrGLTexture::kBottomUp_Orientation;
+ fTextureOrientation[s] = GrGLTexture::kBottomUp_Orientation;
// Must not reset fStageOverride[] here.
}
- programData->fViewMatrix = GrMatrix::InvalidMatrix();
- programData->fViewportSize.set(-1, -1);
- programData->fColor = GrColor_ILLEGAL;
- programData->fColorFilterColor = GrColor_ILLEGAL;
+ fViewMatrix = GrMatrix::InvalidMatrix();
+ fViewportSize.set(-1, -1);
+ fColor = GrColor_ILLEGAL;
+ fColorFilterColor = GrColor_ILLEGAL;
}
///////////////////////////////////////////////////////////////////////////////
void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
int stageNum,
- const GrGLProgram::StageDesc& desc,
const char* fsInColor, // NULL means no incoming color
const char* fsOutColor,
const char* vsInCoord,
- GrGLShaderBuilder* segments,
- StageUniLocations* locations,
- GrGLProgramStage* customStage) const {
-
+ GrGLShaderBuilder* segments) {
GrAssert(stageNum >= 0 && stageNum <= GrDrawState::kNumStages);
- GrAssert((desc.fInConfigFlags & StageDesc::kInConfigBitMask) ==
- desc.fInConfigFlags);
+
+ const GrGLProgram::StageDesc& desc = fDesc.fStages[stageNum];
+ StageUniLocations& locations = fUniLocations.fStages[stageNum];
+ GrGLProgramStage* customStage = fProgramStage[stageNum];
+
+ GrAssert((desc.fInConfigFlags & StageDesc::kInConfigBitMask) == desc.fInConfigFlags);
/// Vertex Shader Stuff
const GrGLShaderVar& mat = segments->getUniformVariable(m);
// Can't use texMatName.c_str() because it's on the stack!
matName = mat.getName().c_str();
- locations->fTextureMatrixUni = kUseUniform;
+ locations.fTextureMatrixUni = kUseUniform;
if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
segments->fVaryingDims = segments->fCoordDims;
sampler_name(stageNum, &samplerName);
segments->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
kSampler2D_GrSLType, samplerName.c_str());
- locations->fSamplerUni = kUseUniform;
+ locations.fSamplerUni = kUseUniform;
const char *varyingVSName, *varyingFSName;
segments->addVarying(GrSLFloatVectorType(segments->fVaryingDims),
"Stage",
- stageNum,
- &varyingVSName,
- &varyingFSName);
+ stageNum,
+ &varyingVSName,
+ &varyingFSName);
if (!matName) {
GrAssert(segments->fVaryingDims == segments->fCoordDims);
texDomainName.c_str(),
texDomainName.c_str());
segments->fSampleCoords = coordVar;
- locations->fTexDomUni = kUseUniform;
+ locations.fTexDomUni = kUseUniform;
}
// NOTE: GrGLProgramStages are now responsible for fetching
#include "GrGLContextInfo.h"
#include "GrGLSL.h"
#include "GrGLTexture.h"
-#include "GrGpu.h"
+//#include "GrGpu.h"
#include "SkString.h"
#include "SkXfermode.h"
* Uniforms are program-local so we can't rely on fHWState to hold the
* previous uniform state after a program change.
*/
-class GrGLProgram {
+class GrGLProgram : public GrRefCnt {
public:
+ SK_DECLARE_INST_COUNT(GrGLProgram)
- class CachedData;
+ struct Desc;
GrGLProgram();
- ~GrGLProgram();
+ virtual ~GrGLProgram();
/**
* This is the heavy initilization routine for building a GLProgram.
- * The result of heavy init is not stored in datamembers of GrGLProgam,
- * but in a separate cacheable container.
*/
bool genProgram(const GrGLContextInfo& gl,
- GrCustomStage** customStages,
- CachedData* programData) const;
+ const Desc& desc,
+ GrCustomStage** customStages);
/**
* The shader may modify the blend coeffecients. Params are in/out
*/
void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const;
+ const Desc& getDesc() { return fDesc; }
+
/**
* Attribute indices. These should not overlap. Matrices consume 3 slots.
*/
return 7 + GrDrawState::kMaxTexCoords + 3 * stage;
}
-public:
+ enum {
+ kUnusedUniform = -1,
+ };
// Parameters that affect code generation
// These structs should be kept compact; they are the input to an
// expensive hash key generator.
- struct ProgramDesc {
- ProgramDesc() {
+ struct Desc {
+ Desc() {
// since we use this as part of a key we can't have any unitialized
// padding
- memset(this, 0, sizeof(ProgramDesc));
+ memset(this, 0, sizeof(Desc));
+ }
+
+ // returns this as a uint32_t array to be used as a key in the program cache
+ const uint32_t* asKey() const {
+ return reinterpret_cast<const uint32_t*>(this);
}
enum OutputConfig {
uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode
int8_t fPadding[1];
-
- } fProgramDesc;
- GR_STATIC_ASSERT(!(sizeof(ProgramDesc) % 4));
+ };
+ GR_STATIC_ASSERT(!(sizeof(Desc) % 4));
// for code readability
- typedef ProgramDesc::StageDesc StageDesc;
+ typedef Desc::StageDesc StageDesc;
private:
+ void genInputColor(GrGLShaderBuilder* builder, SkString* inColor);
- const ProgramDesc& getDesc() { return fProgramDesc; }
- const char* adjustInColor(const SkString& inColor) const;
+ // Determines which uniforms will need to be bound.
+ void genStageCode(const GrGLContextInfo& gl,
+ int stageNum,
+ const char* fsInColor, // NULL means no incoming color
+ const char* fsOutColor,
+ const char* vsInCoord,
+ GrGLShaderBuilder* builder);
-public:
- enum {
- kUnusedUniform = -1,
- };
+ void genGeometryShader(const GrGLContextInfo& gl, GrGLShaderBuilder* segments) const;
+
+ void genUniformCoverage(GrGLShaderBuilder* segments, SkString* inOutCoverage);
+
+ // generates code to compute coverage based on edge AA.
+ void genEdgeCoverage(const GrGLContextInfo& gl,
+ SkString* coverageVar,
+ GrGLShaderBuilder* builder) const;
+
+ // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program
+ bool bindOutputsAttribsAndLinkProgram(const GrGLContextInfo& gl,
+ SkString texCoordAttrNames[GrDrawState::kMaxTexCoords],
+ bool bindColorOut,
+ bool bindDualSrcOut);
+
+ // Binds uniforms; initializes cache to invalid values.
+ void getUniformLocationsAndInitCache(const GrGLContextInfo& gl,
+ const GrGLShaderBuilder& builder);
+
+ bool compileShaders(const GrGLContextInfo& gl, const GrGLShaderBuilder& builder);
+
+ const char* adjustInColor(const SkString& inColor) const;
struct StageUniLocations {
GrGLint fTextureMatrixUni;
}
};
- class CachedData : public ::GrNoncopyable {
- public:
- CachedData() {
- for (int i = 0; i < GrDrawState::kNumStages; ++i) {
- fCustomStage[i] = NULL;
- }
- }
-
- ~CachedData();
-
- void copyAndTakeOwnership(CachedData& other) {
- memcpy(this, &other, sizeof(*this));
- for (int i = 0; i < GrDrawState::kNumStages; ++i) {
- other.fCustomStage[i] = NULL;
- }
- }
-
- public:
-
- // IDs
- GrGLuint fVShaderID;
- GrGLuint fGShaderID;
- GrGLuint fFShaderID;
- GrGLuint fProgramID;
- // shader uniform locations (-1 if shader doesn't use them)
- UniLocations fUniLocations;
-
- // The matrix sent to GL is determined by both the client's matrix and
- // the size of the viewport.
- GrMatrix fViewMatrix;
- SkISize fViewportSize;
-
- // these reflect the current values of uniforms
- // (GL uniform values travel with program)
- GrColor fColor;
- GrColor fCoverage;
- GrColor fColorFilterColor;
- GrMatrix fTextureMatrices[GrDrawState::kNumStages];
- GrRect fTextureDomain[GrDrawState::kNumStages];
- // The texture domain and texture matrix sent to GL depend upon the
- // orientation.
- GrGLTexture::Orientation fTextureOrientation[GrDrawState::kNumStages];
-
- GrGLProgramStage* fCustomStage[GrDrawState::kNumStages];
-
- private:
- enum Constants {
- kUniLocationPreAllocSize = 8
- };
-
- }; // CachedData
-
- enum Constants {
- kProgramKeySize = sizeof(ProgramDesc)
- };
-
- // Provide an opaque ProgramDesc
- const uint32_t* keyData() const{
- return reinterpret_cast<const uint32_t*>(&fProgramDesc);
- }
-
-private:
-
- // Determines which uniforms will need to be bound.
- void genStageCode(const GrGLContextInfo& gl,
- int stageNum,
- const ProgramDesc::StageDesc& desc,
- const char* fsInColor, // NULL means no incoming color
- const char* fsOutColor,
- const char* vsInCoord,
- GrGLShaderBuilder* segments,
- StageUniLocations* locations,
- GrGLProgramStage* override) const;
-
- void genGeometryShader(const GrGLContextInfo& gl,
- GrGLShaderBuilder* segments) const;
-
- // generates code to compute coverage based on edge AA.
- void genEdgeCoverage(const GrGLContextInfo& gl,
- GrVertexLayout layout,
- CachedData* programData,
- SkString* coverageVar,
- GrGLShaderBuilder* segments) const;
-
- // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program
- bool bindOutputsAttribsAndLinkProgram(
- const GrGLContextInfo& gl,
- SkString texCoordAttrNames[GrDrawState::kMaxTexCoords],
- bool bindColorOut,
- bool bindDualSrcOut,
- CachedData* programData) const;
-
- // Binds uniforms; initializes cache to invalid values.
- void getUniformLocationsAndInitCache(const GrGLShaderBuilder& builder,
- const GrGLContextInfo& gl,
- CachedData* programData) const;
-
- friend class GrGpuGL;
+ // IDs
+ GrGLuint fVShaderID;
+ GrGLuint fGShaderID;
+ GrGLuint fFShaderID;
+ GrGLuint fProgramID;
+ // shader uniform locations (-1 if shader doesn't use them)
+ UniLocations fUniLocations;
+
+ // The matrix sent to GL is determined by both the client's matrix and
+ // the size of the viewport.
+ GrMatrix fViewMatrix;
+ SkISize fViewportSize;
+
+ // these reflect the current values of uniforms
+ // (GL uniform values travel with program)
+ GrColor fColor;
+ GrColor fCoverage;
+ GrColor fColorFilterColor;
+ GrMatrix fTextureMatrices[GrDrawState::kNumStages];
+ GrRect fTextureDomain[GrDrawState::kNumStages];
+ // The texture domain and texture matrix sent to GL depend upon the
+ // orientation.
+ GrGLTexture::Orientation fTextureOrientation[GrDrawState::kNumStages];
+
+ GrGLProgramStage* fProgramStage[GrDrawState::kNumStages];
+
+ Desc fDesc;
+
+ friend class GrGpuGL; // TODO: remove this by adding getters and moving functionality.
+
+ typedef GrRefCnt INHERITED;
};
#endif
#define SKIP_CACHE_CHECK true
#define GR_UINT32_MAX static_cast<uint32_t>(-1)
-void GrGpuGL::ProgramCache::Entry::copyAndTakeOwnership(Entry& entry) {
- fProgramData.copyAndTakeOwnership(entry.fProgramData);
- fKey = entry.fKey; // ownership transfer
- fLRUStamp = entry.fLRUStamp;
-}
-
GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl)
: fCount(0)
, fCurrLRUStamp(0)
GrGpuGL::ProgramCache::~ProgramCache() {
for (int i = 0; i < fCount; ++i) {
- GrGpuGL::DeleteProgram(fGL.interface(),
- &fEntries[i].fProgramData);
+ GrGpuGL::DeleteProgram(fGL.interface(), fEntries[i].fProgram);
}
}
fCount = 0;
}
-GrGLProgram::CachedData* GrGpuGL::ProgramCache::getProgramData(
- const GrGLProgram& desc,
- GrCustomStage** stages) {
+GrGLProgram* GrGpuGL::ProgramCache::getProgram(const ProgramDesc& desc, GrCustomStage** stages) {
Entry newEntry;
- newEntry.fKey.setKeyData(desc.keyData());
-
+ newEntry.fKey.setKeyData(desc.asKey());
+
Entry* entry = fHashCache.find(newEntry.fKey);
if (NULL == entry) {
- if (!desc.genProgram(fGL, stages, &newEntry.fProgramData)) {
+ newEntry.fProgram.reset(SkNEW(GrGLProgram));
+ if (!newEntry.fProgram->genProgram(fGL, desc, stages)) {
return NULL;
}
if (fCount < kMaxEntries) {
}
}
fHashCache.remove(entry->fKey, entry);
- GrGpuGL::DeleteProgram(fGL.interface(),
- &entry->fProgramData);
+ GrGpuGL::DeleteProgram(fGL.interface(), entry->fProgram);
}
- entry->copyAndTakeOwnership(newEntry);
+ *entry = newEntry;
fHashCache.insert(entry->fKey, entry);
}
}
}
++fCurrLRUStamp;
- return &entry->fProgramData;
+ return entry->fProgram;
}
-void GrGpuGL::DeleteProgram(const GrGLInterface* gl,
- CachedData* programData) {
- GR_GL_CALL(gl, DeleteShader(programData->fVShaderID));
- if (programData->fGShaderID) {
- GR_GL_CALL(gl, DeleteShader(programData->fGShaderID));
- }
- GR_GL_CALL(gl, DeleteShader(programData->fFShaderID));
- GR_GL_CALL(gl, DeleteProgram(programData->fProgramID));
- GR_DEBUGCODE(programData->fVShaderID = 0);
- GR_DEBUGCODE(programData->fGShaderID = 0);
- GR_DEBUGCODE(programData->fFShaderID = 0);
- GR_DEBUGCODE(programData->fProgramID = 0);
+void GrGpuGL::DeleteProgram(const GrGLInterface* gl, GrGLProgram* program) {
+ GR_GL_CALL(gl, DeleteShader(program->fVShaderID));
+ if (program->fGShaderID) {
+ GR_GL_CALL(gl, DeleteShader(program->fGShaderID));
+ }
+ GR_GL_CALL(gl, DeleteShader(program->fFShaderID));
+ GR_GL_CALL(gl, DeleteProgram(program->fProgramID));
+ GR_DEBUGCODE(program->fVShaderID = 0);
+ GR_DEBUGCODE(program->fGShaderID = 0);
+ GR_DEBUGCODE(program->fFShaderID = 0);
+ GR_DEBUGCODE(program->fProgramID = 0);
}
////////////////////////////////////////////////////////////////////////////////
fHWPathMatrixState.fViewMatrix = vm;
fHWPathMatrixState.fRTSize = viewportSize;
}
- } else if (!fProgramData->fViewMatrix.cheapEqualTo(vm) ||
- fProgramData->fViewportSize != viewportSize) {
+ } else if (!fCurrentProgram->fViewMatrix.cheapEqualTo(vm) ||
+ fCurrentProgram->fViewportSize != viewportSize) {
GrMatrix m;
m.setAll(
GrIntToScalar(2) / viewportSize.fWidth, 0, -GR_Scalar1,
};
GrAssert(GrGLProgram::kUnusedUniform !=
- fProgramData->fUniLocations.fViewMatrixUni);
- GL_CALL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni,
+ fCurrentProgram->fUniLocations.fViewMatrixUni);
+ GL_CALL(UniformMatrix3fv(fCurrentProgram->fUniLocations.fViewMatrixUni,
1, false, mt));
- fProgramData->fViewMatrix = vm;
- fProgramData->fViewportSize = viewportSize;
+ fCurrentProgram->fViewMatrix = vm;
+ fCurrentProgram->fViewportSize = viewportSize;
}
}
static_cast<const GrGLTexture*>(drawState.getTexture(s));
if (NULL != texture) {
- bool orientationChange = fProgramData->fTextureOrientation[s] !=
+ bool orientationChange = fCurrentProgram->fTextureOrientation[s] !=
texture->orientation();
const GrGLint& matrixUni =
- fProgramData->fUniLocations.fStages[s].fTextureMatrixUni;
+ fCurrentProgram->fUniLocations.fStages[s].fTextureMatrixUni;
- const GrMatrix& hwMatrix = fProgramData->fTextureMatrices[s];
+ const GrMatrix& hwMatrix = fCurrentProgram->fTextureMatrices[s];
const GrMatrix& samplerMatrix = drawState.getSampler(s).getMatrix();
if (GrGLProgram::kUnusedUniform != matrixUni &&
};
GL_CALL(UniformMatrix3fv(matrixUni, 1, false, mt));
- fProgramData->fTextureMatrices[s] = samplerMatrix;
+ fCurrentProgram->fTextureMatrices[s] = samplerMatrix;
}
- const GrGLint& domUni =
- fProgramData->fUniLocations.fStages[s].fTexDomUni;
+ const GrGLint& domUni = fCurrentProgram->fUniLocations.fStages[s].fTexDomUni;
const GrRect &texDom = drawState.getSampler(s).getTextureDomain();
if (GrGLProgram::kUnusedUniform != domUni &&
- (orientationChange ||fProgramData->fTextureDomain[s] != texDom)) {
+ (orientationChange ||fCurrentProgram->fTextureDomain[s] != texDom)) {
- fProgramData->fTextureDomain[s] = texDom;
+ fCurrentProgram->fTextureDomain[s] = texDom;
float values[4] = {
GrScalarToFloat(texDom.left()),
}
GL_CALL(Uniform4fv(domUni, 1, values));
}
- fProgramData->fTextureOrientation[s] = texture->orientation();
+ fCurrentProgram->fTextureOrientation[s] = texture->orientation();
}
}
void GrGpuGL::flushColorMatrix() {
- // const ProgramDesc& desc = fCurrentProgram.getDesc();
- int matrixUni = fProgramData->fUniLocations.fColorMatrixUni;
- int vecUni = fProgramData->fUniLocations.fColorMatrixVecUni;
+ int matrixUni = fCurrentProgram->fUniLocations.fColorMatrixUni;
+ int vecUni = fCurrentProgram->fUniLocations.fColorMatrixVecUni;
if (GrGLProgram::kUnusedUniform != matrixUni
&& GrGLProgram::kUnusedUniform != vecUni) {
const float* m = this->getDrawState().getColorMatrix();
}
void GrGpuGL::flushColor(GrColor color) {
- const ProgramDesc& desc = fCurrentProgram.getDesc();
+ const ProgramDesc& desc = fCurrentProgram->getDesc();
const GrDrawState& drawState = this->getDrawState();
if (this->getVertexLayout() & kColor_VertexLayoutBit) {
}
break;
case ProgramDesc::kUniform_ColorInput:
- if (fProgramData->fColor != color) {
+ if (fCurrentProgram->fColor != color) {
// OpenGL ES doesn't support unsigned byte varieties of
// glUniform
float c[] = GR_COLOR_TO_VEC4(color);
GrAssert(GrGLProgram::kUnusedUniform !=
- fProgramData->fUniLocations.fColorUni);
- GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorUni,
- 1, c));
- fProgramData->fColor = color;
+ fCurrentProgram->fUniLocations.fColorUni);
+ GL_CALL(Uniform4fv(fCurrentProgram->fUniLocations.fColorUni, 1, c));
+ fCurrentProgram->fColor = color;
}
break;
case ProgramDesc::kSolidWhite_ColorInput:
GrCrash("Unknown color type.");
}
}
- if (fProgramData->fUniLocations.fColorFilterUni
+ if (fCurrentProgram->fUniLocations.fColorFilterUni
!= GrGLProgram::kUnusedUniform
- && fProgramData->fColorFilterColor
+ && fCurrentProgram->fColorFilterColor
!= drawState.getColorFilterColor()) {
float c[] = GR_COLOR_TO_VEC4(drawState.getColorFilterColor());
- GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c));
- fProgramData->fColorFilterColor = drawState.getColorFilterColor();
+ GL_CALL(Uniform4fv(fCurrentProgram->fUniLocations.fColorFilterUni, 1, c));
+ fCurrentProgram->fColorFilterColor = drawState.getColorFilterColor();
}
}
void GrGpuGL::flushCoverage(GrColor coverage) {
- const ProgramDesc& desc = fCurrentProgram.getDesc();
+ const ProgramDesc& desc = fCurrentProgram->getDesc();
// const GrDrawState& drawState = this->getDrawState();
}
break;
case ProgramDesc::kUniform_ColorInput:
- if (fProgramData->fCoverage != coverage) {
+ if (fCurrentProgram->fCoverage != coverage) {
// OpenGL ES doesn't support unsigned byte varieties of
// glUniform
float c[] = GR_COLOR_TO_VEC4(coverage);
GrAssert(GrGLProgram::kUnusedUniform !=
- fProgramData->fUniLocations.fCoverageUni);
- GL_CALL(Uniform4fv(fProgramData->fUniLocations.fCoverageUni,
- 1, c));
- fProgramData->fCoverage = coverage;
+ fCurrentProgram->fUniLocations.fCoverageUni);
+ GL_CALL(Uniform4fv(fCurrentProgram->fUniLocations.fCoverageUni, 1, c));
+ fCurrentProgram->fCoverage = coverage;
}
break;
case ProgramDesc::kSolidWhite_ColorInput:
}
GrCustomStage* customStages [GrDrawState::kNumStages];
- this->buildProgram(kDrawPoints_DrawType == type,
- blendOpts, dstCoeff, customStages);
- fProgramData = fProgramCache->getProgramData(fCurrentProgram,
- customStages);
- if (NULL == fProgramData) {
+ GrGLProgram::Desc desc;
+ this->buildProgram(kDrawPoints_DrawType == type, blendOpts, dstCoeff, customStages, &desc);
+
+ fCurrentProgram.reset(fProgramCache->getProgram(desc, customStages));
+ if (NULL == fCurrentProgram.get()) {
GrAssert(!"Failed to create program!");
return false;
}
+ fCurrentProgram.get()->ref();
- if (fHWProgramID != fProgramData->fProgramID) {
- GL_CALL(UseProgram(fProgramData->fProgramID));
- fHWProgramID = fProgramData->fProgramID;
+ if (fHWProgramID != fCurrentProgram->fProgramID) {
+ GL_CALL(UseProgram(fCurrentProgram->fProgramID));
+ fHWProgramID = fCurrentProgram->fProgramID;
}
- fCurrentProgram.overrideBlend(&srcCoeff, &dstCoeff);
+ fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
GrColor color;
this->flushTextureMatrixAndDomain(s);
- if (NULL != fProgramData->fCustomStage[s]) {
- const GrSamplerState& sampler =
- this->getDrawState().getSampler(s);
- const GrGLTexture* texture =
- static_cast<const GrGLTexture*>(
- this->getDrawState().getTexture(s));
- fProgramData->fCustomStage[s]->setData(
- this->glInterface(),
- *sampler.getCustomStage(),
- drawState.getRenderTarget(), s);
+ if (NULL != fCurrentProgram->fProgramStage[s]) {
+ const GrSamplerState& sampler = this->getDrawState().getSampler(s);
+ const GrGLTexture* texture = static_cast<const GrGLTexture*>(
+ this->getDrawState().getTexture(s));
+ fCurrentProgram->fProgramStage[s]->setData(this->glInterface(),
+ *sampler.getCustomStage(),
+ drawState.getRenderTarget(), s);
}
}
}
namespace {
-void setup_custom_stage(GrGLProgram::ProgramDesc::StageDesc* stage,
+void setup_custom_stage(GrGLProgram::Desc::StageDesc* stage,
const GrSamplerState& sampler,
GrCustomStage** customStages,
GrGLProgram* program, int index) {
void GrGpuGL::buildProgram(bool isPoints,
BlendOptFlags blendOpts,
GrBlendCoeff dstCoeff,
- GrCustomStage** customStages) {
- ProgramDesc& desc = fCurrentProgram.fProgramDesc;
+ GrCustomStage** customStages,
+ ProgramDesc* desc) {
const GrDrawState& drawState = this->getDrawState();
// This should already have been caught
// to a canonical value to avoid duplicate programs with different keys.
// Must initialize all fields or cache will have false negatives!
- desc.fVertexLayout = this->getVertexLayout();
+ desc->fVertexLayout = this->getVertexLayout();
- desc.fEmitsPointSize = isPoints;
+ desc->fEmitsPointSize = isPoints;
bool requiresAttributeColors =
- !skipColor && SkToBool(desc.fVertexLayout & kColor_VertexLayoutBit);
+ !skipColor && SkToBool(desc->fVertexLayout & kColor_VertexLayoutBit);
bool requiresAttributeCoverage =
- !skipCoverage && SkToBool(desc.fVertexLayout &
+ !skipCoverage && SkToBool(desc->fVertexLayout &
kCoverage_VertexLayoutBit);
// fColorInput/fCoverageInput records how colors are specified for the.
// program. So we strip the bits from the layout to avoid false negatives
// when searching for an existing program in the cache.
- desc.fVertexLayout &= ~(kColor_VertexLayoutBit | kCoverage_VertexLayoutBit);
+ desc->fVertexLayout &= ~(kColor_VertexLayoutBit | kCoverage_VertexLayoutBit);
- desc.fColorFilterXfermode = skipColor ?
+ desc->fColorFilterXfermode = skipColor ?
SkXfermode::kDst_Mode :
drawState.getColorFilterMode();
- desc.fColorMatrixEnabled = drawState.isStateFlagEnabled(GrDrawState::kColorMatrix_StateBit);
+ desc->fColorMatrixEnabled = drawState.isStateFlagEnabled(GrDrawState::kColorMatrix_StateBit);
// no reason to do edge aa or look at per-vertex coverage if coverage is
// ignored
if (skipCoverage) {
- desc.fVertexLayout &= ~(kEdge_VertexLayoutBit |
+ desc->fVertexLayout &= ~(kEdge_VertexLayoutBit |
kCoverage_VertexLayoutBit);
}
(!requiresAttributeColors &&
0xffffffff == drawState.getColor());
if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) {
- desc.fColorInput = ProgramDesc::kTransBlack_ColorInput;
+ desc->fColorInput = ProgramDesc::kTransBlack_ColorInput;
} else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) {
- desc.fColorInput = ProgramDesc::kSolidWhite_ColorInput;
+ desc->fColorInput = ProgramDesc::kSolidWhite_ColorInput;
} else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
- desc.fColorInput = ProgramDesc::kUniform_ColorInput;
+ desc->fColorInput = ProgramDesc::kUniform_ColorInput;
} else {
- desc.fColorInput = ProgramDesc::kAttribute_ColorInput;
+ desc->fColorInput = ProgramDesc::kAttribute_ColorInput;
}
bool covIsSolidWhite = !requiresAttributeCoverage &&
0xffffffff == drawState.getCoverage();
if (skipCoverage) {
- desc.fCoverageInput = ProgramDesc::kTransBlack_ColorInput;
+ desc->fCoverageInput = ProgramDesc::kTransBlack_ColorInput;
} else if (covIsSolidWhite) {
- desc.fCoverageInput = ProgramDesc::kSolidWhite_ColorInput;
+ desc->fCoverageInput = ProgramDesc::kSolidWhite_ColorInput;
} else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
- desc.fCoverageInput = ProgramDesc::kUniform_ColorInput;
+ desc->fCoverageInput = ProgramDesc::kUniform_ColorInput;
} else {
- desc.fCoverageInput = ProgramDesc::kAttribute_ColorInput;
+ desc->fCoverageInput = ProgramDesc::kAttribute_ColorInput;
}
int lastEnabledStage = -1;
- if (!skipCoverage && (desc.fVertexLayout &
+ if (!skipCoverage && (desc->fVertexLayout &
GrDrawTarget::kEdge_VertexLayoutBit)) {
- desc.fVertexEdgeType = drawState.getVertexEdgeType();
+ desc->fVertexEdgeType = drawState.getVertexEdgeType();
} else {
// use canonical value when not set to avoid cache misses
- desc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType;
+ desc->fVertexEdgeType = GrDrawState::kHairLine_EdgeType;
}
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
- StageDesc& stage = desc.fStages[s];
+ StageDesc& stage = desc->fStages[s];
stage.fOptFlags = 0;
stage.setEnabled(this->isStageEnabled(s));
}
}
- setup_custom_stage(&stage, sampler, customStages,
- &fCurrentProgram, s);
+ setup_custom_stage(&stage, sampler, customStages, fCurrentProgram.get(), s);
} else {
stage.fOptFlags = 0;
// when rounding.
GrAssert(4 == GrBytesPerPixel(drawState.getRenderTarget()->config()));
if (kUpOnWrite_DownOnRead_UnpremulConversion == fUnpremulConversion) {
- desc.fOutputConfig =
+ desc->fOutputConfig =
ProgramDesc::kUnpremultiplied_RoundUp_OutputConfig;
} else {
- desc.fOutputConfig =
+ desc->fOutputConfig =
ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig;
}
} else {
- desc.fOutputConfig = ProgramDesc::kPremultiplied_OutputConfig;
+ desc->fOutputConfig = ProgramDesc::kPremultiplied_OutputConfig;
}
- desc.fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput;
+ desc->fDualSrcOutput = ProgramDesc::kNone_DualSrcOutput;
// currently the experimental GS will only work with triangle prims
// (and it doesn't do anything other than pass through values from
// the VS to the FS anyway).
#if 0 && GR_GL_EXPERIMENTAL_GS
- desc.fExperimentalGS = this->getCaps().fGeometryShaderSupport;
+ desc->fExperimentalGS = this->getCaps().fGeometryShaderSupport;
#endif
// we want to avoid generating programs with different "first cov stage"
// coverage stages or the distinction between coverage and color is
// immaterial.
int firstCoverageStage = GrDrawState::kNumStages;
- desc.fFirstCoverageStage = GrDrawState::kNumStages;
+ desc->fFirstCoverageStage = GrDrawState::kNumStages;
bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage;
if (hasCoverage) {
firstCoverageStage = drawState.getFirstCoverageStage();
if (!hasCoverage) {
hasCoverage =
requiresAttributeCoverage ||
- (desc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit);
+ (desc->fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit);
}
if (hasCoverage) {
// color filter is applied between color/coverage computation
- if (SkXfermode::kDst_Mode != desc.fColorFilterXfermode) {
- desc.fFirstCoverageStage = firstCoverageStage;
+ if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) {
+ desc->fFirstCoverageStage = firstCoverageStage;
}
if (this->getCaps().fDualSourceBlendingSupport &&
kCoverageAsAlpha_BlendOptFlag))) {
if (kZero_GrBlendCoeff == dstCoeff) {
// write the coverage value to second color
- desc.fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput;
- desc.fFirstCoverageStage = firstCoverageStage;
+ desc->fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput;
+ desc->fFirstCoverageStage = firstCoverageStage;
} else if (kSA_GrBlendCoeff == dstCoeff) {
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
// cover
- desc.fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput;
- desc.fFirstCoverageStage = firstCoverageStage;
+ desc->fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput;
+ desc->fFirstCoverageStage = firstCoverageStage;
} else if (kSC_GrBlendCoeff == dstCoeff) {
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
// cover
- desc.fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput;
- desc.fFirstCoverageStage = firstCoverageStage;
+ desc->fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput;
+ desc->fFirstCoverageStage = firstCoverageStage;
}
}
}