1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/GrMemoryPool.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,161 @@ 1.4 +/* 1.5 + * Copyright 2012 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "GrMemoryPool.h" 1.12 + 1.13 +#ifdef SK_DEBUG 1.14 + #define VALIDATE this->validate() 1.15 +#else 1.16 + #define VALIDATE 1.17 +#endif 1.18 + 1.19 +GrMemoryPool::GrMemoryPool(size_t preallocSize, size_t minAllocSize) { 1.20 + SkDEBUGCODE(fAllocationCnt = 0); 1.21 + 1.22 + minAllocSize = GrMax<size_t>(minAllocSize, 1 << 10); 1.23 + fMinAllocSize = GrSizeAlignUp(minAllocSize + kPerAllocPad, kAlignment), 1.24 + fPreallocSize = GrSizeAlignUp(preallocSize + kPerAllocPad, kAlignment); 1.25 + fPreallocSize = GrMax(fPreallocSize, fMinAllocSize); 1.26 + 1.27 + fHead = CreateBlock(fPreallocSize); 1.28 + fTail = fHead; 1.29 + fHead->fNext = NULL; 1.30 + fHead->fPrev = NULL; 1.31 + VALIDATE; 1.32 +}; 1.33 + 1.34 +GrMemoryPool::~GrMemoryPool() { 1.35 + VALIDATE; 1.36 + SkASSERT(0 == fAllocationCnt); 1.37 + SkASSERT(fHead == fTail); 1.38 + SkASSERT(0 == fHead->fLiveCount); 1.39 + DeleteBlock(fHead); 1.40 +}; 1.41 + 1.42 +void* GrMemoryPool::allocate(size_t size) { 1.43 + VALIDATE; 1.44 + size = GrSizeAlignUp(size, kAlignment); 1.45 + size += kPerAllocPad; 1.46 + if (fTail->fFreeSize < size) { 1.47 + size_t blockSize = size; 1.48 + blockSize = GrMax<size_t>(blockSize, fMinAllocSize); 1.49 + BlockHeader* block = CreateBlock(blockSize); 1.50 + 1.51 + block->fPrev = fTail; 1.52 + block->fNext = NULL; 1.53 + SkASSERT(NULL == fTail->fNext); 1.54 + fTail->fNext = block; 1.55 + fTail = block; 1.56 + } 1.57 + SkASSERT(fTail->fFreeSize >= size); 1.58 + intptr_t ptr = fTail->fCurrPtr; 1.59 + // We stash a pointer to the block header, just before the allocated space, 1.60 + // so that we can decrement the live count on delete in constant time. 1.61 + *reinterpret_cast<BlockHeader**>(ptr) = fTail; 1.62 + ptr += kPerAllocPad; 1.63 + fTail->fPrevPtr = fTail->fCurrPtr; 1.64 + fTail->fCurrPtr += size; 1.65 + fTail->fFreeSize -= size; 1.66 + fTail->fLiveCount += 1; 1.67 + SkDEBUGCODE(++fAllocationCnt); 1.68 + VALIDATE; 1.69 + return reinterpret_cast<void*>(ptr); 1.70 +} 1.71 + 1.72 +void GrMemoryPool::release(void* p) { 1.73 + VALIDATE; 1.74 + intptr_t ptr = reinterpret_cast<intptr_t>(p) - kPerAllocPad; 1.75 + BlockHeader* block = *reinterpret_cast<BlockHeader**>(ptr); 1.76 + if (1 == block->fLiveCount) { 1.77 + // the head block is special, it is reset rather than deleted 1.78 + if (fHead == block) { 1.79 + fHead->fCurrPtr = reinterpret_cast<intptr_t>(fHead) + 1.80 + kHeaderSize; 1.81 + fHead->fLiveCount = 0; 1.82 + fHead->fFreeSize = fPreallocSize; 1.83 + } else { 1.84 + BlockHeader* prev = block->fPrev; 1.85 + BlockHeader* next = block->fNext; 1.86 + SkASSERT(prev); 1.87 + prev->fNext = next; 1.88 + if (next) { 1.89 + next->fPrev = prev; 1.90 + } else { 1.91 + SkASSERT(fTail == block); 1.92 + fTail = prev; 1.93 + } 1.94 + DeleteBlock(block); 1.95 + } 1.96 + } else { 1.97 + --block->fLiveCount; 1.98 + // Trivial reclaim: if we're releasing the most recent allocation, reuse it 1.99 + if (block->fPrevPtr == ptr) { 1.100 + block->fFreeSize += (block->fCurrPtr - block->fPrevPtr); 1.101 + block->fCurrPtr = block->fPrevPtr; 1.102 + } 1.103 + } 1.104 + SkDEBUGCODE(--fAllocationCnt); 1.105 + VALIDATE; 1.106 +} 1.107 + 1.108 +GrMemoryPool::BlockHeader* GrMemoryPool::CreateBlock(size_t size) { 1.109 + BlockHeader* block = 1.110 + reinterpret_cast<BlockHeader*>(sk_malloc_throw(size + kHeaderSize)); 1.111 + // we assume malloc gives us aligned memory 1.112 + SkASSERT(!(reinterpret_cast<intptr_t>(block) % kAlignment)); 1.113 + block->fLiveCount = 0; 1.114 + block->fFreeSize = size; 1.115 + block->fCurrPtr = reinterpret_cast<intptr_t>(block) + kHeaderSize; 1.116 + block->fPrevPtr = 0; // gcc warns on assigning NULL to an intptr_t. 1.117 + return block; 1.118 +} 1.119 + 1.120 +void GrMemoryPool::DeleteBlock(BlockHeader* block) { 1.121 + sk_free(block); 1.122 +} 1.123 + 1.124 +void GrMemoryPool::validate() { 1.125 +#ifdef SK_DEBUG 1.126 + BlockHeader* block = fHead; 1.127 + BlockHeader* prev = NULL; 1.128 + SkASSERT(block); 1.129 + int allocCount = 0; 1.130 + do { 1.131 + allocCount += block->fLiveCount; 1.132 + SkASSERT(prev == block->fPrev); 1.133 + if (NULL != prev) { 1.134 + SkASSERT(prev->fNext == block); 1.135 + } 1.136 + 1.137 + intptr_t b = reinterpret_cast<intptr_t>(block); 1.138 + size_t ptrOffset = block->fCurrPtr - b; 1.139 + size_t totalSize = ptrOffset + block->fFreeSize; 1.140 + size_t userSize = totalSize - kHeaderSize; 1.141 + intptr_t userStart = b + kHeaderSize; 1.142 + 1.143 + SkASSERT(!(b % kAlignment)); 1.144 + SkASSERT(!(totalSize % kAlignment)); 1.145 + SkASSERT(!(userSize % kAlignment)); 1.146 + SkASSERT(!(block->fCurrPtr % kAlignment)); 1.147 + if (fHead != block) { 1.148 + SkASSERT(block->fLiveCount); 1.149 + SkASSERT(userSize >= fMinAllocSize); 1.150 + } else { 1.151 + SkASSERT(userSize == fPreallocSize); 1.152 + } 1.153 + if (!block->fLiveCount) { 1.154 + SkASSERT(ptrOffset == kHeaderSize); 1.155 + SkASSERT(userStart == block->fCurrPtr); 1.156 + } else { 1.157 + SkASSERT(block == *reinterpret_cast<BlockHeader**>(userStart)); 1.158 + } 1.159 + prev = block; 1.160 + } while ((block = block->fNext)); 1.161 + SkASSERT(allocCount == fAllocationCnt); 1.162 + SkASSERT(prev == fTail); 1.163 +#endif 1.164 +}