Add SkSTArray, hide stack storage cons in SkTArray, unify SkTArray init logic

Review URL: http://codereview.appspot.com/5127044/



git-svn-id: http://skia.googlecode.com/svn/trunk@2342 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrAllocator.h b/gpu/include/GrAllocator.h
index eca2ab0..7f1fe5b 100755
--- a/gpu/include/GrAllocator.h
+++ b/gpu/include/GrAllocator.h
@@ -30,7 +30,6 @@
      *                          Caller is responsible for freeing this memory.
      */
     GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) :
-            fBlocks(fBlockInitialStorage, NUM_INIT_BLOCK_PTRS),
             fItemSize(itemSize),
             fItemsPerBlock(itemsPerBlock),
             fOwnFirstBlock(NULL == initialBlock),
@@ -128,13 +127,12 @@
 private:
     static const int NUM_INIT_BLOCK_PTRS = 8;
     
-    SkTArray<void*> fBlocks;
-    size_t          fBlockSize;
-    char            fBlockInitialStorage[NUM_INIT_BLOCK_PTRS*sizeof(void*)];
-    size_t          fItemSize;
-    int             fItemsPerBlock;
-    bool            fOwnFirstBlock;
-    int             fCount;
+    SkSTArray<NUM_INIT_BLOCK_PTRS, void*>   fBlocks;
+    size_t                                  fBlockSize;
+    size_t                                  fItemSize;
+    int                                     fItemsPerBlock;
+    bool                                    fOwnFirstBlock;
+    int                                     fCount;
 };
 
 template <typename T>
diff --git a/gpu/include/GrClip.h b/gpu/include/GrClip.h
index 9e235bf..d86eb97 100644
--- a/gpu/include/GrClip.h
+++ b/gpu/include/GrClip.h
@@ -135,8 +135,7 @@
     enum {
         kPreAllocElements = 4,
     };
-    SkAlignedSTStorage<kPreAllocElements, Element>  fListStorage;
-    SkTArray<Element>   fList;
+    SkSTArray<kPreAllocElements, Element>   fList;
 };
 #endif
 
