1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrPrimitiveProcessor_DEFINED 9 #define GrPrimitiveProcessor_DEFINED 10 11 #include "GrColor.h" 12 #include "GrProcessor.h" 13 #include "GrShaderVar.h" 14 15 /* 16 * The GrPrimitiveProcessor represents some kind of geometric primitive. This includes the shape 17 * of the primitive and the inherent color of the primitive. The GrPrimitiveProcessor is 18 * responsible for providing a color and coverage input into the Ganesh rendering pipeline. Through 19 * optimization, Ganesh may decide a different color, no color, and / or no coverage are required 20 * from the GrPrimitiveProcessor, so the GrPrimitiveProcessor must be able to support this 21 * functionality. 22 * 23 * There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the 24 * GrPrimitiveProcessor. These loops run on the CPU and to determine known properties of the final 25 * color and coverage inputs to the GrXferProcessor in order to perform optimizations that preserve 26 * correctness. The GrDrawOp seeds these loops with initial color and coverage, in its 27 * getProcessorAnalysisInputs implementation. These seed values are processed by the 28 * subsequent 29 * stages of the rendering pipeline and the output is then fed back into the GrDrawOp in 30 * the applyPipelineOptimizations call, where the op can use the information to inform decisions 31 * about GrPrimitiveProcessor creation. 32 */ 33 34 class GrGLSLPrimitiveProcessor; 35 36 /* 37 * GrPrimitiveProcessor defines an interface which all subclasses must implement. All 38 * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage 39 * pipelines, and they must provide some notion of equality 40 */ 41 class GrPrimitiveProcessor : public GrResourceIOProcessor, public GrProgramElement { 42 public: 43 struct Attribute { 44 enum class InputRate : bool { 45 kPerVertex, 46 kPerInstance 47 }; asShaderVarAttribute48 GrShaderVar asShaderVar() const { 49 return GrShaderVar(fName, GrVertexAttribTypeToSLType(fType), 50 GrShaderVar::kIn_TypeModifier); 51 } isInitializedAttribute52 bool isInitialized() const { return SkToBool(fName); } 53 Attribute() = default; AttributeAttribute54 Attribute(const char* name, GrVertexAttribType type, int offset, InputRate rate) 55 : fName(name), fType(type), fOffsetInRecord(offset), fInputRate(rate) {} 56 const char* fName = nullptr; 57 GrVertexAttribType fType; 58 int fOffsetInRecord; 59 InputRate fInputRate; 60 }; 61 GrPrimitiveProcessor(ClassID classID)62 GrPrimitiveProcessor(ClassID classID) 63 : GrResourceIOProcessor(classID) {} 64 numAttribs()65 int numAttribs() const { return fAttribs.count(); } getAttrib(int index)66 const Attribute& getAttrib(int index) const { return fAttribs[index]; } 67 hasVertexAttribs()68 bool hasVertexAttribs() const { return SkToBool(fVertexStride); } hasInstanceAttribs()69 bool hasInstanceAttribs() const { return SkToBool(fInstanceStride); } 70 71 /** 72 * These return the strides of the vertex and instance buffers. Attributes are expected to be 73 * laid out interleaved in their corresponding buffer (vertex or instance). fOffsetInRecord 74 * indicates an attribute's location in bytes relative to the first attribute. (These are padded 75 * to the nearest 4 bytes for performance reasons.) 76 * 77 * A common practice is to populate the buffer's memory using an implicit array of structs. In 78 * this case, it is best to assert: 79 * 80 * stride == sizeof(struct) and 81 * offsetof(struct, field[i]) == attrib[i].fOffsetInRecord 82 * 83 * NOTE: for instanced draws the vertex buffer has a single record that each instance reuses. 84 */ getVertexStride()85 int getVertexStride() const { return fVertexStride; } getInstanceStride()86 int getInstanceStride() const { return fInstanceStride; } 87 88 // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but 89 // we put these calls on the base class to prevent having to cast 90 virtual bool willUseGeoShader() const = 0; 91 willUsePrimitiveRestart()92 bool willUsePrimitiveRestart() const { return fWillUsePrimitiveRestart; } 93 94 /** 95 * Computes a transformKey from an array of coord transforms. Will only look at the first 96 * <numCoords> transforms in the array. 97 * 98 * TODO: A better name for this function would be "compute" instead of "get". 99 */ 100 uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords, 101 int numCoords) const; 102 103 /** 104 * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry 105 * processor's GL backend implementation. 106 * 107 * TODO: A better name for this function would be "compute" instead of "get". 108 */ 109 virtual void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0; 110 111 112 /** Returns a new instance of the appropriate *GL* implementation class 113 for the given GrProcessor; caller is responsible for deleting 114 the object. */ 115 virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const = 0; 116 isPathRendering()117 virtual bool isPathRendering() const { return false; } 118 119 /** 120 * If non-null, overrides the dest color returned by GrGLSLFragmentShaderBuilder::dstColor(). 121 */ getDestColorOverride()122 virtual const char* getDestColorOverride() const { return nullptr; } 123 getSampleShading()124 virtual float getSampleShading() const { 125 return 0.0; 126 } 127 128 protected: 129 /** 130 * Subclasses call these from their constructor to register vertex and instance attributes. 131 */ addVertexAttrib(const char * name,GrVertexAttribType type)132 const Attribute& addVertexAttrib(const char* name, GrVertexAttribType type) { 133 fAttribs.push_back() = {name, type, fVertexStride, Attribute::InputRate::kPerVertex}; 134 fVertexStride += static_cast<int>(SkAlign4(GrVertexAttribTypeSize(type))); 135 return fAttribs.back(); 136 } addInstanceAttrib(const char * name,GrVertexAttribType type)137 const Attribute& addInstanceAttrib(const char* name, GrVertexAttribType type) { 138 fAttribs.push_back() = {name, type, fInstanceStride, Attribute::InputRate::kPerInstance}; 139 fInstanceStride += static_cast<int>(SkAlign4(GrVertexAttribTypeSize(type))); 140 return fAttribs.back(); 141 } 142 setWillUsePrimitiveRestart()143 void setWillUsePrimitiveRestart() { fWillUsePrimitiveRestart = true; } 144 145 private: addPendingIOs()146 void addPendingIOs() const override { GrResourceIOProcessor::addPendingIOs(); } removeRefs()147 void removeRefs() const override { GrResourceIOProcessor::removeRefs(); } pendingIOComplete()148 void pendingIOComplete() const override { GrResourceIOProcessor::pendingIOComplete(); } notifyRefCntIsZero()149 void notifyRefCntIsZero() const final {} 150 virtual bool hasExplicitLocalCoords() const = 0; 151 152 SkSTArray<8, Attribute> fAttribs; 153 int fVertexStride = 0; 154 int fInstanceStride = 0; 155 bool fWillUsePrimitiveRestart = false; 156 157 typedef GrProcessor INHERITED; 158 }; 159 160 #endif 161