*/
static void OverBudgetCB(void* data);
+ /**
+ * A callback similar to the above for use by the TextBlobCache
+ * TODO move textblob draw calls below context so we can use the call above.
+ */
+ static void TextBlobCacheOverBudgetCB(void* data);
+
// TODO see note on createTextContext
friend class SkGpuDevice;
// GrBatchFontCache will eventually replace GrFontCache
fBatchFontCache = SkNEW_ARGS(GrBatchFontCache, (this));
- fTextBlobCache.reset(SkNEW(GrTextBlobCache));
+ fTextBlobCache.reset(SkNEW_ARGS(GrTextBlobCache, (TextBlobCacheOverBudgetCB, this)));
}
GrContext::~GrContext() {
context->fFlushToReduceCacheSize = true;
}
+void GrContext::TextBlobCacheOverBudgetCB(void* data) {
+ SkASSERT(data);
+
+ // Unlike the GrResourceCache, TextBlobs are drawn at the SkGpuDevice level, therefore they
+ // cannot use fFlushTorReduceCacheSize because it uses AutoCheckFlush. The solution is to move
+ // drawText calls to below the GrContext level, but this is not trivial because they call
+ // drawPath on SkGpuDevice
+ GrContext* context = reinterpret_cast<GrContext*>(data);
+ context->flush();
+}
+
int GrContext::getMaxTextureSize() const {
return SkTMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride);
}
public:
typedef GrAtlasTextContext::BitmapTextBlob BitmapTextBlob;
- GrTextBlobCache() : fPool(kPreAllocSize, kMinGrowthSize) {}
+ /**
+ * The callback function used by the cache when it is still over budget after a purge. The
+ * passed in 'data' is the same 'data' handed to setOverbudgetCallback.
+ */
+ typedef void (*PFOverBudgetCB)(void* data);
+
+ GrTextBlobCache(PFOverBudgetCB cb, void* data)
+ : fPool(kPreAllocSize, kMinGrowthSize)
+ , fCallback(cb)
+ , fData(data) {
+ SkASSERT(cb && data);
+ }
~GrTextBlobCache();
// creates an uncached blob
iter.init(fBlobList, BitmapBlobList::Iter::kTail_IterStart);
BitmapTextBlob* lruBlob = iter.get();
SkASSERT(lruBlob);
- do {
+ while (fPool.size() > kBudget && (lruBlob = iter.get()) && lruBlob != blob) {
fCache.remove(lruBlob->fUniqueID);
fBlobList.remove(lruBlob);
- lruBlob->unref();
iter.prev();
- } while (fPool.size() > kBudget && (lruBlob = iter.get()));
+ lruBlob->unref();
+ }
+
+ // If we break out of the loop with lruBlob == blob, then we haven't purged enough
+ // use the call back and try to free some more. If we are still overbudget after this,
+ // then this single textblob is over our budget
+ if (lruBlob == blob) {
+ (*fCallback)(fData);
+ }
+
+#ifdef SK_DEBUG
+ if (fPool.size() > kBudget) {
+ SkDebugf("Single textblob is larger than our whole budget");
+ }
+#endif
}
}
// based off of the largest cached textblob I have seen in the skps(a couple of kilobytes).
static const int kPreAllocSize = 1 << 17;
static const int kMinGrowthSize = 1 << 17;
- static const int kBudget = 1 << 20;
+ static const int kBudget = 1 << 22;
BitmapBlobList fBlobList;
SkTDynamicHash<BitmapTextBlob, uint32_t> fCache;
GrMemoryPool fPool;
+ PFOverBudgetCB fCallback;
+ void* fData;
};
#endif