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

Side by Side Diff: include/core/SkWriter32.h

Issue 156683004: Cleaner external buffer handling in SkWriter32 (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Make the SkWriter32 constructor call reset Created 6 years, 10 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 | « include/core/SkTDArray.h ('k') | src/core/SkWriter32.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 /* 2 /*
3 * Copyright 2008 The Android Open Source Project 3 * Copyright 2008 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #ifndef SkWriter32_DEFINED 10 #ifndef SkWriter32_DEFINED
(...skipping 12 matching lines...) Expand all
23 23
24 class SkWriter32 : SkNoncopyable { 24 class SkWriter32 : SkNoncopyable {
25 public: 25 public:
26 /** 26 /**
27 * The caller can specify an initial block of storage, which the caller man ages. 27 * The caller can specify an initial block of storage, which the caller man ages.
28 * 28 *
29 * SkWriter32 will try to back reserve and write calls with this external s torage until the 29 * SkWriter32 will try to back reserve and write calls with this external s torage until the
30 * first time an allocation doesn't fit. From then it will use dynamically allocated storage. 30 * first time an allocation doesn't fit. From then it will use dynamically allocated storage.
31 * This used to be optional behavior, but pipe now relies on it. 31 * This used to be optional behavior, but pipe now relies on it.
32 */ 32 */
33 SkWriter32(void* external = NULL, size_t externalBytes = 0) { 33 SkWriter32(void* external = NULL, size_t externalBytes = 0)
34 : fData(0)
35 , fCapacity(0)
36 , fUsed(0)
37 , fExternal(0)
38 {
34 this->reset(external, externalBytes); 39 this->reset(external, externalBytes);
35 } 40 }
36 41
37 // return the current offset (will always be a multiple of 4) 42 // return the current offset (will always be a multiple of 4)
38 size_t bytesWritten() const { return fCount * 4; } 43 size_t bytesWritten() const { return fUsed; }
39 44
40 SK_ATTR_DEPRECATED("use bytesWritten") 45 SK_ATTR_DEPRECATED("use bytesWritten")
41 size_t size() const { return this->bytesWritten(); } 46 size_t size() const { return this->bytesWritten(); }
42 47
43 void reset(void* external = NULL, size_t externalBytes = 0) { 48 void reset(void* external = NULL, size_t externalBytes = 0) {
44 SkASSERT(SkIsAlign4((uintptr_t)external)); 49 SkASSERT(SkIsAlign4((uintptr_t)external));
45 SkASSERT(SkIsAlign4(externalBytes)); 50 SkASSERT(SkIsAlign4(externalBytes));
46 fExternal = (uint32_t*)external; 51
47 fExternalLimit = SkToInt(externalBytes/4); 52 fData = (uint8_t*)external;
48 fCount = 0; 53 fCapacity = externalBytes;
49 fInternal.rewind(); 54 fUsed = 0;
55 fExternal = external;
50 } 56 }
51 57
52 // If all data written is contiguous, then this returns a pointer to it, oth erwise NULL. 58 // Returns the current buffer.
53 // This will work if we've only written to the externally supplied block of storage, or if we've 59 // The pointer may be invalidated by any future write calls.
54 // only written to our internal dynamic storage, but will fail if we have wr itten into both.
55 const uint32_t* contiguousArray() const { 60 const uint32_t* contiguousArray() const {
56 if (this->externalCount() == 0) { 61 return (uint32_t*)fData;
57 return fInternal.begin();
58 } else if (fInternal.isEmpty()) {
59 return fExternal;
60 }
61 return NULL;
62 } 62 }
63 63
64 // size MUST be multiple of 4 64 // size MUST be multiple of 4
65 uint32_t* reserve(size_t size) { 65 uint32_t* reserve(size_t size) {
66 SkASSERT(SkAlign4(size) == size); 66 SkASSERT(SkAlign4(size) == size);
67 const int count = SkToInt(size/4); 67 size_t offset = fUsed;
68 68 size_t totalRequired = fUsed + size;
69 uint32_t* p; 69 if (totalRequired > fCapacity) {
70 // Once we start writing to fInternal, we never write to fExternal again . 70 growToAtLeast(totalRequired);
71 // This simplifies tracking what data is where.
72 if (fInternal.isEmpty() && this->externalCount() + count <= fExternalLim it) {
73 p = fExternal + fCount;
74 } else {
75 p = fInternal.append(count);
76 } 71 }
77 72 fUsed = totalRequired;
78 fCount += count; 73 return (uint32_t*)(fData + offset);
79 return p;
80 } 74 }
81 75
82 // Read or write 4 bytes at offset, which must be a multiple of 4 <= size(). 76 // Read or write 4 bytes at offset, which must be a multiple of 4 <= size().
83 uint32_t read32At(size_t offset) { return this->atOffset(offset); } 77 uint32_t read32At(size_t offset) {
84 void write32At(size_t offset, uint32_t val) { this->atOffset(offset) = val; } 78 SkASSERT(SkAlign4(offset) == offset);
79 SkASSERT(offset < fUsed);
80 return *(uint32_t*)(fData + offset);
81 }
82
83 void write32At(size_t offset, uint32_t val) {
84 SkASSERT(SkAlign4(offset) == offset);
85 SkASSERT(offset < fUsed);
86 *(uint32_t*)(fData + offset) = val;
87 }
85 88
86 bool writeBool(bool value) { 89 bool writeBool(bool value) {
87 this->write32(value); 90 this->write32(value);
88 return value; 91 return value;
89 } 92 }
90 93
91 void writeInt(int32_t value) { 94 void writeInt(int32_t value) {
92 this->write32(value); 95 this->write32(value);
93 } 96 }
94 97
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 void writeMul4(const void* values, size_t size) { 153 void writeMul4(const void* values, size_t size) {
151 this->write(values, size); 154 this->write(values, size);
152 } 155 }
153 156
154 /** 157 /**
155 * Write size bytes from values. size must be a multiple of 4, though 158 * Write size bytes from values. size must be a multiple of 4, though
156 * values need not be 4-byte aligned. 159 * values need not be 4-byte aligned.
157 */ 160 */
158 void write(const void* values, size_t size) { 161 void write(const void* values, size_t size) {
159 SkASSERT(SkAlign4(size) == size); 162 SkASSERT(SkAlign4(size) == size);
160 // TODO: If we're going to spill from fExternal to fInternal, we might w ant to fill
161 // fExternal as much as possible before writing to fInternal.
162 memcpy(this->reserve(size), values, size); 163 memcpy(this->reserve(size), values, size);
163 } 164 }
164 165
165 /** 166 /**
166 * Reserve size bytes. Does not need to be 4 byte aligned. The remaining sp ace (if any) will be 167 * Reserve size bytes. Does not need to be 4 byte aligned. The remaining sp ace (if any) will be
167 * filled in with zeroes. 168 * filled in with zeroes.
168 */ 169 */
169 uint32_t* reservePad(size_t size) { 170 uint32_t* reservePad(size_t size) {
170 uint32_t* p = this->reserve(SkAlign4(size)); 171 uint32_t* p = this->reserve(SkAlign4(size));
171 uint8_t* tail = (uint8_t*)p + size; 172 uint8_t* tail = (uint8_t*)p + size;
(...skipping 30 matching lines...) Expand all
202 * computed by calling strlen(). 203 * computed by calling strlen().
203 */ 204 */
204 static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); 205 static size_t WriteStringSize(const char* str, size_t len = (size_t)-1);
205 206
206 /** 207 /**
207 * Move the cursor back to offset bytes from the beginning. 208 * Move the cursor back to offset bytes from the beginning.
208 * offset must be a multiple of 4 no greater than size(). 209 * offset must be a multiple of 4 no greater than size().
209 */ 210 */
210 void rewindToOffset(size_t offset) { 211 void rewindToOffset(size_t offset) {
211 SkASSERT(SkAlign4(offset) == offset); 212 SkASSERT(SkAlign4(offset) == offset);
212 const int count = SkToInt(offset/4); 213 SkASSERT(offset <= bytesWritten());
213 if (count < this->externalCount()) { 214 fUsed = offset;
214 fInternal.setCount(0);
215 } else {
216 fInternal.setCount(count - this->externalCount());
217 }
218 fCount = count;
219 } 215 }
220 216
221 // copy into a single buffer (allocated by caller). Must be at least size() 217 // copy into a single buffer (allocated by caller). Must be at least size()
222 void flatten(void* dst) const { 218 void flatten(void* dst) const {
223 const size_t externalBytes = this->externalCount()*4; 219 memcpy(dst, fData, fUsed);
224 memcpy(dst, fExternal, externalBytes);
225 dst = (uint8_t*)dst + externalBytes;
226 memcpy(dst, fInternal.begin(), fInternal.bytes());
227 } 220 }
228 221
229 bool writeToStream(SkWStream* stream) const { 222 bool writeToStream(SkWStream* stream) const {
230 return stream->write(fExternal, this->externalCount()*4) 223 return stream->write(fData, fUsed);
231 && stream->write(fInternal.begin(), fInternal.bytes());
232 } 224 }
233 225
234 // read from the stream, and write up to length bytes. Return the actual 226 // read from the stream, and write up to length bytes. Return the actual
235 // number of bytes written. 227 // number of bytes written.
236 size_t readFromStream(SkStream* stream, size_t length) { 228 size_t readFromStream(SkStream* stream, size_t length) {
237 return stream->read(this->reservePad(length), length); 229 return stream->read(this->reservePad(length), length);
238 } 230 }
239 231
240 private: 232 private:
241 uint32_t& atOffset(size_t offset) { 233 void growToAtLeast(size_t size);
242 SkASSERT(SkAlign4(offset) == offset);
243 const int count = SkToInt(offset/4);
244 SkASSERT(count < fCount);
245 234
246 if (count < this->externalCount()) { 235 uint8_t* fData; // Points to either fInternal or fExternal.
247 return fExternal[count]; 236 size_t fCapacity; // Number of bytes we can write to fData.
248 } 237 size_t fUsed; // Number of bytes written.
249 return fInternal[count - this->externalCount()]; 238 void* fExternal; // Unmanaged memory block.
250 } 239 SkTDArray<uint8_t> fInternal; // Managed memory block.
251
252
253 // Number of uint32_t written into fExternal. <= fExternalLimit.
254 int externalCount() const { return fCount - fInternal.count(); }
255
256 int fCount; // Total number of uint32_t written.
257 int fExternalLimit; // Number of uint32_t we can write to fExter nal.
258 uint32_t* fExternal; // Unmanaged memory block.
259 SkTDArray<uint32_t> fInternal; // Managed memory block.
260 }; 240 };
261 241
262 /** 242 /**
263 * Helper class to allocated SIZE bytes as part of the writer, and to provide 243 * Helper class to allocated SIZE bytes as part of the writer, and to provide
264 * that storage to the constructor as its initial storage buffer. 244 * that storage to the constructor as its initial storage buffer.
265 * 245 *
266 * This wrapper ensures proper alignment rules are met for the storage. 246 * This wrapper ensures proper alignment rules are met for the storage.
267 */ 247 */
268 template <size_t SIZE> class SkSWriter32 : public SkWriter32 { 248 template <size_t SIZE> class SkSWriter32 : public SkWriter32 {
269 public: 249 public:
270 SkSWriter32() : SkWriter32(fData.fStorage, SIZE) {} 250 SkSWriter32() : SkWriter32(fData.fStorage, SIZE) {}
271 251
272 private: 252 private:
273 union { 253 union {
274 void* fPtrAlignment; 254 void* fPtrAlignment;
275 double fDoubleAlignment; 255 double fDoubleAlignment;
276 char fStorage[SIZE]; 256 char fStorage[SIZE];
277 } fData; 257 } fData;
278 }; 258 };
279 259
280 #endif 260 #endif
OLDNEW
« no previous file with comments | « include/core/SkTDArray.h ('k') | src/core/SkWriter32.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698