blob: aac3af4d1b5ac5a6b9688e0265d79dc943cec5c3 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 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 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#ifndef SkTextureCache_DEFINED
9#define SkTextureCache_DEFINED
10
11#include "SkBitmap.h"
12#include "SkPoint.h"
13#include "SkGL.h"
14#include "SkTDArray.h"
15
16class SkTextureCache {
17public:
18 SkTextureCache(size_t maxCount, size_t maxSize);
19 ~SkTextureCache();
20
21 size_t getMaxCount() { return fTexCountMax; }
22 size_t getMaxSize() { return fTexSizeMax; }
23
24 void setMaxCount(size_t count);
25 void setMaxSize(size_t size);
26
27 /** Deletes all the caches. Pass true if the texture IDs are still valid,
28 and if so, it will call glDeleteTextures. Pass false if the texture IDs
29 are invalid (e.g. the gl-context has changed), in which case they will
30 just be abandoned.
31 */
32 void deleteAllCaches(bool texturesAreValid);
33
34 static int HashMask() { return kHashMask; }
35
36 class Key {
37 public:
38 Key(const SkBitmap& bm) {
39 fGenID = bm.getGenerationID();
40 fOffset = bm.pixelRefOffset();
41 fWH = (bm.width() << 16) | bm.height();
42 this->computeHash();
43 }
44
45 int getHashIndex() const { return fHashIndex; }
46
47 friend bool operator==(const Key& a, const Key& b) {
48 return a.fHash == b.fHash &&
49 a.fGenID == b.fGenID &&
50 a.fOffset == b.fOffset &&
51 a.fWH == b.fWH;
52 }
53
54 friend bool operator<(const Key& a, const Key& b) {
55 if (a.fHash < b.fHash) {
56 return true;
57 } else if (a.fHash > b.fHash) {
58 return false;
59 }
60
61 if (a.fGenID < b.fGenID) {
62 return true;
63 } else if (a.fGenID > b.fGenID) {
64 return false;
65 }
66
67 if (a.fOffset < b.fOffset) {
68 return true;
69 } else if (a.fOffset > b.fOffset) {
70 return false;
71 }
72
73 return a.fWH < b.fWH;
74 }
75
76 private:
77 void computeHash() {
78 uint32_t hash = fGenID ^ fOffset ^ fWH;
79 fHash = hash;
80 hash ^= hash >> 16;
81 fHashIndex = hash & SkTextureCache::HashMask();
82 }
83
84 uint32_t fHash; // computed from the other fields
85 uint32_t fGenID;
86 size_t fOffset;
87 uint32_t fWH;
88 // for indexing into the texturecache's fHash
89 int fHashIndex;
90 };
91
92 class Entry {
93 public:
94 GLuint name() const { return fName; }
95 SkPoint texSize() const { return fTexSize; }
96 size_t memSize() const { return fMemSize; }
97 const Key& getKey() const { return fKey; }
98
99 // call this to clear the texture name, in case the context has changed
100 // in which case we should't reference or delete this texture in GL
101 void abandonTexture() { fName = 0; }
102
103 private:
104 Entry(const SkBitmap& bitmap);
105 ~Entry();
106
107 int lockCount() const { return fLockCount; }
108 bool isLocked() const { return fLockCount > 0; }
109
110 void lock() { fLockCount += 1; }
111 void unlock() {
112 SkASSERT(fLockCount > 0);
113 fLockCount -= 1;
114 }
115
116 private:
117 GLuint fName;
118 SkPoint fTexSize;
119 Key fKey;
120 size_t fMemSize;
121 int fLockCount;
122
123 Entry* fPrev;
124 Entry* fNext;
125
126 friend class SkTextureCache;
127 };
128
129 Entry* lock(const SkBitmap&);
130 void unlock(Entry*);
131
132private:
133 void purgeIfNecessary(size_t extraSize);
134
135#ifdef SK_DEBUG
136 void validate() const;
137#else
138 void validate() const {}
139#endif
140
141 Entry* fHead;
142 Entry* fTail;
143
144 // limits for the cache
145 size_t fTexCountMax;
146 size_t fTexSizeMax;
147
148 // current values for the cache
149 size_t fTexCount;
150 size_t fTexSize;
151
152 enum {
153 kHashBits = 6,
154 kHashCount = 1 << kHashBits,
155 kHashMask = kHashCount - 1
156 };
157 mutable Entry* fHash[kHashCount];
158 SkTDArray<Entry*> fSorted;
159
160 /* If we find the key, return the entry and ignore index. If we don't,
161 return NULL and set index to the place to insert the entry in fSorted
162 */
163 Entry* find(const Key&, int* index) const;
164 // returns index or <0 if not found. Does NOT update hash
165 int findInSorted(const Key& key) const;
166};
167
168#endif