From 162d467b4a8ca1dae6b16ece1728873d43a287ac Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Thu, 3 Mar 2011 16:14:52 -0600
Subject: [PATCH] SH-1085 Fix for crash when unchecking "mirror."  Basically
 got LLFace to be paranoid about who gets to touch its LLVertexBuffer members.

Reviewed by Nyx.
---
 indra/newview/lldrawable.cpp             |  15 ++-
 indra/newview/lldrawpoolavatar.cpp       |  65 ++++-------
 indra/newview/lldrawpooltree.cpp         |  15 +--
 indra/newview/llface.cpp                 | 131 ++++++++++++++++++-----
 indra/newview/llface.h                   |  23 ++--
 indra/newview/llspatialpartition.cpp     |  15 +--
 indra/newview/llsprite.cpp               |   9 +-
 indra/newview/llviewerjointmesh.cpp      |  16 +--
 indra/newview/llviewerjointmesh_sse.cpp  |   2 +-
 indra/newview/llviewerjointmesh_sse2.cpp |   2 +-
 indra/newview/llvoavatar.cpp             |  31 +++---
 indra/newview/llvograss.cpp              |   2 +-
 indra/newview/llvoground.cpp             |   9 +-
 indra/newview/llvopartgroup.cpp          |   2 +-
 indra/newview/llvosky.cpp                |  46 ++++----
 indra/newview/llvosurfacepatch.cpp       |   4 +-
 indra/newview/llvotree.cpp               |  22 ++--
 indra/newview/llvovolume.cpp             |  73 +++++++------
 indra/newview/llvowater.cpp              |  12 ++-
 indra/newview/pipeline.cpp               |   3 +-
 20 files changed, 293 insertions(+), 204 deletions(-)

diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index d370c72a04b..fe743e74516 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -820,8 +820,7 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector)
 			
 			if (!volume && facep->hasGeometry())
 			{
-				facep->mVertexBuffer = NULL;
-				facep->mLastVertexBuffer = NULL;
+				facep->clearVertexBuffer();
 			}
 		}
 		
@@ -935,6 +934,18 @@ void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp)
 	{
 		mSpatialGroupp->setState(LLSpatialGroup::GEOM_DIRTY);
 	}*/
+
+	if (mSpatialGroupp != groupp && getVOVolume())
+	{ //NULL out vertex buffer references for volumes on spatial group change to maintain
+		//requirement that every face vertex buffer is either NULL or points to a vertex buffer
+		//contained by its drawable's spatial group
+		for (S32 i = 0; i < getNumFaces(); ++i)
+		{
+			LLFace* facep = getFace(i);
+			facep->clearVertexBuffer();
+		}
+	}
+
 	mSpatialGroupp = groupp;
 }
 
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index b044a89af8e..48e561b24bf 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -99,19 +99,6 @@ S32 normal_channel = -1;
 S32 specular_channel = -1;
 S32 cube_channel = -1;
 
-static const U32 rigged_data_mask[] = {
-	LLDrawPoolAvatar::RIGGED_SIMPLE_MASK,
-	LLDrawPoolAvatar::RIGGED_FULLBRIGHT_MASK,
-	LLDrawPoolAvatar::RIGGED_SHINY_MASK,
-	LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY_MASK,
-	LLDrawPoolAvatar::RIGGED_GLOW_MASK,
-	LLDrawPoolAvatar::RIGGED_ALPHA_MASK,
-	LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA_MASK,
-	LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP_MASK,						 
-	LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE_MASK,
-};
-
-
 static LLFastTimer::DeclareTimer FTM_SHADOW_AVATAR("Avatar Shadow");
 
 LLDrawPoolAvatar::LLDrawPoolAvatar() : 
@@ -1297,17 +1284,10 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
 		return;
 	}
 
-	LLVertexBuffer* buffer = face->mVertexBuffer;
-
-	U32 data_mask = 0;
-	for (U32 i = 0; i < face->mRiggedIndex.size(); ++i)
-	{
-		if (face->mRiggedIndex[i] > -1)
-		{
-			data_mask |= rigged_data_mask[i];
-		}
-	}
+	LLVertexBuffer* buffer = face->getVertexBuffer();
 
+	U32 data_mask = face->getRiggedVertexBufferDataMask();
+	
 	if (!buffer || 
 		buffer->getTypeMask() != data_mask ||
 		buffer->getRequestedVerts() != vol_face.mNumVertices)
@@ -1316,16 +1296,19 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
 		face->setIndicesIndex(0);
 		face->setSize(vol_face.mNumVertices, vol_face.mNumIndices, true);
 
+
 		if (sShaderLevel > 0)
 		{
-			face->mVertexBuffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB);
+			buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB);
 		}
 		else
 		{
-			face->mVertexBuffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB);
+			buffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB);
 		}
 
-		face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), true);
+		buffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), true);
+
+		face->setVertexBuffer(buffer);
 
 		U16 offset = 0;
 		
@@ -1341,7 +1324,6 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
 		LLMatrix3 mat_normal(mat3);				
 
 		face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true);
-		buffer = face->mVertexBuffer;
 	}
 
 	if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime())
@@ -1480,9 +1462,9 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
 		
 		stop_glerror();
 
-		U32 data_mask = rigged_data_mask[type];
+		U32 data_mask = LLFace::getRiggedDataMask(type);
 
