Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: src/gpu/GrTextBlobCache.h

Issue 1264283002: Add abliity to set textblob cache budget to GrContext (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: tweak Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrTest.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef GrTextBlobCache_DEFINED 8 #ifndef GrTextBlobCache_DEFINED
9 #define GrTextBlobCache_DEFINED 9 #define GrTextBlobCache_DEFINED
10 10
11 #include "GrAtlasTextContext.h" 11 #include "GrAtlasTextContext.h"
12 #include "SkTDynamicHash.h" 12 #include "SkTDynamicHash.h"
13 #include "SkTextBlob.h" 13 #include "SkTextBlob.h"
14 14
15 class GrTextBlobCache { 15 class GrTextBlobCache {
16 public: 16 public:
17 /** 17 /**
18 * The callback function used by the cache when it is still over budget afte r a purge. The 18 * The callback function used by the cache when it is still over budget afte r a purge. The
19 * passed in 'data' is the same 'data' handed to setOverbudgetCallback. 19 * passed in 'data' is the same 'data' handed to setOverbudgetCallback.
20 */ 20 */
21 typedef void (*PFOverBudgetCB)(void* data); 21 typedef void (*PFOverBudgetCB)(void* data);
22 22
23 GrTextBlobCache(PFOverBudgetCB cb, void* data) 23 GrTextBlobCache(PFOverBudgetCB cb, void* data)
24 : fPool(kPreAllocSize, kMinGrowthSize) 24 : fPool(kPreAllocSize, kMinGrowthSize)
25 , fCallback(cb) 25 , fCallback(cb)
26 , fData(data) { 26 , fData(data)
27 , fBudget(kDefaultBudget) {
27 SkASSERT(cb && data); 28 SkASSERT(cb && data);
28 } 29 }
29 ~GrTextBlobCache(); 30 ~GrTextBlobCache();
30 31
31 // creates an uncached blob 32 // creates an uncached blob
32 GrAtlasTextBlob* createBlob(int glyphCount, int runCount, size_t maxVASize); 33 GrAtlasTextBlob* createBlob(int glyphCount, int runCount, size_t maxVASize);
33 GrAtlasTextBlob* createBlob(const SkTextBlob* blob, size_t maxVAStride) { 34 GrAtlasTextBlob* createBlob(const SkTextBlob* blob, size_t maxVAStride) {
34 int glyphCount = 0; 35 int glyphCount = 0;
35 int runCount = 0; 36 int runCount = 0;
36 BlobGlyphCount(&glyphCount, &runCount, blob); 37 BlobGlyphCount(&glyphCount, &runCount, blob);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 void remove(GrAtlasTextBlob* blob) { 75 void remove(GrAtlasTextBlob* blob) {
75 fCache.remove(blob->fKey); 76 fCache.remove(blob->fKey);
76 fBlobList.remove(blob); 77 fBlobList.remove(blob);
77 blob->unref(); 78 blob->unref();
78 } 79 }
79 80
80 void add(GrAtlasTextBlob* blob) { 81 void add(GrAtlasTextBlob* blob) {
81 fCache.add(blob); 82 fCache.add(blob);
82 fBlobList.addToHead(blob); 83 fBlobList.addToHead(blob);
83 84
85 this->checkPurge(blob);
86 }
87
88 void makeMRU(GrAtlasTextBlob* blob) {
89 if (fBlobList.head() == blob) {
90 return;
91 }
92
93 fBlobList.remove(blob);
94 fBlobList.addToHead(blob);
95 }
96
97 void freeAll();
98
99 // TODO move to SkTextBlob
100 static void BlobGlyphCount(int* glyphCount, int* runCount, const SkTextBlob* blob) {
101 SkTextBlob::RunIterator itCounter(blob);
102 for (; !itCounter.done(); itCounter.next(), (*runCount)++) {
103 *glyphCount += itCounter.glyphCount();
104 }
105 }
106
107 void setBudget(size_t budget) {
108 fBudget = budget;
109 this->checkPurge();
110 }
111
112 private:
113 typedef SkTInternalLList<GrAtlasTextBlob> BitmapBlobList;
114
115 void checkPurge(GrAtlasTextBlob* blob = NULL) {
84 // If we are overbudget, then unref until we are below budget again 116 // If we are overbudget, then unref until we are below budget again
85 if (fPool.size() > kBudget) { 117 if (fPool.size() > fBudget) {
86 BitmapBlobList::Iter iter; 118 BitmapBlobList::Iter iter;
87 iter.init(fBlobList, BitmapBlobList::Iter::kTail_IterStart); 119 iter.init(fBlobList, BitmapBlobList::Iter::kTail_IterStart);
88 GrAtlasTextBlob* lruBlob = iter.get(); 120 GrAtlasTextBlob* lruBlob = iter.get();
89 SkASSERT(lruBlob); 121 SkASSERT(lruBlob);
90 while (fPool.size() > kBudget && (lruBlob = iter.get()) && lruBlob ! = blob) { 122 while (fPool.size() > fBudget && (lruBlob = iter.get()) && lruBlob ! = blob) {
91 fCache.remove(lruBlob->fKey); 123 fCache.remove(lruBlob->fKey);
92 124
93 // Backup the iterator before removing and unrefing the blob 125 // Backup the iterator before removing and unrefing the blob
94 iter.prev(); 126 iter.prev();
95 fBlobList.remove(lruBlob); 127 fBlobList.remove(lruBlob);
96 lruBlob->unref(); 128 lruBlob->unref();
97 } 129 }
98 130
99 // If we break out of the loop with lruBlob == blob, then we haven't purged enough 131 // If we break out of the loop with lruBlob == blob, then we haven't purged enough
100 // use the call back and try to free some more. If we are still ove rbudget after this, 132 // use the call back and try to free some more. If we are still ove rbudget after this,
101 // then this single textblob is over our budget 133 // then this single textblob is over our budget
102 if (lruBlob == blob) { 134 if (blob && lruBlob == blob) {
103 (*fCallback)(fData); 135 (*fCallback)(fData);
104 } 136 }
105 137
106 #ifdef SK_DEBUG 138 #ifdef SPEW_BUDGET_MESSAGE
107 if (fPool.size() > kBudget) { 139 if (fPool.size() > fBudget) {
108 SkDebugf("Single textblob is larger than our whole budget"); 140 SkDebugf("Single textblob is larger than our whole budget");
109 } 141 }
110 #endif 142 #endif
111 } 143 }
112 } 144 }
113 145
114 void makeMRU(GrAtlasTextBlob* blob) {
115 if (fBlobList.head() == blob) {
116 return;
117 }
118
119 fBlobList.remove(blob);
120 fBlobList.addToHead(blob);
121 }
122
123 void freeAll();
124
125 // TODO move to SkTextBlob
126 static void BlobGlyphCount(int* glyphCount, int* runCount, const SkTextBlob* blob) {
127 SkTextBlob::RunIterator itCounter(blob);
128 for (; !itCounter.done(); itCounter.next(), (*runCount)++) {
129 *glyphCount += itCounter.glyphCount();
130 }
131 }
132
133 private:
134 typedef SkTInternalLList<GrAtlasTextBlob> BitmapBlobList;
135
136 // Budget was chosen to be ~4 megabytes. The min alloc and pre alloc sizes in the pool are 146 // Budget was chosen to be ~4 megabytes. The min alloc and pre alloc sizes in the pool are
137 // based off of the largest cached textblob I have seen in the skps(a couple of kilobytes). 147 // based off of the largest cached textblob I have seen in the skps(a couple of kilobytes).
138 static const int kPreAllocSize = 1 << 17; 148 static const int kPreAllocSize = 1 << 17;
139 static const int kMinGrowthSize = 1 << 17; 149 static const int kMinGrowthSize = 1 << 17;
140 static const int kBudget = 1 << 22; 150 static const int kDefaultBudget = 1 << 22;
141 BitmapBlobList fBlobList; 151 BitmapBlobList fBlobList;
142 SkTDynamicHash<GrAtlasTextBlob, GrAtlasTextBlob::Key> fCache; 152 SkTDynamicHash<GrAtlasTextBlob, GrAtlasTextBlob::Key> fCache;
143 GrMemoryPool fPool; 153 GrMemoryPool fPool;
144 PFOverBudgetCB fCallback; 154 PFOverBudgetCB fCallback;
145 void* fData; 155 void* fData;
156 size_t fBudget;
146 }; 157 };
147 158
148 #endif 159 #endif
OLDNEW
« no previous file with comments | « src/gpu/GrTest.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698