diff options
-rw-r--r-- | include/core/SkOrderedWriteBuffer.h | 2 | ||||
-rw-r--r-- | include/core/SkWriter32.h | 19 | ||||
-rw-r--r-- | src/core/SkOrderedWriteBuffer.cpp | 5 | ||||
-rw-r--r-- | src/core/SkWriter32.cpp | 53 | ||||
-rw-r--r-- | tests/Writer32Test.cpp | 18 |
5 files changed, 89 insertions, 8 deletions
diff --git a/include/core/SkOrderedWriteBuffer.h b/include/core/SkOrderedWriteBuffer.h index 6183218af3..51daf5ca14 100644 --- a/include/core/SkOrderedWriteBuffer.h +++ b/include/core/SkOrderedWriteBuffer.h @@ -18,6 +18,8 @@ class SkOrderedWriteBuffer : public SkFlattenableWriteBuffer { public: SkOrderedWriteBuffer(size_t minSize); + SkOrderedWriteBuffer(size_t minSize, void* initialStorage, + size_t storageSize); virtual ~SkOrderedWriteBuffer() {} // deprecated naming convention that will be removed after callers are updated diff --git a/include/core/SkWriter32.h b/include/core/SkWriter32.h index 1b475958fb..c140850b9c 100644 --- a/include/core/SkWriter32.h +++ b/include/core/SkWriter32.h @@ -23,14 +23,23 @@ class SkWStream; class SkWriter32 : SkNoncopyable { public: + /** + * The caller can specify an initial block of storage, which the caller manages. + * SkWriter32 will not attempt to free this in its destructor. It is up to the + * implementation to decide if, and how much, of the storage to utilize, and it + * is possible that it may be ignored entirely. + */ + SkWriter32(size_t minSize, void* initialStorage, size_t storageSize); + SkWriter32(size_t minSize) : fMinSize(minSize), fSize(0), fSingleBlock(NULL), fSingleBlockSize(0), fHead(NULL), - fTail(NULL) { - } + fTail(NULL), + fHeadIsExternalStorage(false) {} + ~SkWriter32(); /** @@ -45,7 +54,7 @@ public: * dynamic allocation (and resets). */ void reset(void* block, size_t size); - + bool writeBool(bool value) { this->writeInt(value); return value; @@ -150,11 +159,13 @@ private: char* fSingleBlock; uint32_t fSingleBlockSize; - + struct Block; Block* fHead; Block* fTail; + bool fHeadIsExternalStorage; + Block* newBlock(size_t bytes); }; diff --git a/src/core/SkOrderedWriteBuffer.cpp b/src/core/SkOrderedWriteBuffer.cpp index bfe2bfc0b4..08938d0e5b 100644 --- a/src/core/SkOrderedWriteBuffer.cpp +++ b/src/core/SkOrderedWriteBuffer.cpp @@ -14,6 +14,11 @@ SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize) : fWriter(minSize) { } +SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize, void* storage, size_t storageSize) : + INHERITED(), + fWriter(minSize, storage, storageSize) { +} + void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) { /* * If we have a factoryset, then the first 32bits tell us... diff --git a/src/core/SkWriter32.cpp b/src/core/SkWriter32.cpp index dfa18a0c65..2ed65d4155 100644 --- a/src/core/SkWriter32.cpp +++ b/src/core/SkWriter32.cpp @@ -9,8 +9,8 @@ struct SkWriter32::Block { Block* fNext; - size_t fSize; - size_t fAllocated; + size_t fSize; // total space allocated (after this) + size_t fAllocated; // space used so far size_t available() const { return fSize - fAllocated; } char* base() { return (char*)(this + 1); } @@ -31,6 +31,12 @@ struct SkWriter32::Block { return (uint32_t*)ptr; } + void rewind() { + fNext = NULL; + fAllocated = 0; + // keep fSize as is + } + static Block* Create(size_t size) { SkASSERT(SkAlign4(size) == size); Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); @@ -39,16 +45,50 @@ struct SkWriter32::Block { block->fAllocated = 0; return block; } + + static Block* CreateFromStorage(void* storage, size_t size) { + SkASSERT(SkIsAlign4((intptr_t)storage)); + Block* block = (Block*)storage; + block->fNext = NULL; + block->fSize = size - sizeof(Block); + block->fAllocated = 0; + return block; + } + }; +#define MIN_BLOCKSIZE (sizeof(SkWriter32::Block) + sizeof(intptr_t)) + /////////////////////////////////////////////////////////////////////////////// +SkWriter32::SkWriter32(size_t minSize, void* storage, size_t storageSize) { + fMinSize = minSize; + fSize = 0; + fSingleBlock = NULL; + fSingleBlockSize = 0; + + storageSize &= ~3; // trunc down to multiple of 4 + if (storageSize >= MIN_BLOCKSIZE) { + fHead = fTail = Block::CreateFromStorage(storage, storageSize); + fHeadIsExternalStorage = true; + } else { + fHead = fTail = NULL; + fHeadIsExternalStorage = false; + } +} + SkWriter32::~SkWriter32() { this->reset(); } void SkWriter32::reset() { - Block* block = fHead; + Block* block = fHead; + + if (fHeadIsExternalStorage) { + SkASSERT(block); + // don't 'free' the first block, since it is owned by the caller + block = block->fNext; + } while (block) { Block* next = block->fNext; sk_free(block); @@ -56,8 +96,13 @@ void SkWriter32::reset() { } fSize = 0; - fHead = fTail = NULL; fSingleBlock = NULL; + if (fHeadIsExternalStorage) { + fHead->rewind(); + fTail = fHead; + } else { + fHead = fTail = NULL; + } } void SkWriter32::reset(void* block, size_t size) { diff --git a/tests/Writer32Test.cpp b/tests/Writer32Test.cpp index a9a07aded8..35fb29f38e 100644 --- a/tests/Writer32Test.cpp +++ b/tests/Writer32Test.cpp @@ -76,6 +76,24 @@ static void Tests(skiatest::Reporter* reporter) { writer.reset(storage, sizeof(storage)); test2(reporter, &writer); } + + // small storage + { + intptr_t storage[8]; + SkWriter32 writer(100, storage, sizeof(storage)); + test1(reporter, &writer); + writer.reset(); // should just rewind our storage + test2(reporter, &writer); + } + + // large storage + { + intptr_t storage[1024]; + SkWriter32 writer(100, storage, sizeof(storage)); + test1(reporter, &writer); + writer.reset(); // should just rewind our storage + test2(reporter, &writer); + } } #include "TestClassDef.h" |