Remove GrGLProgram::CachedData, make GrGLProgram represent the program

Review URL: http://codereview.appspot.com/6409043/



git-svn-id: http://skia.googlecode.com/svn/trunk@4627 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2012-07-16 17:36:28 +00:00
Родитель a2333d9703
Коммит 9ba4fa6f0f
8 изменённых файлов: 423 добавлений и 503 удалений

Просмотреть файл

@ -13,30 +13,40 @@
#include "GrTypes.h" #include "GrTypes.h"
/** /**
* Hash function class that can take a data chunk of any predetermined * Hash function class that can take a data chunk of any predetermined length. The hash function
* length. The hash function used is the One-at-a-Time Hash * used is the One-at-a-Time Hash (http://burtleburtle.net/bob/hash/doobs.html).
* (http://burtleburtle.net/bob/hash/doobs.html). *
* Keys are computed from Entry objects. Entry must be fully ordered by a member:
* int compare(const GrTBinHashKey<Entry, ..>& k);
* which returns negative if the Entry < k, 0 if it equals k, and positive if k < the Entry.
* Additionally, Entry must be flattenable into the key using setKeyData.
*
* This class satisfies the requirements to be a key for a GrTHashTable.
*/ */
template<typename Entry, size_t KeySize> template<typename Entry, size_t KeySize>
class GrBinHashKey { class GrTBinHashKey {
public: public:
GrBinHashKey() GrTBinHashKey() {
: fHash(0) this->reset();
#if GR_DEBUG }
, fIsValid(false)
#endif
{}
GrBinHashKey(const GrBinHashKey<Entry, KeySize>& other) { GrTBinHashKey(const GrTBinHashKey<Entry, KeySize>& other) {
*this = other; *this = other;
} }
GrBinHashKey<Entry, KeySize>& operator=(const GrBinHashKey<Entry,
KeySize>& other) { GrTBinHashKey<Entry, KeySize>& operator=(const GrTBinHashKey<Entry, KeySize>& other) {
memcpy(this, &other, sizeof(*this)); memcpy(this, &other, sizeof(*this));
return *this; return *this;
} }
~GrBinHashKey() { ~GrTBinHashKey() {
}
void reset() {
fHash = 0;
#if GR_DEBUG
fIsValid = false;
#endif
} }
void setKeyData(const uint32_t* SK_RESTRICT data) { void setKeyData(const uint32_t* SK_RESTRICT data) {
@ -60,19 +70,17 @@ public:
fHash = hash; fHash = hash;
} }
int compare(const GrBinHashKey<Entry, KeySize>& key) const { int compare(const GrTBinHashKey<Entry, KeySize>& key) const {
GrAssert(fIsValid && key.fIsValid); GrAssert(fIsValid && key.fIsValid);
return memcmp(fData, key.fData, KeySize); return memcmp(fData, key.fData, KeySize);
} }
static bool static bool EQ(const Entry& entry, const GrTBinHashKey<Entry, KeySize>& key) {
EQ(const Entry& entry, const GrBinHashKey<Entry, KeySize>& key) {
GrAssert(key.fIsValid); GrAssert(key.fIsValid);
return 0 == entry.compare(key); return 0 == entry.compare(key);
} }
static bool static bool LT(const Entry& entry, const GrTBinHashKey<Entry, KeySize>& key) {
LT(const Entry& entry, const GrBinHashKey<Entry, KeySize>& key) {
GrAssert(key.fIsValid); GrAssert(key.fIsValid);
return entry.compare(key) < 0; return entry.compare(key) < 0;
} }
@ -84,7 +92,7 @@ public:
private: private:
uint32_t fHash; uint32_t fHash;
uint8_t fData[KeySize]; //Buffer for key storage uint8_t fData[KeySize]; // Buffer for key storage
#if GR_DEBUG #if GR_DEBUG
public: public:

Просмотреть файл

@ -16,6 +16,8 @@
#include "SkTrace.h" #include "SkTrace.h"
#include "SkXfermode.h" #include "SkXfermode.h"
SK_DEFINE_INST_COUNT(GrGLProgram)
namespace { namespace {
enum { enum {
@ -28,7 +30,7 @@ enum {
#define PRINT_SHADERS 0 #define PRINT_SHADERS 0
typedef GrGLProgram::ProgramDesc::StageDesc StageDesc; typedef GrGLProgram::Desc::StageDesc StageDesc;
#define VIEW_MATRIX_NAME "uViewM" #define VIEW_MATRIX_NAME "uViewM"
@ -95,18 +97,21 @@ GrGLProgram::GrGLProgram() {
} }
GrGLProgram::~GrGLProgram() { GrGLProgram::~GrGLProgram() {
for (int i = 0; i < GrDrawState::kNumStages; ++i) {
delete fProgramStage[i];
}
} }
void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff, void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff,
GrBlendCoeff* dstCoeff) const { GrBlendCoeff* dstCoeff) const {
switch (fProgramDesc.fDualSrcOutput) { switch (fDesc.fDualSrcOutput) {
case ProgramDesc::kNone_DualSrcOutput: case Desc::kNone_DualSrcOutput:
break; break;
// the prog will write a coverage value to the secondary // the prog will write a coverage value to the secondary
// output and the dst is blended by one minus that value. // output and the dst is blended by one minus that value.
case ProgramDesc::kCoverage_DualSrcOutput: case Desc::kCoverage_DualSrcOutput:
case ProgramDesc::kCoverageISA_DualSrcOutput: case Desc::kCoverageISA_DualSrcOutput:
case ProgramDesc::kCoverageISC_DualSrcOutput: case Desc::kCoverageISC_DualSrcOutput:
*dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; *dstCoeff = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
break; break;
default: default:
@ -281,17 +286,15 @@ static void addColorMatrix(SkString* fsCode, const char * outputVar,
} }
void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl, void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl,
GrVertexLayout layout,
CachedData* programData,
SkString* coverageVar, SkString* coverageVar,
GrGLShaderBuilder* segments) const { GrGLShaderBuilder* segments) const {
if (layout & GrDrawTarget::kEdge_VertexLayoutBit) { if (fDesc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit) {
const char *vsName, *fsName; const char *vsName, *fsName;
segments->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName); segments->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName);
segments->fVSAttrs.push_back().set(kVec4f_GrSLType, segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME); GrGLShaderVar::kAttribute_TypeModifier, EDGE_ATTR_NAME);
segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName); segments->fVSCode.appendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
switch (fProgramDesc.fVertexEdgeType) { switch (fDesc.fVertexEdgeType) {
case GrDrawState::kHairLine_EdgeType: case GrDrawState::kHairLine_EdgeType:
segments->fFSCode.appendf("\tfloat edgeAlpha = abs(dot(vec3(gl_FragCoord.xy,1), %s.xyz));\n", fsName); 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"); segments->fFSCode.append("\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n");
@ -345,32 +348,27 @@ void GrGLProgram::genEdgeCoverage(const GrGLContextInfo& gl,
} }
} }
namespace { void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) {
switch (fDesc.fColorInput) {
void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput, case GrGLProgram::Desc::kAttribute_ColorInput: {
GrGLProgram::CachedData* programData, builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
GrGLShaderBuilder* segments,
SkString* inColor) {
switch (colorInput) {
case GrGLProgram::ProgramDesc::kAttribute_ColorInput: {
segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier, GrGLShaderVar::kAttribute_TypeModifier,
COL_ATTR_NAME); COL_ATTR_NAME);
const char *vsName, *fsName; const char *vsName, *fsName;
segments->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName); builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
segments->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName); builder->fVSCode.appendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
*inColor = fsName; *inColor = fsName;
} break; } break;
case GrGLProgram::ProgramDesc::kUniform_ColorInput: case GrGLProgram::Desc::kUniform_ColorInput:
segments->addUniform(GrGLShaderBuilder::kFragment_ShaderType, builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
kVec4f_GrSLType, COL_UNI_NAME); kVec4f_GrSLType, COL_UNI_NAME);
programData->fUniLocations.fColorUni = kUseUniform; fUniLocations.fColorUni = kUseUniform;
*inColor = COL_UNI_NAME; *inColor = COL_UNI_NAME;
break; break;
case GrGLProgram::ProgramDesc::kTransBlack_ColorInput: case GrGLProgram::Desc::kTransBlack_ColorInput:
GrAssert(!"needComputedColor should be false."); GrAssert(!"needComputedColor should be false.");
break; break;
case GrGLProgram::ProgramDesc::kSolidWhite_ColorInput: case GrGLProgram::Desc::kSolidWhite_ColorInput:
break; break;
default: default:
GrCrash("Unknown color type."); GrCrash("Unknown color type.");
@ -378,8 +376,22 @@ void genInputColor(GrGLProgram::ProgramDesc::ColorInput colorInput,
} }
} }
void genAttributeCoverage(GrGLShaderBuilder* segments, void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOutCoverage) {
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, segments->fVSAttrs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier, GrGLShaderVar::kAttribute_TypeModifier,
COV_ATTR_NAME); COV_ATTR_NAME);
@ -394,35 +406,19 @@ void genAttributeCoverage(GrGLShaderBuilder* segments,
*inOutCoverage = fsName; *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, void GrGLProgram::genGeometryShader(const GrGLContextInfo& gl,
GrGLShaderBuilder* segments) const { GrGLShaderBuilder* segments) const {
#if GR_GL_EXPERIMENTAL_GS #if GR_GL_EXPERIMENTAL_GS
if (fProgramDesc.fExperimentalGS) { if (fDesc.fExperimentalGS) {
GrAssert(gl.glslGeneration() >= k150_GrGLSLGeneration); GrAssert(gl.glslGeneration() >= k150_GrGLSLGeneration);
segments->fGSHeader.append("layout(triangles) in;\n" segments->fGSHeader.append("layout(triangles) in;\n"
"layout(triangle_strip, max_vertices = 6) out;\n"); "layout(triangle_strip, max_vertices = 6) out;\n");
segments->fGSCode.append("void main() {\n" segments->fGSCode.append("void main() {\n"
"\tfor (int i = 0; i < 3; ++i) {\n" "\tfor (int i = 0; i < 3; ++i) {\n"
"\t\tgl_Position = gl_in[i].gl_Position;\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"); segments->fGSCode.append("\t\tgl_PointSize = 1.0;\n");
} }
GrAssert(segments->fGSInputs.count() == segments->fGSOutputs.count()); GrAssert(segments->fGSInputs.count() == segments->fGSOutputs.count());
@ -444,7 +440,7 @@ const char* GrGLProgram::adjustInColor(const SkString& inColor) const {
if (inColor.size()) { if (inColor.size()) {
return inColor.c_str(); return inColor.c_str();
} else { } else {
if (ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput) { if (Desc::kSolidWhite_ColorInput == fDesc.fColorInput) {
return all_ones_vec(4); return all_ones_vec(4);
} else { } else {
return all_zeros_vec(4); return all_zeros_vec(4);
@ -452,14 +448,6 @@ const char* GrGLProgram::adjustInColor(const SkString& inColor) const {
} }
} }
// 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 { namespace {
#define GL_CALL(X) GR_GL_CALL(gl.interface(), X) #define GL_CALL(X) GR_GL_CALL(gl.interface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gl.interface(), R, X) #define GL_CALL_RET(R, X) GR_GL_CALL_RET(gl.interface(), R, X)
@ -524,10 +512,11 @@ GrGLuint compile_shader(const GrGLContextInfo& gl, GrGLenum type, const SkString
return compile_shader(gl, type, 1, &str, &length); 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, // compiles all the shaders from builder and stores the shader IDs
GrGLProgram::CachedData* programData) { bool GrGLProgram::compileShaders(const GrGLContextInfo& gl,
const GrGLShaderBuilder& builder) {
SkString shader; SkString shader;
@ -536,7 +525,7 @@ bool compile_shaders(const GrGLContextInfo& gl,
GrPrintf(shader.c_str()); GrPrintf(shader.c_str());
GrPrintf("\n"); GrPrintf("\n");
#endif #endif
if (!(programData->fVShaderID = compile_shader(gl, GR_GL_VERTEX_SHADER, shader))) { if (!(fVShaderID = compile_shader(gl, GR_GL_VERTEX_SHADER, shader))) {
return false; return false;
} }
@ -546,11 +535,11 @@ bool compile_shaders(const GrGLContextInfo& gl,
GrPrintf(shader.c_str()); GrPrintf(shader.c_str());
GrPrintf("\n"); GrPrintf("\n");
#endif #endif
if (!(programData->fGShaderID = compile_shader(gl, GR_GL_GEOMETRY_SHADER, shader))) { if (!(fGShaderID = compile_shader(gl, GR_GL_GEOMETRY_SHADER, shader))) {
return false; return false;
} }
} else { } else {
programData->fGShaderID = 0; fGShaderID = 0;
} }
builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader); builder.getShader(GrGLShaderBuilder::kFragment_ShaderType, &shader);
@ -558,34 +547,34 @@ bool compile_shaders(const GrGLContextInfo& gl,
GrPrintf(shader.c_str()); GrPrintf(shader.c_str());
GrPrintf("\n"); GrPrintf("\n");
#endif #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 false;
} }
return true; return true;
} }
}
bool GrGLProgram::genProgram(const GrGLContextInfo& gl, bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
GrCustomStage** customStages, const Desc& desc,
GrGLProgram::CachedData* programData) const { GrCustomStage** customStages) {
fDesc = desc;
GrGLShaderBuilder builder(gl); 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 #if GR_GL_EXPERIMENTAL_GS
builder.fUsesGS = fProgramDesc.fExperimentalGS; builder.fUsesGS = fDesc.fExperimentalGS;
#endif #endif
SkXfermode::Coeff colorCoeff, uniformCoeff; 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 // 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 =) GR_DEBUGCODE(bool success =)
SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode> SkXfermode::ModeAsCoeff(static_cast<SkXfermode::Mode>
(fProgramDesc.fColorFilterXfermode), (fDesc.fColorFilterXfermode),
&uniformCoeff, &colorCoeff); &uniformCoeff, &colorCoeff);
GR_DEBUGASSERT(success); GR_DEBUGASSERT(success);
} else { } else {
@ -596,7 +585,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
// no need to do the color filter / matrix at all if coverage is 0. The // 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 // output color is scaled by the coverage. All the dual source outputs are
// scaled by the coverage as well. // scaled by the coverage as well.
if (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fCoverageInput) { if (Desc::kTransBlack_ColorInput == fDesc.fCoverageInput) {
colorCoeff = SkXfermode::kZero_Coeff; colorCoeff = SkXfermode::kZero_Coeff;
uniformCoeff = SkXfermode::kZero_Coeff; uniformCoeff = SkXfermode::kZero_Coeff;
applyColorMatrix = false; applyColorMatrix = false;
@ -605,7 +594,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
// If we know the final color is going to be all zeros then we can // If we know the final color is going to be all zeros then we can
// simplify the color filter coeffecients. needComputedColor will then // simplify the color filter coeffecients. needComputedColor will then
// come out false below. // come out false below.
if (ProgramDesc::kTransBlack_ColorInput == fProgramDesc.fColorInput) { if (Desc::kTransBlack_ColorInput == fDesc.fColorInput) {
colorCoeff = SkXfermode::kZero_Coeff; colorCoeff = SkXfermode::kZero_Coeff;
if (SkXfermode::kDC_Coeff == uniformCoeff || if (SkXfermode::kDC_Coeff == uniformCoeff ||
SkXfermode::kDA_Coeff == uniformCoeff) { SkXfermode::kDA_Coeff == uniformCoeff) {
@ -637,7 +626,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType, builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType,
kMat33f_GrSLType, VIEW_MATRIX_NAME); kMat33f_GrSLType, VIEW_MATRIX_NAME);
programData->fUniLocations.fViewMatrixUni = kUseUniform; fUniLocations.fViewMatrixUni = kUseUniform;
builder.fVSAttrs.push_back().set(kVec2f_GrSLType, builder.fVSAttrs.push_back().set(kVec2f_GrSLType,
GrGLShaderVar::kAttribute_TypeModifier, GrGLShaderVar::kAttribute_TypeModifier,
@ -651,12 +640,11 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
SkString inColor; SkString inColor;
if (needComputedColor) { if (needComputedColor) {
genInputColor((ProgramDesc::ColorInput) fProgramDesc.fColorInput, this->genInputColor(&builder, &inColor);
programData, &builder, &inColor);
} }
// we output point size in the GS if present // 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"); builder.fVSCode.append("\tgl_PointSize = 1.0;\n");
} }
@ -679,7 +667,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
// uses of programData, but it's safest to do so below when we're *sure* // uses of programData, but it's safest to do so below when we're *sure*
// we need them. // we need them.
for (int s = 0; s < GrDrawState::kNumStages; ++s) { for (int s = 0; s < GrDrawState::kNumStages; ++s) {
programData->fCustomStage[s] = NULL; fProgramStage[s] = NULL;
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -689,8 +677,8 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
// of each to the next and generating code for each stage. // of each to the next and generating code for each stage.
if (needComputedColor) { if (needComputedColor) {
SkString outColor; SkString outColor;
for (int s = 0; s < fProgramDesc.fFirstCoverageStage; ++s) { for (int s = 0; s < fDesc.fFirstCoverageStage; ++s) {
if (fProgramDesc.fStages[s].isEnabled()) { if (fDesc.fStages[s].isEnabled()) {
// create var to hold stage result // create var to hold stage result
outColor = "color"; outColor = "color";
outColor.appendS32(s); outColor.appendS32(s);
@ -708,20 +696,15 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
} }
if (NULL != customStages[s]) { if (NULL != customStages[s]) {
const GrProgramStageFactory& factory = const GrProgramStageFactory& factory = customStages[s]->getFactory();
customStages[s]->getFactory(); fProgramStage[s] = factory.createGLInstance(*customStages[s]);
programData->fCustomStage[s] =
factory.createGLInstance(*customStages[s]);
} }
this->genStageCode(gl, this->genStageCode(gl,
s, s,
fProgramDesc.fStages[s],
inColor.size() ? inColor.c_str() : NULL, inColor.size() ? inColor.c_str() : NULL,
outColor.c_str(), outColor.c_str(),
inCoords, inCoords,
&builder, &builder);
&programData->fUniLocations.fStages[s],
programData->fCustomStage[s]);
inColor = outColor; inColor = outColor;
} }
} }
@ -730,7 +713,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
// if have all ones or zeros for the "dst" input to the color filter then we // if have all ones or zeros for the "dst" input to the color filter then we
// may be able to make additional optimizations. // may be able to make additional optimizations.
if (needColorFilterUniform && needComputedColor && !inColor.size()) { if (needColorFilterUniform && needComputedColor && !inColor.size()) {
GrAssert(ProgramDesc::kSolidWhite_ColorInput == fProgramDesc.fColorInput); GrAssert(Desc::kSolidWhite_ColorInput == fDesc.fColorInput);
bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff || bool uniformCoeffIsZero = SkXfermode::kIDC_Coeff == uniformCoeff ||
SkXfermode::kIDA_Coeff == uniformCoeff; SkXfermode::kIDA_Coeff == uniformCoeff;
if (uniformCoeffIsZero) { if (uniformCoeffIsZero) {
@ -743,7 +726,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
if (needColorFilterUniform) { if (needColorFilterUniform) {
builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType, builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
kVec4f_GrSLType, COL_FILTER_UNI_NAME); kVec4f_GrSLType, COL_FILTER_UNI_NAME);
programData->fUniLocations.fColorFilterUni = kUseUniform; fUniLocations.fColorFilterUni = kUseUniform;
} }
bool wroteFragColorZero = false; bool wroteFragColorZero = false;
if (SkXfermode::kZero_Coeff == uniformCoeff && if (SkXfermode::kZero_Coeff == uniformCoeff &&
@ -753,7 +736,7 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
colorOutput.getName().c_str(), colorOutput.getName().c_str(),
all_zeros_vec(4)); all_zeros_vec(4));
wroteFragColorZero = true; wroteFragColorZero = true;
} else if (SkXfermode::kDst_Mode != fProgramDesc.fColorFilterXfermode) { } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) {
builder.fFSCode.append("\tvec4 filteredColor;\n"); builder.fFSCode.append("\tvec4 filteredColor;\n");
const char* color = adjustInColor(inColor); const char* color = adjustInColor(inColor);
addColorFilter(&builder.fFSCode, "filteredColor", uniformCoeff, addColorFilter(&builder.fFSCode, "filteredColor", uniformCoeff,
@ -765,8 +748,8 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
kMat44f_GrSLType, COL_MATRIX_UNI_NAME); kMat44f_GrSLType, COL_MATRIX_UNI_NAME);
builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType, builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType,
kVec4f_GrSLType, COL_MATRIX_VEC_UNI_NAME); kVec4f_GrSLType, COL_MATRIX_VEC_UNI_NAME);
programData->fUniLocations.fColorMatrixUni = kUseUniform; fUniLocations.fColorMatrixUni = kUseUniform;
programData->fUniLocations.fColorMatrixVecUni = kUseUniform; fUniLocations.fColorMatrixVecUni = kUseUniform;
builder.fFSCode.append("\tvec4 matrixedColor;\n"); builder.fFSCode.append("\tvec4 matrixedColor;\n");
const char* color = adjustInColor(inColor); const char* color = adjustInColor(inColor);
addColorMatrix(&builder.fFSCode, "matrixedColor", color); addColorMatrix(&builder.fFSCode, "matrixedColor", color);
@ -777,34 +760,32 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
// compute the partial coverage (coverage stages and edge aa) // compute the partial coverage (coverage stages and edge aa)
SkString inCoverage; SkString inCoverage;
bool coverageIsZero = ProgramDesc::kTransBlack_ColorInput == bool coverageIsZero = Desc::kTransBlack_ColorInput == fDesc.fCoverageInput;
fProgramDesc.fCoverageInput;
// we don't need to compute coverage at all if we know the final shader // 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. // output will be zero and we don't have a dual src blend output.
if (!wroteFragColorZero || if (!wroteFragColorZero || Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) {
if (!coverageIsZero) { if (!coverageIsZero) {
this->genEdgeCoverage(gl, layout, programData, &inCoverage, &builder); this->genEdgeCoverage(gl, &inCoverage, &builder);
switch (fProgramDesc.fCoverageInput) { switch (fDesc.fCoverageInput) {
case ProgramDesc::kSolidWhite_ColorInput: case Desc::kSolidWhite_ColorInput:
// empty string implies solid white // empty string implies solid white
break; break;
case ProgramDesc::kAttribute_ColorInput: case Desc::kAttribute_ColorInput:
genAttributeCoverage(&builder, &inCoverage); gen_attribute_coverage(&builder, &inCoverage);
break; break;
case ProgramDesc::kUniform_ColorInput: case Desc::kUniform_ColorInput:
genUniformCoverage(&builder, programData, &inCoverage); this->genUniformCoverage(&builder, &inCoverage);
break; break;
default: default:
GrCrash("Unexpected input coverage."); GrCrash("Unexpected input coverage.");
} }
SkString outCoverage; SkString outCoverage;
const int& startStage = fProgramDesc.fFirstCoverageStage; const int& startStage = fDesc.fFirstCoverageStage;
for (int s = startStage; s < GrDrawState::kNumStages; ++s) { for (int s = startStage; s < GrDrawState::kNumStages; ++s) {
if (fProgramDesc.fStages[s].isEnabled()) { if (fDesc.fStages[s].isEnabled()) {
// create var to hold stage output // create var to hold stage output
outCoverage = "coverage"; outCoverage = "coverage";
outCoverage.appendS32(s); outCoverage.appendS32(s);
@ -825,37 +806,31 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
} }
if (NULL != customStages[s]) { if (NULL != customStages[s]) {
const GrProgramStageFactory& factory = const GrProgramStageFactory& factory = customStages[s]->getFactory();
customStages[s]->getFactory(); fProgramStage[s] = factory.createGLInstance(*customStages[s]);
programData->fCustomStage[s] =
factory.createGLInstance(*customStages[s]);
} }
this->genStageCode(gl, s, this->genStageCode(gl,
fProgramDesc.fStages[s], s,
inCoverage.size() ? inCoverage.c_str() : NULL, inCoverage.size() ? inCoverage.c_str() : NULL,
outCoverage.c_str(), outCoverage.c_str(),
inCoords, inCoords,
&builder, &builder);
&programData->fUniLocations.fStages[s],
programData->fCustomStage[s]);
inCoverage = outCoverage; inCoverage = outCoverage;
} }
} }
} }
if (ProgramDesc::kNone_DualSrcOutput != fProgramDesc.fDualSrcOutput) { if (Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
builder.fFSOutputs.push_back().set(kVec4f_GrSLType, builder.fFSOutputs.push_back().set(kVec4f_GrSLType,
GrGLShaderVar::kOut_TypeModifier, GrGLShaderVar::kOut_TypeModifier,
dual_source_output_name()); dual_source_output_name());
bool outputIsZero = coverageIsZero; bool outputIsZero = coverageIsZero;
SkString coeff; SkString coeff;
if (!outputIsZero && if (!outputIsZero &&
ProgramDesc::kCoverage_DualSrcOutput != Desc::kCoverage_DualSrcOutput != fDesc.fDualSrcOutput && !wroteFragColorZero) {
fProgramDesc.fDualSrcOutput && !wroteFragColorZero) {
if (!inColor.size()) { if (!inColor.size()) {
outputIsZero = true; outputIsZero = true;
} else { } else {
if (fProgramDesc.fDualSrcOutput == if (Desc::kCoverageISA_DualSrcOutput == fDesc.fDualSrcOutput) {
ProgramDesc::kCoverageISA_DualSrcOutput) {
coeff.printf("(1 - %s.a)", inColor.c_str()); coeff.printf("(1 - %s.a)", inColor.c_str());
} else { } else {
coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str()); coeff.printf("(vec4(1,1,1,1) - %s)", inColor.c_str());
@ -890,16 +865,14 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
inCoverage.c_str(), inCoverage.c_str(),
&builder.fFSCode); &builder.fFSCode);
} }
if (ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig == if (Desc::kUnpremultiplied_RoundDown_OutputConfig == fDesc.fOutputConfig) {
fProgramDesc.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", 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(), 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 == } else if (Desc::kUnpremultiplied_RoundUp_OutputConfig == fDesc.fOutputConfig) {
fProgramDesc.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", 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(),
colorOutput.getName().c_str(), colorOutput.getName().c_str(),
@ -921,132 +894,124 @@ bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// compile and setup attribs and unis // compile and setup attribs and unis
if (!compile_shaders(gl, builder, programData)) { if (!this->compileShaders(gl, builder)) {
return false; return false;
} }
if (!this->bindOutputsAttribsAndLinkProgram(gl, texCoordAttrs, if (!this->bindOutputsAttribsAndLinkProgram(gl,
texCoordAttrs,
isColorDeclared, isColorDeclared,
dualSourceOutputWritten, dualSourceOutputWritten)) {
programData)) {
return false; return false;
} }
this->getUniformLocationsAndInitCache(builder, gl, programData); this->getUniformLocationsAndInitCache(gl, builder);
return true; return true;
} }
bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLContextInfo& gl, bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLContextInfo& gl,
SkString texCoordAttrNames[], SkString texCoordAttrNames[],
bool bindColorOut, bool bindColorOut,
bool bindDualSrcOut, bool bindDualSrcOut) {
CachedData* programData) const { GL_CALL_RET(fProgramID, CreateProgram());
GL_CALL_RET(programData->fProgramID, CreateProgram()); if (!fProgramID) {
if (!programData->fProgramID) {
return false; return false;
} }
const GrGLint& progID = programData->fProgramID;
GL_CALL(AttachShader(progID, programData->fVShaderID)); GL_CALL(AttachShader(fProgramID, fVShaderID));
if (programData->fGShaderID) { if (fGShaderID) {
GL_CALL(AttachShader(progID, programData->fGShaderID)); GL_CALL(AttachShader(fProgramID, fGShaderID));
} }
GL_CALL(AttachShader(progID, programData->fFShaderID)); GL_CALL(AttachShader(fProgramID, fFShaderID));
if (bindColorOut) { if (bindColorOut) {
GL_CALL(BindFragDataLocation(programData->fProgramID, GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name()));
0, declared_color_output_name()));
} }
if (bindDualSrcOut) { if (bindDualSrcOut) {
GL_CALL(BindFragDataLocationIndexed(programData->fProgramID, GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name()));
0, 1, dual_source_output_name()));
} }
// Bind the attrib locations to same values for all shaders // 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) { for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
if (texCoordAttrNames[t].size()) { if (texCoordAttrNames[t].size()) {
GL_CALL(BindAttribLocation(progID, GL_CALL(BindAttribLocation(fProgramID,
TexCoordAttributeIdx(t), TexCoordAttributeIdx(t),
texCoordAttrNames[t].c_str())); texCoordAttrNames[t].c_str()));
} }
} }
GL_CALL(BindAttribLocation(progID, ColorAttributeIdx(), COL_ATTR_NAME)); GL_CALL(BindAttribLocation(fProgramID, ColorAttributeIdx(), COL_ATTR_NAME));
GL_CALL(BindAttribLocation(progID, CoverageAttributeIdx(), COV_ATTR_NAME)); GL_CALL(BindAttribLocation(fProgramID, CoverageAttributeIdx(), COV_ATTR_NAME));
GL_CALL(BindAttribLocation(progID, EdgeAttributeIdx(), EDGE_ATTR_NAME)); GL_CALL(BindAttribLocation(fProgramID, EdgeAttributeIdx(), EDGE_ATTR_NAME));
GL_CALL(LinkProgram(progID)); GL_CALL(LinkProgram(fProgramID));
GrGLint linked = GR_GL_INIT_ZERO; 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) { if (!linked) {
GrGLint infoLen = GR_GL_INIT_ZERO; 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 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
if (infoLen > 0) { if (infoLen > 0) {
// retrieve length even though we don't need it to workaround // retrieve length even though we don't need it to workaround
// bug in chrome cmd buffer param validation. // bug in chrome cmd buffer param validation.
GrGLsizei length = GR_GL_INIT_ZERO; GrGLsizei length = GR_GL_INIT_ZERO;
GL_CALL(GetProgramInfoLog(progID, GL_CALL(GetProgramInfoLog(fProgramID,
infoLen+1, infoLen+1,
&length, &length,
(char*)log.get())); (char*)log.get()));
GrPrintf((char*)log.get()); GrPrintf((char*)log.get());
} }
GrAssert(!"Error linking program"); GrAssert(!"Error linking program");
GL_CALL(DeleteProgram(progID)); GL_CALL(DeleteProgram(fProgramID));
programData->fProgramID = 0; fProgramID = 0;
return false; return false;
} }
return true; return true;
} }
void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& builder, void GrGLProgram::getUniformLocationsAndInitCache(const GrGLContextInfo& gl,
const GrGLContextInfo& gl, const GrGLShaderBuilder& builder) {
CachedData* programData) const {
const GrGLint& progID = programData->fProgramID;
if (kUseUniform == programData->fUniLocations.fViewMatrixUni) { if (kUseUniform == fUniLocations.fViewMatrixUni) {
GL_CALL_RET(programData->fUniLocations.fViewMatrixUni, GL_CALL_RET(fUniLocations.fViewMatrixUni, GetUniformLocation(fProgramID, VIEW_MATRIX_NAME));
GetUniformLocation(progID, VIEW_MATRIX_NAME)); GrAssert(kUnusedUniform != fUniLocations.fViewMatrixUni);
GrAssert(kUnusedUniform != programData->fUniLocations.fViewMatrixUni);
} }
if (kUseUniform == programData->fUniLocations.fColorUni) { if (kUseUniform == fUniLocations.fColorUni) {
GL_CALL_RET(programData->fUniLocations.fColorUni, GL_CALL_RET(fUniLocations.fColorUni, GetUniformLocation(fProgramID, COL_UNI_NAME));
GetUniformLocation(progID, COL_UNI_NAME)); GrAssert(kUnusedUniform != fUniLocations.fColorUni);
GrAssert(kUnusedUniform != programData->fUniLocations.fColorUni);
} }
if (kUseUniform == programData->fUniLocations.fColorFilterUni) { if (kUseUniform == fUniLocations.fColorFilterUni) {
GL_CALL_RET(programData->fUniLocations.fColorFilterUni, GL_CALL_RET(fUniLocations.fColorFilterUni,
GetUniformLocation(progID, COL_FILTER_UNI_NAME)); GetUniformLocation(fProgramID, COL_FILTER_UNI_NAME));
GrAssert(kUnusedUniform != programData->fUniLocations.fColorFilterUni); GrAssert(kUnusedUniform != fUniLocations.fColorFilterUni);
} }
if (kUseUniform == programData->fUniLocations.fColorMatrixUni) { if (kUseUniform == fUniLocations.fColorMatrixUni) {
GL_CALL_RET(programData->fUniLocations.fColorMatrixUni, GL_CALL_RET(fUniLocations.fColorMatrixUni,
GetUniformLocation(progID, COL_MATRIX_UNI_NAME)); GetUniformLocation(fProgramID, COL_MATRIX_UNI_NAME));
GrAssert(kUnusedUniform != fUniLocations.fColorMatrixUni);
} }
if (kUseUniform == programData->fUniLocations.fColorMatrixVecUni) { if (kUseUniform == fUniLocations.fColorMatrixVecUni) {
GL_CALL_RET(programData->fUniLocations.fColorMatrixVecUni, GL_CALL_RET(fUniLocations.fColorMatrixVecUni,
GetUniformLocation(progID, COL_MATRIX_VEC_UNI_NAME)); GetUniformLocation(fProgramID, COL_MATRIX_VEC_UNI_NAME));
GrAssert(kUnusedUniform != fUniLocations.fColorMatrixVecUni);
} }
if (kUseUniform == programData->fUniLocations.fCoverageUni) { if (kUseUniform == fUniLocations.fCoverageUni) {
GL_CALL_RET(programData->fUniLocations.fCoverageUni, GrAssert(kUnusedUniform != fUniLocations.fCoverageUni);
GetUniformLocation(progID, COV_UNI_NAME));
GrAssert(kUnusedUniform != programData->fUniLocations.fCoverageUni);
} }
for (int s = 0; s < GrDrawState::kNumStages; ++s) { for (int s = 0; s < GrDrawState::kNumStages; ++s) {
StageUniLocations& locations = programData->fUniLocations.fStages[s]; StageUniLocations& locations = fUniLocations.fStages[s];
if (fProgramDesc.fStages[s].isEnabled()) { if (fDesc.fStages[s].isEnabled()) {
if (kUseUniform == locations.fTextureMatrixUni) { if (kUseUniform == locations.fTextureMatrixUni) {
SkString texMName; SkString texMName;
tex_matrix_name(s, &texMName); tex_matrix_name(s, &texMName);
GL_CALL_RET(locations.fTextureMatrixUni, GL_CALL_RET(locations.fTextureMatrixUni,
GetUniformLocation(progID, texMName.c_str())); GetUniformLocation(fProgramID, texMName.c_str()));
GrAssert(kUnusedUniform != locations.fTextureMatrixUni); GrAssert(kUnusedUniform != locations.fTextureMatrixUni);
} }
@ -1054,7 +1019,7 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& build
SkString samplerName; SkString samplerName;
sampler_name(s, &samplerName); sampler_name(s, &samplerName);
GL_CALL_RET(locations.fSamplerUni, GL_CALL_RET(locations.fSamplerUni,
GetUniformLocation(progID,samplerName.c_str())); GetUniformLocation(fProgramID,samplerName.c_str()));
GrAssert(kUnusedUniform != locations.fSamplerUni); GrAssert(kUnusedUniform != locations.fSamplerUni);
} }
@ -1062,33 +1027,32 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& build
SkString texDomName; SkString texDomName;
tex_domain_name(s, &texDomName); tex_domain_name(s, &texDomName);
GL_CALL_RET(locations.fTexDomUni, GL_CALL_RET(locations.fTexDomUni,
GetUniformLocation(progID, texDomName.c_str())); GetUniformLocation(fProgramID, texDomName.c_str()));
GrAssert(kUnusedUniform != locations.fTexDomUni); GrAssert(kUnusedUniform != locations.fTexDomUni);
} }
if (NULL != programData->fCustomStage[s]) { if (NULL != fProgramStage[s]) {
programData->fCustomStage[s]->initUniforms(&builder, gl.interface(), progID); 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 // init sampler unis and set bogus values for state tracking
for (int s = 0; s < GrDrawState::kNumStages; ++s) { for (int s = 0; s < GrDrawState::kNumStages; ++s) {
if (kUnusedUniform != programData->fUniLocations.fStages[s].fSamplerUni) { if (kUnusedUniform != fUniLocations.fStages[s].fSamplerUni) {
GL_CALL(Uniform1i(programData->fUniLocations.fStages[s].fSamplerUni, s)); GL_CALL(Uniform1i(fUniLocations.fStages[s].fSamplerUni, s));
} }
programData->fTextureMatrices[s] = GrMatrix::InvalidMatrix(); fTextureMatrices[s] = GrMatrix::InvalidMatrix();
programData->fTextureDomain[s].setEmpty(); fTextureDomain[s].setEmpty();
// this is arbitrary, just initialize to something // this is arbitrary, just initialize to something
programData->fTextureOrientation[s] = fTextureOrientation[s] = GrGLTexture::kBottomUp_Orientation;
GrGLTexture::kBottomUp_Orientation;
// Must not reset fStageOverride[] here. // Must not reset fStageOverride[] here.
} }
programData->fViewMatrix = GrMatrix::InvalidMatrix(); fViewMatrix = GrMatrix::InvalidMatrix();
programData->fViewportSize.set(-1, -1); fViewportSize.set(-1, -1);
programData->fColor = GrColor_ILLEGAL; fColor = GrColor_ILLEGAL;
programData->fColorFilterColor = GrColor_ILLEGAL; fColorFilterColor = GrColor_ILLEGAL;
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -1096,17 +1060,17 @@ void GrGLProgram::getUniformLocationsAndInitCache(const GrGLShaderBuilder& build
void GrGLProgram::genStageCode(const GrGLContextInfo& gl, void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
int stageNum, int stageNum,
const GrGLProgram::StageDesc& desc,
const char* fsInColor, // NULL means no incoming color const char* fsInColor, // NULL means no incoming color
const char* fsOutColor, const char* fsOutColor,
const char* vsInCoord, const char* vsInCoord,
GrGLShaderBuilder* segments, GrGLShaderBuilder* segments) {
StageUniLocations* locations,
GrGLProgramStage* customStage) const {
GrAssert(stageNum >= 0 && stageNum <= GrDrawState::kNumStages); 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 /// Vertex Shader Stuff
@ -1124,7 +1088,7 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
const GrGLShaderVar& mat = segments->getUniformVariable(m); const GrGLShaderVar& mat = segments->getUniformVariable(m);
// Can't use texMatName.c_str() because it's on the stack! // Can't use texMatName.c_str() because it's on the stack!
matName = mat.getName().c_str(); matName = mat.getName().c_str();
locations->fTextureMatrixUni = kUseUniform; locations.fTextureMatrixUni = kUseUniform;
if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) { if (desc.fOptFlags & StageDesc::kNoPerspective_OptFlagBit) {
segments->fVaryingDims = segments->fCoordDims; segments->fVaryingDims = segments->fCoordDims;
@ -1143,14 +1107,14 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
sampler_name(stageNum, &samplerName); sampler_name(stageNum, &samplerName);
segments->addUniform(GrGLShaderBuilder::kFragment_ShaderType, segments->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
kSampler2D_GrSLType, samplerName.c_str()); kSampler2D_GrSLType, samplerName.c_str());
locations->fSamplerUni = kUseUniform; locations.fSamplerUni = kUseUniform;
const char *varyingVSName, *varyingFSName; const char *varyingVSName, *varyingFSName;
segments->addVarying(GrSLFloatVectorType(segments->fVaryingDims), segments->addVarying(GrSLFloatVectorType(segments->fVaryingDims),
"Stage", "Stage",
stageNum, stageNum,
&varyingVSName, &varyingVSName,
&varyingFSName); &varyingFSName);
if (!matName) { if (!matName) {
GrAssert(segments->fVaryingDims == segments->fCoordDims); GrAssert(segments->fVaryingDims == segments->fCoordDims);
@ -1203,7 +1167,7 @@ void GrGLProgram::genStageCode(const GrGLContextInfo& gl,
texDomainName.c_str(), texDomainName.c_str(),
texDomainName.c_str()); texDomainName.c_str());
segments->fSampleCoords = coordVar; segments->fSampleCoords = coordVar;
locations->fTexDomUni = kUseUniform; locations.fTexDomUni = kUseUniform;
} }
// NOTE: GrGLProgramStages are now responsible for fetching // NOTE: GrGLProgramStages are now responsible for fetching

Просмотреть файл

@ -13,7 +13,7 @@
#include "GrGLContextInfo.h" #include "GrGLContextInfo.h"
#include "GrGLSL.h" #include "GrGLSL.h"
#include "GrGLTexture.h" #include "GrGLTexture.h"
#include "GrGpu.h" //#include "GrGpu.h"
#include "SkString.h" #include "SkString.h"
#include "SkXfermode.h" #include "SkXfermode.h"
@ -35,28 +35,29 @@ class GrGLShaderBuilder;
* Uniforms are program-local so we can't rely on fHWState to hold the * Uniforms are program-local so we can't rely on fHWState to hold the
* previous uniform state after a program change. * previous uniform state after a program change.
*/ */
class GrGLProgram { class GrGLProgram : public GrRefCnt {
public: public:
SK_DECLARE_INST_COUNT(GrGLProgram)
class CachedData; struct Desc;
GrGLProgram(); GrGLProgram();
~GrGLProgram(); virtual ~GrGLProgram();
/** /**
* This is the heavy initilization routine for building a GLProgram. * 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, bool genProgram(const GrGLContextInfo& gl,
GrCustomStage** customStages, const Desc& desc,
CachedData* programData) const; GrCustomStage** customStages);
/** /**
* The shader may modify the blend coeffecients. Params are in/out * The shader may modify the blend coeffecients. Params are in/out
*/ */
void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const; void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const;
const Desc& getDesc() { return fDesc; }
/** /**
* Attribute indices. These should not overlap. Matrices consume 3 slots. * Attribute indices. These should not overlap. Matrices consume 3 slots.
*/ */
@ -75,16 +76,23 @@ public:
return 7 + GrDrawState::kMaxTexCoords + 3 * stage; return 7 + GrDrawState::kMaxTexCoords + 3 * stage;
} }
public: enum {
kUnusedUniform = -1,
};
// Parameters that affect code generation // Parameters that affect code generation
// These structs should be kept compact; they are the input to an // These structs should be kept compact; they are the input to an
// expensive hash key generator. // expensive hash key generator.
struct ProgramDesc { struct Desc {
ProgramDesc() { Desc() {
// since we use this as part of a key we can't have any unitialized // since we use this as part of a key we can't have any unitialized
// padding // 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 { enum OutputConfig {
@ -224,23 +232,46 @@ public:
uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode
int8_t fPadding[1]; int8_t fPadding[1];
};
} fProgramDesc; GR_STATIC_ASSERT(!(sizeof(Desc) % 4));
GR_STATIC_ASSERT(!(sizeof(ProgramDesc) % 4));
// for code readability // for code readability
typedef ProgramDesc::StageDesc StageDesc; typedef Desc::StageDesc StageDesc;
private: private:
void genInputColor(GrGLShaderBuilder* builder, SkString* inColor);
// 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);
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 ProgramDesc& getDesc() { return fProgramDesc; }
const char* adjustInColor(const SkString& inColor) const; const char* adjustInColor(const SkString& inColor) const;
public:
enum {
kUnusedUniform = -1,
};
struct StageUniLocations { struct StageUniLocations {
GrGLint fTextureMatrixUni; GrGLint fTextureMatrixUni;
GrGLint fSamplerUni; GrGLint fSamplerUni;
@ -273,104 +304,37 @@ public:
} }
}; };
class CachedData : public ::GrNoncopyable { // IDs
public: GrGLuint fVShaderID;
CachedData() { GrGLuint fGShaderID;
for (int i = 0; i < GrDrawState::kNumStages; ++i) { GrGLuint fFShaderID;
fCustomStage[i] = NULL; GrGLuint fProgramID;
} // shader uniform locations (-1 if shader doesn't use them)
} UniLocations fUniLocations;
~CachedData(); // The matrix sent to GL is determined by both the client's matrix and
// the size of the viewport.
GrMatrix fViewMatrix;
SkISize fViewportSize;
void copyAndTakeOwnership(CachedData& other) { // these reflect the current values of uniforms
memcpy(this, &other, sizeof(*this)); // (GL uniform values travel with program)
for (int i = 0; i < GrDrawState::kNumStages; ++i) { GrColor fColor;
other.fCustomStage[i] = NULL; 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];
public: GrGLProgramStage* fProgramStage[GrDrawState::kNumStages];
// IDs Desc fDesc;
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 friend class GrGpuGL; // TODO: remove this by adding getters and moving functionality.
// the size of the viewport.
GrMatrix fViewMatrix;
SkISize fViewportSize;
// these reflect the current values of uniforms typedef GrRefCnt INHERITED;
// (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;
}; };
#endif #endif

Просмотреть файл

@ -175,7 +175,6 @@ GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) {
this->initCaps(); this->initCaps();
fProgramData = NULL;
fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContextInfo())); fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContextInfo()));
fLastSuccessfulStencilFmtIdx = 0; fLastSuccessfulStencilFmtIdx = 0;
@ -186,16 +185,14 @@ GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) {
} }
GrGpuGL::~GrGpuGL() { GrGpuGL::~GrGpuGL() {
if (fProgramData && 0 != fHWProgramID) { if (0 != fHWProgramID) {
// detach the current program so there is no confusion on OpenGL's part // detach the current program so there is no confusion on OpenGL's part
// that we want it to be deleted // that we want it to be deleted
GrAssert(fHWProgramID == fProgramData->fProgramID); GrAssert(fHWProgramID == fCurrentProgram->fProgramID);
GL_CALL(UseProgram(0)); GL_CALL(UseProgram(0));
} }
delete fProgramCache; delete fProgramCache;
fProgramCache = NULL;
fProgramData = NULL;
// This must be called by before the GrDrawTarget destructor // This must be called by before the GrDrawTarget destructor
this->releaseGeometry(); this->releaseGeometry();

Просмотреть файл

@ -162,9 +162,8 @@ private:
static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff); static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
// for readability of function impls // for readability of function impls
typedef GrGLProgram::ProgramDesc ProgramDesc; typedef GrGLProgram::Desc ProgramDesc;
typedef ProgramDesc::StageDesc StageDesc; typedef ProgramDesc::StageDesc StageDesc;
typedef GrGLProgram::CachedData CachedData;
class ProgramCache : public ::GrNoncopyable { class ProgramCache : public ::GrNoncopyable {
public: public:
@ -172,31 +171,37 @@ private:
~ProgramCache(); ~ProgramCache();
void abandon(); void abandon();
CachedData* getProgramData(const GrGLProgram& desc, GrGLProgram* getProgram(const GrGLProgram::Desc& desc, GrCustomStage** stages);
GrCustomStage** stages);
private: private:
enum { enum {
kKeySize = GrGLProgram::kProgramKeySize, kKeySize = sizeof(ProgramDesc),
// We may actually have kMaxEntries+1 shaders in the GL context // We may actually have kMaxEntries+1 shaders in the GL context because we create a new
// because we create a new shader before evicting from the cache. // shader before evicting from the cache.
kMaxEntries = 32 kMaxEntries = 32
}; };
class Entry; class Entry;
typedef GrBinHashKey<Entry, kKeySize> ProgramHashKey; // The value of the hash key is based on the ProgramDesc.
typedef GrTBinHashKey<Entry, kKeySize> ProgramHashKey;
class Entry : public ::GrNoncopyable { class Entry : public ::GrNoncopyable {
public: public:
Entry() {} Entry() : fProgram(NULL), fLRUStamp(0) {}
void copyAndTakeOwnership(Entry& entry); Entry& operator = (const Entry& entry) {
GrSafeRef(entry.fProgram.get());
fProgram.reset(entry.fProgram.get());
fKey = entry.fKey;
fLRUStamp = entry.fLRUStamp;
return *this;
}
int compare(const ProgramHashKey& key) const { int compare(const ProgramHashKey& key) const {
return fKey.compare(key); return fKey.compare(key);
} }
public: public:
CachedData fProgramData; SkAutoTUnref<GrGLProgram> fProgram;
ProgramHashKey fKey; ProgramHashKey fKey;
unsigned int fLRUStamp; unsigned int fLRUStamp; // Move outside entry?
}; };
GrTHashTable<Entry, ProgramHashKey, 8> fHashCache; GrTHashTable<Entry, ProgramHashKey, 8> fHashCache;
@ -243,13 +248,13 @@ private:
// flushing the scissor after that function is called. // flushing the scissor after that function is called.
void flushScissor(); void flushScissor();
static void DeleteProgram(const GrGLInterface* gl, static void DeleteProgram(const GrGLInterface* gl, GrGLProgram* programData);
CachedData* programData);
void buildProgram(bool isPoints, void buildProgram(bool isPoints,
BlendOptFlags blendOpts, BlendOptFlags blendOpts,
GrBlendCoeff dstCoeff, GrBlendCoeff dstCoeff,
GrCustomStage** customStages); GrCustomStage** customStages,
ProgramDesc* desc);
// Inits GrDrawTarget::Caps, sublcass may enable additional caps. // Inits GrDrawTarget::Caps, sublcass may enable additional caps.
void initCaps(); void initCaps();
@ -304,8 +309,7 @@ private:
// GL program-related state // GL program-related state
ProgramCache* fProgramCache; ProgramCache* fProgramCache;
CachedData* fProgramData; SkAutoTUnref<GrGLProgram> fCurrentProgram;
GrGLProgram fCurrentProgram;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
///@name Caching of GL State ///@name Caching of GL State

Просмотреть файл

@ -14,12 +14,6 @@
#define SKIP_CACHE_CHECK true #define SKIP_CACHE_CHECK true
#define GR_UINT32_MAX static_cast<uint32_t>(-1) #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) GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl)
: fCount(0) : fCount(0)
, fCurrLRUStamp(0) , fCurrLRUStamp(0)
@ -28,8 +22,7 @@ GrGpuGL::ProgramCache::ProgramCache(const GrGLContextInfo& gl)
GrGpuGL::ProgramCache::~ProgramCache() { GrGpuGL::ProgramCache::~ProgramCache() {
for (int i = 0; i < fCount; ++i) { for (int i = 0; i < fCount; ++i) {
GrGpuGL::DeleteProgram(fGL.interface(), GrGpuGL::DeleteProgram(fGL.interface(), fEntries[i].fProgram);
&fEntries[i].fProgramData);
} }
} }
@ -37,15 +30,14 @@ void GrGpuGL::ProgramCache::abandon() {
fCount = 0; fCount = 0;
} }
GrGLProgram::CachedData* GrGpuGL::ProgramCache::getProgramData( GrGLProgram* GrGpuGL::ProgramCache::getProgram(const ProgramDesc& desc, GrCustomStage** stages) {
const GrGLProgram& desc,
GrCustomStage** stages) {
Entry newEntry; Entry newEntry;
newEntry.fKey.setKeyData(desc.keyData()); newEntry.fKey.setKeyData(desc.asKey());
Entry* entry = fHashCache.find(newEntry.fKey); Entry* entry = fHashCache.find(newEntry.fKey);
if (NULL == entry) { if (NULL == entry) {
if (!desc.genProgram(fGL, stages, &newEntry.fProgramData)) { newEntry.fProgram.reset(SkNEW(GrGLProgram));
if (!newEntry.fProgram->genProgram(fGL, desc, stages)) {
return NULL; return NULL;
} }
if (fCount < kMaxEntries) { if (fCount < kMaxEntries) {
@ -60,10 +52,9 @@ GrGLProgram::CachedData* GrGpuGL::ProgramCache::getProgramData(
} }
} }
fHashCache.remove(entry->fKey, entry); fHashCache.remove(entry->fKey, entry);
GrGpuGL::DeleteProgram(fGL.interface(), GrGpuGL::DeleteProgram(fGL.interface(), entry->fProgram);
&entry->fProgramData);
} }
entry->copyAndTakeOwnership(newEntry); *entry = newEntry;
fHashCache.insert(entry->fKey, entry); fHashCache.insert(entry->fKey, entry);
} }
@ -75,21 +66,20 @@ GrGLProgram::CachedData* GrGpuGL::ProgramCache::getProgramData(
} }
} }
++fCurrLRUStamp; ++fCurrLRUStamp;
return &entry->fProgramData; return entry->fProgram;
} }
void GrGpuGL::DeleteProgram(const GrGLInterface* gl, void GrGpuGL::DeleteProgram(const GrGLInterface* gl, GrGLProgram* program) {
CachedData* programData) { GR_GL_CALL(gl, DeleteShader(program->fVShaderID));
GR_GL_CALL(gl, DeleteShader(programData->fVShaderID)); if (program->fGShaderID) {
if (programData->fGShaderID) { GR_GL_CALL(gl, DeleteShader(program->fGShaderID));
GR_GL_CALL(gl, DeleteShader(programData->fGShaderID));
} }
GR_GL_CALL(gl, DeleteShader(programData->fFShaderID)); GR_GL_CALL(gl, DeleteShader(program->fFShaderID));
GR_GL_CALL(gl, DeleteProgram(programData->fProgramID)); GR_GL_CALL(gl, DeleteProgram(program->fProgramID));
GR_DEBUGCODE(programData->fVShaderID = 0); GR_DEBUGCODE(program->fVShaderID = 0);
GR_DEBUGCODE(programData->fGShaderID = 0); GR_DEBUGCODE(program->fGShaderID = 0);
GR_DEBUGCODE(programData->fFShaderID = 0); GR_DEBUGCODE(program->fFShaderID = 0);
GR_DEBUGCODE(programData->fProgramID = 0); GR_DEBUGCODE(program->fProgramID = 0);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -150,8 +140,8 @@ void GrGpuGL::flushViewMatrix(DrawType type) {
fHWPathMatrixState.fViewMatrix = vm; fHWPathMatrixState.fViewMatrix = vm;
fHWPathMatrixState.fRTSize = viewportSize; fHWPathMatrixState.fRTSize = viewportSize;
} }
} else if (!fProgramData->fViewMatrix.cheapEqualTo(vm) || } else if (!fCurrentProgram->fViewMatrix.cheapEqualTo(vm) ||
fProgramData->fViewportSize != viewportSize) { fCurrentProgram->fViewportSize != viewportSize) {
GrMatrix m; GrMatrix m;
m.setAll( m.setAll(
GrIntToScalar(2) / viewportSize.fWidth, 0, -GR_Scalar1, GrIntToScalar(2) / viewportSize.fWidth, 0, -GR_Scalar1,
@ -174,11 +164,11 @@ void GrGpuGL::flushViewMatrix(DrawType type) {
}; };
GrAssert(GrGLProgram::kUnusedUniform != GrAssert(GrGLProgram::kUnusedUniform !=
fProgramData->fUniLocations.fViewMatrixUni); fCurrentProgram->fUniLocations.fViewMatrixUni);
GL_CALL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni, GL_CALL(UniformMatrix3fv(fCurrentProgram->fUniLocations.fViewMatrixUni,
1, false, mt)); 1, false, mt));
fProgramData->fViewMatrix = vm; fCurrentProgram->fViewMatrix = vm;
fProgramData->fViewportSize = viewportSize; fCurrentProgram->fViewportSize = viewportSize;
} }
} }
@ -225,13 +215,13 @@ void GrGpuGL::flushTextureMatrixAndDomain(int s) {
static_cast<const GrGLTexture*>(drawState.getTexture(s)); static_cast<const GrGLTexture*>(drawState.getTexture(s));
if (NULL != texture) { if (NULL != texture) {
bool orientationChange = fProgramData->fTextureOrientation[s] != bool orientationChange = fCurrentProgram->fTextureOrientation[s] !=
texture->orientation(); texture->orientation();
const GrGLint& matrixUni = 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(); const GrMatrix& samplerMatrix = drawState.getSampler(s).getMatrix();
if (GrGLProgram::kUnusedUniform != matrixUni && if (GrGLProgram::kUnusedUniform != matrixUni &&
@ -255,16 +245,15 @@ void GrGpuGL::flushTextureMatrixAndDomain(int s) {
}; };
GL_CALL(UniformMatrix3fv(matrixUni, 1, false, mt)); GL_CALL(UniformMatrix3fv(matrixUni, 1, false, mt));
fProgramData->fTextureMatrices[s] = samplerMatrix; fCurrentProgram->fTextureMatrices[s] = samplerMatrix;
} }
const GrGLint& domUni = const GrGLint& domUni = fCurrentProgram->fUniLocations.fStages[s].fTexDomUni;
fProgramData->fUniLocations.fStages[s].fTexDomUni;
const GrRect &texDom = drawState.getSampler(s).getTextureDomain(); const GrRect &texDom = drawState.getSampler(s).getTextureDomain();
if (GrGLProgram::kUnusedUniform != domUni && 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] = { float values[4] = {
GrScalarToFloat(texDom.left()), GrScalarToFloat(texDom.left()),
@ -283,15 +272,14 @@ void GrGpuGL::flushTextureMatrixAndDomain(int s) {
} }
GL_CALL(Uniform4fv(domUni, 1, values)); GL_CALL(Uniform4fv(domUni, 1, values));
} }
fProgramData->fTextureOrientation[s] = texture->orientation(); fCurrentProgram->fTextureOrientation[s] = texture->orientation();
} }
} }
void GrGpuGL::flushColorMatrix() { void GrGpuGL::flushColorMatrix() {
// const ProgramDesc& desc = fCurrentProgram.getDesc(); int matrixUni = fCurrentProgram->fUniLocations.fColorMatrixUni;
int matrixUni = fProgramData->fUniLocations.fColorMatrixUni; int vecUni = fCurrentProgram->fUniLocations.fColorMatrixVecUni;
int vecUni = fProgramData->fUniLocations.fColorMatrixVecUni;
if (GrGLProgram::kUnusedUniform != matrixUni if (GrGLProgram::kUnusedUniform != matrixUni
&& GrGLProgram::kUnusedUniform != vecUni) { && GrGLProgram::kUnusedUniform != vecUni) {
const float* m = this->getDrawState().getColorMatrix(); const float* m = this->getDrawState().getColorMatrix();
@ -320,7 +308,7 @@ static const float ONE_OVER_255 = 1.f / 255.f;
} }
void GrGpuGL::flushColor(GrColor color) { void GrGpuGL::flushColor(GrColor color) {
const ProgramDesc& desc = fCurrentProgram.getDesc(); const ProgramDesc& desc = fCurrentProgram->getDesc();
const GrDrawState& drawState = this->getDrawState(); const GrDrawState& drawState = this->getDrawState();
if (this->getVertexLayout() & kColor_VertexLayoutBit) { if (this->getVertexLayout() & kColor_VertexLayoutBit) {
@ -340,15 +328,14 @@ void GrGpuGL::flushColor(GrColor color) {
} }
break; break;
case ProgramDesc::kUniform_ColorInput: case ProgramDesc::kUniform_ColorInput:
if (fProgramData->fColor != color) { if (fCurrentProgram->fColor != color) {
// OpenGL ES doesn't support unsigned byte varieties of // OpenGL ES doesn't support unsigned byte varieties of
// glUniform // glUniform
float c[] = GR_COLOR_TO_VEC4(color); float c[] = GR_COLOR_TO_VEC4(color);
GrAssert(GrGLProgram::kUnusedUniform != GrAssert(GrGLProgram::kUnusedUniform !=
fProgramData->fUniLocations.fColorUni); fCurrentProgram->fUniLocations.fColorUni);
GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorUni, GL_CALL(Uniform4fv(fCurrentProgram->fUniLocations.fColorUni, 1, c));
1, c)); fCurrentProgram->fColor = color;
fProgramData->fColor = color;
} }
break; break;
case ProgramDesc::kSolidWhite_ColorInput: case ProgramDesc::kSolidWhite_ColorInput:
@ -358,18 +345,18 @@ void GrGpuGL::flushColor(GrColor color) {
GrCrash("Unknown color type."); GrCrash("Unknown color type.");
} }
} }
if (fProgramData->fUniLocations.fColorFilterUni if (fCurrentProgram->fUniLocations.fColorFilterUni
!= GrGLProgram::kUnusedUniform != GrGLProgram::kUnusedUniform
&& fProgramData->fColorFilterColor && fCurrentProgram->fColorFilterColor
!= drawState.getColorFilterColor()) { != drawState.getColorFilterColor()) {
float c[] = GR_COLOR_TO_VEC4(drawState.getColorFilterColor()); float c[] = GR_COLOR_TO_VEC4(drawState.getColorFilterColor());
GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c)); GL_CALL(Uniform4fv(fCurrentProgram->fUniLocations.fColorFilterUni, 1, c));
fProgramData->fColorFilterColor = drawState.getColorFilterColor(); fCurrentProgram->fColorFilterColor = drawState.getColorFilterColor();
} }
} }
void GrGpuGL::flushCoverage(GrColor coverage) { void GrGpuGL::flushCoverage(GrColor coverage) {
const ProgramDesc& desc = fCurrentProgram.getDesc(); const ProgramDesc& desc = fCurrentProgram->getDesc();
// const GrDrawState& drawState = this->getDrawState(); // const GrDrawState& drawState = this->getDrawState();
@ -390,15 +377,14 @@ void GrGpuGL::flushCoverage(GrColor coverage) {
} }
break; break;
case ProgramDesc::kUniform_ColorInput: case ProgramDesc::kUniform_ColorInput:
if (fProgramData->fCoverage != coverage) { if (fCurrentProgram->fCoverage != coverage) {
// OpenGL ES doesn't support unsigned byte varieties of // OpenGL ES doesn't support unsigned byte varieties of
// glUniform // glUniform
float c[] = GR_COLOR_TO_VEC4(coverage); float c[] = GR_COLOR_TO_VEC4(coverage);
GrAssert(GrGLProgram::kUnusedUniform != GrAssert(GrGLProgram::kUnusedUniform !=
fProgramData->fUniLocations.fCoverageUni); fCurrentProgram->fUniLocations.fCoverageUni);
GL_CALL(Uniform4fv(fProgramData->fUniLocations.fCoverageUni, GL_CALL(Uniform4fv(fCurrentProgram->fUniLocations.fCoverageUni, 1, c));
1, c)); fCurrentProgram->fCoverage = coverage;
fProgramData->fCoverage = coverage;
} }
break; break;
case ProgramDesc::kSolidWhite_ColorInput: case ProgramDesc::kSolidWhite_ColorInput:
@ -428,20 +414,21 @@ bool GrGpuGL::flushGraphicsState(DrawType type) {
} }
GrCustomStage* customStages [GrDrawState::kNumStages]; GrCustomStage* customStages [GrDrawState::kNumStages];
this->buildProgram(kDrawPoints_DrawType == type, GrGLProgram::Desc desc;
blendOpts, dstCoeff, customStages); this->buildProgram(kDrawPoints_DrawType == type, blendOpts, dstCoeff, customStages, &desc);
fProgramData = fProgramCache->getProgramData(fCurrentProgram,
customStages); fCurrentProgram.reset(fProgramCache->getProgram(desc, customStages));
if (NULL == fProgramData) { if (NULL == fCurrentProgram.get()) {
GrAssert(!"Failed to create program!"); GrAssert(!"Failed to create program!");
return false; return false;
} }
fCurrentProgram.get()->ref();
if (fHWProgramID != fProgramData->fProgramID) { if (fHWProgramID != fCurrentProgram->fProgramID) {
GL_CALL(UseProgram(fProgramData->fProgramID)); GL_CALL(UseProgram(fCurrentProgram->fProgramID));
fHWProgramID = fProgramData->fProgramID; fHWProgramID = fCurrentProgram->fProgramID;
} }
fCurrentProgram.overrideBlend(&srcCoeff, &dstCoeff); fCurrentProgram->overrideBlend(&srcCoeff, &dstCoeff);
this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff); this->flushBlend(kDrawLines_DrawType == type, srcCoeff, dstCoeff);
GrColor color; GrColor color;
@ -472,16 +459,13 @@ bool GrGpuGL::flushGraphicsState(DrawType type) {
this->flushTextureMatrixAndDomain(s); this->flushTextureMatrixAndDomain(s);
if (NULL != fProgramData->fCustomStage[s]) { if (NULL != fCurrentProgram->fProgramStage[s]) {
const GrSamplerState& sampler = const GrSamplerState& sampler = this->getDrawState().getSampler(s);
this->getDrawState().getSampler(s); const GrGLTexture* texture = static_cast<const GrGLTexture*>(
const GrGLTexture* texture = this->getDrawState().getTexture(s));
static_cast<const GrGLTexture*>( fCurrentProgram->fProgramStage[s]->setData(this->glInterface(),
this->getDrawState().getTexture(s)); *sampler.getCustomStage(),
fProgramData->fCustomStage[s]->setData( drawState.getRenderTarget(), s);
this->glInterface(),
*sampler.getCustomStage(),
drawState.getRenderTarget(), s);
} }
} }
} }
@ -658,7 +642,7 @@ void GrGpuGL::setupGeometry(int* startVertex,
namespace { namespace {
void setup_custom_stage(GrGLProgram::ProgramDesc::StageDesc* stage, void setup_custom_stage(GrGLProgram::Desc::StageDesc* stage,
const GrSamplerState& sampler, const GrSamplerState& sampler,
GrCustomStage** customStages, GrCustomStage** customStages,
GrGLProgram* program, int index) { GrGLProgram* program, int index) {
@ -678,8 +662,8 @@ void setup_custom_stage(GrGLProgram::ProgramDesc::StageDesc* stage,
void GrGpuGL::buildProgram(bool isPoints, void GrGpuGL::buildProgram(bool isPoints,
BlendOptFlags blendOpts, BlendOptFlags blendOpts,
GrBlendCoeff dstCoeff, GrBlendCoeff dstCoeff,
GrCustomStage** customStages) { GrCustomStage** customStages,
ProgramDesc& desc = fCurrentProgram.fProgramDesc; ProgramDesc* desc) {
const GrDrawState& drawState = this->getDrawState(); const GrDrawState& drawState = this->getDrawState();
// This should already have been caught // This should already have been caught
@ -696,31 +680,31 @@ void GrGpuGL::buildProgram(bool isPoints,
// to a canonical value to avoid duplicate programs with different keys. // to a canonical value to avoid duplicate programs with different keys.
// Must initialize all fields or cache will have false negatives! // 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 = bool requiresAttributeColors =
!skipColor && SkToBool(desc.fVertexLayout & kColor_VertexLayoutBit); !skipColor && SkToBool(desc->fVertexLayout & kColor_VertexLayoutBit);
bool requiresAttributeCoverage = bool requiresAttributeCoverage =
!skipCoverage && SkToBool(desc.fVertexLayout & !skipCoverage && SkToBool(desc->fVertexLayout &
kCoverage_VertexLayoutBit); kCoverage_VertexLayoutBit);
// fColorInput/fCoverageInput records how colors are specified for the. // fColorInput/fCoverageInput records how colors are specified for the.
// program. So we strip the bits from the layout to avoid false negatives // program. So we strip the bits from the layout to avoid false negatives
// when searching for an existing program in the cache. // 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 : SkXfermode::kDst_Mode :
drawState.getColorFilterMode(); 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 // no reason to do edge aa or look at per-vertex coverage if coverage is
// ignored // ignored
if (skipCoverage) { if (skipCoverage) {
desc.fVertexLayout &= ~(kEdge_VertexLayoutBit | desc->fVertexLayout &= ~(kEdge_VertexLayoutBit |
kCoverage_VertexLayoutBit); kCoverage_VertexLayoutBit);
} }
@ -729,40 +713,40 @@ void GrGpuGL::buildProgram(bool isPoints,
(!requiresAttributeColors && (!requiresAttributeColors &&
0xffffffff == drawState.getColor()); 0xffffffff == drawState.getColor());
if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) { if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) {
desc.fColorInput = ProgramDesc::kTransBlack_ColorInput; desc->fColorInput = ProgramDesc::kTransBlack_ColorInput;
} else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) { } 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) { } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeColors) {
desc.fColorInput = ProgramDesc::kUniform_ColorInput; desc->fColorInput = ProgramDesc::kUniform_ColorInput;
} else { } else {
desc.fColorInput = ProgramDesc::kAttribute_ColorInput; desc->fColorInput = ProgramDesc::kAttribute_ColorInput;
} }
bool covIsSolidWhite = !requiresAttributeCoverage && bool covIsSolidWhite = !requiresAttributeCoverage &&
0xffffffff == drawState.getCoverage(); 0xffffffff == drawState.getCoverage();
if (skipCoverage) { if (skipCoverage) {
desc.fCoverageInput = ProgramDesc::kTransBlack_ColorInput; desc->fCoverageInput = ProgramDesc::kTransBlack_ColorInput;
} else if (covIsSolidWhite) { } else if (covIsSolidWhite) {
desc.fCoverageInput = ProgramDesc::kSolidWhite_ColorInput; desc->fCoverageInput = ProgramDesc::kSolidWhite_ColorInput;
} else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) { } else if (GR_GL_NO_CONSTANT_ATTRIBUTES && !requiresAttributeCoverage) {
desc.fCoverageInput = ProgramDesc::kUniform_ColorInput; desc->fCoverageInput = ProgramDesc::kUniform_ColorInput;
} else { } else {
desc.fCoverageInput = ProgramDesc::kAttribute_ColorInput; desc->fCoverageInput = ProgramDesc::kAttribute_ColorInput;
} }
int lastEnabledStage = -1; int lastEnabledStage = -1;
if (!skipCoverage && (desc.fVertexLayout & if (!skipCoverage && (desc->fVertexLayout &
GrDrawTarget::kEdge_VertexLayoutBit)) { GrDrawTarget::kEdge_VertexLayoutBit)) {
desc.fVertexEdgeType = drawState.getVertexEdgeType(); desc->fVertexEdgeType = drawState.getVertexEdgeType();
} else { } else {
// use canonical value when not set to avoid cache misses // 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) { for (int s = 0; s < GrDrawState::kNumStages; ++s) {
StageDesc& stage = desc.fStages[s]; StageDesc& stage = desc->fStages[s];
stage.fOptFlags = 0; stage.fOptFlags = 0;
stage.setEnabled(this->isStageEnabled(s)); stage.setEnabled(this->isStageEnabled(s));
@ -825,8 +809,7 @@ void GrGpuGL::buildProgram(bool isPoints,
} }
} }
setup_custom_stage(&stage, sampler, customStages, setup_custom_stage(&stage, sampler, customStages, fCurrentProgram.get(), s);
&fCurrentProgram, s);
} else { } else {
stage.fOptFlags = 0; stage.fOptFlags = 0;
@ -841,23 +824,23 @@ void GrGpuGL::buildProgram(bool isPoints,
// when rounding. // when rounding.
GrAssert(4 == GrBytesPerPixel(drawState.getRenderTarget()->config())); GrAssert(4 == GrBytesPerPixel(drawState.getRenderTarget()->config()));
if (kUpOnWrite_DownOnRead_UnpremulConversion == fUnpremulConversion) { if (kUpOnWrite_DownOnRead_UnpremulConversion == fUnpremulConversion) {
desc.fOutputConfig = desc->fOutputConfig =
ProgramDesc::kUnpremultiplied_RoundUp_OutputConfig; ProgramDesc::kUnpremultiplied_RoundUp_OutputConfig;
} else { } else {
desc.fOutputConfig = desc->fOutputConfig =
ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig; ProgramDesc::kUnpremultiplied_RoundDown_OutputConfig;
} }
} else { } 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 // currently the experimental GS will only work with triangle prims
// (and it doesn't do anything other than pass through values from // (and it doesn't do anything other than pass through values from
// the VS to the FS anyway). // the VS to the FS anyway).
#if 0 && GR_GL_EXPERIMENTAL_GS #if 0 && GR_GL_EXPERIMENTAL_GS
desc.fExperimentalGS = this->getCaps().fGeometryShaderSupport; desc->fExperimentalGS = this->getCaps().fGeometryShaderSupport;
#endif #endif
// we want to avoid generating programs with different "first cov stage" // we want to avoid generating programs with different "first cov stage"
@ -866,7 +849,7 @@ void GrGpuGL::buildProgram(bool isPoints,
// coverage stages or the distinction between coverage and color is // coverage stages or the distinction between coverage and color is
// immaterial. // immaterial.
int firstCoverageStage = GrDrawState::kNumStages; int firstCoverageStage = GrDrawState::kNumStages;
desc.fFirstCoverageStage = GrDrawState::kNumStages; desc->fFirstCoverageStage = GrDrawState::kNumStages;
bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage; bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage;
if (hasCoverage) { if (hasCoverage) {
firstCoverageStage = drawState.getFirstCoverageStage(); firstCoverageStage = drawState.getFirstCoverageStage();
@ -876,13 +859,13 @@ void GrGpuGL::buildProgram(bool isPoints,
if (!hasCoverage) { if (!hasCoverage) {
hasCoverage = hasCoverage =
requiresAttributeCoverage || requiresAttributeCoverage ||
(desc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit); (desc->fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit);
} }
if (hasCoverage) { if (hasCoverage) {
// color filter is applied between color/coverage computation // color filter is applied between color/coverage computation
if (SkXfermode::kDst_Mode != desc.fColorFilterXfermode) { if (SkXfermode::kDst_Mode != desc->fColorFilterXfermode) {
desc.fFirstCoverageStage = firstCoverageStage; desc->fFirstCoverageStage = firstCoverageStage;
} }
if (this->getCaps().fDualSourceBlendingSupport && if (this->getCaps().fDualSourceBlendingSupport &&
@ -890,18 +873,18 @@ void GrGpuGL::buildProgram(bool isPoints,
kCoverageAsAlpha_BlendOptFlag))) { kCoverageAsAlpha_BlendOptFlag))) {
if (kZero_GrBlendCoeff == dstCoeff) { if (kZero_GrBlendCoeff == dstCoeff) {
// write the coverage value to second color // write the coverage value to second color
desc.fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput; desc->fDualSrcOutput = ProgramDesc::kCoverage_DualSrcOutput;
desc.fFirstCoverageStage = firstCoverageStage; desc->fFirstCoverageStage = firstCoverageStage;
} else if (kSA_GrBlendCoeff == dstCoeff) { } else if (kSA_GrBlendCoeff == dstCoeff) {
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
// cover // cover
desc.fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput; desc->fDualSrcOutput = ProgramDesc::kCoverageISA_DualSrcOutput;
desc.fFirstCoverageStage = firstCoverageStage; desc->fFirstCoverageStage = firstCoverageStage;
} else if (kSC_GrBlendCoeff == dstCoeff) { } else if (kSC_GrBlendCoeff == dstCoeff) {
// SA dst coeff becomes 1-(1-SA)*coverage when dst is partially // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially
// cover // cover
desc.fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput; desc->fDualSrcOutput = ProgramDesc::kCoverageISC_DualSrcOutput;
desc.fFirstCoverageStage = firstCoverageStage; desc->fFirstCoverageStage = firstCoverageStage;
} }
} }
} }

Просмотреть файл

@ -231,8 +231,6 @@ bool GrGpuGL::programUnitTest() {
StageDesc::kSmearAlpha_InConfigFlag, StageDesc::kSmearAlpha_InConfigFlag,
StageDesc::kSmearRed_InConfigFlag, StageDesc::kSmearRed_InConfigFlag,
}; };
GrGLProgram program;
ProgramDesc& pdesc = program.fProgramDesc;
static const int NUM_TESTS = 512; static const int NUM_TESTS = 512;
@ -247,6 +245,7 @@ bool GrGpuGL::programUnitTest() {
} }
#endif #endif
ProgramDesc pdesc;
pdesc.fVertexLayout = 0; pdesc.fVertexLayout = 0;
pdesc.fEmitsPointSize = random.nextF() > .5f; pdesc.fEmitsPointSize = random.nextF() > .5f;
pdesc.fColorInput = random_int(&random, ProgramDesc::kColorInputCnt); pdesc.fColorInput = random_int(&random, ProgramDesc::kColorInputCnt);
@ -317,14 +316,15 @@ bool GrGpuGL::programUnitTest() {
} }
} }
} }
CachedData cachedData;
GR_STATIC_ASSERT(sizeof(customStages) == GR_STATIC_ASSERT(sizeof(customStages) ==
GrDrawState::kNumStages * sizeof(GrCustomStage*)); GrDrawState::kNumStages * sizeof(GrCustomStage*));
GrCustomStage** stages = reinterpret_cast<GrCustomStage**>(&customStages); GrCustomStage** stages = reinterpret_cast<GrCustomStage**>(&customStages);
if (!program.genProgram(this->glContextInfo(), stages, &cachedData)) { SkAutoTUnref<GrGLProgram> program(SkNEW(GrGLProgram));
if (!program->genProgram(this->glContextInfo(), pdesc, stages)) {
return false; return false;
} }
DeleteProgram(this->glInterface(), &cachedData); DeleteProgram(this->glInterface(), program);
} }
return true; return true;
} }

