Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |