aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrAtlas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/GrAtlas.cpp')
-rw-r--r--src/gpu/GrAtlas.cpp196
1 files changed, 113 insertions, 83 deletions
diff --git a/src/gpu/GrAtlas.cpp b/src/gpu/GrAtlas.cpp
index b3340a02d9..e33ec6519e 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
}