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); |
} |