Просмотреть файл

@ -87,10 +87,10 @@ static void test_binHashKey()
kDataLenUsedForKey = 8 kDataLenUsedForKey = 8
}; };
GrBinHashKey<BogusEntry, kDataLenUsedForKey> keyA; GrTBinHashKey<BogusEntry, kDataLenUsedForKey> keyA;
keyA.setKeyData(testStringA); keyA.setKeyData(testStringA);
// test copy constructor and comparison // test copy constructor and comparison
GrBinHashKey<BogusEntry, kDataLenUsedForKey> keyA2(keyA); GrTBinHashKey<BogusEntry, kDataLenUsedForKey> keyA2(keyA);
GrAssert(keyA.compare(keyA2) == 0); GrAssert(keyA.compare(keyA2) == 0);
GrAssert(keyA.getHash() == keyA2.getHash()); GrAssert(keyA.getHash() == keyA2.getHash());
// test re-init // test re-init
@ -98,7 +98,7 @@ static void test_binHashKey()
GrAssert(keyA.compare(keyA2) == 0); GrAssert(keyA.compare(keyA2) == 0);
GrAssert(keyA.getHash() == keyA2.getHash()); GrAssert(keyA.getHash() == keyA2.getHash());
// test sorting // test sorting
GrBinHashKey<BogusEntry, kDataLenUsedForKey> keyB; GrTBinHashKey<BogusEntry, kDataLenUsedForKey> keyB;
keyB.setKeyData(testStringB); keyB.setKeyData(testStringB);
GrAssert(keyA.compare(keyB) < 0); GrAssert(keyA.compare(keyB) < 0);
GrAssert(keyA.getHash() != keyB.getHash()); GrAssert(keyA.getHash() != keyB.getHash());