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

Side by Side Diff: src/gpu/GrAllocator.h

Issue 362023002: Reduce integer divides in GrAllocator (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: iter getters Created 6 years, 5 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 | « no previous file | src/gpu/GrDrawState.h » ('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 * Copyright 2010 Google Inc. 2 * Copyright 2010 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef GrAllocator_DEFINED 8 #ifndef GrAllocator_DEFINED
9 #define GrAllocator_DEFINED 9 #define GrAllocator_DEFINED
10 10
11 #include "GrConfig.h" 11 #include "GrConfig.h"
12 #include "GrTypes.h" 12 #include "GrTypes.h"
13 #include "SkTArray.h" 13 #include "SkTArray.h"
14 #include "SkTypes.h" 14 #include "SkTypes.h"
15 15
16 class GrAllocator : SkNoncopyable { 16 class GrAllocator : SkNoncopyable {
17 public: 17 public:
18 ~GrAllocator() { 18 ~GrAllocator() { this->reset(); }
19 reset();
20 }
21 19
22 /** 20 /**
23 * Create an allocator 21 * Create an allocator
24 * 22 *
25 * @param itemSize the size of each item to allocate 23 * @param itemSize the size of each item to allocate
26 * @param itemsPerBlock the number of items to allocate at once 24 * @param itemsPerBlock the number of items to allocate at once
27 * @param initialBlock optional memory to use for the first block. 25 * @param initialBlock optional memory to use for the first block.
28 * Must be at least itemSize*itemsPerBlock sized. 26 * Must be at least itemSize*itemsPerBlock sized.
29 * Caller is responsible for freeing this memory. 27 * Caller is responsible for freeing this memory.
30 */ 28 */
31 GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) : 29 GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock)
32 fItemSize(itemSize), 30 : fItemSize(itemSize)
33 fItemsPerBlock(itemsPerBlock), 31 , fItemsPerBlock(itemsPerBlock)
34 fOwnFirstBlock(NULL == initialBlock), 32 , fOwnFirstBlock(NULL == initialBlock)
35 fCount(0) { 33 , fCount(0)
34 , fInsertionIndexInBlock(0) {
36 SkASSERT(itemsPerBlock > 0); 35 SkASSERT(itemsPerBlock > 0);
37 fBlockSize = fItemSize * fItemsPerBlock; 36 fBlockSize = fItemSize * fItemsPerBlock;
38 fBlocks.push_back() = initialBlock; 37 if (fOwnFirstBlock) {
39 SkDEBUGCODE(if (!fOwnFirstBlock) {*((char*)initialBlock+fBlockSize-1)='a ';} ); 38 // This force us to allocate a new block on push_back().
40 } 39 fInsertionIndexInBlock = fItemsPerBlock;
41 40 } else {
42 /* 41 fBlocks.push_back() = initialBlock;
43 * Set first block of memory to write into. Must be called before any other methods. 42 fInsertionIndexInBlock = 0;
44 * This requires that you have passed NULL in the constructor. 43 }
45 *
46 * @param initialBlock optional memory to use for the first block.
47 * Must be at least itemSize*itemsPerBlock sized.
48 * Caller is responsible for freeing this memory.
49 */
50 void setInitialBlock(void* initialBlock) {
51 SkASSERT(0 == fCount);
52 SkASSERT(1 == fBlocks.count());
53 SkASSERT(NULL == fBlocks.back());
54 fOwnFirstBlock = false;
55 fBlocks.back() = initialBlock;
56 } 44 }
57 45
58 /** 46 /**
59 * Adds an item and returns pointer to it. 47 * Adds an item and returns pointer to it.
60 * 48 *
61 * @return pointer to the added item. 49 * @return pointer to the added item.
62 */ 50 */
63 void* push_back() { 51 void* push_back() {
64 int indexInBlock = fCount % fItemsPerBlock;
65 // we always have at least one block 52 // we always have at least one block
66 if (0 == indexInBlock) { 53 if (fItemsPerBlock == fInsertionIndexInBlock) {
67 if (0 != fCount) { 54 fBlocks.push_back() = sk_malloc_throw(fBlockSize);
68 fBlocks.push_back() = sk_malloc_throw(fBlockSize); 55 fInsertionIndexInBlock = 0;
69 } else if (fOwnFirstBlock) {
70 fBlocks[0] = sk_malloc_throw(fBlockSize);
71 }
72 } 56 }
73 void* ret = (char*)fBlocks[fCount/fItemsPerBlock] + 57 void* ret = (char*)fBlocks.back() + fItemSize * fInsertionIndexInBlock;
74 fItemSize * indexInBlock;
75 ++fCount; 58 ++fCount;
59 ++fInsertionIndexInBlock;
76 return ret; 60 return ret;
77 } 61 }
78 62
79 /** 63 /**
80 * removes all added items 64 * Removes all added items.
81 */ 65 */
82 void reset() { 66 void reset() {
83 int blockCount = SkTMax((unsigned)1, 67 int firstBlockToFree = fOwnFirstBlock ? 0 : 1;
84 GrUIDivRoundUp(fCount, fItemsPerBlock)); 68 for (int i = firstBlockToFree; i < fBlocks.count(); ++i) {
85 for (int i = 1; i < blockCount; ++i) {
86 sk_free(fBlocks[i]); 69 sk_free(fBlocks[i]);
87 } 70 }
88 if (fOwnFirstBlock) { 71 if (fOwnFirstBlock) {
89 sk_free(fBlocks[0]); 72 fBlocks.reset();
90 fBlocks[0] = NULL; 73 // This force us to allocate a new block on push_back().
74 fInsertionIndexInBlock = fItemsPerBlock;
75 } else {
76 fBlocks.pop_back_n(fBlocks.count() - 1);
77 fInsertionIndexInBlock = 0;
91 } 78 }
92 fBlocks.pop_back_n(blockCount-1);
93 fCount = 0; 79 fCount = 0;
94 } 80 }
95 81
96 /** 82 /**
97 * count of items 83 * Returns the item count.
98 */ 84 */
99 int count() const { 85 int count() const {
100 return fCount; 86 return fCount;
101 } 87 }
102 88
103 /** 89 /**
104 * is the count 0 90 * Is the count 0?
105 */ 91 */
106 bool empty() const { return fCount == 0; } 92 bool empty() const { return 0 == fCount; }
107 93
108 /** 94 /**
109 * access last item, only call if count() != 0 95 * Access last item, only call if count() != 0
110 */ 96 */
111 void* back() { 97 void* back() {
112 SkASSERT(fCount); 98 SkASSERT(fCount);
113 return (*this)[fCount-1]; 99 SkASSERT(fInsertionIndexInBlock > 0);
100 return (char*)(fBlocks.back()) + (fInsertionIndexInBlock - 1) * fItemSiz e;
114 } 101 }
115 102
116 /** 103 /**
117 * access last item, only call if count() != 0 104 * Access last item, only call if count() != 0
118 */ 105 */
119 const void* back() const { 106 const void* back() const {
120 SkASSERT(fCount); 107 SkASSERT(fCount);
121 return (*this)[fCount-1]; 108 SkASSERT(fInsertionIndexInBlock > 0);
109 return (const char*)(fBlocks.back()) + (fInsertionIndexInBlock - 1) * fI temSize;
122 } 110 }
123 111
112
124 /** 113 /**
125 * access item by index. 114 * Iterates through the allocator. This is faster than using operator[] when walking linearly
115 * through the allocator.
116 */
117 class Iter {
118 public:
119 /**
120 * Initializes the iterator. next() must be called before get().
121 */
122 Iter(const GrAllocator* allocator)
123 : fAllocator(allocator)
124 , fBlockIndex(-1)
125 , fIndexInBlock(allocator->fItemsPerBlock - 1)
126 , fItemIndex(-1) {}
127
128 /**
129 * Advances the iterator. Iteration is finished when next() returns fals e.
130 */
131 bool next() {
132 ++fIndexInBlock;
133 ++fItemIndex;
134 if (fIndexInBlock == fAllocator->fItemsPerBlock) {
135 ++fBlockIndex;
136 fIndexInBlock = 0;
137 }
138 return fItemIndex < fAllocator->fCount;
139 }
140
141 /**
142 * Gets the current iterator value. Call next() at least once before cal ling. Don't call
143 * after next() returns false.
144 */
145 const void* get() const {
146 SkASSERT(fItemIndex >= 0 && fItemIndex < fAllocator->fCount);
147 return (char*) fAllocator->fBlocks[fBlockIndex] + fIndexInBlock * fA llocator->fItemSize;
148 }
149
150 private:
151 const GrAllocator* fAllocator;
152 int fBlockIndex;
153 int fIndexInBlock;
154 int fItemIndex;
155 };
156
157 /**
158 * Access item by index.
126 */ 159 */
127 void* operator[] (int i) { 160 void* operator[] (int i) {
128 SkASSERT(i >= 0 && i < fCount); 161 SkASSERT(i >= 0 && i < fCount);
129 return (char*)fBlocks[i / fItemsPerBlock] + 162 return (char*)fBlocks[i / fItemsPerBlock] +
130 fItemSize * (i % fItemsPerBlock); 163 fItemSize * (i % fItemsPerBlock);
131 } 164 }
132 165
133 /** 166 /**
134 * access item by index. 167 * Access item by index.
135 */ 168 */
136 const void* operator[] (int i) const { 169 const void* operator[] (int i) const {
137 SkASSERT(i >= 0 && i < fCount); 170 SkASSERT(i >= 0 && i < fCount);
138 return (const char*)fBlocks[i / fItemsPerBlock] + 171 return (const char*)fBlocks[i / fItemsPerBlock] +
139 fItemSize * (i % fItemsPerBlock); 172 fItemSize * (i % fItemsPerBlock);
140 } 173 }
141 174
175 protected:
176 /**
177 * Set first block of memory to write into. Must be called before any other methods.
178 * This requires that you have passed NULL in the constructor.
179 *
180 * @param initialBlock optional memory to use for the first block.
181 * Must be at least itemSize*itemsPerBlock sized.
182 * Caller is responsible for freeing this memory.
183 */
184 void setInitialBlock(void* initialBlock) {
185 SkASSERT(0 == fCount);
186 SkASSERT(0 == fBlocks.count());
187 SkASSERT(fItemsPerBlock == fInsertionIndexInBlock);
188 fOwnFirstBlock = false;
189 fBlocks.push_back() = initialBlock;
190 fInsertionIndexInBlock = 0;
191 }
192
193 // For access to above function.
194 template <typename T> friend class GrTAllocator;
195
142 private: 196 private:
143 static const int NUM_INIT_BLOCK_PTRS = 8; 197 static const int NUM_INIT_BLOCK_PTRS = 8;
144 198
145 SkSTArray<NUM_INIT_BLOCK_PTRS, void*> fBlocks; 199 SkSTArray<NUM_INIT_BLOCK_PTRS, void*, true> fBlocks;
146 size_t fBlockSize; 200 size_t fBlockSize;
147 size_t fItemSize; 201 size_t fItemSize;
148 int fItemsPerBlock; 202 int fItemsPerBlock;
149 bool fOwnFirstBlock; 203 bool fOwnFirstBlock;
150 int fCount; 204 int fCount;
205 int fInsertionIndexInBlock;
151 206
152 typedef SkNoncopyable INHERITED; 207 typedef SkNoncopyable INHERITED;
153 }; 208 };
154 209
155 template <typename T> 210 template <typename T>
156 class GrTAllocator : SkNoncopyable { 211 class GrTAllocator : SkNoncopyable {
157 public: 212 public:
158 virtual ~GrTAllocator() { this->reset(); }; 213 virtual ~GrTAllocator() { this->reset(); };
159 214
160 /** 215 /**
(...skipping 17 matching lines...) Expand all
178 } 233 }
179 234
180 T& push_back(const T& t) { 235 T& push_back(const T& t) {
181 void* item = fAllocator.push_back(); 236 void* item = fAllocator.push_back();
182 SkASSERT(NULL != item); 237 SkASSERT(NULL != item);
183 SkNEW_PLACEMENT_ARGS(item, T, (t)); 238 SkNEW_PLACEMENT_ARGS(item, T, (t));
184 return *(T*)item; 239 return *(T*)item;
185 } 240 }
186 241
187 /** 242 /**
188 * removes all added items 243 * Removes all added items.
189 */ 244 */
190 void reset() { 245 void reset() {
191 int c = fAllocator.count(); 246 int c = fAllocator.count();
192 for (int i = 0; i < c; ++i) { 247 for (int i = 0; i < c; ++i) {
193 ((T*)fAllocator[i])->~T(); 248 ((T*)fAllocator[i])->~T();
194 } 249 }
195 fAllocator.reset(); 250 fAllocator.reset();
196 } 251 }
197 252
198 /** 253 /**
199 * count of items 254 * Returns the item count.
200 */ 255 */
201 int count() const { 256 int count() const {
202 return fAllocator.count(); 257 return fAllocator.count();
203 } 258 }
204 259
205 /** 260 /**
206 * is the count 0 261 * Is the count 0?
207 */ 262 */
208 bool empty() const { return fAllocator.empty(); } 263 bool empty() const { return fAllocator.empty(); }
209 264
210 /** 265 /**
211 * access last item, only call if count() != 0 266 * Access last item, only call if count() != 0
212 */ 267 */
213 T& back() { 268 T& back() {
214 return *(T*)fAllocator.back(); 269 return *(T*)fAllocator.back();
215 } 270 }
216 271
217 /** 272 /**
218 * access last item, only call if count() != 0 273 * Access last item, only call if count() != 0
219 */ 274 */
220 const T& back() const { 275 const T& back() const {
221 return *(const T*)fAllocator.back(); 276 return *(const T*)fAllocator.back();
222 } 277 }
223 278
224 /** 279 /**
225 * access item by index. 280 * Iterates through the allocator. This is faster than using operator[] when walking linearly
281 * through the allocator.
282 */
283 class Iter {
284 public:
285 /**
286 * Initializes the iterator. next() must be called before get() or ops * and ->.
287 */
288 Iter(const GrTAllocator* allocator) : fImpl(&allocator->fAllocator) {}
289
290 /**
291 * Advances the iterator. Iteration is finished when next() returns fals e.
292 */
293 bool next() { return fImpl.next(); }
294
295 /**
296 * Gets the current iterator value. Call next() at least once before cal ling. Don't call
297 * after next() returns false.
298 */
299 const T* get() const { return (const T*) fImpl.get(); }
300
301 /**
302 * Convenience operators. Same rules for calling apply as get().
303 */
304 const T& operator*() const { return *this->get(); }
305 const T* operator->() const { return this->get(); }
306
307 private:
308 GrAllocator::Iter fImpl;
309 };
310
311 /**
312 * Access item by index.
226 */ 313 */
227 T& operator[] (int i) { 314 T& operator[] (int i) {
228 return *(T*)(fAllocator[i]); 315 return *(T*)(fAllocator[i]);
229 } 316 }
230 317
231 /** 318 /**
232 * access item by index. 319 * Access item by index.
233 */ 320 */
234 const T& operator[] (int i) const { 321 const T& operator[] (int i) const {
235 return *(const T*)(fAllocator[i]); 322 return *(const T*)(fAllocator[i]);
236 } 323 }
237 324
238 protected: 325 protected:
239 /* 326 /*
240 * Set first block of memory to write into. Must be called before any other methods. 327 * Set first block of memory to write into. Must be called before any other methods.
241 * 328 *
242 * @param initialBlock optional memory to use for the first block. 329 * @param initialBlock optional memory to use for the first block.
(...skipping 16 matching lines...) Expand all
259 public: 346 public:
260 GrSTAllocator() : INHERITED(N) { 347 GrSTAllocator() : INHERITED(N) {
261 this->setInitialBlock(fStorage.get()); 348 this->setInitialBlock(fStorage.get());
262 } 349 }
263 350
264 private: 351 private:
265 SkAlignedSTStorage<N, T> fStorage; 352 SkAlignedSTStorage<N, T> fStorage;
266 }; 353 };
267 354
268 #endif 355 #endif
OLDNEW
« no previous file with comments | « no previous file | src/gpu/GrDrawState.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698