aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-07 17:48:04 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-07 17:48:04 +0000
commitf56225c848cb0cd0fde4cb37558174ae096b93d1 (patch)
tree051d8cf769345784f26467823b7c6d57312bb3a6 /src
parent0b6dc190bb3723375a85ac47855bb663aba9ce0c (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.cpp61
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;