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