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

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: 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
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 this->reset(external, externalBytes); 34 : fData((uint8_t*)external)
35 , fCapacity(externalBytes)
36 , fUsed(0)
37 , fExternal(external)
38 {
39 SkASSERT(SkIsAlign4((uintptr_t)external));
40 SkASSERT(SkIsAlign4(externalBytes));
reed1 2014/02/06 20:14:40 or we could just trim the low bits off of external
iancottrell 2014/02/06 21:33:06 I was staying compatible with the contract it used
reed1 2014/02/06 21:41:34 Sure, separate CL or not at all.
35 } 41 }
36 42
37 // return the current offset (will always be a multiple of 4) 43 // return the current offset (will always be a multiple of 4)
38 size_t bytesWritten() const { return fCount * 4; } 44 size_t bytesWritten() const { return fUsed; }
39 45
40 SK_ATTR_DEPRECATED("use bytesWritten") 46 SK_ATTR_DEPRECATED("use bytesWritten")
41 size_t size() const { return this->bytesWritten(); } 47 size_t size() const { return this->bytesWritten(); }
42 48
43 void reset(void* external = NULL, size_t externalBytes = 0) { 49 void reset(void* external = NULL, size_t externalBytes = 0) {
44 SkASSERT(SkIsAlign4((uintptr_t)external)); 50 SkASSERT(SkIsAlign4((uintptr_t)external));
45 SkASSERT(SkIsAlign4(externalBytes)); 51 SkASSERT(SkIsAlign4(externalBytes));
46 fExternal = (uint32_t*)external; 52
47 fExternalLimit = SkToInt(externalBytes/4); 53 fData = (uint8_t*)external;
48 fCount = 0; 54 fCapacity = externalBytes;
49 fInternal.rewind(); 55 fUsed = 0;
56 fExternal = external;
50 } 57 }
51 58
52 // If all data written is contiguous, then this returns a pointer to it, oth erwise NULL. 59 // Returns the current buffer.
53 // This will work if we've only written to the externally supplied block of storage, or if we've 60 // The pointer may be invalidated by any future write calls.
reed1 2014/02/06 20:14:40 Does this guy always return all of the space writt
iancottrell 2014/02/06 21:33:06 I am trying hard to not change the public interfac
reed1 2014/02/06 21:41:34 I'm mostly asking that we well-document the API, a
mtklein 2014/02/06 22:01:24 Right, SkPictureFlat wants read-only contiguous ac
iancottrell 2014/02/07 12:20:40 Yes, let's just deprecate this method, the two use
54 // only written to our internal dynamic storage, but will fail if we have wr itten into both.
55 const uint32_t* contiguousArray() const { 61 const uint32_t* contiguousArray() const {
56 if (this->externalCount() == 0) { 62 return (uint32_t*)fData;
57 return fInternal.begin();
58 } else if (fInternal.isEmpty()) {
59 return fExternal;
60 }
61 return NULL;
62 } 63 }
63 64
64 // size MUST be multiple of 4 65 // size MUST be multiple of 4
65 uint32_t* reserve(size_t size) { 66 uint32_t* reserve(size_t size) {
66 SkASSERT(SkAlign4(size) == size); 67 SkASSERT(SkAlign4(size) == size);
67 const int count = SkToInt(size/4); 68 size_t offset = fUsed;
68 69 size_t used = fUsed + size;
69 uint32_t* p; 70 if (used > fCapacity) { grow(used); }
reed1 2014/02/06 20:14:40 style nit: skia always wants the body on the next
reed1 2014/02/06 20:14:40 Perhaps a comment that we are passing "used" as th
iancottrell 2014/02/06 21:33:06 Done.
iancottrell 2014/02/06 21:33:06 used is the space used in total after the current
reed1 2014/02/06 21:41:34 I think here the value is just knowing what the me
70 // Once we start writing to fInternal, we never write to fExternal again . 71 fUsed = used;
71 // This simplifies tracking what data is where. 72 return (uint32_t*)(fData+offset);
reed1 2014/02/06 20:14:40 style nit: skia likes spaces around binary operato
iancottrell 2014/02/06 21:33:06 Done.
72 if (fInternal.isEmpty() && this->externalCount() + count <= fExternalLim it) {
73 p = fExternal + fCount;
74 } else {
75 p = fInternal.append(count);
76 }
77
78 fCount += count;
79 return p;
80 } 73 }
81 74
82 // Read or write 4 bytes at offset, which must be a multiple of 4 <= size(). 75 // 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); } 76 uint32_t read32At(size_t offset) {
84 void write32At(size_t offset, uint32_t val) { this->atOffset(offset) = val; } 77 SkASSERT(SkAlign4(offset) == offset);
78 SkASSERT(offset < fUsed);
79 return *(uint32_t*)(fData+offset);
80 }
81
82 void write32At(size_t offset, uint32_t val) {
83 SkASSERT(SkAlign4(offset) == offset);
84 SkASSERT(offset < fUsed);
85 *(uint32_t*)(fData+offset) = val;
86 }
85 87
86 bool writeBool(bool value) { 88 bool writeBool(bool value) {
87 this->write32(value); 89 this->write32(value);
88 return value; 90 return value;
89 } 91 }
90 92
91 void writeInt(int32_t value) { 93 void writeInt(int32_t value) {
92 this->write32(value); 94 this->write32(value);
93 } 95 }
94 96
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 void writeMul4(const void* values, size_t size) { 152 void writeMul4(const void* values, size_t size) {
151 this->write(values, size); 153 this->write(values, size);
152 } 154 }
153 155
154 /** 156 /**
155 * Write size bytes from values. size must be a multiple of 4, though 157 * Write size bytes from values. size must be a multiple of 4, though
156 * values need not be 4-byte aligned. 158 * values need not be 4-byte aligned.
157 */ 159 */
158 void write(const void* values, size_t size) { 160 void write(const void* values, size_t size) {
159 SkASSERT(SkAlign4(size) == size); 161 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); 162 memcpy(this->reserve(size), values, size);
163 } 163 }
164 164
165 /** 165 /**
166 * Reserve size bytes. Does not need to be 4 byte aligned. The remaining sp ace (if any) will be 166 * Reserve size bytes. Does not need to be 4 byte aligned. The remaining sp ace (if any) will be
167 * filled in with zeroes. 167 * filled in with zeroes.
168 */ 168 */
169 uint32_t* reservePad(size_t size) { 169 uint32_t* reservePad(size_t size) {
170 uint32_t* p = this->reserve(SkAlign4(size)); 170 uint32_t* p = this->reserve(SkAlign4(size));
171 uint8_t* tail = (uint8_t*)p + size; 171 uint8_t* tail = (uint8_t*)p + size;
(...skipping 30 matching lines...) Expand all
202 * computed by calling strlen(). 202 * computed by calling strlen().
203 */ 203 */
204 static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); 204 static size_t WriteStringSize(const char* str, size_t len = (size_t)-1);
205 205
206 /** 206 /**
207 * Move the cursor back to offset bytes from the beginning. 207 * Move the cursor back to offset bytes from the beginning.
208 * offset must be a multiple of 4 no greater than size(). 208 * offset must be a multiple of 4 no greater than size().
209 */ 209 */
210 void rewindToOffset(size_t offset) { 210 void rewindToOffset(size_t offset) {
211 SkASSERT(SkAlign4(offset) == offset); 211 SkASSERT(SkAlign4(offset) == offset);
212 const int count = SkToInt(offset/4); 212 SkASSERT(offset <= bytesWritten());
213 if (count < this->externalCount()) { 213 fUsed = offset;
214 fInternal.setCount(0);
215 } else {
216 fInternal.setCount(count - this->externalCount());
217 }
218 fCount = count;
219 } 214 }
220 215
221 // copy into a single buffer (allocated by caller). Must be at least size() 216 // copy into a single buffer (allocated by caller). Must be at least size()
222 void flatten(void* dst) const { 217 void flatten(void* dst) const {
223 const size_t externalBytes = this->externalCount()*4; 218 memcpy(dst, fData, fUsed);
224 memcpy(dst, fExternal, externalBytes);
225 dst = (uint8_t*)dst + externalBytes;
226 memcpy(dst, fInternal.begin(), fInternal.bytes());
227 } 219 }
228 220
229 bool writeToStream(SkWStream* stream) const { 221 bool writeToStream(SkWStream* stream) const {
230 return stream->write(fExternal, this->externalCount()*4) 222 return stream->write(fData, fUsed);
231 && stream->write(fInternal.begin(), fInternal.bytes());
232 } 223 }
233 224
234 // read from the stream, and write up to length bytes. Return the actual 225 // read from the stream, and write up to length bytes. Return the actual
235 // number of bytes written. 226 // number of bytes written.
236 size_t readFromStream(SkStream* stream, size_t length) { 227 size_t readFromStream(SkStream* stream, size_t length) {
237 return stream->read(this->reservePad(length), length); 228 return stream->read(this->reservePad(length), length);
238 } 229 }
239 230
240 private: 231 private:
241 uint32_t& atOffset(size_t offset) { 232 void grow(size_t size);
reed1 2014/02/06 20:14:40 // size is the number of bytes we want to grow by,
iancottrell 2014/02/06 21:33:06 size is the new minimum size. Maybe calling the fu
reed1 2014/02/06 21:41:34 That seems much clearer.
242 SkASSERT(SkAlign4(offset) == offset);
243 const int count = SkToInt(offset/4);
244 SkASSERT(count < fCount);
245 233
246 if (count < this->externalCount()) { 234 uint8_t* fData; // Points to either fInternal or fExternal.
247 return fExternal[count]; 235 size_t fCapacity; // Number of bytes we can write to fData.
248 } 236 size_t fUsed; // Number of bytes written.
249 return fInternal[count - this->externalCount()]; 237 void* fExternal; // Unmanaged memory block.
250 } 238 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 }; 239 };
261 240
262 /** 241 /**
263 * Helper class to allocated SIZE bytes as part of the writer, and to provide 242 * 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. 243 * that storage to the constructor as its initial storage buffer.
265 * 244 *
266 * This wrapper ensures proper alignment rules are met for the storage. 245 * This wrapper ensures proper alignment rules are met for the storage.
267 */ 246 */
268 template <size_t SIZE> class SkSWriter32 : public SkWriter32 { 247 template <size_t SIZE> class SkSWriter32 : public SkWriter32 {
269 public: 248 public:
270 SkSWriter32() : SkWriter32(fData.fStorage, SIZE) {} 249 SkSWriter32() : SkWriter32(fData.fStorage, SIZE) {}
271 250
272 private: 251 private:
273 union { 252 union {
274 void* fPtrAlignment; 253 void* fPtrAlignment;
275 double fDoubleAlignment; 254 double fDoubleAlignment;
276 char fStorage[SIZE]; 255 char fStorage[SIZE];
277 } fData; 256 } fData;
278 }; 257 };
279 258
280 #endif 259 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698