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