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 "GrNonAtomicRef.h" 13 #include "GrProcessor.h" 14 #include "GrProxyRef.h" 15 #include "GrShaderVar.h" 16 17 class GrCoordTransform; 18 19 /* 20 * The GrPrimitiveProcessor represents some kind of geometric primitive. This includes the shape 21 * of the primitive and the inherent color of the primitive. The GrPrimitiveProcessor is 22 * responsible for providing a color and coverage input into the Ganesh rendering pipeline. Through 23 * optimization, Ganesh may decide a different color, no color, and / or no coverage are required 24 * from the GrPrimitiveProcessor, so the GrPrimitiveProcessor must be able to support this 25 * functionality. 26 * 27 * There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the 28 * GrPrimitiveProcessor. These loops run on the CPU and to determine known properties of the final 29 * color and coverage inputs to the GrXferProcessor in order to perform optimizations that preserve 30 * correctness. The GrDrawOp seeds these loops with initial color and coverage, in its 31 * getProcessorAnalysisInputs implementation. These seed values are processed by the 32 * subsequent 33 * stages of the rendering pipeline and the output is then fed back into the GrDrawOp in 34 * the applyPipelineOptimizations call, where the op can use the information to inform decisions 35 * about GrPrimitiveProcessor creation. 36 */ 37 38 class GrGLSLPrimitiveProcessor; 39 40 /** 41 * GrPrimitiveProcessor defines an interface which all subclasses must implement. All 42 * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage 43 * pipelines, and they must provide some notion of equality 44 * 45 * TODO: This class does not really need to be ref counted. Instances should be allocated using 46 * GrOpFlushState's arena and destroyed when the arena is torn down. 47 */ 48 class GrPrimitiveProcessor : public GrProcessor, public GrNonAtomicRef<GrPrimitiveProcessor> { 49 public: 50 class TextureSampler; 51 52 /** Describes a vertex or instance attribute. */ 53 class Attribute { 54 public: 55 constexpr Attribute() = default; 56 constexpr Attribute(const char* name, 57 GrVertexAttribType cpuType, 58 GrSLType gpuType) 59 : fName(name), fCPUType(cpuType), fGPUType(gpuType) {} 60 constexpr Attribute(const Attribute&) = default; 61 62 Attribute& operator=(const Attribute&) = default; 63 64 constexpr bool isInitialized() const { return SkToBool(fName); } 65 66 constexpr const char* name() const { return fName; } 67 constexpr GrVertexAttribType cpuType() const { return fCPUType; } 68 constexpr GrSLType gpuType() const { return fGPUType; } 69 70 inline constexpr size_t size() const; 71 constexpr size_t sizeAlign4() const { return SkAlign4(this->size()); } 72 73 GrShaderVar asShaderVar() const { 74 return {fName, fGPUType, GrShaderVar::kIn_TypeModifier}; 75 } 76 77 private: 78 const char* fName = nullptr; 79 GrVertexAttribType fCPUType = kFloat_GrVertexAttribType; 80 GrSLType fGPUType = kFloat_GrSLType; 81 }; 82 83 class Iter { 84 public: 85 Iter() : fCurr(nullptr), fRemaining(0) {} 86 Iter(const Iter& iter) : fCurr(iter.fCurr), fRemaining(iter.fRemaining) {} 87 Iter& operator= (const Iter& iter) { 88 fCurr = iter.fCurr; 89 fRemaining = iter.fRemaining; 90 return *this; 91 } 92 Iter(const Attribute* attrs, int count) : fCurr(attrs), fRemaining(count) { 93 this->skipUninitialized(); 94 } 95 96 bool operator!=(const Iter& that) const { return fCurr != that.fCurr; } 97 const Attribute& operator*() const { return *fCurr; } 98 void operator++() { 99 if (fRemaining) { 100 fRemaining--; 101 fCurr++; 102 this->skipUninitialized(); 103 } 104 } 105 106 private: 107 void skipUninitialized() { 108 if (!fRemaining) { 109 fCurr = nullptr; 110 } else { 111 while (!fCurr->isInitialized()) { 112 ++fCurr; 113 } 114 } 115 } 116 117 const Attribute* fCurr; 118 int fRemaining; 119 }; 120 121 class AttributeSet { 122 public: 123 Iter begin() const { return Iter(fAttributes, fCount); } 124 Iter end() const { return Iter(); } 125 126 private: 127 friend class GrPrimitiveProcessor; 128 129 void init(const Attribute* attrs, int count) { 130 fAttributes = attrs; 131 fRawCount = count; 132 fCount = 0; 133 fStride = 0; 134 for (int i = 0; i < count; ++i) { 135 if (attrs[i].isInitialized()) { 136 fCount++; 137 fStride += attrs[i].sizeAlign4(); 138 } 139 } 140 } 141 142 const Attribute* fAttributes = nullptr; 143 int fRawCount = 0; 144 int fCount = 0; 145 size_t fStride = 0; 146 }; 147 148 GrPrimitiveProcessor(ClassID); 149 150 int numTextureSamplers() const { return fTextureSamplerCnt; } 151 const TextureSampler& textureSampler(int index) const; 152 int numVertexAttributes() const { return fVertexAttributes.fCount; } 153 const AttributeSet& vertexAttributes() const { return fVertexAttributes; } 154 int numInstanceAttributes() const { return fInstanceAttributes.fCount; } 155 const AttributeSet& instanceAttributes() const { return fInstanceAttributes; } 156 157 bool hasVertexAttributes() const { return SkToBool(fVertexAttributes.fCount); } 158 bool hasInstanceAttributes() const { return SkToBool(fInstanceAttributes.fCount); } 159 160 /** 161 * A common practice is to populate the the vertex/instance's memory using an implicit array of 162 * structs. In this case, it is best to assert that: 163 * stride == sizeof(struct) 164 */ 165 size_t vertexStride() const { return fVertexAttributes.fStride; } 166 size_t instanceStride() const { return fInstanceAttributes.fStride; } 167 168 // Only the GrGeometryProcessor subclass actually has a geo shader or vertex attributes, but 169 // we put these calls on the base class to prevent having to cast 170 virtual bool willUseGeoShader() const = 0; 171 172 /** 173 * Computes a transformKey from an array of coord transforms. Will only look at the first 174 * <numCoords> transforms in the array. 175 * 176 * TODO: A better name for this function would be "compute" instead of "get". 177 */ 178 uint32_t getTransformKey(const SkTArray<const GrCoordTransform*, true>& coords, 179 int numCoords) const; 180 181 /** 182 * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry 183 * processor's GL backend implementation. 184 * 185 * TODO: A better name for this function would be "compute" instead of "get". 186 */ 187 virtual void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0; 188 189 190 void getAttributeKey(GrProcessorKeyBuilder* b) const { 191 // Ensure that our CPU and GPU type fields fit together in a 32-bit value, and we never 192 // collide with the "uninitialized" value. 193 static_assert(kGrVertexAttribTypeCount < (1 << 8), ""); 194 static_assert(kGrSLTypeCount < (1 << 8), ""); 195 196 auto add_attributes = [=](const Attribute* attrs, int attrCount) { 197 for (int i = 0; i < attrCount; ++i) { 198 b->add32(attrs[i].isInitialized() ? (attrs[i].cpuType() << 16) | attrs[i].gpuType() 199 : ~0); 200 } 201 }; 202 add_attributes(fVertexAttributes.fAttributes, fVertexAttributes.fRawCount); 203 add_attributes(fInstanceAttributes.fAttributes, fInstanceAttributes.fRawCount); 204 } 205 206 /** Returns a new instance of the appropriate *GL* implementation class 207 for the given GrProcessor; caller is responsible for deleting 208 the object. */ 209 virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const = 0; 210 211 virtual bool isPathRendering() const { return false; } 212 213 protected: 214 void setVertexAttributes(const Attribute* attrs, int attrCount) { 215 fVertexAttributes.init(attrs, attrCount); 216 } 217 void setInstanceAttributes(const Attribute* attrs, int attrCount) { 218 SkASSERT(attrCount >= 0); 219 fInstanceAttributes.init(attrs, attrCount); 220 } 221 void setTextureSamplerCnt(int cnt) { 222 SkASSERT(cnt >= 0); 223 fTextureSamplerCnt = cnt; 224 } 225 226 /** 227 * Helper for implementing onTextureSampler(). E.g.: 228 * return IthTexureSampler(i, fMyFirstSampler, fMySecondSampler, fMyThirdSampler); 229 */ 230 template <typename... Args> 231 static const TextureSampler& IthTextureSampler(int i, const TextureSampler& samp0, 232 const Args&... samps) { 233 return (0 == i) ? samp0 : IthTextureSampler(i - 1, samps...); 234 } 235 inline static const TextureSampler& IthTextureSampler(int i); 236 237 private: 238 virtual const TextureSampler& onTextureSampler(int) const { return IthTextureSampler(0); } 239 240 AttributeSet fVertexAttributes; 241 AttributeSet fInstanceAttributes; 242 243 int fTextureSamplerCnt = 0; 244 typedef GrProcessor INHERITED; 245 }; 246 247 ////////////////////////////////////////////////////////////////////////////// 248 249 /** 250 * Used to represent a texture that is required by a GrPrimitiveProcessor. It holds a GrTextureProxy 251 * along with an associated GrSamplerState. TextureSamplers don't perform any coord manipulation to 252 * account for texture origin. 253 */ 254 class GrPrimitiveProcessor::TextureSampler { 255 public: 256 TextureSampler() = default; 257 258 TextureSampler(GrTextureType, GrPixelConfig, const GrSamplerState&, uint32_t extraSamplerKey); 259 260 explicit TextureSampler(GrTextureType, GrPixelConfig, 261 GrSamplerState::Filter = GrSamplerState::Filter::kNearest, 262 GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp); 263 264 TextureSampler(const TextureSampler&) = delete; 265 TextureSampler& operator=(const TextureSampler&) = delete; 266 267 void reset(GrTextureType, GrPixelConfig, const GrSamplerState&, uint32_t extraSamplerKey = 0); 268 void reset(GrTextureType, GrPixelConfig, 269 GrSamplerState::Filter, 270 GrSamplerState::WrapMode wrapXAndY); 271 272 GrTextureType textureType() const { return fTextureType; } 273 GrPixelConfig config() const { return fConfig; } 274 275 const GrSamplerState& samplerState() const { return fSamplerState; } 276 277 uint32_t extraSamplerKey() const { return fExtraSamplerKey; } 278 279 bool isInitialized() const { return fConfig != kUnknown_GrPixelConfig; } 280 281 private: 282 GrSamplerState fSamplerState; 283 GrTextureType fTextureType = GrTextureType::k2D; 284 GrPixelConfig fConfig = kUnknown_GrPixelConfig; 285 uint32_t fExtraSamplerKey = 0; 286 }; 287 288 const GrPrimitiveProcessor::TextureSampler& GrPrimitiveProcessor::IthTextureSampler(int i) { 289 SK_ABORT("Illegal texture sampler index"); 290 static const TextureSampler kBogus; 291 return kBogus; 292 } 293 294 ////////////////////////////////////////////////////////////////////////////// 295 296 /** 297 * Returns the size of the attrib type in bytes. 298 * This was moved from include/private/GrTypesPriv.h in service of Skia dependents that build 299 * with C++11. 300 */ 301 static constexpr inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) { 302 switch (type) { 303 case kFloat_GrVertexAttribType: 304 return sizeof(float); 305 case kFloat2_GrVertexAttribType: 306 return 2 * sizeof(float); 307 case kFloat3_GrVertexAttribType: 308 return 3 * sizeof(float); 309 case kFloat4_GrVertexAttribType: 310 return 4 * sizeof(float); 311 case kHalf_GrVertexAttribType: 312 return sizeof(uint16_t); 313 case kHalf2_GrVertexAttribType: 314 return 2 * sizeof(uint16_t); 315 case kHalf3_GrVertexAttribType: 316 return 3 * sizeof(uint16_t); 317 case kHalf4_GrVertexAttribType: 318 return 4 * sizeof(uint16_t); 319 case kInt2_GrVertexAttribType: 320 return 2 * sizeof(int32_t); 321 case kInt3_GrVertexAttribType: 322 return 3 * sizeof(int32_t); 323 case kInt4_GrVertexAttribType: 324 return 4 * sizeof(int32_t); 325 case kByte_GrVertexAttribType: 326 return 1 * sizeof(char); 327 case kByte2_GrVertexAttribType: 328 return 2 * sizeof(char); 329 case kByte3_GrVertexAttribType: 330 return 3 * sizeof(char); 331 case kByte4_GrVertexAttribType: 332 return 4 * sizeof(char); 333 case kUByte_GrVertexAttribType: 334 return 1 * sizeof(char); 335 case kUByte2_GrVertexAttribType: 336 return 2 * sizeof(char); 337 case kUByte3_GrVertexAttribType: 338 return 3 * sizeof(char); 339 case kUByte4_GrVertexAttribType: 340 return 4 * sizeof(char); 341 case kUByte_norm_GrVertexAttribType: 342 return 1 * sizeof(char); 343 case kUByte4_norm_GrVertexAttribType: 344 return 4 * sizeof(char); 345 case kShort2_GrVertexAttribType: 346 return 2 * sizeof(int16_t); 347 case kShort4_GrVertexAttribType: 348 return 4 * sizeof(int16_t); 349 case kUShort2_GrVertexAttribType: // fall through 350 case kUShort2_norm_GrVertexAttribType: 351 return 2 * sizeof(uint16_t); 352 case kInt_GrVertexAttribType: 353 return sizeof(int32_t); 354 case kUint_GrVertexAttribType: 355 return sizeof(uint32_t); 356 } 357 // GCC fails because SK_ABORT evaluates to non constexpr. clang and cl.exe think this is 358 // unreachable and don't complain. 359 #if defined(__clang__) || !defined(__GNUC__) 360 SK_ABORT("Unsupported type conversion"); 361 #endif 362 return 0; 363 } 364 365 constexpr size_t GrPrimitiveProcessor::Attribute::size() const { 366 return GrVertexAttribTypeSize(fCPUType); 367 } 368 369 #endif 370