Refactor how Gr handles vertex and index data. GrGpu and GrInOrderDrawBuffer both GrBufferAllocPool to manage reserved and set-to-array vertex and index data.

rietveld issue 4188049

git-svn-id: http://skia.googlecode.com/svn/trunk@786 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrConfig.h b/gpu/include/GrConfig.h
index ff694da..7805074 100644
--- a/gpu/include/GrConfig.h
+++ b/gpu/include/GrConfig.h
@@ -84,7 +84,7 @@
         #undef GR_LINUX_BUILD
         #define GR_LINUX_BUILD      1
 //      #error "LINUX"
-    #endif    
+    #endif
 #endif
 
 // we need both GR_DEBUG and GR_RELEASE to be defined as 0 or 1
@@ -121,10 +121,10 @@
 #include <stdint.h>
 
 /*
- *  The "user config" file can be empty, and everything should work. It is 
+ *  The "user config" file can be empty, and everything should work. It is
  *  meant to store a given platform/client's overrides of our guess-work.
  *
- *  A alternate user config file can be specified by defining 
+ *  A alternate user config file can be specified by defining
  *  GR_USER_CONFIG_FILE. It should be defined relative to GrConfig.h
  *
  *  e.g. it can specify GR_DEBUG/GR_RELEASE as it please, change the BUILD
@@ -132,7 +132,7 @@
  */
 #if !defined(GR_USER_CONFIG_FILE)
     #include "GrUserConfig.h"
-#else 
+#else
     #include GR_USER_CONFIG_FILE
 #endif
 
@@ -155,7 +155,7 @@
 #define GR_STRING_IMPL(X) #X
 
 /**
- *  GR_CONCAT concatenates X and Y  where each is expanded before 
+ *  GR_CONCAT concatenates X and Y  where each is expanded before
  *  contanenation if either contains macros.
  */
 #define GR_CONCAT(X,Y) GR_CONCAT_IMPL(X,Y)
@@ -167,8 +167,8 @@
 #define GR_FILE_AND_LINE_STR __FILE__ "(" GR_STRING(__LINE__) ") : "
 
 /**
- *  Compilers have different ways of issuing warnings. This macro 
- *  attempts to abstract them, but may need to be specialized for your 
+ *  Compilers have different ways of issuing warnings. This macro
+ *  attempts to abstract them, but may need to be specialized for your
  *  particular compiler.
  *  To insert compiler warnings use "#pragma message GR_WARN(<string>)"
  */
@@ -184,9 +184,9 @@
 #if !defined(GR_ALWAYSBREAK)
     #if     GR_WIN32_BUILD
         #define GR_ALWAYSBREAK __debugbreak()
-    #else 
+    #else
         // TODO: do other platforms really not have continuable breakpoints?
-        // sign extend for 64bit architectures to be sure this is 
+        // sign extend for 64bit architectures to be sure this is
         // in the high address range
         #define GR_ALWAYSBREAK *((int*)(int64_t)(int32_t)0xbeefcafe) = 0;
     #endif
@@ -240,7 +240,7 @@
 inline void GrCrash(const char* msg) { GrPrintf(msg); GrAlwaysAssert(false); }
 
 /**
- *  GR_DEBUGCODE compiles the code X in debug builds only 
+ *  GR_DEBUGCODE compiles the code X in debug builds only
  */
 #if !defined(GR_DEBUGCODE)
     #if GR_DEBUG
@@ -255,7 +255,7 @@
  *  it may print the message in the compiler log. Obviously, the condition must
  *  be evaluatable at compile time.
  */
-// VS 2010 and GCC compiled with c++0x or gnu++0x support the new 
+// VS 2010 and GCC compiled with c++0x or gnu++0x support the new
 // static_assert.
 #if !defined(GR_STATIC_ASSERT)
     #if (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)
@@ -278,7 +278,7 @@
 
 #if !defined(GR_TEXT_SCALAR_TYPE_IS_USHORT)
     #define GR_TEXT_SCALAR_TYPE_IS_USHORT  0
-#endif    
+#endif
 #if !defined(GR_TEXT_SCALAR_TYPE_IS_FLOAT)
     #define GR_TEXT_SCALAR_TYPE_IS_FLOAT   0
 #endif
@@ -310,13 +310,23 @@
 /**
  *  GR_AGGRESSIVE_SHADER_OPTS controls how aggressively shaders are optimized
  *  for special cases. On systems where program changes are expensive this
- *  may not be advantageous. Consecutive draws may no longer use the same 
+ *  may not be advantageous. Consecutive draws may no longer use the same
  *  program.
  */
 #if !defined(GR_AGGRESSIVE_SHADER_OPTS)
     #define GR_AGGRESSIVE_SHADER_OPTS 0
 #endif
 
+/**
+ * GR_GEOM_BUFFER_LOCK_THRESHOLD gives a threshold (in bytes) for when Gr should
+ * lock a GrGeometryBuffer to update its contents. It will use Lock() if the
+ * size of the udpated region is greater than the threshold. Otherwise it will
+ * use updateData() or updateSubData().
+ */
+#if !defined(GR_GEOM_BUFFER_LOCK_THRESHOLD)
+    #define GR_GEOM_BUFFER_LOCK_THRESHOLD (1 << 15)
+#endif
+
 ///////////////////////////////////////////////////////////////////////////////
 // tail section:
 //
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index ccc045e..6b9c3f3 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -20,12 +20,13 @@
 #include "GrClip.h"

 #include "GrGpu.h"

 #include "GrTextureCache.h"

-#include "GrInOrderDrawBuffer.h"

-#include "GrVertexBufferAllocPool.h"

 #include "GrPaint.h"

 

 class GrFontCache;

 class GrPathIter;

+class GrVertexBufferAllocPool;

+class GrIndexBufferAllocPool;

