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; |