| Index: src/gpu/GrAtlas.cpp
|
| diff --git a/src/gpu/GrAtlas.cpp b/src/gpu/GrAtlas.cpp
|
| index 646c213b8675a738aa190daeece4ebc2088f49ab..c2fcf46f687b5656a71f0c02ca6cf82ca4e2a727 100644
|
| --- a/src/gpu/GrAtlas.cpp
|
| +++ b/src/gpu/GrAtlas.cpp
|
| @@ -35,10 +35,6 @@
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| -#ifdef SK_DEBUG
|
| - static int gCounter;
|
| -#endif
|
| -
|
| // for testing
|
| #define FONT_CACHE_STATS 0
|
| #if FONT_CACHE_STATS
|
| @@ -46,7 +42,6 @@ static int g_UploadCount = 0;
|
| #endif
|
|
|
| GrPlot::GrPlot() : fDrawToken(NULL, 0)
|
| - , fNext(NULL)
|
| , fTexture(NULL)
|
| , fAtlasMgr(NULL)
|
| , fBytesPerPixel(1)
|
| @@ -94,6 +89,11 @@ bool GrPlot::addSubImage(int width, int height, const void* image,
|
| return true;
|
| }
|
|
|
| +void GrPlot::resetRects() {
|
| + SkASSERT(NULL != fRects);
|
| + fRects->reset();
|
| +}
|
| +
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrPixelConfig config) {
|
| @@ -104,19 +104,17 @@ GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrPixelConfig config) {
|
|
|
| // set up allocated plots
|
| size_t bpp = GrBytesPerPixel(fPixelConfig);
|
| - fPlots = SkNEW_ARRAY(GrPlot, (GR_PLOT_WIDTH*GR_PLOT_HEIGHT));
|
| - fFreePlots = NULL;
|
| - GrPlot* currPlot = fPlots;
|
| + fPlotArray = SkNEW_ARRAY(GrPlot, (GR_PLOT_WIDTH*GR_PLOT_HEIGHT));
|
| +
|
| + GrPlot* currPlot = fPlotArray;
|
| for (int y = GR_PLOT_HEIGHT-1; y >= 0; --y) {
|
| for (int x = GR_PLOT_WIDTH-1; x >= 0; --x) {
|
| currPlot->fAtlasMgr = this;
|
| currPlot->fOffset.set(x, y);
|
| currPlot->fBytesPerPixel = bpp;
|
|
|
| - // add to free list
|
| - currPlot->fNext = fFreePlots;
|
| - fFreePlots = currPlot;
|
| -
|
| + // build LRU list
|
| + fPlotList.addToHead(currPlot);
|
| ++currPlot;
|
| }
|
| }
|
| @@ -124,7 +122,7 @@ GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrPixelConfig config) {
|
|
|
| GrAtlasMgr::~GrAtlasMgr() {
|
| SkSafeUnref(fTexture);
|
| - SkDELETE_ARRAY(fPlots);
|
| + SkDELETE_ARRAY(fPlotArray);
|
|
|
| fGpu->unref();
|
| #if FONT_CACHE_STATS
|
| @@ -132,25 +130,29 @@ GrAtlasMgr::~GrAtlasMgr() {
|
| #endif
|
| }
|
|
|
| +void GrAtlasMgr::moveToHead(GrPlot* plot) {
|
| + if (fPlotList.head() == plot) {
|
| + return;
|
| + }
|
| +
|
| + fPlotList.remove(plot);
|
| + fPlotList.addToHead(plot);
|
| +};
|
| +
|
| GrPlot* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
|
| int width, int height, const void* image,
|
| GrIPoint16* loc) {
|
| - // iterate through entire plot list, see if we can find a hole
|
| - GrPlot* plotIter = atlas->fPlots;
|
| - while (plotIter) {
|
| - if (plotIter->addSubImage(width, height, image, loc)) {
|
| - return plotIter;
|
| + // iterate through entire plot list for this atlas, see if we can find a hole
|
| + // last one was most recently added and probably most empty
|
| + for (int i = atlas->fPlots.count()-1; i >= 0; --i) {
|
| + GrPlot* plot = atlas->fPlots[i];
|
| + if (plot->addSubImage(width, height, image, loc)) {
|
| + this->moveToHead(plot);
|
| + return plot;
|
| }
|
| - plotIter = plotIter->fNext;
|
| - }
|
| -
|
| - // If the above fails, then either we have no starting plot, or the current
|
| - // plot list is full. Either way we need to allocate a new plot
|
| - GrPlot* newPlot = this->allocPlot();
|
| - if (NULL == newPlot) {
|
| - return NULL;
|
| }
|
|
|
| + // before we get a new plot, make sure we have a backing texture
|
| if (NULL == fTexture) {
|
| // TODO: Update this to use the cache rather than directly creating a texture.
|
| GrTextureDesc desc;
|
| @@ -164,77 +166,53 @@ GrPlot* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
|
| return NULL;
|
| }
|
| }
|
| - // be sure to set texture for fast lookup
|
| - newPlot->fTexture = fTexture;
|
|
|
| - if (!newPlot->addSubImage(width, height, image, loc)) {
|
| - this->freePlot(newPlot);
|
| - return NULL;
|
| + // now look through all allocated plots for one we can share, in MRU order
|
| + GrPlotList::Iter plotIter;
|
| + plotIter.init(fPlotList, GrPlotList::Iter::kHead_IterStart);
|
| + GrPlot* plot;
|
| + while (NULL != (plot = plotIter.get())) {
|
| + // make sure texture is set for quick lookup
|
| + plot->fTexture = fTexture;
|
| + if (plot->addSubImage(width, height, image, loc)) {
|
| + this->moveToHead(plot);
|
| + // new plot for atlas, put at end of array
|
| + *(atlas->fPlots.append()) = plot;
|
| + return plot;
|
| + }
|
| + plotIter.next();
|
| }
|
|
|
| - // new plot, put at head
|
| - newPlot->fNext = atlas->fPlots;
|
| - atlas->fPlots = newPlot;
|
| -
|
| - return newPlot;
|
| + // If the above fails, then the current plot list has no room
|
| + return NULL;
|
| }
|
|
|
| -bool GrAtlasMgr::removeUnusedPlots(GrAtlas* atlas) {
|
| -
|
| - // GrPlot** is used so that the head element can be easily
|
| - // modified when the first element is deleted
|
| - GrPlot** plotRef = &atlas->fPlots;
|
| - GrPlot* plot = atlas->fPlots;
|
| - bool removed = false;
|
| - while (NULL != plot) {
|
| - if (plot->drawToken().isIssued()) {
|
| - *plotRef = plot->fNext;
|
| - this->freePlot(plot);
|
| - plot = *plotRef;
|
| - removed = true;
|
| - } else {
|
| - plotRef = &plot->fNext;
|
| - plot = plot->fNext;
|
| +bool GrAtlasMgr::removePlot(GrAtlas* atlas, const GrPlot* plot) {
|
| + // iterate through plot list for this atlas
|
| + int count = atlas->fPlots.count();
|
| + for (int i = 0; i < count; ++i) {
|
| + if (plot == atlas->fPlots[i]) {
|
| + atlas->fPlots.remove(i);
|
| + return true;
|
| }
|
| }
|
|
|
| - return removed;
|
| -}
|
| -
|
| -void GrAtlasMgr::deletePlotList(GrPlot* plot) {
|
| - while (NULL != plot) {
|
| - GrPlot* next = plot->fNext;
|
| - this->freePlot(plot);
|
| - plot = next;
|
| - }
|
| + return false;
|
| }
|
|
|
| -GrPlot* GrAtlasMgr::allocPlot() {
|
| - if (NULL == fFreePlots) {
|
| - return NULL;
|
| - } else {
|
| - GrPlot* alloc = fFreePlots;
|
| - fFreePlots = alloc->fNext;
|
| -#ifdef SK_DEBUG
|
| -// GrPrintf(" GrPlot %p [%d %d] %d\n", this, alloc->fOffset.fX, alloc->fOffset.fY, gCounter);
|
| - gCounter += 1;
|
| -#endif
|
| - return alloc;
|
| +// get a plot that's not being used by the current draw
|
| +GrPlot* GrAtlasMgr::getUnusedPlot() {
|
| + GrPlotList::Iter plotIter;
|
| + plotIter.init(fPlotList, GrPlotList::Iter::kTail_IterStart);
|
| + GrPlot* plot;
|
| + while (NULL != (plot = plotIter.get())) {
|
| + if (plot->drawToken().isIssued()) {
|
| + return plot;
|
| + }
|
| + plotIter.prev();
|
| }
|
|
|
| -}
|
| -
|
| -void GrAtlasMgr::freePlot(GrPlot* plot) {
|
| - SkASSERT(this == plot->fAtlasMgr);
|
| -
|
| - plot->fRects->reset();
|
| - plot->fNext = fFreePlots;
|
| - fFreePlots = plot;
|
| -
|
| -#ifdef SK_DEBUG
|
| - --gCounter;
|
| -// GrPrintf("~GrPlot %p [%d %d] %d\n", this, plot->fOffset.fX, plot->fOffset.fY, gCounter);
|
| -#endif
|
| + return NULL;
|
| }
|
|
|
| SkISize GrAtlas::getSize() const {
|
|
|