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
diff --git a/gpu/src/GrBufferAllocPool.cpp b/gpu/src/GrBufferAllocPool.cpp
new file mode 100644
index 0000000..35f0c5e
--- /dev/null
+++ b/gpu/src/GrBufferAllocPool.cpp
@@ -0,0 +1,430 @@
+/*
+ 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.
+ */
+
+#include "GrBufferAllocPool.h"
+#include "GrTypes.h"
+#include "GrVertexBuffer.h"
+#include "GrIndexBuffer.h"
+#include "GrGpu.h"
+
+#if GR_DEBUG
+ #define VALIDATE validate
+#else
+ #define VALIDATE()
+#endif
+
+#define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 12)
+
+GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu,
+ BufferType bufferType,
+ bool frequentResetHint,
+ size_t blockSize,
+ int preallocBufferCnt) :
+ fBlocks(GrMax(8, 2*preallocBufferCnt)) {
+ GrAssert(NULL != gpu);
+ fGpu = gpu;
+ fBufferType = bufferType;
+ fFrequentResetHint = frequentResetHint;
+ fGpu->ref();
+ fBufferPtr = NULL;
+ fMinBlockSize = GrMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);
+
+ fPreallocBuffersInUse = 0;
+ fFirstPreallocBuffer = 0;
+ for (int i = 0; i < preallocBufferCnt; ++i) {
+ GrGeometryBuffer* buffer = this->createBuffer(fMinBlockSize);
+ if (NULL != buffer) {
+ *fPreallocBuffers.append() = buffer;
+ buffer->ref();
+ }
+ }
+}
+
+GrBufferAllocPool::~GrBufferAllocPool() {
+ VALIDATE();
+ if (fBlocks.count()) {
+ GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
+ if (buffer->isLocked()) {
+ buffer->unlock();
+ }
+ }
+ fPreallocBuffers.unrefAll();
+ while (!fBlocks.empty()) {
+ destroyBlock();
+ }
+ fGpu->unref();
+}
+
+void GrBufferAllocPool::reset() {
+ VALIDATE();
+ if (fBlocks.count()) {
+ GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
+ if (buffer->isLocked()) {
+ buffer->unlock();
+ }
+ }
+ while (!fBlocks.empty()) {
+ destroyBlock();
+ }
+ if (fPreallocBuffers.count()) {
+ // must set this after above loop.
+ fFirstPreallocBuffer = (fFirstPreallocBuffer + fPreallocBuffersInUse) %
+ fPreallocBuffers.count();
+ }
+ fCpuData.realloc(fGpu->supportsBufferLocking() ? 0 : fMinBlockSize);
+ GrAssert(0 == fPreallocBuffersInUse);
+ VALIDATE();
+}
+
+void GrBufferAllocPool::unlock() {
+ VALIDATE();
+
+ if (NULL != fBufferPtr) {
+ BufferBlock& block = fBlocks.back();
+ if (block.fBuffer->isLocked()) {
+ block.fBuffer->unlock();
+ } else {
+ size_t flushSize = block.fBuffer->size() - block.fBytesFree;
+ flushCpuData(fBlocks.back().fBuffer, flushSize);
+ }
+ fBufferPtr = NULL;
+ }
+ VALIDATE();
+}
+
+#if GR_DEBUG
+void GrBufferAllocPool::validate() const {
+ if (NULL != fBufferPtr) {
+ GrAssert(!fBlocks.empty());
+ if (fBlocks.back().fBuffer->isLocked()) {
+ GrGeometryBuffer* buf = fBlocks.back().fBuffer;
+ GrAssert(buf->lockPtr() == fBufferPtr);
+ } else {
+ GrAssert(fCpuData.get() == fBufferPtr);
+ GrAssert(fCpuData.size() == fBlocks.back().fBuffer->size());
+ }
+ } else {
+ GrAssert(fBlocks.empty() || !fBlocks.back().fBuffer->isLocked());
+ }
+ for (int i = 0; i < fBlocks.count() - 1; ++i) {
+ GrAssert(!fBlocks[i].fBuffer->isLocked());
+ }
+}
+#endif
+
+void* GrBufferAllocPool::makeSpace(size_t size,
+ size_t alignment,
+ const GrGeometryBuffer** buffer,
+ size_t* offset) {
+ VALIDATE();
+
+ GrAssert(NULL != buffer);
+ GrAssert(NULL != offset);
+
+ if (NULL != fBufferPtr) {
+ BufferBlock& back = fBlocks.back();
+ size_t usedBytes = back.fBuffer->size() - back.fBytesFree;
+ size_t pad = GrSizeAlignUpPad(usedBytes,
+ alignment);
+ if ((size + pad) <= back.fBytesFree) {
+ usedBytes += pad;
+ *offset = usedBytes;
+ *buffer = back.fBuffer;
+ back.fBytesFree -= size + pad;
+ return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
+ }
+ }
+
+ if (!createBlock(size)) {
+ return NULL;
+ }
+ VALIDATE();
+ GrAssert(NULL != fBufferPtr);
+
+ *offset = 0;
+ BufferBlock& back = fBlocks.back();
+ *buffer = back.fBuffer;
+ back.fBytesFree -= size;
+ return fBufferPtr;
+}
+
+int GrBufferAllocPool::currentBufferItems(size_t itemSize) const {
+ VALIDATE();
+ if (NULL != fBufferPtr) {
+ const BufferBlock& back = fBlocks.back();
+ size_t usedBytes = back.fBuffer->size() - back.fBytesFree;
+ size_t pad = GrSizeAlignUpPad(usedBytes, itemSize);
+ return (back.fBytesFree - pad) / itemSize;
+ } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
+ return fMinBlockSize / itemSize;
+ }
+ return 0;
+}
+
+int GrBufferAllocPool::preallocatedBuffersRemaining() const {
+ return fPreallocBuffers.count() - fPreallocBuffersInUse;
+}
+
+int GrBufferAllocPool::preallocatedBufferCount() const {
+ return fPreallocBuffers.count();
+}
+
+void GrBufferAllocPool::putBack(size_t bytes) {
+ VALIDATE();
+ if (NULL != fBufferPtr) {
+ BufferBlock& back = fBlocks.back();
+ size_t bytesUsed = back.fBuffer->size() - back.fBytesFree;
+ if (bytes >= bytesUsed) {
+ destroyBlock();
+ bytes -= bytesUsed;
+ } else {
+ back.fBytesFree += bytes;
+ return;
+ }
+ }
+ VALIDATE();
+ GrAssert(NULL == fBufferPtr);
+ // we don't partially roll-back buffers because our VB semantics say locking
+ // a VB discards its previous content.
+ // We could honor it by being sure we use updateSubData and not lock
+ // we will roll-back fully released buffers, though.
+ while (!fBlocks.empty() &&
+ bytes >= fBlocks.back().fBuffer->size()) {
+ bytes -= fBlocks.back().fBuffer->size();
+ destroyBlock();
+ }
+ VALIDATE();
+}
+
+bool GrBufferAllocPool::createBlock(size_t requestSize) {
+
+ size_t size = GrMax(requestSize, fMinBlockSize);
+ GrAssert(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);
+
+ VALIDATE();
+
+ BufferBlock& block = fBlocks.push_back();
+
+ if (size == fMinBlockSize &&
+ fPreallocBuffersInUse < fPreallocBuffers.count()) {
+
+ uint32_t nextBuffer = (fPreallocBuffersInUse + fFirstPreallocBuffer) %
+ fPreallocBuffers.count();
+ block.fBuffer = fPreallocBuffers[nextBuffer];
+ block.fBuffer->ref();
+ ++fPreallocBuffersInUse;
+ } else {
+ block.fBuffer = this->createBuffer(size);
+ if (NULL == block.fBuffer) {
+ fBlocks.pop_back();
+ return false;
+ }
+ }
+
+ block.fBytesFree = size;
+ if (NULL != fBufferPtr) {
+ GrAssert(fBlocks.count() > 1);
+ BufferBlock& prev = fBlocks.fromBack(1);
+ if (prev.fBuffer->isLocked()) {
+ prev.fBuffer->unlock();
+ } else {
+ flushCpuData(prev.fBuffer,
+ prev.fBuffer->size() - prev.fBytesFree);
+ }
+ fBufferPtr = NULL;
+ }
+
+ GrAssert(NULL == fBufferPtr);
+
+ if (fGpu->supportsBufferLocking() &&
+ size > GR_GEOM_BUFFER_LOCK_THRESHOLD &&
+ (!fFrequentResetHint || requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD)) {
+ fBufferPtr = block.fBuffer->lock();
+ }
+
+ if (NULL == fBufferPtr) {
+ fBufferPtr = fCpuData.realloc(size);
+ }
+
+ VALIDATE();
+
+ return true;
+}
+
+void GrBufferAllocPool::destroyBlock() {
+ GrAssert(!fBlocks.empty());
+
+ BufferBlock& block = fBlocks.back();
+ if (fPreallocBuffersInUse > 0) {
+ uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
+ fFirstPreallocBuffer +
+ (fPreallocBuffers.count() - 1)) %
+ fPreallocBuffers.count();
+ if (block.fBuffer == fPreallocBuffers[prevPreallocBuffer]) {
+ --fPreallocBuffersInUse;
+ }
+ }
+ GrAssert(!block.fBuffer->isLocked());
+ block.fBuffer->unref();
+ fBlocks.pop_back();
+ fBufferPtr = NULL;
+}
+
+void GrBufferAllocPool::flushCpuData(GrGeometryBuffer* buffer,
+ size_t flushSize) {
+ GrAssert(NULL != buffer);
+ GrAssert(!buffer->isLocked());
+ GrAssert(fCpuData.get() == fBufferPtr);
+ GrAssert(fCpuData.size() == buffer->size());
+ GrAssert(flushSize <= buffer->size());
+
+ bool updated = false;
+ if (fGpu->supportsBufferLocking() &&
+ flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
+ void* data = buffer->lock();
+ if (NULL != data) {
+ memcpy(data, fBufferPtr, flushSize);
+ buffer->unlock();
+ updated = true;
+ }
+ }
+ buffer->updateData(fBufferPtr, flushSize);
+}
+
+GrGeometryBuffer* GrBufferAllocPool::createBuffer(size_t size) {
+ if (kIndex_BufferType == fBufferType) {
+ return fGpu->createIndexBuffer(size, true);
+ } else {
+ GrAssert(kVertex_BufferType == fBufferType);
+ return fGpu->createVertexBuffer(size, true);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
+ bool frequentResetHint,
+ size_t bufferSize,
+ int preallocBufferCnt)
+: GrBufferAllocPool(gpu,
+ kVertex_BufferType,
+ frequentResetHint,
+ bufferSize,
+ preallocBufferCnt) {
+}
+
+void* GrVertexBufferAllocPool::makeSpace(GrVertexLayout layout,
+ int vertexCount,
+ const GrVertexBuffer** buffer,
+ int* startVertex) {
+
+ GrAssert(vertexCount >= 0);
+ GrAssert(NULL != buffer);
+ GrAssert(NULL != startVertex);
+
+ size_t vSize = GrDrawTarget::VertexSize(layout);
+ size_t offset;
+ const GrGeometryBuffer* geomBuffer;
+ void* ptr = INHERITED::makeSpace(vSize * vertexCount,
+ vSize,
+ &geomBuffer,
+ &offset);
+
+ *buffer = (const GrVertexBuffer*) geomBuffer;
+ GrAssert(0 == offset % vSize);
+ *startVertex = offset / vSize;
+ return ptr;
+}
+
+bool GrVertexBufferAllocPool::appendVertices(GrVertexLayout layout,
+ int vertexCount,
+ const void* vertices,
+ const GrVertexBuffer** buffer,
+ int* startVertex) {
+ void* space = makeSpace(layout, vertexCount, buffer, startVertex);
+ if (NULL != space) {
+ memcpy(space,
+ vertices,
+ GrDrawTarget::VertexSize(layout) * vertexCount);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+int GrVertexBufferAllocPool::preallocatedBufferVertices(GrVertexLayout layout) const {
+ return INHERITED::preallocatedBufferSize() /
+ GrDrawTarget::VertexSize(layout);
+}
+
+int GrVertexBufferAllocPool::currentBufferVertices(GrVertexLayout layout) const {
+ return currentBufferItems(GrDrawTarget::VertexSize(layout));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu,
+ bool frequentResetHint,
+ size_t bufferSize,
+ int preallocBufferCnt)
+: GrBufferAllocPool(gpu,
+ kIndex_BufferType,
+ frequentResetHint,
+ bufferSize,
+ preallocBufferCnt) {
+}
+
+void* GrIndexBufferAllocPool::makeSpace(int indexCount,
+ const GrIndexBuffer** buffer,
+ int* startIndex) {
+
+ GrAssert(indexCount >= 0);
+ GrAssert(NULL != buffer);
+ GrAssert(NULL != startIndex);
+
+ size_t offset;
+ const GrGeometryBuffer* geomBuffer;
+ void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t),
+ sizeof(uint16_t),
+ &geomBuffer,
+ &offset);
+
+ *buffer = (const GrIndexBuffer*) geomBuffer;
+ GrAssert(0 == offset % sizeof(uint16_t));
+ *startIndex = offset / sizeof(uint16_t);
+ return ptr;
+}
+
+bool GrIndexBufferAllocPool::appendIndices(int indexCount,
+ const void* indices,
+ const GrIndexBuffer** buffer,
+ int* startIndex) {
+ void* space = makeSpace(indexCount, buffer, startIndex);
+ if (NULL != space) {
+ memcpy(space, indices, sizeof(uint16_t) * indexCount);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+int GrIndexBufferAllocPool::preallocatedBufferIndices() const {
+ return INHERITED::preallocatedBufferSize() / sizeof(uint16_t);
+}
+
+int GrIndexBufferAllocPool::currentBufferIndices() const {
+ return currentBufferItems(sizeof(uint16_t));
+}
diff --git a/gpu/src/GrBufferAllocPool.h b/gpu/src/GrBufferAllocPool.h
new file mode 100644
index 0000000..80f16ab
--- /dev/null
+++ b/gpu/src/GrBufferAllocPool.h
@@ -0,0 +1,349 @@
+/*
+ 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 GrBufferAllocPool_DEFINED
+#define GrBufferAllocPool_DEFINED
+
+#include "GrNoncopyable.h"
+#include "GrTDArray.h"
+#include "GrTArray.h"
+#include "GrMemory.h"
+
+class GrGeometryBuffer;
+class GrGpu;
+
+/**
+ * A pool of geometry buffers tied to a GrGpu.
+ *
+ * The pool allows a client to make space for geometry and then put back excess
+ * space if it over allocated. When a client is ready to draw from the pool
+ * it calls unlock on the pool ensure buffers are ready for drawing. The pool
+ * can be reset after drawing is completed to recycle space.
+ *
+ * At creation time a minimum per-buffer size can be specified. Additionally,
+ * a number of buffers to preallocate can be specified. These will
+ * be allocated at the min size and kept around until the pool is destroyed.
+ */
+class GrBufferAllocPool : GrNoncopyable {
+protected:
+
+ // We could make the createBuffer a virtual except that we want to use it
+ // in the cons for pre-allocated buffers.
+ enum BufferType {
+ kVertex_BufferType,
+ kIndex_BufferType,
+ };
+
+ /**
+ * Constructor
+ *
+ * @param gpu The GrGpu used to create the buffers.
+ * @param bufferType The type of buffers to create.
+ * @param frequentResetHint A hint that indicates that the pool
+ * should expect frequent unlock() calls
+ * (as opposed to many makeSpace / acquires
+ * between resets).
+ * @param bufferSize The minimum size of created buffers.
+ * This value will be clamped to some
+ * reasonable minimum.
+ * @param preallocBufferCnt The pool will allocate this number of
+ * buffers at bufferSize and keep them until it
+ * is destroyed.
+ */
+ GrBufferAllocPool(GrGpu* gpu,
+ BufferType bufferType,
+ bool frequentResetHint,
+ size_t bufferSize = 0,
+ int preallocBufferCnt = 0);
+
+ virtual ~GrBufferAllocPool();
+
+public:
+ /**
+ * Ensures all buffers are unlocked and have all data written to them.
+ * Call before drawing using buffers from the pool.
+ */
+ void unlock();
+
+ /**
+ * Invalidates all the data in the pool, unrefs non-preallocated buffers.
+ */
+ void reset();
+
+ /**
+ * Gets the number of preallocated buffers that are yet to be used.
+ */
+ int preallocatedBuffersRemaining() const;
+
+ /**
+ * gets the number of preallocated buffers
+ */
+ int preallocatedBufferCount() const;
+
+
+ /**
+ * Frees data from makeSpaces in LIFO order.
+ */
+ void putBack(size_t bytes);
+
+ /**
+ * Gets the GrGpu that this pool is associated with.
+ */
+ GrGpu* getGpu() { return fGpu; }
+
+protected:
+ /**
+ * Gets the size of the preallocated buffers.
+ *
+ * @return the size of preallocated buffers.
+ */
+ size_t preallocatedBufferSize() const {
+ return fPreallocBuffers.count() ? fMinBlockSize : 0;
+ }
+
+ /**
+ * Returns a block of memory to hold data. A buffer designated to hold the
+ * data is given to the caller. The buffer may or may not be locked. The
+ * returned ptr remains valid until any of the following:
+ * *makeSpace is called again.
+ * *unlock is called.
+ * *reset is called.
+ * *this object is destroyed.
+ *
+ * Once unlock on the pool is called the data is guaranteed to be in the
+ * buffer at the offset indicated by offset. Until that time it may be
+ * in temporary storage and/or the buffer may be locked.
+ *
+ * @param size the amount of data to make space for
+ * @param alignment alignment constraint from start of buffer
+ * @param buffer returns the buffer that will hold the data.
+ * @param offset returns the offset into buffer of the data.
+ * @return pointer to where the client should write the data.
+ */
+ void* makeSpace(size_t size,
+ size_t alignment,
+ const GrGeometryBuffer** buffer,
+ size_t* offset);
+
+ /**
+ * Gets the number of items of a size that can be added to the current
+ * buffer without spilling to another buffer. If the pool has been reset, or
+ * the previous makeSpace completely exhausted a buffer then the returned
+ * size will be the size of the next available preallocated buffer, or zero
+ * if no preallocated buffer remains available. It is assumed that items
+ * should be itemSize-aligned from the start of a buffer.
+ *
+ * @return the number of items that would fit in the current buffer.
+ */
+ int currentBufferItems(size_t itemSize) const;
+
+ GrGeometryBuffer* createBuffer(size_t size);
+
+private:
+
+ struct BufferBlock {
+ size_t fBytesFree;
+ GrGeometryBuffer* fBuffer;
+ };
+
+ bool createBlock(size_t requestSize);
+ void destroyBlock();
+ void flushCpuData(GrGeometryBuffer* buffer, size_t flushSize);
+#if GR_DEBUG
+ void validate() const;
+#endif
+
+ GrGpu* fGpu;
+ bool fFrequentResetHint;
+ GrTDArray<GrGeometryBuffer*> fPreallocBuffers;
+ size_t fMinBlockSize;
+ BufferType fBufferType;
+
+ GrTArray<BufferBlock> fBlocks;
+ int fPreallocBuffersInUse;
+ int fFirstPreallocBuffer;
+ GrAutoMalloc fCpuData;
+ void* fBufferPtr;
+};
+
+class GrVertexBuffer;
+
+/**
+ * A GrBufferAllocPool of vertex buffers
+ */
+class GrVertexBufferAllocPool : public GrBufferAllocPool {
+public:
+ /**
+ * Constructor
+ *
+ * @param gpu The GrGpu used to create the vertex buffers.
+ * @param frequentResetHint A hint that indicates that the pool
+ * should expect frequent unlock() calls
+ * (as opposed to many makeSpace / acquires
+ * between resets).
+ * @param bufferSize The minimum size of created VBs This value
+ * will be 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,
+ bool frequentResetHint,
+ size_t bufferSize = 0,
+ int preallocBufferCnt = 0);
+
+ /**
+ * Returns a block of memory to hold vertices. A buffer designated to hold
+ * the vertices given to the caller. The buffer may or may not be locked.
+ * The returned ptr remains valid until any of the following:
+ * *makeSpace is called again.
+ * *unlock is called.
+ * *reset is called.
+ * *this object is destroyed.
+ *
+ * Once unlock on the pool is called the vertices are guaranteed to be in
+ * the buffer at the offset indicated by startVertex. Until that time they
+ * may be in temporary storage and/or the buffer may be locked.
+ *
+ * @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 from layout param.
+ * @return pointer to first vertex.
+ */
+ void* makeSpace(GrVertexLayout layout,
+ int vertexCount,
+ const GrVertexBuffer** buffer,
+ int* startVertex);
+
+ /**
+ * Shortcut to make space and then write verts into the made space.
+ */
+ bool appendVertices(GrVertexLayout layout,
+ int vertexCount,
+ const void* vertices,
+ const GrVertexBuffer** buffer,
+ int* startVertex);
+
+ /**
+ * Gets the number of vertices that can be added to the current VB without
+ * spilling to another VB. If the pool has been reset, or the previous
+ * makeSpace completely exhausted a VB then the returned number of vertices
+ * would fit in the next available preallocated buffer. If any makeSpace
+ * would force a new VB to be created the return value will be zero.
+ *
+ * @param the format of vertices to compute space for.
+ * @return the number of vertices that would fit in the current buffer.
+ */
+ int currentBufferVertices(GrVertexLayout layout) const;
+
+ /**
+ * Gets the number of vertices that can fit in a preallocated vertex buffer.
+ * Zero if no preallocated buffers.
+ *
+ * @param the format of vertices to compute space for.
+ *
+ * @return number of vertices that fit in one of the preallocated vertex
+ * buffers.
+ */
+ int preallocatedBufferVertices(GrVertexLayout layout) const;
+
+private:
+ typedef GrBufferAllocPool INHERITED;
+};
+
+class GrIndexBuffer;
+
+/**
+ * A GrBufferAllocPool of index buffers
+ */
+class GrIndexBufferAllocPool : public GrBufferAllocPool {
+public:
+ /**
+ * Constructor
+ *
+ * @param gpu The GrGpu used to create the index buffers.
+ * @param frequentResetHint A hint that indicates that the pool
+ * should expect frequent unlock() calls
+ * (as opposed to many makeSpace / acquires
+ * between resets).
+ * @param bufferSize The minimum size of created IBs This value
+ * will be clamped to some reasonable minimum.
+ * @param preallocBufferCnt The pool will allocate this number of VBs at
+ * bufferSize and keep them until it is
+ * destroyed.
+ */
+ GrIndexBufferAllocPool(GrGpu* gpu,
+ bool frequentResetHint,
+ size_t bufferSize = 0,
+ int preallocBufferCnt = 0);
+
+ /**
+ * Returns a block of memory to hold indices. A buffer designated to hold
+ * the indices is given to the caller. The buffer may or may not be locked.
+ * The returned ptr remains valid until any of the following:
+ * *makeSpace is called again.
+ * *unlock is called.
+ * *reset is called.
+ * *this object is destroyed.
+ *
+ * Once unlock on the pool is called the indices are guaranteed to be in the
+ * buffer at the offset indicated by startIndex. Until that time they may be
+ * in temporary storage and/or the buffer may be locked.
+ *
+ * @param indexCount number of indices to allocate space for
+ * @param buffer returns the index buffer that will hold the indices.
+ * @param startIndex returns the offset into buffer of the first index.
+ * @return pointer to first index.
+ */
+ void* makeSpace(int indexCount,
+ const GrIndexBuffer** buffer,
+ int* startIndex);
+
+ /**
+ * Shortcut to make space and then write indices into the made space.
+ */
+ bool appendIndices(int indexCount,
+ const void* indices,
+ const GrIndexBuffer** buffer,
+ int* startIndex);
+
+ /**
+ * Gets the number of indices that can be added to the current IB without
+ * spilling to another IB. If the pool has been reset, or the previous
+ * makeSpace completely exhausted a IB then the returned number of indices
+ * would fit in the next available preallocated buffer. If any makeSpace
+ * would force a new IB to be created the return value will be zero.
+ */
+ int currentBufferIndices() const;
+
+ /**
+ * Gets the number of indices that can fit in a preallocated index buffer.
+ * Zero if no preallocated buffers.
+ *
+ * @return number of indices that fit in one of the preallocated index
+ * buffers.
+ */
+ int preallocatedBufferIndices() const;
+
+private:
+ typedef GrBufferAllocPool INHERITED;
+};
+
+#endif
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index e224891..d14777e 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -14,7 +14,6 @@
limitations under the License.
*/
-
#include "GrContext.h"
#include "GrTypes.h"
#include "GrTextureCache.h"
@@ -23,23 +22,16 @@
#include "GrPathIter.h"
#include "GrClipIterator.h"
#include "GrIndexBuffer.h"
+#include "GrInOrderDrawBuffer.h"
+#include "GrBufferAllocPool.h"
#define DEFER_TEXT_RENDERING 1
static const size_t MAX_TEXTURE_CACHE_COUNT = 128;
static const size_t MAX_TEXTURE_CACHE_BYTES = 8 * 1024 * 1024;
-#if DEFER_TEXT_RENDERING
- static const uint32_t POOL_VB_SIZE = 2048 *
- GrDrawTarget::VertexSize(
- GrDrawTarget::kTextFormat_VertexLayoutBit |
- GrDrawTarget::StageTexCoordVertexLayoutBit(0,0));
- static const uint32_t NUM_POOL_VBS = 8;
-#else
- static const uint32_t POOL_VB_SIZE = 0;
- static const uint32_t NUM_POOL_VBS = 0;
-
-#endif
+static const uint32_t TEXT_POOL_VB_SIZE = 1 << 18; // enough to draw 4K untextured glyphs
+static const uint32_t NUM_TEXT_POOL_VBS = 4;
GrContext* GrContext::Create(GrGpu::Engine engine,
GrGpu::Platform3DContext context3D) {
@@ -60,6 +52,9 @@
fGpu->unref();
delete fTextureCache;
delete fFontCache;
+ delete fTextDrawBuffer;
+ delete fTextVBAllocPool;
+ delete fTextIBAllocPool;
}
void GrContext::abandonAllTextures() {
@@ -487,7 +482,7 @@
const uint16_t indices[],
int indexCount) {
GrVertexLayout layout = 0;
- bool interLeave = false;
+ int vertexSize = sizeof(GrPoint);
GrDrawTarget::AutoReleaseGeometry geo;
@@ -498,18 +493,16 @@
layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
} else {
layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
- interLeave = true;
+ vertexSize += sizeof(GrPoint);
}
}
if (NULL != colors) {
layout |= GrDrawTarget::kColor_VertexLayoutBit;
+ vertexSize += sizeof(GrColor);
}
- static const GrVertexLayout interleaveMask =
- (GrDrawTarget::StageTexCoordVertexLayoutBit(0,0) |
- GrDrawTarget::kColor_VertexLayoutBit);
- if (interleaveMask & layout) {
+ if (sizeof(GrPoint) != vertexSize) {
if (!geo.set(fGpu, layout, vertexCount, 0)) {
GrPrintf("Failed to get space for vertices!");
return;
@@ -533,11 +526,11 @@
curVertex = (void*)((intptr_t)curVertex + vsize);
}
} else {
- fGpu->setVertexSourceToArray(positions, layout);
+ fGpu->setVertexSourceToArray(layout, positions, vertexCount);
}
if (NULL != indices) {
- fGpu->setIndexSourceToArray(indices);
+ fGpu->setIndexSourceToArray(indices, indexCount);
fGpu->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
} else {
fGpu->drawNonIndexed(primitiveType, 0, vertexCount);
@@ -816,7 +809,7 @@
}
case GrPathIter::kCubic_Command: {
generate_cubic_points(pts[0], pts[1], pts[2], pts[3],
- tolSqd, &vert,
+ tolSqd, &vert,
cubic_point_count(pts, tol));
break;
}
@@ -892,8 +885,10 @@
}
void GrContext::flushText() {
- fTextDrawBuffer.playback(fGpu);
- fTextDrawBuffer.reset();
+ if (NULL != fTextDrawBuffer) {
+ fTextDrawBuffer->playback(fGpu);
+ fTextDrawBuffer->reset();
+ }
}
bool GrContext::readPixels(int left, int top, int width, int height,
@@ -1026,16 +1021,28 @@
fGpu->printStats();
}
-GrContext::GrContext(GrGpu* gpu) :
- fVBAllocPool(gpu,
- gpu->supportsBufferLocking() ? POOL_VB_SIZE : 0,
- gpu->supportsBufferLocking() ? NUM_POOL_VBS : 0),
- fTextDrawBuffer(gpu->supportsBufferLocking() ? &fVBAllocPool : NULL) {
+GrContext::GrContext(GrGpu* gpu) {
fGpu = gpu;
fGpu->ref();
fTextureCache = new GrTextureCache(MAX_TEXTURE_CACHE_COUNT,
MAX_TEXTURE_CACHE_BYTES);
fFontCache = new GrFontCache(fGpu);
+
+#if DEFER_TEXT_RENDERING
+ fTextVBAllocPool = new GrVertexBufferAllocPool(gpu,
+ false,
+ TEXT_POOL_VB_SIZE,
+ NUM_TEXT_POOL_VBS);
+ fTextIBAllocPool = new GrIndexBufferAllocPool(gpu, false, 0, 0);
+
+ fTextDrawBuffer = new GrInOrderDrawBuffer(fTextVBAllocPool,
+ fTextIBAllocPool);
+#else
+ fTextDrawBuffer = NULL;
+ fTextVBAllocPool = NULL;
+ fTextIBAllocPool = NULL;
+#endif
+
}
bool GrContext::finalizeTextureKey(GrTextureKey* key,
@@ -1063,8 +1070,8 @@
GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
GrDrawTarget* target;
#if DEFER_TEXT_RENDERING
- fTextDrawBuffer.initializeDrawStateAndClip(*fGpu);
- target = &fTextDrawBuffer;
+ fTextDrawBuffer->initializeDrawStateAndClip(*fGpu);
+ target = fTextDrawBuffer;
#else
target = fGpu;
#endif
diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index 0f31e9a..5cfc6f4 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -458,20 +458,22 @@
fReservedGeometry.fLocked = false;
}
-void GrDrawTarget::setVertexSourceToArray(const void* array,
- GrVertexLayout vertexLayout) {
- fGeometrySrc.fVertexSrc = kArray_GeometrySrcType;
- fGeometrySrc.fVertexArray = array;
+void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
+ const void* vertexArray,
+ int vertexCount) {
+ fGeometrySrc.fVertexSrc = kArray_GeometrySrcType;
fGeometrySrc.fVertexLayout = vertexLayout;
+ setVertexSourceToArrayHelper(vertexArray, vertexCount);
}
-void GrDrawTarget::setIndexSourceToArray(const void* array) {
- fGeometrySrc.fIndexSrc = kArray_GeometrySrcType;
- fGeometrySrc.fIndexArray = array;
+void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
+ int indexCount) {
+ fGeometrySrc.fIndexSrc = kArray_GeometrySrcType;
+ setIndexSourceToArrayHelper(indexArray, indexCount);
}
-void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer,
- GrVertexLayout vertexLayout) {
+void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
+ const GrVertexBuffer* buffer) {
fGeometrySrc.fVertexSrc = kBuffer_GeometrySrcType;
fGeometrySrc.fVertexBuffer = buffer;
fGeometrySrc.fVertexLayout = vertexLayout;
diff --git a/gpu/src/GrGLIndexBuffer.cpp b/gpu/src/GrGLIndexBuffer.cpp
index 82cffaa..2dc4154 100644
--- a/gpu/src/GrGLIndexBuffer.cpp
+++ b/gpu/src/GrGLIndexBuffer.cpp
@@ -18,18 +18,14 @@
#include "GrGLIndexBuffer.h"
#include "GrGpuGL.h"
-GrGLIndexBuffer::GrGLIndexBuffer(GLuint id, GrGpuGL* gl, uint32_t sizeInBytes,
- bool dynamic) :
+GrGLIndexBuffer::GrGLIndexBuffer(GLuint id, GrGpuGL* gl, size_t sizeInBytes,
+ bool dynamic) :
INHERITED(sizeInBytes, dynamic),
fGL(gl),
fBufferID(id),
fLockPtr(NULL) {
}
-GLuint GrGLIndexBuffer::bufferID() const {
- return fBufferID;
-}
-
GrGLIndexBuffer::~GrGLIndexBuffer() {
// make sure we've not been abandoned
if (fBufferID) {
@@ -38,8 +34,17 @@
}
}
+void GrGLIndexBuffer::bind() const {
+ GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, fBufferID));
+ fGL->notifyIndexBufferBind(this);
+}
+
+GLuint GrGLIndexBuffer::bufferID() const {
+ return fBufferID;
+}
+
void GrGLIndexBuffer::abandon() {
- fBufferID = 0;
+ fBufferID = 0;
fGL = NULL;
fLockPtr = NULL;
}
@@ -48,12 +53,9 @@
GrAssert(fBufferID);
GrAssert(!isLocked());
if (fGL->supportsBufferLocking()) {
- GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, fBufferID));
- fGL->notifyIndexBufferBind(this);
- // call bufferData with null ptr to allow driver to perform renaming
- // If this call is removed revisit updateData to be sure it doesn't
- // leave buffer undersized (as it currently does).
- GR_GL(BufferData(GL_ELEMENT_ARRAY_BUFFER, size(), NULL,
+ bind();
+ // Let driver know it can discard the old data
+ GR_GL(BufferData(GL_ELEMENT_ARRAY_BUFFER, size(), NULL,
dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
fLockPtr = GR_GLEXT(fGL->extensions(),
MapBuffer(GL_ELEMENT_ARRAY_BUFFER, GR_WRITE_ONLY));
@@ -63,27 +65,27 @@
return NULL;
}
+void* GrGLIndexBuffer::lockPtr() const {
+ return fLockPtr;
+}
+
void GrGLIndexBuffer::unlock() {
GrAssert(fBufferID);
GrAssert(isLocked());
+ GrAssert(fGL->supportsBufferLocking());
- if (fGL->supportsBufferLocking()) {
- GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, fBufferID));
- fGL->notifyIndexBufferBind(this);
- GR_GLEXT(fGL->extensions(),
- UnmapBuffer(GL_ELEMENT_ARRAY_BUFFER));
- fLockPtr = NULL;
- }
+ bind();
+ GR_GLEXT(fGL->extensions(), UnmapBuffer(GL_ELEMENT_ARRAY_BUFFER));
+ fLockPtr = NULL;
}
bool GrGLIndexBuffer::isLocked() const {
GrAssert(fBufferID);
#if GR_DEBUG
if (fGL->supportsBufferLocking()) {
+ bind();
GLint mapped;
- GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, fBufferID));
- fGL->notifyIndexBufferBind(this);
- GR_GL(GetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER,
+ GR_GL(GetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER,
GR_BUFFER_MAPPED, &mapped));
GrAssert(!!mapped == !!fLockPtr);
}
@@ -91,16 +93,33 @@
return NULL != fLockPtr;
}
-bool GrGLIndexBuffer::updateData(const void* src, uint32_t srcSizeInBytes) {
+bool GrGLIndexBuffer::updateData(const void* src, size_t srcSizeInBytes) {
GrAssert(fBufferID);
GrAssert(!isLocked());
if (srcSizeInBytes > size()) {
return false;
}
- GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, fBufferID));
- fGL->notifyIndexBufferBind(this);
- GR_GL(BufferData(GL_ELEMENT_ARRAY_BUFFER, srcSizeInBytes, src,
- dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
+ bind();
+ GLenum usage = dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
+ if (size() == srcSizeInBytes) {
+ GR_GL(BufferData(GL_ELEMENT_ARRAY_BUFFER, srcSizeInBytes, src, usage));
+ } else {
+ GR_GL(BufferData(GL_ELEMENT_ARRAY_BUFFER, size(), NULL, usage));
+ GR_GL(BufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, srcSizeInBytes, src));
+ }
+ return true;
+}
+
+bool GrGLIndexBuffer::updateSubData(const void* src,
+ size_t srcSizeInBytes,
+ size_t offset) {
+ GrAssert(fBufferID);
+ GrAssert(!isLocked());
+ if (srcSizeInBytes + offset > size()) {
+ return false;
+ }
+ bind();
+ GR_GL(BufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, srcSizeInBytes, src));
return true;
}
diff --git a/gpu/src/GrGLVertexBuffer.cpp b/gpu/src/GrGLVertexBuffer.cpp
index b4ddc24..ec48936 100644
--- a/gpu/src/GrGLVertexBuffer.cpp
+++ b/gpu/src/GrGLVertexBuffer.cpp
@@ -18,8 +18,8 @@
#include "GrGLVertexBuffer.h"
#include "GrGpuGL.h"
-GrGLVertexBuffer::GrGLVertexBuffer(GLuint id, GrGpuGL* gl, uint32_t sizeInBytes,
- bool dynamic) :
+GrGLVertexBuffer::GrGLVertexBuffer(GLuint id, GrGpuGL* gl, size_t sizeInBytes,
+ bool dynamic) :
INHERITED(sizeInBytes, dynamic),
fGL(gl),
fBufferID(id),
@@ -34,11 +34,16 @@
}
}
+void GrGLVertexBuffer::bind() const {
+ GR_GL(BindBuffer(GL_ARRAY_BUFFER, fBufferID));
+ fGL->notifyVertexBufferBind(this);
+}
+
GLuint GrGLVertexBuffer::bufferID() const {
return fBufferID;
}
-void GrGLVertexBuffer::abandon() {
+void GrGLVertexBuffer::abandon() {
fBufferID = 0;
fGL = NULL;
fLockPtr = NULL;
@@ -48,30 +53,29 @@
GrAssert(fBufferID);
GrAssert(!isLocked());
if (fGL->supportsBufferLocking()) {
- GR_GL(BindBuffer(GL_ARRAY_BUFFER, fBufferID));
- fGL->notifyVertexBufferBind(this);
- // call bufferData with null ptr to allow driver to perform renaming
- // If this call is removed revisit updateData to be sure it doesn't
- // leave buffer undersized (as it currently does).
- GR_GL(BufferData(GL_ARRAY_BUFFER, size(), NULL,
+ bind();
+ // Let driver know it can discard the old data
+ GR_GL(BufferData(GL_ARRAY_BUFFER, size(), NULL,
dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
fLockPtr = GR_GLEXT(fGL->extensions(),
- MapBuffer(GL_ARRAY_BUFFER, GR_WRITE_ONLY));
+ MapBuffer(GL_ARRAY_BUFFER, GR_WRITE_ONLY));
return fLockPtr;
}
return NULL;
}
+void* GrGLVertexBuffer::lockPtr() const {
+ return fLockPtr;
+}
+
void GrGLVertexBuffer::unlock() {
GrAssert(fBufferID);
GrAssert(isLocked());
- if (fGL->supportsBufferLocking()) {
- GR_GL(BindBuffer(GL_ARRAY_BUFFER, fBufferID));
- fGL->notifyVertexBufferBind(this);
- GR_GLEXT(fGL->extensions(),
- UnmapBuffer(GL_ARRAY_BUFFER));
- fLockPtr = NULL;
- }
+ GrAssert(fGL->supportsBufferLocking());
+
+ bind();
+ GR_GLEXT(fGL->extensions(), UnmapBuffer(GL_ARRAY_BUFFER));
+ fLockPtr = NULL;
}
bool GrGLVertexBuffer::isLocked() const {
@@ -79,8 +83,7 @@
#if GR_DEBUG
if (fGL->supportsBufferLocking()) {
GLint mapped;
- GR_GL(BindBuffer(GL_ARRAY_BUFFER, fBufferID));
- fGL->notifyVertexBufferBind(this);
+ bind();
GR_GL(GetBufferParameteriv(GL_ARRAY_BUFFER, GR_BUFFER_MAPPED, &mapped));
GrAssert(!!mapped == !!fLockPtr);
}
@@ -88,16 +91,33 @@
return NULL != fLockPtr;
}
-bool GrGLVertexBuffer::updateData(const void* src, uint32_t srcSizeInBytes) {
+bool GrGLVertexBuffer::updateData(const void* src, size_t srcSizeInBytes) {
GrAssert(fBufferID);
GrAssert(!isLocked());
if (srcSizeInBytes > size()) {
return false;
}
- GR_GL(BindBuffer(GL_ARRAY_BUFFER, fBufferID));
- fGL->notifyVertexBufferBind(this);
- GR_GL(BufferData(GL_ARRAY_BUFFER, srcSizeInBytes, src,
- dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
+ bind();
+ GLenum usage = dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW;
+ if (size() == srcSizeInBytes) {
+ GR_GL(BufferData(GL_ARRAY_BUFFER, srcSizeInBytes, src, usage));
+ } else {
+ GR_GL(BufferData(GL_ARRAY_BUFFER, size(), NULL, usage));
+ GR_GL(BufferSubData(GL_ARRAY_BUFFER, 0, srcSizeInBytes, src));
+ }
+ return true;
+}
+
+bool GrGLVertexBuffer::updateSubData(const void* src,
+ size_t srcSizeInBytes,
+ size_t offset) {
+ GrAssert(fBufferID);
+ GrAssert(!isLocked());
+ if (srcSizeInBytes + offset > size()) {
+ return false;
+ }
+ bind();
+ GR_GL(BufferSubData(GL_ARRAY_BUFFER, offset, srcSizeInBytes, src));
return true;
}
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index 057a8c9..e406f6f 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -14,7 +14,6 @@
limitations under the License.
*/
-
#include "GrGpu.h"
#include "GrMemory.h"
#include "GrTextStrike.h"
@@ -22,6 +21,10 @@
#include "GrClipIterator.h"
#include "GrIndexBuffer.h"
#include "GrVertexBuffer.h"
+#include "GrBufferAllocPool.h"
+
+// probably makes no sense for this to be less than a page
+static size_t VERTEX_POOL_VB_SIZE = 1 << 12;
///////////////////////////////////////////////////////////////////////////////
@@ -57,6 +60,12 @@
extern void gr_run_unittests();
GrGpu::GrGpu() : f8bitPaletteSupport(false),
+ fCurrPoolVertexBuffer(NULL),
+ fCurrPoolStartVertex(0),
+ fCurrPoolIndexBuffer(NULL),
+ fCurrPoolStartIndex(0),
+ fVertexPool(NULL),
+ fIndexPool(NULL),
fQuadIndexBuffer(NULL),
fUnitSquareVertexBuffer(NULL) {
#if GR_DEBUG
@@ -68,6 +77,8 @@
GrGpu::~GrGpu() {
GrSafeUnref(fQuadIndexBuffer);
GrSafeUnref(fUnitSquareVertexBuffer);
+ delete fVertexPool;
+ delete fIndexPool;
}
void GrGpu::resetContext() {
@@ -124,11 +135,11 @@
///////////////////////////////////////////////////////////////////////////////
-static const int MAX_QUADS = 512; // max possible: (1 << 14) - 1;
+static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1;
GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535);
-static inline void fillIndices(uint16_t* indices, int quadCount) {
+static inline void fill_indices(uint16_t* indices, int quadCount) {
for (int i = 0; i < quadCount; ++i) {
indices[6 * i + 0] = 4 * i + 0;
indices[6 * i + 1] = 4 * i + 1;
@@ -147,11 +158,11 @@
if (NULL != fQuadIndexBuffer) {
uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock();
if (NULL != indices) {
- fillIndices(indices, MAX_QUADS);
+ fill_indices(indices, MAX_QUADS);
fQuadIndexBuffer->unlock();
} else {
indices = (uint16_t*)GrMalloc(SIZE);
- fillIndices(indices, MAX_QUADS);
+ fill_indices(indices, MAX_QUADS);
if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
fQuadIndexBuffer->unref();
fQuadIndexBuffer = NULL;
@@ -222,41 +233,53 @@
AutoStateRestore asr(this);
AutoGeometrySrcRestore agsr(this);
- this->disableState(kClip_StateBit);
- eraseStencilClip();
+
+ // We have to use setVertexSourceToBuffer (and index) in order
+ // to ensure we correctly restore the client's geom sources.
+ // We tack the clip verts onto the vertex pool but we don't
+ // use the various helper functions because of their side effects.
int rectTotal = fClip.countRects();
- static const int PtsPerRect = 4;
- // this may be called while geometry is already reserved by the
- // client. So we use our own vertex array where we avoid malloc
- // if we have 4 or fewer rects.
- GrAutoSTMalloc<PtsPerRect * 4, GrPoint> vertices(PtsPerRect *
- rectTotal);
- this->setVertexSourceToArray(vertices.get(), 0);
+ if (NULL == fVertexPool) {
+ fVertexPool = new GrVertexBufferAllocPool(this,
+ true,
+ VERTEX_POOL_VB_SIZE,
+ 1);
+ }
+ const GrVertexBuffer* vertexBuffer;
+ int vStart;
+ GrPoint* rectVertices =
+ reinterpret_cast<GrPoint*>(fVertexPool->makeSpace(0,
+ rectTotal * 4,
+ &vertexBuffer,
+ &vStart));
+ for (int r = 0; r < rectTotal; ++r) {
+ const GrIRect& rect = fClip.getRects()[r];
+ rectVertices[4 * r].setIRectFan(rect.fLeft, rect.fTop,
+ rect.fRight, rect.fBottom);
+ }
+ fVertexPool->unlock();
+ this->setVertexSourceToBuffer(0, vertexBuffer);
+ this->setIndexSourceToBuffer(quadIndexBuffer());
+ this->setViewMatrix(GrMatrix::I());
+ // don't clip the clip or recurse!
+ this->disableState(kClip_StateBit);
+ this->eraseStencilClip();
+ this->setStencilPass((GrDrawTarget::StencilPass)kSetClip_StencilPass);
int currRect = 0;
while (currRect < rectTotal) {
int rectCount = GrMin(this->maxQuadsInIndexBuffer(),
rectTotal - currRect);
-
- GrPoint* verts = (GrPoint*)vertices +
- (currRect * PtsPerRect);
-
- for (int i = 0; i < rectCount; i++) {
- GrRect r(fClip.getRects()[i + currRect]);
- verts = r.setRectFan(verts);
- }
- this->setIndexSourceToBuffer(quadIndexBuffer());
-
- this->setViewMatrix(GrMatrix::I());
- this->setStencilPass((GrDrawTarget::StencilPass)kSetClip_StencilPass);
- this->drawIndexed(GrGpu::kTriangles_PrimitiveType,
- currRect * PtsPerRect, 0,
- rectCount * PtsPerRect, rectCount * 6);
-
+ this->drawIndexed(kTriangles_PrimitiveType,
+ vStart + currRect * 4,
+ 0,
+ rectCount*4,
+ rectCount*6);
currRect += rectCount;
}
fClipState.fStencilClipTarget = fCurrDrawState.fRenderTarget;
}
+
fClipState.fClipIsDirty = false;
if (!fClipState.fClipInStencil) {
r = &fClip.getBounds();
@@ -274,10 +297,10 @@
///////////////////////////////////////////////////////////////////////////////
void GrGpu::drawIndexed(PrimitiveType type,
- uint32_t startVertex,
- uint32_t startIndex,
- uint32_t vertexCount,
- uint32_t indexCount) {
+ int startVertex,
+ int startIndex,
+ int vertexCount,
+ int indexCount) {
GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
fReservedGeometry.fLocked);
GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
@@ -293,15 +316,17 @@
fStats.fDrawCnt += 1;
#endif
- setupGeometry(startVertex, startIndex, vertexCount, indexCount);
+ int sVertex = startVertex;
+ int sIndex = startIndex;
+ setupGeometry(&sVertex, &sIndex, vertexCount, indexCount);
- drawIndexedHelper(type, startVertex, startIndex,
+ drawIndexedHelper(type, sVertex, sIndex,
vertexCount, indexCount);
}
void GrGpu::drawNonIndexed(PrimitiveType type,
- uint32_t startVertex,
- uint32_t vertexCount) {
+ int startVertex,
+ int vertexCount) {
GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
fReservedGeometry.fLocked);
@@ -313,37 +338,103 @@
fStats.fDrawCnt += 1;
#endif
- setupGeometry(startVertex, 0, vertexCount, 0);
+ int sVertex = startVertex;
+ setupGeometry(&sVertex, NULL, vertexCount, 0);
- drawNonIndexedHelper(type, startVertex, vertexCount);
+ drawNonIndexedHelper(type, sVertex, vertexCount);
+}
+
+void GrGpu::finalizeReservedVertices() {
+ GrAssert(NULL != fVertexPool);
+ fVertexPool->unlock();
+}
+
+void GrGpu::finalizeReservedIndices() {
+ GrAssert(NULL != fIndexPool);
+ fIndexPool->unlock();
+}
+
+void GrGpu::prepareVertexPool() {
+ if (NULL == fVertexPool) {
+ fVertexPool = new GrVertexBufferAllocPool(this, true, VERTEX_POOL_VB_SIZE, 1);
+ } else {
+ fVertexPool->reset();
+ }
+}
+
+void GrGpu::prepareIndexPool() {
+ if (NULL == fVertexPool) {
+ fIndexPool = new GrIndexBufferAllocPool(this, true, 0, 1);
+ } else {
+ fIndexPool->reset();
+ }
}
bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout,
void** vertices,
void** indices) {
- GrAssert((fReservedGeometry.fVertexCount == 0) ||
- (NULL != vertices));
- if (NULL != vertices) {
- *vertices = fVertices.realloc(VertexSize(vertexLayout) *
- fReservedGeometry.fVertexCount);
- if (!*vertices && fReservedGeometry.fVertexCount) {
+ GrAssert(!fReservedGeometry.fLocked);
+ size_t reservedVertexSpace = 0;
+
+ if (fReservedGeometry.fVertexCount) {
+ GrAssert(NULL != vertices);
+
+ prepareVertexPool();
+
+ *vertices = fVertexPool->makeSpace(vertexLayout,
+ fReservedGeometry.fVertexCount,
+ &fCurrPoolVertexBuffer,
+ &fCurrPoolStartVertex);
+ if (NULL == *vertices) {
return false;
}
+ reservedVertexSpace = VertexSize(vertexLayout) *
+ fReservedGeometry.fVertexCount;
}
- GrAssert((fReservedGeometry.fIndexCount == 0) ||
- (NULL != indices));
- if (NULL != indices) {
- *indices = fIndices.realloc(sizeof(uint16_t) *
- fReservedGeometry.fIndexCount);
- if (!*indices && fReservedGeometry.fIndexCount) {
+ if (fReservedGeometry.fIndexCount) {
+ GrAssert(NULL != indices);
+
+ prepareIndexPool();
+
+ *indices = fIndexPool->makeSpace(fReservedGeometry.fIndexCount,
+ &fCurrPoolIndexBuffer,
+ &fCurrPoolStartIndex);
+ if (NULL == *indices) {
+ fVertexPool->putBack(reservedVertexSpace);
+ fCurrPoolVertexBuffer = NULL;
return false;
}
}
return true;
}
-void GrGpu::releaseGeometryHelper() {
- return;
+void GrGpu::releaseGeometryHelper() {}
+
+void GrGpu::setVertexSourceToArrayHelper(const void* vertexArray, int vertexCount) {
+ GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
+ prepareVertexPool();
+#if GR_DEBUG
+ bool success =
+#endif
+ fVertexPool->appendVertices(fGeometrySrc.fVertexLayout,
+ vertexCount,
+ vertexArray,
+ &fCurrPoolVertexBuffer,
+ &fCurrPoolStartVertex);
+ GR_DEBUGASSERT(success);
+}
+
+void GrGpu::setIndexSourceToArrayHelper(const void* indexArray, int indexCount) {
+ GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
+ prepareIndexPool();
+#if GR_DEBUG
+ bool success =
+#endif
+ fIndexPool->appendIndices(indexCount,
+ indexArray,
+ &fCurrPoolIndexBuffer,
+ &fCurrPoolStartIndex);
+ GR_DEBUGASSERT(success);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index 0b5927a..8d00af9 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -87,13 +87,6 @@
GrGpuGL::GrGpuGL() {
-#if GR_GL_NO_CLIENT_SIDE_ARRAYS
- fClientArrayVB = NULL;
- fClientArrayIB = NULL;
- fOversizeVBDrawCnt = 0;
- fOversizeIBDrawCnt = 0;
-#endif
-
if (gPrintStartupSpew) {
GrPrintf("------------------------- create GrGpuGL %p --------------\n",
this);
@@ -229,7 +222,6 @@
GrPrintf("Single Stencil Pass For Winding: %s\n", (fSingleStencilPassForWinding ? "YES" : "NO"));
}
-
#if GR_SUPPORT_GLDESKTOP
fRGBA8Renderbuffer = true;
#else
@@ -251,6 +243,7 @@
#else
fBufferLockSupport = has_gl_extension("GL_OES_mapbuffer");
#endif
+
if (gPrintStartupSpew) {
GrPrintf("Map Buffer: %s\n", (fBufferLockSupport ? "YES" : "NO"));
}
@@ -372,10 +365,6 @@
}
GrGpuGL::~GrGpuGL() {
-#if GR_GL_NO_CLIENT_SIDE_ARRAYS
- GrSafeUnref(fClientArrayVB);
- GrSafeUnref(fClientArrayIB);
-#endif
}
void GrGpuGL::resetContextHelper() {
@@ -430,6 +419,8 @@
fHWDrawState.fReverseFill = false;
fHWDrawState.fStencilPass = kNone_StencilPass;
fHWStencilClip = false;
+ fClipState.fClipIsDirty = true;
+ fClipState.fStencilClipTarget = NULL;
fHWGeometryState.fIndexBuffer = NULL;
fHWGeometryState.fVertexBuffer = NULL;
@@ -445,63 +436,6 @@
resetContextHelper();
}
-#if GR_GL_NO_CLIENT_SIDE_ARRAYS
-void GrGpuGL::putClientVertexDataInBuffer(const void* vertexData, size_t vertexDataSize) {
- static const size_t MIN_VB_SIZE = 1 << 11;
- static const int MAX_OVERSIZE_VB_DRAWS = 100;
-
- if (NULL != vertexData) {
- size_t currMinVBSize = GrMax(MIN_VB_SIZE, vertexDataSize);
- // if we don't have a VB, its too small, or too big, create a new one
- if (NULL == fClientArrayVB ||
- fClientArrayVB->size() < currMinVBSize ||
- (fOversizeVBDrawCnt >= MAX_OVERSIZE_VB_DRAWS &&
- currMinVBSize == MIN_VB_SIZE &&
- fClientArrayVB->size() > MIN_VB_SIZE)) {
-
- if (fHWGeometryState.fVertexBuffer == fClientArrayVB) {
- fHWGeometryState.fVertexBuffer = NULL;
- fHWGeometryState.fArrayPtrsDirty = true;
- }
- GrSafeUnref(fClientArrayVB);
- fClientArrayVB = (GrGLVertexBuffer*)createVertexBuffer(currMinVBSize, true);
- fOversizeVBDrawCnt = 0;
- }
- fClientArrayVB->updateData(vertexData, vertexDataSize);
- if (currMinVBSize == MIN_VB_SIZE && fClientArrayVB->size() > MIN_VB_SIZE) {
- ++fOversizeVBDrawCnt;
- }
- }
-}
-
-void GrGpuGL::putClientIndexDataInBuffer(const void* indexData, size_t indexDataSize) {
- static const size_t MIN_IB_SIZE = 1 << 8;
- static const int MAX_OVERSIZE_IB_DRAWS = 100;
-
- if (NULL != indexData) {
- size_t currMinIBSize = GrMax(MIN_IB_SIZE, indexDataSize);
- // if we don't have a IB, its too small, or too big, create a new one
- if (NULL == fClientArrayIB ||
- fClientArrayIB->size() < currMinIBSize ||
- (fOversizeIBDrawCnt >= MAX_OVERSIZE_IB_DRAWS &&
- currMinIBSize == MIN_IB_SIZE &&
- fClientArrayIB->size() > MIN_IB_SIZE)) {
-
- if (fHWGeometryState.fIndexBuffer == fClientArrayIB) {
- fHWGeometryState.fIndexBuffer = NULL;
- }
- GrSafeUnref(fClientArrayIB);
- fClientArrayIB = (GrGLIndexBuffer*)createIndexBuffer(currMinIBSize, true);
- fOversizeIBDrawCnt = 0;
- }
- fClientArrayIB->updateData(indexData, indexDataSize);
- if (currMinIBSize == MIN_IB_SIZE && fClientArrayIB->size() > MIN_IB_SIZE) {
- ++fOversizeIBDrawCnt;
- }
- }
-}
-#endif
-
GrRenderTarget* GrGpuGL::createPlatformRenderTarget(
intptr_t platformRenderTarget,
int width, int height) {
@@ -1202,19 +1136,12 @@
GLvoid* indices = (GLvoid*)(sizeof(uint16_t) * startIndex);
-#if GR_GL_NO_CLIENT_SIDE_ARRAYS
- if (kBuffer_GeometrySrcType != fGeometrySrc.fIndexSrc) {
- // we accounted for the startIndex when shoving data into a vb
- indices = NULL;
- }
-#else
- if (kReserved_GeometrySrcType == fGeometrySrc.fIndexSrc) {
- indices = (GLvoid*)((intptr_t)indices + (intptr_t)fIndices.get());
- } else if (kArray_GeometrySrcType == fGeometrySrc.fIndexSrc) {
- indices = (GLvoid*)((intptr_t)indices +
- (intptr_t)fGeometrySrc.fIndexArray);
- }
-#endif
+ GrAssert(NULL != fHWGeometryState.fIndexBuffer);
+ GrAssert(NULL != fHWGeometryState.fVertexBuffer);
+
+ // our setupGeometry better have adjusted this to zero since
+ // DrawElements always draws from the begining of the arrays for idx 0.
+ GrAssert(0 == startVertex);
GR_GL(DrawElements(gPrimitiveType2GLMode[type], indexCount,
GL_UNSIGNED_SHORT, indices));
@@ -1225,6 +1152,15 @@
uint32_t vertexCount) {
GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
+ GrAssert(NULL != fHWGeometryState.fVertexBuffer);
+
+ // our setupGeometry better have adjusted this to zero.
+ // DrawElements doesn't take an offset so we always adjus the startVertex.
+ GrAssert(0 == startVertex);
+
+ // pass 0 for parameter first. We have to adjust gl*Pointer() to
+ // account for startVertex in the DrawElements case. So we always
+ // rely on setupGeometry to have accounted for startVertex.
GR_GL(DrawArrays(gPrimitiveType2GLMode[type], 0, vertexCount));
}
@@ -1330,6 +1266,7 @@
if (!fCurrDrawState.fReverseFill) {
funcRef |= pathStencilMask;
}
+
GR_GL(StencilFunc(GL_EQUAL, funcRef, funcMask));
GR_GL(StencilMask(pathStencilMask));
GR_GL(StencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
@@ -1425,6 +1362,7 @@
GLint funcRef = 0;
GLuint funcMask = pathStencilMask;
GLenum funcFunc;
+
if (stencilClip) {
funcRef |= clipStencilMask;
funcMask |= clipStencilMask;
@@ -1774,84 +1712,62 @@
}
}
+void GrGpuGL::setBuffers(bool indexed,
+ int* extraVertexOffset,
+ int* extraIndexOffset) {
-const GLvoid* GrGpuGL::setBuffersAndGetVertexStart(int vertexStride, int startVertex,
- int startIndex, int vertexCount,
- int indexCount) {
- const GLvoid* posPtr = (GLvoid*)(vertexStride * startVertex);
+ GrAssert(NULL != extraVertexOffset);
- if (kBuffer_GeometrySrcType == fGeometrySrc.fVertexSrc) {
- GrAssert(NULL != fGeometrySrc.fVertexBuffer);
- GrAssert(!fGeometrySrc.fVertexBuffer->isLocked());
- if (fHWGeometryState.fVertexBuffer != fGeometrySrc.fVertexBuffer) {
- GrGLVertexBuffer* buf =
- (GrGLVertexBuffer*)fGeometrySrc.fVertexBuffer;
- GR_GL(BindBuffer(GL_ARRAY_BUFFER, buf->bufferID()));
- fHWGeometryState.fArrayPtrsDirty = true;
- fHWGeometryState.fVertexBuffer = fGeometrySrc.fVertexBuffer;
- }
- } else {
- if (kArray_GeometrySrcType == fGeometrySrc.fVertexSrc) {
- posPtr = (void*)((intptr_t)fGeometrySrc.fVertexArray +
- (intptr_t)posPtr);
- } else {
- GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fVertexSrc);
- posPtr = (void*)((intptr_t)fVertices.get() + (intptr_t)posPtr);
- }
- #if GR_GL_NO_CLIENT_SIDE_ARRAYS
- putClientVertexDataInBuffer(posPtr, vertexCount * vertexStride);
- posPtr = NULL;
- if (fHWGeometryState.fVertexBuffer != fClientArrayVB) {
- GR_GL(BindBuffer(GL_ARRAY_BUFFER, fClientArrayVB->bufferID()));
- fHWGeometryState.fArrayPtrsDirty = true;
- fHWGeometryState.fVertexBuffer = fClientArrayVB;
- }
- #else
- if (NULL != fHWGeometryState.fVertexBuffer) {
- GR_GL(BindBuffer(GL_ARRAY_BUFFER, 0));
- fHWGeometryState.fArrayPtrsDirty = true;
- fHWGeometryState.fVertexBuffer = NULL;
- }
- #endif
+ GrGLVertexBuffer* vbuf;
+ switch (fGeometrySrc.fVertexSrc) {
+ case kBuffer_GeometrySrcType:
+ *extraVertexOffset = 0;
+ vbuf = (GrGLVertexBuffer*) fGeometrySrc.fVertexBuffer;
+ break;
+ case kArray_GeometrySrcType:
+ case kReserved_GeometrySrcType:
+ finalizeReservedVertices();
+ *extraVertexOffset = fCurrPoolStartVertex;
+ vbuf = (GrGLVertexBuffer*) fCurrPoolVertexBuffer;
+ break;
+ default:
+ vbuf = NULL; // suppress warning
+ GrCrash("Unknown geometry src type!");
}
- if (0 != indexCount) {
-
- if (kBuffer_GeometrySrcType == fGeometrySrc.fIndexSrc) {
- GrAssert(NULL != fGeometrySrc.fIndexBuffer);
- GrAssert(!fGeometrySrc.fIndexBuffer->isLocked());
- if (fHWGeometryState.fIndexBuffer != fGeometrySrc.fIndexBuffer) {
- GrGLIndexBuffer* buf =
- (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
- GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->bufferID()));
- fHWGeometryState.fIndexBuffer = fGeometrySrc.fIndexBuffer;
- }
- }
- #if GR_GL_NO_CLIENT_SIDE_ARRAYS
- else {
- const uint16_t* indices;
- if (kArray_GeometrySrcType == fGeometrySrc.fIndexSrc) {
- indices = reinterpret_cast<const uint16_t*>(fGeometrySrc.fIndexArray);
- } else {
- GrAssert(kReserved_GeometrySrcType == fGeometrySrc.fIndexSrc);
- indices = reinterpret_cast<const uint16_t*>(fIndices.get());
- }
- // we shove just the referenced part of the index data into the begining
- // of the buffer and drawIndexedHelper ignores startIndex.
- putClientIndexDataInBuffer(indices + startIndex, indexCount * sizeof(uint16_t));
- if (fHWGeometryState.fIndexBuffer != fClientArrayIB) {
- GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, fClientArrayIB->bufferID()));
- fHWGeometryState.fIndexBuffer = fClientArrayIB;
- }
- }
- #else
- else if (NULL != fHWGeometryState.fIndexBuffer) {
- // we rely on drawIndexedHelper to pass to client side
- // ptr to DrawElements
- GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
- fHWGeometryState.fIndexBuffer = NULL;
- }
- #endif
+ GrAssert(NULL != vbuf);
+ GrAssert(!vbuf->isLocked());
+ if (fHWGeometryState.fVertexBuffer != vbuf) {
+ GR_GL(BindBuffer(GL_ARRAY_BUFFER, vbuf->bufferID()));
+ fHWGeometryState.fArrayPtrsDirty = true;
+ fHWGeometryState.fVertexBuffer = vbuf;
}
- return posPtr;
+
+ if (indexed) {
+ GrAssert(NULL != extraIndexOffset);
+
+ GrGLIndexBuffer* ibuf;
+ switch (fGeometrySrc.fIndexSrc) {
+ case kBuffer_GeometrySrcType:
+ *extraIndexOffset = 0;
+ ibuf = (GrGLIndexBuffer*)fGeometrySrc.fIndexBuffer;
+ break;
+ case kArray_GeometrySrcType:
+ case kReserved_GeometrySrcType:
+ finalizeReservedIndices();
+ *extraIndexOffset = fCurrPoolStartIndex;
+ ibuf = (GrGLIndexBuffer*) fCurrPoolIndexBuffer;
+ break;
+ default:
+ ibuf = NULL; // suppress warning
+ GrCrash("Unknown geometry src type!");
+ }
+
+ GrAssert(NULL != ibuf);
+ GrAssert(!ibuf->isLocked());
+ if (fHWGeometryState.fIndexBuffer != ibuf) {
+ GR_GL(BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
+ fHWGeometryState.fIndexBuffer = ibuf;
+ }
+ }
}
diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h
index e46c2ce..d89b8d5 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -61,8 +61,7 @@
protected:
struct {
- const void*
- fPositionPtr;
+ size_t fVertexOffset;
GrVertexLayout fVertexLayout;
const GrVertexBuffer* fVertexBuffer;
const GrIndexBuffer* fIndexBuffer;
@@ -72,28 +71,27 @@
DrState fHWDrawState;
bool fHWStencilClip;
+ // GrGpu overrides
virtual void drawIndexedHelper(PrimitiveType type,
uint32_t startVertex,
uint32_t startIndex,
uint32_t vertexCount,
uint32_t indexCount);
-
virtual void drawNonIndexedHelper(PrimitiveType type,
uint32_t vertexCount,
uint32_t numVertices);
-
virtual void flushScissor(const GrIRect* rect);
-
void eraseStencil(uint32_t value, uint32_t mask);
virtual void eraseStencilClip();
+ // binds texture unit in GL
void setTextureUnit(int unitIdx);
- // binds appropriate vertex and index buffers and returns either the ptr
- // to client memory or offset into a VB of the first vertex
- const GLvoid* setBuffersAndGetVertexStart(int vertexStride, int startVertex,
- int startIndex, int vertexCount,
- int indexCount);
+ // binds appropriate vertex and index buffers, also returns any extra
+ // extra verts or indices to offset by.
+ void setBuffers(bool indexed,
+ int* extraVertexOffset,
+ int* extraIndexOffset);
// flushes state that is common to fixed and programmable GL
// dither
@@ -118,13 +116,6 @@
GrGLExts fExts;
-#if GR_GL_NO_CLIENT_SIDE_ARRAYS
- void putClientVertexDataInBuffer(const void* vertexData,
- size_t vertexDataSize);
- void putClientIndexDataInBuffer(const void* indexData,
- size_t indexDataSize);
-#endif
-
private:
void resetContextHelper();
@@ -174,13 +165,6 @@
int fActiveTextureUnitIdx;
typedef GrGpu INHERITED;
-
-#if GR_GL_NO_CLIENT_SIDE_ARRAYS
- GrGLVertexBuffer* fClientArrayVB;
- GrGLIndexBuffer* fClientArrayIB;
- int fOversizeVBDrawCnt;
- int fOversizeIBDrawCnt;
-#endif
};
bool has_gl_extension(const char* ext);
diff --git a/gpu/src/GrGpuGLFixed.cpp b/gpu/src/GrGpuGLFixed.cpp
index a028cba..76494de 100644
--- a/gpu/src/GrGpuGLFixed.cpp
+++ b/gpu/src/GrGpuGLFixed.cpp
@@ -95,7 +95,7 @@
}
fHWGeometryState.fVertexLayout = 0;
- fHWGeometryState.fPositionPtr = (void*) ~0;
+ fHWGeometryState.fVertexOffset = ~0;
GR_GL(EnableClientState(GL_VERTEX_ARRAY));
GR_GL(DisableClientState(GL_TEXTURE_COORD_ARRAY));
GR_GL(ShadeModel(GL_FLAT));
@@ -246,10 +246,10 @@
return true;
}
-void GrGpuGLFixed::setupGeometry(uint32_t startVertex,
- uint32_t startIndex,
- uint32_t vertexCount,
- uint32_t indexCount) {
+void GrGpuGLFixed::setupGeometry(int* startVertex,
+ int* startIndex,
+ int vertexCount,
+ int indexCount) {
int newColorOffset;
int newTexCoordOffsets[kNumStages];
@@ -263,9 +263,11 @@
oldTexCoordOffsets,
&oldColorOffset);
- const GLvoid* posPtr = setBuffersAndGetVertexStart(newStride, startVertex,
- startIndex, vertexCount,
- indexCount);
+ bool indexed = NULL == startIndex;
+
+ int extraVertexOffset;
+ int extraIndexOffset;
+ setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
GLenum scalarType;
if (fGeometrySrc.fVertexLayout & kTextFormat_VertexLayoutBit) {
@@ -274,32 +276,43 @@
scalarType = GrGLType;
}
- bool baseChange = posPtr != fHWGeometryState.fPositionPtr;
- bool scalarChange =
- (GrGLTextType != GrGLType) &&
- (kTextFormat_VertexLayoutBit &
- (fHWGeometryState.fVertexLayout ^ fGeometrySrc.fVertexLayout));
- bool strideChange = newStride != oldStride;
- bool posChange = baseChange || scalarChange || strideChange;
+ size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
+ *startVertex = 0;
+ if (indexed) {
+ *startIndex += extraIndexOffset;
+ }
- if (posChange || fHWGeometryState.fArrayPtrsDirty) {
- GR_GL(VertexPointer(2, scalarType, newStride, posPtr));
- fHWGeometryState.fPositionPtr = posPtr;
+ // all the Pointers must be set if any of these are true
+ bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
+ vertexOffset != fHWGeometryState.fVertexOffset ||
+ newStride != oldStride;
+
+ // position and tex coord offsets change if above conditions are true
+ // or the type changed based on text vs nontext type coords.
+ bool posAndTexChange = allOffsetsChange ||
+ ((GrGLTextType != GrGLType) &&
+ (kTextFormat_VertexLayoutBit &
+ (fHWGeometryState.fVertexLayout ^
+ fGeometrySrc.fVertexLayout)));
+
+ if (posAndTexChange) {
+ GR_GL(VertexPointer(2, scalarType, newStride, (GLvoid*)vertexOffset));
+ fHWGeometryState.fVertexOffset = vertexOffset;
}
for (int s = 0; s < kNumStages; ++s) {
// need to enable array if tex coord offset is 0
// (using positions as coords)
if (newTexCoordOffsets[s] >= 0) {
- GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffsets[s];
+ GLvoid* texCoordOffset = (GLvoid*)(vertexOffset + newTexCoordOffsets[s]);
if (oldTexCoordOffsets[s] < 0) {
GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
GR_GL(EnableClientState(GL_TEXTURE_COORD_ARRAY));
- GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordPtr));
- } else if (fHWGeometryState.fArrayPtrsDirty || posChange ||
+ GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset));
+ } else if (posAndTexChange ||
newTexCoordOffsets[s] != oldTexCoordOffsets[s]) {
GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
- GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordPtr));
+ GR_GL(TexCoordPointer(2, scalarType, newStride, texCoordOffset));
}
} else if (oldTexCoordOffsets[s] >= 0) {
GR_GL(ClientActiveTexture(GL_TEXTURE0+s));
@@ -308,13 +321,12 @@
}
if (newColorOffset > 0) {
- GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset;
+ GLvoid* colorOffset = (GLvoid*)(vertexOffset + newColorOffset);
if (oldColorOffset <= 0) {
GR_GL(EnableClientState(GL_COLOR_ARRAY));
- GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorPtr));
- } else if (fHWGeometryState.fArrayPtrsDirty || posChange ||
- newColorOffset != oldColorOffset) {
- GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorPtr));
+ GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorOffset));
+ } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
+ GR_GL(ColorPointer(4, GL_UNSIGNED_BYTE, newStride, colorOffset));
}
} else if (oldColorOffset > 0) {
GR_GL(DisableClientState(GL_COLOR_ARRAY));
diff --git a/gpu/src/GrGpuGLFixed.h b/gpu/src/GrGpuGLFixed.h
index 85db830..abb11aa 100644
--- a/gpu/src/GrGpuGLFixed.h
+++ b/gpu/src/GrGpuGLFixed.h
@@ -25,24 +25,24 @@
public:
GrGpuGLFixed();
virtual ~GrGpuGLFixed();
-
+
virtual void resetContext();
protected:
// overrides from GrGpu
virtual bool flushGraphicsState(PrimitiveType type);
- virtual void setupGeometry(uint32_t startVertex,
- uint32_t startIndex,
- uint32_t vertexCount,
- uint32_t indexCount);
+ virtual void setupGeometry(int* startVertex,
+ int* startIndex,
+ int vertexCount,
+ int indexCount);
private:
void resetContextHelper();
// when the texture is GL_RGBA we set the GL_COMBINE texture
// environment rgb operand 0 to be GL_COLOR to modulate each incoming
- // R,G, & B by the texture's R, G, & B. When the texture is alpha-only we
- // set the operand to GL_ALPHA so that the incoming frag's R, G, &B are all
+ // R,G, & B by the texture's R, G, & B. When the texture is alpha-only we
+ // set the operand to GL_ALPHA so that the incoming frag's R, G, &B are all
// modulated by the texture's A.
enum TextureEnvRGBOperands {
kAlpha_TextureEnvRGBOperand,
diff --git a/gpu/src/GrGpuGLShaders.cpp b/gpu/src/GrGpuGLShaders.cpp
index b3bfc9a..cf41b1d 100644
--- a/gpu/src/GrGpuGLShaders.cpp
+++ b/gpu/src/GrGpuGLShaders.cpp
@@ -546,7 +546,7 @@
fTextureOrientation = (GrGLTexture::Orientation)-1; // illegal
fHWGeometryState.fVertexLayout = 0;
- fHWGeometryState.fPositionPtr = (void*) ~0;
+ fHWGeometryState.fVertexOffset = ~0;
GR_GL(DisableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
GR_GL(DisableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
GR_GL(EnableVertexAttribArray(GR_GL_POS_ATTR_LOCATION));
@@ -838,10 +838,10 @@
return true;
}
-void GrGpuGLShaders::setupGeometry(uint32_t startVertex,
- uint32_t startIndex,
- uint32_t vertexCount,
- uint32_t indexCount) {
+void GrGpuGLShaders::setupGeometry(int* startVertex,
+ int* startIndex,
+ int vertexCount,
+ int indexCount) {
int newColorOffset;
int newTexCoordOffsets[kNumStages];
@@ -854,10 +854,11 @@
GLsizei oldStride = VertexSizeAndOffsetsByStage(fHWGeometryState.fVertexLayout,
oldTexCoordOffsets,
&oldColorOffset);
+ bool indexed = NULL == startIndex;
- const GLvoid* posPtr = setBuffersAndGetVertexStart(newStride, startVertex,
- startIndex, vertexCount,
- indexCount);
+ int extraVertexOffset;
+ int extraIndexOffset;
+ setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
GLenum scalarType;
bool texCoordNorm;
@@ -869,49 +870,58 @@
texCoordNorm = false;
}
- bool baseChange = posPtr != fHWGeometryState.fPositionPtr;
- bool scalarChange = (GrGLTextType != GrGLType) &&
- (kTextFormat_VertexLayoutBit &
- (fHWGeometryState.fVertexLayout ^
- fGeometrySrc.fVertexLayout));
- bool strideChange = newStride != oldStride;
- bool posChange = baseChange || scalarChange || strideChange;
+ size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
+ *startVertex = 0;
+ if (indexed) {
+ *startIndex += extraIndexOffset;
+ }
- if (fHWGeometryState.fArrayPtrsDirty || posChange) {
+ // all the Pointers must be set if any of these are true
+ bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
+ vertexOffset != fHWGeometryState.fVertexOffset ||
+ newStride != oldStride;
+
+ // position and tex coord offsets change if above conditions are true
+ // or the type/normalization changed based on text vs nontext type coords.
+ bool posAndTexChange = allOffsetsChange ||
+ (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) &&
+ (kTextFormat_VertexLayoutBit &
+ (fHWGeometryState.fVertexLayout ^
+ fGeometrySrc.fVertexLayout)));
+
+ if (posAndTexChange) {
GR_GL(VertexAttribPointer(GR_GL_POS_ATTR_LOCATION, 2, scalarType,
- false, newStride, posPtr));
- fHWGeometryState.fPositionPtr = posPtr;
+ false, newStride, (GLvoid*)vertexOffset));
+ fHWGeometryState.fVertexOffset = vertexOffset;
}
// this class only supports one stage.
if (newTexCoordOffsets[0] > 0) {
- GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffsets[0];
+ GLvoid* texCoordOffset = (GLvoid*)(vertexOffset + newTexCoordOffsets[0]);
if (oldTexCoordOffsets[0] <= 0) {
GR_GL(EnableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
GR_GL(VertexAttribPointer(GR_GL_TEX_ATTR_LOCATION, 2, scalarType,
- texCoordNorm, newStride, texCoordPtr));
- } else if (fHWGeometryState.fArrayPtrsDirty || posChange ||
- newTexCoordOffsets[0] != oldTexCoordOffsets[0]) {
+ texCoordNorm, newStride, texCoordOffset));
+ } else if (posAndTexChange ||
+ newTexCoordOffsets[0] != oldTexCoordOffsets[0]) {
GR_GL(VertexAttribPointer(GR_GL_TEX_ATTR_LOCATION, 2, scalarType,
- texCoordNorm, newStride, texCoordPtr));
+ texCoordNorm, newStride, texCoordOffset));
}
} else if (oldTexCoordOffsets[0] > 0) {
GR_GL(DisableVertexAttribArray(GR_GL_TEX_ATTR_LOCATION));
}
if (newColorOffset > 0) {
- GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset;
+ GLvoid* colorOffset = (GLvoid*)(vertexOffset + newColorOffset);
if (oldColorOffset <= 0) {
GR_GL(EnableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
GR_GL(VertexAttribPointer(GR_GL_COL_ATTR_LOCATION, 4,
GL_UNSIGNED_BYTE,
- true, newStride, colorPtr));
- }
- if (fHWGeometryState.fArrayPtrsDirty || posChange ||
- newColorOffset != oldColorOffset) {
+ true, newStride, colorOffset));
+ } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
GR_GL(VertexAttribPointer(GR_GL_COL_ATTR_LOCATION, 4,
GL_UNSIGNED_BYTE,
- true, newStride, colorPtr));
+ true, newStride, colorOffset));
}
} else if (oldColorOffset > 0) {
GR_GL(DisableVertexAttribArray(GR_GL_COL_ATTR_LOCATION));
diff --git a/gpu/src/GrGpuGLShaders.h b/gpu/src/GrGpuGLShaders.h
index e5a5665..a048e93 100644
--- a/gpu/src/GrGpuGLShaders.h
+++ b/gpu/src/GrGpuGLShaders.h
@@ -25,7 +25,7 @@
public:
GrGpuGLShaders();
virtual ~GrGpuGLShaders();
-
+
virtual void resetContext();
// type of colors used by a program
@@ -37,27 +37,27 @@
protected:
// overrides from GrGpu
virtual bool flushGraphicsState(PrimitiveType type);
- virtual void setupGeometry(uint32_t startVertex,
- uint32_t startIndex,
- uint32_t vertexCount,
- uint32_t indexCount);
-
+ virtual void setupGeometry(int* startVertex,
+ int* startIndex,
+ int vertexCount,
+ int indexCount);
+
private:
void resetContextHelper();
-
+
// sets the texture matrix uniform for currently bound program
- void flushTexMatrix(GLint location,
+ void flushTexMatrix(GLint location,
GrGLTexture::Orientation orientation);
// sets the MVP matrix uniform for currently bound program
void flushMatrix(GLint location);
-
+
void flushTwoPointRadial(GLint paramsLocation, const GrSamplerState&);
-
+
// reads shader from array and compiles it with GL, returns shader ID or 0 if failed
GLuint loadShader(GLenum type, const char* src);
-
+
struct ProgramData;
- // creates a GL program with two shaders attached.
+ // creates a GL program with two shaders attached.
// Gets the relevant uniform locations.
// Sets the texture sampler if present to texture 0
// Binds the program
@@ -74,17 +74,17 @@
void flushProgram(PrimitiveType type);
enum Programs {
- // use vertex coordinates
+ // use vertex coordinates
kTextureVertCoords_Program = 0,
kTextureVertCoordsProj_Program,
-
+
// use separate tex coords
kTextureTexCoords_Program,
kTextureTexCoordsProj_Program,
// constant color texture, no proj
// verts as a tex coords
- kTextureVertCoordsNoColor_Program,
+ kTextureVertCoordsNoColor_Program,
// constant color texture, no proj
// separate tex coords
@@ -99,12 +99,12 @@
// programs for sweep texture lookup
kSweepTextureVertCoords_Program,
- kSweepTextureTexCoords_Program,
-
+ kSweepTextureTexCoords_Program,
+
// programs for two-point radial lookup
kTwoPointRadialTextureVertCoords_Program,
kTwoPointRadialTextureTexCoords_Program,
-
+
// color only drawing
kNoTexture_Program,
@@ -113,23 +113,23 @@
// Records per-program information
// we can specify the attribute locations so that they are constant
- // across our shaders. But the driver determines the uniform locations
+ // across our shaders. But the driver determines the uniform locations
// at link time. We don't need to remember the sampler uniform location
// because we will bind a texture slot to it and never change it
- // Uniforms are program-local so we can't rely on fHWState to hold the
+ // Uniforms are program-local so we can't rely on fHWState to hold the
// previous uniform state after a program change.
struct ProgramData {
// IDs
GLuint fVShaderID;
GLuint fFShaderID;
GLuint fProgramID;
-
+
// shader uniform locations (-1 if shader doesn't use them)
GLint fMatrixLocation;
GLint fTexMatrixLocation;
GLint fColorLocation;
GLint fTwoPointParamsLocation;
-
+
ColorType fColorType;
// these reflect the current values of uniforms
@@ -142,10 +142,10 @@
GrScalar fRadial2Radius0;
bool fRadial2PosRoot;
};
-
+
ProgramData fPrograms[kProgramCount];
Programs fHWProgram;
-
+
GrGLTexture::Orientation fTextureOrientation;
typedef GrGpuGL INHERITED;
diff --git a/gpu/src/GrGpuGLShaders2.cpp b/gpu/src/GrGpuGLShaders2.cpp
index 81f83c9..d423ee2 100644
--- a/gpu/src/GrGpuGLShaders2.cpp
+++ b/gpu/src/GrGpuGLShaders2.cpp
@@ -983,7 +983,7 @@
// Must initialize all fields or cache will have false negatives!
desc->fVertexLayout = fGeometrySrc.fVertexLayout;
-
+
desc->fOptFlags = 0;
if (kPoints_PrimitiveType != primType) {
desc->fOptFlags |= ProgramDesc::kNotPoints_OptFlagBit;
@@ -1112,7 +1112,7 @@
fTextureOrientation = (GrGLTexture::Orientation)-1; // illegal
fHWGeometryState.fVertexLayout = 0;
- fHWGeometryState.fPositionPtr = (void*) ~0;
+ fHWGeometryState.fVertexOffset = ~0;
GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION));
for (int t = 0; t < kMaxTexCoords; ++t) {
GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t)));
@@ -1315,10 +1315,10 @@
return true;
}
-void GrGpuGLShaders2::setupGeometry(uint32_t startVertex,
- uint32_t startIndex,
- uint32_t vertexCount,
- uint32_t indexCount) {
+void GrGpuGLShaders2::setupGeometry(int* startVertex,
+ int* startIndex,
+ int vertexCount,
+ int indexCount) {
int newColorOffset;
int newTexCoordOffsets[kMaxTexCoords];
@@ -1331,10 +1331,11 @@
GLsizei oldStride = VertexSizeAndOffsetsByIdx(fHWGeometryState.fVertexLayout,
oldTexCoordOffsets,
&oldColorOffset);
+ bool indexed = NULL != startIndex;
- const GLvoid* posPtr = setBuffersAndGetVertexStart(newStride, startVertex,
- startIndex, vertexCount,
- indexCount);
+ int extraVertexOffset;
+ int extraIndexOffset;
+ setBuffers(indexed, &extraVertexOffset, &extraIndexOffset);
GLenum scalarType;
bool texCoordNorm;
@@ -1346,31 +1347,42 @@
texCoordNorm = false;
}
- bool baseChange = posPtr != fHWGeometryState.fPositionPtr;
- bool scalarChange = (GrGLTextType != GrGLType) &&
- (kTextFormat_VertexLayoutBit &
- (fHWGeometryState.fVertexLayout ^
- fGeometrySrc.fVertexLayout));
- bool strideChange = newStride != oldStride;
- bool posChange = baseChange || scalarChange || strideChange;
+ size_t vertexOffset = (*startVertex + extraVertexOffset) * newStride;
+ *startVertex = 0;
+ if (indexed) {
+ *startIndex += extraIndexOffset;
+ }
- if (fHWGeometryState.fArrayPtrsDirty || posChange) {
+ // all the Pointers must be set if any of these are true
+ bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
+ vertexOffset != fHWGeometryState.fVertexOffset ||
+ newStride != oldStride;
+
+ // position and tex coord offsets change if above conditions are true
+ // or the type/normalization changed based on text vs nontext type coords.
+ bool posAndTexChange = allOffsetsChange ||
+ (((GrGLTextType != GrGLType) || GR_GL_TEXT_TEXTURE_NORMALIZED) &&
+ (kTextFormat_VertexLayoutBit &
+ (fHWGeometryState.fVertexLayout ^
+ fGeometrySrc.fVertexLayout)));
+
+ if (posAndTexChange) {
GR_GL(VertexAttribPointer(POS_ATTR_LOCATION, 2, scalarType,
- false, newStride, posPtr));
- fHWGeometryState.fPositionPtr = posPtr;
+ false, newStride, (GLvoid*)vertexOffset));
+ fHWGeometryState.fVertexOffset = vertexOffset;
}
for (int t = 0; t < kMaxTexCoords; ++t) {
if (newTexCoordOffsets[t] > 0) {
- GLvoid* texCoordPtr = (int8_t*)posPtr + newTexCoordOffsets[t];
+ GLvoid* texCoordOffset = (GLvoid*)(vertexOffset + newTexCoordOffsets[t]);
if (oldTexCoordOffsets[t] <= 0) {
GR_GL(EnableVertexAttribArray(TEX_ATTR_LOCATION(t)));
GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType,
- texCoordNorm, newStride, texCoordPtr));
- } else if (fHWGeometryState.fArrayPtrsDirty || posChange ||
- newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
+ texCoordNorm, newStride, texCoordOffset));
+ } else if (posAndTexChange ||
+ newTexCoordOffsets[t] != oldTexCoordOffsets[t]) {
GR_GL(VertexAttribPointer(TEX_ATTR_LOCATION(t), 2, scalarType,
- texCoordNorm, newStride, texCoordPtr));
+ texCoordNorm, newStride, texCoordOffset));
}
} else if (oldTexCoordOffsets[t] > 0) {
GR_GL(DisableVertexAttribArray(TEX_ATTR_LOCATION(t)));
@@ -1378,23 +1390,23 @@
}
if (newColorOffset > 0) {
- GLvoid* colorPtr = (int8_t*)posPtr + newColorOffset;
+ GLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
if (oldColorOffset <= 0) {
GR_GL(EnableVertexAttribArray(COL_ATTR_LOCATION));
GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4,
GL_UNSIGNED_BYTE,
- true, newStride, colorPtr));
- } else if (fHWGeometryState.fArrayPtrsDirty || posChange ||
- newColorOffset != oldColorOffset) {
+ true, newStride, colorOffset));
+ } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
GR_GL(VertexAttribPointer(COL_ATTR_LOCATION, 4,
GL_UNSIGNED_BYTE,
- true, newStride, colorPtr));
+ true, newStride, colorOffset));
}
} else if (oldColorOffset > 0) {
GR_GL(DisableVertexAttribArray(COL_ATTR_LOCATION));
}
fHWGeometryState.fVertexLayout = fGeometrySrc.fVertexLayout;
+ fHWGeometryState.fArrayPtrsDirty = false;
}
#endif
diff --git a/gpu/src/GrGpuGLShaders2.h b/gpu/src/GrGpuGLShaders2.h
index bba63f6..bb710e3 100644
--- a/gpu/src/GrGpuGLShaders2.h
+++ b/gpu/src/GrGpuGLShaders2.h
@@ -31,10 +31,10 @@
protected:
// overrides from GrGpu
virtual bool flushGraphicsState(PrimitiveType type);
- virtual void setupGeometry(uint32_t startVertex,
- uint32_t startIndex,
- uint32_t vertexCount,
- uint32_t indexCount);
+ virtual void setupGeometry(int* startVertex,
+ int* startIndex,
+ int vertexCount,
+ int indexCount);
private:
@@ -42,7 +42,7 @@
// sets the texture matrix uniform for currently bound program
void flushTextureMatrix(int stage);
-
+
// sets the MVP matrix uniform for currently bound program
void flushViewMatrix();
diff --git a/gpu/src/GrInOrderDrawBuffer.cpp b/gpu/src/GrInOrderDrawBuffer.cpp
index 494f227..49b8901 100644
--- a/gpu/src/GrInOrderDrawBuffer.cpp
+++ b/gpu/src/GrInOrderDrawBuffer.cpp
@@ -17,25 +17,27 @@
#include "GrInOrderDrawBuffer.h"
#include "GrTexture.h"
-#include "GrVertexBufferAllocPool.h"
+#include "GrBufferAllocPool.h"
#include "GrGpu.h"
-GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrVertexBufferAllocPool* pool) :
+GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrVertexBufferAllocPool* vertexPool,
+ GrIndexBufferAllocPool* indexPool) :
fDraws(DRAWS_BLOCK_SIZE, fDrawsStorage),
fStates(STATES_BLOCK_SIZE, fStatesStorage),
fClips(CLIPS_BLOCK_SIZE, fClipsStorage),
fClipChanged(true),
- fCPUVertices((NULL == pool) ? 0 : VERTEX_BLOCK_SIZE),
- fBufferVertices(pool),
- fIndices(INDEX_BLOCK_SIZE),
- fCurrReservedVertices(NULL),
- fCurrReservedIndices(NULL),
- fCurrVertexBuffer(NULL),
+ fVertexPool(*vertexPool),
+ fCurrPoolVertexBuffer(NULL),
+ fCurrPoolStartVertex(0),
+ fIndexPool(*indexPool),
+ fCurrPoolIndexBuffer(NULL),
+ fCurrPoolStartIndex(0),
fReservedVertexBytes(0),
fReservedIndexBytes(0),
fUsedReservedVertexBytes(0),
fUsedReservedIndexBytes(0) {
- GrAssert(NULL == pool || pool->getGpu()->supportsBufferLocking());
+ GrAssert(NULL != vertexPool);
+ GrAssert(NULL != indexPool);
}
GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
@@ -47,108 +49,95 @@
this->setClip(target.getClip());
}
-void GrInOrderDrawBuffer::drawIndexed(PrimitiveType type,
- uint32_t startVertex,
- uint32_t startIndex,
- uint32_t vertexCount,
- uint32_t indexCount) {
+void GrInOrderDrawBuffer::drawIndexed(PrimitiveType primitiveType,
+ int startVertex,
+ int startIndex,
+ int vertexCount,
+ int indexCount) {
if (!vertexCount || !indexCount) {
return;
}
Draw& draw = fDraws.push_back();
- draw.fType = type;
+ draw.fPrimitiveType = primitiveType;
draw.fStartVertex = startVertex;
draw.fStartIndex = startIndex;
draw.fVertexCount = vertexCount;
draw.fIndexCount = indexCount;
draw.fClipChanged = grabClip();
- draw.fStateChange = grabState();
+ draw.fStateChanged = grabState();
draw.fVertexLayout = fGeometrySrc.fVertexLayout;
switch (fGeometrySrc.fVertexSrc) {
- case kArray_GeometrySrcType:
- draw.fUseVertexBuffer = false;
- draw.fVertexArray = fGeometrySrc.fVertexArray;
- break;
- case kReserved_GeometrySrcType: {
- draw.fUseVertexBuffer = NULL != fBufferVertices;
- if (draw.fUseVertexBuffer) {
- draw.fVertexBuffer = fCurrVertexBuffer;
- draw.fStartVertex += fCurrStartVertex;
- } else {
- draw.fVertexArray = fCurrReservedVertices;
- }
- size_t vertexBytes = (vertexCount + startVertex) *
- VertexSize(fGeometrySrc.fVertexLayout);
- fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes,
- vertexBytes);
- } break;
case kBuffer_GeometrySrcType:
- draw.fUseVertexBuffer = true;
draw.fVertexBuffer = fGeometrySrc.fVertexBuffer;
break;
+ case kReserved_GeometrySrcType: {
+ size_t vertexBytes = (vertexCount + startVertex) *
+ VertexSize(fGeometrySrc.fVertexLayout);
+ fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes,
+ vertexBytes);
+ } // fallthrough
+ case kArray_GeometrySrcType:
+ draw.fVertexBuffer = fCurrPoolVertexBuffer;
+ draw.fStartVertex += fCurrPoolStartVertex;
+ break;
+ default:
+ GrCrash("unknown geom src type");
}
switch (fGeometrySrc.fIndexSrc) {
- case kArray_GeometrySrcType:
- draw.fUseIndexBuffer = false;
- draw.fIndexArray = fGeometrySrc.fIndexArray;
- break;
- case kReserved_GeometrySrcType: {
- draw.fUseIndexBuffer = false;
- draw.fIndexArray = fCurrReservedIndices;
- size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t);
- fUsedReservedIndexBytes = GrMax(fUsedReservedIndexBytes, indexBytes);
- } break;
case kBuffer_GeometrySrcType:
- draw.fUseIndexBuffer = true;
draw.fIndexBuffer = fGeometrySrc.fIndexBuffer;
break;
+ case kReserved_GeometrySrcType: {
+ size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t);
+ fUsedReservedIndexBytes = GrMax(fUsedReservedIndexBytes, indexBytes);
+ } // fallthrough
+ case kArray_GeometrySrcType:
+ draw.fIndexBuffer = fCurrPoolIndexBuffer;
+ draw.fStartIndex += fCurrPoolStartVertex;
+ break;
+ default:
+ GrCrash("unknown geom src type");
}
}
-void GrInOrderDrawBuffer::drawNonIndexed(PrimitiveType type,
- uint32_t startVertex,
- uint32_t vertexCount) {
+void GrInOrderDrawBuffer::drawNonIndexed(PrimitiveType primitiveType,
+ int startVertex,
+ int vertexCount) {
if (!vertexCount) {
return;
}
Draw& draw = fDraws.push_back();
- draw.fType = type;
+ draw.fPrimitiveType = primitiveType;
draw.fStartVertex = startVertex;
draw.fStartIndex = 0;
draw.fVertexCount = vertexCount;
draw.fIndexCount = 0;
draw.fClipChanged = grabClip();
- draw.fStateChange = grabState();
+ draw.fStateChanged = grabState();
draw.fVertexLayout = fGeometrySrc.fVertexLayout;
switch (fGeometrySrc.fVertexSrc) {
- case kArray_GeometrySrcType:
- draw.fUseVertexBuffer = false;
- draw.fVertexArray = fGeometrySrc.fVertexArray;
- break;
- case kReserved_GeometrySrcType: {
- draw.fUseVertexBuffer = NULL != fBufferVertices;
- if (draw.fUseVertexBuffer) {
- draw.fVertexBuffer = fCurrVertexBuffer;
- draw.fStartVertex += fCurrStartVertex;
- } else {
- draw.fVertexArray = fCurrReservedVertices;
- }
- size_t vertexBytes = (vertexCount + startVertex) *
- VertexSize(fGeometrySrc.fVertexLayout);
- fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes,
- vertexBytes);
- } break;
case kBuffer_GeometrySrcType:
- draw.fUseVertexBuffer = true;
draw.fVertexBuffer = fGeometrySrc.fVertexBuffer;
break;
+ case kReserved_GeometrySrcType: {
+ size_t vertexBytes = (vertexCount + startVertex) *
+ VertexSize(fGeometrySrc.fVertexLayout);
+ fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes,
+ vertexBytes);
+ } // fallthrough
+ case kArray_GeometrySrcType:
+ draw.fVertexBuffer = fCurrPoolVertexBuffer;
+ draw.fStartVertex += fCurrPoolStartVertex;
+ break;
+ default:
+ GrCrash("unknown geom src type");
}
}
@@ -165,12 +154,10 @@
}
fDraws.reset();
fStates.reset();
- if (NULL == fBufferVertices) {
- fCPUVertices.reset();
- } else {
- fBufferVertices->reset();
- }
- fIndices.reset();
+
+ fVertexPool.reset();
+ fIndexPool.reset();
+
fClips.reset();
}
@@ -183,9 +170,8 @@
return;
}
- if (NULL != fBufferVertices) {
- fBufferVertices->unlock();
- }
+ fVertexPool.unlock();
+ fIndexPool.unlock();
GrDrawTarget::AutoStateRestore asr(target);
GrDrawTarget::AutoClipRestore acr(target);
@@ -198,7 +184,7 @@
for (uint32_t i = 0; i < numDraws; ++i) {
const Draw& draw = fDraws[i];
- if (draw.fStateChange) {
+ if (draw.fStateChanged) {
++currState;
target->restoreDrawState(fStates[currState]);
}
@@ -206,52 +192,58 @@
++currClip;
target->setClip(fClips[currClip]);
}
- if (draw.fUseVertexBuffer) {
- target->setVertexSourceToBuffer(draw.fVertexBuffer, draw.fVertexLayout);
- } else {
- target->setVertexSourceToArray(draw.fVertexArray, draw.fVertexLayout);
- }
+ uint32_t vertexReserveCount = 0;
+ uint32_t indexReserveCount = 0;
+
+ target->setVertexSourceToBuffer(draw.fVertexLayout, draw.fVertexBuffer);
+
if (draw.fIndexCount) {
- if (draw.fUseIndexBuffer) {
- target->setIndexSourceToBuffer(draw.fIndexBuffer);
- } else {
- target->setIndexSourceToArray(draw.fIndexArray);
- }
- target->drawIndexed(draw.fType,
+ target->setIndexSourceToBuffer(draw.fIndexBuffer);
+ }
+
+ if (draw.fIndexCount) {
+ target->drawIndexed(draw.fPrimitiveType,
draw.fStartVertex,
draw.fStartIndex,
draw.fVertexCount,
draw.fIndexCount);
} else {
- target->drawNonIndexed(draw.fType,
+ target->drawNonIndexed(draw.fPrimitiveType,
draw.fStartVertex,
draw.fVertexCount);
}
+ if (vertexReserveCount || indexReserveCount) {
+ target->releaseReservedGeometry();
+ }
}
}
bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout,
- int32_t* vertexCount,
- int32_t* indexCount) const {
+ int* vertexCount,
+ int* indexCount) const {
+ // we will recommend a flush if the data could fit in a single
+ // preallocated buffer but none are left and it can't fit
+ // in the current buffer (which may not be prealloced).
bool flush = false;
if (NULL != indexCount) {
- *indexCount = -1;
+ int32_t currIndices = fIndexPool.currentBufferIndices();
+ if (*indexCount > currIndices &&
+ (!fIndexPool.preallocatedBuffersRemaining() &&
+ *indexCount <= fIndexPool.preallocatedBufferIndices())) {
+
+ flush = true;
+ }
+ *indexCount = currIndices;
}
if (NULL != vertexCount) {
- if (NULL != fBufferVertices) {
- // we will recommend a flush if the verts could fit in a single
- // preallocated vertex buffer but none are left and it can't fit
- // in the current VB (which may not be prealloced).
- if (*vertexCount > fBufferVertices->currentBufferVertices(vertexLayout) &&
- (!fBufferVertices->preallocatedBuffersRemaining() &&
- *vertexCount <= fBufferVertices->preallocatedBufferVertices(vertexLayout))) {
+ int32_t currVertices = fVertexPool.currentBufferVertices(vertexLayout);
+ if (*vertexCount > currVertices &&
+ (!fVertexPool.preallocatedBuffersRemaining() &&
+ *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexLayout))) {
- flush = true;
- }
- *vertexCount = fBufferVertices->currentBufferVertices(vertexLayout);
- } else {
- *vertexCount = -1;
+ flush = true;
}
+ *vertexCount = currVertices;
}
return flush;
}
@@ -259,31 +251,34 @@
bool GrInOrderDrawBuffer::acquireGeometryHelper(GrVertexLayout vertexLayout,
void** vertices,
void** indices) {
+ GrAssert(!fReservedGeometry.fLocked);
if (fReservedGeometry.fVertexCount) {
+ GrAssert(NULL != vertices);
+ GrAssert(0 == fReservedVertexBytes);
+ GrAssert(0 == fUsedReservedVertexBytes);
+
fReservedVertexBytes = VertexSize(vertexLayout) *
fReservedGeometry.fVertexCount;
- if (NULL == fBufferVertices) {
- fCurrReservedVertices = fCPUVertices.alloc(fReservedVertexBytes);
- } else {
- fCurrReservedVertices = fBufferVertices->alloc(vertexLayout,
- fReservedGeometry.fVertexCount,
- &fCurrVertexBuffer,
- &fCurrStartVertex);
- }
- if (NULL != vertices) {
- *vertices = fCurrReservedVertices;
- }
- if (NULL == fCurrReservedVertices) {
+ *vertices = fVertexPool.makeSpace(vertexLayout,
+ fReservedGeometry.fVertexCount,
+ &fCurrPoolVertexBuffer,
+ &fCurrPoolStartVertex);
+ if (NULL == *vertices) {
return false;
}
}
if (fReservedGeometry.fIndexCount) {
- fReservedIndexBytes = sizeof(uint16_t) * fReservedGeometry.fIndexCount;
- fCurrReservedIndices = fIndices.alloc(fReservedIndexBytes);
- if (NULL != indices) {
- *indices = fCurrReservedIndices;
- }
- if (NULL == fCurrReservedIndices) {
+ GrAssert(NULL != indices);
+ GrAssert(0 == fReservedIndexBytes);
+ GrAssert(0 == fUsedReservedIndexBytes);
+
+ *indices = fIndexPool.makeSpace(fReservedGeometry.fIndexCount,
+ &fCurrPoolIndexBuffer,
+ &fCurrPoolStartIndex);
+ if (NULL == *indices) {
+ fVertexPool.putBack(fReservedVertexBytes);
+ fReservedVertexBytes = 0;
+ fCurrPoolVertexBuffer = NULL;
return false;
}
}
@@ -295,22 +290,45 @@
GrAssert(fUsedReservedIndexBytes <= fReservedIndexBytes);
size_t vertexSlack = fReservedVertexBytes - fUsedReservedVertexBytes;
- if (NULL == fBufferVertices) {
- fCPUVertices.release(vertexSlack);
- } else {
- fBufferVertices->release(vertexSlack);
- GR_DEBUGCODE(fCurrVertexBuffer = NULL);
- GR_DEBUGCODE(fCurrStartVertex = 0);
- }
+ fVertexPool.putBack(vertexSlack);
- fIndices.release(fReservedIndexBytes - fUsedReservedIndexBytes);
+ size_t indexSlack = fReservedIndexBytes - fUsedReservedIndexBytes;
+ fIndexPool.putBack(indexSlack);
- fCurrReservedVertices = NULL;
- fCurrReservedIndices = NULL;
fReservedVertexBytes = 0;
fReservedIndexBytes = 0;
fUsedReservedVertexBytes = 0;
fUsedReservedIndexBytes = 0;
+ fCurrPoolVertexBuffer = 0;
+ fCurrPoolStartVertex = 0;
+
+}
+
+void GrInOrderDrawBuffer::setVertexSourceToArrayHelper(const void* vertexArray,
+ int vertexCount) {
+ GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
+#if GR_DEBUG
+ bool success =
+#endif
+ fVertexPool.appendVertices(fGeometrySrc.fVertexLayout,
+ vertexCount,
+ vertexArray,
+ &fCurrPoolVertexBuffer,
+ &fCurrPoolStartVertex);
+ GR_DEBUGASSERT(success);
+}
+
+void GrInOrderDrawBuffer::setIndexSourceToArrayHelper(const void* indexArray,
+ int indexCount) {
+ GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
+#if GR_DEBUG
+ bool success =
+#endif
+ fIndexPool.appendIndices(indexCount,
+ indexArray,
+ &fCurrPoolIndexBuffer,
+ &fCurrPoolStartIndex);
+ GR_DEBUGASSERT(success);
}
bool GrInOrderDrawBuffer::grabState() {
diff --git a/gpu/src/GrVertexBufferAllocPool.cpp b/gpu/src/GrVertexBufferAllocPool.cpp
deleted file mode 100644
index 360a086..0000000
--- a/gpu/src/GrVertexBufferAllocPool.cpp
+++ /dev/null
@@ -1,221 +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.
- */
-
-
-#include "GrVertexBufferAllocPool.h"
-#include "GrVertexBuffer.h"
-#include "GrGpu.h"
-
-#define GrVertexBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 10)
-
-GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
- size_t blockSize,
- int preallocBufferCnt) :
- fBlocks(GrMax(8, 2*preallocBufferCnt)) {
- GrAssert(NULL != gpu);
- fGpu = gpu;
- fGpu->ref();
- fBufferPtr = NULL;
- fMinBlockSize = GrMax(GrVertexBufferAllocPool_MIN_BLOCK_SIZE, blockSize);
-
- fPreallocBuffersInUse = 0;
- fFirstPreallocBuffer = 0;
- for (int i = 0; i < preallocBufferCnt; ++i) {
- GrVertexBuffer* buffer = gpu->createVertexBuffer(fMinBlockSize, true);
- if (NULL != buffer) {
- *fPreallocBuffers.append() = buffer;
- buffer->ref();
- }
- }
-}
-
-GrVertexBufferAllocPool::~GrVertexBufferAllocPool() {
- fPreallocBuffers.unrefAll();
- while (!fBlocks.empty()) {
- destroyBlock();
- }
- fGpu->unref();
-}
-
-void GrVertexBufferAllocPool::reset() {
- while (!fBlocks.empty()) {
- destroyBlock();
- }
- if (fPreallocBuffers.count()) {
- // must set this after above loop.
- fFirstPreallocBuffer = (fFirstPreallocBuffer + fPreallocBuffersInUse) %
- fPreallocBuffers.count();
- }
- GrAssert(0 == fPreallocBuffersInUse);
-}
-
-void GrVertexBufferAllocPool::unlock() {
- GrAssert((NULL == fBufferPtr) ? (!fBlocks.empty() ||
- !fBlocks.back().fVertexBuffer->isLocked()) :
- (!fBlocks.empty() &&
- fBlocks.back().fVertexBuffer->isLocked()));
- if (NULL != fBufferPtr) {
- GrAssert(!fBlocks.empty());
- GrAssert(fBlocks.back().fVertexBuffer->isLocked());
- fBufferPtr = NULL;
- fBlocks.back().fVertexBuffer->unlock();
- }
-#if GR_DEBUG
- for (uint32_t i = 0; i < fBlocks.count(); ++i) {
- GrAssert(!fBlocks[i].fVertexBuffer->isLocked());
- }
-#endif
-}
-
-void* GrVertexBufferAllocPool::alloc(GrVertexLayout layout,
- uint32_t vertexCount,
- GrVertexBuffer** buffer,
- uint32_t* startVertex) {
- GrAssert(NULL != buffer);
- size_t vSize = GrDrawTarget::VertexSize(layout);
- size_t bytes = vSize * vertexCount;
-
- if (NULL != fBufferPtr) {
- GrAssert(!fBlocks.empty());
- GrAssert(fBlocks.back().fVertexBuffer->isLocked());
- BufferBlock& back = fBlocks.back();
- uint32_t usedBytes = back.fVertexBuffer->size() - back.fBytesFree;
- uint32_t pad = GrUIAlignUpPad(usedBytes,
- GrDrawTarget::VertexSize(layout));
- if ((bytes + pad) <= back.fBytesFree) {
- usedBytes += pad;
- *startVertex = usedBytes / vSize;
- *buffer = back.fVertexBuffer;
- back.fBytesFree -= bytes + pad;
- return (void*)((intptr_t)fBufferPtr + usedBytes);
- }
- }
-
- if (!createBlock(GrMax(bytes, fMinBlockSize))) {
- return NULL;
- }
- *startVertex = 0;
- GrAssert(NULL != fBufferPtr);
- BufferBlock& back = fBlocks.back();
- *buffer = back.fVertexBuffer;
- back.fBytesFree -= bytes;
- return fBufferPtr;
-}
-
-int GrVertexBufferAllocPool::currentBufferVertices(GrVertexLayout layout) const {
- if (NULL != fBufferPtr) {
- GrAssert(!fBlocks.empty());
- const BufferBlock& back = fBlocks.back();
- GrAssert(back.fVertexBuffer->isLocked());
- return back.fBytesFree / GrDrawTarget::VertexSize(layout);
- } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
- return fMinBlockSize / GrDrawTarget::VertexSize(layout);
- }
- return 0;
-}
-
-int GrVertexBufferAllocPool::preallocatedBuffersRemaining() const {
- return fPreallocBuffers.count() - fPreallocBuffersInUse;
-}
-
-int GrVertexBufferAllocPool::preallocatedBufferVertices(GrVertexLayout layout) const {
- return fPreallocBuffers.count() ?
- (fMinBlockSize / GrDrawTarget::VertexSize(layout)) :
- 0;
-}
-
-int GrVertexBufferAllocPool::preallocatedBufferCount() const {
- return fPreallocBuffers.count();
-}
-
-void GrVertexBufferAllocPool::release(size_t bytes) {
- if (NULL != fBufferPtr) {
- GrAssert(!fBlocks.empty());
- BufferBlock& back = fBlocks.back();
- GrAssert(back.fVertexBuffer->isLocked());
- size_t bytesUsed = back.fVertexBuffer->size() - back.fBytesFree;
- if (bytes >= bytesUsed) {
- destroyBlock();
- bytes -= bytesUsed;
- } else {
- back.fBytesFree += bytes;
- return;
- }
- }
- GrAssert(NULL == fBufferPtr);
- GrAssert(fBlocks.empty() ||
- !fBlocks.back().fVertexBuffer->isLocked());
- // we don't honor release if it is within an already unlocked VB
- // Our VB semantics say locking a VB discards its previous content
- while (!fBlocks.empty() &&
- bytes >= fBlocks.back().fVertexBuffer->size()) {
- bytes -= fBlocks.back().fVertexBuffer->size();
- destroyBlock();
- }
-}
-
-bool GrVertexBufferAllocPool::createBlock(size_t size) {
- GrAssert(size >= GrVertexBufferAllocPool_MIN_BLOCK_SIZE);
-
- BufferBlock& block = fBlocks.push_back();
-
- if (size == fMinBlockSize &&
- fPreallocBuffersInUse < fPreallocBuffers.count()) {
-
- uint32_t nextBuffer = (fPreallocBuffersInUse + fFirstPreallocBuffer) %
- fPreallocBuffers.count();
- block.fVertexBuffer = fPreallocBuffers[nextBuffer];
- block.fVertexBuffer->ref();
- ++fPreallocBuffersInUse;
- } else {
- block.fVertexBuffer = fGpu->createVertexBuffer(size, true);
- if (NULL == block.fVertexBuffer) {
- fBlocks.pop_back();
- return false;
- }
- }
-
- block.fBytesFree = size;
- if (NULL != fBufferPtr) {
- GrAssert(fBlocks.count() > 1);
- BufferBlock& prev = fBlocks.fromBack(1);
- GrAssert(prev.fVertexBuffer->isLocked());
- fBufferPtr = NULL;
- prev.fVertexBuffer->unlock();
- }
- fBufferPtr = block.fVertexBuffer->lock();
- return true;
-}
-
-void GrVertexBufferAllocPool::destroyBlock() {
- GrAssert(!fBlocks.empty());
-
- BufferBlock& block = fBlocks.back();
- if (fPreallocBuffersInUse > 0) {
- uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
- fFirstPreallocBuffer +
- (fPreallocBuffers.count() - 1)) %
- fPreallocBuffers.count();
- if (block.fVertexBuffer == fPreallocBuffers[prevPreallocBuffer]) {
- --fPreallocBuffersInUse;
- }
- }
- block.fVertexBuffer->unref();
- fBlocks.pop_back();
- fBufferPtr = NULL;
-}
-
-
diff --git a/gpu/src/gr_files.mk b/gpu/src/gr_files.mk
index 67d2838..4c06345 100644
--- a/gpu/src/gr_files.mk
+++ b/gpu/src/gr_files.mk
@@ -22,4 +22,4 @@
GrTextureCache.cpp \
GrTextContext.cpp \
GrTextStrike.cpp \
- GrVertexBufferAllocPool.cpp
+ GrBufferAllocPool.cpp