diff options
author | 2012-12-07 17:48:04 +0000 | |
---|---|---|
committer | 2012-12-07 17:48:04 +0000 | |
commit | f56225c848cb0cd0fde4cb37558174ae096b93d1 (patch) | |
tree | 051d8cf769345784f26467823b7c6d57312bb3a6 /src | |
parent | 0b6dc190bb3723375a85ac47855bb663aba9ce0c (diff) |
speedup peek32() when the offset is in the last block (fTail)
Review URL: https://codereview.appspot.com/6906047
git-svn-id: http://skia.googlecode.com/svn/trunk@6708 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkWriter32.cpp | 61 |
1 files changed, 43 insertions, 18 deletions
diff --git a/src/core/SkWriter32.cpp b/src/core/SkWriter32.cpp index 6a8492731b..ce240c25f5 100644 --- a/src/core/SkWriter32.cpp +++ b/src/core/SkWriter32.cpp @@ -66,6 +66,7 @@ SkWriter32::SkWriter32(size_t minSize, void* storage, size_t storageSize) { fSize = 0; fSingleBlock = NULL; fSingleBlockSize = 0; + fWrittenBeforeLastBlock = 0; storageSize &= ~3; // trunc down to multiple of 4 if (storageSize >= MIN_BLOCKSIZE) { @@ -96,6 +97,7 @@ void SkWriter32::reset() { } fSize = 0; + fWrittenBeforeLastBlock = 0; fSingleBlock = NULL; if (fHeadIsExternalStorage) { SkASSERT(fHead); @@ -128,7 +130,11 @@ uint32_t* SkWriter32::reserve(size_t size) { if (NULL == block) { SkASSERT(NULL == fHead); fHead = fTail = block = Block::Create(SkMax32(size, fMinSize)); + SkASSERT(0 == fWrittenBeforeLastBlock); } else if (block->available() < size) { + SkASSERT(fSize > 0); + fWrittenBeforeLastBlock = fSize; + fTail = Block::Create(SkMax32(size, fMinSize)); block->fNext = fTail; block = fTail; @@ -149,6 +155,11 @@ uint32_t* SkWriter32::peek32(size_t offset) { return (uint32_t*)(fSingleBlock + offset); } + // try the fast case, where offset is within fTail + if (offset >= fWrittenBeforeLastBlock) { + return fTail->peek32(offset - fWrittenBeforeLastBlock); + } + Block* block = fHead; SkASSERT(NULL != block); @@ -179,29 +190,39 @@ void SkWriter32::rewindToOffset(size_t offset) { return; } - // Similar to peek32, except that we free up any following blocks - Block* block = fHead; - SkASSERT(NULL != block); - while (offset >= block->fAllocatedSoFar) { - offset -= block->fAllocatedSoFar; - block = block->fNext; + // Try the fast case, where offset is within fTail + if (offset >= fWrittenBeforeLastBlock) { + fTail->fAllocatedSoFar = offset - fWrittenBeforeLastBlock; + } else { + // Similar to peek32, except that we free up any following blocks. + // We have to re-compute fWrittenBeforeLastBlock as well. + + size_t globalOffset = offset; + Block* block = fHead; SkASSERT(NULL != block); - } + while (offset >= block->fAllocatedSoFar) { + offset -= block->fAllocatedSoFar; + block = block->fNext; + SkASSERT(NULL != block); + } - // update the size on the "last" block - block->fAllocatedSoFar = offset; - // end our list - fTail = block; - Block* next = block->fNext; - block->fNext = NULL; - // free up any trailing blocks - block = next; - while (block) { + // this has to be recomputed, since we may free up fTail + fWrittenBeforeLastBlock = globalOffset - offset; + + // update the size on the "last" block + block->fAllocatedSoFar = offset; + // end our list + fTail = block; Block* next = block->fNext; - sk_free(block); + block->fNext = NULL; + // free up any trailing blocks block = next; + while (block) { + Block* next = block->fNext; + sk_free(block); + block = next; + } } - SkDEBUGCODE(this->validate();) } @@ -310,6 +331,10 @@ void SkWriter32::validate() const { SkASSERT(SkIsAlign4(block->fSizeOfBlock)); SkASSERT(SkIsAlign4(block->fAllocatedSoFar)); SkASSERT(block->fAllocatedSoFar <= block->fSizeOfBlock); + if (NULL == block->fNext) { + SkASSERT(fTail == block); + SkASSERT(fWrittenBeforeLastBlock == accum); + } accum += block->fAllocatedSoFar; SkASSERT(accum <= fSize); block = block->fNext; |