| Index: src/core/SkChunkAlloc.cpp
|
| diff --git a/src/core/SkChunkAlloc.cpp b/src/core/SkChunkAlloc.cpp
|
| index 62cdf1532f75b15738c296cf786d24b23ed1dfa0..dec50c99aa7952a81bf08cd3b4e934c2677d1fa2 100644
|
| --- a/src/core/SkChunkAlloc.cpp
|
| +++ b/src/core/SkChunkAlloc.cpp
|
| @@ -23,6 +23,18 @@ struct SkChunkAlloc::Block {
|
| char* fFreePtr;
|
| // data[] follows
|
|
|
| + size_t blockSize() {
|
| + char* start = this->startOfData();
|
| + size_t bytes = fFreePtr - start;
|
| + return fFreeSize + bytes;
|
| + }
|
| +
|
| + void reset() {
|
| + fNext = NULL;
|
| + fFreeSize = this->blockSize();
|
| + fFreePtr = this->startOfData();
|
| + }
|
| +
|
| char* startOfData() {
|
| return reinterpret_cast<char*>(this + 1);
|
| }
|
| @@ -69,6 +81,34 @@ void SkChunkAlloc::reset() {
|
| fBlockCount = 0;
|
| }
|
|
|
| +void SkChunkAlloc::rewind() {
|
| + Block* largest = fBlock;
|
| +
|
| + if (largest) {
|
| + Block* next;
|
| + for (Block* cur = largest->fNext; cur; cur = next) {
|
| + next = cur->fNext;
|
| + if (cur->blockSize() > largest->blockSize()) {
|
| + sk_free(largest);
|
| + largest = cur;
|
| + } else {
|
| + sk_free(cur);
|
| + }
|
| + }
|
| +
|
| + largest->reset();
|
| + fTotalCapacity = largest->blockSize();
|
| + fBlockCount = 1;
|
| + } else {
|
| + fTotalCapacity = 0;
|
| + fBlockCount = 0;
|
| + }
|
| +
|
| + fBlock = largest;
|
| + fChunkSize = fMinSize; // reset to our initial minSize
|
| + fTotalUsed = 0;
|
| +}
|
| +
|
| SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
|
| size_t size = bytes;
|
| if (size < fChunkSize) {
|
| @@ -79,7 +119,6 @@ SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
|
| ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0);
|
|
|
| if (block) {
|
| - // block->fNext = fBlock;
|
| block->fFreeSize = size;
|
| block->fFreePtr = block->startOfData();
|
|
|
| @@ -91,23 +130,38 @@ SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
|
| return block;
|
| }
|
|
|
| -void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) {
|
| - fTotalUsed += bytes;
|
| -
|
| - bytes = SkAlign4(bytes);
|
| +SkChunkAlloc::Block* SkChunkAlloc::addBlockIfNecessary(size_t bytes, AllocFailType ftype) {
|
| + SkASSERT(SkIsAlign4(bytes));
|
|
|
| - Block* block = fBlock;
|
| -
|
| - if (block == NULL || bytes > block->fFreeSize) {
|
| - block = this->newBlock(bytes, ftype);
|
| - if (NULL == block) {
|
| + if (!fBlock || bytes > fBlock->fFreeSize) {
|
| + Block* block = this->newBlock(bytes, ftype);
|
| + if (!block) {
|
| return NULL;
|
| }
|
| block->fNext = fBlock;
|
| fBlock = block;
|
| }
|
|
|
| - SkASSERT(block && bytes <= block->fFreeSize);
|
| + SkASSERT(fBlock && bytes <= fBlock->fFreeSize);
|
| + return fBlock;
|
| +}
|
| +
|
| +void SkChunkAlloc::preAlloc(size_t bytes) {
|
| + bytes = SkAlign4(bytes);
|
| +
|
| + this->addBlockIfNecessary(bytes, kReturnNil_AllocFailType);
|
| +}
|
| +
|
| +void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) {
|
| + fTotalUsed += bytes;
|
| +
|
| + bytes = SkAlign4(bytes);
|
| +
|
| + Block* block = this->addBlockIfNecessary(bytes, ftype);
|
| + if (!block) {
|
| + return NULL;
|
| + }
|
| +
|
| char* ptr = block->fFreePtr;
|
|
|
| block->fFreeSize -= bytes;
|
| @@ -123,6 +177,7 @@ size_t SkChunkAlloc::unalloc(void* ptr) {
|
| char* start = block->startOfData();
|
| if (start <= cPtr && cPtr < block->fFreePtr) {
|
| bytes = block->fFreePtr - cPtr;
|
| + fTotalUsed -= bytes;
|
| block->fFreeSize += bytes;
|
| block->fFreePtr = cPtr;
|
| }
|
|
|