| Index: src/gpu/gl/GrGLShaderBuilder.cpp
|
| diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
|
| index d11394a7b39371608b1ce113cbc7b8d1a49a4e78..f4ffb4dd2ce2f071743c9c3d08b3edb7abaa4d56 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()));
|
| + }
|
| }
|
|
|