diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-12-21 15:36:33 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-12-21 15:36:33 +0000 |
commit | 5595af1b2ebe6590e98641464d43d22281a7f295 (patch) | |
tree | 0534fea47765d36fea593666cda4633241a61e65 /include | |
parent | 2859eb74f9c87471b2429cd12b84144b97157efb (diff) |
unify how we handle externally-provided storage in SkWriter32, with the goal
of simplifying the logic in reserve() so it can be inlined/accelerated.
Review URL: https://codereview.appspot.com/6962048
git-svn-id: http://skia.googlecode.com/svn/trunk@6923 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'include')
-rw-r--r-- | include/core/SkWriter32.h | 107 |
1 files changed, 81 insertions, 26 deletions
diff --git a/include/core/SkWriter32.h b/include/core/SkWriter32.h index 3f5a2433ed..3e0b012997 100644 --- a/include/core/SkWriter32.h +++ b/include/core/SkWriter32.h @@ -24,6 +24,7 @@ class SkStream; class SkWStream; class SkWriter32 : SkNoncopyable { + struct BlockHeader; public: /** * The caller can specify an initial block of storage, which the caller manages. @@ -36,35 +37,32 @@ public: SkWriter32(size_t minSize) : fMinSize(minSize), fSize(0), - fSingleBlock(NULL), - fSingleBlockSize(0), fWrittenBeforeLastBlock(0), fHead(NULL), - fTail(NULL), - fHeadIsExternalStorage(false) {} + fTail(NULL) {} ~SkWriter32(); - /** - * Returns the single block backing the writer, or NULL if the memory is - * to be dynamically allocated. - */ - void* getSingleBlock() const { return fSingleBlock; } - // return the current offset (will always be a multiple of 4) uint32_t bytesWritten() const { return fSize; } // DEPRECATED: use byetsWritten instead uint32_t size() const { return this->bytesWritten(); } void reset(); - uint32_t* reserve(size_t size); // size MUST be multiple of 4 + + // size MUST be multiple of 4 + uint32_t* reserve(size_t size) { + SkASSERT(SkAlign4(size) == size); + + Block* block = fTail; + if (NULL == block || block->available() < size) { + block = this->doReserve(size); + } + fSize += size; + return block->alloc(size); + } - /** - * Specify the single block to back the writer, rathern than dynamically - * allocating the memory. If block == NULL, then the writer reverts to - * dynamic allocation (and resets). - */ - void reset(void* block, size_t size); + void reset(void* storage, size_t size); bool writeBool(bool value) { this->writeInt(value); @@ -197,22 +195,79 @@ public: bool writeToStream(SkWStream*); private: - size_t fMinSize; - uint32_t fSize; + struct Block { + Block* fNext; + char* fBasePtr; + size_t fSizeOfBlock; // total space allocated (after this) + size_t fAllocatedSoFar; // space used so far + + size_t available() const { return fSizeOfBlock - fAllocatedSoFar; } + char* base() { return fBasePtr; } + const char* base() const { return fBasePtr; } + + uint32_t* alloc(size_t size) { + SkASSERT(SkAlign4(size) == size); + SkASSERT(this->available() >= size); + void* ptr = this->base() + fAllocatedSoFar; + fAllocatedSoFar += size; + SkASSERT(fAllocatedSoFar <= fSizeOfBlock); + return (uint32_t*)ptr; + } - char* fSingleBlock; - uint32_t fSingleBlockSize; + uint32_t* peek32(size_t offset) { + SkASSERT(offset <= fAllocatedSoFar + 4); + void* ptr = this->base() + offset; + return (uint32_t*)ptr; + } + + void rewind() { + fNext = NULL; + fAllocatedSoFar = 0; + // keep fSizeOfBlock as is + } + + static Block* Create(size_t size) { + SkASSERT(SkIsAlign4(size)); + Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); + block->fNext = NULL; + block->fBasePtr = (char*)(block + 1); + block->fSizeOfBlock = size; + block->fAllocatedSoFar = 0; + return block; + } + Block* initFromStorage(void* storage, size_t size) { + SkASSERT(SkIsAlign4((intptr_t)storage)); + SkASSERT(SkIsAlign4(size)); + Block* block = this; + block->fNext = NULL; + block->fBasePtr = (char*)storage; + block->fSizeOfBlock = size; + block->fAllocatedSoFar = 0; + return block; + } + }; + + enum { + MIN_BLOCKSIZE = sizeof(SkWriter32::Block) + sizeof(intptr_t) + }; + + Block fExternalBlock; + Block* fHead; + Block* fTail; + size_t fMinSize; + uint32_t fSize; // sum of bytes written in all blocks *before* fTail uint32_t fWrittenBeforeLastBlock; - struct Block; - Block* fHead; - Block* fTail; - - bool fHeadIsExternalStorage; + bool isHeadExternallyAllocated() const { + return fHead == &fExternalBlock; + } Block* newBlock(size_t bytes); + + // only call from reserve() + Block* doReserve(size_t bytes); SkDEBUGCODE(void validate() const;) }; |