blob: 7a2b2a79a17ade040c3c93106b5b22cf8c590015 [file] [log] [blame]
joshualittb7133be2015-04-08 09:08:31 -07001/*
2 * Copyright 2015 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 GrTextBlobCache_DEFINED
9#define GrTextBlobCache_DEFINED
10
11#include "GrAtlasTextContext.h"
12#include "SkTDynamicHash.h"
13#include "SkTextBlob.h"
14
15class GrTextBlobCache {
16public:
17 typedef GrAtlasTextContext::BitmapTextBlob BitmapTextBlob;
18
19 GrTextBlobCache() : fPool(kPreAllocSize, kMinGrowthSize) {}
20 ~GrTextBlobCache();
21
22 // creates an uncached blob
23 BitmapTextBlob* createBlob(int glyphCount, int runCount, size_t maxVASize);
24
25 BitmapTextBlob* createCachedBlob(const SkTextBlob* blob, size_t maxVAStride) {
26 int glyphCount = 0;
27 int runCount = 0;
28 BlobGlyphCount(&glyphCount, &runCount, blob);
29 BitmapTextBlob* cacheBlob = this->createBlob(glyphCount, runCount, maxVAStride);
30 cacheBlob->fUniqueID = blob->uniqueID();
31 this->add(cacheBlob);
32 return cacheBlob;
33 }
34
35 BitmapTextBlob* find(uint32_t uniqueID) {
36 return fCache.find(uniqueID);
37 }
38
39 void remove(BitmapTextBlob* blob) {
40 fCache.remove(blob->fUniqueID);
41 fBlobList.remove(blob);
42 blob->unref();
43 }
44
45 void add(BitmapTextBlob* blob) {
46 fCache.add(blob);
47 fBlobList.addToHead(blob);
48
49 // If we are overbudget, then unref until we are below budget again
50 if (fPool.size() > kBudget) {
51 BitmapBlobList::Iter iter;
52 iter.init(fBlobList, BitmapBlobList::Iter::kTail_IterStart);
53 BitmapTextBlob* lruBlob = iter.get();
54 SkASSERT(lruBlob);
55 do {
56 fCache.remove(lruBlob->fUniqueID);
57 fBlobList.remove(lruBlob);
58 lruBlob->unref();
59 iter.prev();
60 } while (fPool.size() > kBudget && (lruBlob = iter.get()));
61 }
62 }
63
64 void makeMRU(BitmapTextBlob* blob) {
65 if (fBlobList.head() == blob) {
66 return;
67 }
68
69 fBlobList.remove(blob);
70 fBlobList.addToHead(blob);
71 }
72
73private:
74 // TODO move to SkTextBlob
75 void BlobGlyphCount(int* glyphCount, int* runCount, const SkTextBlob* blob) {
76 SkTextBlob::RunIterator itCounter(blob);
77 for (; !itCounter.done(); itCounter.next(), (*runCount)++) {
78 *glyphCount += itCounter.glyphCount();
79 }
80 }
81
82 typedef SkTInternalLList<BitmapTextBlob> BitmapBlobList;
83
84 // Budget was chosen to be ~4 megabytes. The min alloc and pre alloc sizes in the pool are
85 // based off of the largest cached textblob I have seen in the skps(a couple of kilobytes).
86 static const int kPreAllocSize = 1 << 17;
87 static const int kMinGrowthSize = 1 << 17;
88 static const int kBudget = 1 << 20;
89 BitmapBlobList fBlobList;
90 SkTDynamicHash<BitmapTextBlob, uint32_t> fCache;
91 GrMemoryPool fPool;
92};
93
94#endif