35 : fSizeBudget(kDefaultBudget)
36 , fMessageBusID(messageBusID)
37 , fPurgeBlobInbox(messageBusID) { }
48 blob->draw(canvas, glyphRunList.
origin(),
paint, atlasDelegate);
52 const GlyphRunList& glyphRunList,
56 positionMatrix.
preTranslate(glyphRunList.origin().x(), glyphRunList.origin().y());
59 glyphRunList,
paint, positionMatrix, strikeDeviceInfo);
65 if (blob ==
nullptr || !blob->canReuse(
paint, positionMatrix)) {
66 if (blob !=
nullptr) {
72 glyphRunList,
paint, positionMatrix,
79 blob = this->addOrReturnExisting(glyphRunList, blob);
86static void post_purge_blob_message(uint32_t blobID, uint32_t cacheID) {
95 blob = this->internalAdd(std::move(blob));
96 glyphRunList.temporaryShuntBlobNotifyAddedToCache(fMessageBusID, post_purge_blob_message);
102 const BlobIDCacheEntry* idEntry = fBlobIDCache.find(
key.fUniqueID);
103 if (idEntry ==
nullptr) {
109 if (blobPtr !=
nullptr && blobPtr != fBlobList.head()) {
110 fBlobList.remove(blobPtr);
111 fBlobList.addToHead(blobPtr);
116void TextBlobRedrawCoordinator::remove(
TextBlob* blob) {
118 this->internalRemove(blob);
121void TextBlobRedrawCoordinator::internalRemove(
TextBlob* blob) {
123 auto* idEntry = fBlobIDCache.find(
id);
125 if (idEntry !=
nullptr) {
127 if (blob == stillExists.
get()) {
128 fCurrentSize -= blob->
size();
129 fBlobList.remove(blob);
130 idEntry->removeBlob(blob);
131 if (idEntry->fBlobs.empty()) {
132 fBlobIDCache.remove(
id);
140 fBlobIDCache.reset();
147 this->internalPurgeStaleBlobs();
150void TextBlobRedrawCoordinator::internalPurgeStaleBlobs() {
152 fPurgeBlobInbox.poll(&msgs);
154 for (
const auto& msg : msgs) {
155 auto* idEntry = fBlobIDCache.find(msg.fBlobID);
162 for (
const auto& blob : idEntry->fBlobs) {
163 fCurrentSize -= blob->
size();
164 fBlobList.remove(blob.get());
168 fBlobIDCache.remove(msg.fBlobID);
179 return fCurrentSize > fSizeBudget;
182void TextBlobRedrawCoordinator::internalCheckPurge(
TextBlob* blob) {
184 this->internalPurgeStaleBlobs();
187 if (fCurrentSize > fSizeBudget) {
188 TextBlobList::Iter iter;
189 iter.init(fBlobList, TextBlobList::Iter::kTail_IterStart);
191 while (fCurrentSize > fSizeBudget && (lruBlob = iter.get()) && lruBlob != blob) {
195 this->internalRemove(lruBlob);
198 #ifdef SPEW_BUDGET_MESSAGE
199 if (fCurrentSize > fSizeBudget) {
200 SkDebugf(
"Single textblob is larger than our whole budget");
207 auto id = blob->key().fUniqueID;
208 auto* idEntry = fBlobIDCache.find(
id);
210 idEntry = fBlobIDCache.set(
id, BlobIDCacheEntry(
id));
213 if (
sk_sp<TextBlob> alreadyIn = idEntry->find(blob->key()); alreadyIn) {
214 blob = std::move(alreadyIn);
216 fBlobList.addToHead(blob.
get());
217 fCurrentSize += blob->size();
218 idEntry->addBlob(blob);
221 this->internalCheckPurge(blob.
get());
225TextBlobRedrawCoordinator::BlobIDCacheEntry::BlobIDCacheEntry() : fID(
SK_InvalidGenID) {}
227TextBlobRedrawCoordinator::BlobIDCacheEntry::BlobIDCacheEntry(uint32_t
id) : fID(
id) {}
229uint32_t TextBlobRedrawCoordinator::BlobIDCacheEntry::GetKey(
230 const TextBlobRedrawCoordinator::BlobIDCacheEntry& entry) {
234void TextBlobRedrawCoordinator::BlobIDCacheEntry::addBlob(
sk_sp<TextBlob> blob) {
236 SkASSERT(blob->key().fUniqueID == fID);
239 fBlobs.emplace_back(std::move(blob));
242void TextBlobRedrawCoordinator::BlobIDCacheEntry::removeBlob(
TextBlob* blob) {
246 auto index = this->findBlobIndex(blob->
key());
249 fBlobs.removeShuffle(index);
254 auto index = this->findBlobIndex(
key);
255 return index < 0 ? nullptr : fBlobs[index];
258int TextBlobRedrawCoordinator::BlobIDCacheEntry::findBlobIndex(
const TextBlob::Key&
key)
const {
259 for (
int i = 0;
i < fBlobs.size(); ++
i) {
bool SkShouldPostMessageToBus(const GrClientMappedBufferManager::BufferFinishedMessage &, GrDirectContext::DirectContextID potentialRecipient)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define DECLARE_SKMESSAGEBUS_MESSAGE(Message, IDType, AllowCopyableMessage)
static constexpr uint32_t SK_InvalidGenID
int find(T *array, int N, T item)
SkMatrix & preTranslate(SkScalar dx, SkScalar dy)
static void Post(Message m)
static SkStrikeCache * GlobalStrikeCache()
size_t usedBytes() const SK_EXCLUDES(fSpinLock)
bool isOverBudget() const SK_EXCLUDES(fSpinLock)
TextBlobRedrawCoordinator(uint32_t messageBusID)
void drawGlyphRunList(SkCanvas *canvas, const SkMatrix &viewMatrix, const GlyphRunList &glyphRunList, const SkPaint &paint, SkStrikeDeviceInfo strikeDeviceInfo, const AtlasDrawDelegate &)
void freeAll() SK_EXCLUDES(fSpinLock)
void purgeStaleBlobs() SK_EXCLUDES(fSpinLock)
static sk_sp< TextBlob > Make(const sktext::GlyphRunList &glyphRunList, const SkPaint &paint, const SkMatrix &positionMatrix, SkStrikeDeviceInfo strikeDeviceInfo, StrikeForGPUCacheInterface *strikeCache)
std::function< void(const sktext::gpu::AtlasSubRun *subRun, SkPoint drawOrigin, const SkPaint &paint, sk_sp< SkRefCnt > subRunStorage, sktext::gpu::RendererData)> AtlasDrawDelegate
static std::tuple< bool, Key > Make(const GlyphRunList &glyphRunList, const SkPaint &paint, const SkMatrix &drawMatrix, const SkStrikeDeviceInfo &strikeDevice)