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

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

Issue 177463003: New approach for GPU font atlas (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Remove unnecessary method declarations. Created 6 years, 9 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
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 #include "GrAtlas.h" 9 #include "GrAtlas.h"
10 #include "GrContext.h" 10 #include "GrContext.h"
(...skipping 28 matching lines...) Expand all
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
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 }
OLDNEW
« src/gpu/GrAtlas.h ('K') | « src/gpu/GrAtlas.h ('k') | src/gpu/GrBitmapTextContext.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698