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