| Index: src/gpu/GrTRecorder.h
|
| diff --git a/src/gpu/GrTRecorder.h b/src/gpu/GrTRecorder.h
|
| index bddf1978d801479552267ca829786ff7dfddc4ce..1c49c86f385abffc78951a21a82ef1e8506d251a 100644
|
| --- a/src/gpu/GrTRecorder.h
|
| +++ b/src/gpu/GrTRecorder.h
|
| @@ -46,6 +46,7 @@ template<typename TItem> struct GrTRecorderAllocWrapper;
|
| template<typename TBase, typename TAlign> class GrTRecorder : SkNoncopyable {
|
| public:
|
| class Iter;
|
| + class ReverseIter;
|
|
|
| /**
|
| * Create a recorder.
|
| @@ -162,6 +163,7 @@ private:
|
| const GrTRecorderAllocWrapper<UItem>&);
|
|
|
| friend class Iter;
|
| + friend class ReverseIter;
|
| };
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
| @@ -182,7 +184,7 @@ void GrTRecorder<TBase, TAlign>::pop_back() {
|
| fLastItem = NULL;
|
| return;
|
| }
|
| - if (!fTailBlock->fBack) {
|
| + while (!fTailBlock->fBack) {
|
| // We popped the last entry in a block that isn't the head block. Move back a block but
|
| // don't free it since we'll probably grow into it shortly.
|
| fTailBlock = fTailBlock->fPrev;
|
| @@ -239,6 +241,15 @@ TItem* GrTRecorder<TBase, TAlign>::alloc_back(int dataLength) {
|
| return rawPtr;
|
| }
|
|
|
| +/**
|
| + * Iterates through a recorder from front to back. The initial state of the iterator is
|
| + * to not have the front item loaded yet; next() must be called first. Usage model:
|
| + *
|
| + * GrTRecorder<TBase, TAlign>::Iter iter(recorder);
|
| + * while (iter.next()) {
|
| + * iter->doSomething();
|
| + * }
|
| + */
|
| template<typename TBase, typename TAlign>
|
| class GrTRecorder<TBase, TAlign>::Iter {
|
| public:
|
| @@ -273,6 +284,55 @@ private:
|
| TBase* fItem;
|
| };
|
|
|
| +/**
|
| + * Iterates through a recorder in reverse, from back to front. This version mirrors "Iter",
|
| + * so the initial state is to have recorder.back() loaded already. (Note that this will
|
| + * assert if the recorder is empty.) Usage model:
|
| + *
|
| + * GrTRecorder<TBase, TAlign>::ReverseIter reverseIter(recorder);
|
| + * do {
|
| + * reverseIter->doSomething();
|
| + * } while (reverseIter.previous());
|
| + */
|
| +template<typename TBase, typename TAlign>
|
| +class GrTRecorder<TBase, TAlign>::ReverseIter {
|
| +public:
|
| + ReverseIter(GrTRecorder& recorder)
|
| + : fBlock(recorder.fTailBlock),
|
| + fItem(&recorder.back()) {
|
| + Header* lastHeader = reinterpret_cast<Header*>(
|
| + reinterpret_cast<TAlign*>(fItem) - length_of<Header>::kValue);
|
| + fPosition = fBlock->fBack - lastHeader->fTotalLength;
|
| + }
|
| +
|
| + bool previous() {
|
| + Header* header = reinterpret_cast<Header*>(&(*fBlock)[fPosition]);
|
| +
|
| + while (0 == fPosition) {
|
| + if (!fBlock->fPrev) {
|
| + // We've reached the front of the recorder.
|
| + return false;
|
| + }
|
| + fBlock = fBlock->fPrev;
|
| + fPosition = fBlock->fBack;
|
| + }
|
| +
|
| + fPosition -= header->fPrevLength;
|
| + SkASSERT(fPosition >= 0);
|
| +
|
| + fItem = reinterpret_cast<TBase*>(&(*fBlock)[fPosition + length_of<Header>::kValue]);
|
| + return true;
|
| + }
|
| +
|
| + TBase* get() const { return fItem; }
|
| + TBase* operator->() const { return this->get(); }
|
| +
|
| +private:
|
| + MemBlock* fBlock;
|
| + int fPosition;
|
| + TBase* fItem;
|
| +};
|
| +
|
| template<typename TBase, typename TAlign>
|
| void GrTRecorder<TBase, TAlign>::reset() {
|
| Iter iter(*this);
|
|
|