diff --git a/gpu/src/GrAAHairLinePathRenderer.cpp b/gpu/src/GrAAHairLinePathRenderer.cpp
index 32a477b..6c136e2 100644
--- a/gpu/src/GrAAHairLinePathRenderer.cpp
+++ b/gpu/src/GrAAHairLinePathRenderer.cpp
@@ -133,6 +133,7 @@
 namespace {
 
 typedef SkTArray<SkPoint, true> PtArray;
+#define PREALLOC_PTARRAY(N) SkSTArray<(N),SkPoint, true>
 typedef SkTArray<int, true> IntArray;
 
 /**
@@ -344,8 +345,7 @@
                 bounds.outset(SK_Scalar1, SK_Scalar1);
                 bounds.roundOut(&ibounds);
                 if (SkIRect::Intersects(clip, ibounds)) {
-                    SkPoint stackStorage[32];
-                    PtArray q((void*)stackStorage, 32);
+                    PREALLOC_PTARRAY(32) q;
                     // in perspective have to do conversion in src space
                     if (persp) {
                         SkScalar tolScale = 
@@ -629,10 +629,8 @@
 
     GrMatrix viewM = fTarget->getViewMatrix();
 
-    SkAlignedSTStorage<128, GrPoint> lineStorage;
-    SkAlignedSTStorage<128, GrPoint> quadStorage;
-    PtArray lines(&lineStorage);
-    PtArray quads(&quadStorage);
+    PREALLOC_PTARRAY(128) lines;
+    PREALLOC_PTARRAY(128) quads;
     IntArray qSubdivs;
     fQuadCnt = generate_lines_and_quads(*fPath, viewM, fTranslate, clip,
                                         &lines, &quads, &qSubdivs);
diff --git a/gpu/src/GrClip.cpp b/gpu/src/GrClip.cpp
index afa143a..a02d9f4 100644
--- a/gpu/src/GrClip.cpp
+++ b/gpu/src/GrClip.cpp
@@ -10,30 +10,25 @@
 
 #include "GrClip.h"
 
-GrClip::GrClip()
-    : fList(&fListStorage) {
+GrClip::GrClip() {
     fConservativeBounds.setEmpty();
     fConservativeBoundsValid = true;
 }
 
-GrClip::GrClip(const GrClip& src)
-    : fList(&fListStorage) {
+GrClip::GrClip(const GrClip& src) {
     *this = src;
 }
 
-GrClip::GrClip(const GrIRect& rect)
-    : fList(&fListStorage) {
+GrClip::GrClip(const GrIRect& rect) {
     this->setFromIRect(rect);
 }
 
-GrClip::GrClip(const GrRect& rect)
-    : fList(&fListStorage) {
+GrClip::GrClip(const GrRect& rect) {
     this->setFromRect(rect);
 }
 
 GrClip::GrClip(GrClipIterator* iter, GrScalar tx, GrScalar ty,
-               const GrRect* bounds)
-    : fList(&fListStorage) {
+               const GrRect* bounds) {
     this->setFromIterator(iter, tx, ty, bounds);
 }
 
diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index 59661d8..51e6fdd 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -329,8 +329,7 @@
 #define DEBUG_INVAL_BUFFER 0xdeadcafe
 #define DEBUG_INVAL_START_IDX -1
 
-GrDrawTarget::GrDrawTarget() 
-: fGeoSrcStateStack(&fGeoSrcStateStackStorage) {
+GrDrawTarget::GrDrawTarget() {
 #if GR_DEBUG
     VertexLayoutUnitTest();
 #endif
diff --git a/gpu/src/GrDrawTarget.h b/gpu/src/GrDrawTarget.h
index f1c98e8..81d0b2b 100644
--- a/gpu/src/GrDrawTarget.h
+++ b/gpu/src/GrDrawTarget.h
@@ -1376,10 +1376,8 @@
     enum {
         kPreallocGeoSrcStateStackCnt = 4,
     };
-    SkAlignedSTStorage<kPreallocGeoSrcStateStackCnt, 
-                        GeometrySrcState> 
-                                     fGeoSrcStateStackStorage;
-    SkTArray<GeometrySrcState, true> fGeoSrcStateStack;
+    SkSTArray<kPreallocGeoSrcStateStackCnt, 
+              GeometrySrcState, true>           fGeoSrcStateStack;
     
 };
 
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index 91e659d..7b98ffa 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -36,7 +36,6 @@
     , fIndexPool(NULL)
     , fVertexPoolUseCnt(0)
     , fIndexPoolUseCnt(0)
-    , fGeomPoolStateStack(&fGeoSrcStateStackStorage)
     , fQuadIndexBuffer(NULL)
     , fUnitSquareVertexBuffer(NULL)
     , fPathRendererChain(NULL)
diff --git a/gpu/src/GrGpu.h b/gpu/src/GrGpu.h
index 9ecb4b0..3193a56 100644
--- a/gpu/src/GrGpu.h
+++ b/gpu/src/GrGpu.h
@@ -374,9 +374,8 @@
     enum {
         kPreallocGeomPoolStateStackCnt = 4,
     };
-    SkAlignedSTStorage<kPreallocGeomPoolStateStackCnt, 
-                       GeometryPoolState>           fGeoSrcStateStackStorage;
-    SkTArray<GeometryPoolState, true>               fGeomPoolStateStack;
+    SkSTArray<kPreallocGeomPoolStateStackCnt,
+              GeometryPoolState, true>              fGeomPoolStateStack;
     
     mutable GrIndexBuffer*      fQuadIndexBuffer; // mutable so it can be
                                                   // created on-demand
diff --git a/gpu/src/GrInOrderDrawBuffer.cpp b/gpu/src/GrInOrderDrawBuffer.cpp
index 9519655..3d78da3 100644
--- a/gpu/src/GrInOrderDrawBuffer.cpp
+++ b/gpu/src/GrInOrderDrawBuffer.cpp
@@ -30,8 +30,7 @@
     , fCurrQuad(0)
 
     , fVertexPool(*vertexPool)
-    , fIndexPool(*indexPool)
-    , fGeoPoolStateStack(&fGeoStackStorage) {
+    , fIndexPool(*indexPool) {
 
     fCaps = gpu->getCaps();
 
diff --git a/gpu/src/GrInOrderDrawBuffer.h b/gpu/src/GrInOrderDrawBuffer.h
index f0b5c9e..122be53 100644
--- a/gpu/src/GrInOrderDrawBuffer.h
+++ b/gpu/src/GrInOrderDrawBuffer.h
@@ -161,6 +161,15 @@
     GrVertexBufferAllocPool&        fVertexPool;
 
     GrIndexBufferAllocPool&         fIndexPool;
+
+    enum {
+        kDrawPreallocCnt         = 8,
+        kStatePreallocCnt        = 8,
+        kClipPreallocCnt         = 8,
+        kClearPreallocCnt        = 4,
+        kGeoPoolStatePreAllocCnt = 4,
+    };
+
     struct GeometryPoolState {
         const GrVertexBuffer*           fPoolVertexBuffer;
         int                             fPoolStartVertex;
@@ -172,23 +181,12 @@
         size_t                          fUsedPoolVertexBytes;
         size_t                          fUsedPoolIndexBytes;
     };
-    SkTArray<GeometryPoolState> fGeoPoolStateStack;
-
-    
-    enum {
-        kDrawPreallocCnt         = 8,
-        kStatePreallocCnt        = 8,
-        kClipPreallocCnt         = 8,
-        kClearPreallocCnt        = 4,
-        kGeoPoolStatePreAllocCnt = 4,
-    };
+    SkSTArray<kGeoPoolStatePreAllocCnt, GeometryPoolState> fGeoPoolStateStack;
 
     SkAlignedSTStorage<kDrawPreallocCnt, Draw>              fDrawStorage;
     SkAlignedSTStorage<kStatePreallocCnt, SavedDrawState>   fStateStorage;
     SkAlignedSTStorage<kClipPreallocCnt, GrClip>            fClipStorage;
     SkAlignedSTStorage<kClearPreallocCnt, Clear>            fClearStorage;
-    SkAlignedSTStorage<kGeoPoolStatePreAllocCnt, 
-                        GeometryPoolState>                  fGeoStackStorage;
 
     typedef GrDrawTarget INHERITED;
 };
diff --git a/gpu/src/GrPathRendererChain.cpp b/gpu/src/GrPathRendererChain.cpp
index 87ebe10..7a064e8 100644
--- a/gpu/src/GrPathRendererChain.cpp
+++ b/gpu/src/GrPathRendererChain.cpp
@@ -16,8 +16,7 @@
 GrPathRendererChain::GrPathRendererChain(GrContext* context, UsageFlags flags)
     : fInit(false)
     , fOwner(context)
-    , fFlags(flags)
-    , fChain(fStorage.get(), kPreAllocCount) {
+    , fFlags(flags) {
     fInit = false;
 }
     
diff --git a/gpu/src/GrPathRendererChain.h b/gpu/src/GrPathRendererChain.h
index 24abda4..5719484 100644
--- a/gpu/src/GrPathRendererChain.h
+++ b/gpu/src/GrPathRendererChain.h
@@ -55,8 +55,7 @@
     bool fInit;
     GrContext*                                          fOwner;
     UsageFlags                                          fFlags;
-    SkAlignedSTStorage<kPreAllocCount, GrPathRenderer*> fStorage;
-    SkTArray<GrPathRenderer*, true>                     fChain;
+    SkSTArray<kPreAllocCount, GrPathRenderer*, true>    fChain;
 };
 
 GR_MAKE_BITFIELD_OPS(GrPathRendererChain::UsageFlags)
diff --git a/include/core/SkTArray.h b/include/core/SkTArray.h
index 3e2a006..9237611 100644
--- a/include/core/SkTArray.h
+++ b/include/core/SkTArray.h
@@ -35,66 +35,14 @@
      * elements.
      */
     explicit SkTArray(int reserveCount) {
-        SkASSERT(reserveCount >= 0);
-        fCount = 0;
-        fReserveCount = reserveCount > gMIN_ALLOC_COUNT ? reserveCount :
-                                                          gMIN_ALLOC_COUNT;
-        fAllocCount = fReserveCount;
-        fMemArray = sk_malloc_throw(sizeof(T) * fReserveCount);
-        fPreAllocMemArray = NULL;
+        this->init(NULL, 0, NULL, reserveCount);
     }
-
-    /**
-     * Creates an empty array that will use the passed storage block until it
-     * is insufficiently large to hold the entire array.
-     */
-    template <int N>
-    SkTArray(SkAlignedSTStorage<N,T>* storage) {
-        SkASSERT(N > 0);
-        fCount              = 0;
-        fReserveCount       = N;
-        fAllocCount         = N;
-        fMemArray           = storage->get();
-        fPreAllocMemArray   = storage->get();
-    }
-
-    /**
-     * Creates an empty array that will use the passed memory block until the
-     * count exceeds preAllocCount. Be careful not to use this constructor
-     * when you really want the (T*, int) version.
-     */
-    SkTArray(void* preAllocStorage, int preAllocCount) {
-        SkASSERT(preAllocCount >= 0);
-        // we allow NULL,0 args and revert to the default cons. behavior
-        // this makes it possible for a owner-object to use same constructor
-        // to get either prealloc or nonprealloc behavior based using same line
-        SkASSERT((NULL == preAllocStorage) == !preAllocCount);
-
-        fCount              = 0;
-        fReserveCount       = preAllocCount > 0 ? preAllocCount :
-                                                  gMIN_ALLOC_COUNT;
-        fAllocCount         = preAllocCount;
-        fMemArray           = preAllocStorage;
-        fPreAllocMemArray   = preAllocStorage;
-    }
-
+  
     /**
      * Copies one array to another. The new array will be heap allocated.
      */
     explicit SkTArray(const SkTArray& array) {
-        fCount              = array.count();
-        fReserveCount       = gMIN_ALLOC_COUNT;
-        fAllocCount         = SkMax32(fReserveCount, fCount);
-        fMemArray           = sk_malloc_throw(sizeof(T) * fAllocCount);
-        fPreAllocMemArray   = NULL;
-
-        if (DATA_TYPE) {
-            memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
-        } else {
-            for (int i = 0; i < fCount; ++i) {
-                new (fItemArray + i) T(array[i]);
-            }
-        }
+        this->init(array.fItemArray, array.fCount, NULL, 0);
     }
 
     /**
@@ -103,90 +51,7 @@
      * when you really want the (void*, int) version.
      */
     SkTArray(const T* array, int count) {
-        SkASSERT(count >= 0);
-        fCount              = count;
-        fReserveCount       = gMIN_ALLOC_COUNT;
-        fAllocCount         = SkMax32(fReserveCount, fCount);
-        fMemArray           = sk_malloc_throw(sizeof(T) * fAllocCount);
-        fPreAllocMemArray   = NULL;
-        if (DATA_TYPE) {
-            memcpy(fMemArray, array, sizeof(T) * fCount);
-        } else {
-            for (int i = 0; i < fCount; ++i) {
-                new (fItemArray + i) T(array[i]);
-            }
-        }
-    }
-
-    /**
-     * Copy another array, using preallocated storage if preAllocCount >=
-     * array.count(). Otherwise preAllocStorage is only used if the array
-     * shrinks to fit.
-     */
-    SkTArray(const SkTArray& array,
-             void* preAllocStorage, int preAllocCount) {
-
-        SkASSERT(preAllocCount >= 0);
-
-        // for same reason as non-copying cons we allow NULL, 0 for prealloc
-        SkASSERT((NULL == preAllocStorage) == !preAllocCount);
-
-        fCount              = array.count();
-        fReserveCount       = preAllocCount > 0 ? preAllocCount :
-                                                  gMIN_ALLOC_COUNT;
-        fPreAllocMemArray   = preAllocStorage;
-
-        if (fReserveCount >= fCount && preAllocCount) {
-            fAllocCount = fReserveCount;
-            fMemArray = preAllocStorage;
-        } else {
-            fAllocCount = SkMax32(fCount, fReserveCount);
-            fMemArray = sk_malloc_throw(fAllocCount * sizeof(T));
-        }
-
-        if (DATA_TYPE) {
-            memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
-        } else {
-            for (int i = 0; i < fCount; ++i) {
-                new (fItemArray + i) T(array[i]);
-            }
-        }
-    }
-
-    /**
-     * Copy C array to SkTArray, using preallocated storage if preAllocCount >=
-     * preAllocCount. Otherwise preAllocStorage is only used if the array
-     * shrinks to fit.
-     */
-    SkTArray(const T* array, int count,
-             void* preAllocStorage, int preAllocCount) {
-
-        SkASSERT(count >= 0);
-        SkASSERT(preAllocCount >= 0);
-
-        // for same reason as non-copying cons we allow NULL, 0 for prealloc
-        SkASSERT((NULL == preAllocStorage) == !preAllocCount);
-
-        fCount              = count;
-        fReserveCount       = (preAllocCount > 0) ? preAllocCount :
-                                                    gMIN_ALLOC_COUNT;
-        fPreAllocMemArray   = preAllocStorage;
-
-        if (fReserveCount >= fCount && preAllocCount) {
-            fAllocCount = fReserveCount;
-            fMemArray = preAllocStorage;
-        } else {
-            fAllocCount = SkMax32(fCount, fReserveCount);
-            fMemArray = sk_malloc_throw(fAllocCount * sizeof(T));
-        }
-
-        if (DATA_TYPE) {
-            memcpy(fMemArray, array, sizeof(T) * fCount);
-        } else {
-            for (int i = 0; i < fCount; ++i) {
-                new (fItemArray + i) T(array[i]);
-            }
-        }
+        this->init(array, count, NULL, 0);
     }
 
     /**
@@ -209,7 +74,7 @@
         return *this;
     }
 
-    ~SkTArray() {
+    virtual ~SkTArray() {
         for (int i = 0; i < fCount; ++i) {
             fItemArray[i].~T();
         }
@@ -379,6 +244,63 @@
         return fItemArray[fCount - i - 1];
     }
 
+protected:
+    /**
+     * Creates an empty array that will use the passed storage block until it
+     * is insufficiently large to hold the entire array.
+     */
+    template <int N>
+    SkTArray(SkAlignedSTStorage<N,T>* storage) {
+        this->init(NULL, 0, storage->get(), N);
+    }
+
+    /**
+     * Copy another array, using preallocated storage if preAllocCount >=
+     * array.count(). Otherwise storage will only be used when array shrinks
+     * to fit.
+     */
+    template <int N>
+    SkTArray(const SkTArray& array, SkAlignedSTStorage<N,T>* storage) {
+        this->init(array.fItemArray, array.fCount, storage->get(), N);
+    }
+
+    /**
+     * Copy a C array, using preallocated storage if preAllocCount >=
+     * count. Otherwise storage will only be used when array shrinks
+     * to fit.
+     */
+    template <int N>
+    SkTArray(const T* array, int count, SkAlignedSTStorage<N,T>* storage) {
+        this->init(array, count, storage->get(), N);
+    }
+
+    void init(const T* array, int count,
+               void* preAllocStorage, int preAllocOrReserveCount) {
+        GrAssert(count >= 0);
+        GrAssert(preAllocOrReserveCount >= 0);
+        fCount              = count;
+        fReserveCount       = (preAllocOrReserveCount > 0) ?
+                                    preAllocOrReserveCount :
+                                    gMIN_ALLOC_COUNT;
+        fPreAllocMemArray   = preAllocStorage;
+        if (fReserveCount >= fCount &&
+            NULL != preAllocStorage) {
+            fAllocCount = fReserveCount;
+            fMemArray = preAllocStorage;
+        } else {
+            fAllocCount = GrMax(fCount, fReserveCount);
+            fMemArray = GrMalloc(fAllocCount * sizeof(T));
+        }
+
+        if (DATA_TYPE) {
+            memcpy(fMemArray, array, sizeof(T) * fCount);
+        } else {
+            for (int i = 0; i < fCount; ++i) {
+                new (fItemArray + i) T(array[i]);
+            }
+        }
+    }
+
 private:
 
     static const int gMIN_ALLOC_COUNT = 8;
@@ -436,5 +358,42 @@
     };
 };
 
+/**
+ * Subclass of SkTArray that contains a preallocated memory block for the array.
+ */
+template <int N, typename T, bool DATA_TYPE = false>
+class SkSTArray : public SkTArray<T, DATA_TYPE> {
+private:
+    typedef SkTArray<T, DATA_TYPE> INHERITED;
+
+public:
+    SkSTArray() : INHERITED(&fStorage) {
+    }
+
+    SkSTArray(const SkSTArray& array)
+        : INHERITED(array, &fStorage) {
+    }
+
+    explicit SkSTArray(const INHERITED& array)
+        : INHERITED(array, &fStorage) {
+    }
+
+    SkSTArray(const T* array, int count)
+        : INHERITED(array, count, &fStorage) {
+    }
+
+    SkSTArray& operator= (const SkSTArray& array) {
+        return *this = *(const INHERITED*)&array;
+    }
+
+    SkSTArray& operator= (const INHERITED& array) {
+        INHERITED::operator=(array);
+        return *this;
+    }
+
+private:
+    SkAlignedSTStorage<N,T> fStorage;
+};
+
 #endif