+class GrInOrderDrawBuffer;

 

 class GrContext : public GrRefCnt {

 public:

@@ -236,21 +237,21 @@
      *  @param paint        describes how to color pixels.

      *  @param strokeWidth  If strokeWidth < 0, then the rect is filled, else

      *                      the rect is mitered stroked based on strokeWidth. If

-     *                      strokeWidth == 0, then the stroke is always a single 

+     *                      strokeWidth == 0, then the stroke is always a single

      *                      pixel thick.

-     *  @param matrix       Optional matrix applied to the rect. Applied before 

+     *  @param matrix       Optional matrix applied to the rect. Applied before

      *                      context's matrix or the paint's matrix.

      *  The rects coords are used to access the paint (through texture matrix)

      */

-    void drawRect(const GrPaint& paint, 

-                  const GrRect&, 

+    void drawRect(const GrPaint& paint,

+                  const GrRect&,

                   GrScalar strokeWidth = -1,

                   const GrMatrix* matrix = NULL);

 

     /**

      * Maps a rect of paint coordinates onto the a rect of destination

      * coordinates. Each rect can optionally be transformed. The srcRect

-     * is stretched over the dstRect. The dstRect is transformed by the 

+     * is stretched over the dstRect. The dstRect is transformed by the

      * context's matrix and the srcRect is transformed by the paint's matrix.

      * Additional optional matrices can be provided by parameters.

      *

@@ -453,8 +454,9 @@
     GrTextureCache* fTextureCache;

     GrFontCache*    fFontCache;

 

-    GrVertexBufferAllocPool fVBAllocPool;

-    GrInOrderDrawBuffer     fTextDrawBuffer;

+    GrVertexBufferAllocPool*    fTextVBAllocPool;

+    GrIndexBufferAllocPool*     fTextIBAllocPool;

+    GrInOrderDrawBuffer*        fTextDrawBuffer;

 

     GrContext(GrGpu* gpu);

 

diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h
index e7f37f1..88782f1 100644
--- a/gpu/include/GrDrawTarget.h
+++ b/gpu/include/GrDrawTarget.h
@@ -47,8 +47,6 @@
      * The presence or absence of texture coordinates for each stage in the
      * vertex layout indicates whether a stage is enabled or not.
      */
-
-    // Currently there is just one stage but this will be changed soon.
     enum {
         kNumStages = 2,
         kMaxTexCoords = kNumStages
@@ -479,6 +477,36 @@
     GR_STATIC_ASSERT(kHighVertexLayoutBit < (1 << 8*sizeof(GrVertexLayout)));
 
     /**
+     * There are three paths for specifying geometry (vertices and optionally
+     * indices) to the draw target. When indexed drawing the indices and vertices
+     * can be each use a different path.
+     *
+     * 1. Provide a cpu array (set*SourceToArray). This is useful when the
+     *    caller's client has already provided vertex data in a format
+     *    the time compatible with a GrVertexLayout. The array must contain the
+     *    data at set*SourceToArray is called. The source stays in effect for
+     *    drawIndexed & drawNonIndexed calls until set*SourceToArray is called
+     *    again or one of the other two paths is chosen.
+     *
+     * 2. Reserve and Lock. This is most useful when the caller has data it must
+     *    transform before drawing and will not likely render it again. The
+     *    caller requests that the draw target make room for some amount of
+     *    vertex and/or index data. The target provides ptrs to hold the data
+     *    data. The caller can write the data into the pts up until the first
+     *    drawIndexed or drawNonIndexed call. At this point the data is frozen
+     *    and the ptrs are no longer guaranteed to be valid. All subsequent
+     *    drawIndexed & drawNonIndexed calls will use this data until
+     *    releaseReserved geometry is called. This must be called before another
+     *    source is set.
+     *
+     * 3. Vertex and Index Buffers. This is most useful for geometry that will
+     *    be rendered multiple times. SetVertexSourceToBuffer &
+     *    SetIndexSourceToBuffer are used to set the buffer and subsequent
+     *    drawIndexed and drawNonIndexed calls use this source until another
+     *    source is set.
+     */
+
+    /**
      * Reserves space for vertices and/or indices. Draw target will use
      * reserved vertices / indices at next draw.
      *
@@ -491,14 +519,19 @@
      *          to be filled by caller. The next indexed draw will read from
      *          these indices.
      *
-     * If a client does not already have a vertex buffer or cpu arrays then this
-     * is the preferred way to allocate vertex/index array. It allows the
-     * subclass of GrDrawTarget to decide whether to put data in buffers, to
-     * group vertex data that uses the same state (e.g. for deferred rendering),
-     * etc.
+     * If a client does not already have a vertex buffer then this is the
+     * preferred way to allocate vertex/index array. It allows the subclass of
+     * GrDrawTarget to decide whether to put data in buffers, to group vertex
+     * data that uses the same state (e.g. for deferred rendering), etc.
      *
-     * This must be matched with a releaseReservedGeometry call after all
-     * draws that reference the reserved geometry data have been called.
+     * Following the first draw after reserveAndLockGeometry the ptrs returned
+     * by releaseReservedGeometry are no longer valid and the geometry data
+     * cannot be further modified. The contents that were put in the reserved
+     * space can be drawn by multiple draws, however.
+     *
+     * reserveAndLockGeometry must be matched with a releaseReservedGeometry
+     * call after all draws that reference the reserved geometry data have
+     * been called.
      *
      * AutoGeometryRelease can be used to automatically call the release.
      *
@@ -541,8 +574,8 @@
      * @return  true if target should be flushed based on the input values.
      */
     virtual bool geometryHints(GrVertexLayout vertexLayout,
-                               int32_t*       vertexCount,
-                               int32_t*       indexCount) const;
+                               int* vertexCount,
+                               int* indexCount) const;
 
     /**
      * Releases reserved vertex/index data from reserveAndLockGeometry().
@@ -550,21 +583,25 @@
     void releaseReservedGeometry();
 
     /**
-     * Sets source of vertex data for the next draw. Data does not have to be
-     * in the array until drawIndexed or drawNonIndexed.
+     * Sets source of vertex data for the next draw. Array must contain
+     * the vertex data when this is called.
      *
      * @param array         cpu array containing vertex data.
-     * @param vertexLayout  layout of the vertex data in the array.
+     * @param size          size of the vertex data.
+     * @param vertexCount   the number of vertices in the array.
      */
-    void setVertexSourceToArray(const void* array, GrVertexLayout vertexLayout);
+    void setVertexSourceToArray(GrVertexLayout vertexLayout,
+                                const void* vertexArray,
+                                int vertexCount);
 
     /**
-     * Sets source of index data for the next indexed draw. Data does not have
-     * to be in the array until drawIndexed or drawNonIndexed.
+     * Sets source of index data for the next indexed draw. Array must contain
+     * the indices when this is called.
      *
-     * @param array cpu array containing index data.
+     * @param array         cpu array containing index data.
+     * @param indexCount    the number of indices in the array.
      */
-    void setIndexSourceToArray(const void* array);
+    void setIndexSourceToArray(const void* indexArray, int indexCount);
 
     /**
      * Sets source of vertex data for the next draw. Data does not have to be
@@ -574,8 +611,8 @@
      *                      unlocked before draw call.
      * @param vertexLayout  layout of the vertex data in the buffer.
      */
-    void setVertexSourceToBuffer(const GrVertexBuffer* buffer,
-                                 GrVertexLayout vertexLayout);
+    void setVertexSourceToBuffer(GrVertexLayout vertexLayout,
+                                 const GrVertexBuffer* buffer);
 
     /**
      * Sets source of index data for the next indexed draw. Data does not have
@@ -600,10 +637,10 @@
      *                     specified primitive.
      */
     virtual void drawIndexed(PrimitiveType type,
-                             uint32_t startVertex,
-                             uint32_t startIndex,
-                             uint32_t vertexCount,
-                             uint32_t indexCount) = 0;
+                             int startVertex,
+                             int startIndex,
+                             int vertexCount,
+                             int indexCount) = 0;
 
     /**
      * Draws non-indexed geometry using the current state and current vertex
@@ -615,8 +652,8 @@
      * @param vertexCount  one greater than the max index.
      */
     virtual void drawNonIndexed(PrimitiveType type,
-                                uint32_t startVertex,
-                                uint32_t vertexCount)  = 0;
+                                int startVertex,
+                                int vertexCount)  = 0;
 
     ///////////////////////////////////////////////////////////////////////////
 
