Chromium Code Reviews| Index: src/gpu/GrAtlas.cpp |
| diff --git a/src/gpu/GrAtlas.cpp b/src/gpu/GrAtlas.cpp |
| index b3340a02d985e03f0a3dbb3acaf7f09351b0a392..ffb5148fd005a091bf7c8f32f748da36cb7dfbf0 100644 |
| --- a/src/gpu/GrAtlas.cpp |
| +++ b/src/gpu/GrAtlas.cpp |
| @@ -6,13 +6,10 @@ |
| * found in the LICENSE file. |
| */ |
| - |
| - |
| #include "GrAtlas.h" |
| #include "GrContext.h" |
| #include "GrGpu.h" |
| #include "GrRectanizer.h" |
| -#include "GrPlotMgr.h" |
| #if 0 |
| #define GR_PLOT_WIDTH 8 |
| @@ -50,60 +47,24 @@ |
| static int g_UploadCount = 0; |
| #endif |
| -GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, int bpp) : |
| - fDrawToken(NULL, 0) { |
| - fAtlasMgr = mgr; // just a pointer, not an owner |
| - fNext = NULL; |
| - |
| - fTexture = mgr->getTexture(); // we're not an owner, just a pointer |
| - fPlot.set(plotX, plotY); |
| - |
| +GrPlot::GrPlot() : fDrawToken(NULL, 0) |
| + , fNext(NULL) |
| + , fTexture(NULL) |
| + , fAtlasMgr(NULL) |
| + , fBytesPerPixel(1) |
| +{ |
| fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER, |
| GR_ATLAS_HEIGHT - BORDER); |
| - |
| - fBytesPerPixel = bpp; |
| - |
| -#ifdef SK_DEBUG |
| -// GrPrintf(" GrAtlas %p [%d %d] %d\n", this, plotX, plotY, gCounter); |
| - gCounter += 1; |
| -#endif |
| + fOffset.set(0, 0); |
| } |
| -GrAtlas::~GrAtlas() { |
| - fAtlasMgr->freePlot(fPlot.fX, fPlot.fY); |
| - |
| +GrPlot::~GrPlot() { |
| delete fRects; |
| - |
| -#ifdef SK_DEBUG |
| - --gCounter; |
| -// GrPrintf("~GrAtlas %p [%d %d] %d\n", this, fPlot.fX, fPlot.fY, gCounter); |
| -#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->drawToken().isIssued()) { |
| - *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; |
| +static void adjustForOffset(GrIPoint16* loc, const GrIPoint16& offset) { |
| + loc->fX += offset.fX * GR_ATLAS_WIDTH; |
| + loc->fY += offset.fY * GR_ATLAS_HEIGHT; |
| } |
| static uint8_t* zerofill(uint8_t* ptr, int count) { |
| @@ -113,7 +74,7 @@ static uint8_t* zerofill(uint8_t* ptr, int count) { |
| return ptr; |
| } |
| -bool GrAtlas::addSubImage(int width, int height, const void* image, |
| +bool GrPlot::addSubImage(int width, int height, const void* image, |
| GrIPoint16* loc) { |
| if (!fRects->addRect(width + BORDER, height + BORDER, loc)) { |
| return false; |
| @@ -137,7 +98,7 @@ bool GrAtlas::addSubImage(int width, int height, const void* image, |
| sk_bzero(dst, dstRB); // zero bottom row |
| image = storage.get(); |
| } |
| - adjustForPlot(loc, fPlot); |
| + adjustForOffset(loc, fOffset); |
|
bsalomon
2013/09/27 18:42:55
this->
jvanverth1
2013/09/27 19:12:54
It's static -- renamed the function.
|
| GrContext* context = fTexture->getContext(); |
| // We pass the flag that does not force a flush. We assume our caller is |
| // smart and hasn't referenced the part of the texture we're about to update |
| @@ -165,12 +126,30 @@ GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrPixelConfig config) { |
| fPixelConfig = config; |
| gpu->ref(); |
| fTexture = NULL; |
| - fPlotMgr = SkNEW_ARGS(GrPlotMgr, (GR_PLOT_WIDTH, GR_PLOT_HEIGHT)); |
| + |
| + // set up allocated plots |
| + int bpp = GrBytesPerPixel(fPixelConfig); |
| + fPlots = SkNEW_ARRAY(GrPlot, (GR_PLOT_WIDTH*GR_PLOT_HEIGHT)); |
| + fFreePlots = NULL; |
| + GrPlot* currPlot = fPlots; |
| + 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; |
| + |
| + ++currPlot; |
| + } |
| + } |
| } |
| GrAtlasMgr::~GrAtlasMgr() { |
| SkSafeUnref(fTexture); |
| - delete fPlotMgr; |
| + SkDELETE_ARRAY(fPlots); |
| fGpu->unref(); |
| #if FONT_CACHE_STATS |
| @@ -178,23 +157,22 @@ GrAtlasMgr::~GrAtlasMgr() { |
| #endif |
| } |
| -GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas** atlas, |
| - int width, int height, const void* image, |
| - GrIPoint16* loc) { |
| - // 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; |
| +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; |
| } |
| - atlasIter = atlasIter->fNext; |
| + plotIter = plotIter->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->newPlot(&plot)) { |
| + // 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; |
| } |
| @@ -211,22 +189,74 @@ GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas** atlas, |
| return NULL; |
| } |
| } |
| - |
| - int bpp = GrBytesPerPixel(fPixelConfig); |
| - GrAtlas* newAtlas = SkNEW_ARGS(GrAtlas, (this, plot.fX, plot.fY, bpp)); |
| - if (!newAtlas->addSubImage(width, height, image, loc)) { |
| - delete newAtlas; |
| + // be sure to set texture for fast lookup |
| + newPlot->fTexture = fTexture; |
| + |
| + if (!newPlot->addSubImage(width, height, image, loc)) { |
| + this->freePlot(newPlot); |
| return NULL; |
| } |
| - // new atlas, put at head |
| - newAtlas->fNext = *atlas; |
| - *atlas = newAtlas; |
| + // new plot, put at head |
| + newPlot->fNext = atlas->fPlots; |
| + atlas->fPlots = newPlot; |
| - return newAtlas; |
| + return newPlot; |
| +} |
| + |
| +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; |
| + } |
| + } |
| + |
| + return removed; |
| } |
| -void GrAtlasMgr::freePlot(int x, int y) { |
| - SkASSERT(fPlotMgr->isBusy(x, y)); |
| - fPlotMgr->freePlot(x, y); |
| +void GrAtlasMgr::deletePlotList(GrPlot* plot) { |
| + while (NULL != plot) { |
| + GrPlot* next = plot->fNext; |
| + this->freePlot(plot); |
| + plot = next; |
| + } |
| +} |
| + |
| +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; |
| + } |
| + |
| +} |
| + |
| +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 |
| } |