-		LLVertexBuffer* buff = face->mVertexBuffer;
+		LLVertexBuffer* buff = face->getVertexBuffer();
 
 		if (buff)
 		{
@@ -1624,49 +1606,38 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const
 
 void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type)
 {
-	if (facep->mRiggedIndex.empty())
-	{
-		facep->mRiggedIndex.resize(LLDrawPoolAvatar::NUM_RIGGED_PASSES);
-		for (U32 i = 0; i < facep->mRiggedIndex.size(); ++i)
-		{
-			facep->mRiggedIndex[i] = -1;
-		}
-	}
-
 	if (type >= NUM_RIGGED_PASSES)
 	{
 		llerrs << "Invalid rigged face type." << llendl;
 	}
 
-	if (facep->mRiggedIndex[type] != -1)
+	if (facep->getRiggedIndex(type) != -1)
 	{
 		llerrs << "Tried to add a rigged face that's referenced elsewhere." << llendl;
 	}	
-
 	
-	facep->mRiggedIndex[type] = mRiggedFace[type].size();
-	facep->mDrawPoolp = this;
+	facep->setRiggedIndex(type, mRiggedFace[type].size());
+	facep->setPool(this);
 	mRiggedFace[type].push_back(facep);
 }
 
 void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep)
 {
-	
-	facep->mDrawPoolp = NULL;
+	facep->setPool(NULL);
 
 	for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i)
 	{
-		S32 index = facep->mRiggedIndex[i];
+		S32 index = facep->getRiggedIndex(i);
 		
 		if (index > -1)
 		{
 			if (mRiggedFace[i].size() > index && mRiggedFace[i][index] == facep)
 			{
-				facep->mRiggedIndex[i] = -1;
+				facep->setRiggedIndex(i,-1);
 				mRiggedFace[i].erase(mRiggedFace[i].begin()+index);
 				for (U32 j = index; j < mRiggedFace[i].size(); ++j)
 				{ //bump indexes down for faces referenced after erased face
-					mRiggedFace[i][j]->mRiggedIndex[i] = j;
+					mRiggedFace[i][j]->setRiggedIndex(i, j);
 				}
 			}
 			else
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index f1198c9a8de..195ee60a2ef 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -107,11 +107,12 @@ void LLDrawPoolTree::render(S32 pass)
 			 iter != mDrawFace.end(); iter++)
 		{
 			LLFace *face = *iter;
-			if(face->mVertexBuffer.notNull())
+			LLVertexBuffer* buff = face->getVertexBuffer();
+			if(buff)
 			{
-				face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
-				face->mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, face->mVertexBuffer->getRequestedVerts()-1, face->mVertexBuffer->getRequestedIndices(), 0); 
-				gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices());
+				buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
+				buff->drawRange(LLRender::TRIANGLES, 0, buff->getRequestedVerts()-1, buff->getRequestedIndices(), 0); 
+				gPipeline.addTrianglesDrawn(buff->getRequestedIndices());
 			}
 		}
 	}
@@ -200,13 +201,13 @@ void LLDrawPoolTree::renderTree(BOOL selecting)
 		LLFace *face = *iter;
 		LLDrawable *drawablep = face->getDrawable();
 
-		if (drawablep->isDead() || face->mVertexBuffer.isNull())
+		if (drawablep->isDead() || !face->getVertexBuffer())
 		{
 			continue;
 		}
 
-		face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
-		U16* indicesp = (U16*) face->mVertexBuffer->getIndicesPointer();
+		face->getVertexBuffer()->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
+		U16* indicesp = (U16*) face->getVertexBuffer()->getIndicesPointer();
 
 		// Render each of the trees
 		LLVOTree *treep = (LLVOTree *)drawablep->getVObj().get();
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 863e335f4ac..10847e70670 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -250,6 +250,11 @@ void LLFace::setWorldMatrix(const LLMatrix4 &mat)
 	llerrs << "Faces on this drawable are not independently modifiable\n" << llendl;
 }
 
+void LLFace::setPool(LLFacePool* pool)
+{
+	mDrawPoolp = pool;
+}
+
 void LLFace::setPool(LLFacePool* new_pool, LLViewerTexture *texturep)
 {
 	LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
@@ -375,6 +380,8 @@ void LLFace::setSize(S32 num_vertices, S32 num_indices, bool align)
 		mVertexBuffer = NULL;
 		mLastVertexBuffer = NULL;
 	}
+
+	llassert(verify());
 }
 
 //============================================================================
@@ -579,23 +586,26 @@ void LLFace::printDebugInfo() const
 	llinfos << "II: " << mIndicesIndex << " Count:" << mIndicesCount << llendl;
 	llinfos << llendl;
 
-	poolp->printDebugInfo();
-
-	S32 pool_references = 0;
-	for (std::vector<LLFace*>::iterator iter = poolp->mReferences.begin();
-		 iter != poolp->mReferences.end(); iter++)
+	if (poolp)
 	{
-		LLFace *facep = *iter;
-		if (facep == this)
+		poolp->printDebugInfo();
+
+		S32 pool_references = 0;
+		for (std::vector<LLFace*>::iterator iter = poolp->mReferences.begin();
+			 iter != poolp->mReferences.end(); iter++)
 		{
-			llinfos << "Pool reference: " << pool_references << llendl;
-			pool_references++;
+			LLFace *facep = *iter;
+			if (facep == this)
+			{
+				llinfos << "Pool reference: " << pool_references << llendl;
+				pool_references++;
+			}
 		}
-	}
 
-	if (pool_references != 1)
-	{
-		llinfos << "Incorrect number of pool references!" << llendl;
+		if (pool_references != 1)
+		{
+			llinfos << "Incorrect number of pool references!" << llendl;
+		}
 	}
 
 #if 0
