| Index: src/gpu/GrAtlas.cpp
|
| diff --git a/src/gpu/GrAtlas.cpp b/src/gpu/GrAtlas.cpp
|
| index c1d6d3d693c4f332907a996874d1f72ed7231cae..f2daca11c5879340a0c9cb05e0b6724d80aafff6 100644
|
| --- a/src/gpu/GrAtlas.cpp
|
| +++ b/src/gpu/GrAtlas.cpp
|
| @@ -44,9 +44,17 @@
|
| static int gCounter;
|
| #endif
|
|
|
| +// for testing
|
| +#define FONT_CACHE_STATS 0
|
| +#if FONT_CACHE_STATS
|
| +static int g_UploadCount = 0;
|
| +#endif
|
| +
|
| GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, GrMaskFormat format) {
|
| fAtlasMgr = mgr; // just a pointer, not an owner
|
| fNext = NULL;
|
| + fUsed = false;
|
| +
|
| fTexture = mgr->getTexture(format); // we're not an owner, just a pointer
|
| fPlot.set(plotX, plotY);
|
|
|
| @@ -62,7 +70,7 @@ GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, GrMaskFormat format) {
|
| }
|
|
|
| GrAtlas::~GrAtlas() {
|
| - fAtlasMgr->freePlot(fPlot.fX, fPlot.fY);
|
| + fAtlasMgr->freePlot(fMaskFormat, fPlot.fX, fPlot.fY);
|
|
|
| delete fRects;
|
|
|
| @@ -72,6 +80,27 @@ GrAtlas::~GrAtlas() {
|
| #endif
|
| }
|
|
|
| +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->used()) {
|
| + *atlasRef = atlas->fNext;
|
| + atlasMgr->deleteAtlas(atlas);
|
| + atlas = *atlasRef;
|
| + removed = true;
|
| + } else {
|
| + atlasRef = &atlas->fNext;
|
| + atlas = atlas->fNext;
|
| + }
|
| + }
|
| +
|
| + return removed;
|
| +}
|
| +
|
| static void adjustForPlot(GrIPoint16* loc, const GrIPoint16& plot) {
|
| loc->fX += plot.fX * GR_ATLAS_WIDTH;
|
| loc->fY += plot.fY * GR_ATLAS_HEIGHT;
|
| @@ -122,6 +151,11 @@ bool GrAtlas::addSubImage(int width, int height, const void* image,
|
| // now tell the caller to skip the top/left BORDER
|
| loc->fX += BORDER;
|
| loc->fY += BORDER;
|
| +
|
| +#if FONT_CACHE_STATS
|
| + ++g_UploadCount;
|
| +#endif
|
| +
|
| return true;
|
| }
|
|
|
| @@ -139,7 +173,11 @@ GrAtlasMgr::~GrAtlasMgr() {
|
| GrSafeUnref(fTexture[i]);
|
| }
|
| delete fPlotMgr;
|
| +
|
| fGpu->unref();
|
| +#if FONT_CACHE_STATS
|
| + GrPrintf("Num uploads: %d\n", g_UploadCount);
|
| +#endif
|
| }
|
|
|
| static GrPixelConfig maskformat2pixelconfig(GrMaskFormat format) {
|
| @@ -156,18 +194,23 @@ static GrPixelConfig maskformat2pixelconfig(GrMaskFormat format) {
|
| return kUnknown_GrPixelConfig;
|
| }
|
|
|
| -GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
|
| +GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas** atlas,
|
| int width, int height, const void* image,
|
| GrMaskFormat format,
|
| GrIPoint16* loc) {
|
| - GrAssert(NULL == atlas || atlas->getMaskFormat() == format);
|
| + GrAssert(NULL == *atlas || (*atlas)->getMaskFormat() == format);
|
|
|
| - if (atlas && atlas->addSubImage(width, height, image, loc)) {
|
| - return atlas;
|
| + // 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
|
| - // one is full. Either way we need to allocate a new atlas
|
| + // atlas list is full. Either way we need to allocate a new atlas
|
|
|
| GrIPoint16 plot;
|
| if (!fPlotMgr->newPlot(&plot)) {
|
| @@ -196,11 +239,14 @@ GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
|
| return NULL;
|
| }
|
|
|
| - newAtlas->fNext = atlas;
|
| + // new atlas, put at head
|
| + newAtlas->fNext = *atlas;
|
| + *atlas = newAtlas;
|
| +
|
| return newAtlas;
|
| }
|
|
|
| -void GrAtlasMgr::freePlot(int x, int y) {
|
| +void GrAtlasMgr::freePlot(GrMaskFormat format, int x, int y) {
|
| GrAssert(fPlotMgr->isBusy(x, y));
|
| fPlotMgr->freePlot(x, y);
|
| }
|
|
|