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
diff --git a/src/core/SkWriter32.cpp b/src/core/SkWriter32.cpp
index 4bb83b3..b66a7fe 100644
--- a/src/core/SkWriter32.cpp
+++ b/src/core/SkWriter32.cpp
@@ -1,80 +1,20 @@
-
/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+
#include "SkWriter32.h"
-struct SkWriter32::Block {
- Block* fNext;
- 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 (char*)(this + 1); }
- const char* base() const { return (const char*)(this + 1); }
-
- 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;
- }
-
- 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(SkAlign4(size) == size);
- Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
- block->fNext = NULL;
- block->fSizeOfBlock = size;
- block->fAllocatedSoFar = 0;
- return block;
- }
-
- static Block* CreateFromStorage(void* storage, size_t size) {
- SkASSERT(SkIsAlign4((intptr_t)storage));
- Block* block = (Block*)storage;
- block->fNext = NULL;
- block->fSizeOfBlock = size - sizeof(Block);
- block->fAllocatedSoFar = 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;
fWrittenBeforeLastBlock = 0;
+ fHead = fTail = NULL;
- 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;
+ if (storageSize) {
+ this->reset(storage, storageSize);
}
}
@@ -85,7 +25,7 @@
void SkWriter32::reset() {
Block* block = fHead;
- if (fHeadIsExternalStorage) {
+ if (this->isHeadExternallyAllocated()) {
SkASSERT(block);
// don't 'free' the first block, since it is owned by the caller
block = block->fNext;
@@ -98,40 +38,29 @@
fSize = 0;
fWrittenBeforeLastBlock = 0;
- fSingleBlock = NULL;
- if (fHeadIsExternalStorage) {
- SkASSERT(fHead);
- fHead->rewind();
- fTail = fHead;
- } else {
- fHead = fTail = NULL;
+ fHead = fTail = NULL;
+}
+
+void SkWriter32::reset(void* storage, size_t storageSize) {
+ this->reset();
+
+ storageSize &= ~3; // trunc down to multiple of 4
+ if (storageSize > 0 && SkIsAlign4((intptr_t)storage)) {
+ fHead = fTail = fExternalBlock.initFromStorage(storage, storageSize);
}
}
-void SkWriter32::reset(void* block, size_t size) {
- this->reset();
- SkASSERT(0 == ((fSingleBlock - (char*)0) & 3)); // need 4-byte alignment
- fSingleBlock = (char*)block;
- fSingleBlockSize = (size & ~3);
-}
-
-uint32_t* SkWriter32::reserve(size_t size) {
+SkWriter32::Block* SkWriter32::doReserve(size_t size) {
SkASSERT(SkAlign4(size) == size);
- if (fSingleBlock) {
- uint32_t* ptr = (uint32_t*)(fSingleBlock + fSize);
- fSize += size;
- SkASSERT(fSize <= fSingleBlockSize);
- return ptr;
- }
-
Block* block = fTail;
+ SkASSERT(NULL == block || block->available() < size);
if (NULL == block) {
SkASSERT(NULL == fHead);
fHead = fTail = block = Block::Create(SkMax32(size, fMinSize));
SkASSERT(0 == fWrittenBeforeLastBlock);
- } else if (block->available() < size) {
+ } else {
SkASSERT(fSize > 0);
fWrittenBeforeLastBlock = fSize;
@@ -139,10 +68,7 @@
block->fNext = fTail;
block = fTail;
}
-
- fSize += size;
-
- return block->alloc(size);
+ return block;
}
uint32_t* SkWriter32::peek32(size_t offset) {
@@ -151,10 +77,6 @@
SkASSERT(SkAlign4(offset) == offset);
SkASSERT(offset <= fSize);
- if (fSingleBlock) {
- return (uint32_t*)(fSingleBlock + offset);
- }
-
// try the fast case, where offset is within fTail
if (offset >= fWrittenBeforeLastBlock) {
return fTail->peek32(offset - fWrittenBeforeLastBlock);
@@ -176,7 +98,7 @@
return;
}
if (0 == offset) {
- this->reset(NULL, 0);
+ this->reset();
return;
}
@@ -186,10 +108,6 @@
SkASSERT(offset <= fSize);
fSize = offset;
- if (fSingleBlock) {
- return;
- }
-
// Try the fast case, where offset is within fTail
if (offset >= fWrittenBeforeLastBlock) {
fTail->fAllocatedSoFar = offset - fWrittenBeforeLastBlock;
@@ -227,11 +145,6 @@
}
void SkWriter32::flatten(void* dst) const {
- if (fSingleBlock) {
- memcpy(dst, fSingleBlock, fSize);
- return;
- }
-
const Block* block = fHead;
SkDEBUGCODE(size_t total = 0;)
@@ -270,17 +183,6 @@
#include "SkStream.h"
size_t SkWriter32::readFromStream(SkStream* stream, size_t length) {
- if (fSingleBlock) {
- SkASSERT(fSingleBlockSize >= fSize);
- size_t remaining = fSingleBlockSize - fSize;
- if (length > remaining) {
- length = remaining;
- }
- stream->read(fSingleBlock + fSize, length);
- fSize += length;
- return length;
- }
-
char scratch[1024];
const size_t MAX = sizeof(scratch);
size_t remaining = length;
@@ -301,10 +203,6 @@
}
bool SkWriter32::writeToStream(SkWStream* stream) {
- if (fSingleBlock) {
- return stream->write(fSingleBlock, fSize);
- }
-
const Block* block = fHead;
while (block) {
if (!stream->write(block->base(), block->fAllocatedSoFar)) {
@@ -318,12 +216,6 @@
#ifdef SK_DEBUG
void SkWriter32::validate() const {
SkASSERT(SkIsAlign4(fSize));
- SkASSERT(SkIsAlign4(fSingleBlockSize));
-
- if (fSingleBlock) {
- SkASSERT(fSize <= fSingleBlockSize);
- return;
- }
size_t accum = 0;
const Block* block = fHead;