diff options
author | Loren Shih <seraph@lindenlab.com> | 2011-02-23 12:50:17 -0500 |
---|---|---|
committer | Loren Shih <seraph@lindenlab.com> | 2011-02-23 12:50:17 -0500 |
commit | 9b50def44f8b6a477d54ae72891d4d1b1225e247 (patch) | |
tree | df2e012ae6869ed381f6e3835b61e9cc6b9b2554 /indra/llrender | |
parent | d46594bf714cd19ebcbf693463c4d39e4c771bb8 (diff) | |
parent | e216fabde0b23923a3fff5c5edcb6a6a0be10ddd (diff) |
Automated merge up from viewer-development into mesh-development
Diffstat (limited to 'indra/llrender')
-rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 160 | ||||
-rw-r--r-- | indra/llrender/llvertexbuffer.h | 567 |
2 files changed, 412 insertions, 315 deletions
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index f5e85aecda..7a1ccb0cb4 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -49,6 +49,7 @@ U32 LLVertexBuffer::sSetCount = 0; S32 LLVertexBuffer::sCount = 0; S32 LLVertexBuffer::sGLCount = 0; S32 LLVertexBuffer::sMappedCount = 0; +BOOL LLVertexBuffer::sDisableVBOMapping = FALSE ; BOOL LLVertexBuffer::sEnableVBOs = TRUE; U32 LLVertexBuffer::sGLRenderBuffer = 0; U32 LLVertexBuffer::sGLRenderIndices = 0; @@ -297,6 +298,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const { llassert(mRequestedNumIndices >= 0); + if (indices_offset >= (U32) mRequestedNumIndices || indices_offset + count > (U32) mRequestedNumIndices) { @@ -328,6 +330,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { llassert(mRequestedNumVerts >= 0); + if (first >= (U32) mRequestedNumVerts || first + count > (U32) mRequestedNumVerts) { @@ -351,9 +354,10 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const } //static -void LLVertexBuffer::initClass(bool use_vbo) +void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping) { sEnableVBOs = use_vbo; + sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ; LLGLNamePool::registerPool(&sDynamicVBOPool); LLGLNamePool::registerPool(&sDynamicIBOPool); LLGLNamePool::registerPool(&sStreamVBOPool); @@ -497,6 +501,8 @@ LLVertexBuffer::~LLVertexBuffer() destroyGLBuffer(); destroyGLIndices(); sCount--; + + llassert_always(!mMappedData && !mMappedIndexData) ; }; //---------------------------------------------------------------------------- @@ -645,6 +651,8 @@ void LLVertexBuffer::destroyGLBuffer() { if (useVBOs()) { + freeClientBuffer() ; + if (mMappedData || mMappedIndexData) { llerrs << "Vertex buffer destroyed while mapped!" << llendl; @@ -672,11 +680,13 @@ void LLVertexBuffer::destroyGLIndices() { if (useVBOs()) { + freeClientBuffer() ; + if (mMappedData || mMappedIndexData) { llerrs << "Vertex buffer destroyed while mapped." << llendl; } - releaseIndices(); + releaseIndices(); } else { @@ -848,6 +858,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) if (mResized && useVBOs()) { + freeClientBuffer() ; setBuffer(0); } } @@ -871,6 +882,36 @@ BOOL LLVertexBuffer::useVBOs() const } //---------------------------------------------------------------------------- +void LLVertexBuffer::freeClientBuffer() +{ + if(useVBOs() && sDisableVBOMapping && (mMappedData || mMappedIndexData)) + { + delete[] mMappedData ; + delete[] mMappedIndexData ; + mMappedData = NULL ; + mMappedIndexData = NULL ; + } +} + +void LLVertexBuffer::allocateClientVertexBuffer() +{ + if(!mMappedData) + { + U32 size = getSize() ; + mMappedData = new U8[size]; + memset(mMappedData, 0, size); + } +} + +void LLVertexBuffer::allocateClientIndexBuffer() +{ + if(!mMappedIndexData) + { + U32 size = getIndicesSize(); + mMappedIndexData = new U8[size]; + memset(mMappedIndexData, 0, size); + } +} // Map for data access U8* LLVertexBuffer::mapBuffer(S32 access) @@ -893,10 +934,14 @@ U8* LLVertexBuffer::mapBuffer(S32 access) mLocked = TRUE; stop_glerror(); - U8* src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); - mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src); - mAlignedOffset = mMappedData - src; - + if(sDisableVBOMapping) + { + allocateClientVertexBuffer() ; + } + else + { + mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } stop_glerror(); } { @@ -905,6 +950,14 @@ U8* LLVertexBuffer::mapBuffer(S32 access) mMappedIndexData = LL_NEXT_ALIGNED_ADDRESS<U8>(src); mAlignedIndexOffset = mMappedIndexData - src; + if(sDisableVBOMapping) + { + allocateClientIndexBuffer() ; + } + else + { + mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } stop_glerror(); } @@ -918,37 +971,51 @@ U8* LLVertexBuffer::mapBuffer(S32 access) llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ; llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl; - //-------------------- - //print out more debug info before crash - llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ; - GLint size ; - glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ; - llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ; - //-------------------- + if(!sDisableVBOMapping) + { + //-------------------- + //print out more debug info before crash + llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ; + GLint size ; + glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ; + llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ; + //-------------------- - GLint buff; - glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); - if ((GLuint)buff != mGLBuffer) + GLint buff; + glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); + if ((GLuint)buff != mGLBuffer) + { + llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + } + + + llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl; + } + else { - llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + llerrs << "memory allocation for vertex data failed." << llendl ; } - - - llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl; } if (!mMappedIndexData) { log_glerror(); - GLint buff; - glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); - if ((GLuint)buff != mGLIndices) + if(!sDisableVBOMapping) { - llerrs << "Invalid GL index buffer bound: " << buff << llendl; - } + GLint buff; + glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); + if ((GLuint)buff != mGLIndices) + { + llerrs << "Invalid GL index buffer bound: " << buff << llendl; + } - llerrs << "glMapBuffer returned NULL (no index data)" << llendl; + llerrs << "glMapBuffer returned NULL (no index data)" << llendl; + } + else + { + llerrs << "memory allocation for Index data failed. " << llendl ; + } } sMappedCount++; @@ -964,11 +1031,29 @@ void LLVertexBuffer::unmapBuffer() { if (useVBOs() && mLocked) { - stop_glerror(); - glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); - stop_glerror(); - glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); - stop_glerror(); + if(sDisableVBOMapping) + { + if(mMappedData) + { + stop_glerror(); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData); + stop_glerror(); + } + if(mMappedIndexData) + { + stop_glerror(); + glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData); + stop_glerror(); + } + } + else + { + stop_glerror(); + glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); + stop_glerror(); + glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); + stop_glerror(); + } /*if (!sMapped) { @@ -982,15 +1067,22 @@ void LLVertexBuffer::unmapBuffer() //throw out client data (we won't be using it again) mEmpty = TRUE; mFinal = TRUE; + + if(sDisableVBOMapping) + { + freeClientBuffer() ; + } } else { mEmpty = FALSE; } - mMappedIndexData = NULL; - mMappedData = NULL; - + if(!sDisableVBOMapping) + { + mMappedIndexData = NULL; + mMappedData = NULL; + } mLocked = FALSE; } } diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 77c9da2d6c..fb81720c86 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -1,281 +1,286 @@ -/** - * @file llvertexbuffer.h - * @brief LLVertexBuffer wrapper for OpengGL vertex buffer objects - * - * $LicenseInfo:firstyear=2003&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLVERTEXBUFFER_H -#define LL_LLVERTEXBUFFER_H - -#include "llgl.h" -#include "v2math.h" -#include "v3math.h" -#include "v4math.h" -#include "v4coloru.h" -#include "llstrider.h" -#include "llrender.h" -#include <set> -#include <vector> -#include <list> - -//============================================================================ -// NOTES -// Threading: -// All constructors should take an 'create' paramater which should only be -// 'true' when called from the main thread. Otherwise createGLBuffer() will -// be called as soon as getVertexPointer(), etc is called (which MUST ONLY be -// called from the main (i.e OpenGL) thread) - - -//============================================================================ -// gl name pools for dynamic and streaming buffers - -class LLVBOPool : public LLGLNamePool -{ -protected: - virtual GLuint allocateName() - { - GLuint name; - glGenBuffersARB(1, &name); - return name; - } - - virtual void releaseName(GLuint name) - { - glDeleteBuffersARB(1, &name); - } -}; - - -//============================================================================ -// base class - -class LLVertexBuffer : public LLRefCount -{ -public: - LLVertexBuffer(const LLVertexBuffer& rhs) - { - *this = rhs; - } - - const LLVertexBuffer& operator=(const LLVertexBuffer& rhs) - { - llerrs << "Illegal operation!" << llendl; - return *this; - } - - static LLVBOPool sStreamVBOPool; - static LLVBOPool sDynamicVBOPool; - static LLVBOPool sStreamIBOPool; - static LLVBOPool sDynamicIBOPool; - - static S32 sWeight4Loc; - - static BOOL sUseStreamDraw; - static BOOL sPreferStreamDraw; - - static void initClass(bool use_vbo); - static void cleanupClass(); - static void setupClientArrays(U32 data_mask); - static void clientCopy(F64 max_time = 0.005); //copy data from client to GL - static void unbind(); //unbind any bound vertex buffer - - //get the size of a vertex with the given typemask - static S32 calcVertexSize(const U32& typemask); - - //get the size of a buffer with the given typemask and vertex count - //fill offsets with the offset of each vertex component array into the buffer - // indexed by the following enum - static S32 calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices); - - - enum { - TYPE_VERTEX, - TYPE_NORMAL, - TYPE_TEXCOORD0, - TYPE_TEXCOORD1, - TYPE_TEXCOORD2, - TYPE_TEXCOORD3, - TYPE_COLOR, - // These use VertexAttribPointer and should possibly be made generic - TYPE_BINORMAL, - TYPE_WEIGHT, - TYPE_WEIGHT4, - TYPE_CLOTHWEIGHT, - TYPE_MAX, - TYPE_INDEX, - }; - enum { - MAP_VERTEX = (1<<TYPE_VERTEX), - MAP_NORMAL = (1<<TYPE_NORMAL), - MAP_TEXCOORD0 = (1<<TYPE_TEXCOORD0), - MAP_TEXCOORD1 = (1<<TYPE_TEXCOORD1), - MAP_TEXCOORD2 = (1<<TYPE_TEXCOORD2), - MAP_TEXCOORD3 = (1<<TYPE_TEXCOORD3), - MAP_COLOR = (1<<TYPE_COLOR), - // These use VertexAttribPointer and should possibly be made generic - MAP_BINORMAL = (1<<TYPE_BINORMAL), - MAP_WEIGHT = (1<<TYPE_WEIGHT), - MAP_WEIGHT4 = (1<<TYPE_WEIGHT4), - MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT), - }; - -protected: - friend class LLRender; - - virtual ~LLVertexBuffer(); // use unref() - - virtual void setupVertexBuffer(U32 data_mask) const; // pure virtual, called from mapBuffer() - - void genBuffer(); - void genIndices(); - void releaseBuffer(); - void releaseIndices(); - void createGLBuffer(); - void createGLIndices(); - void destroyGLBuffer(); - void destroyGLIndices(); - void updateNumVerts(S32 nverts); - void updateNumIndices(S32 nindices); - virtual BOOL useVBOs() const; - void unmapBuffer(); - -public: - LLVertexBuffer(U32 typemask, S32 usage); - - // map for data access - U8* mapBuffer(S32 access = -1); - // set for rendering - virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0 - // allocate buffer - void allocateBuffer(S32 nverts, S32 nindices, bool create); - virtual void resizeBuffer(S32 newnverts, S32 newnindices); - - // Only call each getVertexPointer, etc, once before calling unmapBuffer() - // call unmapBuffer() after calls to getXXXStrider() before any cals to setBuffer() - // example: - // vb->getVertexBuffer(verts); - // vb->getNormalStrider(norms); - // setVertsNorms(verts, norms); - // vb->unmapBuffer(); - bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0); - bool getIndexStrider(LLStrider<U16>& strider, S32 index=0); - bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0); - bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0); - bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0); - bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0); - bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0); - bool getWeightStrider(LLStrider<F32>& strider, S32 index=0); - bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0); - bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0); - - BOOL isEmpty() const { return mEmpty; } - BOOL isLocked() const { return mLocked; } - S32 getNumVerts() const { return mNumVerts; } - S32 getNumIndices() const { return mNumIndices; } - S32 getRequestedVerts() const { return mRequestedNumVerts; } - S32 getRequestedIndices() const { return mRequestedNumIndices; } - - U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } - U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } - U32 getTypeMask() const { return mTypeMask; } - bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); } - S32 getSize() const; - S32 getIndicesSize() const { return mNumIndices * sizeof(U16); } - U8* getMappedData() const { return mMappedData; } - U8* getMappedIndices() const { return mMappedIndexData; } - S32 getOffset(S32 type) const { return mOffsets[type]; } - S32 getUsage() const { return mUsage; } - - void markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count); - - void draw(U32 mode, U32 count, U32 indices_offset) const; - void drawArrays(U32 mode, U32 offset, U32 count) const; - void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const; - - //for debugging, validate data in given range is valid - void validateRange(U32 start, U32 end, U32 count, U32 offset) const; - - - -protected: - S32 mNumVerts; // Number of vertices allocated - S32 mNumIndices; // Number of indices allocated - S32 mRequestedNumVerts; // Number of vertices requested - S32 mRequestedNumIndices; // Number of indices requested - - ptrdiff_t mAlignedOffset; - ptrdiff_t mAlignedIndexOffset; - S32 mSize; - U32 mTypeMask; - S32 mUsage; // GL usage - U32 mGLBuffer; // GL VBO handle - U32 mGLIndices; // GL IBO handle - U8* mMappedData; // pointer to currently mapped data (NULL if unmapped) - U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped) - BOOL mLocked; // if TRUE, buffer is being or has been written to in client memory - BOOL mFinal; // if TRUE, buffer can not be mapped again - BOOL mFilthy; // if TRUE, entire buffer must be copied (used to prevent redundant dirty flags) - BOOL mEmpty; // if TRUE, client buffer is empty (or NULL). Old values have been discarded. - S32 mOffsets[TYPE_MAX]; - BOOL mResized; // if TRUE, client buffer has been resized and GL buffer has not - BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded) - - class DirtyRegion - { - public: - U32 mIndex; - U32 mCount; - U32 mIndicesIndex; - U32 mIndicesCount; - - DirtyRegion(U32 vi, U32 vc, U32 ii, U32 ic) - : mIndex(vi), mCount(vc), mIndicesIndex(ii), mIndicesCount(ic) - { } - }; - - std::vector<DirtyRegion> mDirtyRegions; //vector of dirty regions to rebuild - -public: - static S32 sCount; - static S32 sGLCount; - static S32 sMappedCount; - static BOOL sMapped; - static std::vector<U32> sDeleteList; - typedef std::list<LLVertexBuffer*> buffer_list_t; - - static BOOL sEnableVBOs; - static S32 sTypeSize[TYPE_MAX]; - static U32 sGLMode[LLRender::NUM_MODES]; - static U32 sGLRenderBuffer; - static U32 sGLRenderIndices; - static BOOL sVBOActive; - static BOOL sIBOActive; - static U32 sLastMask; - static U32 sAllocatedBytes; - static U32 sBindCount; - static U32 sSetCount; -}; - - -#endif // LL_LLVERTEXBUFFER_H +/**
+ * @file llvertexbuffer.h
+ * @brief LLVertexBuffer wrapper for OpengGL vertex buffer objects
+ *
+ * $LicenseInfo:firstyear=2003&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVERTEXBUFFER_H
+#define LL_LLVERTEXBUFFER_H
+
+#include "llgl.h"
+#include "v2math.h"
+#include "v3math.h"
+#include "v4math.h"
+#include "v4coloru.h"
+#include "llstrider.h"
+#include "llrender.h"
+#include <set>
+#include <vector>
+#include <list>
+
+//============================================================================
+// NOTES
+// Threading:
+// All constructors should take an 'create' paramater which should only be
+// 'true' when called from the main thread. Otherwise createGLBuffer() will
+// be called as soon as getVertexPointer(), etc is called (which MUST ONLY be
+// called from the main (i.e OpenGL) thread)
+
+
+//============================================================================
+// gl name pools for dynamic and streaming buffers
+
+class LLVBOPool : public LLGLNamePool
+{
+protected:
+ virtual GLuint allocateName()
+ {
+ GLuint name;
+ glGenBuffersARB(1, &name);
+ return name;
+ }
+
+ virtual void releaseName(GLuint name)
+ {
+ glDeleteBuffersARB(1, &name);
+ }
+};
+
+
+//============================================================================
+// base class
+
+class LLVertexBuffer : public LLRefCount
+{
+public:
+ LLVertexBuffer(const LLVertexBuffer& rhs)
+ {
+ *this = rhs;
+ }
+
+ const LLVertexBuffer& operator=(const LLVertexBuffer& rhs)
+ {
+ llerrs << "Illegal operation!" << llendl;
+ return *this;
+ }
+
+ static LLVBOPool sStreamVBOPool;
+ static LLVBOPool sDynamicVBOPool;
+ static LLVBOPool sStreamIBOPool;
+ static LLVBOPool sDynamicIBOPool;
+
+ static S32 sWeight4Loc;
+
+ static BOOL sUseStreamDraw;
+ static BOOL sPreferStreamDraw;
+
+ static void initClass(bool use_vbo, bool no_vbo_mapping);
+ static void cleanupClass();
+ static void setupClientArrays(U32 data_mask);
+ static void clientCopy(F64 max_time = 0.005); //copy data from client to GL
+ static void unbind(); //unbind any bound vertex buffer
+
+ //get the size of a vertex with the given typemask
+ static S32 calcVertexSize(const U32& typemask);
+
+ //get the size of a buffer with the given typemask and vertex count
+ //fill offsets with the offset of each vertex component array into the buffer
+ // indexed by the following enum
+ static S32 calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices);
+
+
+ enum {
+ TYPE_VERTEX,
+ TYPE_NORMAL,
+ TYPE_TEXCOORD0,
+ TYPE_TEXCOORD1,
+ TYPE_TEXCOORD2,
+ TYPE_TEXCOORD3,
+ TYPE_COLOR,
+ // These use VertexAttribPointer and should possibly be made generic
+ TYPE_BINORMAL,
+ TYPE_WEIGHT,
+ TYPE_WEIGHT4,
+ TYPE_CLOTHWEIGHT,
+ TYPE_MAX,
+ TYPE_INDEX,
+ };
+ enum {
+ MAP_VERTEX = (1<<TYPE_VERTEX),
+ MAP_NORMAL = (1<<TYPE_NORMAL),
+ MAP_TEXCOORD0 = (1<<TYPE_TEXCOORD0),
+ MAP_TEXCOORD1 = (1<<TYPE_TEXCOORD1),
+ MAP_TEXCOORD2 = (1<<TYPE_TEXCOORD2),
+ MAP_TEXCOORD3 = (1<<TYPE_TEXCOORD3),
+ MAP_COLOR = (1<<TYPE_COLOR),
+ // These use VertexAttribPointer and should possibly be made generic
+ MAP_BINORMAL = (1<<TYPE_BINORMAL),
+ MAP_WEIGHT = (1<<TYPE_WEIGHT),
+ MAP_WEIGHT4 = (1<<TYPE_WEIGHT4),
+ MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT),
+ };
+
+protected:
+ friend class LLRender;
+
+ virtual ~LLVertexBuffer(); // use unref()
+
+ virtual void setupVertexBuffer(U32 data_mask) const; // pure virtual, called from mapBuffer()
+
+ void genBuffer();
+ void genIndices();
+ void releaseBuffer();
+ void releaseIndices();
+ void createGLBuffer();
+ void createGLIndices();
+ void destroyGLBuffer();
+ void destroyGLIndices();
+ void updateNumVerts(S32 nverts);
+ void updateNumIndices(S32 nindices);
+ virtual BOOL useVBOs() const;
+ void unmapBuffer();
+
+public:
+ LLVertexBuffer(U32 typemask, S32 usage);
+
+ // map for data access
+ U8* mapBuffer(S32 access = -1);
+ // set for rendering
+ virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0
+ // allocate buffer
+ void allocateBuffer(S32 nverts, S32 nindices, bool create);
+ virtual void resizeBuffer(S32 newnverts, S32 newnindices);
+
+ void freeClientBuffer() ;
+ void allocateClientVertexBuffer() ;
+ void allocateClientIndexBuffer() ;
+
+ // Only call each getVertexPointer, etc, once before calling unmapBuffer()
+ // call unmapBuffer() after calls to getXXXStrider() before any cals to setBuffer()
+ // example:
+ // vb->getVertexBuffer(verts);
+ // vb->getNormalStrider(norms);
+ // setVertsNorms(verts, norms);
+ // vb->unmapBuffer();
+ bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0);
+ bool getIndexStrider(LLStrider<U16>& strider, S32 index=0);
+ bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0);
+ bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0);
+ bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
+ bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
+ bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0);
+ bool getWeightStrider(LLStrider<F32>& strider, S32 index=0);
+ bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0);
+ bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0);
+
+ BOOL isEmpty() const { return mEmpty; }
+ BOOL isLocked() const { return mLocked; }
+ S32 getNumVerts() const { return mNumVerts; }
+ S32 getNumIndices() const { return mNumIndices; }
+ S32 getRequestedVerts() const { return mRequestedNumVerts; }
+ S32 getRequestedIndices() const { return mRequestedNumIndices; }
+
+ U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; }
+ U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; }
+ U32 getTypeMask() const { return mTypeMask; }
+ bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); }
+ S32 getSize() const;
+ S32 getIndicesSize() const { return mNumIndices * sizeof(U16); }
+ U8* getMappedData() const { return mMappedData; }
+ U8* getMappedIndices() const { return mMappedIndexData; }
+ S32 getOffset(S32 type) const { return mOffsets[type]; }
+ S32 getUsage() const { return mUsage; }
+
+ void markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count);
+
+ void draw(U32 mode, U32 count, U32 indices_offset) const;
+ void drawArrays(U32 mode, U32 offset, U32 count) const;
+ void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
+
+ //for debugging, validate data in given range is valid
+ void validateRange(U32 start, U32 end, U32 count, U32 offset) const;
+
+
+
+protected:
+ S32 mNumVerts; // Number of vertices allocated
+ S32 mNumIndices; // Number of indices allocated
+ S32 mRequestedNumVerts; // Number of vertices requested
+ S32 mRequestedNumIndices; // Number of indices requested
+
+ ptrdiff_t mAlignedOffset;
+ ptrdiff_t mAlignedIndexOffset;
+ S32 mSize;
+ U32 mTypeMask;
+ S32 mUsage; // GL usage
+ U32 mGLBuffer; // GL VBO handle
+ U32 mGLIndices; // GL IBO handle
+ U8* mMappedData; // pointer to currently mapped data (NULL if unmapped)
+ U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped)
+ BOOL mLocked; // if TRUE, buffer is being or has been written to in client memory
+ BOOL mFinal; // if TRUE, buffer can not be mapped again
+ BOOL mFilthy; // if TRUE, entire buffer must be copied (used to prevent redundant dirty flags)
+ BOOL mEmpty; // if TRUE, client buffer is empty (or NULL). Old values have been discarded.
+ S32 mOffsets[TYPE_MAX];
+ BOOL mResized; // if TRUE, client buffer has been resized and GL buffer has not
+ BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded)
+
+ class DirtyRegion
+ {
+ public:
+ U32 mIndex;
+ U32 mCount;
+ U32 mIndicesIndex;
+ U32 mIndicesCount;
+
+ DirtyRegion(U32 vi, U32 vc, U32 ii, U32 ic)
+ : mIndex(vi), mCount(vc), mIndicesIndex(ii), mIndicesCount(ic)
+ { }
+ };
+
+ std::vector<DirtyRegion> mDirtyRegions; //vector of dirty regions to rebuild
+
+public:
+ static S32 sCount;
+ static S32 sGLCount;
+ static S32 sMappedCount;
+ static BOOL sMapped;
+ static std::vector<U32> sDeleteList;
+ typedef std::list<LLVertexBuffer*> buffer_list_t;
+
+ static BOOL sDisableVBOMapping; //disable glMapBufferARB
+ static BOOL sEnableVBOs;
+ static S32 sTypeSize[TYPE_MAX];
+ static BOOL sVBOActive;
+ static BOOL sIBOActive;
+ static U32 sGLMode[LLRender::NUM_MODES];
+ static U32 sGLRenderBuffer;
+ static U32 sGLRenderIndices;
+ static U32 sLastMask;
+ static U32 sAllocatedBytes;
+ static U32 sBindCount;
+ static U32 sSetCount;
+};
+
+
+#endif // LL_LLVERTEXBUFFER_H
|