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

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 reference to GrAtlasMgr 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
« no previous file with comments | « src/gpu/GrAtlas.h ('k') | src/gpu/GrBitmapTextContext.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 17 matching lines...) Expand all
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
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 }
OLDNEW
« no previous file with comments | « src/gpu/GrAtlas.h ('k') | src/gpu/GrBitmapTextContext.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698