Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: src/gpu/GrAtlas.cpp

Issue 24981004: GrAtlas cleanup: Split out GrPlot and GrAtlas (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Add new GrPlot allocator Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
10
11 #include "GrAtlas.h" 9 #include "GrAtlas.h"
12 #include "GrContext.h" 10 #include "GrContext.h"
13 #include "GrGpu.h" 11 #include "GrGpu.h"
14 #include "GrRectanizer.h" 12 #include "GrRectanizer.h"
15 #include "GrPlotMgr.h"
16 13
17 #if 0 14 #if 0
18 #define GR_PLOT_WIDTH 8 15 #define GR_PLOT_WIDTH 8
19 #define GR_PLOT_HEIGHT 4 16 #define GR_PLOT_HEIGHT 4
20 #define GR_ATLAS_WIDTH 256 17 #define GR_ATLAS_WIDTH 256
21 #define GR_ATLAS_HEIGHT 256 18 #define GR_ATLAS_HEIGHT 256
22 19
23 #define GR_ATLAS_TEXTURE_WIDTH (GR_PLOT_WIDTH * GR_ATLAS_WIDTH) 20 #define GR_ATLAS_TEXTURE_WIDTH (GR_PLOT_WIDTH * GR_ATLAS_WIDTH)
24 #define GR_ATLAS_TEXTURE_HEIGHT (GR_PLOT_HEIGHT * GR_ATLAS_HEIGHT) 21 #define GR_ATLAS_TEXTURE_HEIGHT (GR_PLOT_HEIGHT * GR_ATLAS_HEIGHT)
25 22
(...skipping 17 matching lines...) Expand all
43 #ifdef SK_DEBUG 40 #ifdef SK_DEBUG
44 static int gCounter; 41 static int gCounter;
45 #endif 42 #endif
46 43
47 // for testing 44 // for testing
48 #define FONT_CACHE_STATS 0 45 #define FONT_CACHE_STATS 0
49 #if FONT_CACHE_STATS 46 #if FONT_CACHE_STATS
50 static int g_UploadCount = 0; 47 static int g_UploadCount = 0;
51 #endif 48 #endif
52 49
53 GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, int bpp) : 50 GrPlot::GrPlot() : fDrawToken(NULL, 0)
54 fDrawToken(NULL, 0) { 51 , fNext(NULL)
55 fAtlasMgr = mgr; // just a pointer, not an owner 52 , fTexture(NULL)
56 fNext = NULL; 53 , fAtlasMgr(NULL)
57 54 , fBytesPerPixel(1)
58 fTexture = mgr->getTexture(); // we're not an owner, just a pointer 55 {
59 fPlot.set(plotX, plotY);
60
61 fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER, 56 fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER,
62 GR_ATLAS_HEIGHT - BORDER); 57 GR_ATLAS_HEIGHT - BORDER);
63 58 fOffset.set(0, 0);
64 fBytesPerPixel = bpp;
65
66 #ifdef SK_DEBUG
67 // GrPrintf(" GrAtlas %p [%d %d] %d\n", this, plotX, plotY, gCounter);
68 gCounter += 1;
69 #endif
70 } 59 }
71 60
72 GrAtlas::~GrAtlas() { 61 GrPlot::~GrPlot() {
73 fAtlasMgr->freePlot(fPlot.fX, fPlot.fY);
74
75 delete fRects; 62 delete fRects;
76
77 #ifdef SK_DEBUG
78 --gCounter;
79 // GrPrintf("~GrAtlas %p [%d %d] %d\n", this, fPlot.fX, fPlot.fY, gCounter);
80 #endif
81 } 63 }
82 64
83 bool GrAtlas::RemoveUnusedAtlases(GrAtlasMgr* atlasMgr, GrAtlas** startAtlas) { 65 static void adjustForOffset(GrIPoint16* loc, const GrIPoint16& offset) {
84 // GrAtlas** is used so that a pointer to the head element can be passed in and 66 loc->fX += offset.fX * GR_ATLAS_WIDTH;
85 // modified when the first element is deleted 67 loc->fY += offset.fY * GR_ATLAS_HEIGHT;
86 GrAtlas** atlasRef = startAtlas;
87 GrAtlas* atlas = *startAtlas;
88 bool removed = false;
89 while (NULL != atlas) {
90 if (atlas->drawToken().isIssued()) {
91 *atlasRef = atlas->fNext;
92 atlasMgr->deleteAtlas(atlas);
93 atlas = *atlasRef;
94 removed = true;
95 } else {
96 atlasRef = &atlas->fNext;
97 atlas = atlas->fNext;
98 }
99 }
100
101 return removed;
102 }
103
104 static void adjustForPlot(GrIPoint16* loc, const GrIPoint16& plot) {
105 loc->fX += plot.fX * GR_ATLAS_WIDTH;
106 loc->fY += plot.fY * GR_ATLAS_HEIGHT;
107 } 68 }
108 69
109 static uint8_t* zerofill(uint8_t* ptr, int count) { 70 static uint8_t* zerofill(uint8_t* ptr, int count) {
110 while (--count >= 0) { 71 while (--count >= 0) {
111 *ptr++ = 0; 72 *ptr++ = 0;
112 } 73 }
113 return ptr; 74 return ptr;
114 } 75 }
115 76
116 bool GrAtlas::addSubImage(int width, int height, const void* image, 77 bool GrPlot::addSubImage(int width, int height, const void* image,
117 GrIPoint16* loc) { 78 GrIPoint16* loc) {
118 if (!fRects->addRect(width + BORDER, height + BORDER, loc)) { 79 if (!fRects->addRect(width + BORDER, height + BORDER, loc)) {
119 return false; 80 return false;
120 } 81 }
121 82
122 SkAutoSMalloc<1024> storage; 83 SkAutoSMalloc<1024> storage;
123 int dstW = width + 2*BORDER; 84 int dstW = width + 2*BORDER;
124 int dstH = height + 2*BORDER; 85 int dstH = height + 2*BORDER;
125 if (BORDER) { 86 if (BORDER) {
126 const size_t dstRB = dstW * fBytesPerPixel; 87 const size_t dstRB = dstW * fBytesPerPixel;
127 uint8_t* dst = (uint8_t*)storage.reset(dstH * dstRB); 88 uint8_t* dst = (uint8_t*)storage.reset(dstH * dstRB);
128 sk_bzero(dst, dstRB); // zero top row 89 sk_bzero(dst, dstRB); // zero top row
129 dst += dstRB; 90 dst += dstRB;
130 for (int y = 0; y < height; y++) { 91 for (int y = 0; y < height; y++) {
131 dst = zerofill(dst, fBytesPerPixel); // zero left edge 92 dst = zerofill(dst, fBytesPerPixel); // zero left edge
132 memcpy(dst, image, width * fBytesPerPixel); 93 memcpy(dst, image, width * fBytesPerPixel);
133 dst += width * fBytesPerPixel; 94 dst += width * fBytesPerPixel;
134 dst = zerofill(dst, fBytesPerPixel); // zero right edge 95 dst = zerofill(dst, fBytesPerPixel); // zero right edge
135 image = (const void*)((const char*)image + width * fBytesPerPixel); 96 image = (const void*)((const char*)image + width * fBytesPerPixel);
136 } 97 }
137 sk_bzero(dst, dstRB); // zero bottom row 98 sk_bzero(dst, dstRB); // zero bottom row
138 image = storage.get(); 99 image = storage.get();
139 } 100 }
140 adjustForPlot(loc, fPlot); 101 adjustForOffset(loc, fOffset);
bsalomon 2013/09/27 18:42:55 this->
jvanverth1 2013/09/27 19:12:54 It's static -- renamed the function.
141 GrContext* context = fTexture->getContext(); 102 GrContext* context = fTexture->getContext();
142 // We pass the flag that does not force a flush. We assume our caller is 103 // We pass the flag that does not force a flush. We assume our caller is
143 // smart and hasn't referenced the part of the texture we're about to update 104 // smart and hasn't referenced the part of the texture we're about to update
144 // since the last flush. 105 // since the last flush.
145 context->writeTexturePixels(fTexture, 106 context->writeTexturePixels(fTexture,
146 loc->fX, loc->fY, dstW, dstH, 107 loc->fX, loc->fY, dstW, dstH,
147 fTexture->config(), image, 0, 108 fTexture->config(), image, 0,
148 GrContext::kDontFlush_PixelOpsFlag); 109 GrContext::kDontFlush_PixelOpsFlag);
149 110
150 // now tell the caller to skip the top/left BORDER 111 // now tell the caller to skip the top/left BORDER
151 loc->fX += BORDER; 112 loc->fX += BORDER;
152 loc->fY += BORDER; 113 loc->fY += BORDER;
153 114
154 #if FONT_CACHE_STATS 115 #if FONT_CACHE_STATS
155 ++g_UploadCount; 116 ++g_UploadCount;
156 #endif 117 #endif
157 118
158 return true; 119 return true;
159 } 120 }
160 121
161 /////////////////////////////////////////////////////////////////////////////// 122 ///////////////////////////////////////////////////////////////////////////////
162 123
163 GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrPixelConfig config) { 124 GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrPixelConfig config) {
164 fGpu = gpu; 125 fGpu = gpu;
165 fPixelConfig = config; 126 fPixelConfig = config;
166 gpu->ref(); 127 gpu->ref();
167 fTexture = NULL; 128 fTexture = NULL;
168 fPlotMgr = SkNEW_ARGS(GrPlotMgr, (GR_PLOT_WIDTH, GR_PLOT_HEIGHT)); 129
130 // set up allocated plots
131 int bpp = GrBytesPerPixel(fPixelConfig);
132 fPlots = SkNEW_ARRAY(GrPlot, (GR_PLOT_WIDTH*GR_PLOT_HEIGHT));
133 fFreePlots = NULL;
134 GrPlot* currPlot = fPlots;
135 for (int y = GR_PLOT_HEIGHT-1; y >= 0; --y) {
136 for (int x = GR_PLOT_WIDTH-1; x >= 0; --x) {
137 currPlot->fAtlasMgr = this;
138 currPlot->fOffset.set(x, y);
139 currPlot->fBytesPerPixel = bpp;
140
141 // add to free list
142 currPlot->fNext = fFreePlots;
143 fFreePlots = currPlot;
144
145 ++currPlot;
146 }
147 }
169 } 148 }
170 149
171 GrAtlasMgr::~GrAtlasMgr() { 150 GrAtlasMgr::~GrAtlasMgr() {
172 SkSafeUnref(fTexture); 151 SkSafeUnref(fTexture);
173 delete fPlotMgr; 152 SkDELETE_ARRAY(fPlots);
174 153
175 fGpu->unref(); 154 fGpu->unref();
176 #if FONT_CACHE_STATS 155 #if FONT_CACHE_STATS
177 GrPrintf("Num uploads: %d\n", g_UploadCount); 156 GrPrintf("Num uploads: %d\n", g_UploadCount);
178 #endif 157 #endif
179 } 158 }
180 159
181 GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas** atlas, 160 GrPlot* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
182 int width, int height, const void* image, 161 int width, int height, const void* image,
183 GrIPoint16* loc) { 162 GrIPoint16* loc) {
184 // iterate through entire atlas list, see if we can find a hole 163 // iterate through entire plot list, see if we can find a hole
185 GrAtlas* atlasIter = *atlas; 164 GrPlot* plotIter = atlas->fPlots;
186 while (atlasIter) { 165 while (plotIter) {
187 if (atlasIter->addSubImage(width, height, image, loc)) { 166 if (plotIter->addSubImage(width, height, image, loc)) {
188 return atlasIter; 167 return plotIter;
189 } 168 }
190 atlasIter = atlasIter->fNext; 169 plotIter = plotIter->fNext;
191 } 170 }
192 171
193 // If the above fails, then either we have no starting atlas, or the current 172 // If the above fails, then either we have no starting plot, or the current
194 // atlas list is full. Either way we need to allocate a new atlas 173 // plot list is full. Either way we need to allocate a new plot
195 174 GrPlot* newPlot = this->allocPlot();
196 GrIPoint16 plot; 175 if (NULL == newPlot) {
197 if (!fPlotMgr->newPlot(&plot)) {
198 return NULL; 176 return NULL;
199 } 177 }
200 178
201 if (NULL == fTexture) { 179 if (NULL == fTexture) {
202 // TODO: Update this to use the cache rather than directly creating a te xture. 180 // TODO: Update this to use the cache rather than directly creating a te xture.
203 GrTextureDesc desc; 181 GrTextureDesc desc;
204 desc.fFlags = kDynamicUpdate_GrTextureFlagBit; 182 desc.fFlags = kDynamicUpdate_GrTextureFlagBit;
205 desc.fWidth = GR_ATLAS_TEXTURE_WIDTH; 183 desc.fWidth = GR_ATLAS_TEXTURE_WIDTH;
206 desc.fHeight = GR_ATLAS_TEXTURE_HEIGHT; 184 desc.fHeight = GR_ATLAS_TEXTURE_HEIGHT;
207 desc.fConfig = fPixelConfig; 185 desc.fConfig = fPixelConfig;
208 186
209 fTexture = fGpu->createTexture(desc, NULL, 0); 187 fTexture = fGpu->createTexture(desc, NULL, 0);
210 if (NULL == fTexture) { 188 if (NULL == fTexture) {
211 return NULL; 189 return NULL;
212 } 190 }
213 } 191 }
214 192 // be sure to set texture for fast lookup
215 int bpp = GrBytesPerPixel(fPixelConfig); 193 newPlot->fTexture = fTexture;
216 GrAtlas* newAtlas = SkNEW_ARGS(GrAtlas, (this, plot.fX, plot.fY, bpp)); 194
217 if (!newAtlas->addSubImage(width, height, image, loc)) { 195 if (!newPlot->addSubImage(width, height, image, loc)) {
218 delete newAtlas; 196 this->freePlot(newPlot);
219 return NULL; 197 return NULL;
220 } 198 }
221 199
222 // new atlas, put at head 200 // new plot, put at head
223 newAtlas->fNext = *atlas; 201 newPlot->fNext = atlas->fPlots;
224 *atlas = newAtlas; 202 atlas->fPlots = newPlot;
225 203
226 return newAtlas; 204 return newPlot;
227 } 205 }
228 206
229 void GrAtlasMgr::freePlot(int x, int y) { 207 bool GrAtlasMgr::removeUnusedPlots(GrAtlas* atlas) {
230 SkASSERT(fPlotMgr->isBusy(x, y)); 208 // GrPlot** is used so that the head element can be easily
231 fPlotMgr->freePlot(x, y); 209 // modified when the first element is deleted
210 GrPlot** plotRef = &atlas->fPlots;
211 GrPlot* plot = atlas->fPlots;
212 bool removed = false;
213 while (NULL != plot) {
214 if (plot->drawToken().isIssued()) {
215 *plotRef = plot->fNext;
216 this->freePlot(plot);
217 plot = *plotRef;
218 removed = true;
219 } else {
220 plotRef = &plot->fNext;
221 plot = plot->fNext;
222 }
223 }
224
225 return removed;
232 } 226 }
227
228 void GrAtlasMgr::deletePlotList(GrPlot* plot) {
229 while (NULL != plot) {
230 GrPlot* next = plot->fNext;
231 this->freePlot(plot);
232 plot = next;
233 }
234 }
235
236 GrPlot* GrAtlasMgr::allocPlot() {
237 if (NULL == fFreePlots) {
238 return NULL;
239 } else {
240 GrPlot* alloc = fFreePlots;
241 fFreePlots = alloc->fNext;
242 #ifdef SK_DEBUG
243 // GrPrintf(" GrPlot %p [%d %d] %d\n", this, alloc->fOffset.fX, alloc->fO ffset.fY, gCounter);
244 gCounter += 1;
245 #endif
246 return alloc;
247 }
248
249 }
250
251 void GrAtlasMgr::freePlot(GrPlot* plot) {
252 SkASSERT(this == plot->fAtlasMgr);
253
254 plot->fRects->reset();
255 plot->fNext = fFreePlots;
256 fFreePlots = plot;
257
258 #ifdef SK_DEBUG
259 --gCounter;
260 // GrPrintf("~GrPlot %p [%d %d] %d\n", this, plot->fOffset.fX, plot->fOffset. fY, gCounter);
261 #endif
262 }
OLDNEW
« src/gpu/GrAtlas.h ('K') | « src/gpu/GrAtlas.h ('k') | src/gpu/GrRectanizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698