| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2010 Google Inc. | 3 * Copyright 2010 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #include "GrAtlas.h" | 9 #include "GrAtlas.h" |
| 10 #include "GrContext.h" | 10 #include "GrContext.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 #define GR_ATLAS_WIDTH 256 | 28 #define GR_ATLAS_WIDTH 256 |
| 29 #define GR_ATLAS_HEIGHT 256 | 29 #define GR_ATLAS_HEIGHT 256 |
| 30 | 30 |
| 31 #define GR_PLOT_WIDTH (GR_ATLAS_TEXTURE_WIDTH / GR_ATLAS_WIDTH) | 31 #define GR_PLOT_WIDTH (GR_ATLAS_TEXTURE_WIDTH / GR_ATLAS_WIDTH) |
| 32 #define GR_PLOT_HEIGHT (GR_ATLAS_TEXTURE_HEIGHT / GR_ATLAS_HEIGHT) | 32 #define GR_PLOT_HEIGHT (GR_ATLAS_TEXTURE_HEIGHT / GR_ATLAS_HEIGHT) |
| 33 | 33 |
| 34 #endif | 34 #endif |
| 35 | 35 |
| 36 /////////////////////////////////////////////////////////////////////////////// | 36 /////////////////////////////////////////////////////////////////////////////// |
| 37 | 37 |
| 38 #ifdef SK_DEBUG | |
| 39 static int gCounter; | |
| 40 #endif | |
| 41 | |
| 42 // for testing | 38 // for testing |
| 43 #define FONT_CACHE_STATS 0 | 39 #define FONT_CACHE_STATS 0 |
| 44 #if FONT_CACHE_STATS | 40 #if FONT_CACHE_STATS |
| 45 static int g_UploadCount = 0; | 41 static int g_UploadCount = 0; |
| 46 #endif | 42 #endif |
| 47 | 43 |
| 48 GrPlot::GrPlot() : fDrawToken(NULL, 0) | 44 GrPlot::GrPlot() : fDrawToken(NULL, 0) |
| 49 , fNext(NULL) | |
| 50 , fTexture(NULL) | 45 , fTexture(NULL) |
| 51 , fAtlasMgr(NULL) | 46 , fAtlasMgr(NULL) |
| 52 , fBytesPerPixel(1) | 47 , fBytesPerPixel(1) |
| 53 { | 48 { |
| 54 fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH, | 49 fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH, |
| 55 GR_ATLAS_HEIGHT); | 50 GR_ATLAS_HEIGHT); |
| 56 fOffset.set(0, 0); | 51 fOffset.set(0, 0); |
| 57 } | 52 } |
| 58 | 53 |
| 59 GrPlot::~GrPlot() { | 54 GrPlot::~GrPlot() { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 87 fTexture->config(), image, 0, | 82 fTexture->config(), image, 0, |
| 88 GrContext::kDontFlush_PixelOpsFlag); | 83 GrContext::kDontFlush_PixelOpsFlag); |
| 89 | 84 |
| 90 #if FONT_CACHE_STATS | 85 #if FONT_CACHE_STATS |
| 91 ++g_UploadCount; | 86 ++g_UploadCount; |
| 92 #endif | 87 #endif |
| 93 | 88 |
| 94 return true; | 89 return true; |
| 95 } | 90 } |
| 96 | 91 |
| 92 void GrPlot::resetRects() { |
| 93 SkASSERT(NULL != fRects); |
| 94 fRects->reset(); |
| 95 } |
| 96 |
| 97 /////////////////////////////////////////////////////////////////////////////// | 97 /////////////////////////////////////////////////////////////////////////////// |
| 98 | 98 |
| 99 GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrPixelConfig config) { | 99 GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrPixelConfig config) { |
| 100 fGpu = gpu; | 100 fGpu = gpu; |
| 101 fPixelConfig = config; | 101 fPixelConfig = config; |
| 102 gpu->ref(); | 102 gpu->ref(); |
| 103 fTexture = NULL; | 103 fTexture = NULL; |
| 104 | 104 |
| 105 // set up allocated plots | 105 // set up allocated plots |
| 106 size_t bpp = GrBytesPerPixel(fPixelConfig); | 106 size_t bpp = GrBytesPerPixel(fPixelConfig); |
| 107 fPlots = SkNEW_ARRAY(GrPlot, (GR_PLOT_WIDTH*GR_PLOT_HEIGHT)); | 107 fPlotArray = SkNEW_ARRAY(GrPlot, (GR_PLOT_WIDTH*GR_PLOT_HEIGHT)); |
| 108 fFreePlots = NULL; | 108 |
| 109 GrPlot* currPlot = fPlots; | 109 GrPlot* currPlot = fPlotArray; |
| 110 for (int y = GR_PLOT_HEIGHT-1; y >= 0; --y) { | 110 for (int y = GR_PLOT_HEIGHT-1; y >= 0; --y) { |
| 111 for (int x = GR_PLOT_WIDTH-1; x >= 0; --x) { | 111 for (int x = GR_PLOT_WIDTH-1; x >= 0; --x) { |
| 112 currPlot->fAtlasMgr = this; | 112 currPlot->fAtlasMgr = this; |
| 113 currPlot->fOffset.set(x, y); | 113 currPlot->fOffset.set(x, y); |
| 114 currPlot->fBytesPerPixel = bpp; | 114 currPlot->fBytesPerPixel = bpp; |
| 115 | 115 |
| 116 // add to free list | 116 // build LRU list |
| 117 currPlot->fNext = fFreePlots; | 117 fPlotList.addToHead(currPlot); |
| 118 fFreePlots = currPlot; | |
| 119 | |
| 120 ++currPlot; | 118 ++currPlot; |
| 121 } | 119 } |
| 122 } | 120 } |
| 123 } | 121 } |
| 124 | 122 |
| 125 GrAtlasMgr::~GrAtlasMgr() { | 123 GrAtlasMgr::~GrAtlasMgr() { |
| 126 SkSafeUnref(fTexture); | 124 SkSafeUnref(fTexture); |
| 127 SkDELETE_ARRAY(fPlots); | 125 SkDELETE_ARRAY(fPlotArray); |
| 128 | 126 |
| 129 fGpu->unref(); | 127 fGpu->unref(); |
| 130 #if FONT_CACHE_STATS | 128 #if FONT_CACHE_STATS |
| 131 GrPrintf("Num uploads: %d\n", g_UploadCount); | 129 GrPrintf("Num uploads: %d\n", g_UploadCount); |
| 132 #endif | 130 #endif |
| 133 } | 131 } |
| 134 | 132 |
| 133 void GrAtlasMgr::moveToHead(GrPlot* plot) { |
| 134 if (fPlotList.head() == plot) { |
| 135 return; |
| 136 } |
| 137 |
| 138 fPlotList.remove(plot); |
| 139 fPlotList.addToHead(plot); |
| 140 }; |
| 141 |
| 135 GrPlot* GrAtlasMgr::addToAtlas(GrAtlas* atlas, | 142 GrPlot* GrAtlasMgr::addToAtlas(GrAtlas* atlas, |
| 136 int width, int height, const void* image, | 143 int width, int height, const void* image, |
| 137 GrIPoint16* loc) { | 144 GrIPoint16* loc) { |
| 138 // iterate through entire plot list, see if we can find a hole | 145 // iterate through entire plot list for this atlas, see if we can find a hol
e |
| 139 GrPlot* plotIter = atlas->fPlots; | 146 // last one was most recently added and probably most empty |
| 140 while (plotIter) { | 147 for (int i = atlas->fPlots.count()-1; i >= 0; --i) { |
| 141 if (plotIter->addSubImage(width, height, image, loc)) { | 148 GrPlot* plot = atlas->fPlots[i]; |
| 142 return plotIter; | 149 if (plot->addSubImage(width, height, image, loc)) { |
| 150 this->moveToHead(plot); |
| 151 return plot; |
| 143 } | 152 } |
| 144 plotIter = plotIter->fNext; | |
| 145 } | 153 } |
| 146 | 154 |
| 147 // If the above fails, then either we have no starting plot, or the current | 155 // before we get a new plot, make sure we have a backing texture |
| 148 // plot list is full. Either way we need to allocate a new plot | |
| 149 GrPlot* newPlot = this->allocPlot(); | |
| 150 if (NULL == newPlot) { | |
| 151 return NULL; | |
| 152 } | |
| 153 | |
| 154 if (NULL == fTexture) { | 156 if (NULL == fTexture) { |
| 155 // TODO: Update this to use the cache rather than directly creating a te
xture. | 157 // TODO: Update this to use the cache rather than directly creating a te
xture. |
| 156 GrTextureDesc desc; | 158 GrTextureDesc desc; |
| 157 desc.fFlags = kDynamicUpdate_GrTextureFlagBit; | 159 desc.fFlags = kDynamicUpdate_GrTextureFlagBit; |
| 158 desc.fWidth = GR_ATLAS_TEXTURE_WIDTH; | 160 desc.fWidth = GR_ATLAS_TEXTURE_WIDTH; |
| 159 desc.fHeight = GR_ATLAS_TEXTURE_HEIGHT; | 161 desc.fHeight = GR_ATLAS_TEXTURE_HEIGHT; |
| 160 desc.fConfig = fPixelConfig; | 162 desc.fConfig = fPixelConfig; |
| 161 | 163 |
| 162 fTexture = fGpu->createTexture(desc, NULL, 0); | 164 fTexture = fGpu->createTexture(desc, NULL, 0); |
| 163 if (NULL == fTexture) { | 165 if (NULL == fTexture) { |
| 164 return NULL; | 166 return NULL; |
| 165 } | 167 } |
| 166 } | 168 } |
| 167 // be sure to set texture for fast lookup | |
| 168 newPlot->fTexture = fTexture; | |
| 169 | 169 |
| 170 if (!newPlot->addSubImage(width, height, image, loc)) { | 170 // now look through all allocated plots for one we can share, in MRU order |
| 171 this->freePlot(newPlot); | 171 GrPlotList::Iter plotIter; |
| 172 return NULL; | 172 plotIter.init(fPlotList, GrPlotList::Iter::kHead_IterStart); |
| 173 GrPlot* plot; |
| 174 while (NULL != (plot = plotIter.get())) { |
| 175 // make sure texture is set for quick lookup |
| 176 plot->fTexture = fTexture; |
| 177 if (plot->addSubImage(width, height, image, loc)) { |
| 178 this->moveToHead(plot); |
| 179 // new plot for atlas, put at end of array |
| 180 *(atlas->fPlots.append()) = plot; |
| 181 return plot; |
| 182 } |
| 183 plotIter.next(); |
| 173 } | 184 } |
| 174 | 185 |
| 175 // new plot, put at head | 186 // If the above fails, then the current plot list has no room |
| 176 newPlot->fNext = atlas->fPlots; | 187 return NULL; |
| 177 atlas->fPlots = newPlot; | |
| 178 | |
| 179 return newPlot; | |
| 180 } | 188 } |
| 181 | 189 |
| 182 bool GrAtlasMgr::removeUnusedPlots(GrAtlas* atlas) { | 190 bool GrAtlasMgr::removePlot(GrAtlas* atlas, const GrPlot* plot) { |
| 183 | 191 // iterate through plot list for this atlas |
| 184 // GrPlot** is used so that the head element can be easily | 192 int count = atlas->fPlots.count(); |
| 185 // modified when the first element is deleted | 193 for (int i = 0; i < count; ++i) { |
| 186 GrPlot** plotRef = &atlas->fPlots; | 194 if (plot == atlas->fPlots[i]) { |
| 187 GrPlot* plot = atlas->fPlots; | 195 atlas->fPlots.remove(i); |
| 188 bool removed = false; | 196 return true; |
| 189 while (NULL != plot) { | |
| 190 if (plot->drawToken().isIssued()) { | |
| 191 *plotRef = plot->fNext; | |
| 192 this->freePlot(plot); | |
| 193 plot = *plotRef; | |
| 194 removed = true; | |
| 195 } else { | |
| 196 plotRef = &plot->fNext; | |
| 197 plot = plot->fNext; | |
| 198 } | 197 } |
| 199 } | 198 } |
| 200 | 199 |
| 201 return removed; | 200 return false; |
| 202 } | 201 } |
| 203 | 202 |
| 204 void GrAtlasMgr::deletePlotList(GrPlot* plot) { | 203 // get a plot that's not being used by the current draw |
| 205 while (NULL != plot) { | 204 GrPlot* GrAtlasMgr::getUnusedPlot() { |
| 206 GrPlot* next = plot->fNext; | 205 GrPlotList::Iter plotIter; |
| 207 this->freePlot(plot); | 206 plotIter.init(fPlotList, GrPlotList::Iter::kTail_IterStart); |
| 208 plot = next; | 207 GrPlot* plot; |
| 209 } | 208 while (NULL != (plot = plotIter.get())) { |
| 210 } | 209 if (plot->drawToken().isIssued()) { |
| 211 | 210 return plot; |
| 212 GrPlot* GrAtlasMgr::allocPlot() { | 211 } |
| 213 if (NULL == fFreePlots) { | 212 plotIter.prev(); |
| 214 return NULL; | |
| 215 } else { | |
| 216 GrPlot* alloc = fFreePlots; | |
| 217 fFreePlots = alloc->fNext; | |
| 218 #ifdef SK_DEBUG | |
| 219 // GrPrintf(" GrPlot %p [%d %d] %d\n", this, alloc->fOffset.fX, alloc->fO
ffset.fY, gCounter); | |
| 220 gCounter += 1; | |
| 221 #endif | |
| 222 return alloc; | |
| 223 } | 213 } |
| 224 | 214 |
| 225 } | 215 return NULL; |
| 226 | |
| 227 void GrAtlasMgr::freePlot(GrPlot* plot) { | |
| 228 SkASSERT(this == plot->fAtlasMgr); | |
| 229 | |
| 230 plot->fRects->reset(); | |
| 231 plot->fNext = fFreePlots; | |
| 232 fFreePlots = plot; | |
| 233 | |
| 234 #ifdef SK_DEBUG | |
| 235 --gCounter; | |
| 236 // GrPrintf("~GrPlot %p [%d %d] %d\n", this, plot->fOffset.fX, plot->fOffset.
fY, gCounter); | |
| 237 #endif | |
| 238 } | 216 } |
| 239 | 217 |
| 240 SkISize GrAtlas::getSize() const { | 218 SkISize GrAtlas::getSize() const { |
| 241 return SkISize::Make(GR_ATLAS_TEXTURE_WIDTH, GR_ATLAS_TEXTURE_HEIGHT); | 219 return SkISize::Make(GR_ATLAS_TEXTURE_WIDTH, GR_ATLAS_TEXTURE_HEIGHT); |
| 242 } | 220 } |
| OLD | NEW |