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

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

Issue 750613002: Add pop_back to GrTRecorder.h (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Add comments Created 6 years 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 | tests/GrTRecorderTest.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 * Copyright 2014 Google Inc. 2 * Copyright 2014 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 GrTRecorder_DEFINED 8 #ifndef GrTRecorder_DEFINED
9 #define GrTRecorder_DEFINED 9 #define GrTRecorder_DEFINED
10 10
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 public: 47 public:
48 class Iter; 48 class Iter;
49 49
50 /** 50 /**
51 * Create a recorder. 51 * Create a recorder.
52 * 52 *
53 * @param initialSizeInBytes The amount of memory reserved by the recorder initially, 53 * @param initialSizeInBytes The amount of memory reserved by the recorder initially,
54 and after calls to reset(). 54 and after calls to reset().
55 */ 55 */
56 GrTRecorder(int initialSizeInBytes) 56 GrTRecorder(int initialSizeInBytes)
57 : fHeadBlock(MemBlock::Alloc(LengthOf(initialSizeInBytes))), 57 : fHeadBlock(MemBlock::Alloc(LengthOf(initialSizeInBytes), NULL)),
58 fTailBlock(fHeadBlock), 58 fTailBlock(fHeadBlock),
59 fLastItem(NULL) {} 59 fLastItem(NULL) {}
60 60
61 ~GrTRecorder() { 61 ~GrTRecorder() {
62 this->reset(); 62 this->reset();
63 MemBlock::Free(fHeadBlock); 63 MemBlock::Free(fHeadBlock);
64 } 64 }
65 65
66 bool empty() { return !fLastItem; } 66 bool empty() { return !fLastItem; }
67 67
68 TBase& back() { 68 TBase& back() {
69 SkASSERT(!this->empty()); 69 SkASSERT(!this->empty());
70 return *fLastItem; 70 return *fLastItem;
71 } 71 }
72 72
73 /** 73 /**
74 * Removes and destroys the last block added to the recorder. It may not be called when the
75 * recorder is empty.
76 */
77 void pop_back();
78
79 /**
74 * Destruct all items in the list and reset to empty. 80 * Destruct all items in the list and reset to empty.
75 */ 81 */
76 void reset(); 82 void reset();
77 83
78 /** 84 /**
79 * Retrieve the extra data associated with an item that was allocated using 85 * Retrieve the extra data associated with an item that was allocated using
80 * GrNEW_APPEND_WITH_DATA_TO_RECORDER(). 86 * GrNEW_APPEND_WITH_DATA_TO_RECORDER().
81 * 87 *
82 * @param item The item whose data to retrieve. The pointer must be of the same type 88 * @param item The item whose data to retrieve. The pointer must be of the same type
83 * that was allocated initally; it can't be a pointer to a base class. 89 * that was allocated initally; it can't be a pointer to a base class.
84 * 90 *
85 * @return The item's associated data. 91 * @return The item's associated data.
86 */ 92 */
87 template<typename TItem> static const void* GetDataForItem(const TItem* item ) { 93 template<typename TItem> static const void* GetDataForItem(const TItem* item ) {
88 const TAlign* ptr = reinterpret_cast<const TAlign*>(item); 94 const TAlign* ptr = reinterpret_cast<const TAlign*>(item);
89 return &ptr[length_of<TItem>::kValue]; 95 return &ptr[length_of<TItem>::kValue];
90 } 96 }
91 template<typename TItem> static void* GetDataForItem(TItem* item) { 97 template<typename TItem> static void* GetDataForItem(TItem* item) {
92 TAlign* ptr = reinterpret_cast<TAlign*>(item); 98 TAlign* ptr = reinterpret_cast<TAlign*>(item);
93 return &ptr[length_of<TItem>::kValue]; 99 return &ptr[length_of<TItem>::kValue];
94 } 100 }
95 101
96 private: 102 private:
97 template<typename TItem> struct length_of { 103 template<typename TItem> struct length_of {
98 enum { kValue = (sizeof(TItem) + sizeof(TAlign) - 1) / sizeof(TAlign) }; 104 enum { kValue = (sizeof(TItem) + sizeof(TAlign) - 1) / sizeof(TAlign) };
99 }; 105 };
100 static int LengthOf(int bytes) { return (bytes + sizeof(TAlign) - 1) / sizeo f(TAlign); } 106 static int LengthOf(int bytes) { return (bytes + sizeof(TAlign) - 1) / sizeo f(TAlign); }
101 107
102 struct Header { 108 struct Header {
103 int fTotalLength; 109 int fTotalLength; // The length of an entry including header, item, and data in TAligns.
110 int fPrevLength; // Same but for the previous entry. Used for iterating backwards.
104 }; 111 };
105 template<typename TItem> TItem* alloc_back(int dataLength); 112 template<typename TItem> TItem* alloc_back(int dataLength);
106 113
107 struct MemBlock : SkNoncopyable { 114 struct MemBlock : SkNoncopyable {
108 static MemBlock* Alloc(int length) { 115 /** Allocates a new block and appends it to prev if not NULL. The length param is in units
116 of TAlign. */
117 static MemBlock* Alloc(int length, MemBlock* prev) {
109 MemBlock* block = reinterpret_cast<MemBlock*>( 118 MemBlock* block = reinterpret_cast<MemBlock*>(
110 sk_malloc_throw(sizeof(TAlign) * (length_of<MemBlock>::kValue + length))); 119 sk_malloc_throw(sizeof(TAlign) * (length_of<MemBlock>::kValue + length)));
111 block->fLength = length; 120 block->fLength = length;
112 block->fBack = 0; 121 block->fBack = 0;
113 block->fNext = NULL; 122 block->fNext = NULL;
123 block->fPrev = prev;
124 if (prev) {
125 SkASSERT(NULL == prev->fNext);
126 prev->fNext = block;
127 }
114 return block; 128 return block;
115 } 129 }
116 130
131 // Frees from this block forward. Also adjusts prev block's next ptr.
117 static void Free(MemBlock* block) { 132 static void Free(MemBlock* block) {
118 if (!block) { 133 if (block && block->fPrev) {
119 return; 134 SkASSERT(block->fPrev->fNext == block);
135 block->fPrev->fNext = NULL;
120 } 136 }
121 Free(block->fNext); 137 while (block) {
122 sk_free(block); 138 MemBlock* next = block->fNext;
139 sk_free(block);
140 block = next;
141 }
123 } 142 }
124 143
125 TAlign& operator [](int i) { 144 TAlign& operator [](int i) {
126 return reinterpret_cast<TAlign*>(this)[length_of<MemBlock>::kValue + i]; 145 return reinterpret_cast<TAlign*>(this)[length_of<MemBlock>::kValue + i];
127 } 146 }
128 147
129 int fLength; 148 int fLength; // Length in units of TAlign of the block.
130 int fBack; 149 int fBack; // Offset, in TAligns, to unused portion of the memor y block.
131 MemBlock* fNext; 150 MemBlock* fNext;
151 MemBlock* fPrev;
132 }; 152 };
133 MemBlock* const fHeadBlock; 153 MemBlock* const fHeadBlock;
134 MemBlock* fTailBlock; 154 MemBlock* fTailBlock;
135 155
136 TBase* fLastItem; 156 TBase* fLastItem;
137 157
138 template<typename TItem> friend struct GrTRecorderAllocWrapper; 158 template<typename TItem> friend struct GrTRecorderAllocWrapper;
139 159
140 template <typename UBase, typename UAlign, typename UItem> 160 template <typename UBase, typename UAlign, typename UItem>
141 friend void* operator new(size_t, GrTRecorder<UBase, UAlign>&, 161 friend void* operator new(size_t, GrTRecorder<UBase, UAlign>&,
142 const GrTRecorderAllocWrapper<UItem>&); 162 const GrTRecorderAllocWrapper<UItem>&);
143 163
144 friend class Iter; 164 friend class Iter;
145 }; 165 };
146 166
147 //////////////////////////////////////////////////////////////////////////////// 167 ////////////////////////////////////////////////////////////////////////////////
148 168
149 template<typename TBase, typename TAlign> 169 template<typename TBase, typename TAlign>
170 void GrTRecorder<TBase, TAlign>::pop_back() {
171 SkASSERT(fLastItem);
172 Header* header = reinterpret_cast<Header*>(
173 reinterpret_cast<TAlign*>(fLastItem) - length_of<Header>::kValue);
174 fTailBlock->fBack -= header->fTotalLength;
175 fLastItem->~TBase();
176
177 int lastItemLength = header->fPrevLength;
178
179 if (!header->fPrevLength) {
180 // We popped the first entry in the recorder.
181 SkASSERT(0 == fTailBlock->fBack);
182 fLastItem = NULL;
183 return;
184 }
185 if (!fTailBlock->fBack) {
186 // We popped the last entry in a block that isn't the head block. Move b ack a block but
187 // don't free it since we'll probably grow into it shortly.
188 fTailBlock = fTailBlock->fPrev;
189 SkASSERT(fTailBlock);
190 }
191 fLastItem = reinterpret_cast<TBase*>(
192 &(*fTailBlock)[fTailBlock->fBack - lastItemLength + length_of<Header>::k Value]);
193 }
194
195 template<typename TBase, typename TAlign>
150 template<typename TItem> 196 template<typename TItem>
151 TItem* GrTRecorder<TBase, TAlign>::alloc_back(int dataLength) { 197 TItem* GrTRecorder<TBase, TAlign>::alloc_back(int dataLength) {
198 // Find the header of the previous entry and get its length. We need to stor e that in the new
199 // header for backwards iteration (pop_back()).
200 int prevLength = 0;
201 if (fLastItem) {
202 Header* lastHeader = reinterpret_cast<Header*>(
203 reinterpret_cast<TAlign*>(fLastItem) - length_of<Header>::kValue);
204 prevLength = lastHeader->fTotalLength;
205 }
206
152 const int totalLength = length_of<Header>::kValue + length_of<TItem>::kValue + dataLength; 207 const int totalLength = length_of<Header>::kValue + length_of<TItem>::kValue + dataLength;
153 208
209 // Check if there is room in the current block and if not walk to next (allo cating if
210 // necessary). Note that pop_back() and reset() can leave the recorder in a state where it
211 // has preallocated blocks hanging off the tail that are currently unused.
154 while (fTailBlock->fBack + totalLength > fTailBlock->fLength) { 212 while (fTailBlock->fBack + totalLength > fTailBlock->fLength) {
155 if (!fTailBlock->fNext) { 213 if (!fTailBlock->fNext) {
156 fTailBlock->fNext = MemBlock::Alloc(SkTMax(2 * fTailBlock->fLength, totalLength)); 214 fTailBlock = MemBlock::Alloc(SkTMax(2 * fTailBlock->fLength, totalLe ngth), fTailBlock);
215 } else {
216 fTailBlock = fTailBlock->fNext;
157 } 217 }
158 fTailBlock = fTailBlock->fNext;
159 SkASSERT(0 == fTailBlock->fBack); 218 SkASSERT(0 == fTailBlock->fBack);
160 } 219 }
161 220
162 Header* header = reinterpret_cast<Header*>(&(*fTailBlock)[fTailBlock->fBack] ); 221 Header* header = reinterpret_cast<Header*>(&(*fTailBlock)[fTailBlock->fBack] );
163 TItem* rawPtr = reinterpret_cast<TItem*>( 222 TItem* rawPtr = reinterpret_cast<TItem*>(
164 &(*fTailBlock)[fTailBlock->fBack + length_of<Header>::kV alue]); 223 &(*fTailBlock)[fTailBlock->fBack + length_of<Header>::kV alue]);
165 224
166 header->fTotalLength = totalLength; 225 header->fTotalLength = totalLength;
226 header->fPrevLength = prevLength;
167 fLastItem = rawPtr; 227 fLastItem = rawPtr;
168 fTailBlock->fBack += totalLength; 228 fTailBlock->fBack += totalLength;
169 229
170 // FIXME: We currently require that the base and subclass share the same sta rt address. 230 // FIXME: We currently require that the base and subclass share the same sta rt address.
171 // This is not required by the C++ spec, and is likely to not be true in the case of 231 // This is not required by the C++ spec, and is likely to not be true in the case of
172 // multiple inheritance or a base class that doesn't have virtual methods (w hen the 232 // multiple inheritance or a base class that doesn't have virtual methods (w hen the
173 // subclass does). It would be ideal to find a more robust solution that com es at no 233 // subclass does). It would be ideal to find a more robust solution that com es at no
174 // extra cost to performance or code generality. 234 // extra cost to performance or code generality.
175 SkDEBUGCODE(void* baseAddr = fLastItem; 235 SkDEBUGCODE(void* baseAddr = fLastItem;
176 void* subclassAddr = rawPtr); 236 void* subclassAddr = rawPtr);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 Iter iter(*this); 278 Iter iter(*this);
219 while (iter.next()) { 279 while (iter.next()) {
220 iter->~TBase(); 280 iter->~TBase();
221 } 281 }
222 282
223 // Assume the next time this recorder fills up it will use approximately the same 283 // Assume the next time this recorder fills up it will use approximately the same
224 // amount of space as last time. Leave enough space for up to ~50% growth; f ree 284 // amount of space as last time. Leave enough space for up to ~50% growth; f ree
225 // everything else. 285 // everything else.
226 if (fTailBlock->fBack <= fTailBlock->fLength / 2) { 286 if (fTailBlock->fBack <= fTailBlock->fLength / 2) {
227 MemBlock::Free(fTailBlock->fNext); 287 MemBlock::Free(fTailBlock->fNext);
228 fTailBlock->fNext = NULL;
229 } else if (fTailBlock->fNext) { 288 } else if (fTailBlock->fNext) {
230 MemBlock::Free(fTailBlock->fNext->fNext); 289 MemBlock::Free(fTailBlock->fNext->fNext);
231 fTailBlock->fNext->fNext = NULL; 290 fTailBlock->fNext->fNext = NULL;
232 } 291 }
233 292
234 for (MemBlock* block = fHeadBlock; block; block = block->fNext) { 293 for (MemBlock* block = fHeadBlock; block; block = block->fNext) {
235 block->fBack = 0; 294 block->fBack = 0;
236 } 295 }
237 296
238 fTailBlock = fHeadBlock; 297 fTailBlock = fHeadBlock;
(...skipping 26 matching lines...) Expand all
265 SK_CRASH(); 324 SK_CRASH();
266 } 325 }
267 326
268 #define GrNEW_APPEND_TO_RECORDER(recorder, type_name, args) \ 327 #define GrNEW_APPEND_TO_RECORDER(recorder, type_name, args) \
269 (new (recorder, GrTRecorderAllocWrapper<type_name>()) type_name args) 328 (new (recorder, GrTRecorderAllocWrapper<type_name>()) type_name args)
270 329
271 #define GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, type_name, args, size_of_da ta) \ 330 #define GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, type_name, args, size_of_da ta) \
272 (new (recorder, GrTRecorderAllocWrapper<type_name>(recorder, size_of_data)) type_name args) 331 (new (recorder, GrTRecorderAllocWrapper<type_name>(recorder, size_of_data)) type_name args)
273 332
274 #endif 333 #endif
OLDNEW
« no previous file with comments | « no previous file | tests/GrTRecorderTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698