@@ -976,6 +986,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 								bool force_rebuild)
 {
 	LLFastTimer t(FTM_FACE_GET_GEOM);
+	llassert(verify());
 	const LLVolumeFace &vf = volume.getVolumeFace(f);
 	S32 num_vertices = (S32)vf.mNumVertices;
 	S32 num_indices = (S32) vf.mNumIndices;
@@ -1842,16 +1853,7 @@ BOOL LLFace::verify(const U32* indices_array) const
 	BOOL ok = TRUE;
 
 	if( mVertexBuffer.isNull() )
-	{
-		if( mGeomCount )
-		{
-			// This happens before teleports as faces are torn down.
-			// Stop the crash in DEV-31893 with a null pointer check,
-			// but present this info.
-			// To clean up the log, the geometry could be cleared, or the
-			// face could otherwise be marked for no ::verify.
-			llinfos << "Face with no vertex buffer and " << mGeomCount << " mGeomCount" << llendl;
-		}
+	{ //no vertex buffer, face is implicitly valid
 		return TRUE;
 	}
 	
@@ -1859,7 +1861,7 @@ BOOL LLFace::verify(const U32* indices_array) const
 	if ((mGeomIndex + mGeomCount) > mVertexBuffer->getNumVerts())
 	{
 		ok = FALSE;
-		llinfos << "Face not within pool range!" << llendl;
+		llinfos << "Face references invalid vertices!" << llendl;
 	}
 
 	S32 indices_count = (S32)getIndicesCount();
@@ -1875,6 +1877,12 @@ BOOL LLFace::verify(const U32* indices_array) const
 		llinfos << "Face has bogus indices count" << llendl;
 	}
 	
+	if (mIndicesIndex + mIndicesCount > mVertexBuffer->getNumIndices())
+	{
+		ok = FALSE;
+		llinfos << "Face references invalid indices!" << llendl;
+	}
+
 #if 0
 	S32 geom_start = getGeomStart();
 	S32 geom_count = mGeomCount;
@@ -2183,3 +2191,78 @@ BOOL LLFace::switchTexture()
 	return mUsingAtlas ;
 }
 
+
+void LLFace::setVertexBuffer(LLVertexBuffer* buffer)
+{
+	mVertexBuffer = buffer;
+	llassert(verify());
+}
+
+void LLFace::clearVertexBuffer()
+{
+	mVertexBuffer = NULL;
+	mLastVertexBuffer = NULL;
+}
+
+//static
+U32 LLFace::getRiggedDataMask(U32 type)
+{
+	static const U32 rigged_data_mask[] = {
+		LLDrawPoolAvatar::RIGGED_SIMPLE_MASK,
+		LLDrawPoolAvatar::RIGGED_FULLBRIGHT_MASK,
+		LLDrawPoolAvatar::RIGGED_SHINY_MASK,
+		LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY_MASK,
+		LLDrawPoolAvatar::RIGGED_GLOW_MASK,
+		LLDrawPoolAvatar::RIGGED_ALPHA_MASK,
+		LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA_MASK,
+		LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP_MASK,						 
+		LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE_MASK,
+	};
+
+	llassert(type < sizeof(rigged_data_mask)/sizeof(U32));
+
+	return rigged_data_mask[type];
+}
+
+U32 LLFace::getRiggedVertexBufferDataMask() const
+{
+	U32 data_mask = 0;
+	for (U32 i = 0; i < mRiggedIndex.size(); ++i)
+	{
+		if (mRiggedIndex[i] > -1)
+		{
+			data_mask |= LLFace::getRiggedDataMask(i);
+		}
+	}
+
+	return data_mask;
+}
+
+S32 LLFace::getRiggedIndex(U32 type) const
+{
+	if (mRiggedIndex.empty())
+	{
+		return -1;
+	}
+
+	llassert(type < mRiggedIndex.size());
+
+	return mRiggedIndex[type];
+}
+
+void LLFace::setRiggedIndex(U32 type, S32 index)
+{
+	if (mRiggedIndex.empty())
+	{
+		mRiggedIndex.resize(LLDrawPoolAvatar::NUM_RIGGED_PASSES);
+		for (U32 i = 0; i < mRiggedIndex.size(); ++i)
+		{
+			mRiggedIndex[i] = -1;
+		}
+	}
+
+	llassert(type < mRiggedIndex.size());
+
+	mRiggedIndex[type] = index;
+}
+
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index cc04bf2f1ca..1f69dd145e6 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -131,14 +131,14 @@ class LLFace
 	LLDrawable*		getDrawable()		const	{ return mDrawablep; }
 	LLViewerObject*	getViewerObject()	const	{ return mVObjp; }
 	S32				getLOD()			const	{ return mVObjp.notNull() ? mVObjp->getLOD() : 0; }
-	LLVertexBuffer* getVertexBuffer()	const	{ return mVertexBuffer; }
 	void			setPoolType(U32 type)		{ mPoolType = type; }
 	S32				getTEOffset()				{ return mTEOffset; }
 	LLViewerTexture*	getTexture() const;
 
 	void			setViewerObject(LLViewerObject* object);
 	void			setPool(LLFacePool *pool, LLViewerTexture *texturep);
-	
+	void			setPool(LLFacePool* pool);
+
 	void			setDrawable(LLDrawable *drawable);
 	void			setTEOffset(const S32 te_offset);
 	
@@ -218,6 +218,16 @@ class LLFace
 	void                  removeAtlas() ;
 	BOOL                  switchTexture() ;
 
+	//vertex buffer tracking
+	void setVertexBuffer(LLVertexBuffer* buffer);
+	void clearVertexBuffer(); //sets mVertexBuffer and mLastVertexBuffer to NULL
+	LLVertexBuffer* getVertexBuffer()	const	{ return mVertexBuffer; }
+	U32 getRiggedVertexBufferDataMask() const;
+	S32 getRiggedIndex(U32 type) const;
+	void setRiggedIndex(U32 type, S32 index);
+
+	static U32 getRiggedDataMask(U32 type);
+
 public: //aligned members
 	LLVector4a		mExtents[2];
 
@@ -235,8 +245,6 @@ class LLFace
 	
 	LLVector2		mTexExtents[2];
 	F32				mDistance;
-	LLPointer<LLVertexBuffer> mVertexBuffer;
-	LLPointer<LLVertexBuffer> mLastVertexBuffer;
 	F32			mLastUpdateTime;
 	F32			mLastSkinTime;
 	F32			mLastMoveTime;
@@ -244,10 +252,9 @@ class LLFace
 	LLDrawInfo* mDrawInfo;
 
 private:
