/* * 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 "src/gpu/GrCaps.h" #include "src/gpu/GrGeometryProcessor.h" #include "src/gpu/GrProgramInfo.h" #include "src/gpu/GrRenderTarget.h" #include "src/gpu/GrRenderTargetPriv.h" #include "src/gpu/glsl/GrGLSLFragmentProcessor.h" #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" #include "src/gpu/glsl/GrGLSLPrimitiveProcessor.h" #include "src/gpu/glsl/GrGLSLProgramDataManager.h" #include "src/gpu/glsl/GrGLSLUniformHandler.h" #include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h" #include "src/gpu/glsl/GrGLSLXferProcessor.h" class GrProgramDesc; class GrShaderVar; class GrGLSLVaryingHandler; class SkString; class GrShaderCaps; class GrGLSLProgramBuilder { public: using UniformHandle = GrGLSLUniformHandler::UniformHandle; using SamplerHandle = GrGLSLUniformHandler::SamplerHandle; virtual ~GrGLSLProgramBuilder() {} virtual const GrCaps* caps() const = 0; const GrShaderCaps* shaderCaps() const { return this->caps()->shaderCaps(); } GrSurfaceOrigin origin() const { return fProgramInfo.origin(); } const GrPipeline& pipeline() const { return fProgramInfo.pipeline(); } const GrPrimitiveProcessor& primitiveProcessor() const { return fProgramInfo.primProc(); } GrProcessor::CustomFeatures processorFeatures() const { return fProgramInfo.requestedFeatures(); } bool snapVerticesToPixelCenters() const { return fProgramInfo.pipeline().snapVerticesToPixelCenters(); } bool hasPointSize() const { return fProgramInfo.primitiveType() == GrPrimitiveType::kPoints; } // TODO: stop passing in the renderTarget for just the sampleLocations int effectiveSampleCnt() const { SkASSERT(GrProcessor::CustomFeatures::kSampleLocations & fProgramInfo.requestedFeatures()); return fRenderTarget->renderTargetPriv().getSampleLocations().count(); } const SkTArray& getSampleLocations() const { return fRenderTarget->renderTargetPriv().getSampleLocations(); } const GrProgramDesc& desc() const { return fDesc; } void appendUniformDecls(GrShaderFlags visibility, SkString*) const; const char* samplerVariable(SamplerHandle handle) const { return this->uniformHandler()->samplerVariable(handle); } GrSwizzle samplerSwizzle(SamplerHandle handle) const { if (this->caps()->shaderCaps()->textureSwizzleAppliedInShader()) { return this->uniformHandler()->samplerSwizzle(handle); } return GrSwizzle::RGBA(); } // Used to add a uniform for the RenderTarget width (used for sk_Width) without mangling // the name of the uniform inside of a stage. void addRTWidthUniform(const char* name); // Used to add a uniform for the RenderTarget height (used for sk_Height and frag position) // without mangling the name of the uniform inside of a stage. void addRTHeightUniform(const char* name); // 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); virtual GrGLSLUniformHandler* uniformHandler() = 0; virtual const GrGLSLUniformHandler* uniformHandler() const = 0; virtual GrGLSLVaryingHandler* varyingHandler() = 0; // Used for backend customization of the output color and secondary color variables from the // fragment processor. Only used if the outputs are explicitly declared in the shaders virtual void finalizeFragmentOutputColor(GrShaderVar& outputColor) {} virtual void finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {} // number of each input/output type in a single allocation block, used by many builders static const int kVarsPerBlock; GrGLSLVertexBuilder fVS; GrGLSLGeometryBuilder fGS; GrGLSLFragmentShaderBuilder fFS; int fStageIndex; const GrRenderTarget* fRenderTarget; // TODO: remove this const GrProgramDesc& fDesc; const GrProgramInfo& fProgramInfo; GrGLSLBuiltinUniformHandles fUniformHandles; std::unique_ptr fGeometryProcessor; std::unique_ptr fXferProcessor; std::unique_ptr[]> fFragmentProcessors; int fFragmentProcessorCnt; protected: explicit GrGLSLProgramBuilder(GrRenderTarget*, const GrProgramDesc&, const GrProgramInfo&); void addFeature(GrShaderFlags shaders, uint32_t featureBit, const char* extensionName); bool emitAndInstallProcs(); void finalizeShaders(); bool fragColorIsInOut() const { return fFS.primaryColorOutputIsInOut(); } private: // reset is called by program creator between each processor's emit code. It increments the // stage offset for variable name mangling, and also ensures verfication variables in the // fragment shader are cleared. void reset() { this->addStage(); SkDEBUGCODE(fFS.debugOnly_resetPerStageVerification();) } void addStage() { fStageIndex++; } class AutoStageAdvance { public: AutoStageAdvance(GrGLSLProgramBuilder* pb) : fPB(pb) { fPB->reset(); // Each output to the fragment processor gets its own code section fPB->fFS.nextStage(); } ~AutoStageAdvance() {} private: GrGLSLProgramBuilder* fPB; }; // Generates a possibly mangled name for a stage variable and writes it to the fragment shader. void nameExpression(SkString*, const char* baseName); void emitAndInstallPrimProc(SkString* outputColor, SkString* outputCoverage); void emitAndInstallFragProcs(SkString* colorInOut, SkString* coverageInOut); SkString emitAndInstallFragProc(const GrFragmentProcessor&, int index, int transformedCoordVarsIdx, const SkString& input, SkString output, SkTArray>*); void emitAndInstallXferProc(const SkString& colorIn, const SkString& coverageIn); SamplerHandle emitSampler(const GrSurfaceProxy*, GrSamplerState, const GrSwizzle&, const char* name); bool checkSamplerCounts(); #ifdef SK_DEBUG void verify(const GrPrimitiveProcessor&); void verify(const GrFragmentProcessor&); void verify(const GrXferProcessor&); #endif // These are used to check that we don't excede the allowable number of resources in a shader. int fNumFragmentSamplers; SkSTArray<4, GrGLSLPrimitiveProcessor::TransformVar> fTransformedCoordVars; }; #endif