'<(skia_src_path)/gpu/gl/GrGLProgram.h',
'<(skia_src_path)/gpu/gl/GrGLProgramDesc.cpp',
'<(skia_src_path)/gpu/gl/GrGLProgramDesc.h',
+ '<(skia_src_path)/gpu/gl/GrGLProgramEffects.cpp',
+ '<(skia_src_path)/gpu/gl/GrGLProgramEffects.h',
'<(skia_src_path)/gpu/gl/GrGLProgramDataManager.cpp',
'<(skia_src_path)/gpu/gl/GrGLProgramDataManager.h',
'<(skia_src_path)/gpu/gl/GrGLRenderTarget.cpp',
'<(skia_src_path)/gpu/gl/GrGpuGL_program.cpp',
# Files for building GLSL shaders
- '<(skia_src_path)/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp',
- '<(skia_src_path)/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h',
- '<(skia_src_path)/gpu/gl/builders/GrGLNvprProgramBuilder.cpp',
- '<(skia_src_path)/gpu/gl/builders/GrGLNvprProgramBuilder.h',
- '<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.cpp',
- '<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.h',
+ '<(skia_src_path)/gpu/gl/builders/GrGLSLPrettyPrint.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLShaderBuilder.h',
+ '<(skia_src_path)/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.cpp',
+ '<(skia_src_path)/gpu/gl/builders/GrGLFragmentOnlyProgramBuilder.h',
+ '<(skia_src_path)/gpu/gl/builders/GrGLFullProgramBuilder.cpp',
+ '<(skia_src_path)/gpu/gl/builders/GrGLFullProgramBuilder.h',
+ '<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.cpp',
+ '<(skia_src_path)/gpu/gl/builders/GrGLProgramBuilder.h',
'<(skia_src_path)/gpu/gl/builders/GrGLShaderStringBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLShaderStringBuilder.h',
- '<(skia_src_path)/gpu/gl/builders/GrGLSLPrettyPrint.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLVertexShaderBuilder.cpp',
'<(skia_src_path)/gpu/gl/builders/GrGLVertexShaderBuilder.h',
'<(skia_src_path)/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp',
if (!fp->willUseInputColor()) {
fColorStages.reset();
}
- SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (fp));
+ SkNEW_APPEND_TO_TARRAY(&fColorStages, GrProcessorStage, (fp));
return fp;
}
if (!fp->willUseInputColor()) {
fCoverageStages.reset();
}
- SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrFragmentStage, (fp));
+ SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrProcessorStage, (fp));
return fp;
}
fCoordChangeMatrixSet = false;
}
- virtual ~GrProcessorStage() {}
-
GrProcessorStage(const GrProcessorStage& other) {
fCoordChangeMatrixSet = other.fCoordChangeMatrixSet;
if (other.fCoordChangeMatrixSet) {
}
}
- virtual const GrProcessor* getProcessor() const = 0;
+ const GrProcessor* getProcessor() const { return fProc.get(); }
void convertToPendingExec() { fProc.convertToPendingExec(); }
-protected:
+private:
bool fCoordChangeMatrixSet;
SkMatrix fCoordChangeMatrix;
GrProgramElementRef<const GrProcessor> fProc;
public:
GrFragmentStage(const GrFragmentProcessor* fp) : GrProcessorStage(fp) {}
- virtual const GrFragmentProcessor* getProcessor() const {
- return static_cast<const GrFragmentProcessor*>(fProc.get());
+ const GrFragmentProcessor* getFragmentProcessor() const {
+ return static_cast<const GrFragmentProcessor*>(this->getProcessor());
}
-
- typedef GrFragmentProcessor Processor;
- typedef GrGLFragmentProcessor GLProcessor;
};
class GrGeometryStage : public GrProcessorStage {
public:
GrGeometryStage(const GrGeometryProcessor* gp) : GrProcessorStage(gp) {}
- virtual const GrGeometryProcessor* getProcessor() const {
- return static_cast<const GrGeometryProcessor*>(fProc.get());
+ const GrGeometryProcessor* getGeometryProcessor() const {
+ return static_cast<const GrGeometryProcessor*>(this->getProcessor());
}
-
- typedef GrGeometryProcessor Processor;
- typedef GrGLGeometryProcessor GLProcessor;
};
#endif
#define GrTBackendProcessorFactory_DEFINED
#include "GrBackendProcessorFactory.h"
+#include "gl/GrGLProgramEffects.h"
/**
* Implements GrBackendEffectFactory for a GrProcessor subclass as a singleton. This can be used by
#include "SkStrokeRec.h"
#include "SkTraceEvent.h"
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLGeometryProcessor.h"
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
const char *vsName, *fsName;
builder->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName);
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
const GrShaderVar& inQuadEdge = geometryProcessor.cast<QuadEdgeEffect>().inQuadEdge();
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("\t%s = %s;\n", vsName, inQuadEdge.c_str());
}
#include "GrAARectRenderer.h"
#include "GrGpu.h"
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLGeometryProcessor.h"
#include "GrTBackendProcessorFactory.h"
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
builder->addVarying(kVec4f_GrSLType, "Rect", &vsRectName, &fsRectName);
const GrShaderVar& inRect = geometryProcessor.cast<GrAlignedRectEffect>().inRect();
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("\t%s = %s;\n", vsRectName, inRect.c_str());
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
// TODO: compute all these offsets, spans, and scales in the VS
fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.z) - 0.5;\n", fsRectName);
fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.w) - 0.5;\n", fsRectName);
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
&vsRectEdgeName, &fsRectEdgeName);
const GrRectEffect& rectEffect = geometryProcessor.cast<GrRectEffect>();
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("%s = %s;", vsRectEdgeName, rectEffect.inRectEdge().c_str());
// setup the varying for width/2+.5 and height/2+.5
vsWidthHeightName,
rectEffect.inWidthHeight().c_str());
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
// TODO: compute all these offsets, spans, and scales in the VS
fsBuilder->codeAppendf("\tfloat insetW = min(1.0, %s.x) - 0.5;\n", fsWidthHeightName);
fsBuilder->codeAppendf("\tfloat insetH = min(1.0, %s.y) - 0.5;\n", fsWidthHeightName);
if (this->hasGeometryProcessor()) {
const GrGeometryStage& stage = *this->getGeometryProcessor();
- const GrGeometryProcessor* gp = stage.getProcessor();
+ const GrGeometryProcessor* gp = stage.getGeometryProcessor();
SkASSERT(gp);
// make sure that any attribute indices have the correct binding type, that the attrib
// type and effect's shader lang type are compatible, and that attributes shared by
// Run through the coverage stages and see if the coverage will be all ones at the end.
if (this->hasGeometryProcessor()) {
- const GrGeometryProcessor* gp = fGeometryProcessor->getProcessor();
+ const GrGeometryProcessor* gp = fGeometryProcessor->getGeometryProcessor();
gp->computeInvariantOutput(&inout);
}
for (int s = 0; s < this->numCoverageStages(); ++s) {
bool GrDrawState::willEffectReadDstColor() const {
if (!this->isColorWriteDisabled()) {
for (int s = 0; s < this->numColorStages(); ++s) {
- if (this->getColorStage(s).getProcessor()->willReadDstColor()) {
+ if (this->getColorStage(s).getFragmentProcessor()->willReadDstColor()) {
return true;
}
}
}
for (int s = 0; s < this->numCoverageStages(); ++s) {
- if (this->getCoverageStage(s).getProcessor()->willReadDstColor()) {
+ if (this->getCoverageStage(s).getFragmentProcessor()->willReadDstColor()) {
return true;
}
}
SkASSERT(drawState.getRenderTarget());
if (drawState.hasGeometryProcessor()) {
- const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getProcessor();
+ const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getGeometryProcessor();
int numTextures = gp->numTextures();
for (int t = 0; t < numTextures; ++t) {
GrTexture* texture = gp->texture(t);
}
for (int i = 0; i < ds.numColorStages(); ++i) {
- const GrFragmentProcessor* fp = ds.getColorStage(i).getProcessor();
+ const GrFragmentProcessor* fp = ds.getColorStage(i).getFragmentProcessor();
if (!fp->willUseInputColor()) {
firstColorStage = i;
fInputColorIsUsed = false;
}
static void get_stage_stats(const GrFragmentStage& stage, bool* readsDst, bool* readsFragPosition) {
- if (stage.getProcessor()->willReadDstColor()) {
+ if (stage.getFragmentProcessor()->willReadDstColor()) {
*readsDst = true;
}
- if (stage.getProcessor()->willReadFragmentPosition()) {
+ if (stage.getFragmentProcessor()->willReadFragmentPosition()) {
*readsFragPosition = true;
}
}
#include "GrOvalRenderer.h"
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLGeometryProcessor.h"
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
const char *vsName, *fsName;
builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName);
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();;
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();;
vsBuilder->codeAppendf("\t%s = %s;\n", vsName, circleEffect.inCircleEdge().c_str());
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("\tfloat d = length(%s.xy);\n", fsName);
fsBuilder->codeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0);\n", fsName);
if (circleEffect.isStroked()) {
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
builder->addVarying(kVec2f_GrSLType, "EllipseOffsets", &vsOffsetName, &fsOffsetName);
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("%s = %s;", vsOffsetName,
ellipseEffect.inEllipseOffset().c_str());
vsBuilder->codeAppendf("%s = %s;", vsRadiiName, ellipseEffect.inEllipseRadii().c_str());
// for outer curve
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("\tvec2 scaledOffset = %s*%s.xy;\n", fsOffsetName, fsRadiiName);
fsBuilder->codeAppend("\tfloat test = dot(scaledOffset, scaledOffset) - 1.0;\n");
fsBuilder->codeAppendf("\tvec2 grad = 2.0*scaledOffset*%s.xy;\n", fsRadiiName);
GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
builder->addVarying(kVec2f_GrSLType, "EllipseOffsets0",
&vsOffsetName0, &fsOffsetName0);
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("%s = %s;", vsOffsetName0,
ellipseEffect.inEllipseOffsets0().c_str());
const char *vsOffsetName1, *fsOffsetName1;
vsBuilder->codeAppendf("\t%s = %s;\n", vsOffsetName1,
ellipseEffect.inEllipseOffsets1().c_str());
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
// for outer curve
#include "GrBezierEffect.h"
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLGeometryProcessor.h"
public:
GrGLConicEffect(const GrBackendProcessorFactory&, const GrProcessor&);
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
fEdgeType = ce.getEdgeType();
}
-void GrGLConicEffect::emitCode(GrGLGPBuilder* builder,
+void GrGLConicEffect::emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
&vsName, &fsName);
const GrShaderVar& inConicCoeffs = geometryProcessor.cast<GrConicEffect>().inConicCoeffs();
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("%s = %s;", vsName, inConicCoeffs.c_str());
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppend("float edgeAlpha;");
switch (fEdgeType) {
public:
GrGLQuadEffect(const GrBackendProcessorFactory&, const GrProcessor&);
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
fEdgeType = ce.getEdgeType();
}
-void GrGLQuadEffect::emitCode(GrGLGPBuilder* builder,
+void GrGLQuadEffect::emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
const char *vsName, *fsName;
builder->addVarying(kVec4f_GrSLType, "HairQuadEdge", &vsName, &fsName);
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
const GrShaderVar& inHairQuadEdge = geometryProcessor.cast<GrQuadEffect>().inHairQuadEdge();
vsBuilder->codeAppendf("%s = %s;", vsName, inHairQuadEdge.c_str());
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("float edgeAlpha;");
switch (fEdgeType) {
public:
GrGLCubicEffect(const GrBackendProcessorFactory&, const GrProcessor&);
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
fEdgeType = ce.getEdgeType();
}
-void GrGLCubicEffect::emitCode(GrGLGPBuilder* builder,
+void GrGLCubicEffect::emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
builder->addVarying(kVec4f_GrSLType, "CubicCoeffs",
&vsName, &fsName, GrGLShaderVar::kHigh_Precision);
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
const GrShaderVar& inCubicCoeffs = geometryProcessor.cast<GrCubicEffect>().inCubicCoeffs();
vsBuilder->codeAppendf("%s = %s;", vsName, inCubicCoeffs.c_str());
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
GrGLShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, GrGLShaderVar::kHigh_Precision);
GrGLShaderVar dklmdx("dklmdx", kVec3f_GrSLType, 0, GrGLShaderVar::kHigh_Precision);
*/
#include "GrCustomCoordsTextureEffect.h"
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLTexture.h"
GrGLCustomCoordsTextureEffect(const GrBackendProcessorFactory& factory, const GrProcessor&)
: INHERITED (factory) {}
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsVaryingName, &fsVaryingNamePtr);
fsCoordName = fsVaryingNamePtr;
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
const GrShaderVar& inTextureCoords = customCoordsTextureEffect.inTextureCoords();
vsBuilder->codeAppendf("\t%s = %s;\n", vsVaryingName, inTextureCoords.c_str());
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("\t%s = ", outputColor);
fsBuilder->appendTextureLookupAndModulate(inputColor,
samplers[0],
#include "../GrAARectRenderer.h"
#include "GrGeometryProcessor.h"
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLGeometryProcessor.h"
#include "gl/GrGLSL.h"
public:
GLDashingCircleEffect(const GrBackendProcessorFactory&, const GrProcessor&);
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
fPrevIntervalLength = SK_ScalarMax;
}
-void GLDashingCircleEffect::emitCode(GrGLGPBuilder* builder,
+void GLDashingCircleEffect::emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
const char *vsCoordName, *fsCoordName;
builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName);
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dce.inCoord().c_str());
// transforms all points so that we can compare them to our test circle
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s.z) * %s.z;\n",
fsCoordName, fsCoordName, paramName, paramName);
fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
public:
GLDashingLineEffect(const GrBackendProcessorFactory&, const GrProcessor&);
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
fPrevIntervalLength = SK_ScalarMax;
}
-void GLDashingLineEffect::emitCode(GrGLGPBuilder* builder,
+void GLDashingLineEffect::emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
const char *vsCoordName, *fsCoordName;
builder->addVarying(kVec2f_GrSLType, "Coord", &vsCoordName, &fsCoordName);
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, de.inCoord().c_str());
// transforms all points so that we can compare them to our test rect
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("\t\tfloat xShifted = %s.x - floor(%s.x / %s) * %s;\n",
fsCoordName, fsCoordName, intervalName, intervalName);
fsBuilder->codeAppendf("\t\tvec2 fragPosShifted = vec2(xShifted, %s.y);\n", fsCoordName);
*/
#include "GrDistanceFieldTextureEffect.h"
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/GrGLProcessor.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLTexture.h"
#endif
{}
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
geometryProcessor.cast<GrDistanceFieldTextureEffect>();
SkASSERT(1 == dfTexEffect.getVertexAttribs().count());
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
fsCoordName = fsCoordNamePtr;
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dfTexEffect.inTextureCoords().c_str());
const char* textureSizeUniName = NULL;
: INHERITED(factory)
, fTextureSize(SkISize::Make(-1, -1)) {}
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& effect,
const GrProcessorKey& key,
const char* outputColor,
effect.cast<GrDistanceFieldNoGammaTextureEffect>();
SkASSERT(1 == dfTexEffect.getVertexAttribs().count());
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
fsCoordName = fsCoordNamePtr;
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("%s = %s;", vsCoordName, dfTexEffect.inTextureCoords().c_str());
const char* textureSizeUniName = NULL;
, fTextureSize(SkISize::Make(-1,-1))
, fTextColor(GrColor_ILLEGAL) {}
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsCoordNamePtr);
fsCoordName = fsCoordNamePtr;
- GrGLVertexBuilder* vsBuilder = builder->getVertexShaderBuilder();
+ GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
vsBuilder->codeAppendf("\t%s = %s;\n", vsCoordName, dfTexEffect.inTextureCoords().c_str());
const char* textureSizeUniName = NULL;
kVec3f_GrSLType, "TextureSize",
&textureSizeUniName);
- GrGLGPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
+ GrGLProcessorFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
* This is similar to emitCode() in the base class, except it takes a full shader builder.
* This allows the effect subclass to emit vertex code.
*/
- virtual void emitCode(GrGLGPBuilder* builder,
+ virtual void emitCode(GrGLFullProgramBuilder* builder,
const GrGeometryProcessor& geometryProcessor,
const GrProcessorKey& key,
const char* outputColor,
#define GrGLProcessor_DEFINED
#include "GrBackendProcessorFactory.h"
-#include "GrGLProgramDataManager.h"
-#include "GrTextureAccess.h"
+#include "GrGLProgramEffects.h"
+#include "GrGLShaderVar.h"
+#include "GrGLSL.h"
/** @file
This file contains specializations for OpenGL of the shader stages declared in
#include "GrGLProgram.h"
+#include "builders/GrGLFullProgramBuilder.h"
+#include "builders/GrGLFragmentOnlyProgramBuilder.h"
#include "GrAllocator.h"
#include "GrProcessor.h"
#include "GrCoordTransform.h"
#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
-/**
- * Retrieves the final matrix that a transform needs to apply to its source coords.
- */
-static SkMatrix get_transform_matrix(const GrProcessorStage& processorStage,
- bool useExplicitLocalCoords,
- int transformIdx) {
- const GrCoordTransform& coordTransform =
- processorStage.getProcessor()->coordTransform(transformIdx);
- SkMatrix combined;
-
- if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
- // If we have explicit local coords then we shouldn't need a coord change.
- const SkMatrix& ccm =
- useExplicitLocalCoords ? SkMatrix::I() : processorStage.getCoordChangeMatrix();
- combined.setConcat(coordTransform.getMatrix(), ccm);
+GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
+ const GrOptDrawState& optState,
+ const GrGLProgramDesc& desc,
+ const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[]) {
+ SkAutoTDelete<GrGLProgramBuilder> builder;
+ if (desc.getHeader().fUseFragShaderOnly) {
+ SkASSERT(gpu->glCaps().pathRenderingSupport());
+ SkASSERT(gpu->glPathRendering()->texturingMode() ==
+ GrGLPathRendering::FixedFunction_TexturingMode);
+ SkASSERT(NULL == geometryProcessor);
+ builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, optState, desc)));
} else {
- combined = coordTransform.getMatrix();
+ builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, optState, desc)));
}
- if (coordTransform.reverseY()) {
- // combined.postScale(1,-1);
- // combined.postTranslate(0,1);
- combined.set(SkMatrix::kMSkewY,
- combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
- combined.set(SkMatrix::kMScaleY,
- combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
- combined.set(SkMatrix::kMTransY,
- combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
+ if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) {
+ SkASSERT(0 != builder->getProgramID());
+ return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder));
}
- return combined;
+ return NULL;
}
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
GrGLProgram::GrGLProgram(GrGpuGL* gpu,
const GrGLProgramDesc& desc,
- const BuiltinUniformHandles& builtinUniforms,
- GrGLuint programID,
- const UniformInfoArray& uniforms,
- GrGLInstalledProcessors* geometryProcessor,
- GrGLInstalledProcessors* colorProcessors,
- GrGLInstalledProcessors* coverageProcessors)
+ const GrGLProgramBuilder& builder)
: fColor(GrColor_ILLEGAL)
, fCoverage(GrColor_ILLEGAL)
, fDstCopyTexUnit(-1)
- , fBuiltinUniformHandles(builtinUniforms)
- , fProgramID(programID)
- , fGeometryProcessor(SkSafeRef(geometryProcessor))
- , fColorEffects(SkRef(colorProcessors))
- , fCoverageEffects(SkRef(coverageProcessors))
+ , fBuiltinUniformHandles(builder.getBuiltinUniformHandles())
+ , fGeometryProcessor(SkSafeRef(builder.getGeometryProcessor()))
+ , fColorEffects(SkRef(builder.getColorEffects()))
+ , fCoverageEffects(SkRef(builder.getCoverageEffects()))
+ , fProgramID(builder.getProgramID())
+ , fHasVertexShader(builder.hasVertexShader())
+ , fTexCoordSetCnt(builder.getTexCoordSetCount())
, fDesc(desc)
, fGpu(gpu)
- , fProgramDataManager(gpu, uniforms) {
+ , fProgramDataManager(gpu, this, builder) {
this->initSamplerUniforms();
}
fDstCopyTexUnit = texUnitIdx++;
}
if (fGeometryProcessor.get()) {
- this->initSamplers(fGeometryProcessor.get(), &texUnitIdx);
- }
- this->initSamplers(fColorEffects.get(), &texUnitIdx);
- this->initSamplers(fCoverageEffects.get(), &texUnitIdx);
-}
-
-void GrGLProgram::initSamplers(GrGLInstalledProcessors* ip, int* texUnitIdx) {
- int numEffects = ip->fGLProcessors.count();
- SkASSERT(numEffects == ip->fSamplers.count());
- for (int e = 0; e < numEffects; ++e) {
- SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[e];
- int numSamplers = samplers.count();
- for (int s = 0; s < numSamplers; ++s) {
- SkASSERT(samplers[s].fUniform.isValid());
- fProgramDataManager.setSampler(samplers[s].fUniform, *texUnitIdx);
- samplers[s].fTextureUnit = (*texUnitIdx)++;
- }
- }
-}
-
-void GrGLProgram::bindTextures(const GrGLInstalledProcessors* ip,
- const GrProcessor& processor,
- int effectIdx) {
- const SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[effectIdx];
- int numSamplers = samplers.count();
- SkASSERT(numSamplers == processor.numTextures());
- for (int s = 0; s < numSamplers; ++s) {
- SkASSERT(samplers[s].fTextureUnit >= 0);
- const GrTextureAccess& textureAccess = processor.textureAccess(s);
- fGpu->bindTexture(samplers[s].fTextureUnit,
- textureAccess.getParams(),
- static_cast<GrGLTexture*>(textureAccess.getTexture()));
+ fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx);
}
+ fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx);
+ fCoverageEffects->initSamplers(fProgramDataManager, &texUnitIdx);
}
-
///////////////////////////////////////////////////////////////////////////////
void GrGLProgram::setData(const GrOptDrawState& optState,
SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
}
- // we set the textures, and uniforms for installed processors in a generic way, but subclasses
- // of GLProgram determine how to set coord transforms
if (fGeometryProcessor.get()) {
SkASSERT(geometryProcessor);
- this->setData<GrGeometryStage>(&geometryProcessor, fGeometryProcessor.get());
+ fGeometryProcessor->setData(fGpu, drawType, fProgramDataManager, geometryProcessor);
}
- this->setData<GrFragmentStage>(colorStages, fColorEffects.get());
- this->setData<GrFragmentStage>(coverageStages, fCoverageEffects.get());
-
- // Some of GrGLProgram subclasses need to update state here
- this->didSetData(drawType);
-}
+ fColorEffects->setData(fGpu, drawType, fProgramDataManager, colorStages);
+ fCoverageEffects->setData(fGpu, drawType, fProgramDataManager, coverageStages);
-void GrGLProgram::setTransformData(const GrProcessorStage& processor,
- int effectIdx,
- GrGLInstalledProcessors* ip) {
- SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx];
- int numTransforms = transforms.count();
- SkASSERT(numTransforms == processor.getProcessor()->numTransforms());
- for (int t = 0; t < numTransforms; ++t) {
- SkASSERT(transforms[t].fHandle.isValid());
- const SkMatrix& matrix = get_transform_matrix(processor, ip->fHasExplicitLocalCoords, t);
- if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
- fProgramDataManager.setSkMatrix(transforms[t].fHandle.convertToUniformHandle(), matrix);
- transforms[t].fCurrentValue = matrix;
- }
+ // PathTexGen state applies to the the fixed function vertex shader. For
+ // custom shaders, it's ignored, so we don't need to change the texgen
+ // settings in that case.
+ if (!fHasVertexShader) {
+ fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
}
}
-void GrGLProgram::didSetData(GrGpu::DrawType drawType) {
- SkASSERT(!GrGpu::IsPathRenderingDrawType(drawType));
-}
-
void GrGLProgram::setColor(const GrOptDrawState& optState,
GrColor color,
SharedGLState* sharedState) {
void GrGLProgram::setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
const GrOptDrawState& optState) {
+ const GrRenderTarget* rt = optState.getRenderTarget();
+ SkISize size;
+ size.set(rt->width(), rt->height());
+
// Load the RT height uniform if it is needed to y-flip gl_FragCoord.
if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
- fMatrixState.fRenderTargetSize.fHeight != optState.getRenderTarget()->width()) {
+ fMatrixState.fRenderTargetSize.fHeight != size.fHeight) {
fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
- SkIntToScalar(optState.getRenderTarget()->height()));
+ SkIntToScalar(size.fHeight));
}
- // call subclasses to set the actual view matrix
- this->onSetMatrixAndRenderTargetHeight(drawType, optState);
-}
-
-void GrGLProgram::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
- const GrOptDrawState& optState) {
- const GrRenderTarget* rt = optState.getRenderTarget();
- SkISize size;
- size.set(rt->width(), rt->height());
- if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
- fMatrixState.fRenderTargetSize != size ||
- !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
+ if (GrGpu::IsPathRenderingDrawType(drawType)) {
+ fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
+ } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
+ fMatrixState.fRenderTargetSize != size ||
+ !fMatrixState.fViewMatrix.cheapEqualTo(optState.getViewMatrix())) {
SkASSERT(fBuiltinUniformHandles.fViewMatrixUni.isValid());
fMatrixState.fViewMatrix = optState.getViewMatrix();
fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
}
}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-GrGLNvprProgramBase::GrGLNvprProgramBase(GrGpuGL* gpu,
- const GrGLProgramDesc& desc,
- const BuiltinUniformHandles& builtinUniforms,
- GrGLuint programID,
- const UniformInfoArray& uniforms,
- GrGLInstalledProcessors* colorProcessors,
- GrGLInstalledProcessors* coverageProcessors)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL, colorProcessors,
- coverageProcessors) {
-}
-
-void GrGLNvprProgramBase::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
- const GrOptDrawState& optState) {
- SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
- const GrRenderTarget* rt = optState.getRenderTarget();
- SkISize size;
- size.set(rt->width(), rt->height());
- fGpu->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-GrGLNvprProgram::GrGLNvprProgram(GrGpuGL* gpu,
- const GrGLProgramDesc& desc,
- const BuiltinUniformHandles& builtinUniforms,
- GrGLuint programID,
- const UniformInfoArray& uniforms,
- GrGLInstalledProcessors* colorProcessors,
- GrGLInstalledProcessors* coverageProcessors,
- const SeparableVaryingInfoArray& separableVaryings)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors,
- coverageProcessors) {
- int count = separableVaryings.count();
- fVaryings.push_back_n(count);
- for (int i = 0; i < count; i++) {
- Varying& varying = fVaryings[i];
- const SeparableVaryingInfo& builderVarying = separableVaryings[i];
- SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount());
- SkDEBUGCODE(
- varying.fType = builderVarying.fVariable.getType();
- );
- varying.fLocation = builderVarying.fLocation;
- }
-}
-
-void GrGLNvprProgram::didSetData(GrGpu::DrawType drawType) {
- SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
-}
-
-void GrGLNvprProgram::setTransformData(const GrProcessorStage& processor,
- int effectIdx,
- GrGLInstalledProcessors* ip) {
- SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx];
- int numTransforms = transforms.count();
- SkASSERT(numTransforms == processor.getProcessor()->numTransforms());
- for (int t = 0; t < numTransforms; ++t) {
- SkASSERT(transforms[t].fHandle.isValid());
- const SkMatrix& transform = get_transform_matrix(processor, ip->fHasExplicitLocalCoords, t);
- if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
- continue;
- }
- transforms[t].fCurrentValue = transform;
- const Varying& fragmentInput = fVaryings[transforms[t].fHandle.handle()];
- SkASSERT(transforms[t].fType == kVec2f_GrSLType || transforms[t].fType == kVec3f_GrSLType);
- unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
- fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID,
- fragmentInput.fLocation,
- GR_GL_OBJECT_LINEAR,
- components,
- transform);
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////
-
-GrGLLegacyNvprProgram::GrGLLegacyNvprProgram(GrGpuGL* gpu,
- const GrGLProgramDesc& desc,
- const BuiltinUniformHandles& builtinUniforms,
- GrGLuint programID,
- const UniformInfoArray& uniforms,
- GrGLInstalledProcessors* colorProcessors,
- GrGLInstalledProcessors* coverageProcessors,
- int texCoordSetCnt)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors,
- coverageProcessors)
- , fTexCoordSetCnt(texCoordSetCnt) {
-}
-
-void GrGLLegacyNvprProgram::didSetData(GrGpu::DrawType drawType) {
- SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
- fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
-}
-
-void GrGLLegacyNvprProgram::setTransformData(const GrProcessorStage& processorStage,
- int effectIdx,
- GrGLInstalledProcessors* ip) {
- // We've hidden the texcoord index in the first entry of the transforms array for each effect
- int texCoordIndex = ip->fTransforms[effectIdx][0].fHandle.handle();
- int numTransforms = processorStage.getProcessor()->numTransforms();
- for (int t = 0; t < numTransforms; ++t) {
- const SkMatrix& transform = get_transform_matrix(processorStage, false, t);
- GrGLPathRendering::PathTexGenComponents components =
- GrGLPathRendering::kST_PathTexGenComponents;
- if (processorStage.isPerspectiveCoordTransform(t, false)) {
- components = GrGLPathRendering::kSTR_PathTexGenComponents;
- }
- fGpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform);
- }
-}
#define GrGLProgram_DEFINED
#include "builders/GrGLProgramBuilder.h"
-#include "builders/GrGLNvprProgramBuilder.h"
#include "GrDrawState.h"
#include "GrGLContext.h"
#include "GrGLProgramDesc.h"
#include "SkXfermode.h"
class GrGLProcessor;
-class GrGLInstalledProcessors;
+class GrGLProgramEffects;
class GrGLProgramBuilder;
/**
typedef GrGLProgramBuilder::BuiltinUniformHandles BuiltinUniformHandles;
+ static GrGLProgram* Create(GrGpuGL* gpu,
+ const GrOptDrawState& optState,
+ const GrGLProgramDesc& desc,
+ const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[]);
+
virtual ~GrGLProgram();
/**
*/
GrGLuint programID() const { return fProgramID; }
- /*
- * The base class always has a vertex shader, only the NVPR variants may omit a vertex shader
- */
- virtual bool hasVertexShader() const { return true; }
+ bool hasVertexShader() const { return fHasVertexShader; }
/**
* Some GL state that is relevant to programs is not stored per-program. In particular color
const GrDeviceCoordTexture* dstCopy, // can be NULL
SharedGLState*);
-protected:
+private:
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
- typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
GrGLProgram(GrGpuGL*,
const GrGLProgramDesc&,
- const BuiltinUniformHandles&,
- GrGLuint programID,
- const UniformInfoArray&,
- GrGLInstalledProcessors* geometryProcessor,
- GrGLInstalledProcessors* colorProcessors,
- GrGLInstalledProcessors* coverageProcessors);
+ const GrGLProgramBuilder&);
// Sets the texture units for samplers.
void initSamplerUniforms();
- void initSamplers(GrGLInstalledProcessors* processors, int* texUnitIdx);
// Helper for setData(). Makes GL calls to specify the initial color when there is not
// per-vertex colors.
// per-vertex coverages.
void setCoverage(const GrOptDrawState&, GrColor coverage, SharedGLState*);
- // A templated helper to loop over effects, set the transforms(via subclass) and bind textures
- template <class ProcessorStage>
- void setData(const ProcessorStage* effectStages[],
- GrGLInstalledProcessors* installedProcessors) {
- int numEffects = installedProcessors->fGLProcessors.count();
- SkASSERT(numEffects == installedProcessors->fTransforms.count());
- SkASSERT(numEffects == installedProcessors->fSamplers.count());
- for (int e = 0; e < numEffects; ++e) {
- const GrProcessor& effect = *effectStages[e]->getProcessor();
- installedProcessors->fGLProcessors[e]->setData(fProgramDataManager, effect);
- this->setTransformData(*effectStages[e], e, installedProcessors);
- this->bindTextures(installedProcessors, effect, e);
- }
- }
- virtual void setTransformData(const GrProcessorStage& effectStage,
- int effectIdx,
- GrGLInstalledProcessors* pe);
- void bindTextures(const GrGLInstalledProcessors*, const GrProcessor&, int effectIdx);
-
- /*
- * Legacy NVPR needs a hook here to flush path tex gen settings.
- * TODO when legacy nvpr is removed, remove this call.
- */
- virtual void didSetData(GrGpu::DrawType);
-
// Helper for setData() that sets the view matrix and loads the render target height uniform
- void setMatrixAndRenderTargetHeight(GrGpu::DrawType, const GrOptDrawState&);
- virtual void onSetMatrixAndRenderTargetHeight(GrGpu::DrawType, const GrOptDrawState&);
+ void setMatrixAndRenderTargetHeight(GrGpu::DrawType drawType, const GrOptDrawState&);
// these reflect the current values of uniforms (GL uniform values travel with program)
- MatrixState fMatrixState;
- GrColor fColor;
- GrColor fCoverage;
- int fDstCopyTexUnit;
- BuiltinUniformHandles fBuiltinUniformHandles;
- GrGLuint fProgramID;
+ MatrixState fMatrixState;
+ GrColor fColor;
+ GrColor fCoverage;
+ int fDstCopyTexUnit;
- // the installed effects
- SkAutoTUnref<GrGLInstalledProcessors> fGeometryProcessor;
- SkAutoTUnref<GrGLInstalledProcessors> fColorEffects;
- SkAutoTUnref<GrGLInstalledProcessors> fCoverageEffects;
+ BuiltinUniformHandles fBuiltinUniformHandles;
+ SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
+ SkAutoTUnref<GrGLProgramEffects> fColorEffects;
+ SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
+ GrGLuint fProgramID;
+ bool fHasVertexShader;
+ int fTexCoordSetCnt;
- GrGLProgramDesc fDesc;
- GrGpuGL* fGpu;
- GrGLProgramDataManager fProgramDataManager;
+ GrGLProgramDesc fDesc;
+ GrGpuGL* fGpu;
- friend class GrGLProgramBuilder;
+ GrGLProgramDataManager fProgramDataManager;
typedef SkRefCnt INHERITED;
};
-/*
- * Below are slight specializations of the program object for the different types of programs
- * The default GrGL programs consist of at the very least a vertex and fragment shader.
- * Legacy Nvpr only has a fragment shader, 1.3+ Nvpr ignores the vertex shader, but both require
- * specialized methods for setting transform data. Both types of NVPR also require setting the
- * projection matrix through a special function call
- */
-class GrGLNvprProgramBase : public GrGLProgram {
-protected:
- GrGLNvprProgramBase(GrGpuGL*,
- const GrGLProgramDesc&,
- const BuiltinUniformHandles&,
- GrGLuint programID,
- const UniformInfoArray&,
- GrGLInstalledProcessors* colorProcessors,
- GrGLInstalledProcessors* coverageProcessors);
- virtual void onSetMatrixAndRenderTargetHeight(GrGpu::DrawType, const GrOptDrawState&);
-
- typedef GrGLProgram INHERITED;
-};
-
-class GrGLNvprProgram : public GrGLNvprProgramBase {
-public:
- virtual bool hasVertexShader() const SK_OVERRIDE { return true; }
-
-private:
- typedef GrGLNvprProgramBuilder::SeparableVaryingInfo SeparableVaryingInfo;
- typedef GrGLNvprProgramBuilder::SeparableVaryingInfoArray SeparableVaryingInfoArray;
- GrGLNvprProgram(GrGpuGL*,
- const GrGLProgramDesc&,
- const BuiltinUniformHandles&,
- GrGLuint programID,
- const UniformInfoArray&,
- GrGLInstalledProcessors* colorProcessors,
- GrGLInstalledProcessors* coverageProcessors,
- const SeparableVaryingInfoArray& separableVaryings);
- virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
- virtual void setTransformData(const GrProcessorStage&,
- int effectIdx,
- GrGLInstalledProcessors*) SK_OVERRIDE;
-
- struct Varying {
- GrGLint fLocation;
- SkDEBUGCODE(
- GrSLType fType;
- );
- };
- SkTArray<Varying, true> fVaryings;
-
- friend class GrGLNvprProgramBuilder;
-
- typedef GrGLNvprProgramBase INHERITED;
-};
-
-class GrGLLegacyNvprProgram : public GrGLNvprProgramBase {
-public:
- virtual bool hasVertexShader() const SK_OVERRIDE { return false; }
-
-private:
- GrGLLegacyNvprProgram(GrGpuGL* gpu,
- const GrGLProgramDesc& desc,
- const BuiltinUniformHandles&,
- GrGLuint programID,
- const UniformInfoArray&,
- GrGLInstalledProcessors* colorProcessors,
- GrGLInstalledProcessors* coverageProcessors,
- int texCoordSetCnt);
- virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
- virtual void setTransformData(const GrProcessorStage&,
- int effectIdx,
- GrGLInstalledProcessors*) SK_OVERRIDE;
-
- int fTexCoordSetCnt;
-
- friend class GrGLLegacyNvprProgramBuilder;
-
- typedef GrGLNvprProgramBase INHERITED;
-};
-
#endif
* found in the LICENSE file.
*/
+#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLPathRendering.h"
+#include "gl/GrGLProgram.h"
#include "gl/GrGLUniformHandle.h"
#include "gl/GrGpuGL.h"
#include "SkMatrix.h"
SkASSERT(arrayCount <= uni.fArrayCount || \
(1 == arrayCount && GrGLShaderVar::kNonArray == uni.fArrayCount))
-GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu, const UniformInfoArray& uniforms)
- : fGpu(gpu) {
- int count = uniforms.count();
+GrGLProgramDataManager::GrGLProgramDataManager(GrGpuGL* gpu,
+ GrGLProgram* program,
+ const GrGLProgramBuilder& builder)
+ : fGpu(gpu),
+ fProgram(program) {
+ int count = builder.getUniformInfos().count();
fUniforms.push_back_n(count);
for (int i = 0; i < count; i++) {
Uniform& uniform = fUniforms[i];
- const UniformInfo& builderUniform = uniforms[i];
+ const GrGLProgramBuilder::UniformInfo& builderUniform = builder.getUniformInfos()[i];
SkASSERT(GrGLShaderVar::kNonArray == builderUniform.fVariable.getArrayCount() ||
builderUniform.fVariable.getArrayCount() > 0);
SkDEBUGCODE(
uniform.fVSLocation = builderUniform.fLocation;
} else {
uniform.fVSLocation = kUnusedUniform;
- }
+ }
if (GrGLProgramBuilder::kFragment_Visibility & builderUniform.fVisibility) {
uniform.fFSLocation = builderUniform.fLocation;
} else {
uniform.fFSLocation = kUnusedUniform;
}
}
+
+ count = builder.getSeparableVaryingInfos().count();
+ fVaryings.push_back_n(count);
+ for (int i = 0; i < count; i++) {
+ Varying& varying = fVaryings[i];
+ const GrGLProgramBuilder::SeparableVaryingInfo& builderVarying =
+ builder.getSeparableVaryingInfos()[i];
+ SkASSERT(GrGLShaderVar::kNonArray == builderVarying.fVariable.getArrayCount());
+ SkDEBUGCODE(
+ varying.fType = builderVarying.fVariable.getType();
+ );
+ varying.fLocation = builderVarying.fLocation;
+ }
}
void GrGLProgramDataManager::setSampler(UniformHandle u, GrGLint texUnit) const {
};
this->setMatrix3f(u, mt);
}
+
+void GrGLProgramDataManager::setProgramPathFragmentInputTransform(VaryingHandle i,
+ unsigned components,
+ const SkMatrix& matrix) const {
+ const Varying& fragmentInput = fVaryings[i.toProgramDataIndex()];
+ fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgram->programID(),
+ fragmentInput.fLocation,
+ GR_GL_OBJECT_LINEAR,
+ components,
+ matrix);
+}
friend class GrGLProgramBuilder; // For accessing toShaderBuilderIndex().
};
- struct UniformInfo {
- GrGLShaderVar fVariable;
- uint32_t fVisibility;
- GrGLint fLocation;
+ class VaryingHandle : public ShaderResourceHandle {
+ public:
+ /** Creates a reference to a varying in separable varyings of a GrGLShaderBuilder.
+ * The ref can be used to set the varying with the corresponding GrGLProgramDataManager.*/
+ static VaryingHandle CreateFromSeparableVaryingIndex(int i) {
+ return VaryingHandle(i);
+ }
+ VaryingHandle() { }
+ bool operator==(const VaryingHandle& other) const { return other.fValue == fValue; }
+ private:
+ VaryingHandle(int value) : ShaderResourceHandle(value) { }
+ int toProgramDataIndex() const { SkASSERT(isValid()); return fValue; }
+ friend class GrGLProgramDataManager; // For accessing toProgramDataIndex().
};
- // This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
- // after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
- // name strings. Otherwise, we'd have to hand out copies.
- typedef GrTAllocator<UniformInfo> UniformInfoArray;
-
- GrGLProgramDataManager(GrGpuGL*, const UniformInfoArray&);
+ GrGLProgramDataManager(GrGpuGL*, GrGLProgram*, const GrGLProgramBuilder&);
/** Functions for uploading uniform values. The varities ending in v can be used to upload to an
* array of uniforms. arrayCount must be <= the array count of the uniform.
// convenience method for uploading a SkMatrix to a 3x3 matrix uniform
void setSkMatrix(UniformHandle, const SkMatrix&) const;
+ void setProgramPathFragmentInputTransform(VaryingHandle i,
+ unsigned components,
+ const SkMatrix& matrix) const;
+
private:
enum {
kUnusedUniform = -1,
int fArrayCount;
);
};
+ struct Varying {
+ GrGLint fLocation;
+ SkDEBUGCODE(
+ GrSLType fType;
+ );
+ };
SkTArray<Uniform, true> fUniforms;
+ SkTArray<Varying, true> fVaryings;
GrGpuGL* fGpu;
+ GrGLProgram* fProgram;
typedef SkRefCnt INHERITED;
};
+
#endif
* found in the LICENSE file.
*/
-#include "gl/builders/GrGLFragmentShaderBuilder.h"
+#include "gl/builders/GrGLProgramBuilder.h"
#include "GrGLProgramDesc.h"
#include "GrBackendProcessorFactory.h"
#include "GrProcessor.h"
if (NULL == key) {
return false;
}
- uint32_t attribKey = gen_attrib_key(stage.getProcessor());
+ uint32_t attribKey = gen_attrib_key(stage.getGeometryProcessor());
// Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
// don't fit.
dstCopyTexture = dstCopy->texture();
}
header->fDstReadKey = GrGLFragmentShaderBuilder::KeyForDstRead(dstCopyTexture,
- gpu->glCaps());
+ gpu->glCaps());
SkASSERT(0 != header->fDstReadKey);
} else {
header->fDstReadKey = 0;
}
if (optState.readsFragPosition()) {
- header->fFragPosKey =
- GrGLFragmentShaderBuilder::KeyForFragmentPosition(optState.getRenderTarget(),
- gpu->glCaps());
+ header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition(
+ optState.getRenderTarget(), gpu->glCaps());
} else {
header->fFragPosKey = 0;
}
// visible to GrGLProcessors. Then make public accessors as necessary and remove friends.
friend class GrGLProgram;
friend class GrGLProgramBuilder;
- friend class GrGLLegacyNvprProgramBuilder;
- friend class GrGLVertexBuilder;
+ friend class GrGLFullProgramBuilder;
+ friend class GrGLFragmentOnlyProgramBuilder;
+ friend class GrGLVertexShaderBuilder;
friend class GrGLFragmentShaderBuilder;
- friend class GrGLGeometryBuilder;
+ friend class GrGLGeometryShaderBuilder;
};
#endif
--- /dev/null
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLProgramEffects.h"
+#include "gl/GrGLProcessor.h"
+#include "gl/GrGLPathRendering.h"
+#include "gl/builders/GrGLFullProgramBuilder.h"
+#include "gl/builders/GrGLFragmentOnlyProgramBuilder.h"
+#include "gl/GrGLGeometryProcessor.h"
+#include "gl/GrGpuGL.h"
+
+typedef GrGLProcessor::TransformedCoords TransformedCoords;
+typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray;
+typedef GrGLProcessor::TextureSampler TextureSampler;
+typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
+
+namespace {
+/**
+ * Retrieves the final matrix that a transform needs to apply to its source coords.
+ */
+SkMatrix get_transform_matrix(const GrProcessorStage& effectStage,
+ bool useExplicitLocalCoords,
+ int transformIdx) {
+ const GrCoordTransform& coordTransform = effectStage.getProcessor()->coordTransform(transformIdx);
+ SkMatrix combined;
+
+ if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
+ // If we have explicit local coords then we shouldn't need a coord change.
+ const SkMatrix& ccm =
+ useExplicitLocalCoords ? SkMatrix::I() : effectStage.getCoordChangeMatrix();
+ combined.setConcat(coordTransform.getMatrix(), ccm);
+ } else {
+ combined = coordTransform.getMatrix();
+ }
+ if (coordTransform.reverseY()) {
+ // combined.postScale(1,-1);
+ // combined.postTranslate(0,1);
+ combined.set(SkMatrix::kMSkewY,
+ combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
+ combined.set(SkMatrix::kMScaleY,
+ combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
+ combined.set(SkMatrix::kMTransY,
+ combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
+ }
+ return combined;
+}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+GrGLProgramEffects::~GrGLProgramEffects() {
+ int numEffects = fGLProcessors.count();
+ for (int e = 0; e < numEffects; ++e) {
+ SkDELETE(fGLProcessors[e]);
+ }
+}
+
+void GrGLProgramEffects::initSamplers(const GrGLProgramDataManager& programResourceManager, int* texUnitIdx) {
+ int numEffects = fGLProcessors.count();
+ SkASSERT(numEffects == fSamplers.count());
+ for (int e = 0; e < numEffects; ++e) {
+ SkTArray<Sampler, true>& samplers = fSamplers[e];
+ int numSamplers = samplers.count();
+ for (int s = 0; s < numSamplers; ++s) {
+ SkASSERT(samplers[s].fUniform.isValid());
+ programResourceManager.setSampler(samplers[s].fUniform, *texUnitIdx);
+ samplers[s].fTextureUnit = (*texUnitIdx)++;
+ }
+ }
+}
+
+void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrProcessor& effect, int effectIdx) {
+ const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx];
+ int numSamplers = samplers.count();
+ SkASSERT(numSamplers == effect.numTextures());
+ for (int s = 0; s < numSamplers; ++s) {
+ SkASSERT(samplers[s].fTextureUnit >= 0);
+ const GrTextureAccess& textureAccess = effect.textureAccess(s);
+ gpu->bindTexture(samplers[s].fTextureUnit,
+ textureAccess.getParams(),
+ static_cast<GrGLTexture*>(textureAccess.getTexture()));
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
+ GrGpu::DrawType drawType,
+ const GrGLProgramDataManager& programDataManager,
+ const GrGeometryStage* effectStages) {
+ SkASSERT(1 == fGLProcessors.count());
+ SkASSERT(1 == fTransforms.count());
+ SkASSERT(1 == fSamplers.count());
+ this->setDataInternal(gpu, drawType, programDataManager, *effectStages, 0);
+}
+
+void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
+ GrGpu::DrawType drawType,
+ const GrGLProgramDataManager& programDataManager,
+ const GrFragmentStage* effectStages[]) {
+ int numEffects = fGLProcessors.count();
+ SkASSERT(numEffects == fTransforms.count());
+ SkASSERT(numEffects == fSamplers.count());
+ for (int e = 0; e < numEffects; ++e) {
+ this->setDataInternal(gpu, drawType, programDataManager, *effectStages[e], e);
+ }
+}
+
+void GrGLVertexProgramEffects::setDataInternal(GrGpuGL* gpu,
+ GrGpu::DrawType drawType,
+ const GrGLProgramDataManager& programDataManager,
+ const GrProcessorStage& effectStage,
+ int index) {
+ const GrProcessor& effect = *effectStage.getProcessor();
+ fGLProcessors[index]->setData(programDataManager, effect);
+ if (GrGpu::IsPathRenderingDrawType(drawType)) {
+ this->setPathTransformData(gpu, programDataManager, effectStage, index);
+ } else {
+ this->setTransformData(gpu, programDataManager, effectStage, index);
+ }
+ this->bindTextures(gpu, effect, index);
+}
+
+void GrGLVertexProgramEffects::setTransformData(GrGpuGL* gpu,
+ const GrGLProgramDataManager& pdman,
+ const GrProcessorStage& effectStage,
+ int effectIdx) {
+ SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
+ int numTransforms = transforms.count();
+ SkASSERT(numTransforms == effectStage.getProcessor()->numTransforms());
+ for (int t = 0; t < numTransforms; ++t) {
+ SkASSERT(transforms[t].fHandle.isValid());
+ const SkMatrix& matrix = get_transform_matrix(effectStage, fHasExplicitLocalCoords, t);
+ if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
+ pdman.setSkMatrix(transforms[t].fHandle, matrix);
+ transforms[t].fCurrentValue = matrix;
+ }
+ }
+}
+
+void GrGLVertexProgramEffects::setPathTransformData(GrGpuGL* gpu,
+ const GrGLProgramDataManager& pdman,
+ const GrProcessorStage& effectStage,
+ int effectIdx) {
+ SkTArray<PathTransform, true>& transforms = fPathTransforms[effectIdx];
+ int numTransforms = transforms.count();
+ SkASSERT(numTransforms == effectStage.getProcessor()->numTransforms());
+ for (int t = 0; t < numTransforms; ++t) {
+ SkASSERT(transforms[t].fHandle.isValid());
+ const SkMatrix& transform = get_transform_matrix(effectStage, fHasExplicitLocalCoords, t);
+ if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
+ continue;
+ }
+ transforms[t].fCurrentValue = transform;
+ switch (transforms[t].fType) {
+ case kVec2f_GrSLType:
+ pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 2, transform);
+ break;
+ case kVec3f_GrSLType:
+ pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 3, transform);
+ break;
+ default:
+ SkFAIL("Unexpected matrix type.");
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
+ GrGpu::DrawType,
+ const GrGLProgramDataManager& pdman,
+ const GrFragmentStage* effectStages[]) {
+ int numEffects = fGLProcessors.count();
+ SkASSERT(numEffects == fTransforms.count());
+ SkASSERT(numEffects == fSamplers.count());
+ for (int e = 0; e < numEffects; ++e) {
+ const GrProcessorStage& effectStage = *effectStages[e];
+ const GrProcessor& effect = *effectStage.getProcessor();
+ fGLProcessors[e]->setData(pdman, effect);
+ this->setPathTexGenState(gpu, effectStage, e);
+ this->bindTextures(gpu, effect, e);
+ }
+}
+
+void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu,
+ const GrProcessorStage& effectStage,
+ int effectIdx) {
+ int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
+ int numTransforms = effectStage.getProcessor()->numTransforms();
+ for (int t = 0; t < numTransforms; ++t) {
+ const SkMatrix& transform = get_transform_matrix(effectStage, false, t);
+ GrGLPathRendering::PathTexGenComponents components =
+ GrGLPathRendering::kST_PathTexGenComponents;
+ if (effectStage.isPerspectiveCoordTransform(t, false)) {
+ components = GrGLPathRendering::kSTR_PathTexGenComponents;
+ }
+ gpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLProgramEffects_DEFINED
+#define GrGLProgramEffects_DEFINED
+
+#include "GrBackendProcessorFactory.h"
+#include "GrGLProgramDataManager.h"
+#include "GrGpu.h"
+#include "GrTexture.h"
+#include "GrTextureAccess.h"
+
+class GrProcessor;
+class GrProcessorStage;
+class GrGLVertexProgramEffectsBuilder;
+class GrGLProgramBuilder;
+class GrGLFullProgramBuilder;
+class GrGLFragmentOnlyProgramBuilder;
+
+/**
+ * This class encapsulates an array of GrGLProcessors and their supporting data (coord transforms
+ * and textures). It is built with GrGLProgramEffectsBuilder, then used to manage the necessary GL
+ * state and shader uniforms.
+ */
+class GrGLProgramEffects : public SkRefCnt {
+public:
+ typedef GrGLProgramDataManager::UniformHandle UniformHandle;
+ typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
+ virtual ~GrGLProgramEffects();
+
+ /**
+ * Assigns a texture unit to each sampler. It starts on *texUnitIdx and writes the next
+ * available unit to *texUnitIdx when it returns.
+ */
+ void initSamplers(const GrGLProgramDataManager&, int* texUnitIdx);
+
+ /**
+ * Calls setData() on each effect, and sets their transformation matrices and texture bindings.
+ */
+ virtual void setData(GrGpuGL*,
+ GrGpu::DrawType,
+ const GrGLProgramDataManager&,
+ const GrGeometryStage* effectStages) {
+ SkFAIL("For geometry processor only");
+ }
+
+ virtual void setData(GrGpuGL*,
+ GrGpu::DrawType,
+ const GrGLProgramDataManager&,
+ const GrFragmentStage* effectStages[]) = 0;
+
+protected:
+ GrGLProgramEffects(int reserveCount)
+ : fGLProcessors(reserveCount)
+ , fSamplers(reserveCount) {
+ }
+
+ /**
+ * Helper for setData(). Binds all the textures for an effect.
+ */
+ void bindTextures(GrGpuGL*, const GrProcessor&, int effectIdx);
+
+ struct Sampler {
+ SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
+ UniformHandle fUniform;
+ int fTextureUnit;
+ };
+
+ /*
+ * Helpers for shader builders to build up program effects objects alongside shader code
+ */
+ void addEffect(GrGLProcessor* effect) { fGLProcessors.push_back(effect); }
+ SkTArray<Sampler, true>& addSamplers() { return fSamplers.push_back(); }
+
+ SkTArray<GrGLProcessor*> fGLProcessors;
+ SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
+
+private:
+ friend class GrGLProgramBuilder;
+ friend class GrGLFullProgramBuilder;
+ friend class GrGLFragmentOnlyShaderBuilder;
+
+ typedef SkRefCnt INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
+ */
+class GrGLVertexProgramEffects : public GrGLProgramEffects {
+public:
+ virtual void setData(GrGpuGL*,
+ GrGpu::DrawType,
+ const GrGLProgramDataManager&,
+ const GrGeometryStage* effectStages) SK_OVERRIDE;
+
+ virtual void setData(GrGpuGL*,
+ GrGpu::DrawType,
+ const GrGLProgramDataManager&,
+ const GrFragmentStage* effectStages[]) SK_OVERRIDE;
+
+private:
+ GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords)
+ : INHERITED(reserveCount)
+ , fTransforms(reserveCount)
+ , fHasExplicitLocalCoords(explicitLocalCoords) {
+ }
+
+ struct Transform {
+ Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
+ UniformHandle fHandle;
+ SkMatrix fCurrentValue;
+ };
+
+ struct PathTransform {
+ PathTransform() { fCurrentValue = SkMatrix::InvalidMatrix(); }
+ VaryingHandle fHandle;
+ SkMatrix fCurrentValue;
+ GrSLType fType;
+ };
+
+ /*
+ * These functions are used by the builders to build up program effects along side the shader
+ * code itself
+ */
+ SkSTArray<2, Transform, true>& addTransforms() { return fTransforms.push_back(); }
+ SkTArray<PathTransform, true>& addPathTransforms() { return fPathTransforms.push_back(); }
+
+ /**
+ * Helper for setData(). Sets all the transform matrices for an effect.
+ */
+ void setDataInternal(GrGpuGL* gpu,
+ GrGpu::DrawType drawType,
+ const GrGLProgramDataManager& programDataManager,
+ const GrProcessorStage& effectStage,
+ int index);
+ void setTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrProcessorStage&,
+ int effectIdx);
+ void setPathTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&,
+ const GrProcessorStage&, int effectIdx);
+
+
+ SkTArray<SkSTArray<2, Transform, true> > fTransforms;
+ SkTArray<SkTArray<PathTransform, true> > fPathTransforms;
+ bool fHasExplicitLocalCoords;
+
+ friend class GrGLFullProgramBuilder;
+
+ typedef GrGLProgramEffects INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * This is a GrGLProgramEffects implementation that does coord transforms with
+ * the the NV_path_rendering PathTexGen functionality.
+ */
+class GrGLPathTexGenProgramEffects : public GrGLProgramEffects {
+public:
+ virtual void setData(GrGpuGL*,
+ GrGpu::DrawType,
+ const GrGLProgramDataManager&,
+ const GrFragmentStage* effectStages[]) SK_OVERRIDE;
+
+private:
+ GrGLPathTexGenProgramEffects(int reserveCount)
+ : INHERITED(reserveCount)
+ , fTransforms(reserveCount) {
+ }
+
+ /**
+ * Helper for setData(). Sets the PathTexGen state for each transform in an effect.
+ */
+ void setPathTexGenState(GrGpuGL*, const GrProcessorStage&, int effectIdx);
+
+ struct Transforms {
+ Transforms(int texCoordIndex)
+ : fTexCoordIndex(texCoordIndex) {}
+ int fTexCoordIndex;
+ };
+
+ /*
+ * Helper for fragment only shader builder to build up the program effects alongside the shader
+ */
+ void addTransforms(int coordIndex) {
+ fTransforms.push_back(Transforms(coordIndex));
+ }
+
+ SkTArray<Transforms> fTransforms;
+
+ friend class GrGLFragmentOnlyProgramBuilder;
+
+ typedef GrGLProgramEffects INHERITED;
+};
+
+#endif
~ProgramCache();
void abandon();
- GrGLProgram* getProgram(const GrOptDrawState&,
- const GrGLProgramDesc&,
- DrawType,
+ GrGLProgram* getProgram(const GrOptDrawState& optState,
+ const GrGLProgramDesc& desc,
const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[]);
#include "GrGpuGL.h"
-#include "builders/GrGLProgramBuilder.h"
#include "GrProcessor.h"
#include "GrGLProcessor.h"
#include "GrGLPathRendering.h"
GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState,
const GrGLProgramDesc& desc,
- DrawType type,
const GrGeometryStage* geometryProcessor,
const GrFragmentStage* colorStages[],
const GrFragmentStage* coverageStages[]) {
#ifdef PROGRAM_CACHE_STATS
++fCacheMisses;
#endif
- GrGLProgram* program = GrGLProgramBuilder::CreateProgram(optState, desc, type,
- geometryProcessor, colorStages,
- coverageStages, fGpu);
+ GrGLProgram* program = GrGLProgram::Create(fGpu, optState, desc, geometryProcessor,
+ colorStages, coverageStages);
if (NULL == program) {
return NULL;
}
fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(),
desc,
- type,
geometryProcessor,
colorStages.begin(),
coverageStages.begin()));
--- /dev/null
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLFragmentOnlyProgramBuilder.h"
+#include "../GrGpuGL.h"
+
+GrGLFragmentOnlyProgramBuilder::GrGLFragmentOnlyProgramBuilder(GrGpuGL* gpu,
+ const GrOptDrawState& optState,
+ const GrGLProgramDesc& desc)
+ : INHERITED(gpu, optState, desc) {
+ SkASSERT(desc.getHeader().fUseFragShaderOnly);
+ SkASSERT(gpu->glCaps().pathRenderingSupport());
+ SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
+ SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
+}
+
+int GrGLFragmentOnlyProgramBuilder::addTexCoordSets(int count) {
+ int firstFreeCoordSet = fTexCoordSetCnt;
+ fTexCoordSetCnt += count;
+ SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt);
+ return firstFreeCoordSet;
+}
+
+void
+GrGLFragmentOnlyProgramBuilder::createAndEmitEffects(const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[],
+ GrGLSLExpr4* inputColor,
+ GrGLSLExpr4* inputCoverage) {
+ ///////////////////////////////////////////////////////////////////////////
+ // emit the per-effect code for both color and coverage effects
+
+ EffectKeyProvider colorKeyProvider(&this->desc(), EffectKeyProvider::kColor_EffectType);
+ fColorEffects.reset(this->onCreateAndEmitEffects(colorStages,
+ this->desc().numColorEffects(),
+ colorKeyProvider,
+ inputColor));
+
+ EffectKeyProvider coverageKeyProvider(&this->desc(), EffectKeyProvider::kCoverage_EffectType);
+ fCoverageEffects.reset(this->onCreateAndEmitEffects(coverageStages,
+ this->desc().numCoverageEffects(),
+ coverageKeyProvider,
+ inputCoverage));
+}
+
+GrGLProgramEffects* GrGLFragmentOnlyProgramBuilder::onCreateAndEmitEffects(
+ const GrFragmentStage* effectStages[], int effectCnt,
+ const GrGLProgramDesc::EffectKeyProvider& keyProvider, GrGLSLExpr4* inOutFSColor) {
+ fProgramEffects.reset(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (effectCnt)));
+ this->INHERITED::createAndEmitEffects(effectStages,
+ effectCnt,
+ keyProvider,
+ inOutFSColor);
+ return fProgramEffects.detach();
+}
+
+void GrGLFragmentOnlyProgramBuilder::emitEffect(const GrProcessorStage& stage,
+ const GrProcessorKey& key,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) {
+ SkASSERT(fProgramEffects.get());
+ const GrProcessor& effect = *stage.getProcessor();
+
+ SkSTArray<2, GrGLProcessor::TransformedCoords> coords(effect.numTransforms());
+ SkSTArray<4, GrGLProcessor::TextureSampler> samplers(effect.numTextures());
+
+ this->setupPathTexGen(stage, &coords);
+ this->emitSamplers(effect, &samplers);
+
+ SkASSERT(fEffectEmitter);
+ GrGLProcessor* glEffect = fEffectEmitter->createGLInstance();
+ fProgramEffects->addEffect(glEffect);
+
+ GrGLFragmentShaderBuilder* fsBuilder = this->getFragmentShaderBuilder();
+ // Enclose custom code in a block to avoid namespace conflicts
+ SkString openBrace;
+ openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
+ fsBuilder->codeAppend(openBrace.c_str());
+
+ fEffectEmitter->emit(key, outColor, inColor, coords, samplers);
+
+ fsBuilder->codeAppend("\t}\n");
+}
+
+void GrGLFragmentOnlyProgramBuilder::setupPathTexGen(
+ const GrProcessorStage& effectStage, GrGLProcessor::TransformedCoordsArray* outCoords) {
+ int numTransforms = effectStage.getProcessor()->numTransforms();
+ int texCoordIndex = this->addTexCoordSets(numTransforms);
+
+ fProgramEffects->addTransforms(texCoordIndex);
+
+ SkString name;
+ for (int t = 0; t < numTransforms; ++t) {
+ GrSLType type =
+ effectStage.isPerspectiveCoordTransform(t, false) ?
+ kVec3f_GrSLType :
+ kVec2f_GrSLType;
+
+ name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
+ SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, (name, type));
+ }
+}
--- /dev/null
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLFragmentOnlyProgramBuilder_DEFINED
+#define GrGLFragmentOnlyProgramBuilder_DEFINED
+
+#include "GrGLProgramBuilder.h"
+
+class GrGLFragmentOnlyProgramBuilder : public GrGLProgramBuilder {
+public:
+ GrGLFragmentOnlyProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
+
+ int addTexCoordSets(int count);
+
+private:
+ virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[],
+ GrGLSLExpr4* inputColor,
+ GrGLSLExpr4* inputCoverage) SK_OVERRIDE;
+
+ GrGLProgramEffects* onCreateAndEmitEffects(const GrFragmentStage* effectStages[],
+ int effectCnt,
+ const GrGLProgramDesc::EffectKeyProvider&,
+ GrGLSLExpr4* inOutFSColor);
+
+ virtual void emitEffect(const GrProcessorStage& stage,
+ const GrProcessorKey& key,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) SK_OVERRIDE;
+
+ /**
+ * Helper for emitEffect(). Allocates texture units from the builder for each transform in an
+ * effect. The transforms all use adjacent texture units. They either use two or three of the
+ * coordinates at a given texture unit, depending on if they need perspective interpolation.
+ * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
+ * types are appended to the TransformedCoordsArray* object, which is in turn passed to the
+ * effect's emitCode() function.
+ */
+ void setupPathTexGen(const GrProcessorStage&, GrGLProcessor::TransformedCoordsArray*);
+
+ virtual GrGLProgramEffects* getProgramEffects() SK_OVERRIDE { return fProgramEffects.get(); }
+
+ typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
+
+ SkAutoTDelete<GrGLPathTexGenProgramEffects> fProgramEffects;
+
+ typedef GrGLProgramBuilder INHERITED;
+};
+
+#endif
#include "GrGLProgramBuilder.h"
#include "../GrGpuGL.h"
-#define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X)
-#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(), R, X)
-
+namespace {
+#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
+#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
// ES2 FS only guarantees mediump and lowp support
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
-const char* GrGLFragmentShaderBuilder::kDstCopyColorName = "_dstColor";
-static const char* declared_color_output_name() { return "fsColorOut"; }
-static const char* dual_source_output_name() { return "dualSourceOut"; }
-static void append_default_precision_qualifier(GrGLShaderVar::Precision p,
+static const char kDstCopyColorName[] = "_dstColor";
+inline const char* declared_color_output_name() { return "fsColorOut"; }
+inline const char* dual_source_output_name() { return "dualSourceOut"; }
+inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
GrGLStandard standard,
SkString* str) {
// Desktop GLSL has added precision qualifiers but they don't do anything.
}
}
}
+}
-GrGLFragmentShaderBuilder::DstReadKey
-GrGLFragmentShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
- const GrGLCaps& caps) {
+GrGLFragmentShaderBuilder::DstReadKey GrGLFragmentShaderBuilder::KeyForDstRead(
+ const GrTexture* dstCopy, const GrGLCaps& caps) {
uint32_t key = kYesDstRead_DstReadKeyBit;
if (caps.fbFetchSupport()) {
return key;
return static_cast<DstReadKey>(key);
}
-GrGLFragmentShaderBuilder::FragPosKey
-GrGLFragmentShaderBuilder::KeyForFragmentPosition(const GrRenderTarget* dst,
- const GrGLCaps&) {
+GrGLFragmentShaderBuilder::FragPosKey GrGLFragmentShaderBuilder::KeyForFragmentPosition(
+ const GrRenderTarget* dst, const GrGLCaps&) {
if (kTopLeft_GrSurfaceOrigin == dst->origin()) {
return kTopLeftFragPosRead_FragPosKey;
} else {
, fHasCustomColorOutput(false)
, fHasSecondaryOutput(false)
, fSetupFragPosition(false)
- , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey)
- , fHasReadDstColor(false)
- , fHasReadFragmentPosition(false) {
+ , fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey){
+}
+
+const char* GrGLFragmentShaderBuilder::dstColor() {
+ if (fProgramBuilder->fCodeStage.inStageCode()) {
+ const GrProcessor* effect = fProgramBuilder->fCodeStage.effectStage()->getProcessor();
+ // TODO GPs can't read dst color, and full program builder only returns a pointer to the
+ // base fragment shader builder which does not have this function. Unfortunately,
+ // the code stage class only has a GrProcessor pointer so this is required for the time
+ // being
+ if (!static_cast<const GrFragmentProcessor*>(effect)->willReadDstColor()) {
+ SkDEBUGFAIL("GrGLProcessor asked for dst color but its generating GrProcessor "
+ "did not request access.");
+ return "";
+ }
+ }
+
+ GrGpuGL* gpu = fProgramBuilder->gpu();
+ if (gpu->glCaps().fbFetchSupport()) {
+ this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
+ gpu->glCaps().fbFetchExtensionString());
+ return gpu->glCaps().fbFetchColorName();
+ } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) {
+ return kDstCopyColorName;
+ } else {
+ return "";
+ }
}
bool GrGLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
}
const char* GrGLFragmentShaderBuilder::fragmentPosition() {
- fHasReadFragmentPosition = true;
+ GrGLProgramBuilder::CodeStage* cs = &fProgramBuilder->fCodeStage;
+ if (cs->inStageCode()) {
+ const GrProcessor* effect = cs->effectStage()->getProcessor();
+ if (!effect->willReadFragmentPosition()) {
+ SkDEBUGFAIL("GrGLProcessor asked for frag position but its generating GrProcessor "
+ "did not request access.");
+ return "";
+ }
+ }
GrGpuGL* gpu = fProgramBuilder->gpu();
// We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
static const char* kCoordName = "fragCoordYDown";
if (!fSetupFragPosition) {
// temporarily change the stage index because we're inserting non-stage code.
- GrGLProgramBuilder::AutoStageRestore asr(fProgramBuilder);
+ GrGLProgramBuilder::CodeStage::AutoStageRestore csar(cs, NULL);
+
SkASSERT(!fProgramBuilder->fUniformHandles.fRTHeightUni.isValid());
const char* rtHeightName;
fProgramBuilder->fUniformHandles.fRTHeightUni =
fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kFloat_GrSLType,
- "RTHeight",
- &rtHeightName);
+ kFloat_GrSLType,
+ "RTHeight",
+ &rtHeightName);
// Using glFragCoord.zw for the last two components tickles an Adreno driver bug that
// causes programs to fail to link. Making this function return a vec2() didn't fix the
}
}
-const char* GrGLFragmentShaderBuilder::dstColor() {
- fHasReadDstColor = true;
-
- GrGpuGL* gpu = fProgramBuilder->gpu();
- if (gpu->glCaps().fbFetchSupport()) {
- this->addFeature(1 << (GrGLFragmentShaderBuilder::kLastGLSLPrivateFeature + 1),
- gpu->glCaps().fbFetchExtensionString());
- return gpu->glCaps().fbFetchColorName();
- } else if (fProgramBuilder->fUniformHandles.fDstCopySamplerUni.isValid()) {
- return kDstCopyColorName;
- } else {
- return "";
- }
-}
-
-void GrGLFragmentShaderBuilder::emitCodeToReadDstTexture() {
- bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & fProgramBuilder->header().fDstReadKey);
- const char* dstCopyTopLeftName;
- const char* dstCopyCoordScaleName;
- const char* dstCopySamplerName;
- uint32_t configMask;
- if (SkToBool(kUseAlphaConfig_DstReadKeyBit & fProgramBuilder->header().fDstReadKey)) {
- configMask = kA_GrColorComponentFlag;
- } else {
- configMask = kRGBA_GrColorComponentFlags;
- }
- fProgramBuilder->fUniformHandles.fDstCopySamplerUni =
- fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kSampler2D_GrSLType,
- "DstCopySampler",
- &dstCopySamplerName);
- fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni =
- fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kVec2f_GrSLType,
- "DstCopyUpperLeft",
- &dstCopyTopLeftName);
- fProgramBuilder->fUniformHandles.fDstCopyScaleUni =
- fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kVec2f_GrSLType,
- "DstCopyCoordScale",
- &dstCopyCoordScaleName);
- const char* fragPos = this->fragmentPosition();
-
- this->codeAppend("// Read color from copy of the destination.\n");
- this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
- fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
- if (!topDown) {
- this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
- }
- this->codeAppendf("vec4 %s = ", GrGLFragmentShaderBuilder::kDstCopyColorName);
- this->appendTextureLookup(dstCopySamplerName,
- "_dstTexCoord",
- configMask,
- "rgba");
- this->codeAppend(";");
-}
-
-void GrGLFragmentShaderBuilder::enableCustomOutput() {
- SkASSERT(!fHasCustomColorOutput);
- fHasCustomColorOutput = true;
- fOutputs.push_back().set(kVec4f_GrSLType,
- GrGLShaderVar::kOut_TypeModifier,
- declared_color_output_name());
-}
-
-void GrGLFragmentShaderBuilder::enableSecondaryOutput() {
- SkASSERT(!fHasSecondaryOutput);
- fHasSecondaryOutput = true;
- fOutputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kOut_TypeModifier,
- dual_source_output_name());
-}
-
-const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const {
- return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
-}
-
-const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const {
- return dual_source_output_name();
-}
-
-void GrGLFragmentShaderBuilder::enableSecondaryOutput(const GrGLSLExpr4& inputColor,
- const GrGLSLExpr4& inputCoverage) {
- this->enableSecondaryOutput();
- const char* secondaryOutputName = this->getSecondaryColorOutputName();
- GrGLSLExpr4 coeff(1);
- switch (fProgramBuilder->header().fSecondaryOutputType) {
- case GrOptDrawState::kCoverage_SecondaryOutputType:
- break;
- case GrOptDrawState::kCoverageISA_SecondaryOutputType:
- // Get (1-A) into coeff
- coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a());
- break;
- case GrOptDrawState::kCoverageISC_SecondaryOutputType:
- // Get (1-RGBA) into coeff
- coeff = GrGLSLExpr4(1) - inputColor;
- break;
- default:
- SkFAIL("Unexpected Secondary Output");
+void GrGLFragmentShaderBuilder::addVarying(GrSLType type,
+ const char* name,
+ const char** fsInName,
+ GrGLShaderVar::Precision fsPrecision) {
+ fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision);
+ if (fsInName) {
+ *fsInName = name;
}
- // Get coeff * coverage into modulate and then write that to the dual source output.
- this->codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str());
}
-void GrGLFragmentShaderBuilder::combineColorAndCoverage(const GrGLSLExpr4& inputColor,
- const GrGLSLExpr4& inputCoverage) {
- GrGLSLExpr4 fragColor = inputColor * inputCoverage;
- switch (fProgramBuilder->header().fPrimaryOutputType) {
- case GrOptDrawState::kModulate_PrimaryOutputType:
- break;
- case GrOptDrawState::kCombineWithDst_PrimaryOutputType:
- {
- // Tack on "+(1-coverage)dst onto the frag color.
- GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage;
- GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(this->dstColor());
- fragColor = fragColor + dstContribution;
- }
- break;
- default:
- SkFAIL("Unknown Primary Output");
+void GrGLFragmentShaderBuilder::bindProgramLocations(GrGLuint programId) {
+ GrGpuGL* gpu = fProgramBuilder->gpu();
+ if (fHasCustomColorOutput) {
+ GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name()));
}
-
- // On any post 1.10 GLSL supporting GPU, we declare custom output
- if (k110_GrGLSLGeneration != fProgramBuilder->gpu()->glslGeneration()) {
- this->enableCustomOutput();
+ if (fHasSecondaryOutput) {
+ GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name()));
}
-
- this->codeAppendf("\t%s = %s;\n", this->getPrimaryColorOutputName(), fragColor.c_str());
}
bool GrGLFragmentShaderBuilder::compileAndAttachShaders(GrGLuint programId,
gpu->glStandard(),
&fragShaderSrc);
fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kFragment_Visibility, &fragShaderSrc);
- this->appendDecls(fInputs, &fragShaderSrc);
+ fProgramBuilder->appendDecls(fInputs, &fragShaderSrc);
// We shouldn't have declared outputs on 1.10
SkASSERT(k110_GrGLSLGeneration != gpu->glslGeneration() || fOutputs.empty());
- this->appendDecls(fOutputs, &fragShaderSrc);
+ fProgramBuilder->appendDecls(fOutputs, &fragShaderSrc);
fragShaderSrc.append(fFunctions);
fragShaderSrc.append("void main() {\n");
fragShaderSrc.append(fCode);
return true;
}
-void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) {
- if (fHasCustomColorOutput) {
- GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name()));
+void GrGLFragmentShaderBuilder::emitCodeBeforeEffects() {
+ const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
+ GrGpuGL* gpu = fProgramBuilder->gpu();
+
+ ///////////////////////////////////////////////////////////////////////////
+ // emit code to read the dst copy texture, if necessary
+ if (kNoDstRead_DstReadKey != header.fDstReadKey && !gpu->glCaps().fbFetchSupport()) {
+ bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey);
+ const char* dstCopyTopLeftName;
+ const char* dstCopyCoordScaleName;
+ const char* dstCopySamplerName;
+ uint32_t configMask;
+ if (SkToBool(kUseAlphaConfig_DstReadKeyBit & header.fDstReadKey)) {
+ configMask = kA_GrColorComponentFlag;
+ } else {
+ configMask = kRGBA_GrColorComponentFlags;
+ }
+ fProgramBuilder->fUniformHandles.fDstCopySamplerUni =
+ fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kSampler2D_GrSLType,
+ "DstCopySampler",
+ &dstCopySamplerName);
+ fProgramBuilder->fUniformHandles.fDstCopyTopLeftUni =
+ fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kVec2f_GrSLType,
+ "DstCopyUpperLeft",
+ &dstCopyTopLeftName);
+ fProgramBuilder->fUniformHandles.fDstCopyScaleUni =
+ fProgramBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kVec2f_GrSLType,
+ "DstCopyCoordScale",
+ &dstCopyCoordScaleName);
+ const char* fragPos = fragmentPosition();
+
+ this->codeAppend("// Read color from copy of the destination.\n");
+ this->codeAppendf("vec2 _dstTexCoord = (%s.xy - %s) * %s;",
+ fragPos, dstCopyTopLeftName, dstCopyCoordScaleName);
+ if (!topDown) {
+ this->codeAppend("_dstTexCoord.y = 1.0 - _dstTexCoord.y;");
+ }
+ this->codeAppendf("vec4 %s = ", kDstCopyColorName);
+ this->appendTextureLookup(dstCopySamplerName,
+ "_dstTexCoord",
+ configMask,
+ "rgba");
+ this->codeAppend(";");
}
- if (fHasSecondaryOutput) {
- GL_CALL(BindFragDataLocationIndexed(programID, 0, 1, dual_source_output_name()));
+
+ if (k110_GrGLSLGeneration != gpu->glslGeneration()) {
+ fOutputs.push_back().set(kVec4f_GrSLType,
+ GrGLShaderVar::kOut_TypeModifier,
+ declared_color_output_name());
+ fHasCustomColorOutput = true;
}
}
-void GrGLFragmentShaderBuilder::addVarying(GrSLType type,
- const char* name,
- const char** fsInName,
- GrGLShaderVar::Precision fsPrecision) {
- fInputs.push_back().set(type, GrGLShaderVar::kVaryingIn_TypeModifier, name, fsPrecision);
- if (fsInName) {
- *fsInName = name;
+void GrGLFragmentShaderBuilder::emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage) {
+ const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
+
+ ///////////////////////////////////////////////////////////////////////////
+ // write the secondary color output if necessary
+ if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
+ const char* secondaryOutputName = this->enableSecondaryOutput();
+ GrGLSLExpr4 coeff(1);
+ switch (header.fSecondaryOutputType) {
+ case GrOptDrawState::kCoverage_SecondaryOutputType:
+ break;
+ case GrOptDrawState::kCoverageISA_SecondaryOutputType:
+ // Get (1-A) into coeff
+ coeff = GrGLSLExpr4::VectorCast(GrGLSLExpr1(1) - inputColor.a());
+ break;
+ case GrOptDrawState::kCoverageISC_SecondaryOutputType:
+ // Get (1-RGBA) into coeff
+ coeff = GrGLSLExpr4(1) - inputColor;
+ break;
+ default:
+ SkFAIL("Unexpected Secondary Output");
+ }
+ // Get coeff * coverage into modulate and then write that to the dual source output.
+ codeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inputCoverage).c_str());
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // combine color and coverage as frag color
+
+ // Get "color * coverage" into fragColor
+ GrGLSLExpr4 fragColor = inputColor * inputCoverage;
+ switch (header.fPrimaryOutputType) {
+ case GrOptDrawState::kModulate_PrimaryOutputType:
+ break;
+ case GrOptDrawState::kCombineWithDst_PrimaryOutputType:
+ {
+ // Tack on "+(1-coverage)dst onto the frag color.
+ GrGLSLExpr4 dstCoeff = GrGLSLExpr4(1) - inputCoverage;
+ GrGLSLExpr4 dstContribution = dstCoeff * GrGLSLExpr4(dstColor());
+ fragColor = fragColor + dstContribution;
+ }
+ break;
+ default:
+ SkFAIL("Unknown Primary Output");
}
+ codeAppendf("\t%s = %s;\n", this->getColorOutputName(), fragColor.c_str());
}
+
+const char* GrGLFragmentShaderBuilder::enableSecondaryOutput() {
+ if (!fHasSecondaryOutput) {
+ fOutputs.push_back().set(kVec4f_GrSLType,
+ GrGLShaderVar::kOut_TypeModifier,
+ dual_source_output_name());
+ fHasSecondaryOutput = true;
+ }
+ return dual_source_output_name();
+}
+
+const char* GrGLFragmentShaderBuilder::getColorOutputName() const {
+ return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
+}
+
#ifndef GrGLFragmentShaderBuilder_DEFINED
#define GrGLFragmentShaderBuilder_DEFINED
-
#include "GrGLShaderBuilder.h"
+class GrGLProgramBuilder;
+
/*
- * This base class encapsulates the functionality which the GP uses to build fragment shaders
+ * This base class encapsulates the functionality which all GrProcessors are allowed to use in their
+ * fragment shader
*/
-class GrGLGPFragmentBuilder : public GrGLShaderBuilder {
+class GrGLProcessorFragmentShaderBuilder : public GrGLShaderBuilder {
public:
- GrGLGPFragmentBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
- virtual ~GrGLGPFragmentBuilder() {}
+ GrGLProcessorFragmentShaderBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
+ virtual ~GrGLProcessorFragmentShaderBuilder() {}
/**
* Use of these features may require a GLSL extension to be enabled. Shaders may not compile
* if code is added that uses one of these features without calling enableFeature()
/*
* Fragment processor's, in addition to all of the above, may need to use dst color so they use
- * this builder to create their shader. Because this is the only shader builder the FP sees, we
- * just call it FPShaderBuilder
+ * this builder to create their shader
*/
-class GrGLFPFragmentBuilder : public GrGLGPFragmentBuilder {
+class GrGLFragmentProcessorShaderBuilder : public GrGLProcessorFragmentShaderBuilder {
public:
- GrGLFPFragmentBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
-
+ GrGLFragmentProcessorShaderBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
/** Returns the variable name that holds the color of the destination pixel. This may be NULL if
no effect advertised that it will read the destination. */
virtual const char* dstColor() = 0;
private:
- typedef GrGLGPFragmentBuilder INHERITED;
+ typedef GrGLProcessorFragmentShaderBuilder INHERITED;
};
-// TODO rename to Fragment Builder
-class GrGLFragmentShaderBuilder : public GrGLFPFragmentBuilder {
+class GrGLFragmentShaderBuilder : public GrGLFragmentProcessorShaderBuilder {
public:
typedef uint8_t DstReadKey;
typedef uint8_t FragPosKey;
GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, const GrGLProgramDesc& desc);
- // true public interface, defined explicitly in the abstract interfaces above
+ virtual const char* dstColor() SK_OVERRIDE;
+
virtual bool enableFeature(GLSLFeature) SK_OVERRIDE;
+
virtual SkString ensureFSCoords2D(const GrGLProcessor::TransformedCoordsArray& coords,
int index) SK_OVERRIDE;
- virtual const char* fragmentPosition() SK_OVERRIDE;
- virtual const char* dstColor() SK_OVERRIDE;
- // Private public interface, used by GrGLProgramBuilder to build a fragment shader
- void emitCodeToReadDstTexture();
- void enableCustomOutput();
- void enableSecondaryOutput();
- const char* getPrimaryColorOutputName() const;
- const char* getSecondaryColorOutputName() const;
- void enableSecondaryOutput(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
- void combineColorAndCoverage(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
- bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
- void bindFragmentShaderLocations(GrGLuint programID);
+ virtual const char* fragmentPosition() SK_OVERRIDE;
+private:
/*
- * An internal call for GrGLProgramBuilder to use to add varyings to the vertex shader
+ * An internal call for GrGLFullProgramBuilder to use to add varyings to the vertex shader
*/
void addVarying(GrSLType type,
const char* name,
const char** fsInName,
GrGLShaderVar::Precision fsPrecision = GrGLShaderVar::kDefault_Precision);
- // As GLProcessors emit code, there are some conditions we need to verify. We use the below
- // state to track this. The reset call is called per processor emitted.
- bool hasReadDstColor() const { return fHasReadDstColor; }
- bool hasReadFragmentPosition() const { return fHasReadFragmentPosition; }
- void reset() {
- fHasReadDstColor = false;
- fHasReadFragmentPosition = false;
- }
+ /*
+ * Private functions used by GrGLProgramBuilder for compilation
+ */
+ void bindProgramLocations(GrGLuint programId);
+ bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
+ void emitCodeBeforeEffects();
+ void emitCodeAfterEffects(const GrGLSLExpr4& inputColor, const GrGLSLExpr4& inputCoverage);
+
+ /** Enables using the secondary color output and returns the name of the var in which it is
+ to be stored */
+ const char* enableSecondaryOutput();
+
+ /** Gets the name of the primary color output. */
+ const char* getColorOutputName() const;
-private:
/**
* Features that should only be enabled by GrGLFragmentShaderBuilder itself.
*/
kTopLeftOrigin_DstReadKeyBit = 0x4, // Set if dst-copy origin is top-left.
};
- // Interpretation of FragPosKey when generating code
enum {
kNoFragPosRead_FragPosKey = 0, // The fragment positition will not be needed.
kTopLeftFragPosRead_FragPosKey = 0x1,// Read frag pos relative to top-left.
kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left.
};
- static const char* kDstCopyColorName;
-
bool fHasCustomColorOutput;
bool fHasSecondaryOutput;
bool fSetupFragPosition;
bool fTopLeftFragPosRead;
- // some state to verify shaders and effects are consistent, this is reset between effects by
- // the program creator
- bool fHasReadDstColor;
- bool fHasReadFragmentPosition;
-
- friend class GrGLNvprProgramBuilder;
friend class GrGLProgramBuilder;
+ friend class GrGLFullProgramBuilder;
- typedef GrGLFPFragmentBuilder INHERITED;
+ typedef GrGLFragmentProcessorShaderBuilder INHERITED;
};
#endif
--- /dev/null
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLFullProgramBuilder.h"
+#include "../GrGLGeometryProcessor.h"
+#include "../GrGpuGL.h"
+
+GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optState,
+ const GrGLProgramDesc& desc)
+ : INHERITED(gpu, optState, desc)
+ , fGLGeometryProcessorEmitter(this)
+ , fGS(this)
+ , fVS(this) {
+}
+
+void
+GrGLFullProgramBuilder::createAndEmitEffects(const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[],
+ GrGLSLExpr4* inputColor,
+ GrGLSLExpr4* inputCoverage) {
+ fVS.emitCodeBeforeEffects(inputColor, inputCoverage);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // emit the per-effect code for both color and coverage effects
+
+ EffectKeyProvider colorKeyProvider(&this->desc(), EffectKeyProvider::kColor_EffectType);
+ fColorEffects.reset(this->onCreateAndEmitEffects(colorStages,
+ this->desc().numColorEffects(),
+ colorKeyProvider,
+ inputColor));
+
+ if (geometryProcessor) {
+ const GrGeometryProcessor& gp = *geometryProcessor->getGeometryProcessor();
+ fGLGeometryProcessorEmitter.set(&gp);
+ fEffectEmitter = &fGLGeometryProcessorEmitter;
+ fVS.emitAttributes(gp);
+ GrGLSLExpr4 gpInputCoverage = *inputCoverage;
+ GrGLSLExpr4 gpOutputCoverage;
+ EffectKeyProvider gpKeyProvider(&this->desc(),
+ EffectKeyProvider::kGeometryProcessor_EffectType);
+ bool useLocalCoords = this->getVertexShaderBuilder()->hasExplicitLocalCoords();
+ fProgramEffects.reset(SkNEW_ARGS(GrGLVertexProgramEffects, (1, useLocalCoords)));
+ this->INHERITED::emitEffect(*geometryProcessor, 0, gpKeyProvider, &gpInputCoverage,
+ &gpOutputCoverage);
+ fGeometryProcessor.reset(fProgramEffects.detach());
+ *inputCoverage = gpOutputCoverage;
+ }
+
+ EffectKeyProvider coverageKeyProvider(&this->desc(), EffectKeyProvider::kCoverage_EffectType);
+ fCoverageEffects.reset(this->onCreateAndEmitEffects(coverageStages,
+ this->desc().numCoverageEffects(),
+ coverageKeyProvider,
+ inputCoverage));
+
+ fVS.emitCodeAfterEffects();
+}
+
+void GrGLFullProgramBuilder::addVarying(GrSLType type,
+ const char* name,
+ const char** vsOutName,
+ const char** fsInName,
+ GrGLShaderVar::Precision fsPrecision) {
+ fVS.addVarying(type, name, vsOutName);
+
+ SkString* fsInputName = fVS.fOutputs.back().accessName();
+
+#if GR_GL_EXPERIMENTAL_GS
+ if (desc().getHeader().fExperimentalGS) {
+ // TODO let the caller use these names
+ fGS.addVarying(type, fsInputName->c_str(), NULL);
+ fsInputName = fGS.fOutputs.back().accessName();
+ }
+#endif
+ fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision);
+}
+
+GrGLFullProgramBuilder::VaryingHandle
+GrGLFullProgramBuilder::addSeparableVarying(GrSLType type,
+ const char* name,
+ const char** vsOutName,
+ const char** fsInName) {
+ addVarying(type, name, vsOutName, fsInName);
+ SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back();
+ varying.fVariable = fFS.fInputs.back();
+ return VaryingHandle::CreateFromSeparableVaryingIndex(fSeparableVaryingInfos.count() - 1);
+}
+
+GrGLProgramEffects* GrGLFullProgramBuilder::onCreateAndEmitEffects(
+ const GrFragmentStage* effectStages[],
+ int effectCnt,
+ const GrGLProgramDesc::EffectKeyProvider& keyProvider,
+ GrGLSLExpr4* inOutFSColor) {
+ fProgramEffects.reset(SkNEW_ARGS(GrGLVertexProgramEffects,
+ (effectCnt,
+ this->getVertexShaderBuilder()->hasExplicitLocalCoords())));
+ this->INHERITED::createAndEmitEffects(effectStages,
+ effectCnt,
+ keyProvider,
+ inOutFSColor);
+ return fProgramEffects.detach();
+}
+
+void GrGLFullProgramBuilder::emitEffect(const GrProcessorStage& stage,
+ const GrProcessorKey& key,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) {
+ SkASSERT(fProgramEffects.get());
+ const GrProcessor& effect = *stage.getProcessor();
+ SkSTArray<2, GrGLProcessor::TransformedCoords> coords(effect.numTransforms());
+ SkSTArray<4, GrGLProcessor::TextureSampler> samplers(effect.numTextures());
+
+ this->emitTransforms(stage, &coords);
+ this->emitSamplers(effect, &samplers);
+
+ SkASSERT(fEffectEmitter);
+ GrGLProcessor* glEffect = fEffectEmitter->createGLInstance();
+ fProgramEffects->addEffect(glEffect);
+
+ // Enclose custom code in a block to avoid namespace conflicts
+ SkString openBrace;
+ openBrace.printf("{ // Stage %d: %s\n", stageIndex, glEffect->name());
+ fFS.codeAppend(openBrace.c_str());
+ fVS.codeAppend(openBrace.c_str());
+
+ fEffectEmitter->emit(key, outColor, inColor, coords, samplers);
+
+ fVS.codeAppend("\t}\n");
+ fFS.codeAppend("\t}\n");
+}
+
+void GrGLFullProgramBuilder::emitTransforms(const GrProcessorStage& effectStage,
+ GrGLProcessor::TransformedCoordsArray* outCoords) {
+ SkTArray<GrGLVertexProgramEffects::Transform, true>& transforms =
+ fProgramEffects->addTransforms();
+ const GrProcessor* effect = effectStage.getProcessor();
+ int numTransforms = effect->numTransforms();
+ transforms.push_back_n(numTransforms);
+
+ SkTArray<GrGLVertexProgramEffects::PathTransform, true>* pathTransforms = NULL;
+ const GrGLCaps* glCaps = this->ctxInfo().caps();
+ if (glCaps->pathRenderingSupport() &&
+ this->gpu()->glPathRendering()->texturingMode() ==
+ GrGLPathRendering::SeparableShaders_TexturingMode) {
+ pathTransforms = &fProgramEffects->addPathTransforms();
+ pathTransforms->push_back_n(numTransforms);
+ }
+
+ for (int t = 0; t < numTransforms; t++) {
+ const char* uniName = "StageMatrix";
+ GrSLType varyingType =
+ effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalCoords()) ?
+ kVec3f_GrSLType :
+ kVec2f_GrSLType;
+
+ SkString suffixedUniName;
+ if (0 != t) {
+ suffixedUniName.append(uniName);
+ suffixedUniName.appendf("_%i", t);
+ uniName = suffixedUniName.c_str();
+ }
+ transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
+ kMat33f_GrSLType,
+ uniName,
+ &uniName);
+
+ const char* varyingName = "MatrixCoord";
+ SkString suffixedVaryingName;
+ if (0 != t) {
+ suffixedVaryingName.append(varyingName);
+ suffixedVaryingName.appendf("_%i", t);
+ varyingName = suffixedVaryingName.c_str();
+ }
+ const char* vsVaryingName;
+ const char* fsVaryingName;
+ if (pathTransforms) {
+ (*pathTransforms)[t].fHandle =
+ this->addSeparableVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
+ (*pathTransforms)[t].fType = varyingType;
+ } else {
+ this->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
+ }
+
+ const GrGLShaderVar& coords =
+ kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ?
+ fVS.positionAttribute() :
+ fVS.localCoordsAttribute();
+ // varying = matrix * coords (logically)
+ SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
+ if (kVec2f_GrSLType == varyingType) {
+ fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
+ vsVaryingName, uniName, coords.c_str());
+ } else {
+ fVS.codeAppendf("%s = %s * vec3(%s, 1);",
+ vsVaryingName, uniName, coords.c_str());
+ }
+ SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
+ (SkString(fsVaryingName), varyingType));
+ }
+}
+
+bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId,
+ SkTDArray<GrGLuint>* shaderIds) const {
+ return INHERITED::compileAndAttachShaders(programId, shaderIds)
+ && fVS.compileAndAttachShaders(programId, shaderIds)
+#if GR_GL_EXPERIMENTAL_GS
+ && (!desc().getHeader().fExperimentalGS
+ || fGS.compileAndAttachShaders(programId, shaderIds))
+#endif
+ ;
+}
+
+void GrGLFullProgramBuilder::bindProgramLocations(GrGLuint programId) {
+ fVS.bindProgramLocations(programId);
+ INHERITED::bindProgramLocations(programId);
+}
--- /dev/null
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLFullProgramBuilder_DEFINED
+#define GrGLFullProgramBuilder_DEFINED
+
+#include "GrGLProgramBuilder.h"
+#include "../GrGLGeometryProcessor.h"
+
+class GrGLVertexProgramEffects;
+
+class GrGLFullProgramBuilder : public GrGLProgramBuilder {
+public:
+ GrGLFullProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
+
+ /** Add a varying variable to the current program to pass values between vertex and fragment
+ shaders. If the last two parameters are non-NULL, they are filled in with the name
+ generated. */
+ void addVarying(GrSLType type,
+ const char* name,
+ const char** vsOutName = NULL,
+ const char** fsInName = NULL,
+ GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision);
+
+ /** Add a separable varying input variable to the current program.
+ * A separable varying (fragment shader input) is a varying that can be used also when vertex
+ * shaders are not used. With a vertex shader, the operation is same as with other
+ * varyings. Without a vertex shader, such as with NV_path_rendering, GL APIs are used to
+ * populate the variable. The APIs can refer to the variable through the returned handle.
+ */
+ VaryingHandle addSeparableVarying(GrSLType type,
+ const char* name,
+ const char** vsOutName,
+ const char** fsInName);
+
+ GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; }
+
+ /*
+ * This non-virtual call will hide the parent call to prevent GPs from accessing fragment shader
+ * functionality they shouldn't be using
+ */
+ GrGLProcessorFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
+
+private:
+ virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[],
+ GrGLSLExpr4* inputColor,
+ GrGLSLExpr4* inputCoverage) SK_OVERRIDE;
+
+ GrGLProgramEffects* onCreateAndEmitEffects(const GrFragmentStage* effectStages[],
+ int effectCnt,
+ const GrGLProgramDesc::EffectKeyProvider&,
+ GrGLSLExpr4* inOutFSColor);
+
+ class GrGLGeometryProcessorEmitter : public GrGLProgramBuilder::GrGLProcessorEmitterInterface {
+ public:
+ GrGLGeometryProcessorEmitter(GrGLFullProgramBuilder* builder)
+ : fBuilder(builder)
+ , fGeometryProcessor(NULL)
+ , fGLGeometryProcessor(NULL) {}
+ virtual ~GrGLGeometryProcessorEmitter() {}
+ void set(const GrGeometryProcessor* gp) {
+ SkASSERT(NULL == fGeometryProcessor);
+ fGeometryProcessor = gp;
+ }
+ virtual GrGLProcessor* createGLInstance() {
+ SkASSERT(fGeometryProcessor);
+ SkASSERT(NULL == fGLGeometryProcessor);
+ fGLGeometryProcessor =
+ fGeometryProcessor->getFactory().createGLInstance(*fGeometryProcessor);
+ return fGLGeometryProcessor;
+ }
+ virtual void emit(const GrProcessorKey& key,
+ const char* outColor,
+ const char* inColor,
+ const GrGLProcessor::TransformedCoordsArray& coords,
+ const GrGLProcessor::TextureSamplerArray& samplers) {
+ SkASSERT(fGeometryProcessor);
+ SkASSERT(fGLGeometryProcessor);
+ fGLGeometryProcessor->emitCode(fBuilder, *fGeometryProcessor, key, outColor,
+ inColor, coords, samplers);
+ // this will not leak because it has already been used by createGLInstance
+ fGLGeometryProcessor = NULL;
+ fGeometryProcessor = NULL;
+ }
+ private:
+ GrGLFullProgramBuilder* fBuilder;
+ const GrGeometryProcessor* fGeometryProcessor;
+ GrGLGeometryProcessor* fGLGeometryProcessor;
+ };
+
+ virtual void emitEffect(const GrProcessorStage& stage,
+ const GrProcessorKey& key,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) SK_OVERRIDE;
+
+ /**
+ * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
+ * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
+ * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
+ * of the varyings in the VS and FS as well their types are appended to the
+ * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
+ */
+ void emitTransforms(const GrProcessorStage& effectStage,
+ GrGLProcessor::TransformedCoordsArray* outCoords);
+
+ virtual bool compileAndAttachShaders(GrGLuint programId,
+ SkTDArray<GrGLuint>* shaderIds) const SK_OVERRIDE;
+
+ virtual void bindProgramLocations(GrGLuint programId) SK_OVERRIDE;
+
+ virtual GrGLProgramEffects* getProgramEffects() SK_OVERRIDE { return fProgramEffects.get(); }
+
+ typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
+
+ GrGLGeometryProcessorEmitter fGLGeometryProcessorEmitter;
+ GrGLGeometryShaderBuilder fGS;
+ GrGLVertexShaderBuilder fVS;
+ SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
+
+ typedef GrGLProgramBuilder INHERITED;
+};
+
+#endif
#include "GrGLProgramBuilder.h"
#include "../GrGpuGL.h"
-GrGLGeometryBuilder::GrGLGeometryBuilder(GrGLProgramBuilder* program)
+GrGLGeometryShaderBuilder::GrGLGeometryShaderBuilder(GrGLFullProgramBuilder* program)
: INHERITED(program) {
}
-void GrGLGeometryBuilder::addVarying(GrSLType type,
+void GrGLGeometryShaderBuilder::addVarying(GrSLType type,
const char* name,
const char** gsOutName) {
// if we have a GS take each varying in as an array
}
-bool GrGLGeometryBuilder::compileAndAttachShaders(GrGLuint programId,
+bool GrGLGeometryShaderBuilder::compileAndAttachShaders(GrGLuint programId,
SkTDArray<GrGLuint>* shaderIds) const {
const GrGLContext& glCtx = fProgramBuilder->gpu()->glContext();
SkASSERT(fProgramBuilder->ctxInfo().glslGeneration() >= k150_GrGLSLGeneration);
SkString geomShaderSrc(GrGetGLSLVersionDecl(fProgramBuilder->ctxInfo()));
geomShaderSrc.append("layout(triangles) in;\n"
"layout(triangle_strip, max_vertices = 6) out;\n");
- this->appendDecls(fInputs, &geomShaderSrc);
- this->appendDecls(fOutputs, &geomShaderSrc);
+ fProgramBuilder->appendDecls(fInputs, &geomShaderSrc);
+ fProgramBuilder->appendDecls(fOutputs, &geomShaderSrc);
geomShaderSrc.append("void main() {\n");
geomShaderSrc.append("\tfor (int i = 0; i < 3; ++i) {\n"
"\t\tgl_Position = gl_in[i].gl_Position;\n");
#include "GrGLShaderBuilder.h"
-class GrGLGeometryBuilder : public GrGLShaderBuilder {
+class GrGLProgramBuilder;
+
+class GrGLGeometryShaderBuilder : public GrGLFullShaderBuilder {
public:
- GrGLGeometryBuilder(GrGLProgramBuilder* program);
+ GrGLGeometryShaderBuilder(GrGLFullProgramBuilder* program);
+private:
/*
* an internal call for GrGLFullProgramBuilder to add varyings
*/
bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
- typedef GrGLShaderBuilder INHERITED;
+ friend class GrGLFullProgramBuilder;
+ typedef GrGLFullShaderBuilder INHERITED;
};
#endif
+++ /dev/null
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrGLLegacyNvprProgramBuilder.h"
-#include "../GrGpuGL.h"
-
-GrGLLegacyNvprProgramBuilder::GrGLLegacyNvprProgramBuilder(GrGpuGL* gpu,
- const GrOptDrawState& optState,
- const GrGLProgramDesc& desc)
- : INHERITED(gpu, optState, desc)
- , fTexCoordSetCnt(0) {
- SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
- SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
-}
-
-int GrGLLegacyNvprProgramBuilder::addTexCoordSets(int count) {
- int firstFreeCoordSet = fTexCoordSetCnt;
- fTexCoordSetCnt += count;
- SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt);
- return firstFreeCoordSet;
-}
-
-void GrGLLegacyNvprProgramBuilder::emitTransforms(const GrProcessorStage& processorStage,
- GrGLProcessor::TransformedCoordsArray* outCoords,
- GrGLInstalledProcessors* installedProcessors) {
- int numTransforms = processorStage.getProcessor()->numTransforms();
- int texCoordIndex = this->addTexCoordSets(numTransforms);
-
- SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
- installedProcessors->addTransforms();
-
- // Use the first uniform location as the texcoord index. This may seem a bit hacky but it
- // allows us to use one program effects object for all of our programs which really simplifies
- // the code overall
- transforms.push_back_n(1);
- transforms[0].fHandle = GrGLInstalledProcessors::ShaderVarHandle(texCoordIndex);
-
- SkString name;
- for (int t = 0; t < numTransforms; ++t) {
- GrSLType type = processorStage.isPerspectiveCoordTransform(t, false) ? kVec3f_GrSLType :
- kVec2f_GrSLType;
-
- name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
- SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, (name, type));
- }
-}
-
-GrGLProgram* GrGLLegacyNvprProgramBuilder::createProgram(GrGLuint programID) {
- return SkNEW_ARGS(GrGLLegacyNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
- fColorEffects, fCoverageEffects, fTexCoordSetCnt));
-}
+++ /dev/null
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrGLLegacyNvprProgramBuilder_DEFINED
-#define GrGLLegacyNvprProgramBuilder_DEFINED
-
-#include "GrGLProgramBuilder.h"
-
-class GrGLLegacyNvprProgramBuilder : public GrGLProgramBuilder {
-public:
- GrGLLegacyNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
-
- virtual GrGLProgram* createProgram(GrGLuint programID);
-
-private:
- int addTexCoordSets(int count);
- void emitTransforms(const GrProcessorStage&,
- GrGLProcessor::TransformedCoordsArray* outCoords,
- GrGLInstalledProcessors*);
-
- int fTexCoordSetCnt;
-
- typedef GrGLProgramBuilder INHERITED;
-};
-
-#endif
+++ /dev/null
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrGLNvprProgramBuilder.h"
-#include "../GrGpuGL.h"
-
-#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
-#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
-
-GrGLNvprProgramBuilder::GrGLNvprProgramBuilder(GrGpuGL* gpu,
- const GrOptDrawState& optState,
- const GrGLProgramDesc& desc)
- : INHERITED(gpu, optState, desc)
- , fSeparableVaryingInfos(kVarsPerBlock) {
-}
-
-void GrGLNvprProgramBuilder::emitTransforms(const GrProcessorStage& processorStage,
- GrGLProcessor::TransformedCoordsArray* outCoords,
- GrGLInstalledProcessors* installedProcessors) {
- const GrProcessor* effect = processorStage.getProcessor();
- int numTransforms = effect->numTransforms();
-
- SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
- installedProcessors->addTransforms();
- transforms.push_back_n(numTransforms);
-
- for (int t = 0; t < numTransforms; t++) {
- GrSLType varyingType =
- processorStage.isPerspectiveCoordTransform(t, false) ?
- kVec3f_GrSLType :
- kVec2f_GrSLType;
-
- const char* varyingName = "MatrixCoord";
- SkString suffixedVaryingName;
- if (0 != t) {
- suffixedVaryingName.append(varyingName);
- suffixedVaryingName.appendf("_%i", t);
- varyingName = suffixedVaryingName.c_str();
- }
- const char* vsVaryingName;
- const char* fsVaryingName;
- transforms[t].fHandle = this->addSeparableVarying(varyingType, varyingName,
- &vsVaryingName, &fsVaryingName);
- transforms[t].fType = varyingType;
-
- SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
- (SkString(fsVaryingName), varyingType));
- }
-}
-
-GrGLInstalledProcessors::ShaderVarHandle
-GrGLNvprProgramBuilder::addSeparableVarying(GrSLType type,
- const char* name,
- const char** vsOutName,
- const char** fsInName) {
- addVarying(type, name, vsOutName, fsInName);
- SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back();
- varying.fVariable = fFS.fInputs.back();
- return GrGLInstalledProcessors::ShaderVarHandle(fSeparableVaryingInfos.count() - 1);
-}
-
-void GrGLNvprProgramBuilder::resolveSeparableVaryings(GrGLuint programId) {
- int count = fSeparableVaryingInfos.count();
- for (int i = 0; i < count; ++i) {
- GrGLint location;
- GL_CALL_RET(location,
- GetProgramResourceLocation(programId,
- GR_GL_FRAGMENT_INPUT,
- fSeparableVaryingInfos[i].fVariable.c_str()));
- fSeparableVaryingInfos[i].fLocation = location;
- }
-}
-
-GrGLProgram* GrGLNvprProgramBuilder::createProgram(GrGLuint programID) {
- // this is just for nvpr es, which has separable varyings that are plugged in after
- // building
- this->resolveSeparableVaryings(programID);
- return SkNEW_ARGS(GrGLNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
- fColorEffects, fCoverageEffects, fSeparableVaryingInfos));
-}
+++ /dev/null
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrGLNvprProgramBuilder_DEFINED
-#define GrGLNvprProgramBuilder_DEFINED
-
-#include "GrGLProgramBuilder.h"
-
-class GrGLNvprProgramBuilder : public GrGLProgramBuilder {
-public:
- GrGLNvprProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
-
- /*
- * The separable varying info must be passed to GrGLProgram so this must
- * be part of the public interface
- */
- struct SeparableVaryingInfo {
- GrGLShaderVar fVariable;
- GrGLint fLocation;
- };
-
- typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
-
- virtual GrGLProgram* createProgram(GrGLuint programID);
-
-private:
- virtual void emitTransforms(const GrProcessorStage&,
- GrGLProcessor::TransformedCoordsArray* outCoords,
- GrGLInstalledProcessors*) SK_OVERRIDE;
-
- typedef GrGLInstalledProcessors::ShaderVarHandle ShaderVarHandle;
-
- /**
- * Add a separable varying input variable to the current program.
- * A separable varying (fragment shader input) is a varying that can be used also when vertex
- * shaders are not used. With a vertex shader, the operation is same as with other
- * varyings. Without a vertex shader, such as with NV_path_rendering, GL APIs are used to
- * populate the variable. The APIs can refer to the variable through the returned handle.
- */
- ShaderVarHandle addSeparableVarying(GrSLType type,
- const char* name,
- const char** vsOutName,
- const char** fsInName);
-
- void resolveSeparableVaryings(GrGLuint programId);
-
- SeparableVaryingInfoArray fSeparableVaryingInfos;
-
- typedef GrGLProgramBuilder INHERITED;
-};
-
-#endif
* found in the LICENSE file.
*/
-#include "GrGLProgramBuilder.h"
-#include "gl/GrGLGeometryProcessor.h"
#include "gl/GrGLProgram.h"
#include "gl/GrGLSLPrettyPrint.h"
#include "gl/GrGLUniformHandle.h"
-#include "../GrGpuGL.h"
#include "GrCoordTransform.h"
-#include "GrGLLegacyNvprProgramBuilder.h"
-#include "GrGLNvprProgramBuilder.h"
+#include "../GrGpuGL.h"
+#include "GrGLFragmentShaderBuilder.h"
#include "GrGLProgramBuilder.h"
#include "GrTexture.h"
+#include "GrGLVertexShaderBuilder.h"
#include "SkRTConf.h"
#include "SkTraceEvent.h"
+namespace {
#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->gpu()->glInterface(), R, X)
+// number of each input/output type in a single allocation block
+static const int kVarsPerBlock = 8;
+
// ES2 FS only guarantees mediump and lowp support
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
+}
-//////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////
-const int GrGLProgramBuilder::kVarsPerBlock = 8;
-
-GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState,
- const GrGLProgramDesc& desc,
- GrGpu::DrawType drawType,
- const GrGeometryStage* geometryProcessor,
- const GrFragmentStage* colorStages[],
- const GrFragmentStage* coverageStages[],
- GrGpuGL* gpu) {
- // create a builder. This will be handed off to effects so they can use it to add
- // uniforms, varyings, textures, etc
- SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(desc,
- optState,
- drawType,
- SkToBool(geometryProcessor),
- gpu));
-
- GrGLProgramBuilder* pb = builder.get();
- const GrGLProgramDesc::KeyHeader& header = pb->header();
-
- // emit code to read the dst copy texture, if necessary
- if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey
- && !gpu->glCaps().fbFetchSupport()) {
- pb->fFS.emitCodeToReadDstTexture();
- }
+bool GrGLProgramBuilder::genProgram(const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[]) {
+ const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
+
+ fFS.emitCodeBeforeEffects();
+ ///////////////////////////////////////////////////////////////////////////
// get the initial color and coverage to feed into the first effect in each effect chain
- GrGLSLExpr4 inputColor, inputCoverage;
- pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage);
-
- // if we have a vertex shader(we don't only if we are using NVPR or NVPR ES), then we may have
- // to setup a few more things like builtin vertex attributes
- bool hasVertexShader = !header.fUseFragShaderOnly;
- if (hasVertexShader) {
- pb->fVS.setupLocalCoords();
- pb->fVS.transformGLToSkiaCoords();
- if (header.fEmitsPointSize) {
- pb->fVS.codeAppend("gl_PointSize = 1.0;");
- }
- if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
- pb->fVS.setupBuiltinVertexAttribute("Color", &inputColor);
- }
- if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
- pb->fVS.setupBuiltinVertexAttribute("Coverage", &inputCoverage);
- }
- }
- pb->createAndEmitProcessors(geometryProcessor, colorStages, coverageStages, &inputColor,
- &inputCoverage);
+ GrGLSLExpr4 inputColor;
+ GrGLSLExpr4 inputCoverage;
- if (hasVertexShader) {
- pb->fVS.transformSkiaToGLCoords();
+ if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
+ const char* name;
+ fUniformHandles.fColorUni =
+ this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ "Color",
+ &name);
+ inputColor = GrGLSLExpr4(name);
+ } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
+ inputColor = GrGLSLExpr4(1);
}
- // write the secondary color output if necessary
- if (GrOptDrawState::kNone_SecondaryOutputType != header.fSecondaryOutputType) {
- pb->fFS.enableSecondaryOutput(inputColor, inputCoverage);
+ if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
+ const char* name;
+ fUniformHandles.fCoverageUni =
+ this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ "Coverage",
+ &name);
+ inputCoverage = GrGLSLExpr4(name);
+ } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
+ inputCoverage = GrGLSLExpr4(1);
}
- pb->fFS.combineColorAndCoverage(inputColor, inputCoverage);
+ // Subclasses drive effect emitting
+ this->createAndEmitEffects(geometryProcessor, colorStages, coverageStages, &inputColor,
+ &inputCoverage);
- return pb->finalize();
-}
+ fFS.emitCodeAfterEffects(inputColor, inputCoverage);
-GrGLProgramBuilder*
-GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc,
- const GrOptDrawState& optState,
- GrGpu::DrawType drawType,
- bool hasGeometryProcessor,
- GrGpuGL* gpu) {
- if (desc.getHeader().fUseFragShaderOnly) {
- SkASSERT(gpu->glCaps().pathRenderingSupport());
- SkASSERT(gpu->glPathRendering()->texturingMode() ==
- GrGLPathRendering::FixedFunction_TexturingMode);
- SkASSERT(!hasGeometryProcessor);
- return SkNEW_ARGS(GrGLLegacyNvprProgramBuilder, (gpu, optState, desc));
- } else if (GrGpu::IsPathRenderingDrawType(drawType)) {
- SkASSERT(gpu->glCaps().pathRenderingSupport());
- SkASSERT(gpu->glPathRendering()->texturingMode() ==
- GrGLPathRendering::SeparableShaders_TexturingMode);
- SkASSERT(!hasGeometryProcessor);
- return SkNEW_ARGS(GrGLNvprProgramBuilder, (gpu, optState, desc));
- } else {
- return SkNEW_ARGS(GrGLProgramBuilder, (gpu, optState, desc));
+ if (!this->finish()) {
+ return false;
}
+
+ return true;
}
-/////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optState,
const GrGLProgramDesc& desc)
- : fVS(this)
- , fGS(this)
+ : fEffectEmitter(NULL)
+ , fFragOnly(SkToBool(desc.getHeader().fUseFragShaderOnly))
+ , fTexCoordSetCnt(0)
+ , fProgramID(0)
, fFS(this, desc)
- , fOutOfStage(true)
- , fStageIndex(-1)
+ , fSeparableVaryingInfos(kVarsPerBlock)
+ , fGrProcessorEmitter(this)
, fOptState(optState)
, fDesc(desc)
, fGpu(gpu)
, fUniforms(kVarsPerBlock) {
}
-void GrGLProgramBuilder::addVarying(GrSLType type,
- const char* name,
- const char** vsOutName,
- const char** fsInName,
- GrGLShaderVar::Precision fsPrecision) {
- SkString* fsInputName = fVS.addVarying(type, name, vsOutName);
- fFS.addVarying(type, fsInputName->c_str(), fsInName, fsPrecision);
-}
-
void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name) {
if ('\0' == prefix) {
*out = name;
} else {
out->printf("%c%s", prefix, name);
}
- if (!fOutOfStage) {
+ if (fCodeStage.inStageCode()) {
if (out->endsWith('_')) {
// Names containing "__" are reserved.
out->append("x");
}
- out->appendf("_Stage%d", fStageIndex);
+ out->appendf("_Stage%d", fCodeStage.stageIndex());
}
}
return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fUniforms.count() - 1);
}
+void GrGLProgramBuilder::appendDecls(const VarArray& vars, SkString* out) const {
+ for (int i = 0; i < vars.count(); ++i) {
+ vars[i].appendDecl(this->ctxInfo(), out);
+ out->append(";\n");
+ }
+}
+
void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
SkString* out) const {
for (int i = 0; i < fUniforms.count(); ++i) {
}
}
-const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
- return fGpu->ctxInfo();
-}
-
-void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor,
- GrGLSLExpr4* inputCoverage) {
- const GrGLProgramDesc::KeyHeader& header = this->header();
- if (GrGLProgramDesc::kUniform_ColorInput == header.fColorInput) {
- const char* name;
- fUniformHandles.fColorUni =
- this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kVec4f_GrSLType,
- "Color",
- &name);
- *inputColor = GrGLSLExpr4(name);
- } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
- *inputColor = GrGLSLExpr4(1);
- }
- if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
- const char* name;
- fUniformHandles.fCoverageUni =
- this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kVec4f_GrSLType,
- "Coverage",
- &name);
- *inputCoverage = GrGLSLExpr4(name);
- } else if (GrGLProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
- *inputCoverage = GrGLSLExpr4(1);
- }
-}
-
-void GrGLProgramBuilder::createAndEmitProcessors(const GrGeometryStage* geometryProcessor,
- const GrFragmentStage* colorStages[],
- const GrFragmentStage* coverageStages[],
- GrGLSLExpr4* inputColor,
- GrGLSLExpr4* inputCoverage) {
- bool useLocalCoords = fVS.hasExplicitLocalCoords();
-
- EffectKeyProvider colorKeyProvider(&fDesc, EffectKeyProvider::kColor_EffectType);
- int numColorEffects = fDesc.numColorEffects();
- GrGLInstalledProcessors* ip = SkNEW_ARGS(GrGLInstalledProcessors, (numColorEffects,
- useLocalCoords));
- this->createAndEmitProcessors<GrFragmentStage>(colorStages, numColorEffects, colorKeyProvider,
- inputColor, ip);
- fColorEffects.reset(ip);
-
- if (geometryProcessor) {
- fVS.emitAttributes(*geometryProcessor->getProcessor());
- EffectKeyProvider gpKeyProvider(&fDesc, EffectKeyProvider::kGeometryProcessor_EffectType);
- ip = SkNEW_ARGS(GrGLInstalledProcessors, (1, useLocalCoords));
- this->createAndEmitProcessors<GrGeometryStage>(&geometryProcessor, 1, gpKeyProvider,
- inputCoverage, ip);
- fGeometryProcessor.reset(ip);
- }
-
- EffectKeyProvider coverageKeyProvider(&fDesc, EffectKeyProvider::kCoverage_EffectType);
- int numCoverageEffects = fDesc.numCoverageEffects();
- ip = SkNEW_ARGS(GrGLInstalledProcessors, (numCoverageEffects, useLocalCoords));
- this->createAndEmitProcessors<GrFragmentStage>(coverageStages, numCoverageEffects,
- coverageKeyProvider, inputCoverage, ip);
- fCoverageEffects.reset(ip);
-}
-
-template <class ProcessorStage>
-void GrGLProgramBuilder::createAndEmitProcessors(const ProcessorStage* processStages[],
- int effectCnt,
- const EffectKeyProvider& keyProvider,
- GrGLSLExpr4* fsInOutColor,
- GrGLInstalledProcessors* installedProcessors) {
+void GrGLProgramBuilder::createAndEmitEffects(const GrFragmentStage* effectStages[],
+ int effectCnt,
+ const GrGLProgramDesc::EffectKeyProvider& keyProvider,
+ GrGLSLExpr4* fsInOutColor) {
bool effectEmitted = false;
GrGLSLExpr4 inColor = *fsInOutColor;
GrGLSLExpr4 outColor;
for (int e = 0; e < effectCnt; ++e) {
- // Program builders have a bit of state we need to clear with each effect
- this->reset();
- const ProcessorStage& stage = *processStages[e];
- SkASSERT(stage.getProcessor());
-
- if (inColor.isZeros()) {
- SkString inColorName;
-
- // Effects have no way to communicate zeros, they treat an empty string as ones.
- this->nameVariable(&inColorName, '\0', "input");
- fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str());
- inColor = inColorName;
- }
-
- // create var to hold stage result
- SkString outColorName;
- this->nameVariable(&outColorName, '\0', "output");
- fFS.codeAppendf("vec4 %s;", outColorName.c_str());
- outColor = outColorName;
-
- SkASSERT(installedProcessors);
- const typename ProcessorStage::Processor& processor = *stage.getProcessor();
- SkSTArray<2, GrGLProcessor::TransformedCoords> coords(processor.numTransforms());
- SkSTArray<4, GrGLProcessor::TextureSampler> samplers(processor.numTextures());
-
- this->emitTransforms(stage, &coords, installedProcessors);
- this->emitSamplers(processor, &samplers, installedProcessors);
-
- typename ProcessorStage::GLProcessor* glEffect =
- processor.getFactory().createGLInstance(processor);
- installedProcessors->addEffect(glEffect);
-
- // Enclose custom code in a block to avoid namespace conflicts
- SkString openBrace;
- openBrace.printf("{ // Stage %d: %s\n", fStageIndex, glEffect->name());
- fFS.codeAppend(openBrace.c_str());
-
- glEffect->emitCode(this, processor, keyProvider.get(e), outColor.c_str(), inColor.c_str(),
- coords, samplers);
-
- // We have to check that effects and the code they emit are consistent, ie if an effect
- // asks for dst color, then the emit code needs to follow suit
- verify(processor);
- fFS.codeAppend("}");
-
- inColor = outColor;
+ fGrProcessorEmitter.set(effectStages[e]->getFragmentProcessor());
+ fEffectEmitter = &fGrProcessorEmitter;
+ // calls into the subclass to emit the actual effect into the program effect object
+ this->emitEffect(*effectStages[e], e, keyProvider, &inColor, &outColor);
effectEmitted = true;
}
}
}
-void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) {
- SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
-}
+void GrGLProgramBuilder::emitEffect(const GrProcessorStage& effectStage,
+ int effectIndex,
+ const GrGLProgramDesc::EffectKeyProvider& keyProvider,
+ GrGLSLExpr4* inColor,
+ GrGLSLExpr4* outColor) {
+ SkASSERT(effectStage.getProcessor());
+ CodeStage::AutoStageRestore csar(&fCodeStage, &effectStage);
+
+ if (inColor->isZeros()) {
+ SkString inColorName;
+
+ // Effects have no way to communicate zeros, they treat an empty string as ones.
+ this->nameVariable(&inColorName, '\0', "input");
+ fFS.codeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor->c_str());
+ *inColor = inColorName;
+ }
-void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
- SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
- SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor());
-}
+ // create var to hold stage result
+ SkString outColorName;
+ this->nameVariable(&outColorName, '\0', "output");
+ fFS.codeAppendf("\tvec4 %s;\n", outColorName.c_str());
+ *outColor = outColorName;
-void GrGLProgramBuilder::emitTransforms(const GrProcessorStage& effectStage,
- GrGLProcessor::TransformedCoordsArray* outCoords,
- GrGLInstalledProcessors* installedProcessors) {
- SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
- installedProcessors->addTransforms();
- const GrProcessor* effect = effectStage.getProcessor();
- int numTransforms = effect->numTransforms();
- transforms.push_back_n(numTransforms);
-
- for (int t = 0; t < numTransforms; t++) {
- const char* uniName = "StageMatrix";
- GrSLType varyingType =
- effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalCoords()) ?
- kVec3f_GrSLType :
- kVec2f_GrSLType;
-
- SkString suffixedUniName;
- if (0 != t) {
- suffixedUniName.append(uniName);
- suffixedUniName.appendf("_%i", t);
- uniName = suffixedUniName.c_str();
- }
- transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
- kMat33f_GrSLType,
- uniName,
- &uniName).toShaderBuilderIndex();
-
- const char* varyingName = "MatrixCoord";
- SkString suffixedVaryingName;
- if (0 != t) {
- suffixedVaryingName.append(varyingName);
- suffixedVaryingName.appendf("_%i", t);
- varyingName = suffixedVaryingName.c_str();
- }
- const char* vsVaryingName;
- const char* fsVaryingName;
- this->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
-
- const GrGLShaderVar& coords =
- kPosition_GrCoordSet == effect->coordTransform(t).sourceCoords() ?
- fVS.positionAttribute() :
- fVS.localCoordsAttribute();
-
- // varying = matrix * coords (logically)
- SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
- if (kVec2f_GrSLType == varyingType) {
- fVS.codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
- vsVaryingName, uniName, coords.c_str());
- } else {
- fVS.codeAppendf("%s = %s * vec3(%s, 1);",
- vsVaryingName, uniName, coords.c_str());
- }
- SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
- (SkString(fsVaryingName), varyingType));
- }
+ this->emitEffect(effectStage, keyProvider.get(effectIndex), outColor->c_str(),
+ inColor->isOnes() ? NULL : inColor->c_str(), fCodeStage.stageIndex());
+
+ *inColor = *outColor;
}
-void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
- GrGLProcessor::TextureSamplerArray* outSamplers,
- GrGLInstalledProcessors* installedProcessors) {
- SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = installedProcessors->addSamplers();
- int numTextures = processor.numTextures();
+void GrGLProgramBuilder::emitSamplers(const GrProcessor& effect,
+ GrGLProcessor::TextureSamplerArray* outSamplers) {
+ SkTArray<GrGLProgramEffects::Sampler, true>& samplers =
+ this->getProgramEffects()->addSamplers();
+ int numTextures = effect.numTextures();
samplers.push_back_n(numTextures);
SkString name;
for (int t = 0; t < numTextures; ++t) {
kSampler2D_GrSLType,
name.c_str());
SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
- (samplers[t].fUniform, processor.textureAccess(t)));
+ (samplers[t].fUniform, effect.textureAccess(t)));
}
}
-GrGLProgram* GrGLProgramBuilder::finalize() {
- // verify we can get a program id
- GrGLuint programID;
- GL_CALL_RET(programID, CreateProgram());
- if (0 == programID) {
- return NULL;
+bool GrGLProgramBuilder::finish() {
+ SkASSERT(0 == fProgramID);
+ GL_CALL_RET(fProgramID, CreateProgram());
+ if (!fProgramID) {
+ return false;
}
- // compile shaders and bind attributes / uniforms
SkTDArray<GrGLuint> shadersToDelete;
- if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
- this->cleanupProgram(programID, shadersToDelete);
- return NULL;
- }
- if (!this->header().fUseFragShaderOnly) {
- if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) {
- this->cleanupProgram(programID, shadersToDelete);
- return NULL;
- }
- fVS.bindVertexAttributes(programID);
- }
- bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
- if (usingBindUniform) {
- this->bindUniformLocations(programID);
+
+ if (!this->compileAndAttachShaders(fProgramID, &shadersToDelete)) {
+ GL_CALL(DeleteProgram(fProgramID));
+ return false;
}
- fFS.bindFragmentShaderLocations(programID);
- GL_CALL(LinkProgram(programID));
+
+ this->bindProgramLocations(fProgramID);
+
+ GL_CALL(LinkProgram(fProgramID));
// Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
bool checkLinked = !fGpu->ctxInfo().isChromium();
checkLinked = true;
#endif
if (checkLinked) {
- checkLinkStatus(programID);
+ GrGLint linked = GR_GL_INIT_ZERO;
+ GL_CALL(GetProgramiv(fProgramID, GR_GL_LINK_STATUS, &linked));
+ if (!linked) {
+ GrGLint infoLen = GR_GL_INIT_ZERO;
+ 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(fProgramID,
+ infoLen+1,
+ &length,
+ (char*)log.get()));
+ GrPrintf((char*)log.get());
+ }
+ SkDEBUGFAIL("Error linking program");
+ GL_CALL(DeleteProgram(fProgramID));
+ fProgramID = 0;
+ return false;
+ }
}
- if (!usingBindUniform) {
- this->resolveUniformLocations(programID);
+
+ this->resolveProgramLocations(fProgramID);
+
+ for (int i = 0; i < shadersToDelete.count(); ++i) {
+ GL_CALL(DeleteShader(shadersToDelete[i]));
}
- this->cleanupShaders(shadersToDelete);
+ return true;
+}
- return this->createProgram(programID);
+bool GrGLProgramBuilder::compileAndAttachShaders(GrGLuint programId,
+ SkTDArray<GrGLuint>* shaderIds) const {
+ return fFS.compileAndAttachShaders(programId, shaderIds);
}
-void GrGLProgramBuilder::bindUniformLocations(GrGLuint programID) {
- int count = fUniforms.count();
- for (int i = 0; i < count; ++i) {
- GL_CALL(BindUniformLocation(programID, i, fUniforms[i].fVariable.c_str()));
- fUniforms[i].fLocation = i;
+void GrGLProgramBuilder::bindProgramLocations(GrGLuint programId) {
+ fFS.bindProgramLocations(programId);
+
+ // skbug.com/2056
+ bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
+ if (usingBindUniform) {
+ int count = fUniforms.count();
+ for (int i = 0; i < count; ++i) {
+ GL_CALL(BindUniformLocation(programId, i, fUniforms[i].fVariable.c_str()));
+ fUniforms[i].fLocation = i;
+ }
}
}
-bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID) {
- GrGLint linked = GR_GL_INIT_ZERO;
- GL_CALL(GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
- if (!linked) {
- GrGLint infoLen = GR_GL_INIT_ZERO;
- GL_CALL(GetProgramiv(programID, 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(programID,
- infoLen+1,
- &length,
- (char*)log.get()));
- GrPrintf((char*)log.get());
+void GrGLProgramBuilder::resolveProgramLocations(GrGLuint programId) {
+ bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
+ if (!usingBindUniform) {
+ int count = fUniforms.count();
+ for (int i = 0; i < count; ++i) {
+ GrGLint location;
+ GL_CALL_RET(location,
+ GetUniformLocation(programId, fUniforms[i].fVariable.c_str()));
+ fUniforms[i].fLocation = location;
}
- SkDEBUGFAIL("Error linking program");
- GL_CALL(DeleteProgram(programID));
- programID = 0;
}
- return SkToBool(linked);
-}
-void GrGLProgramBuilder::resolveUniformLocations(GrGLuint programID) {
- int count = fUniforms.count();
+ int count = fSeparableVaryingInfos.count();
for (int i = 0; i < count; ++i) {
GrGLint location;
- GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
- fUniforms[i].fLocation = location;
- }
-}
-
-void GrGLProgramBuilder::cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs) {
- GL_CALL(DeleteProgram(programID));
- cleanupShaders(shaderIDs);
-}
-void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
- for (int i = 0; i < shaderIDs.count(); ++i) {
- GL_CALL(DeleteShader(shaderIDs[i]));
+ GL_CALL_RET(location,
+ GetProgramResourceLocation(programId,
+ GR_GL_FRAGMENT_INPUT,
+ fSeparableVaryingInfos[i].fVariable.c_str()));
+ fSeparableVaryingInfos[i].fLocation = location;
}
}
-GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
- return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
- fGeometryProcessor, fColorEffects, fCoverageEffects));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-GrGLInstalledProcessors::~GrGLInstalledProcessors() {
- int numEffects = fGLProcessors.count();
- for (int e = 0; e < numEffects; ++e) {
- SkDELETE(fGLProcessors[e]);
- }
+const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
+ return fGpu->ctxInfo();
}
#ifndef GrGLProgramBuilder_DEFINED
#define GrGLProgramBuilder_DEFINED
+#include "GrAllocator.h"
+#include "GrBackendProcessorFactory.h"
+#include "GrColor.h"
+#include "GrProcessor.h"
#include "GrGLFragmentShaderBuilder.h"
#include "GrGLGeometryShaderBuilder.h"
#include "GrGLVertexShaderBuilder.h"
-#include "../GrGLProgramDataManager.h"
-#include "../GrGLUniformHandle.h"
+#include "SkTypes.h"
+#include "gl/GrGLProcessor.h"
+#include "gl/GrGLProgramDesc.h"
+#include "gl/GrGLProgramEffects.h"
+#include "gl/GrGLSL.h"
+#include "gl/GrGLProgramDataManager.h"
-class GrGLInstalledProcessors;
+#include <stdarg.h>
-/*
- * This is the base class for a series of interfaces. This base class *MUST* remain abstract with
- * NO data members because it is used in multiple interface inheritance.
- * Heirarchy:
- * GrGLUniformBuilder
- * / \
- * GrGLFPBuilder GrGLGPBuilder
- * \ /
- * GrGLProgramBuilder(internal use only)
- */
-class GrGLUniformBuilder {
+class GrGLContextInfo;
+class GrProcessorStage;
+class GrGLProgramDesc;
+
+/**
+ Contains all the incremental state of a shader as it is being built,as well as helpers to
+ manipulate that state.
+*/
+class GrGLProgramBuilder {
public:
enum ShaderVisibility {
kVertex_Visibility = 0x1,
kFragment_Visibility = 0x4,
};
- virtual ~GrGLUniformBuilder() {}
-
typedef GrGLProgramDataManager::UniformHandle UniformHandle;
+ typedef GrGLProgramDataManager::VaryingHandle VaryingHandle;
- /** Add a uniform variable to the current program, that has visibility in one or more shaders.
- visibility is a bitfield of ShaderVisibility values indicating from which shaders the
- uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
- supported at this time. The actual uniform name will be mangled. If outName is not NULL then
- it will refer to the final uniform name after return. Use the addUniformArray variant to add
- an array of uniforms. */
- virtual UniformHandle addUniform(uint32_t visibility,
- GrSLType type,
- const char* name,
- const char** outName = NULL) = 0;
- virtual UniformHandle addUniformArray(uint32_t visibility,
- GrSLType type,
- const char* name,
- int arrayCount,
- const char** outName = NULL) = 0;
-
- virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0;
-
- /**
- * Shortcut for getUniformVariable(u).c_str()
- */
- virtual const char* getUniformCStr(UniformHandle u) const = 0;
-
- virtual const GrGLContextInfo& ctxInfo() const = 0;
-
- virtual GrGpuGL* gpu() const = 0;
+ // Handles for program uniforms (other than per-effect uniforms)
+ struct BuiltinUniformHandles {
+ UniformHandle fViewMatrixUni;
+ UniformHandle fRTAdjustmentUni;
+ UniformHandle fColorUni;
+ UniformHandle fCoverageUni;
- /*
- * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
- */
-};
+ // We use the render target height to provide a y-down frag coord when specifying
+ // origin_upper_left is not supported.
+ UniformHandle fRTHeightUni;
-/* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
-class GrGLGPBuilder : public virtual GrGLUniformBuilder {
-public:
- virtual void addVarying(GrSLType type,
- const char* name,
- const char** vsOutName = NULL,
- const char** fsInName = NULL,
- GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) = 0;
+ // Uniforms for computing texture coords to do the dst-copy lookup
+ UniformHandle fDstCopyTopLeftUni;
+ UniformHandle fDstCopyScaleUni;
+ UniformHandle fDstCopySamplerUni;
+ };
- // TODO rename getFragmentBuilder
- virtual GrGLGPFragmentBuilder* getFragmentShaderBuilder() = 0;
- virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
+ struct UniformInfo {
+ GrGLShaderVar fVariable;
+ uint32_t fVisibility;
+ GrGLint fLocation;
+ };
- /*
- * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
- */
-};
+ // This uses an allocator rather than array so that the GrGLShaderVars don't move in memory
+ // after they are inserted. Users of GrGLShaderBuilder get refs to the vars and ptrs to their
+ // name strings. Otherwise, we'd have to hand out copies.
+ typedef GrTAllocator<UniformInfo> UniformInfoArray;
-/* a specializations for FPs. Lets the user add uniforms and FS code */
-class GrGLFPBuilder : public virtual GrGLUniformBuilder {
-public:
- virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() = 0;
+ struct SeparableVaryingInfo {
+ GrGLShaderVar fVariable;
+ GrGLint fLocation;
+ };
- /*
- * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
- */
-};
+ typedef GrTAllocator<SeparableVaryingInfo> SeparableVaryingInfoArray;
-/*
- * Please note - no diamond problems because of virtual inheritance. Also, both base classes
- * are pure virtual with no data members. This is the base class for program building.
- * Subclasses are nearly identical but each has their own way of emitting transforms. State for
- * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those
- * respective builders
-*/
-class GrGLProgramBuilder : public GrGLGPBuilder,
- public GrGLFPBuilder {
-public:
/** Generates a shader program.
*
* The program implements what is specified in the stages given as input.
* to be used.
* @return true if generation was successful.
*/
- static GrGLProgram* CreateProgram(const GrOptDrawState&,
- const GrGLProgramDesc&,
- GrGpu::DrawType,
- const GrGeometryStage* inGeometryProcessor,
- const GrFragmentStage* inColorStages[],
- const GrFragmentStage* inCoverageStages[],
- GrGpuGL* gpu);
-
- virtual UniformHandle addUniform(uint32_t visibility,
- GrSLType type,
- const char* name,
- const char** outName = NULL) SK_OVERRIDE {
+
+ bool genProgram(const GrGeometryStage* inGeometryProcessor,
+ const GrFragmentStage* inColorStages[],
+ const GrFragmentStage* inCoverageStages[]);
+
+ GrGLProgramEffects* getGeometryProcessor() const {
+ SkASSERT(fProgramID); return fGeometryProcessor.get();
+ }
+ GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); }
+ GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); }
+ const BuiltinUniformHandles& getBuiltinUniformHandles() const {
+ SkASSERT(fProgramID);
+ return fUniformHandles;
+ }
+ GrGLuint getProgramID() const { SkASSERT(fProgramID); return fProgramID; }
+ bool hasVertexShader() const { SkASSERT(fProgramID); return !fFragOnly; }
+ int getTexCoordSetCount() const { SkASSERT(fProgramID); return fTexCoordSetCnt; }
+ const UniformInfoArray& getUniformInfos() const { return fUniforms; }
+ const SeparableVaryingInfoArray& getSeparableVaryingInfos() const {
+ return fSeparableVaryingInfos;
+ }
+
+ virtual ~GrGLProgramBuilder() {}
+
+ /** Add a uniform variable to the current program, that has visibility in one or more shaders.
+ visibility is a bitfield of ShaderVisibility values indicating from which shaders the
+ uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not
+ supported at this time. The actual uniform name will be mangled. If outName is not NULL then
+ it will refer to the final uniform name after return. Use the addUniformArray variant to add
+ an array of uniforms. */
+ GrGLProgramDataManager::UniformHandle addUniform(uint32_t visibility,
+ GrSLType type,
+ const char* name,
+ const char** outName = NULL) {
return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
}
- virtual UniformHandle addUniformArray(uint32_t visibility,
- GrSLType type,
- const char* name,
- int arrayCount,
- const char** outName = NULL) SK_OVERRIDE;
+ GrGLProgramDataManager::UniformHandle addUniformArray(uint32_t visibility,
+ GrSLType type,
+ const char* name,
+ int arrayCount,
+ const char** outName = NULL);
- virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const SK_OVERRIDE {
+ const GrGLShaderVar& getUniformVariable(GrGLProgramDataManager::UniformHandle u) const {
return fUniforms[u.toShaderBuilderIndex()].fVariable;
}
- virtual const char* getUniformCStr(UniformHandle u) const SK_OVERRIDE {
+ /**
+ * Shortcut for getUniformVariable(u).c_str()
+ */
+ const char* getUniformCStr(GrGLProgramDataManager::UniformHandle u) const {
return this->getUniformVariable(u).c_str();
}
- virtual const GrGLContextInfo& ctxInfo() const SK_OVERRIDE;
+ const GrGLContextInfo& ctxInfo() const;
- virtual GrGpuGL* gpu() const SK_OVERRIDE { return fGpu; }
-
- virtual GrGLFragmentShaderBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
- virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
-
- virtual void addVarying(GrSLType type,
- const char* name,
- const char** vsOutName = NULL,
- const char** fsInName = NULL,
- GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision);
-
- // Handles for program uniforms (other than per-effect uniforms)
- struct BuiltinUniformHandles {
- UniformHandle fViewMatrixUni;
- UniformHandle fRTAdjustmentUni;
- UniformHandle fColorUni;
- UniformHandle fCoverageUni;
-
- // We use the render target height to provide a y-down frag coord when specifying
- // origin_upper_left is not supported.
- UniformHandle fRTHeightUni;
-
- // Uniforms for computing texture coords to do the dst-copy lookup
- UniformHandle fDstCopyTopLeftUni;
- UniformHandle fDstCopyScaleUni;
- UniformHandle fDstCopySamplerUni;
- };
+ GrGLFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }
+ GrGpuGL* gpu() const { return fGpu; }
protected:
- static GrGLProgramBuilder* CreateProgramBuilder(const GrGLProgramDesc&,
- const GrOptDrawState&,
- GrGpu::DrawType,
- bool hasGeometryProcessor,
- GrGpuGL*);
-
+ typedef GrTAllocator<GrGLShaderVar> VarArray;
GrGLProgramBuilder(GrGpuGL*, const GrOptDrawState&, const GrGLProgramDesc&);
const GrOptDrawState& optState() const { return fOptState; }
const GrGLProgramDesc& desc() const { return fDesc; }
- const GrGLProgramDesc::KeyHeader& header() const { return fDesc.getHeader(); }
+
+ // Helper for emitEffects().
+ void createAndEmitEffects(const GrFragmentStage* effectStages[],
+ int effectCnt,
+ const GrGLProgramDesc::EffectKeyProvider&,
+ GrGLSLExpr4* inOutFSColor);
+
+ /*
+ * A helper function called to emit the geometry processor as well as individual coverage
+ * and color stages. this will call into subclasses emit effect
+ */
+ void emitEffect(const GrProcessorStage& effectStage,
+ int effectIndex,
+ const GrGLProgramDesc::EffectKeyProvider& keyProvider,
+ GrGLSLExpr4* inColor,
+ GrGLSLExpr4* outColor);
+
+ /**
+ * Helper for emitEffect() in subclasses. Emits uniforms for an effect's texture accesses and
+ * appends the necessary data to the TextureSamplerArray* object so effects can add texture
+ * lookups to their code. This method is only meant to be called during the construction phase.
+ */
+ void emitSamplers(const GrProcessor& effect,
+ GrGLProcessor::TextureSamplerArray* outSamplers);
// Generates a name for a variable. The generated string will be name prefixed by the prefix
// char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
// generating stage code.
void nameVariable(SkString* out, char prefix, const char* name);
- void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage);
- void createAndEmitProcessors(const GrGeometryStage* geometryProcessor,
- const GrFragmentStage* colorStages[],
- const GrFragmentStage* coverageStages[],
- GrGLSLExpr4* inputColor,
- GrGLSLExpr4* inputCoverage);
- template <class ProcessorStage>
- void createAndEmitProcessors(const ProcessorStage*[],
- int effectCnt,
- const GrGLProgramDesc::EffectKeyProvider&,
- GrGLSLExpr4* fsInOutColor,
- GrGLInstalledProcessors*);
- void verify(const GrGeometryProcessor&);
- void verify(const GrFragmentProcessor&);
- void emitSamplers(const GrProcessor&,
- GrGLProcessor::TextureSamplerArray* outSamplers,
- GrGLInstalledProcessors*);
-
- // each specific program builder has a distinct transform and must override this function
- virtual void emitTransforms(const GrProcessorStage&,
- GrGLProcessor::TransformedCoordsArray* outCoords,
- GrGLInstalledProcessors*);
- GrGLProgram* finalize();
- void bindUniformLocations(GrGLuint programID);
- bool checkLinkStatus(GrGLuint programID);
- void resolveUniformLocations(GrGLuint programID);
-
- void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
- void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
-
- // Subclasses create different programs
- virtual GrGLProgram* createProgram(GrGLuint programID);
- void appendUniformDecls(ShaderVisibility, SkString*) const;
+ virtual bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
- // reset is called by program creator between each processor's emit code. It increments the
- // stage offset for variable name mangling, and also ensures verfication variables in the
- // fragment shader are cleared.
- void reset() {
- this->enterStage();
- this->addStage();
- fFS.reset();
- }
- void addStage() { fStageIndex++; }
+ virtual void bindProgramLocations(GrGLuint programId);
+ void resolveProgramLocations(GrGLuint programId);
- // This simple class exits the stage and then restores the stage when it goes out of scope
- class AutoStageRestore {
- public:
- AutoStageRestore(GrGLProgramBuilder* pb)
- : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); }
- ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; }
- private:
- GrGLProgramBuilder* fPB;
- bool fOutOfStage;
- };
- void exitStage() { fOutOfStage = true; }
- void enterStage() { fOutOfStage = false; }
- int stageIndex() const { return fStageIndex; }
-
- typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
- typedef GrGLProgramDataManager::UniformInfo UniformInfo;
- typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
-
- // number of each input/output type in a single allocation block, used by many builders
- static const int kVarsPerBlock;
-
- BuiltinUniformHandles fUniformHandles;
- GrGLVertexBuilder fVS;
- GrGLGeometryBuilder fGS;
- GrGLFragmentShaderBuilder fFS;
- bool fOutOfStage;
- int fStageIndex;
-
- SkAutoTUnref<GrGLInstalledProcessors> fGeometryProcessor;
- SkAutoTUnref<GrGLInstalledProcessors> fColorEffects;
- SkAutoTUnref<GrGLInstalledProcessors> fCoverageEffects;
+ void appendDecls(const VarArray&, SkString*) const;
+ void appendUniformDecls(ShaderVisibility, SkString*) const;
- const GrOptDrawState& fOptState;
- const GrGLProgramDesc& fDesc;
- GrGpuGL* fGpu;
- UniformInfoArray fUniforms;
+ class CodeStage : SkNoncopyable {
+ public:
+ CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
- friend class GrGLShaderBuilder;
- friend class GrGLVertexBuilder;
- friend class GrGLFragmentShaderBuilder;
- friend class GrGLGeometryBuilder;
-};
+ bool inStageCode() const {
+ this->validate();
+ return SkToBool(fEffectStage);
+ }
-/**
- * This class encapsulates an array of GrGLProcessors and their supporting data (coord transforms
- * and textures). It is built by GrGLProgramBuilder, then used to manage the necessary GL
- * state and shader uniforms in GLPrograms. Its just Plain old data, and as such is entirely public
- *
- * TODO We really don't need this class to have an array of processors. It makes sense for it
- * to just have one, also break out the transforms
- */
-class GrGLInstalledProcessors : public SkRefCnt {
-public:
- GrGLInstalledProcessors(int reserveCount, bool hasExplicitLocalCoords = false)
- : fGLProcessors(reserveCount)
- , fSamplers(reserveCount)
- , fTransforms(reserveCount)
- , fHasExplicitLocalCoords(hasExplicitLocalCoords) {
- }
+ const GrProcessorStage* effectStage() const {
+ this->validate();
+ return fEffectStage;
+ }
- virtual ~GrGLInstalledProcessors();
+ int stageIndex() const {
+ this->validate();
+ return fCurrentIndex;
+ }
- typedef GrGLProgramDataManager::UniformHandle UniformHandle;
+ class AutoStageRestore : SkNoncopyable {
+ public:
+ AutoStageRestore(CodeStage* codeStage, const GrProcessorStage* newStage) {
+ SkASSERT(codeStage);
+ fSavedIndex = codeStage->fCurrentIndex;
+ fSavedEffectStage = codeStage->fEffectStage;
+
+ if (NULL == newStage) {
+ codeStage->fCurrentIndex = -1;
+ } else {
+ codeStage->fCurrentIndex = codeStage->fNextIndex++;
+ }
+ codeStage->fEffectStage = newStage;
+
+ fCodeStage = codeStage;
+ }
+ ~AutoStageRestore() {
+ fCodeStage->fCurrentIndex = fSavedIndex;
+ fCodeStage->fEffectStage = fSavedEffectStage;
+ }
+ private:
+ CodeStage* fCodeStage;
+ int fSavedIndex;
+ const GrProcessorStage* fSavedEffectStage;
+ };
+ private:
+ void validate() const { SkASSERT((NULL == fEffectStage) == (-1 == fCurrentIndex)); }
+ int fNextIndex;
+ int fCurrentIndex;
+ const GrProcessorStage* fEffectStage;
+ };
- struct Sampler {
- SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
- UniformHandle fUniform;
- int fTextureUnit;
+ class GrGLProcessorEmitterInterface {
+ public:
+ virtual ~GrGLProcessorEmitterInterface() {}
+ virtual GrGLProcessor* createGLInstance() = 0;
+ virtual void emit(const GrProcessorKey& key,
+ const char* outColor,
+ const char* inColor,
+ const GrGLProcessor::TransformedCoordsArray& coords,
+ const GrGLProcessor::TextureSamplerArray& samplers) = 0;
};
- class ShaderVarHandle {
+ class GrGLFragmentProcessorEmitter : public GrGLProcessorEmitterInterface {
public:
- bool isValid() const { return fHandle > -1; }
- ShaderVarHandle() : fHandle(-1) {}
- ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
- int handle() const { SkASSERT(this->isValid()); return fHandle; }
- UniformHandle convertToUniformHandle() {
- SkASSERT(this->isValid());
- return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
+ GrGLFragmentProcessorEmitter(GrGLProgramBuilder* builder)
+ : fBuilder(builder)
+ , fFragmentProcessor(NULL)
+ , fGLFragmentProcessor(NULL) {}
+ virtual ~GrGLFragmentProcessorEmitter() {}
+ void set(const GrFragmentProcessor* fp) {
+ SkASSERT(NULL == fFragmentProcessor);
+ fFragmentProcessor = fp;
+ }
+ virtual GrGLProcessor* createGLInstance() {
+ SkASSERT(fFragmentProcessor);
+ SkASSERT(NULL == fGLFragmentProcessor);
+ fGLFragmentProcessor =
+ fFragmentProcessor->getFactory().createGLInstance(*fFragmentProcessor);
+ return fGLFragmentProcessor;
+ }
+ virtual void emit(const GrProcessorKey& key,
+ const char* outColor,
+ const char* inColor,
+ const GrGLProcessor::TransformedCoordsArray& coords,
+ const GrGLProcessor::TextureSamplerArray& samplers) {
+ SkASSERT(fFragmentProcessor);
+ SkASSERT(fGLFragmentProcessor);
+ fGLFragmentProcessor->emitCode(fBuilder, *fFragmentProcessor, key, outColor, inColor,
+ coords, samplers);
+ // this will not leak because it hasa already been used by createGLInstance
+ fGLFragmentProcessor = NULL;
+ fFragmentProcessor = NULL;
}
-
private:
- int fHandle;
+ GrGLProgramBuilder* fBuilder;
+ const GrFragmentProcessor* fFragmentProcessor;
+ GrGLFragmentProcessor* fGLFragmentProcessor;
};
- struct Transform {
- Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
- ShaderVarHandle fHandle;
- SkMatrix fCurrentValue;
- GrSLType fType;
- };
+ GrGLProcessorEmitterInterface* fEffectEmitter;
+ CodeStage fCodeStage;
+ SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
+ SkAutoTUnref<GrGLProgramEffects> fColorEffects;
+ SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
+ BuiltinUniformHandles fUniformHandles;
+ bool fFragOnly;
+ int fTexCoordSetCnt;
+ GrGLuint fProgramID;
+ GrGLFragmentShaderBuilder fFS;
+ SeparableVaryingInfoArray fSeparableVaryingInfos;
+
+private:
+ virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[],
+ GrGLSLExpr4* inputColor,
+ GrGLSLExpr4* inputCoverage) = 0;
+ /*
+ * Subclasses override emitEffect below to emit data and code for a specific single effect
+ */
+ virtual void emitEffect(const GrProcessorStage&,
+ const GrProcessorKey&,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) = 0;
+
+ /*
+ * Because we have fragment only builders, and those builders need to implement a subclass
+ * of program effects, we have to have base classes overload the program effects here
+ */
+ virtual GrGLProgramEffects* getProgramEffects() = 0;
+
+ /**
+ * Compiles all the shaders, links them into a program, and writes the program id to the output
+ * struct.
+ **/
+ bool finish();
- void addEffect(GrGLProcessor* effect) { fGLProcessors.push_back(effect); }
- SkTArray<Sampler, true>& addSamplers() { return fSamplers.push_back(); }
- SkTArray<Transform, true>& addTransforms() { return fTransforms.push_back(); }
+ GrGLFragmentProcessorEmitter fGrProcessorEmitter;
- SkTArray<GrGLProcessor*> fGLProcessors;
- SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
- SkTArray<SkSTArray<2, Transform, true> > fTransforms;
- bool fHasExplicitLocalCoords;
+ const GrOptDrawState& fOptState;
+ const GrGLProgramDesc& fDesc;
+ GrGpuGL* fGpu;
+ UniformInfoArray fUniforms;
friend class GrGLShaderBuilder;
friend class GrGLVertexShaderBuilder;
*/
#include "GrGLShaderBuilder.h"
-#include "GrGLProgramBuilder.h"
+#include "GrGLFullProgramBuilder.h"
#include "GrGLProgramBuilder.h"
#include "../GrGpuGL.h"
#include "../GrGLShaderVar.h"
out->appendf(".%s", swizzle);
}
}
+static const int kVarsPerBlock = 8;
}
GrGLShaderBuilder::GrGLShaderBuilder(GrGLProgramBuilder* program)
: fProgramBuilder(program)
- , fInputs(GrGLProgramBuilder::kVarsPerBlock)
- , fOutputs(GrGLProgramBuilder::kVarsPerBlock)
+ , fInputs(kVarsPerBlock)
+ , fOutputs(kVarsPerBlock)
, fFeaturesAddedMask(0) {
}
}
}
-void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
- for (int i = 0; i < vars.count(); ++i) {
- vars[i].appendDecl(fProgramBuilder->ctxInfo(), out);
- out->append(";\n");
- }
-}
-
void GrGLShaderBuilder::appendTextureLookup(const char* samplerName,
const char* coordName,
uint32_t configComponentMask,
swizzle,
kVec2f_GrSLType);
}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+GrGLFullShaderBuilder::GrGLFullShaderBuilder(GrGLFullProgramBuilder* program)
+ : INHERITED(program)
+ , fFullProgramBuilder(program) {}
#define GrGLShaderBuilder_DEFINED
#include "gl/GrGLProgramDesc.h"
+#include "gl/GrGLProgramEffects.h"
+#include "gl/GrGLSL.h"
#include "gl/GrGLProgramDataManager.h"
+#include "GrBackendProcessorFactory.h"
+#include "GrColor.h"
+#include "GrProcessor.h"
+#include "SkTypes.h"
#include <stdarg.h>
class GrGLContextInfo;
+class GrProcessorStage;
+class GrGLProgramDesc;
class GrGLProgramBuilder;
+class GrGLFullProgramBuilder;
/**
base class for all shaders builders
public:
typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray;
typedef GrGLProcessor::TextureSampler TextureSampler;
-
GrGLShaderBuilder(GrGLProgramBuilder* program);
void addInput(GrGLShaderVar i) { fInputs.push_back(i); }
GrGLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
/**
- * Helper for begining and ending a block in the shader code.
+ * Helper for begining and ending a block in the fragment code.
*/
class ShaderBlock {
public:
private:
GrGLShaderBuilder* fBuilder;
};
-
protected:
- typedef GrTAllocator<GrGLShaderVar> VarArray;
- void appendDecls(const VarArray& vars, SkString* out) const;
/*
* this super low level function is just for use internally to builders
*/
void addFeature(uint32_t featureBit, const char* extensionName);
+ typedef GrTAllocator<GrGLShaderVar> VarArray;
+
GrGLProgramBuilder* fProgramBuilder;
SkString fCode;
VarArray fOutputs;
uint32_t fFeaturesAddedMask;
};
+
+
+/*
+ * Full Shader builder is the base class for shaders which are only accessible through full program
+ * builder, ie vertex, geometry, and later TCU / TES. Using this base class, they can access the
+ * full program builder functionality through the full program pointer
+ */
+class GrGLFullShaderBuilder : public GrGLShaderBuilder {
+public:
+ GrGLFullShaderBuilder(GrGLFullProgramBuilder* program);
+
+ GrGLFullProgramBuilder* fullProgramBuilder() { return fFullProgramBuilder; }
+protected:
+ GrGLFullProgramBuilder* fFullProgramBuilder;
+private:
+ typedef GrGLShaderBuilder INHERITED;
+};
#endif
*/
#include "GrGLVertexShaderBuilder.h"
-#include "GrGLProgramBuilder.h"
+#include "GrGLFullProgramBuilder.h"
#include "GrGLShaderStringBuilder.h"
#include "../GrGpuGL.h"
+#include "../../GrOptDrawState.h"
-#define GL_CALL(X) GR_GL_CALL(fProgramBuilder->gpu()->glInterface(), X)
-#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fProgramBuilder->gpu()->glInterface(), R, X)
+#define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X)
+#define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X)
-static const char* color_attribute_name() { return "inColor"; }
-static const char* coverage_attribute_name() { return "inCoverage"; }
+namespace {
+inline const char* color_attribute_name() { return "inColor"; }
+inline const char* coverage_attribute_name() { return "inCoverage"; }
+}
-GrGLVertexBuilder::GrGLVertexBuilder(GrGLProgramBuilder* program)
+GrGLVertexShaderBuilder::GrGLVertexShaderBuilder(GrGLFullProgramBuilder* program)
: INHERITED(program)
, fPositionVar(NULL)
- , fLocalCoordsVar(NULL)
- , fEffectAttribOffset(0) {
-}
-
-SkString* GrGLVertexBuilder::addVarying(GrSLType type, const char* name,
- const char** vsOutName) {
- fOutputs.push_back();
- fOutputs.back().setType(type);
- fOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
- fProgramBuilder->nameVariable(fOutputs.back().accessName(), 'v', name);
-
- if (vsOutName) {
- *vsOutName = fOutputs.back().getName().c_str();
- }
- return fOutputs.back().accessName();
+ , fLocalCoordsVar(NULL) {
}
-
-void GrGLVertexBuilder::setupLocalCoords() {
- fPositionVar = &fInputs.push_back();
- fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "inPosition");
- if (-1 != fProgramBuilder->header().fLocalCoordAttributeIndex) {
- fLocalCoordsVar = &fInputs.push_back();
- fLocalCoordsVar->set(kVec2f_GrSLType,
- GrGLShaderVar::kAttribute_TypeModifier,
- "inLocalCoords");
- } else {
- fLocalCoordsVar = fPositionVar;
+bool GrGLVertexShaderBuilder::addAttribute(const GrShaderVar& var) {
+ SkASSERT(GrShaderVar::kAttribute_TypeModifier == var.getTypeModifier());
+ for (int i = 0; i < fInputs.count(); ++i) {
+ const GrGLShaderVar& attr = fInputs[i];
+ // if attribute already added, don't add it again
+ if (attr.getName().equals(var.getName())) {
+ return false;
+ }
}
- fEffectAttribOffset = fInputs.count();
-}
-
-void GrGLVertexBuilder::transformGLToSkiaCoords() {
- const char* viewMName;
- fProgramBuilder->fUniformHandles.fViewMatrixUni =
- fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
- kMat33f_GrSLType,
- "ViewM",
- &viewMName);
-
- // Transform the position into Skia's device coords.
- this->codeAppendf("vec3 pos3 = %s * vec3(%s, 1);", viewMName, fPositionVar->c_str());
-}
-
-void GrGLVertexBuilder::setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr4* out) {
- SkString name(inName);
- const char *vsName, *fsName;
- fProgramBuilder->addVarying(kVec4f_GrSLType, name.c_str(), &vsName, &fsName);
- name.prepend("in");
- this->addAttribute(GrShaderVar(name.c_str(),
- kVec4f_GrSLType,
- GrShaderVar::kAttribute_TypeModifier));
- this->codeAppendf("%s = %s;", vsName, name.c_str());
- *out = fsName;
- fEffectAttribOffset++;
+ fInputs.push_back(var);
+ return true;
}
-void GrGLVertexBuilder::emitAttributes(const GrGeometryProcessor& gp) {
+void GrGLVertexShaderBuilder::emitAttributes(const GrGeometryProcessor& gp) {
const GrGeometryProcessor::VertexAttribArray& vars = gp.getVertexAttribs();
int numAttributes = vars.count();
for (int a = 0; a < numAttributes; ++a) {
}
}
-void GrGLVertexBuilder::transformSkiaToGLCoords() {
- const char* rtAdjustName;
- fProgramBuilder->fUniformHandles.fRTAdjustmentUni =
- fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
- kVec4f_GrSLType,
- "rtAdjustment",
- &rtAdjustName);
+void GrGLVertexShaderBuilder::addVarying(GrSLType type, const char* name, const char** vsOutName) {
+ fOutputs.push_back();
+ fOutputs.back().setType(type);
+ fOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
+ fProgramBuilder->nameVariable(fOutputs.back().accessName(), 'v', name);
- // Transform from Skia's device coords to GL's normalized device coords.
- this->codeAppendf("gl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);",
- rtAdjustName, rtAdjustName);
+ if (vsOutName) {
+ *vsOutName = fOutputs.back().getName().c_str();
+ }
}
-void GrGLVertexBuilder::bindVertexAttributes(GrGLuint programID) {
+
+void GrGLVertexShaderBuilder::bindProgramLocations(GrGLuint programId) {
+ const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
+ GrGpuGL* gpu = fProgramBuilder->gpu();
+
// Bind the attrib locations to same values for all shaders
- const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->header();
SkASSERT(-1 != header.fPositionAttributeIndex);
- GL_CALL(BindAttribLocation(programID,
+ GL_CALL(BindAttribLocation(programId,
header.fPositionAttributeIndex,
fPositionVar->c_str()));
if (-1 != header.fLocalCoordAttributeIndex) {
- GL_CALL(BindAttribLocation(programID,
+ GL_CALL(BindAttribLocation(programId,
header.fLocalCoordAttributeIndex,
fLocalCoordsVar->c_str()));
}
if (-1 != header.fColorAttributeIndex) {
- GL_CALL(BindAttribLocation(programID,
+ GL_CALL(BindAttribLocation(programId,
header.fColorAttributeIndex,
color_attribute_name()));
}
if (-1 != header.fCoverageAttributeIndex) {
- GL_CALL(BindAttribLocation(programID,
+ GL_CALL(BindAttribLocation(programId,
header.fCoverageAttributeIndex,
coverage_attribute_name()));
}
const GrVertexAttrib* vaPtr = optState.getVertexAttribs();
const int vaCount = optState.getVertexAttribCount();
- // We start binding attributes after builtins
int i = fEffectAttribOffset;
for (int index = 0; index < vaCount; index++) {
if (kGeometryProcessor_GrVertexAttribBinding != vaPtr[index].fBinding) {
index != header.fCoverageAttributeIndex);
// We should never find another effect attribute if we have bound everything
SkASSERT(i < fInputs.count());
- GL_CALL(BindAttribLocation(programID, index, fInputs[i].c_str()));
+ GL_CALL(BindAttribLocation(programId, index, fInputs[i].c_str()));
i++;
}
// Make sure we bound everything
SkASSERT(fInputs.count() == i);
}
-bool GrGLVertexBuilder::compileAndAttachShaders(GrGLuint programId,
+bool GrGLVertexShaderBuilder::compileAndAttachShaders(GrGLuint programId,
SkTDArray<GrGLuint>* shaderIds) const {
GrGpuGL* gpu = fProgramBuilder->gpu();
const GrGLContext& glCtx = gpu->glContext();
const GrGLContextInfo& ctxInfo = gpu->ctxInfo();
SkString vertShaderSrc(GrGetGLSLVersionDecl(ctxInfo));
fProgramBuilder->appendUniformDecls(GrGLProgramBuilder::kVertex_Visibility, &vertShaderSrc);
- this->appendDecls(fInputs, &vertShaderSrc);
- this->appendDecls(fOutputs, &vertShaderSrc);
+ fProgramBuilder->appendDecls(fInputs, &vertShaderSrc);
+ fProgramBuilder->appendDecls(fOutputs, &vertShaderSrc);
vertShaderSrc.append("void main() {");
vertShaderSrc.append(fCode);
vertShaderSrc.append("}\n");
return true;
}
-bool GrGLVertexBuilder::addAttribute(const GrShaderVar& var) {
- SkASSERT(GrShaderVar::kAttribute_TypeModifier == var.getTypeModifier());
- for (int i = 0; i < fInputs.count(); ++i) {
- const GrGLShaderVar& attr = fInputs[i];
- // if attribute already added, don't add it again
- if (attr.getName().equals(var.getName())) {
- return false;
- }
+void GrGLVertexShaderBuilder::emitCodeAfterEffects() {
+ const char* rtAdjustName;
+ fProgramBuilder->fUniformHandles.fRTAdjustmentUni =
+ fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
+ kVec4f_GrSLType,
+ "rtAdjustment",
+ &rtAdjustName);
+
+ // Transform from Skia's device coords to GL's normalized device coords.
+ this->codeAppendf(
+ "gl_Position = vec4(dot(pos3.xz, %s.xy), dot(pos3.yz, %s.zw), 0, pos3.z);",
+ rtAdjustName, rtAdjustName);
+}
+
+void GrGLVertexShaderBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
+ const GrGLProgramDesc::KeyHeader& header = fProgramBuilder->desc().getHeader();
+
+ fPositionVar = &fInputs.push_back();
+ fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "inPosition");
+ if (-1 != header.fLocalCoordAttributeIndex) {
+ fLocalCoordsVar = &fInputs.push_back();
+ fLocalCoordsVar->set(kVec2f_GrSLType,
+ GrGLShaderVar::kAttribute_TypeModifier,
+ "inLocalCoords");
+ } else {
+ fLocalCoordsVar = fPositionVar;
}
- fInputs.push_back(var);
- return true;
+
+ const char* viewMName;
+ fProgramBuilder->fUniformHandles.fViewMatrixUni =
+ fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
+ kMat33f_GrSLType,
+ "ViewM",
+ &viewMName);
+
+ // Transform the position into Skia's device coords.
+ this->codeAppendf("vec3 pos3 = %s * vec3(%s, 1);",
+ viewMName, fPositionVar->c_str());
+
+ // we output point size in the GS if present
+ if (header.fEmitsPointSize
+#if GR_GL_EXPERIMENTAL_GS
+ && !header.fExperimentalGS
+#endif
+ ) {
+ this->codeAppend("gl_PointSize = 1.0;");
+ }
+
+ if (GrGLProgramDesc::kAttribute_ColorInput == header.fColorInput) {
+ this->addAttribute(GrShaderVar(color_attribute_name(),
+ kVec4f_GrSLType,
+ GrShaderVar::kAttribute_TypeModifier));
+ const char *vsName, *fsName;
+ fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
+ this->codeAppendf("%s = %s;", vsName, color_attribute_name());
+ *color = fsName;
+ }
+
+ if (GrGLProgramDesc::kAttribute_ColorInput == header.fCoverageInput) {
+ this->addAttribute(GrShaderVar(coverage_attribute_name(),
+ kVec4f_GrSLType,
+ GrShaderVar::kAttribute_TypeModifier));
+ const char *vsName, *fsName;
+ fFullProgramBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
+ this->codeAppendf("%s = %s;", vsName, coverage_attribute_name());
+ *coverage = fsName;
+ }
+ fEffectAttribOffset = fInputs.count();
}
#ifndef GrGLVertexShader_DEFINED
#define GrGLVertexShader_DEFINED
-
#include "GrGLShaderBuilder.h"
class GrGLProgramBuilder;
-// TODO we only actually ever need to return a GrGLShaderBuilder for this guy, none of the below
-// functions need to be part of VertexShaderBuilder's public interface
-class GrGLVertexBuilder : public GrGLShaderBuilder {
+class GrGLVertexShaderBuilder : public GrGLFullShaderBuilder {
public:
- GrGLVertexBuilder(GrGLProgramBuilder* program);
+ GrGLVertexShaderBuilder(GrGLFullProgramBuilder* program);
+
+ /*
+ * this call is only for GrGLProgramEffects' internal use
+ */
+ void emitAttributes(const GrGeometryProcessor& gp);
/**
* Are explicit local coordinates provided as input to the vertex shader.
*/
bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
+ const SkString* getEffectAttributeName(int attributeIndex) const;
+
/** Returns a vertex attribute that represents the local coords in the VS. This may be the same
as positionAttribute() or it may not be. It depends upon whether the rendering code
specified explicit local coords or not in the GrDrawState. */
*/
const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
+private:
/*
- * Internal call for GrGLProgramBuilder.addVarying
+ * Add attribute will push a new attribute onto the end. It will also assert if there is
+ * a duplicate attribute
*/
- SkString* addVarying(GrSLType type, const char* name, const char** vsOutName);
+ bool addAttribute(const GrShaderVar& var);
+
+ /*
+ * Internal call for GrGLFullProgramBuilder.addVarying
+ */
+ void addVarying(GrSLType type,
+ const char* name,
+ const char** vsOutName);
/*
* private helpers for compilation by GrGLProgramBuilder
*/
- void setupLocalCoords();
- void transformGLToSkiaCoords();
- void setupBuiltinVertexAttribute(const char* inName, GrGLSLExpr4* out);
- void emitAttributes(const GrGeometryProcessor& gp);
- void transformSkiaToGLCoords();
- void bindVertexAttributes(GrGLuint programID);
+ void bindProgramLocations(GrGLuint programId);
bool compileAndAttachShaders(GrGLuint programId, SkTDArray<GrGLuint>* shaderIds) const;
+ void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage);
+ void emitCodeAfterEffects();
-private:
- // an internal call which checks for uniquness of a var before adding it to the list of inputs
- bool addAttribute(const GrShaderVar& var);
struct AttributePair {
void set(int index, const SkString& name) {
fIndex = index; fName = name;
GrGLShaderVar* fLocalCoordsVar;
int fEffectAttribOffset;
- typedef GrGLShaderBuilder INHERITED;
+ friend class GrGLFullProgramBuilder;
+
+ typedef GrGLFullShaderBuilder INHERITED;
};
#endif
#include "GrContextFactory.h"
#include "GrOptDrawState.h"
#include "effects/GrConfigConversionEffect.h"
-#include "gl/builders/GrGLProgramBuilder.h"
#include "gl/GrGLPathRendering.h"
#include "gl/GrGpuGL.h"
#include "SkChecksum.h"
static void get_stage_stats(const GrFragmentStage stage, bool* readsDst,
bool* readsFragPosition, bool* requiresVertexShader) {
- if (stage.getProcessor()->willReadDstColor()) {
+ if (stage.getFragmentProcessor()->willReadDstColor()) {
*readsDst = true;
}
if (stage.getProcessor()->willReadFragmentPosition()) {
SkAutoTUnref<GrOptDrawState> optState(GrOptDrawState::Create(this->getDrawState(),
*this->caps(),
drawType));
- SkAutoTUnref<GrGLProgram> program(
- GrGLProgramBuilder::CreateProgram(*optState,
- pdesc,
- drawType,
- geometryProcessor,
- stages,
- stages + numColorStages,
- this));
+ SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this,
+ *optState.get(),
+ pdesc,
+ geometryProcessor.get(),
+ stages,
+ stages + numColorStages));
for (int s = 0; s < numStages; ++s) {
SkDELETE(stages[s]);
}