-	friend class LLGeometryManager;
-	friend class LLVolumeGeometryManager;
-	friend class LLDrawPoolAvatar;
-
+	LLPointer<LLVertexBuffer> mVertexBuffer;
+	LLPointer<LLVertexBuffer> mLastVertexBuffer;
+	
 	U32			mState;
 	LLFacePool*	mDrawPoolp;
 	U32			mPoolType;
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 14775f0f213..5e7af6bbb3e 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -1486,8 +1486,7 @@ void LLSpatialGroup::destroyGL()
 		for (S32 j = 0; j < drawable->getNumFaces(); j++)
 		{
 			LLFace* facep = drawable->getFace(j);
-			facep->mVertexBuffer = NULL;
-			facep->mLastVertexBuffer = NULL;
+			facep->clearVertexBuffer();
 		}
 	}
 }
@@ -2433,7 +2432,9 @@ void pushVerts(LLSpatialGroup* group, U32 mask)
 
 void pushVerts(LLFace* face, U32 mask)
 {
-	LLVertexBuffer* buffer = face->mVertexBuffer;
+	llassert(face->verify());
+
+	LLVertexBuffer* buffer = face->getVertexBuffer();
 
 	if (buffer)
 	{
@@ -2580,7 +2581,7 @@ void renderOctree(LLSpatialGroup* group)
 				for (S32 j = 0; j < drawable->getNumFaces(); j++)
 				{
 					LLFace* face = drawable->getFace(j);
-					if (face->mVertexBuffer.notNull())
+					if (face->getVertexBuffer())
 					{
 						if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f)
 						{
@@ -2595,10 +2596,10 @@ void renderOctree(LLSpatialGroup* group)
 							continue;
 						}
 
-						face->mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX);
+						face->getVertexBuffer()->setBuffer(LLVertexBuffer::MAP_VERTEX);
 						//drawBox((face->mExtents[0] + face->mExtents[1])*0.5f,
 						//		(face->mExtents[1]-face->mExtents[0])*0.5f);
-						face->mVertexBuffer->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart());
+						face->getVertexBuffer()->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart());
 					}
 				}
 
@@ -3374,7 +3375,7 @@ void renderPhysicsShapes(LLSpatialGroup* group)
 				for (S32 i = 0; i < drawable->getNumFaces(); ++i)
 				{
 					LLFace* face = drawable->getFace(i);
-					LLVertexBuffer* buff = face->mVertexBuffer;
+					LLVertexBuffer* buff = face->getVertexBuffer();
 					if (buff)
 					{
 						glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
diff --git a/indra/newview/llsprite.cpp b/indra/newview/llsprite.cpp
index a69592b61c4..4bde2dfcab5 100644
--- a/indra/newview/llsprite.cpp
+++ b/indra/newview/llsprite.cpp
@@ -186,14 +186,15 @@ void LLSprite::updateFace(LLFace &face)
 	U16 index_offset;
 
 	// Setup face
-	if (face.mVertexBuffer.isNull())
+	if (!face.getVertexBuffer())
 	{	
-		face.mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | 
+		LLVertexBuffer* buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | 
 												LLVertexBuffer::MAP_TEXCOORD0,
 												GL_STREAM_DRAW_ARB);
-		face.mVertexBuffer->allocateBuffer(4, 12, TRUE);
+		buff->allocateBuffer(4, 12, TRUE);
 		face.setGeomIndex(0);
 		face.setIndicesIndex(0);
+		face.setVertexBuffer(buff);
 	}
 		
 	index_offset = face.getGeometry(verticesp,normalsp,tex_coordsp, indicesp);
@@ -242,7 +243,7 @@ void LLSprite::updateFace(LLFace &face)
 		*indicesp++ = 3 + index_offset;
 	}
 
-	face.mVertexBuffer->setBuffer(0);
+	face.getVertexBuffer()->setBuffer(0);
 	face.mCenterAgent = mPosition;
 }
 
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index aa6da5c9f39..77c8bb03294 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -511,7 +511,7 @@ int compare_int(const void *a, const void *b)
 U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
 {
 	if (!mValid || !mMesh || !mFace || !mVisible || 
-		mFace->mVertexBuffer.isNull() ||
+		!mFace->getVertexBuffer() ||
 		mMesh->getNumFaces() == 0) 
 	{
 		return 0;
@@ -582,7 +582,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
 		gGL.getTexUnit(diffuse_channel)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT));
 	}
 	
-	mFace->mVertexBuffer->setBuffer(sRenderMask);
+	mFace->getVertexBuffer()->setBuffer(sRenderMask);
 
 	U32 start = mMesh->mFaceVertexOffset;
 	U32 end = start + mMesh->mFaceVertexCount - 1;
@@ -599,14 +599,14 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
 			}
 		}
 		
-		mFace->mVertexBuffer->drawRange(LLRender::TRIANGLES, start, end, count, offset);
+		mFace->getVertexBuffer()->drawRange(LLRender::TRIANGLES, start, end, count, offset);
 	}
 	else
 	{
 		glPushMatrix();
 		LLMatrix4 jointToWorld = getWorldMatrix();
 		glMultMatrixf((GLfloat*)jointToWorld.mMatrix);
-		mFace->mVertexBuffer->drawRange(LLRender::TRIANGLES, start, end, count, offset);
+		mFace->getVertexBuffer()->drawRange(LLRender::TRIANGLES, start, end, count, offset);
 		glPopMatrix();
 	}
 	gPipeline.addTrianglesDrawn(count);
@@ -661,7 +661,7 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w
 
 	mFace = face;
 
-	if (mFace->mVertexBuffer.isNull())
+	if (!mFace->getVertexBuffer())
 	{
 		return;
 	}
