GrResourceKey.h revision 988018c817f341c0ce09297b7ba5ba60ba76eba9
1
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"
13#include "SkTemplates.h"
14#include "GrBinHashKey.h"
15
16/**
17 * A key used for scratch resources. The key consists of a resource type (subclass) identifier, a
18 * hash, a data length, and type-specific data. A Builder object is used to initialize the
19 * key contents. The contents must be initialized before the key can be used.
20 */
21class GrScratchKey {
22public:
23    /** Uniquely identifies the type of resource that is cached as scratch. */
24    typedef uint32_t ResourceType;
25    /** Generate a unique ResourceType. */
26    static ResourceType GenerateResourceType();
27
28    GrScratchKey() { this->reset(); }
29    GrScratchKey(const GrScratchKey& that) { *this = that; }
30
31    /** Reset to an invalid key. */
32    void reset() {
33        fKey.reset(kMetaDataCnt);
34        fKey[kHash_MetaDataIdx] = 0;
35        fKey[kTypeAndSize_MetaDataIdx] = kInvalidResourceType;
36    }
37
38    bool isValid() const { return kInvalidResourceType != this->resourceType(); }
39
40    ResourceType resourceType() const { return fKey[kTypeAndSize_MetaDataIdx] & 0xffff; }
41
42    uint32_t hash() const { return fKey[kHash_MetaDataIdx]; }
43
44    size_t size() const { return SkToInt(fKey[kTypeAndSize_MetaDataIdx] >> 16); }
45
46    const uint32_t* data() const { return &fKey[kMetaDataCnt]; }
47
48    GrScratchKey& operator=(const GrScratchKey& that) {
49        size_t size = that.size();
50        fKey.reset(SkToInt(size));
51        memcpy(fKey.get(), that.fKey.get(), size);
52        return *this;
53    }
54
55    bool operator==(const GrScratchKey& that) const {
56        return 0 == memcmp(fKey.get(), that.fKey.get(), this->size());
57    }
58    bool operator!=(const GrScratchKey& that) const { return !(*this == that); }
59
60    /** Used to initialize scratch key. */
61    class Builder {
62    public:
63        Builder(GrScratchKey* key, ResourceType type, int data32Count) : fKey(key) {
64            SkASSERT(data32Count >= 0);
65            SkASSERT(type != kInvalidResourceType);
66            key->fKey.reset(kMetaDataCnt + data32Count);
67            SkASSERT(type <= SK_MaxU16);
68            int size = (data32Count + kMetaDataCnt) * sizeof(uint32_t);
69            SkASSERT(size <= SK_MaxU16);
70            key->fKey[kTypeAndSize_MetaDataIdx] = type | (size << 16);
71        }
72
73        ~Builder() { this->finish(); }
74
75        void finish();
76
77        uint32_t& operator[](int dataIdx) {
78            SkASSERT(fKey);
79            SkDEBUGCODE(size_t dataCount = fKey->size() / sizeof(uint32_t) - kMetaDataCnt;)
80            SkASSERT(SkToU32(dataIdx) < dataCount);
81            return fKey->fKey[kMetaDataCnt + dataIdx];
82        }
83
84    private:
85        GrScratchKey* fKey;
86    };
87
88private:
89    enum MetaDataIdx {
90        kHash_MetaDataIdx,
91        // The resource type and size are packed into a single uint32_t.
92        kTypeAndSize_MetaDataIdx,
93
94        kLastMetaDataIdx = kTypeAndSize_MetaDataIdx
95    };
96    static const uint32_t kInvalidResourceType = 0;
97    static const uint32_t kMetaDataCnt = kLastMetaDataIdx + 1;
98
99    // Stencil and textures each require 2 uint32_t values.
100    SkAutoSTArray<kMetaDataCnt + 2, uint32_t> fKey;
101};
102
103class GrResourceKey {
104public:
105    /** Flags set by the GrGpuResource subclass. */
106    typedef uint8_t ResourceFlags;
107
108    /** Creates a key for resource */
109    GrResourceKey(const GrCacheID& id, ResourceFlags flags) {
110        this->init(id.getDomain(), id.getKey(), flags);
111    };
112
113    GrResourceKey(const GrResourceKey& src) { fKey = src.fKey; }
114
115    GrResourceKey() { fKey.reset(); }
116
117    void reset(const GrCacheID& id, ResourceFlags flags) {
118        this->init(id.getDomain(), id.getKey(), flags);
119    }
120
121    uint32_t getHash() const { return fKey.getHash(); }
122
123    ResourceFlags getResourceFlags() const {
124        return *reinterpret_cast<const ResourceFlags*>(fKey.getData() +
125                                                       kResourceFlagsOffset);
126    }
127
128    bool operator==(const GrResourceKey& other) const { return fKey == other.fKey; }
129
130    // A key indicating that the resource is not usable as a scratch resource.
131    static GrResourceKey& NullScratchKey();
132
133private:
134    enum {
135        kCacheIDKeyOffset = 0,
136        kCacheIDDomainOffset = kCacheIDKeyOffset + sizeof(GrCacheID::Key),
137        kResourceFlagsOffset = kCacheIDDomainOffset + sizeof(GrCacheID::Domain),
138        kPadOffset = kResourceFlagsOffset + sizeof(ResourceFlags),
139        kKeySize = SkAlign4(kPadOffset),
140        kPadSize = kKeySize - kPadOffset
141    };
142
143    void init(const GrCacheID::Domain domain, const GrCacheID::Key& key, ResourceFlags flags) {
144        union {
145            uint8_t  fKey8[kKeySize];
146            uint32_t fKey32[kKeySize / 4];
147        } keyData;
148
149        uint8_t* k = keyData.fKey8;
150        memcpy(k + kCacheIDKeyOffset, key.fData8, sizeof(GrCacheID::Key));
151        memcpy(k + kCacheIDDomainOffset, &domain, sizeof(GrCacheID::Domain));
152        memcpy(k + kResourceFlagsOffset, &flags, sizeof(ResourceFlags));
153        memset(k + kPadOffset, 0, kPadSize);
154        fKey.setKeyData(keyData.fKey32);
155    }
156    GrBinHashKey<kKeySize> fKey;
157};
158
159#endif
160