1 /* 2 * Copyright 2014 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 GrProgramDesc_DEFINED 9 #define GrProgramDesc_DEFINED 10 11 #include "GrColor.h" 12 #include "GrTypesPriv.h" 13 #include "SkOpts.h" 14 #include "SkTArray.h" 15 #include "SkTo.h" 16 #include "glsl/GrGLSLFragmentShaderBuilder.h" 17 18 class GrShaderCaps; 19 class GrPipeline; 20 class GrPrimitiveProcessor; 21 22 /** This class describes a program to generate. It also serves as a program cache key */ 23 class GrProgramDesc { 24 public: 25 // Creates an uninitialized key that must be populated by GrGpu::buildProgramDesc() GrProgramDesc()26 GrProgramDesc() {} 27 28 /** 29 * Builds a program descriptor. Before the descriptor can be used, the client must call finalize 30 * on the returned GrProgramDesc. 31 * 32 * @param GrPrimitiveProcessor The geometry 33 * @param hasPointSize Controls whether the shader will output a point size. 34 * @param GrPipeline The optimized drawstate. The descriptor will represent a program 35 * which this optstate can use to draw with. The optstate contains 36 * general draw information, as well as the specific color, geometry, 37 * and coverage stages which will be used to generate the GL Program for 38 * this optstate. 39 * @param GrGpu Ptr to the GrGpu object the program will be used with. 40 * @param GrProgramDesc The built and finalized descriptor 41 **/ 42 static bool Build(GrProgramDesc*, 43 GrPixelConfig, 44 const GrPrimitiveProcessor&, 45 bool hasPointSize, 46 const GrPipeline&, 47 GrGpu*); 48 49 // Returns this as a uint32_t array to be used as a key in the program cache. asKey()50 const uint32_t* asKey() const { 51 return reinterpret_cast<const uint32_t*>(fKey.begin()); 52 } 53 54 // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. keyLength()55 uint32_t keyLength() const { 56 SkASSERT(0 == (fKey.count() % 4)); 57 return fKey.count(); 58 } 59 60 GrProgramDesc& operator= (const GrProgramDesc& other) { 61 uint32_t keyLength = other.keyLength(); 62 fKey.reset(SkToInt(keyLength)); 63 memcpy(fKey.begin(), other.fKey.begin(), keyLength); 64 return *this; 65 } 66 67 bool operator== (const GrProgramDesc& that) const { 68 if (this->keyLength() != that.keyLength()) { 69 return false; 70 } 71 72 SkASSERT(SkIsAlign4(this->keyLength())); 73 int l = this->keyLength() >> 2; 74 const uint32_t* aKey = this->asKey(); 75 const uint32_t* bKey = that.asKey(); 76 for (int i = 0; i < l; ++i) { 77 if (aKey[i] != bKey[i]) { 78 return false; 79 } 80 } 81 return true; 82 } 83 84 bool operator!= (const GrProgramDesc& other) const { 85 return !(*this == other); 86 } 87 setSurfaceOriginKey(int key)88 void setSurfaceOriginKey(int key) { 89 KeyHeader* header = this->atOffset<KeyHeader, kHeaderOffset>(); 90 header->fSurfaceOriginKey = key; 91 } 92 93 struct KeyHeader { 94 // Set to uniquely idenitify any swizzling of the shader's output color(s). 95 uint8_t fOutputSwizzle; 96 uint8_t fColorFragmentProcessorCnt; // Can be packed into 4 bits if required. 97 uint8_t fCoverageFragmentProcessorCnt; 98 // Set to uniquely identify the rt's origin, or 0 if the shader does not require this info. 99 uint8_t fSurfaceOriginKey : 2; 100 bool fSnapVerticesToPixelCenters : 1; 101 bool fHasPointSize : 1; 102 uint8_t fPad : 4; 103 }; 104 GR_STATIC_ASSERT(sizeof(KeyHeader) == 4); 105 106 // This should really only be used internally, base classes should return their own headers header()107 const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); } 108 109 protected: atOffset()110 template<typename T, size_t OFFSET> T* atOffset() { 111 return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET); 112 } 113 atOffset()114 template<typename T, size_t OFFSET> const T* atOffset() const { 115 return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET); 116 } 117 118 // The key, stored in fKey, is composed of two parts: 119 // 1. Header struct defined above. 120 // 2. A Backend specific payload which includes the per-processor keys. 121 enum KeyOffsets { 122 kHeaderOffset = 0, 123 kHeaderSize = SkAlign4(sizeof(KeyHeader)), 124 // Part 4. 125 // This is the offset into the backenend specific part of the key, which includes 126 // per-processor keys. 127 kProcessorKeysOffset = kHeaderOffset + kHeaderSize, 128 }; 129 130 enum { 131 kMaxPreallocProcessors = 8, 132 kIntsPerProcessor = 4, // This is an overestimate of the average effect key size. 133 kPreAllocSize = kHeaderOffset + kHeaderSize + 134 kMaxPreallocProcessors * sizeof(uint32_t) * kIntsPerProcessor, 135 }; 136 key()137 SkSTArray<kPreAllocSize, uint8_t, true>& key() { return fKey; } key()138 const SkSTArray<kPreAllocSize, uint8_t, true>& key() const { return fKey; } 139 140 private: 141 SkSTArray<kPreAllocSize, uint8_t, true> fKey; 142 }; 143 144 #endif 145