@@ -631,14 +668,14 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
-    
+
     class AutoViewMatrixRestore : ::GrNoncopyable {
     public:
         AutoViewMatrixRestore() {
             fDrawTarget = NULL;
         }
 
-        AutoViewMatrixRestore(GrDrawTarget* target) 
+        AutoViewMatrixRestore(GrDrawTarget* target)
             : fDrawTarget(target), fMatrix(fDrawTarget->getViewMatrix()) {
             GrAssert(NULL != target);
         }
@@ -850,10 +887,16 @@
 
     virtual void clipWillChange(const GrClip& clip) = 0;
 
+    virtual void setVertexSourceToArrayHelper(const void* vertexArray,
+                                              int vertexCount) = 0;
+
+    virtual void setIndexSourceToArrayHelper(const void* indexArray,
+                                             int indexCount) = 0;
+
     enum GeometrySrcType {
-        kArray_GeometrySrcType,
-        kReserved_GeometrySrcType,
-        kBuffer_GeometrySrcType
+        kReserved_GeometrySrcType,  // src was set using reserveAndLockGeometry
+        kArray_GeometrySrcType,     // src was set using set*SourceToArray
+        kBuffer_GeometrySrcType     // src was set using set*SourceToBuffer
     };
 
     struct {
@@ -863,25 +906,21 @@
     } fReservedGeometry;
 
     struct GeometrySrc {
-        GeometrySrcType             fVertexSrc;
-        union {
-            const GrVertexBuffer*   fVertexBuffer;
-            const void*             fVertexArray;
-        };
-        GeometrySrcType             fIndexSrc;
-        union {
-            const GrIndexBuffer*    fIndexBuffer;
-            const void*             fIndexArray;
-        };
-        GrVertexLayout              fVertexLayout;
+        GeometrySrcType         fVertexSrc;
+        const GrVertexBuffer*   fVertexBuffer; // valid if src type is buffer
+        GeometrySrcType         fIndexSrc;
+        const GrIndexBuffer*    fIndexBuffer; // valid if src type is buffer
+        GrVertexLayout          fVertexLayout;
     } fGeometrySrc;
 
     GrClip fClip;
 
     DrState fCurrDrawState;
 
-    // not meant for outside usage. Could cause problems if calls between
-    // the save and restore mess with reserved geometry state.
+    // Not meant for external use. Only setVertexSourceToBuffer and
+    // setIndexSourceToBuffer will work since GrDrawTarget subclasses don't
+    // support nested reserveAndLockGeometry (and cpu arrays internally use the
+    // same path).
     class AutoGeometrySrcRestore {
     public:
         AutoGeometrySrcRestore(GrDrawTarget* target) {
diff --git a/gpu/include/GrGLConfig.h b/gpu/include/GrGLConfig.h
index bb10567..c2fdc0d 100644
--- a/gpu/include/GrGLConfig.h
+++ b/gpu/include/GrGLConfig.h
@@ -69,18 +69,15 @@
  *      4. Define GR_GL_PROC_ADDRESS.
  *      5. Optionally define GR_GL_PROC_ADDRESS_HEADER
  *
+ *------------------------------------------------------------------------------
  *
  * The following are optional defines that can be enabled as command line macros
  * defines, in a IDE project, in a GrUserConfig.h file, or in a GL custom setup
  * file (if one is in use). They don't require GR_GL_CUSTOM_SETUP or
  * GR_GL_CUSTOM_SETUP_HEADER to be enabled:
  *
- * GR_GL_NO_CLIENT_SIDE_ARRAYS can be defined to 1 to disable the use of client
- * side vertex and index arrays.
- *
  * GR_GL_LOG_CALLS if 1 GrPrintf every GL call (for debugging purposes) when the
  * global gPrintGL is true (it is initially true).
-
  */
 
 #if GR_GL_CUSTOM_SETUP
@@ -204,10 +201,6 @@
     #define GR_GL_LOG_CALLS 0
 #endif
 
-#if !defined(GR_GL_NO_CLIENT_SIDE_ARRAYS)
-    #define GR_GL_NO_CLIENT_SIDE_ARRAYS 0
-#endif
-
 ////////////////////////////////////////////////////////////////////////////////
 
 #if GR_SCALAR_IS_FIXED
@@ -374,4 +367,3 @@
 #endif
 
 #endif
-
diff --git a/gpu/include/GrGLConfig_chrome.h b/gpu/include/GrGLConfig_chrome.h
index 490a07e..e61a66c 100644
--- a/gpu/include/GrGLConfig_chrome.h
+++ b/gpu/include/GrGLConfig_chrome.h
@@ -18,6 +18,4 @@
 // chrome always assumes BGRA
 #define GR_GL_32BPP_COLOR_FORMAT    GR_BGRA
 
-#define GR_GL_NO_CLIENT_SIDE_ARRAYS 1
-
 #endif
diff --git a/gpu/include/GrGLIndexBuffer.h b/gpu/include/GrGLIndexBuffer.h
index 5177b4b..5755c07 100644
--- a/gpu/include/GrGLIndexBuffer.h
+++ b/gpu/include/GrGLIndexBuffer.h
@@ -27,7 +27,7 @@
 protected:
     GrGLIndexBuffer(GLuint id,
                     GrGpuGL* gl,
-                    uint32_t sizeInBytes,
+                    size_t sizeInBytes,
                     bool dynamic);
 public:
     virtual ~GrGLIndexBuffer();
@@ -37,10 +37,16 @@
     // overrides of GrIndexBuffer
     virtual void abandon();
     virtual void* lock();
+    virtual void* lockPtr() const;
     virtual void unlock();
     virtual bool isLocked() const;
-    virtual bool updateData(const void* src, uint32_t srcSizeInBytes);
+    virtual bool updateData(const void* src, size_t srcSizeInBytes);
+    virtual bool updateSubData(const void* src,  
+                               size_t srcSizeInBytes, 
+                               size_t offset);
 private:
+    void bind() const;
+    
     GrGpuGL*     fGL;
     GLuint       fBufferID;
     void*        fLockPtr;
diff --git a/gpu/include/GrGLVertexBuffer.h b/gpu/include/GrGLVertexBuffer.h
index 6b99f57..30ae734 100644
--- a/gpu/include/GrGLVertexBuffer.h
+++ b/gpu/include/GrGLVertexBuffer.h
@@ -27,7 +27,7 @@
 protected:
     GrGLVertexBuffer(GLuint id,
                      GrGpuGL* gl,
-                     uint32_t sizeInBytes,
+                     size_t sizeInBytes,
                      bool dynamic);
 
 public:
@@ -36,13 +36,18 @@
     // overrides of GrVertexBuffer
     virtual void abandon();
     virtual void* lock();
+    virtual void* lockPtr() const;
     virtual void unlock();
     virtual bool isLocked() const;
-    virtual bool updateData(const void* src, uint32_t srcSizeInBytes);
-
+    virtual bool updateData(const void* src, size_t srcSizeInBytes);
+    virtual bool updateSubData(const void* src,  
+                               size_t srcSizeInBytes, 
+                               size_t offset);
     GLuint bufferID() const;
 
 private:
+    void bind() const;
+    
     GrGpuGL*     fGL;
     GLuint       fBufferID;
     void*        fLockPtr;
diff --git a/gpu/include/GrGeometryBuffer.h b/gpu/include/GrGeometryBuffer.h
new file mode 100644
index 0000000..fc3e358
--- /dev/null
+++ b/gpu/include/GrGeometryBuffer.h
@@ -0,0 +1,116 @@
+/*

+ Copyright 2011 Google Inc.

+ 

+ Licensed under the Apache License, Version 2.0 (the "License");

+ you may not use this file except in compliance with the License.

+ You may obtain a copy of the License at

+ 

+ http://www.apache.org/licenses/LICENSE-2.0

+ 

+ Unless required by applicable law or agreed to in writing, software

+ distributed under the License is distributed on an "AS IS" BASIS,

+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ See the License for the specific language governing permissions and

+ limitations under the License.

+ */

+

+#ifndef GrGeometryBuffer_DEFINED

+#define GrGeometryBuffer_DEFINED

+

+#include "GrRefCnt.h"

+

+/**

+ * Parent class for vertex and index buffers

+ */

+class GrGeometryBuffer : public GrRefCnt {

+public:

+    virtual ~GrGeometryBuffer() {}

+    

+    /**

+     * Retrieves the size of the buffer

+     *

+     * @return the size of the buffer in bytes

+     */

+    size_t size() { return fSizeInBytes; }

+    

+    /**

+     *Retrieves whether the buffer was created with the dynamic flag

+     *

+     * @return true if the buffer was created with the dynamic flag

+     */

+    bool dynamic() const { return fDynamic; }

+    

+    /**

+     * Indicates that GPU context in which this veretx buffer was created is 

+     * destroyed and that Ganesh should not attempt to free the buffer in the

+     * underlying API.

+     */

+    virtual void abandon() = 0;

+    

+    /**

+     * Locks the buffer to be written by the CPU.

+     * 

+     * The previous content of the buffer is invalidated. It is an error

+     * to draw from the buffer while it is locked. It is an error to call lock

+     * on an already locked buffer.

+     * 

+     * @return a pointer to the data or NULL if the lock fails.

+     */

+    virtual void* lock() = 0;

+    

+    /**

+     * Returns the same ptr that lock() returned at time of lock or NULL if the

+     * is not locked.

+     *

+     * @return ptr to locked buffer data or undefined if buffer is not locked.

+     */

+    virtual void* lockPtr() const = 0;

+    

+    /** 

+     * Unlocks the buffer. 

+     * 

+     * The pointer returned by the previous lock call will no longer be valid.

+     */

+    virtual void unlock() = 0;

+    

+    /** 

+     Queries whether the buffer has been locked.

+     

+     @return true if the buffer is locked, false otherwise.

+     */

+    virtual bool isLocked() const = 0;

+    

+    /**

+     * Updates the buffer data. 

+     *  

+     * The size of the buffer will be preserved. The src data will be 

+     * placed at the begining of the buffer and any remaining contents will

+     * be undefined.

+     * 

+     * @return returns true if the update succeeds, false otherwise.

+     */

+    virtual bool updateData(const void* src, size_t srcSizeInBytes) = 0;

+    

+    /**

+     * Updates a portion of the buffer data. 

+     * 

+     * The contents of the buffer outside the update region are preserved.

+     * 

+     * @return returns true if the update succeeds, false otherwise.

+     */

+    virtual bool updateSubData(const void* src, 

+                               size_t srcSizeInBytes, 

+                               size_t offset) = 0;

+protected:

+    GrGeometryBuffer(size_t sizeInBytes, bool dynamic) : 

+        fSizeInBytes(sizeInBytes),

+        fDynamic(dynamic) {}

+

+private:

+    size_t fSizeInBytes;

+    bool     fDynamic;

+    

+    typedef GrRefCnt INHERITED;

+};

+

+#endif

diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h
index 2bbb419..9fb7b9c 100644
--- a/gpu/include/GrGpu.h
+++ b/gpu/include/GrGpu.h
@@ -25,6 +25,8 @@
 #include "GrTexture.h"
 #include "GrMemory.h"
 
+class GrVertexBufferAllocPool;
+class GrIndexBufferAllocPool;
 
 class GrGpu : public GrDrawTarget {
 
@@ -277,20 +279,20 @@
      *
      * @return    the true if NPOT texture/rendertarget can be created.
      */
-    bool npotRenderTargetSupport() const { return fNPOTRenderTargetSupport; } 
+    bool npotRenderTargetSupport() const { return fNPOTRenderTargetSupport; }
 
     int maxTextureDimension() const { return fMaxTextureDimension; }
 
     // GrDrawTarget overrides
     virtual void drawIndexed(PrimitiveType type,
-                             uint32_t startVertex,
-                             uint32_t startIndex,
-                             uint32_t vertexCount,
-                             uint32_t indexCount);
+                             int startVertex,
+                             int startIndex,
+                             int vertexCount,
+                             int indexCount);
 
     virtual void drawNonIndexed(PrimitiveType type,
-                                uint32_t startVertex,
-                                uint32_t vertexCount);
+                                int startVertex,
+                                int vertexCount);
 
     /**
      * Determines if blend is effectively disabled.
@@ -341,7 +343,7 @@
                                         /* rendering a hard clip to the stencil
                                            buffer. Subsequent draws with other
                                            StencilPass values will be clipped
-                                           if kStencilClip_StateBit is set. */
+                                           if kClip_StateBit is set. */
         kGpuCount_StencilPass
     };
 
@@ -384,6 +386,29 @@
     int fMinRenderTargetHeight;
     int fMaxTextureDimension;
 
+    Stats           fStats;
+
+    const GrVertexBuffer*           fCurrPoolVertexBuffer;
+    int                             fCurrPoolStartVertex;
+
+    const GrIndexBuffer*            fCurrPoolIndexBuffer;
+    int                             fCurrPoolStartIndex;
+
+    // GrDrawTarget overrides
+    virtual bool acquireGeometryHelper(GrVertexLayout vertexLayout,
+                                       void**         vertices,
+                                       void**         indices);
+    virtual void releaseGeometryHelper();
+
+    virtual void setVertexSourceToArrayHelper(const void* vertexArray,
+                                              int vertexCount);
+
+    virtual void setIndexSourceToArrayHelper(const void* indexArray,
+                                             int indexCount);
+    // Helpers for setting up geometry state
+    void finalizeReservedVertices();
+    void finalizeReservedIndices();
+
     // overridden by API specific GrGpu-derived class to perform the draw call.
     virtual void drawIndexedHelper(PrimitiveType type,
                                    uint32_t startVertex,
@@ -396,11 +421,12 @@
                                       uint32_t numVertices) = 0;
 
     // called to program the vertex data, indexCount will be 0 if drawing non-
-    // indexed geometry.
-    virtual void setupGeometry(uint32_t startVertex,
-                               uint32_t startIndex,
-                               uint32_t vertexCount,
-                               uint32_t indexCount) = 0;
+    // indexed geometry. The subclass may adjust the startVertex and/or
+    // startIndex since it may have already accounted for these in the setup.
+    virtual void setupGeometry(int* startVertex,
+                               int* startIndex,
+                               int vertexCount,
+                               int indexCount) = 0;
 
 
     // The GrGpu typically records the clients requested state and then flushes
@@ -415,33 +441,21 @@
     // GrGpu subclass removes the clip from the stencil buffer
     virtual void eraseStencilClip() = 0;
 
-    // GrDrawTarget overrides
-    virtual bool acquireGeometryHelper(GrVertexLayout vertexLayout,
-                                       void**         vertices,
-                                       void**         indices);
-    virtual void releaseGeometryHelper();
-
 private:
-    mutable GrIndexBuffer* fQuadIndexBuffer; // mutable so it can be
-                                             // created on-demand
 
-    mutable GrVertexBuffer* fUnitSquareVertexBuffer; // mutable so it can be
-                                                     // created on-demand
+    void prepareVertexPool();
+    void prepareIndexPool();
 
-    static const int MAX_VERTEX_SIZE = GR_CT_MAX(2*sizeof(GrPoint) + sizeof(GrColor),
-                                                 2*sizeof(GrGpuTextVertex));
-    static const int VERTEX_STORAGE = 16 * MAX_VERTEX_SIZE;
-    static const int INDEX_STORAGE = 32 * sizeof(uint16_t);
+    GrVertexBufferAllocPool*    fVertexPool;
 
-protected:
-    GrAutoSMalloc<VERTEX_STORAGE> fVertices;
-    GrAutoSMalloc<INDEX_STORAGE>  fIndices;
+    GrIndexBufferAllocPool*     fIndexPool;
 
-    Stats           fStats;
+    mutable GrIndexBuffer*      fQuadIndexBuffer; // mutable so it can be
+                                                  // created on-demand
 
-private:
-    typedef GrRefCnt INHERITED;
+    mutable GrVertexBuffer*     fUnitSquareVertexBuffer; // mutable so it can be
+                                                         // created on-demand
+    typedef GrDrawTarget INHERITED;
 };
 
 #endif
