Hooks up the GrCustomStage/GrGLProgramStageFactory/GrGLProgramStage
classes from r3726 so they can be used. Does not implement any actual
effect stages.
Has one large known bug: if custom stages are provided, GrSamplerState
comparisons will break; this should preserve correct drawing, but decrease
performance - among other things, we'll break draw batching. To fix this
we'll need a RTTI system for GrCustomState objects, and we'll need to change
the GrSamplerState comparison from a memcmp to something that also does a
deep type-sensitive compare of any GrCustomState objects present.
http://codereview.appspot.com/6074043/
git-svn-id: http://skia.googlecode.com/svn/trunk@3742 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 16a60ce..fb98b4d 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -10,6 +10,8 @@
#include "GrGLProgram.h"
#include "../GrAllocator.h"
+#include "GrCustomStage.h"
+#include "GrGLProgramStage.h"
#include "GrGLShaderVar.h"
#include "SkTrace.h"
#include "SkXfermode.h"
@@ -620,8 +622,17 @@
}
}
+// 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];
+ }
+}
+
bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
+ GrCustomStage** customStages,
GrGLProgram::CachedData* programData) const {
ShaderCodeSegments segments;
@@ -733,6 +744,21 @@
}
///////////////////////////////////////////////////////////////////////////
+ // Convert generic effect representation to GL-specific backend so they
+ // can be accesseed in genStageCode() and in subsequent uses of
+ // programData.
+ for (int s = 0; s < GrDrawState::kNumStages; ++s) {
+ GrCustomStage* customStage = customStages[s];
+ if (NULL != customStage) {
+ GrGLProgramStageFactory* factory = customStage->getGLFactory();
+ programData->fCustomStage[s] =
+ factory->createGLInstance(customStage);
+ } else {
+ programData->fCustomStage[s] = NULL;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
// compute the final color
// if we have color stages string them together, feeding the output color
@@ -766,7 +792,8 @@
outColor.c_str(),
inCoords,
&segments,
- &programData->fUniLocations.fStages[s]);
+ &programData->fUniLocations.fStages[s],
+ programData->fCustomStage[s]);
inColor = outColor;
}
}
@@ -878,13 +905,14 @@
inCoords = texCoordAttrs[tcIdx].c_str();
}
- genStageCode(gl, s,
- fProgramDesc.fStages[s],
- inCoverage.size() ? inCoverage.c_str() : NULL,
- outCoverage.c_str(),
- inCoords,
- &segments,
- &programData->fUniLocations.fStages[s]);
+ this->genStageCode(gl, s,
+ fProgramDesc.fStages[s],
+ inCoverage.size() ? inCoverage.c_str() : NULL,
+ outCoverage.c_str(),
+ inCoords,
+ &segments,
+ &programData->fUniLocations.fStages[s],
+ programData->fCustomStage[s]);
inCoverage = outCoverage;
}
}
@@ -1348,6 +1376,11 @@
imageIncrementName.c_str()));
GrAssert(kUnusedUniform != locations.fImageIncrementUni);
}
+
+ if (NULL != programData->fCustomStage[s]) {
+ programData->fCustomStage[s]->
+ initUniforms(gl.interface(), progID);
+ }
}
}
GL_CALL(UseProgram(progID));
@@ -1363,6 +1396,7 @@
programData->fTextureWidth[s] = -1;
programData->fTextureHeight[s] = -1;
programData->fTextureDomain[s].setEmpty();
+ // Must not reset fStageOverride[] here.
}
programData->fViewMatrix = GrMatrix::InvalidMatrix();
programData->fColor = GrColor_ILLEGAL;
@@ -1712,7 +1746,8 @@
const char* fsOutColor,
const char* vsInCoord,
ShaderCodeSegments* segments,
- StageUniLocations* locations) const {
+ StageUniLocations* locations,
+ GrGLProgramStage* customStage) const {
GrAssert(stageNum >= 0 && stageNum <= GrDrawState::kNumStages);
GrAssert((desc.fInConfigFlags & StageDesc::kInConfigBitMask) ==
@@ -1723,8 +1758,13 @@
// gradients.
static const int coordDims = 2;
int varyingDims;
+
/// Vertex Shader Stuff
+ if (NULL != customStage) {
+ customStage->setupVSUnis(segments->fVSUnis, stageNum);
+ }
+
// decide whether we need a matrix to transform texture coords
// and whether the varying needs a perspective coord.
const char* matName = NULL;
@@ -1808,7 +1848,20 @@
&imageIncrementName, varyingVSName);
}
+ if (NULL != customStage) {
+ GrStringBuilder vertexShader;
+ customStage->emitVS(&vertexShader, varyingVSName);
+ segments->fVSCode.appendf("{\n");
+ segments->fVSCode.append(vertexShader);
+ segments->fVSCode.appendf("}\n");
+ }
+
/// Fragment Shader Stuff
+
+ if (NULL != customStage) {
+ customStage->setupFSUnis(segments->fFSUnis, stageNum);
+ }
+
GrStringBuilder fsCoordName;
// function used to access the shader, may be made projective
GrStringBuilder texFunc("texture2D");
@@ -1959,6 +2012,31 @@
swizzle, modulate.c_str());
}
}
+
+ if (NULL != customStage) {
+ if (desc.fOptFlags & (StageDesc::kIdentityMatrix_OptFlagBit |
+ StageDesc::kNoPerspective_OptFlagBit)) {
+ customStage->setSamplerMode(GrGLProgramStage::kDefault_SamplerMode);
+ } else if (StageDesc::kIdentity_CoordMapping == desc.fCoordMapping &&
+ StageDesc::kSingle_FetchMode == desc.fFetchMode) {
+ customStage->setSamplerMode(GrGLProgramStage::kProj_SamplerMode);
+ } else {
+ customStage->setSamplerMode(
+ GrGLProgramStage::kExplicitDivide_SamplerMode);
+ }
+
+ GrStringBuilder fragmentShader;
+ fsCoordName = customStage->emitTextureSetup(
+ &fragmentShader, varyingFSName,
+ stageNum, coordDims, varyingDims);
+ customStage->emitFS(&fragmentShader, fsOutColor, fsInColor,
+ samplerName, fsCoordName.c_str());
+
+ // Enclose custom code in a block to avoid namespace conflicts
+ segments->fFSCode.appendf("{\n");
+ segments->fFSCode.append(fragmentShader);
+ segments->fFSCode.appendf("}\n");
+ }
}