Index: include/gpu/GrResourceKey.h |
diff --git a/include/gpu/GrResourceKey.h b/include/gpu/GrResourceKey.h |
index 9922c8f5d07249f72b9371088a8a4613c2162e63..9cf955be9817f39b4abceda4aaf5b2c8dd9cb824 100644 |
--- a/include/gpu/GrResourceKey.h |
+++ b/include/gpu/GrResourceKey.h |
@@ -13,149 +13,212 @@ |
#include "SkTemplates.h" |
#include "GrBinHashKey.h" |
-/** |
- * A key used for scratch resources. The key consists of a resource type (subclass) identifier, a |
- * hash, a data length, and type-specific data. A Builder object is used to initialize the |
- * key contents. The contents must be initialized before the key can be used. |
- */ |
-class GrScratchKey { |
+uint32_t GrResourceKeyHash(const uint32_t* data, size_t size); |
+ |
+class GrResourceKey { |
public: |
- /** Uniquely identifies the type of resource that is cached as scratch. */ |
- typedef uint32_t ResourceType; |
- /** Generate a unique ResourceType. */ |
- static ResourceType GenerateResourceType(); |
+ uint32_t hash() const { |
+ this->validate(); |
+ return fKey[kHash_MetaDataIdx]; |
+ } |
- GrScratchKey() { this->reset(); } |
- GrScratchKey(const GrScratchKey& that) { *this = that; } |
+ size_t size() const { |
+ this->validate(); |
+ return this->internalSize(); |
+ } |
+ |
+ const uint32_t* data() const { |
+ this->validate(); |
+ return &fKey[kMetaDataCnt]; |
+ } |
+ |
+protected: |
+ static const uint32_t kInvalidDomain = 0; |
+ |
+ GrResourceKey() { this->reset(); } |
/** Reset to an invalid key. */ |
void reset() { |
+ GR_STATIC_ASSERT((uint16_t)kInvalidDomain == kInvalidDomain); |
fKey.reset(kMetaDataCnt); |
fKey[kHash_MetaDataIdx] = 0; |
- fKey[kTypeAndSize_MetaDataIdx] = kInvalidResourceType; |
+ fKey[kDomainAndSize_MetaDataIdx] = kInvalidDomain; |
} |
- bool isValid() const { return kInvalidResourceType != this->resourceType(); } |
- |
- ResourceType resourceType() const { return fKey[kTypeAndSize_MetaDataIdx] & 0xffff; } |
- |
- uint32_t hash() const { return fKey[kHash_MetaDataIdx]; } |
- |
- size_t size() const { return SkToInt(fKey[kTypeAndSize_MetaDataIdx] >> 16); } |
- |
- const uint32_t* data() const { return &fKey[kMetaDataCnt]; } |
+ bool operator==(const GrResourceKey& that) const { |
+ return 0 == memcmp(fKey.get(), that.fKey.get(), this->size()); |
+ } |
- GrScratchKey& operator=(const GrScratchKey& that) { |
+ GrResourceKey& operator=(const GrResourceKey& that) { |
size_t bytes = that.size(); |
+ SkASSERT(SkIsAlign4(bytes)); |
fKey.reset(SkToInt(bytes / sizeof(uint32_t))); |
memcpy(fKey.get(), that.fKey.get(), bytes); |
return *this; |
} |
- bool operator==(const GrScratchKey& that) const { |
- return 0 == memcmp(fKey.get(), that.fKey.get(), this->size()); |
- } |
- bool operator!=(const GrScratchKey& that) const { return !(*this == that); } |
+ bool isValid() const { return kInvalidDomain != this->domain(); } |
- /** Used to initialize scratch key. */ |
+ uint32_t domain() const { return fKey[kDomainAndSize_MetaDataIdx] & 0xffff; } |
+ |
+ /** Used to initialize a key. */ |
class Builder { |
public: |
- Builder(GrScratchKey* key, ResourceType type, int data32Count) : fKey(key) { |
+ Builder(GrResourceKey* key, uint32_t domain, int data32Count) : fKey(key) { |
SkASSERT(data32Count >= 0); |
- SkASSERT(type != kInvalidResourceType); |
+ SkASSERT(domain != kInvalidDomain); |
key->fKey.reset(kMetaDataCnt + data32Count); |
- SkASSERT(type <= SK_MaxU16); |
int size = (data32Count + kMetaDataCnt) * sizeof(uint32_t); |
- SkASSERT(size <= SK_MaxU16); |
- key->fKey[kTypeAndSize_MetaDataIdx] = type | (size << 16); |
+ SkASSERT(SkToU16(size) == size); |
+ SkASSERT(SkToU16(domain) == domain); |
+ key->fKey[kDomainAndSize_MetaDataIdx] = domain | (size << 16); |
} |
~Builder() { this->finish(); } |
- void finish(); |
+ void finish() { |
+ if (NULL == fKey) { |
+ return; |
+ } |
+ GR_STATIC_ASSERT(0 == kHash_MetaDataIdx); |
+ uint32_t* hash = &fKey->fKey[kHash_MetaDataIdx]; |
+ *hash = GrResourceKeyHash(hash + 1, fKey->internalSize() - sizeof(uint32_t)); |
+ fKey->validate(); |
+ fKey = NULL; |
+ } |
uint32_t& operator[](int dataIdx) { |
SkASSERT(fKey); |
- SkDEBUGCODE(size_t dataCount = fKey->size() / sizeof(uint32_t) - kMetaDataCnt;) |
+ SkDEBUGCODE(size_t dataCount = fKey->internalSize() / sizeof(uint32_t) - kMetaDataCnt;) |
SkASSERT(SkToU32(dataIdx) < dataCount); |
return fKey->fKey[kMetaDataCnt + dataIdx]; |
} |
private: |
- GrScratchKey* fKey; |
+ GrResourceKey* fKey; |
}; |
private: |
+ size_t internalSize() const { |
+ return fKey[kDomainAndSize_MetaDataIdx] >> 16; |
+ } |
+ |
+ void validate() const { |
+ SkASSERT(fKey[kHash_MetaDataIdx] == |
+ GrResourceKeyHash(&fKey[kHash_MetaDataIdx] + 1, |
+ this->internalSize() - sizeof(uint32_t))); |
+ } |
+ |
enum MetaDataIdx { |
kHash_MetaDataIdx, |
- // The resource type and size are packed into a single uint32_t. |
- kTypeAndSize_MetaDataIdx, |
+ // The key domain and size are packed into a single uint32_t. |
+ kDomainAndSize_MetaDataIdx, |
- kLastMetaDataIdx = kTypeAndSize_MetaDataIdx |
+ kLastMetaDataIdx = kDomainAndSize_MetaDataIdx |
}; |
- static const uint32_t kInvalidResourceType = 0; |
static const uint32_t kMetaDataCnt = kLastMetaDataIdx + 1; |
friend class TestResource; // For unit test to access kMetaDataCnt. |
- // Stencil and textures each require 2 uint32_t values. |
- SkAutoSTArray<kMetaDataCnt + 2, uint32_t> fKey; |
+ // bmp textures require 4 uint32_t values. |
+ SkAutoSTArray<kMetaDataCnt + 4, uint32_t> fKey; |
}; |
-class GrResourceKey { |
+/** |
+ * A key used for scratch resources. The key consists of a resource type (subclass) identifier, a |
+ * hash, a data length, and type-specific data. A Builder object is used to initialize the |
+ * key contents. The contents must be initialized before the key can be used. |
+ */ |
+class GrScratchKey : public GrResourceKey { |
+private: |
+ typedef GrResourceKey INHERITED; |
+ |
public: |
- /** Flags set by the GrGpuResource subclass. */ |
- typedef uint8_t ResourceFlags; |
+ /** Uniquely identifies the type of resource that is cached as scratch. */ |
+ typedef uint32_t ResourceType; |
- /** Creates a key for resource */ |
- GrResourceKey(const GrCacheID& id, ResourceFlags flags) { |
- this->init(id.getDomain(), id.getKey(), flags); |
- }; |
+ /** Generate a unique ResourceType. */ |
+ static ResourceType GenerateResourceType(); |
- GrResourceKey(const GrResourceKey& src) { fKey = src.fKey; } |
+ /** Creates an invalid scratch key. It must be initialized using a Builder object before use. */ |
+ GrScratchKey() {} |
- GrResourceKey() { fKey.reset(); } |
+ GrScratchKey(const GrScratchKey& that) { *this = that; } |
- void reset(const GrCacheID& id, ResourceFlags flags) { |
- this->init(id.getDomain(), id.getKey(), flags); |
- } |
+ /** reset() returns the key to the invalid state. */ |
+ using INHERITED::reset; |
+ |
+ using INHERITED::isValid; |
- uint32_t getHash() const { return fKey.getHash(); } |
+ ResourceType resourceType() const { return this->domain(); } |
- ResourceFlags getResourceFlags() const { |
- return *reinterpret_cast<const ResourceFlags*>(fKey.getData() + |
- kResourceFlagsOffset); |
+ GrScratchKey& operator=(const GrScratchKey& that) { |
+ this->INHERITED::operator=(that); |
+ return *this; |
} |
- bool operator==(const GrResourceKey& other) const { return fKey == other.fKey; } |
+ bool operator==(const GrScratchKey& that) const { |
+ return this->INHERITED::operator==(that); |
+ } |
+ bool operator!=(const GrScratchKey& that) const { return !(*this == that); } |
- // A key indicating that the resource is not usable as a scratch resource. |
- static GrResourceKey& NullScratchKey(); |
+ class Builder : public INHERITED::Builder { |
+ public: |
+ Builder(GrScratchKey* key, ResourceType type, int data32Count) |
+ : INHERITED::Builder(key, type, data32Count) {} |
+ }; |
+}; |
+/** |
+ * A key used to cache resources based on their content. The key consists of a domain type (use |
+ * case for the cache), a hash, a data length, and domain-specific data. A Builder object is used to |
+ * initialize the key contents. The contents must be initialized before the key can be used. |
+ */ |
+class GrContentKey : public GrResourceKey { |
private: |
- enum { |
- kCacheIDKeyOffset = 0, |
- kCacheIDDomainOffset = kCacheIDKeyOffset + sizeof(GrCacheID::Key), |
- kResourceFlagsOffset = kCacheIDDomainOffset + sizeof(GrCacheID::Domain), |
- kPadOffset = kResourceFlagsOffset + sizeof(ResourceFlags), |
- kKeySize = SkAlign4(kPadOffset), |
- kPadSize = kKeySize - kPadOffset |
- }; |
+ typedef GrResourceKey INHERITED; |
+ |
+public: |
+ typedef uint32_t Domain; |
+ /** Generate a unique Domain of content keys. */ |
+ static Domain GenerateDomain(); |
+ |
+ /** Creates an invalid content key. It must be initialized using a Builder object before use. */ |
+ GrContentKey() {} |
+ |
+ GrContentKey(const GrContentKey& that) { *this = that; } |
- void init(const GrCacheID::Domain domain, const GrCacheID::Key& key, ResourceFlags flags) { |
- union { |
- uint8_t fKey8[kKeySize]; |
- uint32_t fKey32[kKeySize / 4]; |
- } keyData; |
- |
- uint8_t* k = keyData.fKey8; |
- memcpy(k + kCacheIDKeyOffset, key.fData8, sizeof(GrCacheID::Key)); |
- memcpy(k + kCacheIDDomainOffset, &domain, sizeof(GrCacheID::Domain)); |
- memcpy(k + kResourceFlagsOffset, &flags, sizeof(ResourceFlags)); |
- memset(k + kPadOffset, 0, kPadSize); |
- fKey.setKeyData(keyData.fKey32); |
+ /** reset() returns the key to the invalid state. */ |
+ using INHERITED::reset; |
+ |
+ using INHERITED::isValid; |
+ |
+ GrContentKey& operator=(const GrContentKey& that) { |
+ this->INHERITED::operator=(that); |
+ return *this; |
+ } |
+ |
+ bool operator==(const GrContentKey& that) const { |
+ return this->INHERITED::operator==(that); |
} |
- GrBinHashKey<kKeySize> fKey; |
+ bool operator!=(const GrContentKey& that) const { return !(*this == that); } |
+ |
+ class Builder : public INHERITED::Builder { |
+ public: |
+ Builder(GrContentKey* key, Domain domain, int data32Count) |
+ : INHERITED::Builder(key, domain, data32Count) {} |
+ |
+ /** Used to build a key that wraps another key and adds additional data. */ |
+ Builder(GrContentKey* key, const GrContentKey& innerKey, Domain domain, |
+ int extraData32Cnt) |
+ : INHERITED::Builder(key, domain, (SkToInt(innerKey.size()) >> 2) + extraData32Cnt) { |
+ int innerKeyCnt = SkToInt(innerKey.size()) >> 2; |
+ // add the inner key to the end of the key so that op[] can be indexed normally. |
+ for (int i = 0; i < innerKeyCnt; ++i) { |
+ this->operator[](extraData32Cnt + i) = innerKey.data()[i]; |
+ } |
+ } |
+ }; |
}; |
#endif |