-
diff --git a/gpu/include/GrInOrderDrawBuffer.h b/gpu/include/GrInOrderDrawBuffer.h
index 805861a..463ea2d 100644
--- a/gpu/include/GrInOrderDrawBuffer.h
+++ b/gpu/include/GrInOrderDrawBuffer.h
@@ -24,30 +24,43 @@
 #include "GrClip.h"
 
 class GrVertexBufferAllocPool;
+class GrIndexBufferAllocPool;
 
-// TODO: don't save clip per draw
+/**
+ * GrInOrderDrawBuffer is an implementation of GrDrawTarget that queues up
+ * draws for eventual playback into a GrGpu. In theory one draw buffer could
+ * playback into another. When index or vertex buffers are used as geometry
+ * sources it is the callers the draw buffer only holds references to the
+ * buffers. It is the callers responsibility to ensure that the data is still
+ * valid when the draw buffer is played back into a GrGpu. Similarly, it is the
+ * caller's responsibility to ensure that all referenced textures, buffers,
+ * and rendertargets are associated in the GrGpu object that the buffer is
+ * played back into. The buffer requires VB and IB pools to store geometry.
+ */
+
 class GrInOrderDrawBuffer : public GrDrawTarget {
 public:
 
-    GrInOrderDrawBuffer(GrVertexBufferAllocPool* pool = NULL);
+    GrInOrderDrawBuffer(GrVertexBufferAllocPool* vertexPool,
+                        GrIndexBufferAllocPool* indexPool);
 
     virtual ~GrInOrderDrawBuffer();
 
     void initializeDrawStateAndClip(const GrDrawTarget& target);
 
-    virtual void drawIndexed(PrimitiveType type,
-                             uint32_t startVertex,
-                             uint32_t startIndex,
-                             uint32_t vertexCount,
-                             uint32_t indexCount);
+    virtual void drawIndexed(PrimitiveType primitiveType,
+                             int startVertex,
+                             int startIndex,
+                             int vertexCount,
+                             int indexCount);
 
-    virtual void drawNonIndexed(PrimitiveType type,
-                                uint32_t startVertex,
-                                uint32_t vertexCount);
+    virtual void drawNonIndexed(PrimitiveType primitiveType,
+                                int startVertex,
+                                int vertexCount);
 
     virtual bool geometryHints(GrVertexLayout vertexLayout,
-                               int32_t*       vertexCount,
-                               int32_t*       indexCount) const;
+                               int* vertexCount,
+                               int* indexCount) const;
 
     void reset();
 