@@ -693,7 +693,7 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w
 		if (num_verts)
 		{
 			face->getGeometryAvatar(verticesp, normalsp, tex_coordsp, vertex_weightsp, clothing_weightsp);
-			face->mVertexBuffer->getIndexStrider(indicesp);
+			face->getVertexBuffer()->getIndexStrider(indicesp);
 
 			verticesp += mMesh->mFaceVertexOffset;
 			normalsp += mMesh->mFaceVertexOffset;
@@ -758,7 +758,7 @@ void LLViewerJointMesh::updateGeometryOriginal(LLFace *mFace, LLPolyMesh *mMesh)
 	LLStrider<LLVector3> o_normals;
 
 	//get vertex and normal striders
-	LLVertexBuffer* buffer = mFace->mVertexBuffer;
+	LLVertexBuffer* buffer = mFace->getVertexBuffer();
 	buffer->getVertexStrider(o_vertices,  0);
 	buffer->getNormalStrider(o_normals,   0);
 
@@ -869,7 +869,7 @@ void LLViewerJointMesh::updateJointGeometry()
 		  && mMesh
 		  && mFace
 		  && mMesh->hasWeights()
-		  && mFace->mVertexBuffer.notNull()
+		  && mFace->getVertexBuffer()
 		  && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) == 0))
 	{
 		return;
diff --git a/indra/newview/llviewerjointmesh_sse.cpp b/indra/newview/llviewerjointmesh_sse.cpp
index e3b40f6943b..400b49d0460 100644
--- a/indra/newview/llviewerjointmesh_sse.cpp
+++ b/indra/newview/llviewerjointmesh_sse.cpp
@@ -83,7 +83,7 @@ void LLViewerJointMesh::updateGeometrySSE(LLFace *face, LLPolyMesh *mesh)
 	LLStrider<LLVector3> o_vertices;
 	LLStrider<LLVector3> o_normals;
 
-	LLVertexBuffer *buffer = face->mVertexBuffer;
+	LLVertexBuffer *buffer = face->getVertexBuffer();
 	buffer->getVertexStrider(o_vertices,  mesh->mFaceVertexOffset);
 	buffer->getNormalStrider(o_normals,   mesh->mFaceVertexOffset);
 
diff --git a/indra/newview/llviewerjointmesh_sse2.cpp b/indra/newview/llviewerjointmesh_sse2.cpp
index 5871823dde7..c2296dd5696 100644
--- a/indra/newview/llviewerjointmesh_sse2.cpp
+++ b/indra/newview/llviewerjointmesh_sse2.cpp
@@ -90,7 +90,7 @@ void LLViewerJointMesh::updateGeometrySSE2(LLFace *face, LLPolyMesh *mesh)
 	LLStrider<LLVector3> o_vertices;
 	LLStrider<LLVector3> o_normals;
 
-	LLVertexBuffer *buffer = face->mVertexBuffer;
+	LLVertexBuffer *buffer = face->getVertexBuffer();
 	buffer->getVertexStrider(o_vertices,  mesh->mFaceVertexOffset);
 	buffer->getNormalStrider(o_normals,   mesh->mFaceVertexOffset);
 
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index e982df1c92e..aa7349f1297 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2016,26 +2016,29 @@ void LLVOAvatar::updateMeshData()
 
 			bool terse_update = false;
 
-			if(facep->mVertexBuffer.isNull())
+			facep->setGeomIndex(0);
+			facep->setIndicesIndex(0);
+		
+			LLVertexBuffer* buff = facep->getVertexBuffer();
+			if(!facep->getVertexBuffer())
 			{
-				facep->mVertexBuffer = new LLVertexBufferAvatar();
-				facep->mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE);
+				buff = new LLVertexBufferAvatar();
+				buff->allocateBuffer(num_vertices, num_indices, TRUE);
+				facep->setVertexBuffer(buff);
 			}
 			else
 			{
-				if (facep->mVertexBuffer->getRequestedIndices() == num_indices &&
-					facep->mVertexBuffer->getRequestedVerts() == num_vertices)
+				if (buff->getRequestedIndices() == num_indices &&
+					buff->getRequestedVerts() == num_vertices)
 				{
 					terse_update = true;
 				}
 				else
 				{
-				facep->mVertexBuffer->resizeBuffer(num_vertices, num_indices) ;
-			}
+					buff->resizeBuffer(num_vertices, num_indices);
+				}
 			}
-		
-			facep->setGeomIndex(0);
-			facep->setIndicesIndex(0);
+			
 		
 			// This is a hack! Avatars have their own pool, so we are detecting
 			//   the case of more than one avatar in the pool (thus > 0 instead of >= 0)
@@ -2050,7 +2053,7 @@ void LLVOAvatar::updateMeshData()
 			}
 
 			stop_glerror();
-			facep->mVertexBuffer->setBuffer(0);
+			buff->setBuffer(0);
 
 			if(!f_num)
 			{
@@ -4006,7 +4009,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
 
 	LLFace* face = mDrawable->getFace(0);
 
-	bool needs_rebuild = !face || face->mVertexBuffer.isNull() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY);
+	bool needs_rebuild = !face || !face->getVertexBuffer() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY);
 
 	if (needs_rebuild || mDirtyMesh)
 	{	//LOD changed or new mesh created, allocate new vertex buffer if needed
@@ -4041,7 +4044,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
 			mNeedsSkin = FALSE;
 			mLastSkinTime = gFrameTimeSeconds;
 
-			LLVertexBuffer* vb = mDrawable->getFace(0)->mVertexBuffer;
+			LLVertexBuffer* vb = mDrawable->getFace(0)->getVertexBuffer();
 			if (vb)
 			{
 				vb->setBuffer(0);
@@ -8150,7 +8153,7 @@ BOOL LLVOAvatar::updateLOD()
 	BOOL res = updateJointLODs();
 
 	LLFace* facep = mDrawable->getFace(0);
-	if (facep->mVertexBuffer.isNull())
+	if (!facep->getVertexBuffer())
 	{
 		dirtyMesh(2);
 	}
diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp
index edd41089c01..32822e11816 100644
--- a/indra/newview/llvograss.cpp
+++ b/indra/newview/llvograss.cpp
@@ -453,7 +453,7 @@ void LLVOGrass::plantBlades()
 	face->setTexture(getTEImage(0));
 	face->setState(LLFace::GLOBAL);
 	face->setSize(mNumBlades * 8, mNumBlades * 12);
-	face->mVertexBuffer = NULL;
+	face->setVertexBuffer(NULL);
 	face->setTEOffset(0);
 	face->mCenterLocal = mPosition + mRegionp->getOriginAgent();
 	
diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp
index f032ae8780e..ce256fdedf4 100644
--- a/indra/newview/llvoground.cpp
+++ b/indra/newview/llvoground.cpp
@@ -97,13 +97,14 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable)
 		drawable->addFace(poolp, NULL);
 	face = drawable->getFace(0); 
 		
-	if (face->mVertexBuffer.isNull())
+	if (!face->getVertexBuffer())
 	{
 		face->setSize(5, 12);
-		face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolGround::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
-		face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
+		LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolGround::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
+		buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
 		face->setGeomIndex(0);
 		face->setIndicesIndex(0);
+		face->setVertexBuffer(buff);
 	}
 	
 	index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
@@ -161,7 +162,7 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable)
 	*(texCoordsp++) = LLVector2(0.f, 1.f);
 	*(texCoordsp++) = LLVector2(0.5f, 0.5f);
 	
