/* * 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 "glsl/GrGLSLFragmentShaderBuilder.h" #include "glsl/GrGLSLGeometryShaderBuilder.h" #include "glsl/GrGLSLProgramDataManager.h" #include "glsl/GrGLSLVertexShaderBuilder.h" class GrGLSLCaps; class GrGLSLShaderVar; // Enough precision to represent 1 / 2048 accurately in printf #define GR_SIGNIFICANT_POW2_DECIMAL_DIG 11 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 GrGLSLVertexBuilder; friend class GrGLSLGeometryBuilder; friend class GrGLSLXferBuilder; friend class GrGLSLFragmentShaderBuilder; }; 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 GrGLSLFragmentBuilder* getFragmentShaderBuilder() = 0; virtual GrGLSLVertexBuilder* 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 GrGLSLFragmentBuilder* 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 GrGLSLXPFragmentBuilder* getFragmentShaderBuilder() = 0; /* * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE */ }; class GrGLSLProgramBuilder : public GrGLSLGPBuilder, public GrGLSLFPBuilder, public GrGLSLXPBuilder { public: typedef GrGpu::DrawArgs DrawArgs; GrGLSLXPFragmentBuilder* getFragmentShaderBuilder() override { return &fFS; } GrGLSLVertexBuilder* 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; GrGLSLVertexBuilder fVS; GrGLSLGeometryBuilder fGS; GrGLSLFragmentShaderBuilder fFS; int fStageIndex; BuiltinUniformHandles fUniformHandles; const DrawArgs& fArgs; private: virtual void onAppendUniformDecls(ShaderVisibility visibility, SkString* out) const = 0; friend class GrGLSLShaderBuilder; friend class GrGLSLVertexBuilder; friend class GrGLSLFragmentShaderBuilder; friend class GrGLSLGeometryBuilder; }; #endif