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

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

Issue 654863003: Revert of Create a single command buffer for GrInOrderDrawBuffer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 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
« no previous file with comments | « src/gpu/GrInOrderDrawBuffer.cpp ('k') | 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
(Empty)
1 /*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #ifndef GrTRecorder_DEFINED
9 #define GrTRecorder_DEFINED
10
11 #include "SkTemplates.h"
12 #include "SkTypes.h"
13
14 template<typename TBase, typename TAlign> class GrTRecorder;
15 template<typename TItem> struct GrTRecorderAllocWrapper;
16
17 /**
18 * Records a list of items with a common base type, optional associated data, an d
19 * permanent memory addresses.
20 *
21 * This class preallocates its own chunks of memory for hosting objects, so new items can
22 * be created without excessive calls to malloc().
23 *
24 * To create a new item and append it to the back of the list, use the following macros:
25 *
26 * GrNEW_APPEND_TO_RECORDER(recorder, SubclassName, (args))
27 * GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, SubclassName, (args), sizeOf Data)
28 *
29 * Upon reset or delete, the items are destructed in the same order they were re ceived,
30 * not reverse (stack) order.
31 *
32 * @param TBase Common base type of items in the list. If TBase is not a class with a
33 * virtual destructor, the client is responsible for invoking any necessary
34 * destructors.
35 *
36 * For now, any subclass used in the list must have the same star t address
37 * as TBase (or in other words, the types must be convertible via
38 * reinterpret_cast<>). Classes with multiple inheritance (or any subclass
39 * on an obscure compiler) may not be compatible. This is runtime asserted
40 * in debug builds.
41 *
42 * @param TAlign A type whose size is the desired memory alignment for object a llocations.
43 * This should be the largest known alignment requirement for all objects
44 * that may be stored in the list.
45 */
46 template<typename TBase, typename TAlign> class GrTRecorder : SkNoncopyable {
47 public:
48 class Iter;
49
50 /**
51 * Create a recorder.
52 *
53 * @param initialSizeInBytes The amount of memory reserved by the recorder initially,
54 and after calls to reset().
55 */
56 GrTRecorder(int initialSizeInBytes)
57 : fHeadBlock(MemBlock::Alloc(LengthOf(initialSizeInBytes))),
58 fTailBlock(fHeadBlock),
59 fLastItem(NULL) {}
60
61 ~GrTRecorder() {
62 this->reset();
63 sk_free(fHeadBlock);
64 }
65
66 bool empty() { return !fLastItem; }
67
68 TBase& back() {
69 SkASSERT(!this->empty());
70 return *fLastItem;
71 }
72
73 /**
74 * Destruct all items in the list and reset to empty.
75 */
76 void reset();
77
78 /**
79 * Retrieve the extra data associated with an item that was allocated using
80 * GrNEW_APPEND_WITH_DATA_TO_RECORDER().
81 *
82 * @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.
84 *
85 * @return The item's associated data.
86 */
87 template<typename TItem> static const void* GetDataForItem(const TItem* item ) {
88 const TAlign* ptr = reinterpret_cast<const TAlign*>(item);
89 return &ptr[length_of<TItem>::kValue];
90 }
91 template<typename TItem> static void* GetDataForItem(TItem* item) {
92 TAlign* ptr = reinterpret_cast<TAlign*>(item);
93 return &ptr[length_of<TItem>::kValue];
94 }
95
96 private:
97 template<typename TItem> struct length_of {
98 enum { kValue = (sizeof(TItem) + sizeof(TAlign) - 1) / sizeof(TAlign) };
99 };
100 static int LengthOf(int bytes) { return (bytes + sizeof(TAlign) - 1) / sizeo f(TAlign); }
101
102 struct Header {
103 int fTotalLength;
104 };
105 template<typename TItem> TItem* alloc_back(int dataLength);
106
107 struct MemBlock {
108 static MemBlock* Alloc(int length) {
109 void* ptr = sk_malloc_throw(sizeof(TAlign) * (length_of<MemBlock>::k Value + length));
110 return SkNEW_PLACEMENT_ARGS(ptr, MemBlock, (length));
111 }
112 TAlign& operator [](int i) {
113 return reinterpret_cast<TAlign*>(this)[length_of<MemBlock>::kValue + i];
114 }
115 ~MemBlock() { sk_free(fNext); }
116
117 const int fLength;
118 int fBack;
119 MemBlock* fNext;
120
121 private:
122 MemBlock(int length) : fLength(length), fBack(0), fNext(NULL) {}
123 };
124 MemBlock* const fHeadBlock;
125 MemBlock* fTailBlock;
126
127 TBase* fLastItem;
128
129 template<typename TItem> friend struct GrTRecorderAllocWrapper;
130
131 template <typename UBase, typename UAlign, typename UAlloc>
132 friend void* operator new(size_t, GrTRecorder<UBase, UAlign>&,
133 const GrTRecorderAllocWrapper<UAlloc>&);
134
135 friend class Iter;
136 };
137
138 ////////////////////////////////////////////////////////////////////////////////
139
140 template<typename TBase, typename TAlign>
141 template<typename TItem>
142 TItem* GrTRecorder<TBase, TAlign>::alloc_back(int dataLength) {
143 const int totalLength = length_of<Header>::kValue + length_of<TItem>::kValue + dataLength;
144
145 if (fTailBlock->fBack + totalLength > fTailBlock->fLength) {
146 SkASSERT(!fTailBlock->fNext);
147 fTailBlock->fNext = MemBlock::Alloc(SkTMax(2 * fTailBlock->fLength, tota lLength));
148 fTailBlock = fTailBlock->fNext;
149 }
150
151 Header* header = reinterpret_cast<Header*>(&(*fTailBlock)[fTailBlock->fBack] );
152 TItem* rawPtr = reinterpret_cast<TItem*>(
153 &(*fTailBlock)[fTailBlock->fBack + length_of<Header>::kV alue]);
154
155 header->fTotalLength = totalLength;
156 fLastItem = rawPtr;
157 fTailBlock->fBack += totalLength;
158
159 // FIXME: We currently require that the base and subclass share the same sta rt address.
160 // This is not required by the C++ spec, and is likely to not be true in the case of
161 // multiple inheritance or a base class that doesn't have virtual methods (w hen the
162 // subclass does). It would be ideal to find a more robust solution that com es at no
163 // extra cost to performance or code generality.
164 SkDEBUGCODE(void* baseAddr = fLastItem;
165 void* subclassAddr = rawPtr);
166 SkASSERT(baseAddr == subclassAddr);
167
168 return rawPtr;
169 }
170
171 template<typename TBase, typename TAlign>
172 class GrTRecorder<TBase, TAlign>::Iter {
173 public:
174 Iter(GrTRecorder& recorder) : fBlock(recorder.fHeadBlock), fPosition(0), fIt em(NULL) {}
175
176 bool next() {
177 if (fPosition >= fBlock->fBack) {
178 SkASSERT(fPosition == fBlock->fBack);
179 if (!fBlock->fNext) {
180 return false;
181 }
182 SkASSERT(0 != fBlock->fNext->fBack);
183 fBlock = fBlock->fNext;
184 fPosition = 0;
185 }
186
187 Header* header = reinterpret_cast<Header*>(&(*fBlock)[fPosition]);
188 fItem = reinterpret_cast<TBase*>(&(*fBlock)[fPosition + length_of<Header >::kValue]);
189 fPosition += header->fTotalLength;
190 return true;
191 }
192
193 TBase* get() const {
194 SkASSERT(fItem);
195 return fItem;
196 }
197
198 TBase* operator->() const { return this->get(); }
199
200 private:
201 MemBlock* fBlock;
202 int fPosition;
203 TBase* fItem;
204 };
205
206 template<typename TBase, typename TAlign>
207 void GrTRecorder<TBase, TAlign>::reset() {
208 Iter iter(*this);
209 while (iter.next()) {
210 iter->~TBase();
211 }
212 fHeadBlock->fBack = 0;
213 sk_free(fHeadBlock->fNext);
214 fHeadBlock->fNext = NULL;
215 fTailBlock = fHeadBlock;
216 fLastItem = NULL;
217 }
218
219 ////////////////////////////////////////////////////////////////////////////////
220
221 template<typename TItem> struct GrTRecorderAllocWrapper {
222 GrTRecorderAllocWrapper() : fDataLength(0) {}
223
224 template <typename TBase, typename TAlign>
225 GrTRecorderAllocWrapper(const GrTRecorder<TBase, TAlign>&, int sizeOfData)
226 : fDataLength(GrTRecorder<TBase, TAlign>::LengthOf(sizeOfData)) {}
227
228 const int fDataLength;
229 };
230
231 template <typename TBase, typename TAlign, typename TItem>
232 void* operator new(size_t size, GrTRecorder<TBase, TAlign>& recorder,
233 const GrTRecorderAllocWrapper<TItem>& wrapper) {
234 SkASSERT(size == sizeof(TItem));
235 return recorder.template alloc_back<TItem>(wrapper.fDataLength);
236 }
237
238 template <typename TBase, typename TAlign, typename TItem>
239 void operator delete(void*, GrTRecorder<TBase, TAlign>&, const GrTRecorderAllocW rapper<TItem>&) {
240 // We only provide an operator delete to work around compiler warnings that can come
241 // up for an unmatched operator new when compiling with exceptions.
242 SK_CRASH();
243 }
244
245 #define GrNEW_APPEND_TO_RECORDER(recorder, type_name, args) \
246 (new (recorder, GrTRecorderAllocWrapper<type_name>()) type_name args)
247
248 #define GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, type_name, args, size_of_da ta) \
249 (new (recorder, GrTRecorderAllocWrapper<type_name>(recorder, size_of_data)) type_name args)
250
251 #endif
OLDNEW
« no previous file with comments | « src/gpu/GrInOrderDrawBuffer.cpp ('k') | tests/GrTRecorderTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698