aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrBinHashKey.h
blob: 06ff93180855f806d1e3af22260ce65c969ed151 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#ifndef GrBinHashKey_DEFINED
#define GrBinHashKey_DEFINED

#include "SkChecksum.h"
#include "GrTypes.h"

/**
 *  GrMurmur3HashKey is a hash key class that can take a data chunk of any predetermined
 *  length. It uses the Murmur3 hash function. It is intended to be used with
 *  SkTDynamicHash (where GrBinHashKey is for GrTHashTable).
 */
template<size_t KEY_SIZE_IN_BYTES>
class GrMurmur3HashKey {
public:
    GrMurmur3HashKey() {
        this->reset();
    }

    void reset() {
        fHash = 0;
#ifdef SK_DEBUG
        fIsValid = false;
#endif
    }

    void setKeyData(const uint32_t* data) {
        SK_COMPILE_ASSERT(KEY_SIZE_IN_BYTES % 4 == 0, key_size_mismatch);
        memcpy(fData, data, KEY_SIZE_IN_BYTES);

        fHash = SkChecksum::Murmur3(fData, KEY_SIZE_IN_BYTES);
#ifdef SK_DEBUG
        fIsValid = true;
#endif
    }

    bool operator==(const GrMurmur3HashKey& other) const {
        if (fHash != other.fHash) {
            return false;
        }

        return !memcmp(fData, other.fData, KEY_SIZE_IN_BYTES);
    }

    uint32_t getHash() const {
        SkASSERT(fIsValid);
        return fHash;
    }

    const uint8_t* getData() const {
        SkASSERT(fIsValid);
        return reinterpret_cast<const uint8_t*>(fData);
    }

private:
    uint32_t fHash;
    uint32_t fData[KEY_SIZE_IN_BYTES / sizeof(uint32_t)];  // Buffer for key storage.

#ifdef SK_DEBUG
public:
    bool                fIsValid;
#endif
};

/**
 *  GrBinHashKey is a hash key class that can take a data chunk of any predetermined
 *  length. The hash function used is the One-at-a-Time Hash
 *  (http://burtleburtle.net/bob/hash/doobs.html).
 */
template<size_t KEY_SIZE>
class GrBinHashKey {
public:
    enum { kKeySize = KEY_SIZE };

    GrBinHashKey() {
        this->reset();
    }

    void reset() {
        fHash = 0;
#ifdef SK_DEBUG
        fIsValid = false;
#endif
    }

    void setKeyData(const uint32_t* SK_RESTRICT data) {
        SK_COMPILE_ASSERT(KEY_SIZE % 4 == 0, key_size_mismatch);
        memcpy(&fData, data, KEY_SIZE);

        uint32_t hash = 0;
        size_t len = KEY_SIZE;
        while (len >= 4) {
            hash += *data++;
            hash += (hash << 10);
            hash ^= (hash >> 6);
            len -= 4;
        }
        hash += (hash << 3);
        hash ^= (hash >> 11);
        hash += (hash << 15);
#ifdef SK_DEBUG
        fIsValid = true;
#endif
        fHash = hash;
    }

    bool operator==(const GrBinHashKey<KEY_SIZE>& key) const {
        SkASSERT(fIsValid && key.fIsValid);
        if (fHash != key.fHash) {
            return false;
        }
        for (size_t i = 0; i < SK_ARRAY_COUNT(fData); ++i) {
            if (fData[i] != key.fData[i]) {
                return false;
            }
        }
        return true;
    }

    bool operator<(const GrBinHashKey<KEY_SIZE>& key) const {
        SkASSERT(fIsValid && key.fIsValid);
        for (size_t i = 0; i < SK_ARRAY_COUNT(fData); ++i) {
            if (fData[i] < key.fData[i]) {
                return true;
            } else if (fData[i] > key.fData[i]) {
                return false;
            }
        }
        return false;
    }

    uint32_t getHash() const {
        SkASSERT(fIsValid);
        return fHash;
    }

    const uint8_t* getData() const {
        SkASSERT(fIsValid);
        return reinterpret_cast<const uint8_t*>(fData);
    }

private:
    uint32_t            fHash;
    uint32_t            fData[KEY_SIZE / sizeof(uint32_t)];  // Buffer for key storage.

#ifdef SK_DEBUG
public:
    bool                fIsValid;
#endif
};

#endif