aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-09-30 15:30:27 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-09-30 15:30:27 +0000
commit410552a73d59611901033b2bc5147cc6ade0207c (patch)
treee628e55244cfc90c1e834ece089735f80b97fbff /src/gpu
parenta4acf12a9353ffc834d2c6ee673be447487963c9 (diff)
Move the GL shader compilation step into GrGLShaderBuilder
Moves the compilation step and a few other blocks of code from GrGLProgram to GrGLShaderBuilder. This way GrGLProgram doesn't have to know whether or not there is a vertex shader. R=bsalomon@google.com Author: cdalton@nvidia.com Review URL: https://codereview.chromium.org/23533066 git-svn-id: http://skia.googlecode.com/svn/trunk@11523 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/gl/GrGLProgram.cpp382
-rw-r--r--src/gpu/gl/GrGLProgram.h20
-rw-r--r--src/gpu/gl/GrGLSL.cpp8
-rw-r--r--src/gpu/gl/GrGLSL.h18
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.cpp437
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.h98
6 files changed, 419 insertions, 544 deletions
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index ac9794d4d5..f10e8954f2 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -14,28 +14,13 @@
#include "GrGpuGL.h"
#include "GrGLShaderVar.h"
#include "GrGLSL.h"
-#include "SkTrace.h"
#include "SkXfermode.h"
-#include "SkRTConf.h"
-
SK_DEFINE_INST_COUNT(GrGLProgram)
#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
-SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false,
- "Print the source code for all shaders generated.");
-
-#define COL_ATTR_NAME "aColor"
-#define COV_ATTR_NAME "aCoverage"
-#define EDGE_ATTR_NAME "aEdge"
-
-namespace {
-inline const char* declared_color_output_name() { return "fsColorOut"; }
-inline const char* dual_source_output_name() { return "dualSourceOut"; }
-}
-
GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
const GrGLProgramDesc& desc,
const GrEffectStage* colorStages[],
@@ -55,9 +40,6 @@ GrGLProgram::GrGLProgram(GrGpuGL* gpu,
: fGpu(gpu)
, fUniformManager(gpu) {
fDesc = desc;
- fVShaderID = 0;
- fGShaderID = 0;
- fFShaderID = 0;
fProgramID = 0;
fDstCopyTexUnit = -1;
@@ -72,24 +54,12 @@ GrGLProgram::GrGLProgram(GrGpuGL* gpu,
}
GrGLProgram::~GrGLProgram() {
- if (fVShaderID) {
- GL_CALL(DeleteShader(fVShaderID));
- }
- if (fGShaderID) {
- GL_CALL(DeleteShader(fGShaderID));
- }
- if (fFShaderID) {
- GL_CALL(DeleteShader(fFShaderID));
- }
if (fProgramID) {
GL_CALL(DeleteProgram(fProgramID));
}
}
void GrGLProgram::abandon() {
- fVShaderID = 0;
- fGShaderID = 0;
- fFShaderID = 0;
fProgramID = 0;
}
@@ -219,167 +189,7 @@ void add_color_filter(GrGLShaderBuilder* builder,
}
}
-GrSLConstantVec GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) {
- switch (fDesc.getHeader().fColorInput) {
- case GrGLProgramDesc::kAttribute_ColorInput: {
- GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder();
- SkASSERT(NULL != vertexBuilder);
- vertexBuilder->addAttribute(kVec4f_GrSLType, COL_ATTR_NAME);
- const char *vsName, *fsName;
- vertexBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
- vertexBuilder->vsCodeAppendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
- *inColor = fsName;
- return kNone_GrSLConstantVec;
- }
- case GrGLProgramDesc::kUniform_ColorInput: {
- const char* name;
- fUniformHandles.fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kVec4f_GrSLType, "Color", &name);
- *inColor = name;
- return kNone_GrSLConstantVec;
- }
- case GrGLProgramDesc::kTransBlack_ColorInput:
- inColor->reset();
- return kZeros_GrSLConstantVec;
- case GrGLProgramDesc::kSolidWhite_ColorInput:
- inColor->reset();
- return kOnes_GrSLConstantVec;
- default:
- GrCrash("Unknown color type.");
- return kNone_GrSLConstantVec;
- }
-}
-
-GrSLConstantVec GrGLProgram::genInputCoverage(GrGLShaderBuilder* builder, SkString* inCoverage) {
- switch (fDesc.getHeader().fCoverageInput) {
- case GrGLProgramDesc::kAttribute_ColorInput: {
- GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder->getVertexBuilder();
- SkASSERT(NULL != vertexBuilder);
- vertexBuilder->addAttribute(kVec4f_GrSLType, COV_ATTR_NAME);
- const char *vsName, *fsName;
- vertexBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
- vertexBuilder->vsCodeAppendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
- *inCoverage = fsName;
- return kNone_GrSLConstantVec;
- }
- case GrGLProgramDesc::kUniform_ColorInput: {
- const char* name;
- fUniformHandles.fCoverageUni =
- builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kVec4f_GrSLType, "Coverage", &name);
- *inCoverage = name;
- return kNone_GrSLConstantVec;
- }
- case GrGLProgramDesc::kTransBlack_ColorInput:
- inCoverage->reset();
- return kZeros_GrSLConstantVec;
- case GrGLProgramDesc::kSolidWhite_ColorInput:
- inCoverage->reset();
- return kOnes_GrSLConstantVec;
- default:
- GrCrash("Unknown color type.");
- return kNone_GrSLConstantVec;
- }
-}
-
-void GrGLProgram::genGeometryShader(GrGLShaderBuilder::VertexBuilder* vertexBuilder) const {
-#if GR_GL_EXPERIMENTAL_GS
- // TODO: The builder should add all this glue code.
- if (fDesc.getHeader().fExperimentalGS) {
- SkASSERT(fGpu->glslGeneration() >= k150_GrGLSLGeneration);
- vertexBuilder->fGSHeader.append("layout(triangles) in;\n"
- "layout(triangle_strip, max_vertices = 6) out;\n");
- vertexBuilder->gsCodeAppend("\tfor (int i = 0; i < 3; ++i) {\n"
- "\t\tgl_Position = gl_in[i].gl_Position;\n");
- if (fDesc.getHeader().fEmitsPointSize) {
- vertexBuilder->gsCodeAppend("\t\tgl_PointSize = 1.0;\n");
- }
- SkASSERT(vertexBuilder->fGSInputs.count() == vertexBuilder->fGSOutputs.count());
- int count = vertexBuilder->fGSInputs.count();
- for (int i = 0; i < count; ++i) {
- vertexBuilder->gsCodeAppendf("\t\t%s = %s[i];\n",
- vertexBuilder->fGSOutputs[i].getName().c_str(),
- vertexBuilder->fGSInputs[i].getName().c_str());
- }
- vertexBuilder->gsCodeAppend("\t\tEmitVertex();\n"
- "\t}\n"
- "\tEndPrimitive();\n");
- }
-#endif
-}
-
-const char* GrGLProgram::adjustInColor(const SkString& inColor) const {
- if (inColor.size()) {
- return inColor.c_str();
- } else {
- if (GrGLProgramDesc::kSolidWhite_ColorInput == fDesc.getHeader().fColorInput) {
- return GrGLSLOnesVecf(4);
- } else {
- return GrGLSLZerosVecf(4);
- }
- }
-}
-
namespace {
-// prints a shader using params similar to glShaderSource
-void print_shader(GrGLint stringCnt,
- const GrGLchar** strings,
- GrGLint* stringLengths) {
- for (int i = 0; i < stringCnt; ++i) {
- if (NULL == stringLengths || stringLengths[i] < 0) {
- GrPrintf(strings[i]);
- } else {
- GrPrintf("%.*s", stringLengths[i], strings[i]);
- }
- }
-}
-
-// Compiles a GL shader, returns shader ID or 0 if failed params have same meaning as glShaderSource
-GrGLuint compile_shader(const GrGLInterface* gli,
- GrGLenum type,
- int stringCnt,
- const char** strings,
- int* stringLengths) {
- SK_TRACE_EVENT1("GrGLProgram::CompileShader",
- "stringCount", SkStringPrintf("%i", stringCnt).c_str());
-
- GrGLuint shader;
- GR_GL_CALL_RET(gli, shader, CreateShader(type));
- if (0 == shader) {
- return 0;
- }
-
- GrGLint compiled = GR_GL_INIT_ZERO;
- GR_GL_CALL(gli, ShaderSource(shader, stringCnt, strings, stringLengths));
- GR_GL_CALL(gli, CompileShader(shader));
- GR_GL_CALL(gli, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled));
-
- if (!compiled) {
- GrGLint infoLen = GR_GL_INIT_ZERO;
- GR_GL_CALL(gli, GetShaderiv(shader, 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;
- GR_GL_CALL(gli, GetShaderInfoLog(shader, infoLen+1,
- &length, (char*)log.get()));
- print_shader(stringCnt, strings, stringLengths);
- GrPrintf("\n%s", log.get());
- }
- SkDEBUGFAIL("Shader compilation failed!");
- GR_GL_CALL(gli, DeleteShader(shader));
- return 0;
- }
- return shader;
-}
-
-// helper version of above for when shader is already flattened into a single SkString
-GrGLuint compile_shader(const GrGLInterface* gli, GrGLenum type, const SkString& shader) {
- const GrGLchar* str = shader.c_str();
- int length = shader.size();
- return compile_shader(gli, type, 1, &str, &length);
-}
void expand_known_value4f(SkString* string, GrSLConstantVec vec) {
SkASSERT(string->isEmpty() == (vec != kNone_GrSLConstantVec));
@@ -397,50 +207,6 @@ void expand_known_value4f(SkString* string, GrSLConstantVec vec) {
}
-// compiles all the shaders from builder and stores the shader IDs
-bool GrGLProgram::compileShaders(const GrGLShaderBuilder& builder) {
-
- SkASSERT(!fVShaderID);
- SkASSERT(!fGShaderID);
- SkASSERT(!fFShaderID);
-
- SkString shader;
- if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
- vertexBuilder->vsGetShader(&shader);
- if (c_PrintShaders) {
- GrPrintf(shader.c_str());
- GrPrintf("\n");
- }
- if (!(fVShaderID = compile_shader(fGpu->glInterface(), GR_GL_VERTEX_SHADER, shader))) {
- return false;
- }
-
-#if GR_GL_EXPERIMENTAL_GS
- if (fDesc.getHeader().fExperimentalGS) {
- vertexBuilder->gsGetShader(&shader);
- if (c_PrintShaders) {
- GrPrintf(shader.c_str());
- GrPrintf("\n");
- }
- if (!(fGShaderID = compile_shader(fGpu->glInterface(), GR_GL_GEOMETRY_SHADER, shader))) {
- return false;
- }
- }
-#endif
- }
-
- builder.fsGetShader(&shader);
- if (c_PrintShaders) {
- GrPrintf(shader.c_str());
- GrPrintf("\n");
- }
- if (!(fFShaderID = compile_shader(fGpu->glInterface(), GR_GL_FRAGMENT_SHADER, shader))) {
- return false;
- }
-
- return true;
-}
-
bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]) {
SkASSERT(0 == fProgramID);
@@ -449,42 +215,14 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
bool needsVertexShader = true;
- GrGLShaderBuilder builder(fGpu->ctxInfo(), fUniformManager, fDesc, needsVertexShader);
-
+ GrGLShaderBuilder builder(fGpu, fUniformManager, fDesc, needsVertexShader);
if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
- const char* viewMName;
- fUniformHandles.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_Visibility,
- kMat33f_GrSLType, "ViewM", &viewMName);
-
- vertexBuilder->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n"
- "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n",
- viewMName, vertexBuilder->positionAttribute().c_str());
-
- // we output point size in the GS if present
- if (header.fEmitsPointSize
-#if GR_GL_EXPERIMENTAL_GS
- && !header.fExperimentalGS
-#endif
- ) {
- vertexBuilder->vsCodeAppend("\tgl_PointSize = 1.0;\n");
- }
- }
-
- // the dual source output has no canonical var name, have to
- // declare an output, which is incompatible with gl_FragColor/gl_FragData.
- bool dualSourceOutputWritten = false;
-
- GrGLShaderVar colorOutput;
- bool isColorDeclared = GrGLSLSetupFSColorOuput(fGpu->glslGeneration(),
- declared_color_output_name(),
- &colorOutput);
- if (isColorDeclared) {
- builder.fsOutputAppend(colorOutput);
+ fUniformHandles.fViewMatrixUni = vertexBuilder->getViewMatrixUniform();
}
// incoming color to current stage being processed.
- SkString inColor;
- GrSLConstantVec knownColorValue = this->genInputColor(&builder, &inColor);
+ SkString inColor = builder.getInputColor();
+ GrSLConstantVec knownColorValue = builder.getKnownColorValue();
// Get the coeffs for the Mode-based color filter, determine if color is needed.
SkXfermode::Coeff colorCoeff;
@@ -544,8 +282,8 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
///////////////////////////////////////////////////////////////////////////
// compute the partial coverage
- SkString inCoverage;
- GrSLConstantVec knownCoverageValue = this->genInputCoverage(&builder, &inCoverage);
+ SkString inCoverage = builder.getInputCoverage();
+ GrSLConstantVec knownCoverageValue = builder.getKnownCoverageValue();
for (int e = 0; e < fDesc.numCoverageEffects(); ++e) {
effectUniformArrays[e] = &fCoverageEffects[e].fSamplerUnis;
@@ -576,9 +314,8 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
GrGLProgramDesc::CoverageOutput coverageOutput =
static_cast<GrGLProgramDesc::CoverageOutput>(header.fCoverageOutput);
if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(coverageOutput)) {
- builder.fsOutputAppend().set(kVec4f_GrSLType,
- GrGLShaderVar::kOut_TypeModifier,
- dual_source_output_name());
+ const char* secondaryOutputName = builder.enableSecondaryOutput();
+
// default coeff to ones for kCoverage_DualSrcOutput
SkString coeff;
GrSLConstantVec knownCoeffValue = kOnes_GrSLConstantVec;
@@ -613,8 +350,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
knownCoeffValue,
knownCoverageValue,
false);
- builder.fsCodeAppendf("\t%s = %s;\n", dual_source_output_name(), modulate.c_str());
- dualSourceOutputWritten = true;
+ builder.fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, modulate.c_str());
}
///////////////////////////////////////////////////////////////////////////
@@ -655,33 +391,17 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
} else {
expand_known_value4f(&fragColor, knownFragColorValue);
}
- builder.fsCodeAppendf("\t%s = %s;\n", colorOutput.getName().c_str(), fragColor.c_str());
-
- ///////////////////////////////////////////////////////////////////////////
- // insert GS
-#ifdef SK_DEBUG
- if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
- this->genGeometryShader(vertexBuilder);
- }
-#endif
+ builder.fsCodeAppendf("\t%s = %s;\n", builder.getColorOutputName(), fragColor.c_str());
- ///////////////////////////////////////////////////////////////////////////
- // compile and setup attribs and unis
-
- if (!this->compileShaders(builder)) {
- return false;
- }
-
- if (!this->bindOutputsAttribsAndLinkProgram(builder,
- isColorDeclared,
- dualSourceOutputWritten)) {
+ if (!builder.finish(&fProgramID)) {
return false;
}
- builder.finished(fProgramID);
fUniformHandles.fRTHeightUni = builder.getRTHeightUniform();
fUniformHandles.fDstCopyTopLeftUni = builder.getDstCopyTopLeftUniform();
fUniformHandles.fDstCopyScaleUni = builder.getDstCopyScaleUniform();
+ fUniformHandles.fColorUni = builder.getColorUniform();
+ fUniformHandles.fCoverageUni = builder.getCoverageUniform();
fUniformHandles.fDstCopySamplerUni = builder.getDstCopySamplerUniform();
// This must be called after we set fDstCopySamplerUni above.
this->initSamplerUniforms();
@@ -689,82 +409,6 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
return true;
}
-bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder,
- bool bindColorOut,
- bool bindDualSrcOut) {
- GL_CALL_RET(fProgramID, CreateProgram());
- if (!fProgramID) {
- return false;
- }
-
- if (fVShaderID) {
- GL_CALL(AttachShader(fProgramID, fVShaderID));
- }
- if (fGShaderID) {
- GL_CALL(AttachShader(fProgramID, fGShaderID));
- }
- GL_CALL(AttachShader(fProgramID, fFShaderID));
-
- if (bindColorOut) {
- GL_CALL(BindFragDataLocation(fProgramID, 0, declared_color_output_name()));
- }
- if (bindDualSrcOut) {
- GL_CALL(BindFragDataLocationIndexed(fProgramID, 0, 1, dual_source_output_name()));
- }
-
- const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
-
- // Bind the attrib locations to same values for all shaders
- if (GrGLShaderBuilder::VertexBuilder* vertexBuilder = builder.getVertexBuilder()) {
- GL_CALL(BindAttribLocation(fProgramID,
- header.fPositionAttributeIndex,
- vertexBuilder->positionAttribute().c_str()));
- if (-1 != header.fLocalCoordAttributeIndex) {
- GL_CALL(BindAttribLocation(fProgramID,
- header.fLocalCoordAttributeIndex,
- vertexBuilder->localCoordsAttribute().c_str()));
- }
- if (-1 != header.fColorAttributeIndex) {
- GL_CALL(BindAttribLocation(fProgramID, header.fColorAttributeIndex, COL_ATTR_NAME));
- }
- if (-1 != header.fCoverageAttributeIndex) {
- GL_CALL(BindAttribLocation(fProgramID, header.fCoverageAttributeIndex, COV_ATTR_NAME));
- }
-
- const GrGLShaderBuilder::VertexBuilder::AttributePair* attribEnd = vertexBuilder->getEffectAttributes().end();
- for (const GrGLShaderBuilder::VertexBuilder::AttributePair* attrib = vertexBuilder->getEffectAttributes().begin();
- attrib != attribEnd;
- ++attrib) {
- GL_CALL(BindAttribLocation(fProgramID, attrib->fIndex, attrib->fName.c_str()));
- }
- }
-
- GL_CALL(LinkProgram(fProgramID));
-
- 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;
- }
- return true;
-}
-
void GrGLProgram::initSamplerUniforms() {
GL_CALL(UseProgram(fProgramID));
GrGLint texUnitIdx = 0;
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 09f7668be2..0304acf2c7 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -172,25 +172,10 @@ private:
*/
bool genProgram(const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[]);
- GrSLConstantVec genInputColor(GrGLShaderBuilder* builder, SkString* inColor);
-
- GrSLConstantVec genInputCoverage(GrGLShaderBuilder* builder, SkString* inCoverage);
-
- void genGeometryShader(GrGLShaderBuilder::VertexBuilder* vertexBuilder) const;
-
- // Creates a GL program ID, binds shader attributes to GL vertex attrs, and links the program
- bool bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& builder,
- bool bindColorOut,
- bool bindDualSrcOut);
-
// Sets the texture units for samplers
void initSamplerUniforms();
void initEffectSamplerUniforms(EffectAndSamplers* effect, int* texUnitIdx);
- bool compileShaders(const GrGLShaderBuilder& builder);
-
- const char* adjustInColor(const SkString& inColor) const;
-
// Helper for setData().
void setEffectData(const GrEffectStage& stage, const EffectAndSamplers& effect);
@@ -205,10 +190,7 @@ private:
// Helper for setData() that sets the view matrix and loads the render target height uniform
void setMatrixAndRenderTargetHeight(const GrDrawState&);
- // GL IDs
- GrGLuint fVShaderID;
- GrGLuint fGShaderID;
- GrGLuint fFShaderID;
+ // GL program ID
GrGLuint fProgramID;
// these reflect the current values of uniforms (GL uniform values travel with program)
diff --git a/src/gpu/gl/GrGLSL.cpp b/src/gpu/gl/GrGLSL.cpp
index 29596827da..f48f038546 100644
--- a/src/gpu/gl/GrGLSL.cpp
+++ b/src/gpu/gl/GrGLSL.cpp
@@ -63,14 +63,6 @@ const char* GrGetGLSLVersionDecl(const GrGLContextInfo& info) {
}
}
-bool GrGLSLSetupFSColorOuput(GrGLSLGeneration gen, const char* nameIfDeclared, GrGLShaderVar* var) {
- bool declaredOutput = k110_GrGLSLGeneration != gen;
- var->set(kVec4f_GrSLType,
- GrGLShaderVar::kOut_TypeModifier,
- declaredOutput ? nameIfDeclared : "gl_FragColor");
- return declaredOutput;
-}
-
const char* GrGLSLVectorHomogCoord(int count) {
static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"};
SkASSERT(count >= 1 && count < (int)GR_ARRAY_COUNT(HOMOGS));
diff --git a/src/gpu/gl/GrGLSL.h b/src/gpu/gl/GrGLSL.h
index a54bd3b3d7..b97e709aca 100644
--- a/src/gpu/gl/GrGLSL.h
+++ b/src/gpu/gl/GrGLSL.h
@@ -87,24 +87,6 @@ GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding,
const char* GrGetGLSLVersionDecl(const GrGLContextInfo&);
/**
- * Depending on the GLSL version being emitted there may be an assumed output
- * variable from the fragment shader for the color. Otherwise, the shader must
- * declare an output variable for the color. If this function returns true:
- * * Parameter var's name will be set to nameIfDeclared
- * * The variable must be declared in the fragment shader
- * * The variable has to be bound as the color output
- * (using glBindFragDataLocation)
- * If the function returns false:
- * * Parameter var's name will be set to the GLSL built-in color output name.
- * * Do not declare the variable in the shader.
- * * Do not use glBindFragDataLocation to bind the variable
- * In either case var is initialized to represent the color output in the
- * shader.
- */
-bool GrGLSLSetupFSColorOuput(GrGLSLGeneration gen,
- const char* nameIfDeclared,
- GrGLShaderVar* var);
-/**
* Converts a GrSLType to a string containing the name of the equivalent GLSL type.
*/
static const char* GrGLSLTypeString(GrSLType t) {
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index d11394a7b3..f4ffb4dd2c 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -9,7 +9,13 @@
#include "gl/GrGLProgram.h"
#include "gl/GrGLUniformHandle.h"
#include "GrDrawEffect.h"
+#include "GrGpuGL.h"
#include "GrTexture.h"
+#include "SkRTConf.h"
+#include "SkTrace.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)
// number of each input/output type in a single allocation block
static const int kVarsPerBlock = 8;
@@ -21,10 +27,18 @@ static const int kMaxFSOutputs = 2;
static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar::kMedium_Precision;
typedef GrGLUniformManager::UniformHandle UniformHandle;
+
+SK_CONF_DECLARE(bool, c_PrintShaders, "gpu.printShaders", false,
+ "Print the source code for all shaders generated.");
+
///////////////////////////////////////////////////////////////////////////////
namespace {
+inline const char* color_attribute_name() { return "aColor"; }
+inline const char* coverage_attribute_name() { return "aCoverage"; }
+inline const char* declared_color_output_name() { return "fsColorOut"; }
+inline const char* dual_source_output_name() { return "dualSourceOut"; }
inline const char* sample_function_name(GrSLType type, GrGLSLGeneration glslGen) {
if (kVec2f_GrSLType == type) {
return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D";
@@ -91,28 +105,32 @@ static const char kDstCopyColorName[] = "_dstColor";
///////////////////////////////////////////////////////////////////////////////
-GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
+GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu,
GrGLUniformManager& uniformManager,
const GrGLProgramDesc& desc,
bool needsVertexShader)
: fUniforms(kVarsPerBlock)
- , fCtxInfo(ctxInfo)
+ , fGpu(gpu)
, fUniformManager(uniformManager)
, fFSFeaturesAddedMask(0)
, fFSInputs(kVarsPerBlock)
, fFSOutputs(kMaxFSOutputs)
, fSetupFragPosition(false)
+ , fKnownColorValue(kNone_GrSLConstantVec)
+ , fKnownCoverageValue(kNone_GrSLConstantVec)
+ , fHasCustomColorOutput(false)
+ , fHasSecondaryOutput(false)
, fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) {
const GrGLProgramDesc::KeyHeader& header = desc.getHeader();
if (needsVertexShader) {
- fVertexBuilder.reset(SkNEW_ARGS(VertexBuilder, (this, desc)));
+ fVertexBuilder.reset(SkNEW_ARGS(VertexBuilder, (this, fGpu, desc)));
}
// Emit code to read the dst copy textue if necessary.
if (kNoDstRead_DstReadKey != header.fDstReadKey &&
- GrGLCaps::kNone_FBFetchType == ctxInfo.caps()->fbFetchType()) {
+ GrGLCaps::kNone_FBFetchType == fGpu->glCaps().fbFetchType()) {
bool topDown = SkToBool(kTopLeftOrigin_DstReadKeyBit & header.fDstReadKey);
const char* dstCopyTopLeftName;
const char* dstCopyCoordScaleName;
@@ -143,15 +161,76 @@ GrGLShaderBuilder::GrGLShaderBuilder(const GrGLContextInfo& ctxInfo,
this->fsAppendTextureLookup(fDstCopySampler, "_dstTexCoord");
this->fsCodeAppend(";\n\n");
}
+
+ switch (header.fColorInput) {
+ case GrGLProgramDesc::kAttribute_ColorInput: {
+ SkASSERT(NULL != fVertexBuilder.get());
+ fVertexBuilder->addAttribute(kVec4f_GrSLType, color_attribute_name());
+ const char *vsName, *fsName;
+ fVertexBuilder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
+ fVertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsName, color_attribute_name());
+ fInputColor = fsName;
+ break;
+ }
+ case GrGLProgramDesc::kUniform_ColorInput: {
+ const char* name;
+ fColorUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType, "Color", &name);
+ fInputColor = name;
+ break;
+ }
+ case GrGLProgramDesc::kTransBlack_ColorInput:
+ fKnownColorValue = kZeros_GrSLConstantVec;
+ break;
+ case GrGLProgramDesc::kSolidWhite_ColorInput:
+ fKnownColorValue = kOnes_GrSLConstantVec;
+ break;
+ default:
+ GrCrash("Unknown color type.");
+ }
+
+ switch (header.fCoverageInput) {
+ case GrGLProgramDesc::kAttribute_ColorInput: {
+ SkASSERT(NULL != fVertexBuilder.get());
+ fVertexBuilder->addAttribute(kVec4f_GrSLType, coverage_attribute_name());
+ const char *vsName, *fsName;
+ fVertexBuilder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
+ fVertexBuilder->vsCodeAppendf("\t%s = %s;\n", vsName, coverage_attribute_name());
+ fInputCoverage = fsName;
+ break;
+ }
+ case GrGLProgramDesc::kUniform_ColorInput: {
+ const char* name;
+ fCoverageUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType, "Coverage", &name);
+ fInputCoverage = name;
+ break;
+ }
+ case GrGLProgramDesc::kTransBlack_ColorInput:
+ fKnownCoverageValue = kZeros_GrSLConstantVec;
+ break;
+ case GrGLProgramDesc::kSolidWhite_ColorInput:
+ fKnownCoverageValue = kOnes_GrSLConstantVec;
+ break;
+ default:
+ GrCrash("Unknown coverage type.");
+ }
+
+ if (k110_GrGLSLGeneration != fGpu->glslGeneration()) {
+ fFSOutputs.push_back().set(kVec4f_GrSLType,
+ GrGLShaderVar::kOut_TypeModifier,
+ declared_color_output_name());
+ fHasCustomColorOutput = true;
+ }
}
bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) {
switch (feature) {
case kStandardDerivatives_GLSLFeature:
- if (!fCtxInfo.caps()->shaderDerivativeSupport()) {
+ if (!fGpu->glCaps().shaderDerivativeSupport()) {
return false;
}
- if (kES_GrGLBinding == fCtxInfo.binding()) {
+ if (kES_GrGLBinding == fGpu->glBinding()) {
this->addFSFeature(1 << kStandardDerivatives_GLSLFeature,
"GL_OES_standard_derivatives");
}
@@ -165,23 +244,23 @@ bool GrGLShaderBuilder::enableFeature(GLSLFeature feature) {
bool GrGLShaderBuilder::enablePrivateFeature(GLSLPrivateFeature feature) {
switch (feature) {
case kFragCoordConventions_GLSLPrivateFeature:
- if (!fCtxInfo.caps()->fragCoordConventionsSupport()) {
+ if (!fGpu->glCaps().fragCoordConventionsSupport()) {
return false;
}
- if (fCtxInfo.glslGeneration() < k150_GrGLSLGeneration) {
+ if (fGpu->glslGeneration() < k150_GrGLSLGeneration) {
this->addFSFeature(1 << kFragCoordConventions_GLSLPrivateFeature,
"GL_ARB_fragment_coord_conventions");
}
return true;
case kEXTShaderFramebufferFetch_GLSLPrivateFeature:
- if (GrGLCaps::kEXT_FBFetchType != fCtxInfo.caps()->fbFetchType()) {
+ if (GrGLCaps::kEXT_FBFetchType != fGpu->glCaps().fbFetchType()) {
return false;
}
this->addFSFeature(1 << kEXTShaderFramebufferFetch_GLSLPrivateFeature,
"GL_EXT_shader_framebuffer_fetch");
return true;
case kNVShaderFramebufferFetch_GLSLPrivateFeature:
- if (GrGLCaps::kNV_FBFetchType != fCtxInfo.caps()->fbFetchType()) {
+ if (GrGLCaps::kNV_FBFetchType != fGpu->glCaps().fbFetchType()) {
return false;
}
this->addFSFeature(1 << kNVShaderFramebufferFetch_GLSLPrivateFeature,
@@ -225,7 +304,7 @@ const char* GrGLShaderBuilder::dstColor() {
}
}
static const char kFBFetchColorName[] = "gl_LastFragData[0]";
- GrGLCaps::FBFetchType fetchType = fCtxInfo.caps()->fbFetchType();
+ GrGLCaps::FBFetchType fetchType = fGpu->glCaps().fbFetchType();
if (GrGLCaps::kEXT_FBFetchType == fetchType) {
SkAssertResult(this->enablePrivateFeature(kEXTShaderFramebufferFetch_GLSLPrivateFeature));
return kFBFetchColorName;
@@ -246,10 +325,10 @@ void GrGLShaderBuilder::appendTextureLookup(SkString* out,
SkASSERT(NULL != coordName);
out->appendf("%s(%s, %s)",
- sample_function_name(varyingType, fCtxInfo.glslGeneration()),
+ sample_function_name(varyingType, fGpu->glslGeneration()),
this->getUniformCStr(sampler.fSamplerUniform),
coordName);
- append_swizzle(out, sampler, *fCtxInfo.caps());
+ append_swizzle(out, sampler, fGpu->glCaps());
}
void GrGLShaderBuilder::fsAppendTextureLookup(const GrGLShaderBuilder::TextureSampler& sampler,
@@ -379,7 +458,7 @@ const char* GrGLShaderBuilder::fragmentPosition() {
fSetupFragPosition = true;
}
return "gl_FragCoord";
- } else if (fCtxInfo.caps()->fragCoordConventionsSupport()) {
+ } else if (fGpu->glCaps().fragCoordConventionsSupport()) {
if (!fSetupFragPosition) {
SkAssertResult(this->enablePrivateFeature(kFragCoordConventions_GLSLPrivateFeature));
fFSInputs.push_back().set(kVec4f_GrSLType,
@@ -425,7 +504,7 @@ void GrGLShaderBuilder::fsEmitFunction(GrSLType returnType,
fFSFunctions.appendf(" %s", outName->c_str());
fFSFunctions.append("(");
for (int i = 0; i < argCnt; ++i) {
- args[i].appendDecl(fCtxInfo, &fFSFunctions);
+ args[i].appendDecl(this->ctxInfo(), &fFSFunctions);
if (i < argCnt - 1) {
fFSFunctions.append(", ");
}
@@ -463,7 +542,7 @@ inline void append_default_precision_qualifier(GrGLShaderVar::Precision p,
void GrGLShaderBuilder::appendDecls(const VarArray& vars, SkString* out) const {
for (int i = 0; i < vars.count(); ++i) {
- vars[i].appendDecl(fCtxInfo, out);
+ vars[i].appendDecl(this->ctxInfo(), out);
out->append(";\n");
}
}
@@ -472,33 +551,12 @@ void GrGLShaderBuilder::appendUniformDecls(ShaderVisibility visibility,
SkString* out) const {
for (int i = 0; i < fUniforms.count(); ++i) {
if (fUniforms[i].fVisibility & visibility) {
- fUniforms[i].fVariable.appendDecl(fCtxInfo, out);
+ fUniforms[i].fVariable.appendDecl(this->ctxInfo(), out);
out->append(";\n");
}
}
}
-void GrGLShaderBuilder::fsGetShader(SkString* shaderStr) const {
- *shaderStr = GrGetGLSLVersionDecl(fCtxInfo);
- shaderStr->append(fFSExtensions);
- append_default_precision_qualifier(kDefaultFragmentPrecision,
- fCtxInfo.binding(),
- shaderStr);
- this->appendUniformDecls(kFragment_Visibility, shaderStr);
- this->appendDecls(fFSInputs, shaderStr);
- // We shouldn't have declared outputs on 1.10
- SkASSERT(k110_GrGLSLGeneration != fCtxInfo.glslGeneration() || fFSOutputs.empty());
- this->appendDecls(fFSOutputs, shaderStr);
- shaderStr->append(fFSFunctions);
- shaderStr->append("void main() {\n");
- shaderStr->append(fFSCode);
- shaderStr->append("}\n");
-}
-
-void GrGLShaderBuilder::finished(GrGLuint programID) {
- fUniformManager.getUniformLocations(programID, fUniforms);
-}
-
void GrGLShaderBuilder::emitEffects(
const GrEffectStage* effectStages[],
const GrBackendEffectFactory::EffectKey effectKeys[],
@@ -526,7 +584,7 @@ void GrGLShaderBuilder::emitEffects(
textureSamplers[t].init(this, &effect->textureAccess(t), t);
effectSamplerHandles[e]->push_back(textureSamplers[t].fSamplerUniform);
}
- GrDrawEffect drawEffect(stage, fVertexBuilder.get()
+ GrDrawEffect drawEffect(stage, NULL != fVertexBuilder.get()
&& fVertexBuilder->hasExplicitLocalCoords());
int numAttributes = stage.getVertexAttribIndexCount();
@@ -534,7 +592,7 @@ void GrGLShaderBuilder::emitEffects(
SkSTArray<GrEffect::kMaxVertexAttribs, SkString> attributeNames;
for (int a = 0; a < numAttributes; ++a) {
// TODO: Make addAttribute mangle the name.
- SkASSERT(fVertexBuilder.get());
+ SkASSERT(NULL != fVertexBuilder.get());
SkString attributeName("aAttr");
attributeName.appendS32(attributeIndices[a]);
fVertexBuilder->addEffectAttribute(attributeIndices[a],
@@ -557,7 +615,7 @@ void GrGLShaderBuilder::emitEffects(
// Enclose custom code in a block to avoid namespace conflicts
SkString openBrace;
openBrace.printf("\t{ // Stage %d: %s\n", fCodeStage.stageIndex(), glEffects[e]->name());
- if (fVertexBuilder.get()) {
+ if (NULL != fVertexBuilder.get()) {
fVertexBuilder->vsCodeAppend(openBrace.c_str());
}
this->fsCodeAppend(openBrace.c_str());
@@ -569,7 +627,7 @@ void GrGLShaderBuilder::emitEffects(
inColor.isEmpty() ? NULL : inColor.c_str(),
textureSamplers);
- if (fVertexBuilder.get()) {
+ if (NULL != fVertexBuilder.get()) {
fVertexBuilder->vsCodeAppend("\t}\n");
}
this->fsCodeAppend("\t}\n");
@@ -584,22 +642,170 @@ void GrGLShaderBuilder::emitEffects(
}
}
+const char* GrGLShaderBuilder::getColorOutputName() const {
+ return fHasCustomColorOutput ? declared_color_output_name() : "gl_FragColor";
+}
+
+const char* GrGLShaderBuilder::enableSecondaryOutput() {
+ if (!fHasSecondaryOutput) {
+ fFSOutputs.push_back().set(kVec4f_GrSLType,
+ GrGLShaderVar::kOut_TypeModifier,
+ dual_source_output_name());
+ fHasSecondaryOutput = true;
+ }
+ return dual_source_output_name();
+}
+
+
+bool GrGLShaderBuilder::finish(GrGLuint* outProgramId) {
+ SK_TRACE_EVENT0("GrGLShaderBuilder::finish");
+
+ GrGLuint programId = 0;
+ GL_CALL_RET(programId, CreateProgram());
+ if (!programId) {
+ return false;
+ }
+
+ if (!this->compileAndAttachShaders(programId)) {
+ GL_CALL(DeleteProgram(programId));
+ return false;
+ }
+
+ this->bindProgramLocations(programId);
+
+ GL_CALL(LinkProgram(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());
+ }
+ SkDEBUGFAIL("Error linking program");
+ GL_CALL(DeleteProgram(programId));
+ return false;
+ }
+
+ fUniformManager.getUniformLocations(programId, fUniforms);
+ *outProgramId = programId;
+ return true;
+}
+
+namespace {
+// Compiles a GL shader, attaches it to a program, and releases the shader's reference.
+// (That way there's no need to hang on to the GL shader id and delete it later.)
+bool attach_shader(const GrGLInterface* gli,
+ GrGLuint programId,
+ GrGLenum type,
+ const SkString& shaderSrc) {
+ GrGLuint shaderId;
+ GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
+ if (0 == shaderId) {
+ return false;
+ }
+
+ const GrGLchar* sourceStr = shaderSrc.c_str();
+ int sourceLength = shaderSrc.size();
+ GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength));
+
+ GrGLint compiled = GR_GL_INIT_ZERO;
+ GR_GL_CALL(gli, CompileShader(shaderId));
+ GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
+
+ if (!compiled) {
+ GrGLint infoLen = GR_GL_INIT_ZERO;
+ GR_GL_CALL(gli, GetShaderiv(shaderId, 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;
+ GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1,
+ &length, (char*)log.get()));
+ GrPrintf(shaderSrc.c_str());
+ GrPrintf("\n%s", log.get());
+ }
+ SkDEBUGFAIL("Shader compilation failed!");
+ GR_GL_CALL(gli, DeleteShader(shaderId));
+ return false;
+ } else if (c_PrintShaders) {
+ GrPrintf(shaderSrc.c_str());
+ GrPrintf("\n");
+ }
+
+ GR_GL_CALL(gli, AttachShader(programId, shaderId));
+ GR_GL_CALL(gli, DeleteShader(shaderId));
+ return true;
+}
+
+}
+
+bool GrGLShaderBuilder::compileAndAttachShaders(GrGLuint programId) const {
+ if (NULL != fVertexBuilder.get() && !fVertexBuilder->compileAndAttachShaders(programId)) {
+ return false;
+ }
+
+ SkString fragShaderSrc(GrGetGLSLVersionDecl(this->ctxInfo()));
+ fragShaderSrc.append(fFSExtensions);
+ append_default_precision_qualifier(kDefaultFragmentPrecision,
+ fGpu->glBinding(),
+ &fragShaderSrc);
+ this->appendUniformDecls(kFragment_Visibility, &fragShaderSrc);
+ this->appendDecls(fFSInputs, &fragShaderSrc);
+ // We shouldn't have declared outputs on 1.10
+ SkASSERT(k110_GrGLSLGeneration != fGpu->glslGeneration() || fFSOutputs.empty());
+ this->appendDecls(fFSOutputs, &fragShaderSrc);
+ fragShaderSrc.append(fFSFunctions);
+ fragShaderSrc.append("void main() {\n");
+ fragShaderSrc.append(fFSCode);
+ fragShaderSrc.append("}\n");
+ if (!attach_shader(fGpu->glInterface(), programId, GR_GL_FRAGMENT_SHADER, fragShaderSrc)) {
+ return false;
+ }
+
+ return true;
+}
+
+void GrGLShaderBuilder::bindProgramLocations(GrGLuint programId) const {
+ if (NULL != fVertexBuilder.get()) {
+ fVertexBuilder->bindProgramLocations(programId);
+ }
+
+ if (fHasCustomColorOutput) {
+ GL_CALL(BindFragDataLocation(programId, 0, declared_color_output_name()));
+ }
+ if (fHasSecondaryOutput) {
+ GL_CALL(BindFragDataLocationIndexed(programId, 0, 1, dual_source_output_name()));
+ }
+}
+
+const GrGLContextInfo& GrGLShaderBuilder::ctxInfo() const {
+ return fGpu->ctxInfo();
+}
+
////////////////////////////////////////////////////////////////////////////
GrGLShaderBuilder::VertexBuilder::VertexBuilder(GrGLShaderBuilder* parent,
+ GrGpuGL* gpu,
const GrGLProgramDesc& desc)
- : fVSAttrs(kVarsPerBlock)
+ : fParent(parent)
+ , fGpu(gpu)
+ , fDesc(desc)
+ , fVSAttrs(kVarsPerBlock)
, fVSOutputs(kVarsPerBlock)
, fGSInputs(kVarsPerBlock)
- , fGSOutputs(kVarsPerBlock)
- , fParent(parent)
-#if GR_GL_EXPERIMENTAL_GS
- , fUsesGS(SkToBool(desc.getHeader().fExperimentalGS))
-#else
- , fUsesGS(false)
-#endif
-{
- const GrGLProgramDesc::KeyHeader& header = desc.getHeader();
+ , fGSOutputs(kVarsPerBlock) {
+
+ const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
fPositionVar = &fVSAttrs.push_back();
fPositionVar->set(kVec2f_GrSLType, GrGLShaderVar::kAttribute_TypeModifier, "aPosition");
@@ -611,6 +817,23 @@ GrGLShaderBuilder::VertexBuilder::VertexBuilder(GrGLShaderBuilder* parent,
} else {
fLocalCoordsVar = fPositionVar;
}
+
+ const char* viewMName;
+ fViewMatrixUniform = fParent->addUniform(GrGLShaderBuilder::kVertex_Visibility,
+ kMat33f_GrSLType, "ViewM", &viewMName);
+
+ this->vsCodeAppendf("\tvec3 pos3 = %s * vec3(%s, 1);\n"
+ "\tgl_Position = vec4(pos3.xy, 0, pos3.z);\n",
+ 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->vsCodeAppend("\tgl_PointSize = 1.0;\n");
+ }
}
bool GrGLShaderBuilder::VertexBuilder::addAttribute(GrSLType type,
@@ -654,7 +877,8 @@ void GrGLShaderBuilder::VertexBuilder::addVarying(GrSLType type,
}
// input to FS comes either from VS or GS
const SkString* fsName;
- if (fUsesGS) {
+#if GR_GL_EXPERIMENTAL_GS
+ if (fDesc.getHeader().fExperimentalGS) {
// if we have a GS take each varying in as an array
// and output as non-array.
fGSInputs.push_back();
@@ -667,7 +891,9 @@ void GrGLShaderBuilder::VertexBuilder::addVarying(GrSLType type,
fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
fParent->nameVariable(fGSOutputs.back().accessName(), 'g', name);
fsName = fGSOutputs.back().accessName();
- } else {
+ } else
+#endif
+ {
fsName = fVSOutputs.back().accessName();
}
fParent->fsInputAppend().set(type,
@@ -678,41 +904,88 @@ void GrGLShaderBuilder::VertexBuilder::addVarying(GrSLType type,
}
}
-void GrGLShaderBuilder::VertexBuilder::vsGetShader(SkString* shaderStr) const {
- *shaderStr = GrGetGLSLVersionDecl(fParent->ctxInfo());
- fParent->appendUniformDecls(kVertex_Visibility, shaderStr);
- fParent->appendDecls(fVSAttrs, shaderStr);
- fParent->appendDecls(fVSOutputs, shaderStr);
- shaderStr->append("void main() {\n");
- shaderStr->append(fVSCode);
- shaderStr->append("}\n");
+const SkString* GrGLShaderBuilder::VertexBuilder::getEffectAttributeName(int attributeIndex) const {
+ const AttributePair* attribEnd = fEffectAttributes.end();
+ for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) {
+ if (attrib->fIndex == attributeIndex) {
+ return &attrib->fName;
+ }
+ }
+
+ return NULL;
}
-void GrGLShaderBuilder::VertexBuilder::gsGetShader(SkString* shaderStr) const {
- if (!fUsesGS) {
- shaderStr->reset();
- return;
+bool GrGLShaderBuilder::VertexBuilder::compileAndAttachShaders(GrGLuint programId) const {
+ SkString vertShaderSrc(GrGetGLSLVersionDecl(fParent->ctxInfo()));
+ fParent->appendUniformDecls(kVertex_Visibility, &vertShaderSrc);
+ fParent->appendDecls(fVSAttrs, &vertShaderSrc);
+ fParent->appendDecls(fVSOutputs, &vertShaderSrc);
+ vertShaderSrc.append("void main() {\n");
+ vertShaderSrc.append(fVSCode);
+ vertShaderSrc.append("}\n");
+ if (!attach_shader(fGpu->glInterface(), programId, GR_GL_VERTEX_SHADER, vertShaderSrc)) {
+ return false;
}
- *shaderStr = GrGetGLSLVersionDecl(fParent->ctxInfo());
- shaderStr->append(fGSHeader);
- fParent->appendDecls(fGSInputs, shaderStr);
- fParent->appendDecls(fGSOutputs, shaderStr);
- shaderStr->append("void main() {\n");
- shaderStr->append(fGSCode);
- shaderStr->append("}\n");
+#if GR_GL_EXPERIMENTAL_GS
+ if (fDesc.getHeader().fExperimentalGS) {
+ SkASSERT(fGpu->glslGeneration() >= k150_GrGLSLGeneration);
+ SkString geomShaderSrc(GrGetGLSLVersionDecl(fParent->ctxInfo()));
+ geomShaderSrc.append("layout(triangles) in;\n"
+ "layout(triangle_strip, max_vertices = 6) out;\n");
+ fParent->appendDecls(fGSInputs, &geomShaderSrc);
+ fParent->appendDecls(fGSOutputs, &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");
+ if (fDesc.getHeader().fEmitsPointSize) {
+ geomShaderSrc.append("\t\tgl_PointSize = 1.0;\n");
+ }
+ SkASSERT(fGSInputs.count() == fGSOutputs.count());
+ for (int i = 0; i < fGSInputs.count(); ++i) {
+ geomShaderSrc.appendf("\t\t%s = %s[i];\n",
+ fGSOutputs[i].getName().c_str(),
+ fGSInputs[i].getName().c_str());
+ }
+ geomShaderSrc.append("\t\tEmitVertex();\n"
+ "\t}\n"
+ "\tEndPrimitive();\n");
+ geomShaderSrc.append("}\n");
+ if (!attach_shader(fGpu->glInterface(), programId, GR_GL_GEOMETRY_SHADER, geomShaderSrc)) {
+ return false;
+ }
+ }
+#endif
+
+ return true;
}
+void GrGLShaderBuilder::VertexBuilder::bindProgramLocations(GrGLuint programId) const {
+ const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
-const SkString* GrGLShaderBuilder::VertexBuilder::getEffectAttributeName(int attributeIndex) const {
- const AttributePair* attribEnd = this->getEffectAttributes().end();
- for (const AttributePair* attrib = this->getEffectAttributes().begin();
- attrib != attribEnd;
- ++attrib) {
- if (attrib->fIndex == attributeIndex) {
- return &attrib->fName;
- }
+ // Bind the attrib locations to same values for all shaders
+ SkASSERT(-1 != header.fPositionAttributeIndex);
+ GL_CALL(BindAttribLocation(programId,
+ header.fPositionAttributeIndex,
+ fPositionVar->c_str()));
+ if (-1 != header.fLocalCoordAttributeIndex) {
+ GL_CALL(BindAttribLocation(programId,
+ header.fLocalCoordAttributeIndex,
+ fLocalCoordsVar->c_str()));
+ }
+ if (-1 != header.fColorAttributeIndex) {
+ GL_CALL(BindAttribLocation(programId,
+ header.fColorAttributeIndex,
+ color_attribute_name()));
+ }
+ if (-1 != header.fCoverageAttributeIndex) {
+ GL_CALL(BindAttribLocation(programId,
+ header.fCoverageAttributeIndex,
+ coverage_attribute_name()));
}
- return NULL;
+ const AttributePair* attribEnd = fEffectAttributes.end();
+ for (const AttributePair* attrib = fEffectAttributes.begin(); attrib != attribEnd; ++attrib) {
+ GL_CALL(BindAttribLocation(programId, attrib->fIndex, attrib->fName.c_str()));
+ }
}
diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h
index 3c3275ce36..d73a731a7c 100644
--- a/src/gpu/gl/GrGLShaderBuilder.h
+++ b/src/gpu/gl/GrGLShaderBuilder.h
@@ -105,7 +105,7 @@ public:
kFragment_Visibility = 0x4,
};
- GrGLShaderBuilder(const GrGLContextInfo&,
+ GrGLShaderBuilder(GrGpuGL*,
GrGLUniformManager&,
const GrGLProgramDesc&,
bool needsVertexShader);
@@ -171,9 +171,6 @@ public:
/** Add input/output variable declarations (i.e. 'varying') to the fragment shader. */
GrGLShaderVar& fsInputAppend() { return fFSInputs.push_back(); }
- GrGLShaderVar& fsOutputAppend() { return fFSOutputs.push_back(); }
- GrGLShaderVar& fsInputAppend(const GrGLShaderVar& var) { return fFSInputs.push_back(var); }
- GrGLShaderVar& fsOutputAppend(const GrGLShaderVar& var) { return fFSOutputs.push_back(var); }
/** Generates a EffectKey for the shader code based on the texture access parameters and the
capabilities of the GL context. This is useful for keying the shader programs that may
@@ -238,13 +235,13 @@ public:
/**
* Interfaces used by GrGLProgram.
- * TODO: Hide these from the GrEffects using friend or splitting this into two related classes.
- * Also, GrGLProgram's shader string construction should be moved to this class.
+ * TODO: These are used by GrGLProgram to insert a mode color filter. Remove these when the
+ * color filter is expressed as a GrEffect.
*/
-
- /** Called after building is complete to get the final shader string. To acces the vertex
- and geometry shaders, use the VertexBuilder. */
- void fsGetShader(SkString*) const;
+ const SkString& getInputColor() const { return fInputColor; }
+ GrSLConstantVec getKnownColorValue() const { return fKnownColorValue; }
+ const SkString& getInputCoverage() const { return fInputCoverage; }
+ GrSLConstantVec getKnownCoverageValue() const { return fKnownCoverageValue; }
/**
* Adds code for effects. effectStages contains the effects to add. effectKeys[i] is the key
@@ -265,6 +262,9 @@ public:
SkTArray<GrGLUniformManager::UniformHandle, true>* effectSamplerHandles[],
GrGLEffect* glEffects[]);
+ const char* getColorOutputName() const;
+ const char* enableSecondaryOutput();
+
GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
GrGLUniformManager::UniformHandle getDstCopyTopLeftUniform() const {
return fDstCopyTopLeftUniform;
@@ -272,6 +272,8 @@ public:
GrGLUniformManager::UniformHandle getDstCopyScaleUniform() const {
return fDstCopyScaleUniform;
}
+ GrGLUniformManager::UniformHandle getColorUniform() const { return fColorUniform; }
+ GrGLUniformManager::UniformHandle getCoverageUniform() const { return fCoverageUniform; }
GrGLUniformManager::UniformHandle getDstCopySamplerUniform() const {
return fDstCopySampler.fSamplerUniform;
}
@@ -281,7 +283,7 @@ public:
that only use the fragment shader. */
class VertexBuilder {
public:
- VertexBuilder(GrGLShaderBuilder* parent, const GrGLProgramDesc&);
+ VertexBuilder(GrGLShaderBuilder* parent, GrGpuGL* gpu, const GrGLProgramDesc&);
/**
* Called by GrGLEffects to add code to one of the shaders.
@@ -293,15 +295,7 @@ public:
va_end(args);
}
- void gsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
- va_list args;
- va_start(args, format);
- fGSCode.appendf(format, args);
- va_end(args);
- }
-
void vsCodeAppend(const char* str) { fVSCode.append(str); }
- void gsCodeAppend(const char* str) { fGSCode.append(str); }
/** Add a vertex attribute to the current program that is passed in from the vertex data.
Returns false if the attribute was already there, true otherwise. */
@@ -330,42 +324,38 @@ public:
*/
bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
- /** Called after building is complete to get the final shader string. */
- void vsGetShader(SkString*) const;
- void gsGetShader(SkString*) const;
-
- struct AttributePair {
- void set(int index, const SkString& name) {
- fIndex = index; fName = name;
- }
- int fIndex;
- SkString fName;
- };
- const SkTArray<AttributePair, true>& getEffectAttributes() const {
- return fEffectAttributes;
- }
bool addEffectAttribute(int attributeIndex, GrSLType type, const SkString& name);
const SkString* getEffectAttributeName(int attributeIndex) const;
- // TODO: Everything below here private.
- public:
+ GrGLUniformManager::UniformHandle getViewMatrixUniform() const {
+ return fViewMatrixUniform;
+ }
- VarArray fVSAttrs;
- VarArray fVSOutputs;
- VarArray fGSInputs;
- VarArray fGSOutputs;
- SkString fGSHeader; // layout qualifiers specific to GS
+ bool compileAndAttachShaders(GrGLuint programId) const;
+ void bindProgramLocations(GrGLuint programId) const;
private:
GrGLShaderBuilder* fParent;
-
- bool fUsesGS;
+ GrGpuGL* fGpu;
+ const GrGLProgramDesc& fDesc;
+ VarArray fVSAttrs;
+ VarArray fVSOutputs;
+ VarArray fGSInputs;
+ VarArray fGSOutputs;
SkString fVSCode;
- SkString fGSCode;
+ struct AttributePair {
+ void set(int index, const SkString& name) {
+ fIndex = index; fName = name;
+ }
+ int fIndex;
+ SkString fName;
+ };
SkSTArray<10, AttributePair, true> fEffectAttributes;
+ GrGLUniformManager::UniformHandle fViewMatrixUniform;
+
GrGLShaderVar* fPositionVar;
GrGLShaderVar* fLocalCoordsVar;
};
@@ -374,15 +364,17 @@ public:
It may be NULL if this shader program is only meant to have a fragment shader. */
VertexBuilder* getVertexBuilder() const { return fVertexBuilder.get(); }
- // TODO: Make this do all the compiling, linking, etc.
- void finished(GrGLuint programID);
+ bool finish(GrGLuint* outProgramId);
- const GrGLContextInfo& ctxInfo() const { return fCtxInfo; }
+ const GrGLContextInfo& ctxInfo() const;
private:
void appendDecls(const VarArray&, SkString*) const;
void appendUniformDecls(ShaderVisibility, SkString*) const;
+ bool compileAndAttachShaders(GrGLuint programId) const;
+ void bindProgramLocations(GrGLuint programId) const;
+
typedef GrGLUniformManager::BuilderUniform BuilderUniform;
GrGLUniformManager::BuilderUniformArray fUniforms;
@@ -471,7 +463,7 @@ private:
kBottomLeftFragPosRead_FragPosKey = 0x2,// Read frag pos relative to bottom-left.
};
- const GrGLContextInfo& fCtxInfo;
+ GrGpuGL* fGpu;
GrGLUniformManager& fUniformManager;
uint32_t fFSFeaturesAddedMask;
SkString fFSFunctions;
@@ -484,13 +476,23 @@ private:
bool fSetupFragPosition;
TextureSampler fDstCopySampler;
+ SkString fInputColor;
+ GrSLConstantVec fKnownColorValue;
+ SkString fInputCoverage;
+ GrSLConstantVec fKnownCoverageValue;
+
+ bool fHasCustomColorOutput;
+ bool fHasSecondaryOutput;
+
GrGLUniformManager::UniformHandle fRTHeightUniform;
GrGLUniformManager::UniformHandle fDstCopyTopLeftUniform;
GrGLUniformManager::UniformHandle fDstCopyScaleUniform;
+ GrGLUniformManager::UniformHandle fColorUniform;
+ GrGLUniformManager::UniformHandle fCoverageUniform;
bool fTopLeftFragPosRead;
- SkAutoTDelete<VertexBuilder> fVertexBuilder;
+ SkAutoTDelete<VertexBuilder> fVertexBuilder;
};
#endif