'<(skia_src_path)/gpu/glsl/GrGLSLCaps.cpp',
'<(skia_src_path)/gpu/glsl/GrGLSLCaps.h',
'<(skia_src_path)/gpu/glsl/GrGLSLProcessorTypes.h',
+ '<(skia_src_path)/gpu/glsl/GrGLSLProgramBuilder.cpp',
+ '<(skia_src_path)/gpu/glsl/GrGLSLProgramBuilder.h',
'<(skia_src_path)/gpu/glsl/GrGLSLProgramDataManager.h',
'<(skia_src_path)/gpu/glsl/GrGLSLShaderVar.h',
'<(skia_src_path)/gpu/glsl/GrGLSLTextureSampler.h',
}
private:
- void emitBlendCodeForDstRead(GrGLXPBuilder* pb, const char* srcColor, const char* dstColor,
+ void emitBlendCodeForDstRead(GrGLSLXPBuilder* pb, const char* srcColor, const char* dstColor,
const char* outColor, const GrXferProcessor& proc) override {
GrGLXPFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder();
* This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
* below. It adds a vec3f uniform visible in the FS that represents the constant light color.
*/
- void emitLightColorUniform(GrGLFPBuilder*);
+ void emitLightColorUniform(GrGLSLFPBuilder*);
/**
* These two functions are called from GrGLLightingEffect's emitCode() function.
* the FS. The default of emitLightColor appends the name of the constant light color uniform
* and so this function only needs to be overridden if the light color varies spatially.
*/
- virtual void emitSurfaceToLight(GrGLFPBuilder*, const char* z) = 0;
- virtual void emitLightColor(GrGLFPBuilder*, const char *surfaceToLight);
+ virtual void emitSurfaceToLight(GrGLSLFPBuilder*, const char* z) = 0;
+ virtual void emitLightColor(GrGLSLFPBuilder*, const char *surfaceToLight);
// This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call
// INHERITED::setData().
public:
virtual ~GrGLDistantLight() {}
void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
- void emitSurfaceToLight(GrGLFPBuilder*, const char* z) override;
+ void emitSurfaceToLight(GrGLSLFPBuilder*, const char* z) override;
private:
typedef GrGLLight INHERITED;
public:
virtual ~GrGLPointLight() {}
void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
- void emitSurfaceToLight(GrGLFPBuilder*, const char* z) override;
+ void emitSurfaceToLight(GrGLSLFPBuilder*, const char* z) override;
private:
typedef GrGLLight INHERITED;
public:
virtual ~GrGLSpotLight() {}
void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
- void emitSurfaceToLight(GrGLFPBuilder*, const char* z) override;
- void emitLightColor(GrGLFPBuilder*, const char *surfaceToLight) override;
+ void emitSurfaceToLight(GrGLSLFPBuilder*, const char* z) override;
+ void emitLightColor(GrGLSLFPBuilder*, const char *surfaceToLight) override;
private:
typedef GrGLLight INHERITED;
*/
void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
- virtual void emitLightFunc(GrGLFPBuilder*, SkString* funcName) = 0;
+ virtual void emitLightFunc(GrGLSLFPBuilder*, SkString* funcName) = 0;
private:
typedef GrGLFragmentProcessor INHERITED;
class GrGLDiffuseLightingEffect : public GrGLLightingEffect {
public:
GrGLDiffuseLightingEffect(const GrProcessor&);
- void emitLightFunc(GrGLFPBuilder*, SkString* funcName) override;
+ void emitLightFunc(GrGLSLFPBuilder*, SkString* funcName) override;
protected:
void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
class GrGLSpecularLightingEffect : public GrGLLightingEffect {
public:
GrGLSpecularLightingEffect(const GrProcessor&);
- void emitLightFunc(GrGLFPBuilder*, SkString* funcName) override;
+ void emitLightFunc(GrGLSLFPBuilder*, SkString* funcName) override;
protected:
void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
: INHERITED(proc) {
}
-void GrGLDiffuseLightingEffect::emitLightFunc(GrGLFPBuilder* builder, SkString* funcName) {
+void GrGLDiffuseLightingEffect::emitLightFunc(GrGLSLFPBuilder* builder, SkString* funcName) {
const char* kd;
fKDUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kFloat_GrSLType, kDefault_GrSLPrecision,
: INHERITED(proc) {
}
-void GrGLSpecularLightingEffect::emitLightFunc(GrGLFPBuilder* builder, SkString* funcName) {
+void GrGLSpecularLightingEffect::emitLightFunc(GrGLSLFPBuilder* builder, SkString* funcName) {
const char* ks;
const char* shininess;
}
///////////////////////////////////////////////////////////////////////////////
-void GrGLLight::emitLightColorUniform(GrGLFPBuilder* builder) {
+void GrGLLight::emitLightColorUniform(GrGLSLFPBuilder* builder) {
fColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec3f_GrSLType, kDefault_GrSLPrecision,
"LightColor");
}
-void GrGLLight::emitLightColor(GrGLFPBuilder* builder, const char *surfaceToLight) {
+void GrGLLight::emitLightColor(GrGLSLFPBuilder* builder, const char *surfaceToLight) {
builder->getFragmentShaderBuilder()->codeAppend(builder->getUniformCStr(this->lightColorUni()));
}
setUniformNormal3(pdman, fDirectionUni, distantLight->direction());
}
-void GrGLDistantLight::emitSurfaceToLight(GrGLFPBuilder* builder, const char* z) {
+void GrGLDistantLight::emitSurfaceToLight(GrGLSLFPBuilder* builder, const char* z) {
const char* dir;
fDirectionUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec3f_GrSLType, kDefault_GrSLPrecision,
setUniformPoint3(pdman, fLocationUni, pointLight->location());
}
-void GrGLPointLight::emitSurfaceToLight(GrGLFPBuilder* builder, const char* z) {
+void GrGLPointLight::emitSurfaceToLight(GrGLSLFPBuilder* builder, const char* z) {
const char* loc;
fLocationUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec3f_GrSLType, kDefault_GrSLPrecision,
setUniformNormal3(pdman, fSUni, spotLight->s());
}
-void GrGLSpotLight::emitSurfaceToLight(GrGLFPBuilder* builder, const char* z) {
+void GrGLSpotLight::emitSurfaceToLight(GrGLSLFPBuilder* builder, const char* z) {
const char* location;
fLocationUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec3f_GrSLType, kDefault_GrSLPrecision,
location, fsBuilder->fragmentPosition(), z);
}
-void GrGLSpotLight::emitLightColor(GrGLFPBuilder* builder,
+void GrGLSpotLight::emitLightColor(GrGLSLFPBuilder* builder,
const char *surfaceToLight) {
const char* color = builder->getUniformCStr(this->lightColorUni()); // created by parent class.
void GLColorTableEffect::emitCode(EmitArgs& args) {
const char* yoffsets;
- fRGBAYValuesUni = args.fBuilder->addUniform(GrGLFPBuilder::kFragment_Visibility,
- kVec4f_GrSLType, kDefault_GrSLPrecision,
- "yoffsets", &yoffsets);
+ fRGBAYValuesUni = args.fBuilder->addUniform(GrGLSLFPBuilder::kFragment_Visibility,
+ kVec4f_GrSLType, kDefault_GrSLPrecision,
+ "yoffsets", &yoffsets);
static const float kColorScaleFactor = 255.0f / 256.0f;
static const float kColorOffsetFactor = 1.0f / 512.0f;
GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
GrGLGradientEffect::~GrGLGradientEffect() { }
-void GrGLGradientEffect::emitUniforms(GrGLFPBuilder* builder, const GrGradientEffect& ge) {
+void GrGLGradientEffect::emitUniforms(GrGLSLFPBuilder* builder, const GrGradientEffect& ge) {
if (SkGradientShaderBase::kTwo_GpuColorType == ge.getColorType()) { // 2 Color case
fColorStartUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
return key;
}
-void GrGLGradientEffect::emitColor(GrGLFPBuilder* builder,
+void GrGLGradientEffect::emitColor(GrGLSLFPBuilder* builder,
const GrGradientEffect& ge,
const char* gradientTValue,
const char* outputColor,
gradientTValue);
fsBuilder->codeAppendf("\tvec4 colorTemp = clamp(oneMinus2t, 0.0, 1.0) * %s;\n",
builder->getUniformVariable(fColorStartUni).c_str());
- if (kTegra3_GrGLRenderer == builder->ctxInfo().renderer()) {
+ if (!builder->glslCaps()->canUseMinAndAbsTogether()) {
// The Tegra3 compiler will sometimes never return if we have
// min(abs(oneMinus2t), 1.0), or do the abs first in a separate expression.
fsBuilder->codeAppend("\tfloat minAbs = abs(oneMinus2t);\n");
// Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
// should call this method from their emitCode().
- void emitUniforms(GrGLFPBuilder* builder, const GrGradientEffect&);
+ void emitUniforms(GrGLSLFPBuilder* builder, const GrGradientEffect&);
// emit code that gets a fragment's color from an expression for t; Has branches for 3 separate
// control flows inside -- 2 color gradients, 3 color symmetric gradients (both using
// native GLSL mix), and 4+ color gradients that use the traditional texture lookup.
- void emitColor(GrGLFPBuilder* builder,
+ void emitColor(GrGLSLFPBuilder* builder,
const GrGradientEffect&,
const char* gradientTValue,
const char* outputColor,
this->emitUniforms(args.fBuilder, ge);
SkString coords2D = args.fBuilder->getFragmentShaderBuilder()
->ensureFSCoords2D(args.fCoords, 0);
- const GrGLContextInfo& ctxInfo = args.fBuilder->ctxInfo();
SkString t;
// 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi]
// On Intel GPU there is an issue where it reads the second arguement to atan "- %s.x" as an int
// thus must us -1.0 * %s.x to work correctly
- if (kIntel_GrGLVendor != ctxInfo.vendor()){
- t.printf("atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5",
+ if (args.fBuilder->glslCaps()->mustForceNegatedAtanParamToFloat()){
+ t.printf("atan(- %s.y, -1.0 * %s.x) * 0.1591549430918 + 0.5",
coords2D.c_str(), coords2D.c_str());
} else {
- t.printf("atan(- %s.y, -1.0 * %s.x) * 0.1591549430918 + 0.5",
+ t.printf("atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5",
coords2D.c_str(), coords2D.c_str());
}
this->emitColor(args.fBuilder, ge, t.c_str(), args.fOutputColor, args.fInputColor,
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
const DefaultGeoProc& gp = args.fGP.cast<DefaultGeoProc>();
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
GrGLFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
const CircleEdgeEffect& ce = args.fGP.cast<CircleEdgeEffect>();
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
// emit attributes
vsBuilder->emitAttributes(ce);
- GrGLVertToFrag v(kVec4f_GrSLType);
+ GrGLSLVertToFrag v(kVec4f_GrSLType);
args.fPB->addVarying("CircleEdge", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), ce.inCircleEdge()->fName);
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
const EllipseEdgeEffect& ee = args.fGP.cast<EllipseEdgeEffect>();
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
// emit attributes
vsBuilder->emitAttributes(ee);
- GrGLVertToFrag ellipseOffsets(kVec2f_GrSLType);
+ GrGLSLVertToFrag ellipseOffsets(kVec2f_GrSLType);
args.fPB->addVarying("EllipseOffsets", &ellipseOffsets);
vsBuilder->codeAppendf("%s = %s;", ellipseOffsets.vsOut(),
ee.inEllipseOffset()->fName);
- GrGLVertToFrag ellipseRadii(kVec4f_GrSLType);
+ GrGLSLVertToFrag ellipseRadii(kVec4f_GrSLType);
args.fPB->addVarying("EllipseRadii", &ellipseRadii);
vsBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(),
ee.inEllipseRadii()->fName);
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
const DIEllipseEdgeEffect& ee = args.fGP.cast<DIEllipseEdgeEffect>();
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
// emit attributes
vsBuilder->emitAttributes(ee);
- GrGLVertToFrag offsets0(kVec2f_GrSLType);
+ GrGLSLVertToFrag offsets0(kVec2f_GrSLType);
args.fPB->addVarying("EllipseOffsets0", &offsets0);
vsBuilder->codeAppendf("%s = %s;", offsets0.vsOut(),
ee.inEllipseOffsets0()->fName);
- GrGLVertToFrag offsets1(kVec2f_GrSLType);
+ GrGLSLVertToFrag offsets1(kVec2f_GrSLType);
args.fPB->addVarying("EllipseOffsets1", &offsets1);
vsBuilder->codeAppendf("%s = %s;", offsets1.vsOut(),
ee.inEllipseOffsets1()->fName);
}
void emitCode(EmitArgs& args) override {
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
const GrPathProcessor& pathProc = args.fGP.cast<GrPathProcessor>();
}
}
- void emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin, TransformsOut* tout) {
+ void emitTransforms(GrGLSLGPBuilder* pb, const TransformsIn& tin, TransformsOut* tout) {
tout->push_back_n(tin.count());
fInstalledTransforms.push_back_n(tin.count());
for (int i = 0; i < tin.count(); i++) {
SkString strVaryingName("MatrixCoord");
strVaryingName.appendf("_%i_%i", i, t);
- GrGLVertToFrag v(varyingType);
+ GrGLSLVertToFrag v(varyingType);
fInstalledTransforms[i][t].fHandle =
pb->addSeparableVarying(strVaryingName.c_str(), &v).toIndex();
fInstalledTransforms[i][t].fType = varyingType;
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
const QuadEdgeEffect& qe = args.fGP.cast<QuadEdgeEffect>();
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
// emit attributes
vsBuilder->emitAttributes(qe);
- GrGLVertToFrag v(kVec4f_GrSLType);
+ GrGLSLVertToFrag v(kVec4f_GrSLType);
args.fPB->addVarying("QuadEdge", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), qe.inQuadEdge()->fName);
}
void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
const GrConicEffect& gp = args.fGP.cast<GrConicEffect>();
// emit attributes
vsBuilder->emitAttributes(gp);
- GrGLVertToFrag v(kVec4f_GrSLType);
+ GrGLSLVertToFrag v(kVec4f_GrSLType);
args.fPB->addVarying("ConicCoeffs", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs()->fName);
}
void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
const GrQuadEffect& gp = args.fGP.cast<GrQuadEffect>();
// emit attributes
vsBuilder->emitAttributes(gp);
- GrGLVertToFrag v(kVec4f_GrSLType);
+ GrGLSLVertToFrag v(kVec4f_GrSLType);
args.fPB->addVarying("HairQuadEdge", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge()->fName);
// emit attributes
vsBuilder->emitAttributes(gp);
- GrGLVertToFrag v(kVec4f_GrSLType);
+ GrGLSLVertToFrag v(kVec4f_GrSLType);
args.fPB->addVarying("CubicCoeffs", &v, kHigh_GrSLPrecision);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inCubicCoeffs()->fName);
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
const GrBitmapTextGeoProc& cte = args.fGP.cast<GrBitmapTextGeoProc>();
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
// emit attributes
SkScalar recipWidth = 1.0f / atlas->width();
SkScalar recipHeight = 1.0f / atlas->height();
- GrGLVertToFrag v(kVec2f_GrSLType);
+ GrGLSLVertToFrag v(kVec2f_GrSLType);
pb->addVarying("TextureCoords", &v);
vsBuilder->codeAppendf("%s = vec2(%.*f, %.*f) * %s;", v.vsOut(),
GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipWidth,
fsBuilder->codeAppend("\t\talpha *= edge;\n");
}
- // Woe is me. See https://bug.skia.org/2149 .
- if (kTegra2_GrGLRenderer == args.fBuilder->ctxInfo().renderer()) {
- fsBuilder->codeAppend("\t\tif (-1.0 == alpha) {\n\t\t\tdiscard;\n\t\t}\n");
- }
-
if (GrProcessorEdgeTypeIsInverseFill(cpe.getEdgeType())) {
fsBuilder->codeAppend("\talpha = 1.0 - alpha;\n");
}
}
}
- void emitBlendCodeForDstRead(GrGLXPBuilder* pb, const char* srcColor, const char* dstColor,
+ void emitBlendCodeForDstRead(GrGLSLXPBuilder* pb, const char* srcColor, const char* dstColor,
const char* outColor, const GrXferProcessor& proc) override {
const CustomXP& xp = proc.cast<CustomXP>();
SkASSERT(!xp.hasHWBlendEquation());
void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
const DashingCircleEffect& dce = args.fGP.cast<DashingCircleEffect>();
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
// emit attributes
vsBuilder->emitAttributes(dce);
// XY are dashPos, Z is dashInterval
- GrGLVertToFrag dashParams(kVec3f_GrSLType);
+ GrGLSLVertToFrag dashParams(kVec3f_GrSLType);
args.fPB->addVarying("DashParam", &dashParams);
vsBuilder->codeAppendf("%s = %s;", dashParams.vsOut(), dce.inDashParams()->fName);
// x refers to circle radius - 0.5, y refers to cicle's center x coord
- GrGLVertToFrag circleParams(kVec2f_GrSLType);
+ GrGLSLVertToFrag circleParams(kVec2f_GrSLType);
args.fPB->addVarying("CircleParams", &circleParams);
vsBuilder->codeAppendf("%s = %s;", circleParams.vsOut(), dce.inCircleParams()->fName);
void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
const DashingLineEffect& de = args.fGP.cast<DashingLineEffect>();
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
vsBuilder->emitAttributes(de);
// XY refers to dashPos, Z is the dash interval length
- GrGLVertToFrag inDashParams(kVec3f_GrSLType);
+ GrGLSLVertToFrag inDashParams(kVec3f_GrSLType);
args.fPB->addVarying("DashParams", &inDashParams, GrSLPrecision::kHigh_GrSLPrecision);
vsBuilder->codeAppendf("%s = %s;", inDashParams.vsOut(), de.inDashParams()->fName);
// The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
// respectively.
- GrGLVertToFrag inRectParams(kVec4f_GrSLType);
+ GrGLSLVertToFrag inRectParams(kVec4f_GrSLType);
args.fPB->addVarying("RectParams", &inRectParams, GrSLPrecision::kHigh_GrSLPrecision);
vsBuilder->codeAppendf("%s = %s;", inRectParams.vsOut(), de.inRectParams()->fName);
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
const GrDistanceFieldA8TextGeoProc& dfTexEffect =
args.fGP.cast<GrDistanceFieldA8TextGeoProc>();
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
args.fTransformsIn, args.fTransformsOut);
// add varyings
- GrGLVertToFrag recipScale(kFloat_GrSLType);
- GrGLVertToFrag st(kVec2f_GrSLType);
+ GrGLSLVertToFrag recipScale(kFloat_GrSLType);
+ GrGLSLVertToFrag st(kVec2f_GrSLType);
bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
pb->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName);
SkScalar recipWidth = 1.0f / atlas->width();
SkScalar recipHeight = 1.0f / atlas->height();
- GrGLVertToFrag uv(kVec2f_GrSLType);
+ GrGLSLVertToFrag uv(kVec2f_GrSLType);
pb->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
vsBuilder->codeAppendf("%s = vec2(%.*f, %.*f) * %s;", uv.vsOut(),
GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipWidth,
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
const GrDistanceFieldPathGeoProc& dfTexEffect = args.fGP.cast<GrDistanceFieldPathGeoProc>();
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
// emit attributes
vsBuilder->emitAttributes(dfTexEffect);
- GrGLVertToFrag v(kVec2f_GrSLType);
+ GrGLSLVertToFrag v(kVec2f_GrSLType);
pb->addVarying("TextureCoords", &v, kHigh_GrSLPrecision);
// setup pass through color
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
const GrDistanceFieldLCDTextGeoProc& dfTexEffect =
args.fGP.cast<GrDistanceFieldLCDTextGeoProc>();
- GrGLGPBuilder* pb = args.fPB;
+ GrGLSLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
// set up varyings
bool isUniformScale = SkToBool(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask);
- GrGLVertToFrag recipScale(kFloat_GrSLType);
- GrGLVertToFrag st(kVec2f_GrSLType);
+ GrGLSLVertToFrag recipScale(kFloat_GrSLType);
+ GrGLSLVertToFrag st(kVec2f_GrSLType);
pb->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName);
SkScalar recipWidth = 1.0f / atlas->width();
SkScalar recipHeight = 1.0f / atlas->height();
- GrGLVertToFrag uv(kVec2f_GrSLType);
+ GrGLSLVertToFrag uv(kVec2f_GrSLType);
pb->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
vsBuilder->codeAppendf("%s = vec2(%.*f, %.*f) * %s;", uv.vsOut(),
GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipWidth,
}
private:
- void emitBlendCodeForDstRead(GrGLXPBuilder* pb, const char* srcColor, const char* dstColor,
+ void emitBlendCodeForDstRead(GrGLSLXPBuilder* pb, const char* srcColor, const char* dstColor,
const char* outColor, const GrXferProcessor& proc) override {
const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>();
GrGLXPFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder();
#include "SkFloatingPoint.h"
#include "gl/GrGLContext.h"
#include "gl/GrGLFragmentProcessor.h"
-#include "gl/builders/GrGLProgramBuilder.h"
+#include "glsl/GrGLSLProgramBuilder.h"
#include "glsl/GrGLSLProgramDataManager.h"
#include "glsl/GrGLSLTextureSampler.h"
SkASSERT((Mode)-1 == fMode || textureDomain.mode() == fMode);
SkDEBUGCODE(fMode = textureDomain.mode();)
- GrGLProgramBuilder* program = builder->getProgramBuilder();
+ GrGLSLProgramBuilder* program = builder->getProgramBuilder();
if (textureDomain.mode() != kIgnore_Mode && !fDomainUni.isValid()) {
const char* name;
if (textureDomain.fIndex >= 0) {
uniName.appendS32(textureDomain.fIndex);
}
- fDomainUni = program->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ fDomainUni = program->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, kDefault_GrSLPrecision,
uniName.c_str(), &name);
fDomainName = name;
fTextureRedSupport = false;
fImagingSupport = false;
fTwoFormatLimit = false;
- fFragCoordsConventionSupport = false;
fVertexArrayObjectSupport = false;
fInstancedDrawingSupport = false;
fDirectStateAccessSupport = false;
fSRGBWriteControl = ctxInfo.hasExtension("GL_EXT_sRGB_write_control");
}
- // Frag Coords Convention support is not part of ES
- // Known issue on at least some Intel platforms:
- // http://code.google.com/p/skia/issues/detail?id=946
- if (kIntel_GrGLVendor != ctxInfo.vendor() && kGLES_GrGLStandard != standard) {
- fFragCoordsConventionSupport = ctxInfo.glslGeneration() >= k150_GrGLSLGeneration ||
- ctxInfo.hasExtension("GL_ARB_fragment_coord_conventions");
- }
-
// SGX and Mali GPUs that are based on a tiled-deferred architecture that have trouble with
// frequently changing VBOs. We've measured a performance increase using non-VBO vertex
// data for dynamic content on these GPUs. Perhaps we should read the renderer string and
if (kGLES_GrGLStandard == standard && k110_GrGLSLGeneration == glslCaps->fGLSLGeneration) {
glslCaps->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives";
}
+
+ // Frag Coords Convention support is not part of ES
+ // Known issue on at least some Intel platforms:
+ // http://code.google.com/p/skia/issues/detail?id=946
+ if (kIntel_GrGLVendor != ctxInfo.vendor() &&
+ kGLES_GrGLStandard != standard &&
+ (ctxInfo.glslGeneration() >= k150_GrGLSLGeneration ||
+ ctxInfo.hasExtension("GL_ARB_fragment_coord_conventions"))) {
+ glslCaps->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions";
+ }
+
+ if (kGLES_GrGLStandard == standard) {
+ glslCaps->fSecondaryOutputExtensionString = "GL_EXT_blend_func_extended";
+ }
+
+ // The Tegra3 compiler will sometimes never return if we have min(abs(x), 1.0), so we must do
+ // the abs first in a separate expression.
+ if (kTegra3_GrGLRenderer == ctxInfo.renderer()) {
+ glslCaps->fCanUseMinAndAbsTogether = false;
+ }
+
+ // On Intel GPU there is an issue where it reads the second arguement to atan "- %s.x" as an int
+ // thus must us -1.0 * %s.x to work correctly
+ if (kIntel_GrGLVendor == ctxInfo.vendor()) {
+ glslCaps->fMustForceNegatedAtanParamToFloat = true;
+ }
}
bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
r.appendf("GL_R support: %s\n", (fTextureRedSupport ? "YES": "NO"));
r.appendf("GL_ARB_imaging support: %s\n", (fImagingSupport ? "YES": "NO"));
r.appendf("Two Format Limit: %s\n", (fTwoFormatLimit ? "YES": "NO"));
- r.appendf("Fragment coord conventions support: %s\n",
- (fFragCoordsConventionSupport ? "YES": "NO"));
r.appendf("Vertex array object support: %s\n", (fVertexArrayObjectSupport ? "YES": "NO"));
r.appendf("Instanced drawing support: %s\n", (fInstancedDrawingSupport ? "YES": "NO"));
r.appendf("Direct state access support: %s\n", (fDirectStateAccessSupport ? "YES": "NO"));
/// Is GL_ARB_IMAGING supported
bool imagingSupport() const { return fImagingSupport; }
- /// Is GL_ARB_fragment_coord_conventions supported?
- bool fragCoordConventionsSupport() const { return fFragCoordsConventionSupport; }
-
/// Is there support for Vertex Array Objects?
bool vertexArrayObjectSupport() const { return fVertexArrayObjectSupport; }
bool fTextureRedSupport : 1;
bool fImagingSupport : 1;
bool fTwoFormatLimit : 1;
- bool fFragCoordsConventionSupport : 1;
bool fVertexArrayObjectSupport : 1;
bool fInstancedDrawingSupport : 1;
bool fDirectStateAccessSupport : 1;
class GrProcessor;
class GrProcessorKeyBuilder;
-class GrGLFPBuilder;
+class GrGLSLFPBuilder;
class GrGLSLCaps;
class GrGLFragmentProcessor {
*/
struct EmitArgs {
- EmitArgs(GrGLFPBuilder* builder,
+ EmitArgs(GrGLSLFPBuilder* builder,
const GrFragmentProcessor& fp,
const char* outputColor,
const char* inputColor,
, fInputColor(inputColor)
, fCoords(coords)
, fSamplers(samplers) {}
- GrGLFPBuilder* fBuilder;
+ GrGLSLFPBuilder* fBuilder;
const GrFragmentProcessor& fFp;
const char* fOutputColor;
const char* fInputColor;
vsBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar);
}
-void GrGLGeometryProcessor::emitTransforms(GrGLGPBuilder* pb,
+void GrGLGeometryProcessor::emitTransforms(GrGLSLGPBuilder* pb,
const GrShaderVar& posVar,
const char* localCoords,
const SkMatrix& localMatrix,
SkString strVaryingName("MatrixCoord");
strVaryingName.appendf("_%i_%i", i, t);
- GrGLVertToFrag v(varyingType);
+ GrGLSLVertToFrag v(varyingType);
pb->addVarying(strVaryingName.c_str(), &v, precision);
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
}
}
-void GrGLGeometryProcessor::emitTransforms(GrGLGPBuilder* pb,
+void GrGLGeometryProcessor::emitTransforms(GrGLSLGPBuilder* pb,
const char* localCoords,
const TransformsIn& tin,
TransformsOut* tout) {
SkString strVaryingName("MatrixCoord");
strVaryingName.appendf("_%i_%i", i, t);
- GrGLVertToFrag v(varyingType);
+ GrGLSLVertToFrag v(varyingType);
pb->addVarying(strVaryingName.c_str(), &v, precision);
vb->codeAppendf("%s = %s;", v.vsOut(), localCoords);
}
}
-void GrGLGeometryProcessor::setupPosition(GrGLGPBuilder* pb,
+void GrGLGeometryProcessor::setupPosition(GrGLSLGPBuilder* pb,
GrGPArgs* gpArgs,
const char* posName) {
GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
}
-void GrGLGeometryProcessor::setupPosition(GrGLGPBuilder* pb,
+void GrGLGeometryProcessor::setupPosition(GrGLSLGPBuilder* pb,
GrGPArgs* gpArgs,
const char* posName,
const SkMatrix& mat,
#include "GrGLPrimitiveProcessor.h"
-class GrGLGPBuilder;
+class GrGLSLGPBuilder;
/**
* If a GL effect needs a GrGLFullShaderBuilder* object to emit vertex code, then it must inherit
protected:
// Emit a uniform matrix for each coord transform.
- void emitTransforms(GrGLGPBuilder* gp,
+ void emitTransforms(GrGLSLGPBuilder* gp,
const GrShaderVar& posVar,
const char* localCoords,
const TransformsIn& tin,
}
// Emit pre-transformed coords as a vertex attribute per coord-transform.
- void emitTransforms(GrGLGPBuilder*,
+ void emitTransforms(GrGLSLGPBuilder*,
const GrShaderVar& posVar,
const char* localCoords,
const SkMatrix& localMatrix,
TransformsOut*);
// caller has emitted transforms via attributes
- void emitTransforms(GrGLGPBuilder*,
+ void emitTransforms(GrGLSLGPBuilder*,
const char* localCoords,
const TransformsIn& tin,
TransformsOut* tout);
};
// Create the correct type of position variable given the CTM
- void setupPosition(GrGLGPBuilder*, GrGPArgs*, const char* posName);
- void setupPosition(GrGLGPBuilder*, GrGPArgs*, const char* posName, const SkMatrix& mat,
+ void setupPosition(GrGLSLGPBuilder*, GrGPArgs*, const char* posName);
+ void setupPosition(GrGLSLGPBuilder*, GrGPArgs*, const char* posName, const SkMatrix& mat,
UniformHandle* viewMatrixUniform);
static uint32_t ComputePosKey(const SkMatrix& mat) {
return combined;
}
-void GrGLPrimitiveProcessor::setupUniformColor(GrGLGPBuilder* pb,
+void GrGLPrimitiveProcessor::setupUniformColor(GrGLSLGPBuilder* pb,
const char* outputName,
UniformHandle* colorUniform) {
GrGLFragmentBuilder* fs = pb->getFragmentShaderBuilder();
class GrBatchTracker;
class GrPrimitiveProcessor;
-class GrGLGPBuilder;
+class GrGLSLGPBuilder;
class GrGLPrimitiveProcessor {
public:
typedef SkSTArray<8, GrGLSLTransformedCoordsArray> TransformsOut;
struct EmitArgs {
- EmitArgs(GrGLGPBuilder* pb,
+ EmitArgs(GrGLSLGPBuilder* pb,
const GrPrimitiveProcessor& gp,
const char* outputColor,
const char* outputCoverage,
, fSamplers(samplers)
, fTransformsIn(transformsIn)
, fTransformsOut(transformsOut) {}
- GrGLGPBuilder* fPB;
+ GrGLSLGPBuilder* fPB;
const GrPrimitiveProcessor& fGP;
const char* fOutputColor;
const char* fOutputCoverage;
const SkTArray<const GrCoordTransform*, true>& transforms) = 0;
protected:
- void setupUniformColor(GrGLGPBuilder* pb, const char* outputName, UniformHandle* colorUniform);
+ void setupUniformColor(GrGLSLGPBuilder* pb,
+ const char* outputName,
+ UniformHandle* colorUniform);
struct Transform {
Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
#include "glsl/GrGLSLProgramDataManager.h"
#include "glsl/GrGLSLTextureSampler.h"
-class GrGLXPBuilder;
+class GrGLSLXPBuilder;
class GrXferProcessor;
class GrGLXferProcessor {
typedef GrGLSLTextureSampler::TextureSamplerArray TextureSamplerArray;
struct EmitArgs {
- EmitArgs(GrGLXPBuilder* pb,
+ EmitArgs(GrGLSLXPBuilder* pb,
const GrXferProcessor& xp,
const char* inputColor,
const char* inputCoverage,
, fOutputSecondary(outputSecondary)
, fSamplers(samplers) {}
- GrGLXPBuilder* fPB;
+ GrGLSLXPBuilder* fPB;
const GrXferProcessor& fXP;
const char* fInputColor;
const char* fInputCoverage;
* the blending logic. The base class applies coverage. A subclass only needs to implement this
* method if it can construct a GrXferProcessor that reads the dst color.
*/
- virtual void emitBlendCodeForDstRead(GrGLXPBuilder*, const char* srcColor, const char* dstColor,
- const char* outColor, const GrXferProcessor&) {
+ virtual void emitBlendCodeForDstRead(GrGLSLXPBuilder*,
+ const char* srcColor,
+ const char* dstColor,
+ const char* outColor,
+ const GrXferProcessor&) {
SkFAIL("emitBlendCodeForDstRead not implemented.");
}
#include "GrGLFragmentShaderBuilder.h"
#include "GrRenderTarget.h"
-#include "GrGLProgramBuilder.h"
-#include "gl/GrGLGpu.h"
#include "glsl/GrGLSL.h"
#include "glsl/GrGLSLCaps.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)
+#include "glsl/GrGLSLProgramBuilder.h"
const char* GrGLFragmentShaderBuilder::kDstTextureColorName = "_dstColor";
-static const char* declared_color_output_name() { return "fsColorOut"; }
-static const char* declared_secondary_color_output_name() { return "fsSecondaryColorOut"; }
static const char* specific_layout_qualifier_name(GrBlendEquation equation) {
SkASSERT(GrBlendEquationIsAdvanced(equation));
}
}
-GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLProgramBuilder* program,
+GrGLFragmentShaderBuilder::GrGLFragmentShaderBuilder(GrGLSLProgramBuilder* program,
uint8_t fragPosKey)
: INHERITED(program)
- , fHasCustomColorOutput(false)
- , fHasSecondaryOutput(false)
, fSetupFragPosition(false)
, fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == fragPosKey)
, fCustomColorOutputIndex(-1)
const char* GrGLFragmentShaderBuilder::fragmentPosition() {
fHasReadFragmentPosition = true;
- GrGLGpu* gpu = fProgramBuilder->gpu();
+ const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps();
// We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
// to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
// declaration varies in earlier GLSL specs. So it is simpler to omit it.
if (fTopLeftFragPosRead) {
fSetupFragPosition = true;
return "gl_FragCoord";
- } else if (gpu->glCaps().fragCoordConventionsSupport()) {
+ } else if (const char* extension = glslCaps->fragCoordConventionsExtensionString()) {
if (!fSetupFragPosition) {
- if (gpu->glslGeneration() < k150_GrGLSLGeneration) {
+ if (glslCaps->generation() < k150_GrGLSLGeneration) {
this->addFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
- "GL_ARB_fragment_coord_conventions");
+ extension);
}
fInputs.push_back().set(kVec4f_GrSLType,
GrGLSLShaderVar::kIn_TypeModifier,
const char* rtHeightName;
fProgramBuilder->fUniformHandles.fRTHeightUni =
- fProgramBuilder->addFragPosUniform(GrGLProgramBuilder::kFragment_Visibility,
+ fProgramBuilder->addFragPosUniform(GrGLSLProgramBuilder::kFragment_Visibility,
kFloat_GrSLType,
kDefault_GrSLPrecision,
"RTHeight",
if (glslCaps->fbFetchNeedsCustomOutput()) {
this->enableCustomOutput();
fOutputs[fCustomColorOutputIndex].setTypeModifier(GrShaderVar::kInOut_TypeModifier);
- fbFetchColorName = declared_color_output_name();
+ fbFetchColorName = DeclaredColorOutputName();
}
return fbFetchColorName;
} else {
fCustomColorOutputIndex = fOutputs.count();
fOutputs.push_back().set(kVec4f_GrSLType,
GrGLSLShaderVar::kOut_TypeModifier,
- declared_color_output_name());
+ DeclaredColorOutputName());
}
}
void GrGLFragmentShaderBuilder::enableSecondaryOutput() {
SkASSERT(!fHasSecondaryOutput);
fHasSecondaryOutput = true;
- if (kGLES_GrGLStandard == fProgramBuilder->gpu()->ctxInfo().standard()) {
- this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, "GL_EXT_blend_func_extended");
+ const GrGLSLCaps& caps = *fProgramBuilder->glslCaps();
+ if (const char* extension = caps.secondaryOutputExtensionString()) {
+ this->addFeature(1 << kBlendFuncExtended_GLSLPrivateFeature, extension);
}
// If the primary output is declared, we must declare also the secondary output
// and vice versa, since it is not allowed to use a built-in gl_FragColor and a custom
// output. The condition also co-incides with the condition in whici GLES SL 2.0
// requires the built-in gl_SecondaryFragColorEXT, where as 3.0 requires a custom output.
- const GrGLSLCaps& caps = *fProgramBuilder->glslCaps();
if (caps.mustDeclareFragmentShaderOutput()) {
fOutputs.push_back().set(kVec4f_GrSLType, GrGLSLShaderVar::kOut_TypeModifier,
- declared_secondary_color_output_name());
+ DeclaredSecondaryColorOutputName());
}
}
const char* GrGLFragmentShaderBuilder::getPrimaryColorOutputName() const {
- return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
+ return fHasCustomColorOutput ? DeclaredColorOutputName() : "gl_FragColor";
}
const char* GrGLFragmentShaderBuilder::getSecondaryColorOutputName() const {
- const GrGLSLCaps& caps = *fProgramBuilder->gpu()->glCaps().glslCaps();
- return caps.mustDeclareFragmentShaderOutput() ? declared_secondary_color_output_name()
+ const GrGLSLCaps& caps = *fProgramBuilder->glslCaps();
+ return caps.mustDeclareFragmentShaderOutput() ? DeclaredSecondaryColorOutputName()
: "gl_SecondaryFragColorEXT";
}
&this->precisionQualifier());
}
-void GrGLFragmentShaderBuilder::bindFragmentShaderLocations(GrGLuint programID) {
- const GrGLCaps& caps = fProgramBuilder->gpu()->glCaps();
- if (fHasCustomColorOutput && caps.bindFragDataLocationSupport()) {
- GL_CALL(BindFragDataLocation(programID, 0, declared_color_output_name()));
- }
- if (fHasSecondaryOutput && caps.glslCaps()->mustDeclareFragmentShaderOutput()) {
- GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
- declared_secondary_color_output_name()));
- }
-}
-
-void GrGLFragmentShaderBuilder::addVarying(GrGLVarying* v, GrSLPrecision fsPrec) {
+void GrGLFragmentShaderBuilder::addVarying(GrGLSLVarying* v, GrSLPrecision fsPrec) {
v->fFsIn = v->fVsOut;
if (v->fGsOut) {
v->fFsIn = v->fGsOut;
int removeAt = fMangleString.findLastOf('_');
fMangleString.remove(removeAt, fMangleString.size() - removeAt);
}
+
#include "GrGLShaderBuilder.h"
-#include "gl/GrGLTypes.h"
#include "glsl/GrGLSLProcessorTypes.h"
class GrRenderTarget;
-class GrGLVarying;
+class GrGLSLVarying;
/*
* This base class encapsulates the functionality which the GP uses to build fragment shaders
*/
class GrGLFragmentBuilder : public GrGLShaderBuilder {
public:
- GrGLFragmentBuilder(GrGLProgramBuilder* program)
- : INHERITED(program) {
+ GrGLFragmentBuilder(GrGLSLProgramBuilder* program)
+ : INHERITED(program)
+ , fHasCustomColorOutput(false)
+ , fHasSecondaryOutput(false) {
fSubstageIndices.push_back(0);
}
virtual ~GrGLFragmentBuilder() {}
const SkString& getMangleString() const { return fMangleString; }
+ bool hasCustomColorOutput() const { return fHasCustomColorOutput; }
+ bool hasSecondaryOutput() const { return fHasSecondaryOutput; }
+
+protected:
+ bool fHasCustomColorOutput;
+ bool fHasSecondaryOutput;
+
private:
/*
* State that tracks which child proc in the proc tree is currently emitting code. This is
*/
class GrGLXPFragmentBuilder : public GrGLFragmentBuilder {
public:
- GrGLXPFragmentBuilder(GrGLProgramBuilder* program) : INHERITED(program) {}
+ GrGLXPFragmentBuilder(GrGLSLProgramBuilder* program) : INHERITED(program) {}
/** Returns the variable name that holds the color of the destination pixel. This may be nullptr if
no effect advertised that it will read the destination. */
the key is 0. */
static FragPosKey KeyForFragmentPosition(const GrRenderTarget* dst);
- GrGLFragmentShaderBuilder(GrGLProgramBuilder* program, uint8_t fragPosKey);
+ GrGLFragmentShaderBuilder(GrGLSLProgramBuilder* program, uint8_t fragPosKey);
// true public interface, defined explicitly in the abstract interfaces above
bool enableFeature(GLSLFeature) override;
void enableSecondaryOutput();
const char* getPrimaryColorOutputName() const;
const char* getSecondaryColorOutputName() const;
- void bindFragmentShaderLocations(GrGLuint programID);
// 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.
fHasReadFragmentPosition = false;
}
+ static const char* DeclaredColorOutputName() { return "fsColorOut"; }
+ static const char* DeclaredSecondaryColorOutputName() { return "fsSecondaryColorOut"; }
+
/*
* An internal call for GrGLProgramBuilder to use to add varyings to the vertex shader
*/
- void addVarying(GrGLVarying*, GrSLPrecision);
+ void addVarying(GrGLSLVarying*, GrSLPrecision);
void onFinalize() override;
static const char* kDstTextureColorName;
- bool fHasCustomColorOutput;
- bool fHasSecondaryOutput;
bool fSetupFragPosition;
bool fTopLeftFragPosRead;
int fCustomColorOutputIndex;
#include "GrGLProgramBuilder.h"
#include "../GrGLGpu.h"
-GrGLGeometryBuilder::GrGLGeometryBuilder(GrGLProgramBuilder* program)
+GrGLGeometryBuilder::GrGLGeometryBuilder(GrGLSLProgramBuilder* program)
: INHERITED(program) {
}
-void GrGLGeometryBuilder::addVarying(const char* name, GrSLPrecision precision, GrGLVarying* v) {
+void GrGLGeometryBuilder::addVarying(const char* name, GrSLPrecision precision, GrGLSLVarying* v) {
// if we have a GS take each varying in as an array
// and output as non-array.
if (v->vsVarying()) {
#include "GrGLShaderBuilder.h"
-class GrGLVarying;
+class GrGLSLVarying;
class GrGLGeometryBuilder : public GrGLShaderBuilder {
public:
- GrGLGeometryBuilder(GrGLProgramBuilder* program);
+ GrGLGeometryBuilder(GrGLSLProgramBuilder* program);
private:
/*
* an internal call for GrGLFullProgramBuilder to add varyings
*/
- void addVarying(const char* name, GrSLPrecision precision, GrGLVarying*);
+ void addVarying(const char* name, GrSLPrecision precision, GrGLSLVarying*);
void onFinalize() override {}
#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)
-const int GrGLProgramBuilder::kVarsPerBlock = 8;
-
GrGLProgram* GrGLProgramBuilder::CreateProgram(const DrawArgs& args, GrGLGpu* gpu) {
GrAutoLocaleSetter als("C");
/////////////////////////////////////////////////////////////////////////////
GrGLProgramBuilder::GrGLProgramBuilder(GrGLGpu* gpu, const DrawArgs& args)
- : fVS(this)
- , fGS(this)
- , fFS(this, args.fDesc->header().fFragPosKey)
- , fStageIndex(-1)
+ : INHERITED(args)
, fGeometryProcessor(nullptr)
, fXferProcessor(nullptr)
- , fArgs(args)
, fGpu(gpu)
, fUniforms(kVarsPerBlock)
, fSamplerUniforms(4)
}
void GrGLProgramBuilder::addVarying(const char* name,
- GrGLVarying* varying,
+ GrGLSLVarying* varying,
GrSLPrecision precision) {
SkASSERT(varying);
if (varying->vsVarying()) {
void GrGLProgramBuilder::addPassThroughAttribute(const GrPrimitiveProcessor::Attribute* input,
const char* output) {
GrSLType type = GrVertexAttribTypeToSLType(input->fType);
- GrGLVertToFrag v(type);
+ GrGLSLVertToFrag v(type);
this->addVarying(input->fName, &v);
fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName);
fFS.codeAppendf("%s = %s;", output, v.fsIn());
GrGLProgramBuilder::SeparableVaryingHandle GrGLProgramBuilder::addSeparableVarying(
const char* name,
- GrGLVertToFrag* v,
+ GrGLSLVertToFrag* v,
GrSLPrecision fsPrecision) {
// This call is not used for non-NVPR backends.
SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport() &&
return SeparableVaryingHandle(varyingInfo.fLocation);
}
-void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name, bool mangle) {
- if ('\0' == prefix) {
- *out = name;
- } else {
- out->printf("%c%s", prefix, name);
- }
- if (mangle) {
- if (out->endsWith('_')) {
- // Names containing "__" are reserved.
- out->append("x");
- }
- out->appendf("_Stage%d%s", fStageIndex, fFS.getMangleString().c_str());
- }
-}
-
GrGLSLProgramDataManager::UniformHandle GrGLProgramBuilder::internalAddUniformArray(
uint32_t visibility,
GrSLType type,
return GrGLSLProgramDataManager::UniformHandle(fUniforms.count() - 1);
}
-void GrGLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
- SkString* out) const {
+void GrGLProgramBuilder::onAppendUniformDecls(ShaderVisibility visibility, SkString* out) const {
for (int i = 0; i < fUniforms.count(); ++i) {
if (fUniforms[i].fVisibility & visibility) {
fUniforms[i].fVariable.appendDecl(this->glslCaps(), out);
}
}
-const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
- return fGpu->ctxInfo();
-}
-
const GrGLSLCaps* GrGLProgramBuilder::glslCaps() const {
- return this->ctxInfo().caps()->glslCaps();
+ return this->fGpu->ctxInfo().caps()->glslCaps();
}
bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) {
fFS.enableSecondaryOutput();
}
- if (this->ctxInfo().caps()->glslCaps()->mustDeclareFragmentShaderOutput()) {
+ if (this->glslCaps()->mustDeclareFragmentShaderOutput()) {
fFS.enableCustomOutput();
}
// NVPR actually requires a vertex shader to compile
bool useNvpr = primitiveProcessor().isPathRendering();
if (!useNvpr) {
- fVS.bindVertexAttributes(programID);
+ const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
+
+ int vaCount = primProc.numAttribs();
+ for (int i = 0; i < vaCount; i++) {
+ GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName));
+ }
}
fFS.finalize(kFragment_Visibility);
}
}
- fFS.bindFragmentShaderLocations(programID);
+ const GrGLCaps& caps = this->gpu()->glCaps();
+ if (fFS.hasCustomColorOutput() && caps.bindFragDataLocationSupport()) {
+ GL_CALL(BindFragDataLocation(programID, 0,
+ GrGLFragmentShaderBuilder::DeclaredColorOutputName()));
+ }
+ if (fFS.hasSecondaryOutput() && caps.glslCaps()->mustDeclareFragmentShaderOutput()) {
+ GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
+ GrGLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
+ }
// handle NVPR separable varyings
if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
#ifndef GrGLProgramBuilder_DEFINED
#define GrGLProgramBuilder_DEFINED
-#include "GrGLFragmentShaderBuilder.h"
-#include "GrGLGeometryShaderBuilder.h"
-#include "GrGLVertexShaderBuilder.h"
#include "gl/GrGLProgramDataManager.h"
+#include "glsl/GrGLSLProgramBuilder.h"
#include "glsl/GrGLSLProgramDataManager.h"
#include "glsl/GrGLSLTextureSampler.h"
#include "../GrGLPrimitiveProcessor.h"
class GrFragmentProcessor;
class GrGLContextInfo;
+class GrGLShaderBuilder;
class GrGLSLCaps;
// Enough precision to represent 1 / 2048 accurately in printf
#define GR_SIGNIFICANT_POW2_DECIMAL_DIG 11
-/*
- * 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 {
-public:
- enum ShaderVisibility {
- kVertex_Visibility = 1 << kVertex_GrShaderType,
- kGeometry_Visibility = 1 << kGeometry_GrShaderType,
- kFragment_Visibility = 1 << kFragment_GrShaderType,
- };
-
- virtual ~GrGLUniformBuilder() {}
-
- typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
- typedef GrGLSLProgramDataManager::SeparableVaryingHandle SeparableVaryingHandle;
-
- /** 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 nullptr then
- it will refer to the final uniform name after return. Use the addUniformArray variant to add
- an array of uniforms. */
- UniformHandle addUniform(uint32_t visibility,
- GrSLType type,
- GrSLPrecision precision,
- const char* name,
- const char** outName = nullptr) {
- return this->addUniformArray(visibility, type, precision, name, 0, outName);
- }
-
- virtual UniformHandle addUniformArray(
- uint32_t visibility,
- GrSLType type,
- GrSLPrecision precision,
- const char* name,
- int arrayCount,
- const char** outName = nullptr) {
- return this->internalAddUniformArray(visibility, type, precision, name, true, arrayCount,
- outName);
- }
-
-
- virtual const GrGLSLShaderVar& 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 const GrGLSLCaps* glslCaps() const = 0;
-
- virtual GrGLGpu* gpu() const = 0;
-
- /*
- * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
- */
-private:
- virtual UniformHandle internalAddUniformArray(
- uint32_t visibility,
- GrSLType type,
- GrSLPrecision precision,
- const char* name,
- bool mangleName,
- int arrayCount,
- const char** outName) = 0;
-};
-
-// TODO move this into GrGLGPBuilder and move them both out of this file
-class GrGLVarying {
-public:
- bool vsVarying() const { return kVertToFrag_Varying == fVarying ||
- kVertToGeo_Varying == fVarying; }
- bool fsVarying() const { return kVertToFrag_Varying == fVarying ||
- kGeoToFrag_Varying == fVarying; }
- const char* vsOut() const { return fVsOut; }
- const char* gsIn() const { return fGsIn; }
- const char* gsOut() const { return fGsOut; }
- const char* fsIn() const { return fFsIn; }
- GrSLType type() const { return fType; }
-
-protected:
- enum Varying {
- kVertToFrag_Varying,
- kVertToGeo_Varying,
- kGeoToFrag_Varying,
- };
-
- GrGLVarying(GrSLType type, Varying varying)
- : fVarying(varying), fType(type), fVsOut(nullptr), fGsIn(nullptr), fGsOut(nullptr),
- fFsIn(nullptr) {}
-
- Varying fVarying;
-
-private:
- GrSLType fType;
- const char* fVsOut;
- const char* fGsIn;
- const char* fGsOut;
- const char* fFsIn;
-
- friend class GrGLVertexBuilder;
- friend class GrGLGeometryBuilder;
- friend class GrGLXferBuilder;
- friend class GrGLFragmentShaderBuilder;
-};
-
-struct GrGLVertToFrag : public GrGLVarying {
- GrGLVertToFrag(GrSLType type)
- : GrGLVarying(type, kVertToFrag_Varying) {}
-};
-
-struct GrGLVertToGeo : public GrGLVarying {
- GrGLVertToGeo(GrSLType type)
- : GrGLVarying(type, kVertToGeo_Varying) {}
-};
-
-struct GrGLGeoToFrag : public GrGLVarying {
- GrGLGeoToFrag(GrSLType type)
- : GrGLVarying(type, kGeoToFrag_Varying) {}
-};
-
-/* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
-class GrGLGPBuilder : public virtual GrGLUniformBuilder {
-public:
- /*
- * addVarying allows fine grained control for setting up varyings between stages. If you just
- * need to take an attribute and pass it through to an output value in a fragment shader, use
- * addPassThroughAttribute.
- * TODO convert most uses of addVarying to addPassThroughAttribute
- */
- virtual void addVarying(const char* name,
- GrGLVarying*,
- GrSLPrecision precision = kDefault_GrSLPrecision) = 0;
-
- /*
- * This call can be used by GP to pass an attribute through all shaders directly to 'output' in
- * the fragment shader. Though this call effects both the vertex shader and fragment shader,
- * it expects 'output' to be defined in the fragment shader before this call is made.
- * TODO it might be nicer behavior to have a flag to declare output inside this call
- */
- virtual void addPassThroughAttribute(const GrGeometryProcessor::Attribute*,
- const char* output) = 0;
-
- /*
- * Creates a fragment shader varying that can be referred to.
- * Comparable to GrGLUniformBuilder::addUniform().
- */
- virtual SeparableVaryingHandle addSeparableVarying(
- const char* name, GrGLVertToFrag*, GrSLPrecision fsPrecision = kDefault_GrSLPrecision) = 0;
-
- // TODO rename getFragmentBuilder
- virtual GrGLFragmentBuilder* getFragmentShaderBuilder() = 0;
- virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
-
- /*
- * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
- */
-};
-
-/* a specializations for FPs. Lets the user add uniforms and FS code */
-class GrGLFPBuilder : public virtual GrGLUniformBuilder {
-public:
- virtual GrGLFragmentBuilder* getFragmentShaderBuilder() = 0;
-
- /*
- * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
- */
-};
-
-/* a specializations for XPs. Lets the user add uniforms and FS code */
-class GrGLXPBuilder : public virtual GrGLUniformBuilder {
-public:
- virtual GrGLXPFragmentBuilder* getFragmentShaderBuilder() = 0;
-
- /*
- * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
- */
-};
-
/**
* The below struct represent processors installed in programs.
*/
* 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 GrGLXPBuilder {
+class GrGLProgramBuilder : public GrGLSLProgramBuilder {
public:
- typedef GrGpu::DrawArgs DrawArgs;
/** Generates a shader program.
*
* The program implements what is specified in the stages given as input.
return this->getUniformVariable(u).c_str();
}
- const GrGLContextInfo& ctxInfo() const override;
-
const GrGLSLCaps* glslCaps() const override;
- GrGLGpu* gpu() const override { return fGpu; }
-
- GrGLXPFragmentBuilder* getFragmentShaderBuilder() override { return &fFS; }
- GrGLVertexBuilder* getVertexShaderBuilder() override { return &fVS; }
+ GrGLGpu* gpu() const { return fGpu; }
void addVarying(
const char* name,
- GrGLVarying*,
+ GrGLSLVarying*,
GrSLPrecision precision = kDefault_GrSLPrecision) override;
void addPassThroughAttribute(const GrPrimitiveProcessor::Attribute*,
SeparableVaryingHandle addSeparableVarying(
const char* name,
- GrGLVertToFrag*,
+ GrGLSLVertToFrag*,
GrSLPrecision fsPrecision = kDefault_GrSLPrecision) override;
- // Handles for program uniforms (other than per-effect uniforms)
- struct BuiltinUniformHandles {
- UniformHandle fRTAdjustmentUni;
-
- // We use the render target height to provide a y-down frag coord when specifying
- // origin_upper_left is not supported.
- UniformHandle fRTHeightUni;
- };
-
-protected:
+private:
typedef GrGLProgramDataManager::UniformInfo UniformInfo;
typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
typedef GrGLProgramDataManager::SeparableVaryingInfo SeparableVaryingInfo;
GrGLProgramBuilder(GrGLGpu*, const DrawArgs&);
- const GrPrimitiveProcessor& primitiveProcessor() const { return *fArgs.fPrimitiveProcessor; }
- const GrPipeline& pipeline() const { return *fArgs.fPipeline; }
- const GrProgramDesc& desc() const { return *fArgs.fDesc; }
- const GrProgramDesc::KeyHeader& header() const { return fArgs.fDesc->header(); }
-
UniformHandle internalAddUniformArray(uint32_t visibility,
GrSLType type,
GrSLPrecision precision,
int arrayCount,
const char** outName) override;
- // Used to add a uniform for frag position without mangling the name of the uniform inside of a
- // stage.
- UniformHandle addFragPosUniform(uint32_t visibility,
- GrSLType type,
- GrSLPrecision precision,
- const char* name,
- const char** outName) {
- return this->internalAddUniformArray(visibility, type, precision, name, false, 0, outName);
- }
-
- // Generates a name for a variable. The generated string will be name prefixed by the prefix
- // char (unless the prefix is '\0'). It also will mangle the name to be stage-specific unless
- // explicitly asked not to.
- void nameVariable(SkString* out, char prefix, const char* name, bool mangle = true);
// Generates a possibly mangled name for a stage variable and writes it to the fragment shader.
// If GrGLSLExpr4 has a valid name then it will use that instead
void nameExpression(GrGLSLExpr4*, const char* baseName);
GrGLenum type,
SkTDArray<GrGLuint>* shaderIds);
GrGLProgram* finalize();
- virtual void bindProgramResourceLocations(GrGLuint programID);
+ void bindProgramResourceLocations(GrGLuint programID);
bool checkLinkStatus(GrGLuint programID);
- virtual void resolveProgramResourceLocations(GrGLuint programID);
+ void resolveProgramResourceLocations(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);
+ GrGLProgram* createProgram(GrGLuint programID);
- void appendUniformDecls(ShaderVisibility, SkString*) const;
+ void onAppendUniformDecls(ShaderVisibility visibility, SkString* out) const override;
// 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
private:
GrGLProgramBuilder* fPB;
};
- int stageIndex() const { return fStageIndex; }
-
- const char* rtAdjustment() const { return "rtAdjustment"; }
-
- // 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;
- int fStageIndex;
GrGLInstalledGeoProc* fGeometryProcessor;
GrGLInstalledXferProc* fXferProcessor;
SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
- const DrawArgs& fArgs;
GrGLGpu* fGpu;
UniformInfoArray fUniforms;
GrGLPrimitiveProcessor::TransformsIn fCoordTransforms;
friend class GrGLVertexBuilder;
friend class GrGLFragmentShaderBuilder;
friend class GrGLGeometryBuilder;
+
+ typedef GrGLSLProgramBuilder INHERITED;
};
#endif
*/
#include "GrGLShaderBuilder.h"
-#include "gl/builders/GrGLProgramBuilder.h"
#include "glsl/GrGLSLCaps.h"
#include "glsl/GrGLSLShaderVar.h"
#include "glsl/GrGLSLTextureSampler.h"
+#include "glsl/GrGLSLProgramBuilder.h"
static void map_swizzle(const char* swizzleMap, const char* swizzle, char* mangledSwizzle) {
int i;
}
}
-GrGLShaderBuilder::GrGLShaderBuilder(GrGLProgramBuilder* program)
+GrGLShaderBuilder::GrGLShaderBuilder(GrGLSLProgramBuilder* program)
: fProgramBuilder(program)
- , fInputs(GrGLProgramBuilder::kVarsPerBlock)
- , fOutputs(GrGLProgramBuilder::kVarsPerBlock)
+ , fInputs(GrGLSLProgramBuilder::kVarsPerBlock)
+ , fOutputs(GrGLSLProgramBuilder::kVarsPerBlock)
, fFeaturesAddedMask(0)
, fCodeIndex(kCode)
, fFinalized(false) {
this->versionDecl() = fProgramBuilder->glslCaps()->versionDeclString();
this->compileAndAppendLayoutQualifiers();
SkASSERT(visibility);
- fProgramBuilder->appendUniformDecls((GrGLProgramBuilder::ShaderVisibility) visibility,
+ fProgramBuilder->appendUniformDecls((GrGLSLProgramBuilder::ShaderVisibility) visibility,
&this->uniforms());
this->appendDecls(fInputs, &this->inputs());
// We should not have any outputs in the fragment shader when using version 1.10
- SkASSERT(GrGLProgramBuilder::kFragment_Visibility != visibility ||
+ SkASSERT(GrGLSLProgramBuilder::kFragment_Visibility != visibility ||
k110_GrGLSLGeneration != fProgramBuilder->glslCaps()->generation() ||
fOutputs.empty());
this->appendDecls(fOutputs, &this->outputs());
#include <stdarg.h>
-class GrGLProgramBuilder;
+class GrGLSLProgramBuilder;
class GrGLSLTextureSampler;
/**
*/
class GrGLShaderBuilder {
public:
- GrGLShaderBuilder(GrGLProgramBuilder* program);
+ GrGLShaderBuilder(GrGLSLProgramBuilder* program);
virtual ~GrGLShaderBuilder() {}
void addInput(const GrGLSLShaderVar& input) { fInputs.push_back(input); }
/*
* Get parent builder for adding uniforms
*/
- GrGLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
+ GrGLSLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
/**
* Helper for begining and ending a block in the shader code.
kCode,
};
- GrGLProgramBuilder* fProgramBuilder;
+ GrGLSLProgramBuilder* fProgramBuilder;
SkSTArray<kCode, const char*, true> fCompilerStrings;
SkSTArray<kCode, int, true> fCompilerStringLengths;
SkSTArray<kCode, SkString> fShaderStrings;
*/
#include "GrGLVertexShaderBuilder.h"
-#include "GrGLProgramBuilder.h"
-#include "../GrGLGLSL.h"
-#include "../GrGLGpu.h"
+#include "glsl/GrGLSLProgramBuilder.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)
-
-GrGLVertexBuilder::GrGLVertexBuilder(GrGLProgramBuilder* program)
+GrGLVertexBuilder::GrGLVertexBuilder(GrGLSLProgramBuilder* program)
: INHERITED(program)
, fRtAdjustName(nullptr) {
}
-void GrGLVertexBuilder::addVarying(const char* name, GrSLPrecision precision, GrGLVarying* v) {
+void GrGLVertexBuilder::addVarying(const char* name, GrSLPrecision precision, GrGLSLVarying* v) {
fOutputs.push_back();
fOutputs.back().setType(v->fType);
fOutputs.back().setTypeModifier(GrGLSLShaderVar::kVaryingOut_TypeModifier);
// setup RT Uniform
fProgramBuilder->fUniformHandles.fRTAdjustmentUni =
- fProgramBuilder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
+ fProgramBuilder->addUniform(GrGLSLProgramBuilder::kVertex_Visibility,
kVec4f_GrSLType, precision,
fProgramBuilder->rtAdjustment(),
&fRtAdjustName);
this->codeAppend("gl_PointSize = 1.0;");
}
-void GrGLVertexBuilder::bindVertexAttributes(GrGLuint programID) {
- const GrPrimitiveProcessor& primProc = fProgramBuilder->primitiveProcessor();
-
- int vaCount = primProc.numAttribs();
- for (int i = 0; i < vaCount; i++) {
- GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName));
- }
- return;
-}
-
bool GrGLVertexBuilder::addAttribute(const GrShaderVar& var) {
SkASSERT(GrShaderVar::kAttribute_TypeModifier == var.getTypeModifier());
for (int i = 0; i < fInputs.count(); ++i) {
fInputs.push_back(var);
return true;
}
+
#define GrGLVertexShader_DEFINED
#include "GrGLShaderBuilder.h"
-#include "gl/GrGLTypes.h"
#include "GrGeometryProcessor.h"
-class GrGLVarying;
+class GrGLSLVarying;
class GrGLVertexBuilder : public GrGLShaderBuilder {
public:
- GrGLVertexBuilder(GrGLProgramBuilder* program);
+ GrGLVertexBuilder(GrGLSLProgramBuilder* program);
void transformToNormalizedDeviceSpace(const GrShaderVar& posVar);
void emitAttributes(const GrGeometryProcessor& gp);
/*
* Internal call for GrGLProgramBuilder.addVarying
*/
- void addVarying(const char* name, GrSLPrecision, GrGLVarying*);
-
- /*
- * private helpers for compilation by GrGLProgramBuilder
- */
- void bindVertexAttributes(GrGLuint programID);
+ void addVarying(const char* name, GrSLPrecision, GrGLSLVarying*);
// an internal call which checks for uniquness of a var before adding it to the list of inputs
bool addAttribute(const GrShaderVar& var);
fUsesPrecisionModifiers = false;
fCanUseAnyFunctionInShader = true;
fForceHighPrecisionNDSTransform = false;
+ fCanUseMinAndAbsTogether = true;
+ fMustForceNegatedAtanParamToFloat = false;
fVersionDeclString = nullptr;
fShaderDerivativeExtensionString = nullptr;
+ fFragCoordConventionsExtensionString = nullptr;
+ fSecondaryOutputExtensionString = nullptr;
fFBFetchColorName = nullptr;
fFBFetchExtensionString = nullptr;
fAdvBlendEqInteraction = kNotSupported_AdvBlendEqInteraction;
r.appendf("Drops tile on zero divide: %s\n", (fDropsTileOnZeroDivide ? "YES" : "NO"));
r.appendf("Bindless texture support: %s\n", (fBindlessTextureSupport ? "YES" : "NO"));
r.appendf("Uses precision modifiers: %s\n", (fUsesPrecisionModifiers ? "YES" : "NO"));
- r.appendf("Can Use any() function: %s\n", (fCanUseAnyFunctionInShader ? "YES" : "NO"));
+ r.appendf("Can use any() function: %s\n", (fCanUseAnyFunctionInShader ? "YES" : "NO"));
r.appendf("Force high precision on NDS transform: %s\n", (fForceHighPrecisionNDSTransform ?
"YES" : "NO"));
+ r.appendf("Can use min() and abs() together: %s\n", (fCanUseMinAndAbsTogether ? "YES" : "NO"));
+ r.appendf("Must force negated atan param to float: %s\n", (fMustForceNegatedAtanParamToFloat ?
+ "YES" : "NO"));
r.appendf("Advanced blend equation interaction: %s\n",
kAdvBlendEqInteractionStr[fAdvBlendEqInteraction]);
return r;
bool forceHighPrecisionNDSTransform() const { return fForceHighPrecisionNDSTransform; }
+ bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; }
+
+ bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; }
+
// Returns the string of an extension that must be enabled in the shader to support
// derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
// this function, the caller should check that shaderDerivativeSupport exists.
SkASSERT(this->shaderDerivativeSupport());
return fShaderDerivativeExtensionString;
}
+
+ // Returns the string of an extension that will do all necessary coord transfomations needed
+ // when reading the fragment position. If such an extension does not exisits, this function
+ // returns a nullptr, and all transforms of the frag position must be done manually in the
+ // shader.
+ const char* fragCoordConventionsExtensionString() const {
+ return fFragCoordConventionsExtensionString;
+ }
+
+ // This returns the name of an extension that must be enabled in the shader, if such a thing is
+ // required in order to use a secondary output in the shader. This returns a nullptr if no such
+ // extension is required. However, the return value of this function does not say whether dual
+ // source blending is supported.
+ const char* secondaryOutputExtensionString() const {
+ return fSecondaryOutputExtensionString;
+ }
bool mustSwizzleInShader() const { return fMustSwizzleInShader; }
bool fCanUseAnyFunctionInShader : 1;
bool fForceHighPrecisionNDSTransform : 1;
+ // Used for specific driver bug work arounds
+ bool fCanUseMinAndAbsTogether : 1;
+ bool fMustForceNegatedAtanParamToFloat : 1;
+
const char* fVersionDeclString;
const char* fShaderDerivativeExtensionString;
+ const char* fFragCoordConventionsExtensionString;
+ const char* fSecondaryOutputExtensionString;
const char* fFBFetchColorName;
const char* fFBFetchExtensionString;
--- /dev/null
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "glsl/GrGLSLProgramBuilder.h"
+
+const int GrGLSLProgramBuilder::kVarsPerBlock = 8;
+
+GrGLSLProgramBuilder::GrGLSLProgramBuilder(const DrawArgs& args)
+ : fVS(this)
+ , fGS(this)
+ , fFS(this, args.fDesc->header().fFragPosKey)
+ , fStageIndex(-1)
+ , fArgs(args) {
+}
+
+void GrGLSLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name, bool mangle) {
+ if ('\0' == prefix) {
+ *out = name;
+ } else {
+ out->printf("%c%s", prefix, name);
+ }
+ if (mangle) {
+ if (out->endsWith('_')) {
+ // Names containing "__" are reserved.
+ out->append("x");
+ }
+ out->appendf("_Stage%d%s", fStageIndex, fFS.getMangleString().c_str());
+ }
+}
+
+void GrGLSLProgramBuilder::appendUniformDecls(ShaderVisibility visibility,
+ SkString* out) const {
+ this->onAppendUniformDecls(visibility, out);
+}
+
--- /dev/null
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLSLProgramBuilder_DEFINED
+#define GrGLSLProgramBuilder_DEFINED
+
+#include "GrGeometryProcessor.h"
+#include "GrGpu.h"
+#include "gl/builders/GrGLFragmentShaderBuilder.h"
+#include "gl/builders/GrGLGeometryShaderBuilder.h"
+#include "gl/builders/GrGLVertexShaderBuilder.h"
+#include "glsl/GrGLSLProgramDataManager.h"
+
+class GrGLSLCaps;
+class GrGLSLShaderVar;
+
+class GrGLSLUniformBuilder {
+public:
+ enum ShaderVisibility {
+ kVertex_Visibility = 1 << kVertex_GrShaderType,
+ kGeometry_Visibility = 1 << kGeometry_GrShaderType,
+ kFragment_Visibility = 1 << kFragment_GrShaderType,
+ };
+
+ virtual ~GrGLSLUniformBuilder() {}
+
+ typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
+ typedef GrGLSLProgramDataManager::SeparableVaryingHandle SeparableVaryingHandle;
+
+ /** 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 nullptr
+ then it will refer to the final uniform name after return. Use the addUniformArray variant
+ to add an array of uniforms. */
+ UniformHandle addUniform(uint32_t visibility,
+ GrSLType type,
+ GrSLPrecision precision,
+ const char* name,
+ const char** outName = nullptr) {
+ return this->addUniformArray(visibility, type, precision, name, 0, outName);
+ }
+
+ UniformHandle addUniformArray(uint32_t visibility,
+ GrSLType type,
+ GrSLPrecision precision,
+ const char* name,
+ int arrayCount,
+ const char** outName = nullptr) {
+ return this->internalAddUniformArray(visibility, type, precision, name, true, arrayCount,
+ outName);
+ }
+
+ virtual const GrGLSLShaderVar& getUniformVariable(UniformHandle u) const = 0;
+
+ /**
+ * Shortcut for getUniformVariable(u).c_str()
+ */
+ virtual const char* getUniformCStr(UniformHandle u) const = 0;
+
+ virtual const GrGLSLCaps* glslCaps() const = 0;
+
+ /*
+ * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
+ */
+protected:
+ virtual UniformHandle internalAddUniformArray(
+ uint32_t visibility,
+ GrSLType type,
+ GrSLPrecision precision,
+ const char* name,
+ bool mangleName,
+ int arrayCount,
+ const char** outName) = 0;
+};
+
+// TODO move this into GrGLSLGPBuilder and move them both out of this file
+class GrGLSLVarying {
+public:
+ bool vsVarying() const { return kVertToFrag_Varying == fVarying ||
+ kVertToGeo_Varying == fVarying; }
+ bool fsVarying() const { return kVertToFrag_Varying == fVarying ||
+ kGeoToFrag_Varying == fVarying; }
+ const char* vsOut() const { return fVsOut; }
+ const char* gsIn() const { return fGsIn; }
+ const char* gsOut() const { return fGsOut; }
+ const char* fsIn() const { return fFsIn; }
+ GrSLType type() const { return fType; }
+
+protected:
+ enum Varying {
+ kVertToFrag_Varying,
+ kVertToGeo_Varying,
+ kGeoToFrag_Varying,
+ };
+
+ GrGLSLVarying(GrSLType type, Varying varying)
+ : fVarying(varying), fType(type), fVsOut(nullptr), fGsIn(nullptr), fGsOut(nullptr),
+ fFsIn(nullptr) {}
+
+ Varying fVarying;
+
+private:
+ GrSLType fType;
+ const char* fVsOut;
+ const char* fGsIn;
+ const char* fGsOut;
+ const char* fFsIn;
+
+ friend class GrGLVertexBuilder;
+ friend class GrGLGeometryBuilder;
+ friend class GrGLXferBuilder;
+ friend class GrGLFragmentShaderBuilder;
+};
+
+struct GrGLSLVertToFrag : public GrGLSLVarying {
+ GrGLSLVertToFrag(GrSLType type)
+ : GrGLSLVarying(type, kVertToFrag_Varying) {}
+};
+
+struct GrGLSLVertToGeo : public GrGLSLVarying {
+ GrGLSLVertToGeo(GrSLType type)
+ : GrGLSLVarying(type, kVertToGeo_Varying) {}
+};
+
+struct GrGLSLGeoToFrag : public GrGLSLVarying {
+ GrGLSLGeoToFrag(GrSLType type)
+ : GrGLSLVarying(type, kGeoToFrag_Varying) {}
+};
+
+/* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */
+class GrGLSLGPBuilder : public virtual GrGLSLUniformBuilder {
+public:
+ /*
+ * addVarying allows fine grained control for setting up varyings between stages. If you just
+ * need to take an attribute and pass it through to an output value in a fragment shader, use
+ * addPassThroughAttribute.
+ * TODO convert most uses of addVarying to addPassThroughAttribute
+ */
+ virtual void addVarying(const char* name,
+ GrGLSLVarying*,
+ GrSLPrecision precision = kDefault_GrSLPrecision) = 0;
+
+ /*
+ * This call can be used by GP to pass an attribute through all shaders directly to 'output' in
+ * the fragment shader. Though this call effects both the vertex shader and fragment shader,
+ * it expects 'output' to be defined in the fragment shader before this call is made.
+ * TODO it might be nicer behavior to have a flag to declare output inside this call
+ */
+ virtual void addPassThroughAttribute(const GrGeometryProcessor::Attribute*,
+ const char* output) = 0;
+
+ /*
+ * Creates a fragment shader varying that can be referred to.
+ * Comparable to GrGLSLUniformBuilder::addUniform().
+ */
+ virtual SeparableVaryingHandle addSeparableVarying(
+ const char* name, GrGLSLVertToFrag*,
+ GrSLPrecision fsPrecision = kDefault_GrSLPrecision) = 0;
+
+ // TODO rename getFragmentBuilder
+ virtual GrGLFragmentBuilder* getFragmentShaderBuilder() = 0;
+ virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0;
+
+ /*
+ * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
+ */
+};
+
+
+/* a specializations for FPs. Lets the user add uniforms and FS code */
+class GrGLSLFPBuilder : public virtual GrGLSLUniformBuilder {
+public:
+ virtual GrGLFragmentBuilder* getFragmentShaderBuilder() = 0;
+
+ /*
+ * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
+ */
+};
+
+/* a specializations for XPs. Lets the user add uniforms and FS code */
+class GrGLSLXPBuilder : public virtual GrGLSLUniformBuilder {
+public:
+ virtual GrGLXPFragmentBuilder* getFragmentShaderBuilder() = 0;
+
+ /*
+ * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE
+ */
+};
+
+class GrGLSLProgramBuilder : public GrGLSLGPBuilder,
+ public GrGLSLFPBuilder,
+ public GrGLSLXPBuilder {
+public:
+ typedef GrGpu::DrawArgs DrawArgs;
+
+ GrGLXPFragmentBuilder* getFragmentShaderBuilder() override { return &fFS; }
+ GrGLVertexBuilder* getVertexShaderBuilder() override { return &fVS; }
+
+ // Handles for program uniforms (other than per-effect uniforms)
+ struct BuiltinUniformHandles {
+ UniformHandle fRTAdjustmentUni;
+
+ // We use the render target height to provide a y-down frag coord when specifying
+ // origin_upper_left is not supported.
+ UniformHandle fRTHeightUni;
+ };
+
+protected:
+ explicit GrGLSLProgramBuilder(const DrawArgs& args);
+
+ const GrPrimitiveProcessor& primitiveProcessor() const { return *fArgs.fPrimitiveProcessor; }
+ const GrPipeline& pipeline() const { return *fArgs.fPipeline; }
+ const GrProgramDesc& desc() const { return *fArgs.fDesc; }
+ const GrProgramDesc::KeyHeader& header() const { return fArgs.fDesc->header(); }
+
+ void appendUniformDecls(ShaderVisibility, SkString*) const;
+
+ // Used to add a uniform for frag position without mangling the name of the uniform inside of a
+ // stage.
+ UniformHandle addFragPosUniform(uint32_t visibility,
+ GrSLType type,
+ GrSLPrecision precision,
+ const char* name,
+ const char** outName) {
+ return this->internalAddUniformArray(visibility, type, precision, name, false, 0, outName);
+ }
+
+ const char* rtAdjustment() const { return "rtAdjustment"; }
+
+ // Generates a name for a variable. The generated string will be name prefixed by the prefix
+ // char (unless the prefix is '\0'). It also will mangle the name to be stage-specific unless
+ // explicitly asked not to.
+ void nameVariable(SkString* out, char prefix, const char* name, bool mangle = true);
+
+ // number of each input/output type in a single allocation block, used by many builders
+ static const int kVarsPerBlock;
+
+ GrGLVertexBuilder fVS;
+ GrGLGeometryBuilder fGS;
+ GrGLFragmentShaderBuilder fFS;
+ int fStageIndex;
+
+ BuiltinUniformHandles fUniformHandles;
+
+ const DrawArgs& fArgs;
+
+private:
+ virtual void onAppendUniformDecls(ShaderVisibility visibility, SkString* out) const = 0;
+
+ friend class GrGLShaderBuilder;
+ friend class GrGLVertexBuilder;
+ friend class GrGLFragmentShaderBuilder;
+ friend class GrGLGeometryBuilder;
+};
+
+#endif