-	face->mVertexBuffer->setBuffer(0);
+	face->getVertexBuffer()->setBuffer(0);
 	LLPipeline::sCompiles++;
 	return TRUE;
 }
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index f762f04d8e0..6f354b78b1e 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -463,7 +463,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
 		LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject();
 		facep->setGeomIndex(vertex_count);
 		facep->setIndicesIndex(index_count);
-		facep->mVertexBuffer = buffer;
+		facep->setVertexBuffer(buffer);
 		facep->setPoolType(LLDrawPool::POOL_ALPHA);
 		object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp);
 		
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 80f43e51d20..288d335e1d7 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -1182,7 +1182,7 @@ BOOL LLVOSky::updateSky()
 		}
 	}
 
-	if (mDrawable.notNull() && mDrawable->getFace(0) && mDrawable->getFace(0)->mVertexBuffer.isNull())
+	if (mDrawable.notNull() && mDrawable->getFace(0) && !mDrawable->getFace(0)->getVertexBuffer())
 	{
 		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
 	}
@@ -1233,10 +1233,11 @@ void LLVOSky::createDummyVertexBuffer()
 		mFace[FACE_DUMMY] = mDrawable->addFace(poolp, NULL);
 	}
 
-	if(mFace[FACE_DUMMY]->mVertexBuffer.isNull())
+	if(!mFace[FACE_DUMMY]->getVertexBuffer())
 	{
-		mFace[FACE_DUMMY]->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
-		mFace[FACE_DUMMY]->mVertexBuffer->allocateBuffer(1, 1, TRUE);
+		LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
+		buff->allocateBuffer(1, 1, TRUE);
+		mFace[FACE_DUMMY]->setVertexBuffer(buff);
 	}
 }
 
@@ -1255,13 +1256,13 @@ void LLVOSky::updateDummyVertexBuffer()
 
 	LLFastTimer t(FTM_RENDER_FAKE_VBO_UPDATE) ;
 
-	if(!mFace[FACE_DUMMY] || mFace[FACE_DUMMY]->mVertexBuffer.isNull())
+	if(!mFace[FACE_DUMMY] || !mFace[FACE_DUMMY]->getVertexBuffer())
 		createDummyVertexBuffer() ;
 
 	LLStrider<LLVector3> vertices ;
-	mFace[FACE_DUMMY]->mVertexBuffer->getVertexStrider(vertices,  0);
+	mFace[FACE_DUMMY]->getVertexBuffer()->getVertexStrider(vertices,  0);
 	*vertices = mCameraPosAgent ;
-	mFace[FACE_DUMMY]->mVertexBuffer->setBuffer(0) ;
+	mFace[FACE_DUMMY]->getVertexBuffer()->setBuffer(0) ;
 }
 //----------------------------------
 //end of fake vertex buffer updating
@@ -1304,14 +1305,15 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
 	{
 		face = mFace[FACE_SIDE0 + side]; 
 
-		if (face->mVertexBuffer.isNull())
+		if (!face->getVertexBuffer())
 		{
 			face->setSize(4, 6);
 			face->setGeomIndex(0);
 			face->setIndicesIndex(0);
-			face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
-			face->mVertexBuffer->allocateBuffer(4, 6, TRUE);
-			
+			LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
+			buff->allocateBuffer(4, 6, TRUE);
+			face->setVertexBuffer(buff);
+
 			index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
 			
 			S32 vtx = 0;
@@ -1344,7 +1346,7 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
 			*indicesp++ = index_offset + 3;
 			*indicesp++ = index_offset + 2;
 
-			face->mVertexBuffer->setBuffer(0);
+			buff->setBuffer(0);
 		}
 	}
 
@@ -1471,13 +1473,14 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons
 
 	facep = mFace[f]; 
 
-	if (facep->mVertexBuffer.isNull())
+	if (!facep->getVertexBuffer())
 	{
-		facep->setSize(4, 6);		
-		facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
-		facep->mVertexBuffer->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount(), TRUE);
+		facep->setSize(4, 6);	
+		LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
+		buff->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount(), TRUE);
 		facep->setGeomIndex(0);
 		facep->setIndicesIndex(0);
+		facep->setVertexBuffer(buff);
 	}
 
 	index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
@@ -1506,7 +1509,7 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons
 	*indicesp++ = index_offset + 2;
 	*indicesp++ = index_offset + 3;
 
-	facep->mVertexBuffer->setBuffer(0);
+	facep->getVertexBuffer()->setBuffer(0);
 
 	if (is_sun)
 	{
@@ -1875,13 +1878,14 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
 
 	LLFace *face = mFace[FACE_REFLECTION]; 
 
-	if (face->mVertexBuffer.isNull() || quads*4 != face->getGeomCount())
+	if (!face->getVertexBuffer() || quads*4 != face->getGeomCount())
 	{
 		face->setSize(quads * 4, quads * 6);
-		face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
-		face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
+		LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
+		buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
 		face->setIndicesIndex(0);
 		face->setGeomIndex(0);
+		face->setVertexBuffer(buff);
 	}
 	
 	LLStrider<LLVector3> verticesp;
@@ -2019,7 +2023,7 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
 		}
 	}
 