@@ -56,24 +69,16 @@
 private:
 
     struct Draw {
-        PrimitiveType   fType;
-        uint32_t        fStartVertex;
-        uint32_t        fStartIndex;
-        uint32_t        fVertexCount;
-        uint32_t        fIndexCount;
-        bool            fStateChange;
-        GrVertexLayout  fVertexLayout;
-        bool            fUseVertexBuffer;
-        bool            fClipChanged;
-        union {
-            const GrVertexBuffer*   fVertexBuffer;
-            const void*             fVertexArray;
-        };
-        bool            fUseIndexBuffer;
-        union {
-            const GrIndexBuffer*    fIndexBuffer;
-            const void*             fIndexArray;
-        };
+        PrimitiveType           fPrimitiveType;
+        int                     fStartVertex;
+        int                     fStartIndex;
+        int                     fVertexCount;
+        int                     fIndexCount;
+        bool                    fStateChanged;
+        bool                    fClipChanged;
+        GrVertexLayout          fVertexLayout;
+        const GrVertexBuffer*   fVertexBuffer;
+        const GrIndexBuffer*    fIndexBuffer;
     };
 
     virtual bool acquireGeometryHelper(GrVertexLayout vertexLayout,
@@ -82,33 +87,36 @@
     virtual void releaseGeometryHelper();
     virtual void clipWillChange(const GrClip& clip);
 
+    virtual void setVertexSourceToArrayHelper(const void* vertexArray,
+                                              int vertexCount);
+
+    virtual void setIndexSourceToArrayHelper(const void* indexArray,
+                                             int indexCount);
+
 
     bool grabState();
     bool grabClip();
 
     GrTAllocator<Draw>              fDraws;
-    // HACK: We hold refs on textures in saved state but not RTs, VBs, and IBs.
-    // a) RTs aren't ref counted (yet)
-    // b) we are only using this class for text which doesn't use VBs or IBs
-    // This should be fixed by either refcounting them all or having some
-    // notification occur if a cache is purging an object we have a ptr to.
+    // HACK: We currently do not hold refs on RTs in the saved draw states.
+    // The reason is that in the GL implementation when a GrTexture is destroyed
+    // that has an associated RT the RT is destroyed regardless of its ref count.
+    // We need a third object that holds the shared GL ids and persists until
+    // both reach ref count 0. (skia issue 122)
     GrTAllocator<SavedDrawState>    fStates;
 
     GrTAllocator<GrClip>            fClips;
     bool                            fClipChanged;
 
-    // vertices are either queued in cpu arrays or some vertex buffer pool
-    // that knows about a specific GrGpu object.
-    GrAllocPool                     fCPUVertices;
-    GrVertexBufferAllocPool*        fBufferVertices;
-    GrAllocPool                     fIndices;
-    void*                           fCurrReservedVertices;
-    void*                       	fCurrReservedIndices;
-    // valid if we're queueing vertices in fBufferVertices
-    GrVertexBuffer*                 fCurrVertexBuffer;
-    uint32_t                        fCurrStartVertex;
+    GrVertexBufferAllocPool&        fVertexPool;
+    const GrVertexBuffer*           fCurrPoolVertexBuffer;
+    int                             fCurrPoolStartVertex;
 
-    // caller may conservatively over allocate vertices / indices.
+    GrIndexBufferAllocPool&         fIndexPool;
+    const GrIndexBuffer*            fCurrPoolIndexBuffer;
+    int                             fCurrPoolStartIndex;
+
+    // caller may conservatively over reserve vertices / indices.
     // we release unused space back to allocator if possible
     size_t                          fReservedVertexBytes;
     size_t                          fReservedIndexBytes;
diff --git a/gpu/include/GrIndexBuffer.h b/gpu/include/GrIndexBuffer.h
index 0f4c4d6..85ff749 100644
--- a/gpu/include/GrIndexBuffer.h
+++ b/gpu/include/GrIndexBuffer.h
@@ -18,75 +18,14 @@
 #ifndef GrIndexBuffer_DEFINED
 #define GrIndexBuffer_DEFINED
 
-#include "GrRefCnt.h"
+#include "GrGeometryBuffer.h"
 
-class GrIndexBuffer : public GrRefCnt {
+class GrIndexBuffer : public GrGeometryBuffer {
 protected:
-    GrIndexBuffer(uint32_t sizeInBytes, bool dynamic) : 
-                  fSizeInBytes(sizeInBytes),
-                  fDynamic(dynamic) {}
-public:
-    virtual ~GrIndexBuffer() {}
-    
-    /**
-     Retrieves the size of the index buffer
-
-     @return the size of the index buffer in bytes
-     */
-    uint32_t size() const { return fSizeInBytes; }
-   
-    /**
-     Retrieves whether the index buffer was created with the dynamic flag
-
-     @return true if the index buffer was created with the dynamic flag
-     */
-    bool dynamic() const { return fDynamic; }
-
-    /**
-     Indicates that GPU context in which this veretx buffer was created is 
-     destroyed and that Ganesh should not attempt to free the texture with the
-     underlying API.
-     */
-    virtual void abandon() = 0;
-
-    /**
-     Locks the index buffer to be written by the CPU.
-     
-     The previous content of the index buffer is invalidated. It is an error to
-     draw whil the buffer is locked.  It is an error to call lock on an already
-     locked index buffer.
-     
-     @return a pointer to the index data or NULL if the lock fails.
-     */
-    virtual void* lock() = 0;
-
-    /** 
-     Unlocks the index buffer. 
-     
-     The pointer returned by the previous lock call will no longer be valid.
-     */
-    virtual void unlock() = 0;
-
-    /** 
-     Queries whether the index buffer has been locked.
-     
-     @return true if the index buffer is locked, false otherwise.
-     */
-    virtual bool isLocked() const = 0;
-
-    /**
-     Updates the index buffer data. 
-     
-     The size of the index buffer will be preserved. However, only the updated 
-     region will have defined contents.
-
-     @return returns true if the update succeeds, false otherwise.
-     */
-    virtual bool updateData(const void* src, uint32_t srcSizeInBytes) = 0;
-
+    GrIndexBuffer(size_t sizeInBytes, bool dynamic) :
+        INHERITED(sizeInBytes, dynamic) {}
 private:
-    uint32_t fSizeInBytes;
-    bool     fDynamic;
+    typedef GrGeometryBuffer INHERITED;
 };
 
 #endif
diff --git a/gpu/include/GrMemory.h b/gpu/include/GrMemory.h
index 673d0ab..be8b1d7 100644
--- a/gpu/include/GrMemory.h
+++ b/gpu/include/GrMemory.h
@@ -22,7 +22,10 @@
 
 class GrAutoMalloc : GrNoncopyable {
 public:
-    GrAutoMalloc(size_t bytes) : fPtr(GrMalloc(bytes)) {}
+    GrAutoMalloc() : fPtr(NULL), fAllocatedBytes(0){
+    }
+
+    GrAutoMalloc(size_t bytes) : fPtr(GrMalloc(bytes)), fAllocatedBytes(bytes) {}
     ~GrAutoMalloc() { GrFree(fPtr); }
 
     /**
@@ -31,6 +34,8 @@
      */
     void* get() const { return fPtr; }
 
+    size_t size() const { return fAllocatedBytes; }
+
     /**
      *  transfer ownership of the memory to the caller. It must be freed with
      *  a call to GrFree()
@@ -38,19 +43,44 @@
     void* detach() {
         void* ptr = fPtr;
         fPtr = NULL;    // we no longer own the block
+        fAllocatedBytes = 0;
         return ptr;
     }
-    
+
+    /**
+     *  Reallocates to a new size. May or may not call malloc. The contents
+     *  are not preserved. If growOnly is true it will never reduce the
+     *  allocated size.
+     */
+    void* realloc(size_t newSize, bool growOnly = false) {
+        bool alloc;
+        if (growOnly) {
+            alloc = newSize > fAllocatedBytes;
+        } else {
+            alloc = newSize != fAllocatedBytes;
+        }
+        if (alloc) {
+            GrFree(fPtr);
+            fPtr = newSize ? GrMalloc(newSize) : NULL;
+            fAllocatedBytes = newSize;
+        }
+        GrAssert(fAllocatedBytes >= newSize);
+        GR_DEBUGCODE(memset(fPtr, 0xEF, fAllocatedBytes));
+        return fPtr;
+    }
+
     /**
      *  free the block now. get() will now return NULL
      */
     void free() {
         GrFree(fPtr);
         fPtr = NULL;
+        fAllocatedBytes = 0;
     }
 
 private:
     void* fPtr;
+    size_t fAllocatedBytes;
 };
 
 /**
@@ -86,10 +116,10 @@
      *  detached.
      */
     void* get() const { return fPtr; }
-    
+
     /**
-     *  Reallocates to a new size. May or may not call malloc. The contents 
-     *  are not preserved. If growOnly is true it will never reduce the 
+     *  Reallocates to a new size. May or may not call malloc. The contents
+     *  are not preserved. If growOnly is true it will never reduce the
      *  allocated size.
      */
     void* realloc(size_t newSize, bool growOnly = false) {
@@ -101,7 +131,7 @@
                 GrFree(fPtr);
                 fPtr = fStorage;
                 fAllocatedBytes = SIZE;
-            }            
+            }
         } else if ((newSize > fAllocatedBytes) ||
                    (!growOnly && newSize < (fAllocatedBytes >> 1))) {
             if (NULL != fPtr && fPtr != (void*)fStorage) {
@@ -115,7 +145,7 @@
         GR_DEBUGCODE(memset(fPtr, 0xEF, fAllocatedBytes));
         return fPtr;
     }
-   
+
     /**
      *  free the block now. get() will now return NULL
      */
@@ -126,7 +156,7 @@
         fAllocatedBytes = 0;
         fPtr = NULL;
     }
