Use GrMemoryPool to manage GrCustomStage allocations.
Improve memory reclamation of GrMemoryPool for new/delete/new/delete pattern.
http://codereview.appspot.com/6438046/
git-svn-id: http://skia.googlecode.com/svn/trunk@4744 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrCustomStage.h b/include/gpu/GrCustomStage.h
index 9f5efd3..9060766 100644
--- a/include/gpu/GrCustomStage.h
+++ b/include/gpu/GrCustomStage.h
@@ -81,6 +81,9 @@
virtual unsigned int numTextures() const;
virtual GrTexture* texture(unsigned int index) const;
+ void* operator new(size_t size);
+ void operator delete(void* target);
+
private:
typedef GrRefCnt INHERITED;
};
diff --git a/src/gpu/GrCustomStage.cpp b/src/gpu/GrCustomStage.cpp
index 66b78a6..43de5ae 100644
--- a/src/gpu/GrCustomStage.cpp
+++ b/src/gpu/GrCustomStage.cpp
@@ -7,9 +7,27 @@
#include "GrContext.h"
#include "GrCustomStage.h"
+#include "GrMemoryPool.h"
+#include "SkTLS.h"
SK_DEFINE_INST_COUNT(GrCustomStage)
+class GrCustomStage_Globals {
+public:
+ static GrMemoryPool* GetTLS() {
+ return (GrMemoryPool*)SkTLS::Get(CreateTLS, DeleteTLS);
+ }
+
+private:
+ static void* CreateTLS() {
+ return SkNEW_ARGS(GrMemoryPool, (4096, 4096));
+ }
+
+ static void DeleteTLS(void* pool) {
+ SkDELETE(reinterpret_cast<GrMemoryPool*>(pool));
+ }
+};
+
int32_t GrProgramStageFactory::fCurrStageClassID =
GrProgramStageFactory::kIllegalStageClassID;
@@ -45,3 +63,11 @@
return NULL;
}
+void * GrCustomStage::operator new(size_t size) {
+ return GrCustomStage_Globals::GetTLS()->allocate(size);
+}
+
+void GrCustomStage::operator delete(void* target) {
+ GrCustomStage_Globals::GetTLS()->release(target);
+}
+
diff --git a/src/gpu/GrMemoryPool.cpp b/src/gpu/GrMemoryPool.cpp
index 597f88c..01f303f 100644
--- a/src/gpu/GrMemoryPool.cpp
+++ b/src/gpu/GrMemoryPool.cpp
@@ -57,6 +57,7 @@
// so that we can decrement the live count on delete in constant time.
*reinterpret_cast<BlockHeader**>(ptr) = fTail;
ptr += kPerAllocPad;
+ fTail->fPrevPtr = fTail->fCurrPtr;
fTail->fCurrPtr += size;
fTail->fFreeSize -= size;
fTail->fLiveCount += 1;
@@ -91,6 +92,11 @@
}
} else {
--block->fLiveCount;
+ // Trivial reclaim: if we're releasing the most recent allocation, reuse it
+ if (block->fPrevPtr == ptr) {
+ block->fFreeSize += (block->fCurrPtr - block->fPrevPtr);
+ block->fCurrPtr = block->fPrevPtr;
+ }
}
GR_DEBUGCODE(--fAllocationCnt);
VALIDATE;
@@ -104,6 +110,7 @@
block->fLiveCount = 0;
block->fFreeSize = size;
block->fCurrPtr = reinterpret_cast<intptr_t>(block) + kHeaderSize;
+ block->fPrevPtr = NULL;
return block;
}
diff --git a/src/gpu/GrMemoryPool.h b/src/gpu/GrMemoryPool.h
index 08c9ee2..d327df4 100644
--- a/src/gpu/GrMemoryPool.h
+++ b/src/gpu/GrMemoryPool.h
@@ -53,12 +53,13 @@
void validate();
struct BlockHeader {
- BlockHeader* fNext; // doubly-linked list of blocks.
+ BlockHeader* fNext; ///< doubly-linked list of blocks.
BlockHeader* fPrev;
- int fLiveCount; // number of outstanding allocations in the
- // block.
- intptr_t fCurrPtr; // ptr to the start of blocks free space.
- size_t fFreeSize; // amount of free space left in the block.
+ int fLiveCount; ///< number of outstanding allocations in the
+ ///< block.
+ intptr_t fCurrPtr; ///< ptr to the start of blocks free space.
+ intptr_t fPrevPtr; ///< ptr to the last allocation made
+ size_t fFreeSize; ///< amount of free space left in the block.
};
enum {