bool GrFontCache::freeUnusedPlot(GrTextStrike* preserveStrike, const GrGlyph* glyph) { SkASSERT(preserveStrike); int index = mask_format_to_atlas_index(glyph->fMaskFormat); GrAtlas* atlas = fAtlases[index]; GrPlot* plot = atlas->getUnusedPlot(); if (NULL == plot) { return false; } plot->resetRects(); GrTextStrike* strike = fHead; while (strike) { GrTextStrike* strikeToPurge = strike; strike = strikeToPurge->fNext; strikeToPurge->removePlot(plot); // clear out any empty strikes (except this one) if (strikeToPurge != preserveStrike && strikeToPurge->fPlotUsage.isEmpty()) { this->purgeStrike(strikeToPurge); } } #if FONT_CACHE_STATS ++g_PurgeCount; #endif return true; }
bool GrFontCache::freeUnusedPlot(GrTextStrike* preserveStrike) { SkASSERT(preserveStrike); GrAtlas* atlas = preserveStrike->fAtlas; GrPlot* plot = atlas->getUnusedPlot(); if (NULL == plot) { return false; } plot->resetRects(); GrTextStrike* strike = fHead; GrMaskFormat maskFormat = preserveStrike->fMaskFormat; while (strike) { if (maskFormat != strike->fMaskFormat) { strike = strike->fNext; continue; } GrTextStrike* strikeToPurge = strike; strike = strikeToPurge->fNext; strikeToPurge->removePlot(plot); // clear out any empty strikes (except this one) if (strikeToPurge != preserveStrike && strikeToPurge->fPlotUsage.isEmpty()) { this->purgeStrike(strikeToPurge); } } #if FONT_CACHE_STATS ++g_PurgeCount; #endif return true; }
GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas** atlas, int width, int height, const void* image, GrMaskFormat format, GrIPoint16* loc) { SkASSERT(NULL == *atlas || (*atlas)->getMaskFormat() == format); // iterate through entire atlas list, see if we can find a hole GrAtlas* atlasIter = *atlas; while (atlasIter) { if (atlasIter->addSubImage(width, height, image, loc)) { return atlasIter; } atlasIter = atlasIter->fNext; } // If the above fails, then either we have no starting atlas, or the current // atlas list is full. Either way we need to allocate a new atlas GrIPoint16 plot; if (!fPlotMgr[format]->newPlot(&plot)) { return NULL; } SkASSERT(0 == kA8_GrMaskFormat); SkASSERT(1 == kA565_GrMaskFormat); if (NULL == fTexture[format]) { // TODO: Update this to use the cache rather than directly creating a texture. GrTextureDesc desc; desc.fFlags = kDynamicUpdate_GrTextureFlagBit; desc.fWidth = GR_ATLAS_TEXTURE_WIDTH; desc.fHeight = GR_ATLAS_TEXTURE_HEIGHT; desc.fConfig = maskformat2pixelconfig(format); fTexture[format] = fGpu->createTexture(desc, NULL, 0); if (NULL == fTexture[format]) { return NULL; } } GrAtlas* newAtlas = SkNEW_ARGS(GrAtlas, (this, plot.fX, plot.fY, format)); if (!newAtlas->addSubImage(width, height, image, loc)) { delete newAtlas; return NULL; } // new atlas, put at head newAtlas->fNext = *atlas; *atlas = newAtlas; return newAtlas; }
GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas, int width, int height, const void* image, GrMaskFormat format, GrIPoint16* loc) { GrAssert(NULL == atlas || atlas->getMaskFormat() == format); if (atlas && atlas->addSubImage(width, height, image, loc)) { return atlas; } // If the above fails, then either we have no starting atlas, or the current // one is full. Either way we need to allocate a new atlas GrIPoint16 plot; if (!fPlotMgr->newPlot(&plot)) { return NULL; } GrAssert(0 == kA8_GrMaskFormat); GrAssert(1 == kA565_GrMaskFormat); if (NULL == fTexture[format]) { GrTextureDesc desc = { kDynamicUpdate_GrTextureFlagBit, GR_ATLAS_TEXTURE_WIDTH, GR_ATLAS_TEXTURE_HEIGHT, maskformat2pixelconfig(format), 0 // samples }; fTexture[format] = fGpu->createTexture(desc, NULL, 0); if (NULL == fTexture[format]) { return NULL; } } GrAtlas* newAtlas = new GrAtlas(this, plot.fX, plot.fY, format); if (!newAtlas->addSubImage(width, height, image, loc)) { delete newAtlas; return NULL; } newAtlas->fNext = atlas; return newAtlas; }
bool GrAtlas::RemoveUnusedAtlases(GrAtlasMgr* atlasMgr, GrAtlas** startAtlas) { // GrAtlas** is used so that a pointer to the head element can be passed in and // modified when the first element is deleted GrAtlas** atlasRef = startAtlas; GrAtlas* atlas = *startAtlas; bool removed = false; while (NULL != atlas) { if (atlas->drawToken().isIssued()) { *atlasRef = atlas->fNext; atlasMgr->deleteAtlas(atlas); atlas = *atlasRef; removed = true; } else { atlasRef = &atlas->fNext; atlas = atlas->fNext; } } return removed; }