-	face->mVertexBuffer->setBuffer(0);
+	face->getVertexBuffer()->setBuffer(0);
 }
 
 
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index 690530939ed..dbcd4f50cad 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -890,7 +890,7 @@ void LLVOSurfacePatch::dirtyGeom()
 	if (mDrawable)
 	{
 		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
-		mDrawable->getFace(0)->mVertexBuffer = NULL;
+		mDrawable->getFace(0)->setVertexBuffer(NULL);
 		mDrawable->movePartition();
 	}
 }
@@ -1119,7 +1119,7 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group)
 
 		facep->setIndicesIndex(indices_index);
 		facep->setGeomIndex(index_offset);
-		facep->mVertexBuffer = buffer;
+		facep->setVertexBuffer(buffer);
 
 		LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject();
 		patchp->getGeometry(vertices, normals, colors, texcoords, texcoords2, indices);
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 1b5aed804f3..e6f2b19e070 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -525,11 +525,11 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
 	if(mTrunkLOD >= sMAX_NUM_TREE_LOD_LEVELS) //do not display the tree.
 	{
 		mReferenceBuffer = NULL ;
-		mDrawable->getFace(0)->mVertexBuffer = NULL ;
+		mDrawable->getFace(0)->setVertexBuffer(NULL);
 		return TRUE ;
 	}
 
-	if (mReferenceBuffer.isNull() || mDrawable->getFace(0)->mVertexBuffer.isNull())
+	if (mReferenceBuffer.isNull() || !mDrawable->getFace(0)->getVertexBuffer())
 	{
 		const F32 SRR3 = 0.577350269f; // sqrt(1/3)
 		const F32 SRR2 = 0.707106781f; // sqrt(1/2)
@@ -863,7 +863,7 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
 
 	if (gSavedSettings.getBOOL("RenderAnimateTrees"))
 	{
-		mDrawable->getFace(0)->mVertexBuffer = mReferenceBuffer;
+		mDrawable->getFace(0)->setVertexBuffer(mReferenceBuffer);
 	}
 	else
 	{
@@ -921,8 +921,9 @@ void LLVOTree::updateMesh()
 	calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches);
 
 	LLFace* facep = mDrawable->getFace(0);
-	facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
-	facep->mVertexBuffer->allocateBuffer(vert_count, index_count, TRUE);
+	LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
+	buff->allocateBuffer(vert_count, index_count, TRUE);
+	facep->setVertexBuffer(buff);
 	
 	LLStrider<LLVector3> vertices;
 	LLStrider<LLVector3> normals;
@@ -930,16 +931,15 @@ void LLVOTree::updateMesh()
 	LLStrider<U16> indices;
 	U16 idx_offset = 0;
 
-	facep->mVertexBuffer->getVertexStrider(vertices);
-	facep->mVertexBuffer->getNormalStrider(normals);
-	facep->mVertexBuffer->getTexCoord0Strider(tex_coords);
-	facep->mVertexBuffer->getIndexStrider(indices);
+	buff->getVertexStrider(vertices);
+	buff->getNormalStrider(normals);
+	buff->getTexCoord0Strider(tex_coords);
+	buff->getIndexStrider(indices);
 
 	genBranchPipeline(vertices, normals, tex_coords, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha);
 	
 	mReferenceBuffer->setBuffer(0);
-	facep->mVertexBuffer->setBuffer(0);
-
+	buff->setBuffer(0);
 }
 
 void LLVOTree::appendMesh(LLStrider<LLVector3>& vertices, 
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 132e50904a5..66263412ec5 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3689,7 +3689,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 		(type == LLRenderPass::PASS_INVISIBLE) ||
 		(type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT));
 	
-	if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL))
+	if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_NORMAL))
 	{
 		llwarns << "Non fullbright face has no normals!" << llendl;
 		return;
@@ -3723,13 +3723,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 
 	U8 glow = (U8) (facep->getTextureEntry()->getGlow() * 255);
 
-	if (facep->mVertexBuffer.isNull())
-	{
-		llerrs << "WTF?" << llendl;
-	}
-
 	if (idx >= 0 && 
-		draw_vec[idx]->mVertexBuffer == facep->mVertexBuffer &&
+		draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() &&
 		draw_vec[idx]->mEnd == facep->getGeomIndex()-1 &&
 		(LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex) &&
 #if LL_DARWIN
@@ -3756,7 +3751,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 		U32 offset = facep->getIndicesStart();
 		U32 count = facep->getIndicesCount();
 		LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset, tex, 
-			facep->mVertexBuffer, fullbright, bump); 
+			facep->getVertexBuffer(), fullbright, bump); 
 		draw_info->mGroup = group;
 		draw_info->mVSize = facep->getVirtualSize();
 		draw_vec.push_back(draw_info);
@@ -3896,16 +3891,22 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 		//for each face
 		for (S32 i = 0; i < drawablep->getNumFaces(); i++)
 		{
+			LLFace* facep = drawablep->getFace(i);
+
+			//ALWAYS null out vertex buffer on rebuild -- if the face lands in a render
+			// batch, it will recover its vertex buffer reference from the spatial group
+			facep->setVertexBuffer(NULL);
+			
 			//sum up face verts and indices
 			drawablep->updateFaceSize(i);
-			LLFace* facep = drawablep->getFace(i);
+			
+			
 
 			if (rigged) 
 			{
 				if (!facep->isState(LLFace::RIGGED))
-				{
-					facep->mVertexBuffer = NULL;
-					facep->mLastVertexBuffer = NULL;
+				{ //completely reset vertex buffer
+					facep->clearVertexBuffer();
 				}
 		
 				facep->setState(LLFace::RIGGED);
@@ -4063,14 +4064,13 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 			if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0)
 			{
-				facep->mVertexBuffer = NULL;
-				facep->mLastVertexBuffer = NULL;
+				facep->clearVertexBuffer();
 				continue;
 			}
 
 			cur_total += facep->getGeomCount();
 
-			if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA)
+			if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA)
 			{
 				const LLTextureEntry* te = facep->getTextureEntry();
 				LLViewerTexture* tex = facep->getTexture();
@@ -4083,7 +4083,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 					}
 				}
 