-    
+
 private:
     void*    fPtr;
     uint32_t fAllocatedBytes;
diff --git a/gpu/include/GrTArray.h b/gpu/include/GrTArray.h
index f0d9494..c31c820 100644
--- a/gpu/include/GrTArray.h
+++ b/gpu/include/GrTArray.h
@@ -21,8 +21,6 @@
 #include <new>
 #include "GrTypes.h"
 
-// TODO: convert from uint32_t to int.
-
 // DATA_TYPE indicates that T has a trivial cons, destructor
 // and can be shallow-copied
 template <typename T, bool DATA_TYPE = false> class GrTArray {
@@ -35,15 +33,18 @@
         fPreAllocMemArray = NULL;
     }
 
-    GrTArray(uint32_t reserveCount) {
+    explicit GrTArray(int reserveCount) {
+        GrAssert(reserveCount >= 0);
         fCount = 0;
-        fReserveCount = GrMax(reserveCount, (uint32_t)MIN_ALLOC_COUNT);
+        fReserveCount = reserveCount > MIN_ALLOC_COUNT ? reserveCount :
+                                                         MIN_ALLOC_COUNT;
         fAllocCount = fReserveCount;
         fMemArray = GrMalloc(sizeof(T) * fReserveCount);
         fPreAllocMemArray = NULL;
     }
 
-    GrTArray(void* preAllocStorage, uint32_t preAllocCount) {
+    GrTArray(void* preAllocStorage, int preAllocCount) {
+        GrAssert(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
@@ -57,7 +58,7 @@
         fPreAllocMemArray   = preAllocStorage;
     }
 
-    GrTArray(const GrTArray& array) {
+    explicit GrTArray(const GrTArray& array) {
         fCount              = array.count();
         fReserveCount       = MIN_ALLOC_COUNT;
         fAllocCount         = GrMax(fReserveCount, fCount);
@@ -66,13 +67,14 @@
         if (DATA_TYPE) {
             memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
         } else {
-            for (uint32_t i = 0; i < fCount; ++i) {
+            for (int i = 0; i < fCount; ++i) {
                 new (fItemArray + i) T(array[i]);
             }
         }
     }
 
-    GrTArray(const T* array, uint32_t count) {
+    GrTArray(const T* array, int count) {
+        GrAssert(count >= 0);
         fCount              = count;
         fReserveCount       = MIN_ALLOC_COUNT;
         fAllocCount         = GrMax(fReserveCount, fCount);
@@ -81,14 +83,16 @@
         if (DATA_TYPE) {
             memcpy(fMemArray, array, sizeof(T) * fCount);
         } else {
-            for (uint32_t i = 0; i < fCount; ++i) {
+            for (int i = 0; i < fCount; ++i) {
                 new (fItemArray + i) T(array[i]);
             }
         }
     }
 
     GrTArray(const GrTArray& array,
-             void* preAllocStorage, uint32_t preAllocCount) {
+             void* preAllocStorage, int preAllocCount) {
+
+        GrAssert(preAllocCount >= 0);
 
         // for same reason as non-copying cons we allow NULL, 0 for prealloc
         GrAssert((NULL == preAllocStorage) == !preAllocCount);
@@ -109,14 +113,17 @@
         if (DATA_TYPE) {
             memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
         } else {
-            for (uint32_t i = 0; i < fCount; ++i) {
+            for (int i = 0; i < fCount; ++i) {
                 new (fItemArray + i) T(array[i]);
             }
         }
     }
 
-    GrTArray(const T* array, uint32_t count,
-             void* preAllocStorage, uint32_t preAllocCount) {
+    GrTArray(const T* array, int count,
+             void* preAllocStorage, int preAllocCount) {
+
+        GrAssert(count >= 0);
+        GrAssert(preAllocCount >= 0);
 
         // for same reason as non-copying cons we allow NULL, 0 for prealloc
         GrAssert((NULL == preAllocStorage) == !preAllocCount);
@@ -137,14 +144,14 @@
         if (DATA_TYPE) {
             memcpy(fMemArray, array, sizeof(T) * fCount);
         } else {
-            for (uint32_t i = 0; i < fCount; ++i) {
+            for (int i = 0; i < fCount; ++i) {
                 new (fItemArray + i) T(array[i]);
             }
         }
     }
 
     GrTArray& operator =(const GrTArray& array) {
-        for (uint32_t i = 0; i < fCount; ++i) {
+        for (int i = 0; i < fCount; ++i) {
             fItemArray[i].~T();
         }
         fCount = 0;
@@ -153,7 +160,7 @@
         if (DATA_TYPE) {
             memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
         } else {
-            for (uint32_t i = 0; i < fCount; ++i) {
+            for (int i = 0; i < fCount; ++i) {
                 new (fItemArray + i) T(array[i]);
             }
         }
@@ -161,7 +168,7 @@
     }
 
     ~GrTArray() {
-        for (uint32_t i = 0; i < fCount; ++i) {
+        for (int i = 0; i < fCount; ++i) {
             fItemArray[i].~T();
         }
         if (fMemArray != fPreAllocMemArray) {
@@ -169,7 +176,7 @@
         }
     }
 
-    uint32_t count() const { return fCount; }
+    int count() const { return fCount; }
 
     bool empty() const { return !fCount; }
 
@@ -180,32 +187,36 @@
         return fItemArray[fCount-1];
     }
 
-    void push_back_n(uint32_t n) {
+    void push_back_n(int n) {
+        GrAssert(n >= 0);
         checkRealloc(n);
-        for (uint32_t i = 0; i < n; ++i) {
+        for (int i = 0; i < n; ++i) {
             new (fItemArray + fCount + i) T;
         }
         fCount += n;
     }
 
     void pop_back() {
-        GrAssert(0 != fCount);
+        GrAssert(fCount > 0);
         --fCount;
         fItemArray[fCount].~T();
         checkRealloc(0);
     }
 
-    void pop_back_n(uint32_t n) {
+    void pop_back_n(int n) {
+        GrAssert(n >= 0);
         GrAssert(fCount >= n);
         fCount -= n;
-        for (uint32_t i = 0; i < n; ++i) {
+        for (int i = 0; i < n; ++i) {
             fItemArray[i].~T();
         }
         checkRealloc(0);
     }
 
     // pushes or pops from the back to resize
-    void resize_back(uint32_t newCount) {
+    void resize_back(int newCount) {
+        GrAssert(newCount >= 0);
+
         if (newCount > fCount) {
             push_back_n(newCount - fCount);
         } else if (newCount < fCount) {
@@ -213,42 +224,50 @@
         }
     }
 
-    T& operator[] (uint32_t i) {
+    T& operator[] (int i) {
         GrAssert(i < fCount);
+        GrAssert(i >= 0);
         return fItemArray[i];
     }
 
-    const T& operator[] (uint32_t i) const {
+    const T& operator[] (int i) const {
         GrAssert(i < fCount);
+        GrAssert(i >= 0);
         return fItemArray[i];
     }
 
-    T& front() { GrAssert(fCount); return fItemArray[0];}
+    T& front() { GrAssert(fCount > 0); return fItemArray[0];}
 
-    const T& front() const { GrAssert(fCount); return fItemArray[0];}
+    const T& front() const { GrAssert(fCount > 0); return fItemArray[0];}
 
     T& back() { GrAssert(fCount); return fItemArray[fCount - 1];}
 
-    const T& back() const { GrAssert(fCount); return fItemArray[fCount - 1];}
+    const T& back() const { GrAssert(fCount > 0); return fItemArray[fCount - 1];}
 
-    T& fromBack(uint32_t i) {
+    T& fromBack(int i) {
+        GrAssert(i >= 0);
         GrAssert(i < fCount);
         return fItemArray[fCount - i - 1];
     }
 
-    const T& fromBack(uint32_t i) const {
+    const T& fromBack(int i) const {
+        GrAssert(i >= 0);
         GrAssert(i < fCount);
         return fItemArray[fCount - i - 1];
     }
 
 private:
-    static const uint32_t MIN_ALLOC_COUNT = 8;
 
-    inline void checkRealloc(int32_t delta) {
-        GrAssert(-delta <= (int32_t)fCount);
+    static const int MIN_ALLOC_COUNT = 8;
 
-        uint32_t newCount = fCount + delta;
-        uint32_t fNewAllocCount = fAllocCount;
+    inline void checkRealloc(int delta) {
+        GrAssert(fCount >= 0);
+        GrAssert(fAllocCount >= 0);
+
+        GrAssert(-delta <= fCount);
+
+        int newCount = fCount + delta;
+        int fNewAllocCount = fAllocCount;
 
         if (newCount > fAllocCount) {
             fNewAllocCount = GrMax(newCount + ((newCount + 1) >> 1),
@@ -271,7 +290,7 @@
             if (DATA_TYPE) {
                 memcpy(fNewMemArray, fMemArray, fCount * sizeof(T));
             } else {
-                for (uint32_t i = 0; i < fCount; ++i) {
+                for (int i = 0; i < fCount; ++i) {
                     new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]);
                     fItemArray[i].~T();
                 }
@@ -284,9 +303,9 @@
         }
     }
 
-    uint32_t fReserveCount;
-    uint32_t fCount;
-    uint32_t fAllocCount;
+    int fReserveCount;
+    int fCount;
+    int fAllocCount;
     void*    fPreAllocMemArray;
     union {
         T*       fItemArray;
diff --git a/gpu/include/GrTexture.h b/gpu/include/GrTexture.h
index 71a58e6..4776539 100644
--- a/gpu/include/GrTexture.h
+++ b/gpu/include/GrTexture.h
@@ -25,10 +25,9 @@
 /**
  * GrRenderTarget represents a 2D buffer of pixels that can be rendered to.
  * A context's render target is set by setRenderTarget(). Render targets are
- * created by a createTexture with the kRenderTarget_TextureFlag flag. 
- * Additionally, the rendering destination set in the underlying 3D API at the
- * time of GrContext's creation can be retrieved by calling 
- * currentRenderTarget() after creation before any calles to setRenderTarget().
+ * created by a createTexture with the kRenderTarget_TextureFlag flag.
+ * Additionally, GrContext provides methods for creating GrRenderTargets
+ * that wrap externally created render targets.
  */
 class GrRenderTarget : public GrRefCnt {
 public:
@@ -40,7 +39,7 @@
      * @return the height of the rendertarget
      */
     virtual uint32_t height() const = 0;
-    
+
     /**
      * @return the texture associated with the rendertarget, may be NULL.
      */
@@ -70,10 +69,10 @@
               uint32_t contentHeight,
               uint32_t allocWidth,
               uint32_t allocHeight,
-              PixelConfig config) : 
-                fAllocWidth(allocWidth), 
+              PixelConfig config) :
+                fAllocWidth(allocWidth),
                 fAllocHeight(allocHeight),
-                fContentWidth(contentWidth), 
+                fContentWidth(contentWidth),
                 fContentHeight(contentHeight),
                 fConfig(config) {
                     // only make sense if alloc size is pow2
@@ -82,18 +81,18 @@
                 }
 public:
     virtual ~GrTexture();
-    
+
     /**
      * Retrieves the width of the content area of the texture. Reflects the
      * width passed to GrGpu::createTexture().
-     * 
+     *
      * @return the width in texels
      */
     uint32_t contentWidth() const { return fContentWidth; }
     /**
      * Retrieves the height of the content area of the texture. Reflects the
      * height passed to GrGpu::createTexture().
-     * 
+     *
      * @return the height in texels
      */
     uint32_t contentHeight() const { return fContentHeight; }
@@ -120,7 +119,7 @@
     GrFixed normalizeFixedY(GrFixed y) const { GrAssert(GrIsPow2(fAllocHeight));
                                                return y >> fShiftFixedY; }
 
-    /** 
+    /**
      * Retrieves the pixel config specified when the texture was created.
      */
     PixelConfig config() const { return fConfig; }
@@ -149,7 +148,7 @@
                                    const void* srcData) = 0;
     /**
      * Indicates that GPU context in which this texture was created is destroyed
-     * and that Ganesh should not attempt to free the texture with the 
+     * and that Ganesh should not attempt to free the texture with the
      * underlying API.
      */
     virtual void abandon() = 0;
@@ -157,7 +156,7 @@
     /**
      * Queries whether the texture was created as a render target.
      *
-     * Use asRenderTarget() to use the texture as a render target if this 
+     * Use asRenderTarget() to use the texture as a render target if this
      * returns true.
      *
      * @return true if the texture was created as a render target.
@@ -194,8 +193,8 @@
 #else
     void validate() const {}
 #endif
-    
-private:    
+
+private:
     uint32_t fAllocWidth;
     uint32_t fAllocHeight;
     uint32_t fContentWidth;
diff --git a/gpu/include/GrTypes.h b/gpu/include/GrTypes.h
index a799c2e..9553678 100644
--- a/gpu/include/GrTypes.h
+++ b/gpu/include/GrTypes.h
@@ -45,28 +45,40 @@
 /**
  *  divide, rounding up
  */
-inline uint32_t GrUIDivRoundUp(uint32_t x, uint32_t y) {
+static inline uint32_t GrUIDivRoundUp(uint32_t x, uint32_t y) {
+    return (x + (y-1)) / y;
+}
+static inline size_t GrSizeDivRoundUp(size_t x, uint32_t y) {
     return (x + (y-1)) / y;
 }
 
 /**
  *  align up
  */
-inline uint32_t GrUIAlignUp(uint32_t x, uint32_t alignment) {
+static inline uint32_t GrUIAlignUp(uint32_t x, uint32_t alignment) {
     return GrUIDivRoundUp(x, alignment) * alignment;
 }
+static inline uint32_t GrSizeAlignUp(size_t x, uint32_t alignment) {
+    return GrSizeDivRoundUp(x, alignment) * alignment;
+}
 
 /**
  * amount of pad needed to align up
  */
-inline uint32_t GrUIAlignUpPad(uint32_t x, uint32_t alignment) {
+static inline uint32_t GrUIAlignUpPad(uint32_t x, uint32_t alignment) {
+    return (alignment - x % alignment) % alignment;
+}
+static inline size_t GrSizeAlignUpPad(size_t x, uint32_t alignment) {
     return (alignment - x % alignment) % alignment;
 }
 
 /**
  *  align down
  */
-inline uint32_t GrUIAlignDown(uint32_t x, uint32_t alignment) {
+static inline uint32_t GrUIAlignDown(uint32_t x, uint32_t alignment) {
+    return (x / alignment) * alignment;
+}
+static inline uint32_t GrSizeAlignDown(size_t x, uint32_t alignment) {
     return (x / alignment) * alignment;
 }
 
diff --git a/gpu/include/GrUserConfig.h b/gpu/include/GrUserConfig.h
index 155dc8c..4d44172 100644
--- a/gpu/include/GrUserConfig.h
+++ b/gpu/include/GrUserConfig.h
@@ -65,6 +65,13 @@
  */
 //#define GR_AGGRESSIVE_SHADER_OPTS 1
 
+/*
+ * This gives a threshold in bytes of when to lock a GrGeometryBuffer vs using
+ * updateData or updateSubData. (Note the depending on the underlying 3D API
+ * the update functions may always be implemented using a lock)
+ */
+//#define GR_GEOM_BUFFER_LOCK_THRESHOLD (1<<15)
+
 ///////////////////////////////////////////////////////////////////////////////
 /*
  *  temporary flags (may go away soon)
diff --git a/gpu/include/GrVertexBuffer.h b/gpu/include/GrVertexBuffer.h
index 5e83de9..3792c15 100644
--- a/gpu/include/GrVertexBuffer.h
+++ b/gpu/include/GrVertexBuffer.h
@@ -18,75 +18,14 @@
 #ifndef GrVertexBuffer_DEFINED
 #define GrVertexBuffer_DEFINED
 
-#include "GrRefCnt.h"
+#include "GrGeometryBuffer.h"
 
-class GrVertexBuffer : public GrRefCnt {
+class GrVertexBuffer : public GrGeometryBuffer {
 protected:
-    GrVertexBuffer(uint32_t sizeInBytes, bool dynamic) : 
-             fSizeInBytes(sizeInBytes),
-             fDynamic(dynamic) {}
-public:
-    virtual ~GrVertexBuffer() {}
-    
-    /**
-     Retrieves the size of the vertex buffer
-
-     @return the size of the vertex buffer in bytes
-     */
-    uint32_t size() { return fSizeInBytes; }
-
-    /**
-     Retrieves whether the vertex buffer was created with the dynamic flag
-
-     @return true if the vertex buffer was created with the dynamic flag
-     */
-    bool dynamic() const { return fDynamic; }
-
-    /**
-     Indicates that GPU context in which this veretx buffer was created is 
-     destroyed and that Ganesh should not attempt to free the texture with the
-     underlying API.
-     */
-    virtual void abandon() = 0;
-
-    /**
-     Locks the vertex buffer to be written by the CPU.
-     
-     The previous content of the vertex buffer is invalidated. It is an error to
-     draw whil the buffer is locked.  It is an error to call lock on an already
-     locked vertex buffer.
-     
-     @return a pointer to the vertex data or NULL if the lock fails.
-     */
-    virtual void* lock() = 0;
-
-    /** 
-     Unlocks the vertex buffer. 
-     
-     The pointer returned by the previous lock call will no longer be valid.
-     */
-    virtual void unlock() = 0;
-
-    /** 
-     Queries whether the vertex buffer has been locked.
-     
-     @return true if the vertex buffer is locked, false otherwise.
-     */
-    virtual bool isLocked() const = 0;
-
-    /**
-     Updates the vertex buffer data. 
-     
-     The size of the vertex buffer will be preserved. However, only the updated
-     region will have defined contents.
-
-     @return returns true if the update succeeds, false otherwise.
-     */
-    virtual bool updateData(const void* src, uint32_t srcSizeInBytes) = 0;
-
+    GrVertexBuffer(size_t sizeInBytes, bool dynamic) : 
+        INHERITED(sizeInBytes, dynamic) {}
 private:
-    uint32_t fSizeInBytes;
-    bool     fDynamic;
+    typedef GrGeometryBuffer INHERITED;
 };
 
 #endif
diff --git a/gpu/include/GrVertexBufferAllocPool.h b/gpu/include/GrVertexBufferAllocPool.h
deleted file mode 100644
index 6a781aa..0000000
--- a/gpu/include/GrVertexBufferAllocPool.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
-    Copyright 2010 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- */
-
-
-#ifndef GrVertexBufferAllocPool_DEFINED
-#define GrVertexBufferAllocPool_DEFINED
-
-#include "GrNoncopyable.h"
-#include "GrTDArray.h"
-#include "GrTArray.h"
-
-class GrVertexBuffer;
-class GrGpu;
-
-/**
- * A pool of vertices in vertex buffers tied to a GrGpu.
- *
- * The pool has an alloc() function that returns a pointer into a locked
- * vertex buffer. A client can release() if it has over-allocated.
- *
- * At creation time a minimum VB size can be specified. Additionally,
- * a number of vertex buffers to preallocate can be specified. These will
- * be allocated at the min size and kept until the pool is destroyed.
- */
-class GrVertexBufferAllocPool : GrNoncopyable {
-public:
-    /**
-     * Constructor
-     *
-     * @param gpu               The GrGpu used to create the vertex buffers.
-     * @param bufferSize        The size of created VBs (unless an alloc request
-     *                          exceeds this size in which case a larger VB is
-     *                          created). This value is clamped to some
-     *                          reasonable minimum.
-     * @param preallocBufferCnt The pool will allocate this number of VBs at
-     *                          bufferSize and keep them until it is destroyed.
-     */
-     GrVertexBufferAllocPool(GrGpu* gpu,
-                             size_t   bufferSize = 0,
-                             int preallocBufferCnt = 0);
-    ~GrVertexBufferAllocPool();
-
-    /**
-     * Ensures all VBs are unlocked. Call before using to draw.
-     */
-    void unlock();
-
-    /**
-     *  Frees all vertex data that has been allocated with alloc().
-     */
-    void reset();
-
-    /**
-     * Returns a block of memory bytes size big. The vertex buffer
-     * containing the memory is returned in buffer.
-     *
-     * @param layout       specifies type of vertices to allocate space for
-     * @param vertexCount  number of vertices to allocate space for
-     * @param buffer       returns the vertex buffer that will hold the
-     *                     vertices.
-     * @param startVertex  returns the offset into buffer of the first vertex.
-     *                     In units of the size of a vertex using layout param.
-     * @return pointer to first vertex.
-     */
-    void* alloc(GrVertexLayout layout,
-                uint32_t vertexCount,
-                GrVertexBuffer** buffer,
-                uint32_t* startVertex);
-
-    /**
-     * Gets the number of vertices that can be allocated without changing VBs.
-     * This means either the last VB returned by alloc() if the last alloc did
-     * not exhaust it. If that VB was exhausted by the last alloc or alloc hasn't
-     * been called since reset() then it will be the number of vertices that
-     * would fit in an available preallocated VB. If no preallocated VB
-     * is available then it returns 0 since the next alloc would force a new
-     * VB to be created.
-     */
-    int currentBufferVertices(GrVertexLayout layout) const;
-
-    /**
-     * Gets the number of preallocated buffers that are yet to be used.
-     */
-    int preallocatedBuffersRemaining() const;
-
-    /**
-     * Gets the number of vertices that can fit in a  preallocated vertex buffer.
-     * Zero if no preallocated buffers.
-     */
-    int preallocatedBufferVertices(GrVertexLayout layout) const;
-
-    /**
-     * gets the number of preallocated vertex buffers
-     */
-    int preallocatedBufferCount() const;
-
-
-    /**
-     * Releases the most recently allocated bytes back to the pool.
-     */
-    void release(size_t bytes);
-
-    /**
-     * Gets the GrGpu that this pool is associated with.
-     */
-    GrGpu* getGpu() { return fGpu; }
-
-
-private:
-    struct BufferBlock {
-        size_t              fBytesFree;
-        GrVertexBuffer*     fVertexBuffer;
-    };
-
-    bool createBlock(size_t size);
-    void destroyBlock();
-
-    GrTArray<BufferBlock>       fBlocks;
-    GrTDArray<GrVertexBuffer*>  fPreallocBuffers;
-    int                         fPreallocBuffersInUse;
-    int                         fFirstPreallocBuffer;
-
-    size_t              fMinBlockSize;
-    GrGpu*              fGpu;
-    void*               fBufferPtr;
-};
-
-#endif