• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkChecksum.h"
14 
15 /** This class describes a program to generate. It also serves as a program cache key. Very little
16     of this is GL-specific. The GL-specific parts could be factored out into a subclass. */
17 class GrProgramDesc {
18 public:
19     // Creates an uninitialized key that must be populated by GrGpu::buildProgramDesc()
GrProgramDesc()20     GrProgramDesc() {}
21 
22     // Returns this as a uint32_t array to be used as a key in the program cache.
asKey()23     const uint32_t* asKey() const {
24         return reinterpret_cast<const uint32_t*>(fKey.begin());
25     }
26 
27     // Gets the number of bytes in asKey(). It will be a 4-byte aligned value. When comparing two
28     // keys the size of either key can be used with memcmp() since the lengths themselves begin the
29     // keys and thus the memcmp will exit early if the keys are of different lengths.
keyLength()30     uint32_t keyLength() const { return *this->atOffset<uint32_t, kLengthOffset>(); }
31 
32     // Gets the a checksum of the key. Can be used as a hash value for a fast lookup in a cache.
getChecksum()33     uint32_t getChecksum() const { return *this->atOffset<uint32_t, kChecksumOffset>(); }
34 
35     GrProgramDesc& operator= (const GrProgramDesc& other) {
36         uint32_t keyLength = other.keyLength();
37         fKey.reset(SkToInt(keyLength));
38         memcpy(fKey.begin(), other.fKey.begin(), keyLength);
39         return *this;
40     }
41 
42     bool operator== (const GrProgramDesc& other) const {
43         // The length is masked as a hint to the compiler that the address will be 4 byte aligned.
44         return 0 == memcmp(this->asKey(), other.asKey(), this->keyLength() & ~0x3);
45     }
46 
47     bool operator!= (const GrProgramDesc& other) const {
48         return !(*this == other);
49     }
50 
Less(const GrProgramDesc & a,const GrProgramDesc & b)51     static bool Less(const GrProgramDesc& a, const GrProgramDesc& b) {
52         return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0;
53     }
54 
55     struct KeyHeader {
56         uint8_t                     fFragPosKey;   // set by GrGLShaderBuilder if there are
57                                                    // effects that read the fragment position.
58                                                    // Otherwise, 0.
59         uint8_t                     fSnapVerticesToPixelCenters;
60         int8_t                      fColorEffectCnt;
61         int8_t                      fCoverageEffectCnt;
62     };
63     GR_STATIC_ASSERT(sizeof(KeyHeader) == 4);
64 
numColorEffects()65     int numColorEffects() const {
66         return this->header().fColorEffectCnt;
67     }
68 
numCoverageEffects()69     int numCoverageEffects() const {
70         return this->header().fCoverageEffectCnt;
71     }
72 
numTotalEffects()73     int numTotalEffects() const { return this->numColorEffects() + this->numCoverageEffects(); }
74 
75     // This should really only be used internally, base classes should return their own headers
header()76     const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
77 
78 protected:
atOffset()79     template<typename T, size_t OFFSET> T* atOffset() {
80         return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
81     }
82 
atOffset()83     template<typename T, size_t OFFSET> const T* atOffset() const {
84         return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
85     }
86 
finalize()87     void finalize() {
88         int keyLength = fKey.count();
89         SkASSERT(0 == (keyLength % 4));
90         *(this->atOffset<uint32_t, GrProgramDesc::kLengthOffset>()) = SkToU32(keyLength);
91 
92         uint32_t* checksum = this->atOffset<uint32_t, GrProgramDesc::kChecksumOffset>();
93         *checksum = 0;
94         *checksum = SkChecksum::Compute(reinterpret_cast<uint32_t*>(fKey.begin()), keyLength);
95     }
96 
97     // The key, stored in fKey, is composed of four parts:
98     // 1. uint32_t for total key length.
99     // 2. uint32_t for a checksum.
100     // 3. Header struct defined above.  Also room for extensions to the header
101     // 4. A Backend specific payload.  Room is preallocated for this
102     enum KeyOffsets {
103         // Part 1.
104         kLengthOffset = 0,
105         // Part 2.
106         kChecksumOffset = kLengthOffset + sizeof(uint32_t),
107         // Part 3.
108         kHeaderOffset = kChecksumOffset + sizeof(uint32_t),
109         kHeaderSize = SkAlign4(2 * sizeof(KeyHeader)),
110     };
111 
112     enum {
113         kMaxPreallocProcessors = 8,
114         kIntsPerProcessor      = 4,    // This is an overestimate of the average effect key size.
115         kPreAllocSize = kHeaderOffset + kHeaderSize +
116                         kMaxPreallocProcessors * sizeof(uint32_t) * kIntsPerProcessor,
117     };
118 
key()119     SkSTArray<kPreAllocSize, uint8_t, true>& key() { return fKey; }
key()120     const SkSTArray<kPreAllocSize, uint8_t, true>& key() const { return fKey; }
121 
122 private:
123     SkSTArray<kPreAllocSize, uint8_t, true> fKey;
124 };
125 
126 #endif
127