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

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

Issue 628453002: 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
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 GrTBaseList_DEFINED
9 #define GrTBaseList_DEFINED
10
11 #include "SkTemplates.h"
12 #include "SkTypes.h"
13
14 template<typename TBase, typename TAlign> class GrTBaseList;
15 template<typename T> class GrTBaseListAllocDesc;
16
17 template <typename TBase, typename TAlign, typename T>
18 void* operator new(size_t, GrTBaseList<TBase, TAlign>&, const GrTBaseListAllocDe sc<T>&);
19
20 /**
21 * List of objects with a common base type and permanent memory addresses.
22 *
23 * This class preallocates its own chunks of memory for storing items in the lis t, so new
24 * objects can be created without excessive calls to malloc().
25 *
26 * To create a new item and append it to the back of the list, use the following macros:
27 *
28 * GrNEW_APPEND_TO_TBASELIST(list, SubclassName, (args))
29 * GrNEW_APPEND_WITH_DATA_TO_TBASELIST(list, SubclassName, (args), extraByte sToAllocate)
30 *
31 * @param TBase Common base type of items in the list. If TBase is not a class with a
32 * virtual destructor, the client is responsible for invoking any necessary
33 * destructors.
34 *
35 * For now, any subclass used in the list must have the same star t address
36 * as TBase (or in other words, the types must be convertible via
37 * reinterpret_cast<>). Classes with multiple inheritance (or any subclass
38 * on an obscure compiler) may not be compatible. This is runtime asserted
39 * in debug builds.
40 *
41 * @param TAlign A type whose size is the desired memory alignment for object a llocations.
42 * This should be the largest known alignment requirement for all objects
43 * that may be stored in the buffer.
44 */
45 template<typename TBase, typename TAlign> class GrTBaseList : SkNoncopyable {
46 public:
47 class Iter;
48
49 /**
50 * Create a list for items with a common base type.
51 *
52 * @param initialSizeInBytes The amount of memory reserved by the list init ially, and
53 * and after calls to reset().
54 */
55 GrTBaseList(int initialSizeInBytes)
56 : fHeadBlock(bytes_to_length(initialSizeInBytes)),
57 fTailBlock(&fHeadBlock),
58 fLastItem(NULL) {}
59
60 ~GrTBaseList() { this->reset(); }
61
62 bool empty() { return NULL == fLastItem; }
63
64 TBase& back() {
65 SkASSERT(!this->empty());
66 return *fLastItem;
67 }
68
69 /**
70 * Destruct all items in the list and reset to empty.
71 */
72 void reset();
73
74 private:
75 static int bytes_to_length(int bytes) { return (bytes + sizeof(TAlign) - 1) / sizeof(TAlign); }
76
77 struct ItemHeader {
78 int fTotalLength;
79 };
80 enum { kHeaderLength = (sizeof(ItemHeader) + sizeof(TAlign) - 1) / sizeof(TA lign) };
81
82 template<typename T> void* alloc_back(const GrTBaseListAllocDesc<T>&);
83
84 struct MemBlock {
85 MemBlock(int length) : fLength(length), fBack(0), fBuffer(fLength) {}
86 const int fLength;
87 int fBack;
88 SkAutoTMalloc<TAlign> fBuffer;
89 SkAutoTDelete<MemBlock> fNext;
90 };
91 MemBlock fHeadBlock;
92 MemBlock* fTailBlock;
93
94 TBase* fLastItem;
95
96 template <typename UBase, typename UAlign, typename U>
97 friend void* operator new(size_t, GrTBaseList<UBase, UAlign>&, const GrTBase ListAllocDesc<U>&);
98
99 friend class Iter;
100 };
101
102 /**
103 * Describes a new object allocation for GrTBaseList. Captures type and size.
104 */
105 template<typename T> class GrTBaseListAllocDesc {
106 public:
107 GrTBaseListAllocDesc(int extraBytesToAllocate = 0)
108 : fBytesToAllocate(sizeof(T) + extraBytesToAllocate) {
109 SkASSERT(extraBytesToAllocate >= 0);
110 }
111 int bytesToAllocate() const { return fBytesToAllocate; }
112 private:
113 const int fBytesToAllocate;
114 };
115
116 ////////////////////////////////////////////////////////////////////////////////
117
118 template <typename TBase, typename TAlign, typename T>
119 void* operator new(size_t expectedClassSize,
120 GrTBaseList<TBase, TAlign>& list,
121 const GrTBaseListAllocDesc<T>& desc) {
122 SkASSERT(expectedClassSize == sizeof(T));
123 return list.alloc_back(desc);
124 }
125
126 // Skia doesn't use C++ exceptions but it may be compiled with them enabled. Hav ing an op delete
127 // to match the op new silences warnings about missing op delete when a construc tor throws an
128 // exception.
129 template <typename TBase, typename TAlign, typename T>
130 void operator delete(void*, GrTBaseList<TBase, TAlign>&, const GrTBaseListAllocD esc<T>&) {
131 SK_CRASH();
132 }
133
134 template<typename TBase, typename TAlign>
135 template<typename T>
136 void* GrTBaseList<TBase, TAlign>::alloc_back(const GrTBaseListAllocDesc<T>& desc ) {
137 SkASSERT(desc.bytesToAllocate() >= (int)sizeof(T));
138 const int totalLength = kHeaderLength + bytes_to_length(desc.bytesToAllocate ());
139
140 if (fTailBlock->fBack + totalLength > fTailBlock->fLength) {
141 SkASSERT(NULL == fTailBlock->fNext.get());
142 MemBlock* next = SkNEW_ARGS(MemBlock, (SkTMax(2 * fTailBlock->fLength, t otalLength)));
143 fTailBlock->fNext.reset(next);
144 fTailBlock = next;
145 }
146
147 ItemHeader* header = reinterpret_cast<ItemHeader*>(&fTailBlock->fBuffer[fTai lBlock->fBack]);
148 TBase* rawPtr = reinterpret_cast<T*>(&fTailBlock->fBuffer[fTailBlock->fBack + kHeaderLength]);
149 fTailBlock->fBack += totalLength;
150
151 header->fTotalLength = totalLength;
152
153 fLastItem = rawPtr;
154
155 // FIXME: We currently require that the base and subclass share the same sta rt address.
156 // This is not required by the C++ spec, and is likely to not be true in the case of
157 // multiple inheritance or a base class that doesn't have virtual methods (w hen the
158 // subclass does). It would be ideal to find a more robust solution that com es at no
159 // extra cost to performance or code generality.
160 SkDEBUGCODE(void* baseAddr = fLastItem;
161 void* subclassAddr = rawPtr);
162 SkASSERT(baseAddr == subclassAddr);
163
164 return rawPtr;
165 }
166
167 template<typename TBase, typename TAlign>
168 class GrTBaseList<TBase, TAlign>::Iter {
169 public:
170 Iter(GrTBaseList& list) : fBlock(&list.fHeadBlock), fPosition(0), fItem(NULL ) {}
171
172 bool next() {
173 if (fPosition >= fBlock->fBack) {
174 SkASSERT(fPosition == fBlock->fBack);
175 if (NULL == fBlock->fNext.get()) {
176 return false;
177 }
178 SkASSERT(0 != fBlock->fNext->fBack);
179 fBlock = fBlock->fNext.get();
180 fPosition = 0;
181 }
182
183 ItemHeader* header = reinterpret_cast<ItemHeader*>(&fBlock->fBuffer[fPos ition]);
184 fItem = reinterpret_cast<TBase*>(&fBlock->fBuffer[fPosition + kHeaderLen gth]);
185 fPosition += header->fTotalLength;
186 return true;
187 }
188
189 TBase* get() const {
190 SkASSERT(fItem);
191 return fItem;
192 }
193
194 TBase* operator->() const { return this->get(); }
195
196 private:
197 MemBlock* fBlock;
198 int fPosition;
199 TBase* fItem;
200 };
201
202 template<typename TBase, typename TAlign>
203 void GrTBaseList<TBase, TAlign>::reset() {
204 Iter iter(*this);
205 while (iter.next()) {
206 iter->~TBase();
207 }
208 fHeadBlock.fBack = 0;
209 fHeadBlock.fNext.free();
210 fTailBlock = &fHeadBlock;
211 fLastItem = NULL;
212 }
213
214 #define GrNEW_APPEND_TO_TBASELIST(list, type_name, args) \
215 (new (list, GrTBaseListAllocDesc<type_name>()) type_name args)
216
217 #define GrNEW_APPEND_WITH_DATA_TO_TBASELIST(list, type_name, args, extra_bytes_t o_allocate) \
218 (new (list, GrTBaseListAllocDesc<type_name>(extra_bytes_to_allocate)) type_n ame args)
219
220 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698