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 |