| Index: src/gpu/GrAtlas.cpp
|
| diff --git a/src/gpu/GrAtlas.cpp b/src/gpu/GrAtlas.cpp
|
| index b3340a02d985e03f0a3dbb3acaf7f09351b0a392..e33ec6519e26e09c717e4b2277773606b62c7b6e 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,70 +47,34 @@
|
| 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 adjust_for_offset(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) {
|
| +static uint8_t* zero_fill(uint8_t* ptr, int count) {
|
| while (--count >= 0) {
|
| *ptr++ = 0;
|
| }
|
| 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;
|
| @@ -128,16 +89,16 @@ bool GrAtlas::addSubImage(int width, int height, const void* image,
|
| sk_bzero(dst, dstRB); // zero top row
|
| dst += dstRB;
|
| for (int y = 0; y < height; y++) {
|
| - dst = zerofill(dst, fBytesPerPixel); // zero left edge
|
| + dst = zero_fill(dst, fBytesPerPixel); // zero left edge
|
| memcpy(dst, image, width * fBytesPerPixel);
|
| dst += width * fBytesPerPixel;
|
| - dst = zerofill(dst, fBytesPerPixel); // zero right edge
|
| + dst = zero_fill(dst, fBytesPerPixel); // zero right edge
|
| image = (const void*)((const char*)image + width * fBytesPerPixel);
|
| }
|
| sk_bzero(dst, dstRB); // zero bottom row
|
| image = storage.get();
|
| }
|
| - adjustForPlot(loc, fPlot);
|
| + adjust_for_offset(loc, fOffset);
|
| 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
|
| }
|
|
|