-				BOOL force_simple = (facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA);
+				BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA);
 				U32 type = gPipeline.getPoolTypeFromTE(te, tex);
 				if (type != LLDrawPool::POOL_ALPHA && force_simple)
 				{
@@ -4169,8 +4169,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 			}
 			else
 			{	//face has no renderable geometry
-				facep->mVertexBuffer = NULL;
-				facep->mLastVertexBuffer = NULL;
+				facep->clearVertexBuffer();
 			}		
 		}
 
@@ -4251,7 +4250,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 				for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
 				{
 					LLFace* face = drawablep->getFace(i);
-					if (face && face->mVertexBuffer.notNull())
+					if (face && face->getVertexBuffer())
 					{
 						face->getGeometryVolume(*volume, face->getTEOffset(), 
 							vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex());
@@ -4303,9 +4302,10 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 				for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
 				{
 					LLFace* face = drawablep->getFace(i);
-					if (face && face->mVertexBuffer.notNull() && face->mVertexBuffer->isLocked())
+					LLVertexBuffer* buff = face->getVertexBuffer();
+					if (face && buff && buff->isLocked())
 					{
-						face->mVertexBuffer->setBuffer(0) ;
+						buff->setBuffer(0) ;
 					}
 				}
 			} 
@@ -4375,7 +4375,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 		U32 index_count = facep->getIndicesCount();
 		U32 geom_count = facep->getGeomCount();
 
-		//sum up vertices needed for this texture
+		//sum up vertices needed for this render batch
 		std::vector<LLFace*>::iterator i = face_iter;
 		++i;
 		
@@ -4385,7 +4385,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 			facep = *i;
 			
 			if (geom_count + facep->getGeomCount() > max_vertices)
-			{ //cut vertex buffers on geom count too big
+			{ //cut batches on geom count too big
 				break;
 			}
 
@@ -4413,7 +4413,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 			buffer->allocateBuffer(geom_count, index_count, TRUE);
 		}
 		else 
-		{
+		{ //resize pre-existing buffer
 			if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage)
 			{
 				buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, 
@@ -4434,15 +4434,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 		U16 index_offset = 0;
 
 		while (face_iter < i)
-		{
+		{ //update face indices for new buffer
 			facep = *face_iter;
-			facep->mIndicesIndex = indices_index;
-			facep->mGeomIndex = index_offset;
-			facep->mVertexBuffer = buffer;
+			facep->setIndicesIndex(indices_index);
+			facep->setGeomIndex(index_offset);
+			facep->setVertexBuffer(buffer);	
+			
 			{
+				//for debugging, set last time face was updated vs moved
 				facep->updateRebuildFlags();
+
 				if (!LLPipeline::sDelayVBUpdate)
-				{
+				{ //copy face geometry into vertex buffer
 					LLDrawable* drawablep = facep->getDrawable();
 					LLVOVolume* vobj = drawablep->getVOVolume();
 					LLVolume* volume = vobj->getVolume();
@@ -4459,9 +4462,12 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 			}
 
 			index_offset += facep->getGeomCount();
-			indices_index += facep->mIndicesCount;
+			indices_index += facep->getIndicesCount();
+
+
+			//append face to appropriate render batch
 
-			BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA;
+			BOOL force_simple = facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA;
 			BOOL fullbright = facep->isState(LLFace::FULLBRIGHT);
 			if ((mask & LLVertexBuffer::MAP_NORMAL) == 0)
 			{ //paranoia check to make sure GL doesn't try to read non-existant normals
@@ -4628,7 +4634,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun
 			//sum up face verts and indices
 			drawablep->updateFaceSize(i);
 			LLFace* facep = drawablep->getFace(i);
-			if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA)
+			if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA)
 			{
 				vertex_count += facep->getGeomCount();
 				index_count += facep->getIndicesCount();
@@ -4638,8 +4644,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun
 			}
 			else
 			{
-				facep->mVertexBuffer = NULL;
-				facep->mLastVertexBuffer = NULL;
+				facep->clearVertexBuffer();
 			}
 		}
 	}
diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp
index 77875859e99..69ebad61ac4 100644
--- a/indra/newview/llvowater.cpp
+++ b/indra/newview/llvowater.cpp
@@ -166,16 +166,18 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
 	face->setSize(vertices_per_quad * num_quads,
 				  indices_per_quad * num_quads);
 	
-	if (face->mVertexBuffer.isNull())
+	LLVertexBuffer* buff = face->getVertexBuffer();
+	if (!buff)
 	{
-		face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
-		face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
+		buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
+		buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE);
 		face->setIndicesIndex(0);
 		face->setGeomIndex(0);
+		face->setVertexBuffer(buff);
 	}
 	else
 	{
-		face->mVertexBuffer->resizeBuffer(face->getGeomCount(), face->getIndicesCount());
+		buff->resizeBuffer(face->getGeomCount(), face->getIndicesCount());
 	}
 		
 	index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
@@ -229,7 +231,7 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
 		}
 	}
 	
-	face->mVertexBuffer->setBuffer(0);
+	buff->setBuffer(0);
 
 	mDrawable->movePartition();
 	LLPipeline::sCompiles++;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index b29e32f1d8f..73cd60e2f5e 100755
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -5786,8 +5786,7 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
 	for (S32 i = 0; i < drawable->getNumFaces(); i++)
 	{
 		LLFace* facep = drawable->getFace(i);
-		facep->mVertexBuffer = NULL;
-		facep->mLastVertexBuffer = NULL;
+		facep->clearVertexBuffer();
 	}
 }
 
-- 
GitLab