GrResourceKey.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  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. #ifndef GrResourceKey_DEFINED
  8. #define GrResourceKey_DEFINED
  9. #include "../private/SkOnce.h"
  10. #include "../private/SkTemplates.h"
  11. #include "../private/SkTo.h"
  12. #include "GrTypes.h"
  13. #include "SkData.h"
  14. #include "SkString.h"
  15. #include <new>
  16. uint32_t GrResourceKeyHash(const uint32_t* data, size_t size);
  17. /**
  18. * Base class for all GrGpuResource cache keys. There are two types of cache keys. Refer to the
  19. * comments for each key type below.
  20. */
  21. class GrResourceKey {
  22. public:
  23. uint32_t hash() const {
  24. this->validate();
  25. return fKey[kHash_MetaDataIdx];
  26. }
  27. size_t size() const {
  28. this->validate();
  29. SkASSERT(this->isValid());
  30. return this->internalSize();
  31. }
  32. protected:
  33. static const uint32_t kInvalidDomain = 0;
  34. GrResourceKey() { this->reset(); }
  35. /** Reset to an invalid key. */
  36. void reset() {
  37. GR_STATIC_ASSERT((uint16_t)kInvalidDomain == kInvalidDomain);
  38. fKey.reset(kMetaDataCnt);
  39. fKey[kHash_MetaDataIdx] = 0;
  40. fKey[kDomainAndSize_MetaDataIdx] = kInvalidDomain;
  41. }
  42. bool operator==(const GrResourceKey& that) const {
  43. return this->hash() == that.hash() &&
  44. 0 == memcmp(&fKey[kHash_MetaDataIdx + 1],
  45. &that.fKey[kHash_MetaDataIdx + 1],
  46. this->internalSize() - sizeof(uint32_t));
  47. }
  48. GrResourceKey& operator=(const GrResourceKey& that) {
  49. SkASSERT(that.isValid());
  50. if (this != &that) {
  51. size_t bytes = that.size();
  52. SkASSERT(SkIsAlign4(bytes));
  53. fKey.reset(SkToInt(bytes / sizeof(uint32_t)));
  54. memcpy(fKey.get(), that.fKey.get(), bytes);
  55. this->validate();
  56. }
  57. return *this;
  58. }
  59. bool isValid() const { return kInvalidDomain != this->domain(); }
  60. uint32_t domain() const { return fKey[kDomainAndSize_MetaDataIdx] & 0xffff; }
  61. /** size of the key data, excluding meta-data (hash, domain, etc). */
  62. size_t dataSize() const { return this->size() - 4 * kMetaDataCnt; }
  63. /** ptr to the key data, excluding meta-data (hash, domain, etc). */
  64. const uint32_t* data() const {
  65. this->validate();
  66. return &fKey[kMetaDataCnt];
  67. }
  68. #ifdef SK_DEBUG
  69. void dump() const {
  70. if (!this->isValid()) {
  71. SkDebugf("Invalid Key\n");
  72. } else {
  73. SkDebugf("hash: %d ", this->hash());
  74. SkDebugf("domain: %d ", this->domain());
  75. SkDebugf("size: %dB ", this->internalSize());
  76. for (size_t i = 0; i < this->internalSize(); ++i) {
  77. SkDebugf("%d ", fKey[i]);
  78. }
  79. SkDebugf("\n");
  80. }
  81. }
  82. #endif
  83. /** Used to initialize a key. */
  84. class Builder {
  85. public:
  86. Builder(GrResourceKey* key, uint32_t domain, int data32Count) : fKey(key) {
  87. SkASSERT(data32Count >= 0);
  88. SkASSERT(domain != kInvalidDomain);
  89. key->fKey.reset(kMetaDataCnt + data32Count);
  90. int size = (data32Count + kMetaDataCnt) * sizeof(uint32_t);
  91. SkASSERT(SkToU16(size) == size);
  92. SkASSERT(SkToU16(domain) == domain);
  93. key->fKey[kDomainAndSize_MetaDataIdx] = domain | (size << 16);
  94. }
  95. ~Builder() { this->finish(); }
  96. void finish() {
  97. if (nullptr == fKey) {
  98. return;
  99. }
  100. GR_STATIC_ASSERT(0 == kHash_MetaDataIdx);
  101. uint32_t* hash = &fKey->fKey[kHash_MetaDataIdx];
  102. *hash = GrResourceKeyHash(hash + 1, fKey->internalSize() - sizeof(uint32_t));
  103. fKey->validate();
  104. fKey = nullptr;
  105. }
  106. uint32_t& operator[](int dataIdx) {
  107. SkASSERT(fKey);
  108. SkDEBUGCODE(size_t dataCount = fKey->internalSize() / sizeof(uint32_t) - kMetaDataCnt;)
  109. SkASSERT(SkToU32(dataIdx) < dataCount);
  110. return fKey->fKey[kMetaDataCnt + dataIdx];
  111. }
  112. private:
  113. GrResourceKey* fKey;
  114. };
  115. private:
  116. enum MetaDataIdx {
  117. kHash_MetaDataIdx,
  118. // The key domain and size are packed into a single uint32_t.
  119. kDomainAndSize_MetaDataIdx,
  120. kLastMetaDataIdx = kDomainAndSize_MetaDataIdx
  121. };
  122. static const uint32_t kMetaDataCnt = kLastMetaDataIdx + 1;
  123. size_t internalSize() const {
  124. return fKey[kDomainAndSize_MetaDataIdx] >> 16;
  125. }
  126. void validate() const {
  127. SkASSERT(fKey[kHash_MetaDataIdx] ==
  128. GrResourceKeyHash(&fKey[kHash_MetaDataIdx] + 1,
  129. this->internalSize() - sizeof(uint32_t)));
  130. SkASSERT(SkIsAlign4(this->internalSize()));
  131. }
  132. friend class TestResource; // For unit test to access kMetaDataCnt.
  133. // bmp textures require 5 uint32_t values.
  134. SkAutoSTMalloc<kMetaDataCnt + 5, uint32_t> fKey;
  135. };
  136. /**
  137. * A key used for scratch resources. There are three important rules about scratch keys:
  138. * * Multiple resources can share the same scratch key. Therefore resources assigned the same
  139. * scratch key should be interchangeable with respect to the code that uses them.
  140. * * A resource can have at most one scratch key and it is set at resource creation by the
  141. * resource itself.
  142. * * When a scratch resource is ref'ed it will not be returned from the
  143. * cache for a subsequent cache request until all refs are released. This facilitates using
  144. * a scratch key for multiple render-to-texture scenarios. An example is a separable blur:
  145. *
  146. * GrTexture* texture[2];
  147. * texture[0] = get_scratch_texture(scratchKey);
  148. * texture[1] = get_scratch_texture(scratchKey); // texture[0] is already owned so we will get a
  149. * // different one for texture[1]
  150. * draw_mask(texture[0], path); // draws path mask to texture[0]
  151. * blur_x(texture[0], texture[1]); // blurs texture[0] in y and stores result in texture[1]
  152. * blur_y(texture[1], texture[0]); // blurs texture[1] in y and stores result in texture[0]
  153. * texture[1]->unref(); // texture 1 can now be recycled for the next request with scratchKey
  154. * consume_blur(texture[0]);
  155. * texture[0]->unref(); // texture 0 can now be recycled for the next request with scratchKey
  156. */
  157. class GrScratchKey : public GrResourceKey {
  158. private:
  159. typedef GrResourceKey INHERITED;
  160. public:
  161. /** Uniquely identifies the type of resource that is cached as scratch. */
  162. typedef uint32_t ResourceType;
  163. /** Generate a unique ResourceType. */
  164. static ResourceType GenerateResourceType();
  165. /** Creates an invalid scratch key. It must be initialized using a Builder object before use. */
  166. GrScratchKey() {}
  167. GrScratchKey(const GrScratchKey& that) { *this = that; }
  168. /** reset() returns the key to the invalid state. */
  169. using INHERITED::reset;
  170. using INHERITED::isValid;
  171. ResourceType resourceType() const { return this->domain(); }
  172. GrScratchKey& operator=(const GrScratchKey& that) {
  173. this->INHERITED::operator=(that);
  174. return *this;
  175. }
  176. bool operator==(const GrScratchKey& that) const {
  177. return this->INHERITED::operator==(that);
  178. }
  179. bool operator!=(const GrScratchKey& that) const { return !(*this == that); }
  180. class Builder : public INHERITED::Builder {
  181. public:
  182. Builder(GrScratchKey* key, ResourceType type, int data32Count)
  183. : INHERITED::Builder(key, type, data32Count) {}
  184. };
  185. };
  186. /**
  187. * A key that allows for exclusive use of a resource for a use case (AKA "domain"). There are three
  188. * rules governing the use of unique keys:
  189. * * Only one resource can have a given unique key at a time. Hence, "unique".
  190. * * A resource can have at most one unique key at a time.
  191. * * Unlike scratch keys, multiple requests for a unique key will return the same
  192. * resource even if the resource already has refs.
  193. * This key type allows a code path to create cached resources for which it is the exclusive user.
  194. * The code path creates a domain which it sets on its keys. This guarantees that there are no
  195. * cross-domain collisions.
  196. *
  197. * Unique keys preempt scratch keys. While a resource has a unique key it is inaccessible via its
  198. * scratch key. It can become scratch again if the unique key is removed.
  199. */
  200. class GrUniqueKey : public GrResourceKey {
  201. private:
  202. typedef GrResourceKey INHERITED;
  203. public:
  204. typedef uint32_t Domain;
  205. /** Generate a Domain for unique keys. */
  206. static Domain GenerateDomain();
  207. /** Creates an invalid unique key. It must be initialized using a Builder object before use. */
  208. GrUniqueKey() : fTag(nullptr) {}
  209. GrUniqueKey(const GrUniqueKey& that) { *this = that; }
  210. /** reset() returns the key to the invalid state. */
  211. using INHERITED::reset;
  212. using INHERITED::isValid;
  213. GrUniqueKey& operator=(const GrUniqueKey& that) {
  214. this->INHERITED::operator=(that);
  215. this->setCustomData(sk_ref_sp(that.getCustomData()));
  216. fTag = that.fTag;
  217. return *this;
  218. }
  219. bool operator==(const GrUniqueKey& that) const {
  220. return this->INHERITED::operator==(that);
  221. }
  222. bool operator!=(const GrUniqueKey& that) const { return !(*this == that); }
  223. void setCustomData(sk_sp<SkData> data) {
  224. fData = std::move(data);
  225. }
  226. SkData* getCustomData() const {
  227. return fData.get();
  228. }
  229. const char* tag() const { return fTag; }
  230. #ifdef SK_DEBUG
  231. void dump(const char* label) const {
  232. SkDebugf("%s tag: %s\n", label, fTag ? fTag : "None");
  233. this->INHERITED::dump();
  234. }
  235. #endif
  236. class Builder : public INHERITED::Builder {
  237. public:
  238. Builder(GrUniqueKey* key, Domain type, int data32Count, const char* tag = nullptr)
  239. : INHERITED::Builder(key, type, data32Count) {
  240. key->fTag = tag;
  241. }
  242. /** Used to build a key that wraps another key and adds additional data. */
  243. Builder(GrUniqueKey* key, const GrUniqueKey& innerKey, Domain domain, int extraData32Cnt,
  244. const char* tag = nullptr)
  245. : INHERITED::Builder(key, domain, Data32CntForInnerKey(innerKey) + extraData32Cnt) {
  246. SkASSERT(&innerKey != key);
  247. // add the inner key to the end of the key so that op[] can be indexed normally.
  248. uint32_t* innerKeyData = &this->operator[](extraData32Cnt);
  249. const uint32_t* srcData = innerKey.data();
  250. (*innerKeyData++) = innerKey.domain();
  251. memcpy(innerKeyData, srcData, innerKey.dataSize());
  252. key->fTag = tag;
  253. }
  254. private:
  255. static int Data32CntForInnerKey(const GrUniqueKey& innerKey) {
  256. // key data + domain
  257. return SkToInt((innerKey.dataSize() >> 2) + 1);
  258. }
  259. };
  260. private:
  261. sk_sp<SkData> fData;
  262. const char* fTag;
  263. };
  264. /**
  265. * It is common to need a frequently reused GrUniqueKey where the only requirement is that the key
  266. * is unique. These macros create such a key in a thread safe manner so the key can be truly global
  267. * and only constructed once.
  268. */
  269. /** Place outside of function/class definitions. */
  270. #define GR_DECLARE_STATIC_UNIQUE_KEY(name) static SkOnce name##_once
  271. /** Place inside function where the key is used. */
  272. #define GR_DEFINE_STATIC_UNIQUE_KEY(name) \
  273. static SkAlignedSTStorage<1, GrUniqueKey> name##_storage; \
  274. name##_once(gr_init_static_unique_key_once, &name##_storage); \
  275. static const GrUniqueKey& name = *reinterpret_cast<GrUniqueKey*>(name##_storage.get());
  276. static inline void gr_init_static_unique_key_once(SkAlignedSTStorage<1,GrUniqueKey>* keyStorage) {
  277. GrUniqueKey* key = new (keyStorage->get()) GrUniqueKey;
  278. GrUniqueKey::Builder builder(key, GrUniqueKey::GenerateDomain(), 0);
  279. }
  280. // The cache listens for these messages to purge junk resources proactively.
  281. class GrUniqueKeyInvalidatedMessage {
  282. public:
  283. GrUniqueKeyInvalidatedMessage(const GrUniqueKey& key, uint32_t contextUniqueID)
  284. : fKey(key), fContextID(contextUniqueID) {
  285. SkASSERT(SK_InvalidUniqueID != contextUniqueID);
  286. }
  287. GrUniqueKeyInvalidatedMessage(const GrUniqueKeyInvalidatedMessage&) = default;
  288. GrUniqueKeyInvalidatedMessage& operator=(const GrUniqueKeyInvalidatedMessage&) = default;
  289. const GrUniqueKey& key() const { return fKey; }
  290. uint32_t contextID() const { return fContextID; }
  291. private:
  292. GrUniqueKey fKey;
  293. uint32_t fContextID;
  294. };
  295. static inline bool SkShouldPostMessageToBus(
  296. const GrUniqueKeyInvalidatedMessage& msg, uint32_t msgBusUniqueID) {
  297. return msg.contextID() == msgBusUniqueID;
  298. }
  299. #endif