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

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

Issue 628453002: Create a single command buffer for GrInOrderDrawBuffer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Formatting 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 * @param TBase Common base type of items in the list. If TBase is not a class with a
30 * virtual destructor, the client is responsible for invoking any necessary
31 * destructors.
32 *
33 * For now, any subclass used in the list must have the same star t address
34 * as TBase (or in other words, the types must be convertible via
35 * reinterpret_cast<>). Classes with multiple inheritance (or any subclass
36 * on an obscure compiler) may not be compatible. This is runtime asserted
37 * in debug builds.
38 *
39 * @param TAlign A type whose size is the desired memory alignment for object a llocations.
40 * This should be the largest known alignment requirement for all objects
41 * that may be stored in the list.
42 */
43 template<typename TBase, typename TAlign> class GrTRecorder : SkNoncopyable {
44 public:
45 class Iter;
46
47 /**
48 * Create a recorder.
49 *
50 * @param initialSizeInBytes The amount of memory reserved by the recorder initially,
51 and after calls to reset().
52 */
53 GrTRecorder(int initialSizeInBytes)
54 : fHeadBlock(LengthOf(initialSizeInBytes)),
55 fTailBlock(&fHeadBlock),
56 fLastItem(NULL) {}
57
58 ~GrTRecorder() { this->reset(); }
59
60 bool empty() { return !fLastItem; }
61
62 TBase& back() {
63 SkASSERT(!this->empty());
64 return *fLastItem;
65 }
66
67 /**
68 * Destruct all items in the list and reset to empty.
69 */
70 void reset();
71
72 /**
73 * Retrieve the extra data associated with an item that was allocated using
74 * GrNEW_APPEND_WITH_DATA_TO_RECORDER().
75 *
76 * @param item The item whose data to retrieve. The pointer must be of the same type
77 * that was allocated initally; it can't be a pointer to a base class.
78 *
79 * @return The item's associated data.
80 */
81 template<typename TItem> static const void* GetDataForItem(const TItem* item ) {
82 const TAlign* ptr = reinterpret_cast<const TAlign*>(item);
83 return &ptr[length_of<TItem>::kValue];
84 }
85 template<typename TItem> static void* GetDataForItem(TItem* item) {
86 TAlign* ptr = reinterpret_cast<TAlign*>(item);
87 return &ptr[length_of<TItem>::kValue];
88 }
89
90 private:
91 template<typename TItem> struct length_of {
92 enum { kValue = (sizeof(TItem) + sizeof(TAlign) - 1) / sizeof(TAlign) };
93 };
94 static int LengthOf(int bytes) { return (bytes + sizeof(TAlign) - 1) / sizeo f(TAlign); }
95
96 struct ItemHeader {
97 int fTotalLength;
98 };
99 enum { kHeaderLength = length_of<ItemHeader>::kValue };
100
101 template<typename TItem> TItem* alloc_back(int dataLength);
102
103 struct MemBlock {
104 MemBlock(int length) : fLength(length), fBack(0), fBuffer(fLength) {}
bsalomon 2014/10/11 11:32:49 I didn't pay that much attention to MemBlock befor
Chris Dalton 2014/10/13 18:27:46 It was just a quick code complexity vs perf impact
105 const int fLength;
106 int fBack;
107 SkAutoTMalloc<TAlign> fBuffer;
108 SkAutoTDelete<MemBlock> fNext;
109 };
110 MemBlock fHeadBlock;
111 MemBlock* fTailBlock;
112
113 TBase* fLastItem;
114
115 template<typename TItem> friend struct GrTRecorderAllocWrapper;
116
117 template <typename UBase, typename UAlign, typename UAlloc>
118 friend void* operator new(size_t, GrTRecorder<UBase, UAlign>&,
119 const GrTRecorderAllocWrapper<UAlloc>&);
120
121 friend class Iter;
122 };
123
124 ////////////////////////////////////////////////////////////////////////////////
125
126 template<typename TBase, typename TAlign>
127 template<typename TItem>
128 TItem* GrTRecorder<TBase, TAlign>::alloc_back(int dataLength) {
129 const int totalLength = kHeaderLength + length_of<TItem>::kValue + dataLengt h;
130
131 if (fTailBlock->fBack + totalLength > fTailBlock->fLength) {
132 SkASSERT(!fTailBlock->fNext.get());
133 MemBlock* next = SkNEW_ARGS(MemBlock, (SkTMax(2 * fTailBlock->fLength, t otalLength)));
134 fTailBlock->fNext.reset(next);
135 fTailBlock = next;
136 }
137
138 ItemHeader* header = reinterpret_cast<ItemHeader*>(&fTailBlock->fBuffer[fTai lBlock->fBack]);
139 TItem* rawPtr =
140 reinterpret_cast<TItem*>(&fTailBlock->fBuffer[fTailBlock->fBack + kHeade rLength]);
141
142 header->fTotalLength = totalLength;
143 fLastItem = rawPtr;
144 fTailBlock->fBack += totalLength;
145
146 // FIXME: We currently require that the base and subclass share the same sta rt address.
147 // This is not required by the C++ spec, and is likely to not be true in the case of
148 // multiple inheritance or a base class that doesn't have virtual methods (w hen the
149 // subclass does). It would be ideal to find a more robust solution that com es at no
150 // extra cost to performance or code generality.
151 SkDEBUGCODE(void* baseAddr = fLastItem;
152 void* subclassAddr = rawPtr);
153 SkASSERT(baseAddr == subclassAddr);
154
155 return rawPtr;
156 }
157
158 template<typename TBase, typename TAlign>
159 class GrTRecorder<TBase, TAlign>::Iter {
160 public:
161 Iter(GrTRecorder& recorder) : fBlock(&recorder.fHeadBlock), fPosition(0), fI tem(NULL) {}
162
163 bool next() {
164 if (fPosition >= fBlock->fBack) {
165 SkASSERT(fPosition == fBlock->fBack);
166 if (!fBlock->fNext.get()) {
167 return false;
168 }
169 SkASSERT(0 != fBlock->fNext->fBack);
170 fBlock = fBlock->fNext.get();
171 fPosition = 0;
172 }
173
174 ItemHeader* header = reinterpret_cast<ItemHeader*>(&fBlock->fBuffer[fPos ition]);
175 fItem = reinterpret_cast<TBase*>(&fBlock->fBuffer[fPosition + kHeaderLen gth]);
176 fPosition += header->fTotalLength;
177 return true;
178 }
179
180 TBase* get() const {
181 SkASSERT(fItem);
182 return fItem;
183 }
184
185 TBase* operator->() const { return this->get(); }
186
187 private:
188 MemBlock* fBlock;
189 int fPosition;
190 TBase* fItem;
191 };
192
193 template<typename TBase, typename TAlign>
194 void GrTRecorder<TBase, TAlign>::reset() {
195 Iter iter(*this);
196 while (iter.next()) {
197 iter->~TBase();
198 }
199 fHeadBlock.fBack = 0;
200 fHeadBlock.fNext.free();
201 fTailBlock = &fHeadBlock;
202 fLastItem = NULL;
203 }
204
205 ////////////////////////////////////////////////////////////////////////////////
206
207 template<typename TItem> struct GrTRecorderAllocWrapper {
208 GrTRecorderAllocWrapper() : fDataLength(0) {}
209
210 template <typename TBase, typename TAlign>
211 GrTRecorderAllocWrapper(const GrTRecorder<TBase, TAlign>&, int sizeOfData)
212 : fDataLength(GrTRecorder<TBase, TAlign>::LengthOf(sizeOfData)) {}
213
214 const int fDataLength;
215 };
216
217 template <typename TBase, typename TAlign, typename TItem>
218 void* operator new(size_t size, GrTRecorder<TBase, TAlign>& recorder,
219 const GrTRecorderAllocWrapper<TItem>& wrapper) {
220 SkASSERT(size == sizeof(TItem));
221 return recorder.template alloc_back<TItem>(wrapper.fDataLength);
222 }
223
224 template <typename TBase, typename TAlign, typename TItem>
225 void operator delete(void*, GrTRecorder<TBase, TAlign>&, const GrTRecorderAllocW rapper<TItem>&) {
226 // We only provide an operator delete to work around compiler warnings that can come
227 // up for an unmatched operator new when compiling with exceptions.
228 SK_CRASH();
229 }
230
231 #define GrNEW_APPEND_TO_RECORDER(recorder, type_name, args) \
232 (new (recorder, GrTRecorderAllocWrapper<type_name>()) type_name args)
233
234 #define GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, type_name, args, size_of_da ta) \
235 (new (recorder, GrTRecorderAllocWrapper<type_name>(recorder, size_of_data)) type_name args)
236
237 #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