blob: 4c76b68c2d55e7f67a82915ca3ea22e0b7356ac6 [file] [log] [blame]
bsalomon744998e2014-08-28 09:54:34 -07001
2/*
3 * Copyright 2014 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#ifndef GrResourceKey_DEFINED
10#define GrResourceKey_DEFINED
11
12#include "GrTypes.h"
bsalomon7775c852014-12-30 12:50:52 -080013#include "SkTemplates.h"
bsalomon744998e2014-08-28 09:54:34 -070014
bsalomon24db3b12015-01-23 04:24:04 -080015uint32_t GrResourceKeyHash(const uint32_t* data, size_t size);
bsalomon7775c852014-12-30 12:50:52 -080016
bsalomon24db3b12015-01-23 04:24:04 -080017class GrResourceKey {
18public:
19 uint32_t hash() const {
20 this->validate();
21 return fKey[kHash_MetaDataIdx];
22 }
23
24 size_t size() const {
25 this->validate();
bsalomon3bd12ef2015-01-28 11:39:48 -080026 SkASSERT(this->isValid());
bsalomon24db3b12015-01-23 04:24:04 -080027 return this->internalSize();
28 }
29
bsalomon24db3b12015-01-23 04:24:04 -080030protected:
31 static const uint32_t kInvalidDomain = 0;
32
33 GrResourceKey() { this->reset(); }
bsalomon7775c852014-12-30 12:50:52 -080034
35 /** Reset to an invalid key. */
36 void reset() {
bsalomon24db3b12015-01-23 04:24:04 -080037 GR_STATIC_ASSERT((uint16_t)kInvalidDomain == kInvalidDomain);
bsalomon7775c852014-12-30 12:50:52 -080038 fKey.reset(kMetaDataCnt);
39 fKey[kHash_MetaDataIdx] = 0;
bsalomon24db3b12015-01-23 04:24:04 -080040 fKey[kDomainAndSize_MetaDataIdx] = kInvalidDomain;
bsalomon7775c852014-12-30 12:50:52 -080041 }
42
bsalomon24db3b12015-01-23 04:24:04 -080043 bool operator==(const GrResourceKey& that) const {
bsalomone167f962015-01-27 09:56:04 -080044 SkASSERT(this->isValid() && that.isValid());
bsalomon24db3b12015-01-23 04:24:04 -080045 return 0 == memcmp(fKey.get(), that.fKey.get(), this->size());
46 }
bsalomon7775c852014-12-30 12:50:52 -080047
bsalomon24db3b12015-01-23 04:24:04 -080048 GrResourceKey& operator=(const GrResourceKey& that) {
bsalomon4dffede2015-01-23 07:17:55 -080049 if (this != &that) {
50 size_t bytes = that.size();
51 SkASSERT(SkIsAlign4(bytes));
52 fKey.reset(SkToInt(bytes / sizeof(uint32_t)));
53 memcpy(fKey.get(), that.fKey.get(), bytes);
54 }
bsalomon7775c852014-12-30 12:50:52 -080055 return *this;
56 }
57
bsalomon24db3b12015-01-23 04:24:04 -080058 bool isValid() const { return kInvalidDomain != this->domain(); }
bsalomon7775c852014-12-30 12:50:52 -080059
bsalomon24db3b12015-01-23 04:24:04 -080060 uint32_t domain() const { return fKey[kDomainAndSize_MetaDataIdx] & 0xffff; }
61
bsalomon3bd12ef2015-01-28 11:39:48 -080062 /** size of the key data, excluding meta-data (hash, domain, etc). */
63 size_t dataSize() const { return this->size() - 4 * kMetaDataCnt; }
64
65 /** ptr to the key data, excluding meta-data (hash, domain, etc). */
66 const uint32_t* data() const {
67 this->validate();
68 return &fKey[kMetaDataCnt];
69 }
70
bsalomon24db3b12015-01-23 04:24:04 -080071 /** Used to initialize a key. */
bsalomon7775c852014-12-30 12:50:52 -080072 class Builder {
73 public:
bsalomon24db3b12015-01-23 04:24:04 -080074 Builder(GrResourceKey* key, uint32_t domain, int data32Count) : fKey(key) {
bsalomon7775c852014-12-30 12:50:52 -080075 SkASSERT(data32Count >= 0);
bsalomon24db3b12015-01-23 04:24:04 -080076 SkASSERT(domain != kInvalidDomain);
bsalomon7775c852014-12-30 12:50:52 -080077 key->fKey.reset(kMetaDataCnt + data32Count);
bsalomon7775c852014-12-30 12:50:52 -080078 int size = (data32Count + kMetaDataCnt) * sizeof(uint32_t);
bsalomon24db3b12015-01-23 04:24:04 -080079 SkASSERT(SkToU16(size) == size);
80 SkASSERT(SkToU16(domain) == domain);
81 key->fKey[kDomainAndSize_MetaDataIdx] = domain | (size << 16);
bsalomon7775c852014-12-30 12:50:52 -080082 }
83
84 ~Builder() { this->finish(); }
85
bsalomon24db3b12015-01-23 04:24:04 -080086 void finish() {
87 if (NULL == fKey) {
88 return;
89 }
90 GR_STATIC_ASSERT(0 == kHash_MetaDataIdx);
91 uint32_t* hash = &fKey->fKey[kHash_MetaDataIdx];
92 *hash = GrResourceKeyHash(hash + 1, fKey->internalSize() - sizeof(uint32_t));
93 fKey->validate();
94 fKey = NULL;
95 }
bsalomon7775c852014-12-30 12:50:52 -080096
97 uint32_t& operator[](int dataIdx) {
98 SkASSERT(fKey);
bsalomon24db3b12015-01-23 04:24:04 -080099 SkDEBUGCODE(size_t dataCount = fKey->internalSize() / sizeof(uint32_t) - kMetaDataCnt;)
bsalomon7775c852014-12-30 12:50:52 -0800100 SkASSERT(SkToU32(dataIdx) < dataCount);
101 return fKey->fKey[kMetaDataCnt + dataIdx];
102 }
103
104 private:
bsalomon24db3b12015-01-23 04:24:04 -0800105 GrResourceKey* fKey;
bsalomon7775c852014-12-30 12:50:52 -0800106 };
107
108private:
109 enum MetaDataIdx {
110 kHash_MetaDataIdx,
bsalomon24db3b12015-01-23 04:24:04 -0800111 // The key domain and size are packed into a single uint32_t.
112 kDomainAndSize_MetaDataIdx,
bsalomon7775c852014-12-30 12:50:52 -0800113
bsalomon24db3b12015-01-23 04:24:04 -0800114 kLastMetaDataIdx = kDomainAndSize_MetaDataIdx
bsalomon7775c852014-12-30 12:50:52 -0800115 };
bsalomon7775c852014-12-30 12:50:52 -0800116 static const uint32_t kMetaDataCnt = kLastMetaDataIdx + 1;
117
bsalomon3bd12ef2015-01-28 11:39:48 -0800118 size_t internalSize() const {
119 return fKey[kDomainAndSize_MetaDataIdx] >> 16;
120 }
121
122 void validate() const {
123 SkASSERT(fKey[kHash_MetaDataIdx] ==
124 GrResourceKeyHash(&fKey[kHash_MetaDataIdx] + 1,
125 this->internalSize() - sizeof(uint32_t)));
126 SkASSERT(SkIsAlign4(this->internalSize()));
127 }
128
bsalomon1c60dfe2015-01-21 09:32:40 -0800129 friend class TestResource; // For unit test to access kMetaDataCnt.
130
bsalomon24db3b12015-01-23 04:24:04 -0800131 // bmp textures require 4 uint32_t values.
132 SkAutoSTArray<kMetaDataCnt + 4, uint32_t> fKey;
bsalomon7775c852014-12-30 12:50:52 -0800133};
134
bsalomon24db3b12015-01-23 04:24:04 -0800135/**
136 * A key used for scratch resources. The key consists of a resource type (subclass) identifier, a
137 * hash, a data length, and type-specific data. A Builder object is used to initialize the
138 * key contents. The contents must be initialized before the key can be used.
139 */
140class GrScratchKey : public GrResourceKey {
bsalomon744998e2014-08-28 09:54:34 -0700141private:
bsalomon24db3b12015-01-23 04:24:04 -0800142 typedef GrResourceKey INHERITED;
bsalomon744998e2014-08-28 09:54:34 -0700143
bsalomon24db3b12015-01-23 04:24:04 -0800144public:
145 /** Uniquely identifies the type of resource that is cached as scratch. */
146 typedef uint32_t ResourceType;
bsalomon744998e2014-08-28 09:54:34 -0700147
bsalomon24db3b12015-01-23 04:24:04 -0800148 /** Generate a unique ResourceType. */
149 static ResourceType GenerateResourceType();
150
151 /** Creates an invalid scratch key. It must be initialized using a Builder object before use. */
152 GrScratchKey() {}
153
154 GrScratchKey(const GrScratchKey& that) { *this = that; }
155
156 /** reset() returns the key to the invalid state. */
157 using INHERITED::reset;
158
159 using INHERITED::isValid;
160
161 ResourceType resourceType() const { return this->domain(); }
162
163 GrScratchKey& operator=(const GrScratchKey& that) {
164 this->INHERITED::operator=(that);
165 return *this;
bsalomon744998e2014-08-28 09:54:34 -0700166 }
bsalomon24db3b12015-01-23 04:24:04 -0800167
168 bool operator==(const GrScratchKey& that) const {
169 return this->INHERITED::operator==(that);
170 }
171 bool operator!=(const GrScratchKey& that) const { return !(*this == that); }
172
173 class Builder : public INHERITED::Builder {
174 public:
175 Builder(GrScratchKey* key, ResourceType type, int data32Count)
176 : INHERITED::Builder(key, type, data32Count) {}
177 };
178};
179
180/**
181 * A key used to cache resources based on their content. The key consists of a domain type (use
182 * case for the cache), a hash, a data length, and domain-specific data. A Builder object is used to
183 * initialize the key contents. The contents must be initialized before the key can be used.
184 */
185class GrContentKey : public GrResourceKey {
186private:
187 typedef GrResourceKey INHERITED;
188
189public:
190 typedef uint32_t Domain;
191 /** Generate a unique Domain of content keys. */
192 static Domain GenerateDomain();
193
194 /** Creates an invalid content key. It must be initialized using a Builder object before use. */
195 GrContentKey() {}
196
197 GrContentKey(const GrContentKey& that) { *this = that; }
198
199 /** reset() returns the key to the invalid state. */
200 using INHERITED::reset;
201
202 using INHERITED::isValid;
203
204 GrContentKey& operator=(const GrContentKey& that) {
205 this->INHERITED::operator=(that);
206 return *this;
207 }
208
209 bool operator==(const GrContentKey& that) const {
210 return this->INHERITED::operator==(that);
211 }
212 bool operator!=(const GrContentKey& that) const { return !(*this == that); }
213
214 class Builder : public INHERITED::Builder {
215 public:
216 Builder(GrContentKey* key, Domain domain, int data32Count)
217 : INHERITED::Builder(key, domain, data32Count) {}
218
219 /** Used to build a key that wraps another key and adds additional data. */
220 Builder(GrContentKey* key, const GrContentKey& innerKey, Domain domain,
221 int extraData32Cnt)
bsalomon3bd12ef2015-01-28 11:39:48 -0800222 : INHERITED::Builder(key, domain, Data32CntForInnerKey(innerKey) + extraData32Cnt) {
bsalomon24db3b12015-01-23 04:24:04 -0800223 // add the inner key to the end of the key so that op[] can be indexed normally.
bsalomon3bd12ef2015-01-28 11:39:48 -0800224 uint32_t* innerKeyData = &this->operator[](extraData32Cnt);
225 const uint32_t* srcData = innerKey.data();
226 (*innerKeyData++) = innerKey.domain();
227 memcpy(innerKeyData, srcData, innerKey.dataSize());
228 }
229
230 private:
231 static int Data32CntForInnerKey(const GrContentKey& innerKey) {
232 // key data + domain
233 return SkToInt((innerKey.dataSize() >> 2) + 1);
bsalomon24db3b12015-01-23 04:24:04 -0800234 }
235 };
bsalomon744998e2014-08-28 09:54:34 -0700236};
237
238#endif