Chromium Code Reviews| Index: src/gpu/GrTRecorder.h |
| diff --git a/src/gpu/GrTRecorder.h b/src/gpu/GrTRecorder.h |
| index ab559e4a5962b5abb5f59ec981e21c131fd90b39..39a80052b460467db7e476396315f31708015be7 100644 |
| --- a/src/gpu/GrTRecorder.h |
| +++ b/src/gpu/GrTRecorder.h |
| @@ -54,7 +54,7 @@ public: |
| and after calls to reset(). |
| */ |
| GrTRecorder(int initialSizeInBytes) |
| - : fHeadBlock(MemBlock::Alloc(LengthOf(initialSizeInBytes))), |
| + : fHeadBlock(MemBlock::Alloc(LengthOf(initialSizeInBytes), NULL)), |
| fTailBlock(fHeadBlock), |
| fLastItem(NULL) {} |
| @@ -71,6 +71,12 @@ public: |
| } |
| /** |
| + * Removes and destroys the last block added to the recorder. It may not be called when the |
| + * recorder is empty. |
| + */ |
| + void pop_back(); |
| + |
| + /** |
| * Destruct all items in the list and reset to empty. |
| */ |
| void reset(); |
| @@ -101,25 +107,36 @@ private: |
| struct Header { |
| int fTotalLength; |
| + int fPrevLength; |
| }; |
| template<typename TItem> TItem* alloc_back(int dataLength); |
| struct MemBlock : SkNoncopyable { |
| - static MemBlock* Alloc(int length) { |
| + static MemBlock* Alloc(int length, MemBlock* prev) { |
|
egdaniel
2014/11/21 19:09:46
Add comment on what length means when we alloc Mem
|
| MemBlock* block = reinterpret_cast<MemBlock*>( |
| sk_malloc_throw(sizeof(TAlign) * (length_of<MemBlock>::kValue + length))); |
| block->fLength = length; |
| block->fBack = 0; |
| block->fNext = NULL; |
| + block->fPrev = prev; |
| + if (prev) { |
| + SkASSERT(NULL == prev->fNext); |
| + prev->fNext = block; |
| + } |
| return block; |
| } |
| + // Frees from this block forward. Also adjusts prev block's next ptr. |
| static void Free(MemBlock* block) { |
| - if (!block) { |
| - return; |
| + if (block && block->fPrev) { |
| + SkASSERT(block->fPrev->fNext == block); |
| + block->fPrev->fNext = NULL; |
| + } |
| + while (block) { |
| + MemBlock* next = block->fNext; |
| + sk_free(block); |
| + block = next; |
| } |
| - Free(block->fNext); |
| - sk_free(block); |
| } |
| TAlign& operator [](int i) { |
| @@ -129,6 +146,7 @@ private: |
| int fLength; |
| int fBack; |
|
egdaniel
2014/11/21 19:09:47
comment about what this is
|
| MemBlock* fNext; |
| + MemBlock* fPrev; |
| }; |
| MemBlock* const fHeadBlock; |
| MemBlock* fTailBlock; |
| @@ -147,15 +165,49 @@ private: |
| //////////////////////////////////////////////////////////////////////////////// |
| template<typename TBase, typename TAlign> |
| +void GrTRecorder<TBase, TAlign>::pop_back() { |
| + SkASSERT(fLastItem); |
| + Header* header = reinterpret_cast<Header*>( |
| + reinterpret_cast<TAlign*>(fLastItem) - length_of<Header>::kValue); |
| + fTailBlock->fBack -= header->fTotalLength; |
| + fLastItem->~TBase(); |
| + |
| + int lastItemLength = header->fPrevLength; |
| + |
| + if (!header->fPrevLength) { |
|
egdaniel
2014/11/21 19:09:46
comment about what this if tells about the state w
|
| + SkASSERT(0 == fTailBlock->fBack); |
| + fLastItem = NULL; |
| + return; |
| + } |
| + if (!fTailBlock->fBack) { |
|
egdaniel
2014/11/21 19:09:47
comment about what this if tells about the state w
|
| + MemBlock* prev = fTailBlock->fPrev; |
| + SkASSERT(prev); |
| + MemBlock::Free(fTailBlock); |
| + fTailBlock = prev; |
| + SkASSERT(NULL == fTailBlock->fNext); |
| + } |
| + fLastItem = reinterpret_cast<TBase*>( |
| + &(*fTailBlock)[fTailBlock->fBack - lastItemLength + length_of<Header>::kValue]); |
| +} |
| + |
| +template<typename TBase, typename TAlign> |
| template<typename TItem> |
| TItem* GrTRecorder<TBase, TAlign>::alloc_back(int dataLength) { |
| + int prevLength = 0; |
| + if (fLastItem) { |
| + Header* lastHeader = reinterpret_cast<Header*>( |
| + reinterpret_cast<TAlign*>(fLastItem) - length_of<Header>::kValue); |
| + prevLength = lastHeader->fTotalLength; |
| + } |
| + |
| const int totalLength = length_of<Header>::kValue + length_of<TItem>::kValue + dataLength; |
| while (fTailBlock->fBack + totalLength > fTailBlock->fLength) { |
| if (!fTailBlock->fNext) { |
| - fTailBlock->fNext = MemBlock::Alloc(SkTMax(2 * fTailBlock->fLength, totalLength)); |
| + fTailBlock = MemBlock::Alloc(SkTMax(2 * fTailBlock->fLength, totalLength), fTailBlock); |
| + } else { |
| + fTailBlock = fTailBlock->fNext; |
| } |
| - fTailBlock = fTailBlock->fNext; |
| SkASSERT(0 == fTailBlock->fBack); |
| } |
| @@ -164,6 +216,7 @@ TItem* GrTRecorder<TBase, TAlign>::alloc_back(int dataLength) { |
| &(*fTailBlock)[fTailBlock->fBack + length_of<Header>::kValue]); |
| header->fTotalLength = totalLength; |
| + header->fPrevLength = prevLength; |
| fLastItem = rawPtr; |
| fTailBlock->fBack += totalLength; |
| @@ -225,7 +278,6 @@ void GrTRecorder<TBase, TAlign>::reset() { |
| // everything else. |
| if (fTailBlock->fBack <= fTailBlock->fLength / 2) { |
| MemBlock::Free(fTailBlock->fNext); |
| - fTailBlock->fNext = NULL; |
| } else if (fTailBlock->fNext) { |
| MemBlock::Free(fTailBlock->fNext->fNext); |
| fTailBlock->fNext->fNext = NULL; |