PageRenderTime 186ms CodeModel.GetById 20ms app.highlight 153ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llrender/llvertexbuffer.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2254 lines | 1845 code | 307 blank | 102 comment | 357 complexity | 0dbb5096932ea519ba0cd541fb4619fa MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/** 
   2 * @file llvertexbuffer.cpp
   3 * @brief LLVertexBuffer implementation
   4 *
   5 * $LicenseInfo:firstyear=2003&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#include "linden_common.h"
  28
  29#include <boost/static_assert.hpp>
  30#include "llsys.h"
  31#include "llvertexbuffer.h"
  32// #include "llrender.h"
  33#include "llglheaders.h"
  34#include "llmemtype.h"
  35#include "llrender.h"
  36#include "llvector4a.h"
  37#include "llshadermgr.h"
  38#include "llglslshader.h"
  39#include "llmemory.h"
  40
  41//Next Highest Power Of Two
  42//helper function, returns first number > v that is a power of 2, or v if v is already a power of 2
  43U32 nhpo2(U32 v)
  44{
  45	U32 r = 1;
  46	while (r < v) {
  47		r *= 2;
  48	}
  49	return r;
  50}
  51
  52
  53//============================================================================
  54
  55//static
  56LLVBOPool LLVertexBuffer::sStreamVBOPool;
  57LLVBOPool LLVertexBuffer::sDynamicVBOPool;
  58LLVBOPool LLVertexBuffer::sStreamIBOPool;
  59LLVBOPool LLVertexBuffer::sDynamicIBOPool;
  60U32 LLVBOPool::sBytesPooled = 0;
  61
  62LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL ;
  63U32 LLVertexBuffer::sBindCount = 0;
  64U32 LLVertexBuffer::sSetCount = 0;
  65S32 LLVertexBuffer::sCount = 0;
  66S32 LLVertexBuffer::sGLCount = 0;
  67S32 LLVertexBuffer::sMappedCount = 0;
  68BOOL LLVertexBuffer::sDisableVBOMapping = FALSE ;
  69BOOL LLVertexBuffer::sEnableVBOs = TRUE;
  70U32 LLVertexBuffer::sGLRenderBuffer = 0;
  71U32 LLVertexBuffer::sGLRenderArray = 0;
  72U32 LLVertexBuffer::sGLRenderIndices = 0;
  73U32 LLVertexBuffer::sLastMask = 0;
  74BOOL LLVertexBuffer::sVBOActive = FALSE;
  75BOOL LLVertexBuffer::sIBOActive = FALSE;
  76U32 LLVertexBuffer::sAllocatedBytes = 0;
  77BOOL LLVertexBuffer::sMapped = FALSE;
  78BOOL LLVertexBuffer::sUseStreamDraw = TRUE;
  79BOOL LLVertexBuffer::sUseVAO = FALSE;
  80BOOL LLVertexBuffer::sPreferStreamDraw = FALSE;
  81
  82const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000;  //1 ms
  83
  84class LLGLSyncFence : public LLGLFence
  85{
  86public:
  87#ifdef GL_ARB_sync
  88	GLsync mSync;
  89#endif
  90	
  91	LLGLSyncFence()
  92	{
  93#ifdef GL_ARB_sync
  94		mSync = 0;
  95#endif
  96	}
  97
  98	virtual ~LLGLSyncFence()
  99	{
 100#ifdef GL_ARB_sync
 101		if (mSync)
 102		{
 103			glDeleteSync(mSync);
 104		}
 105#endif
 106	}
 107
 108	void placeFence()
 109	{
 110#ifdef GL_ARB_sync
 111		if (mSync)
 112		{
 113			glDeleteSync(mSync);
 114		}
 115		mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
 116#endif
 117	}
 118
 119	void wait()
 120	{
 121#ifdef GL_ARB_sync
 122		if (mSync)
 123		{
 124			while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
 125			{ //track the number of times we've waited here
 126				static S32 waits = 0;
 127				waits++;
 128			}
 129		}
 130#endif
 131	}
 132
 133
 134};
 135
 136
 137//which power of 2 is i?
 138//assumes i is a power of 2 > 0
 139U32 wpo2(U32 i)
 140{
 141	llassert(i > 0);
 142	llassert(nhpo2(i) == i);
 143
 144	U32 r = 0;
 145
 146	while (i >>= 1) ++r;
 147
 148	return r;
 149}
 150
 151U8* LLVBOPool::allocate(U32& name, U32 size)
 152{
 153	llassert(nhpo2(size) == size);
 154
 155	U32 i = wpo2(size);
 156
 157	if (mFreeList.size() <= i)
 158	{
 159		mFreeList.resize(i+1);
 160	}
 161
 162	U8* ret = NULL;
 163
 164	if (mFreeList[i].empty())
 165	{
 166		//make a new buffer
 167		glGenBuffersARB(1, &name);
 168		glBindBufferARB(mType, name);
 169		glBufferDataARB(mType, size, 0, mUsage);
 170		LLVertexBuffer::sAllocatedBytes += size;
 171
 172		if (LLVertexBuffer::sDisableVBOMapping)
 173		{
 174			ret = (U8*) ll_aligned_malloc_16(size);
 175		}
 176		glBindBufferARB(mType, 0);
 177	}
 178	else
 179	{
 180		name = mFreeList[i].front().mGLName;
 181		ret = mFreeList[i].front().mClientData;
 182
 183		sBytesPooled -= size;
 184
 185		mFreeList[i].pop_front();
 186	}
 187
 188	return ret;
 189}
 190
 191void LLVBOPool::release(U32 name, U8* buffer, U32 size)
 192{
 193	llassert(nhpo2(size) == size);
 194
 195	U32 i = wpo2(size);
 196
 197	llassert(mFreeList.size() > i);
 198
 199	Record rec;
 200	rec.mGLName = name;
 201	rec.mClientData = buffer;
 202
 203	sBytesPooled += size;
 204
 205	mFreeList[i].push_back(rec);
 206}
 207
 208void LLVBOPool::cleanup()
 209{
 210	U32 size = 1;
 211
 212	for (U32 i = 0; i < mFreeList.size(); ++i)
 213	{
 214		record_list_t& l = mFreeList[i];
 215
 216		while (!l.empty())
 217		{
 218			Record& r = l.front();
 219
 220			glDeleteBuffersARB(1, &r.mGLName);
 221
 222			if (r.mClientData)
 223			{
 224				ll_aligned_free_16(r.mClientData);
 225			}
 226
 227			l.pop_front();
 228
 229			LLVertexBuffer::sAllocatedBytes -= size;
 230			sBytesPooled -= size;
 231		}
 232
 233		size *= 2;
 234	}
 235}
 236
 237
 238//NOTE: each component must be AT LEAST 4 bytes in size to avoid a performance penalty on AMD hardware
 239S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
 240{
 241	sizeof(LLVector4), // TYPE_VERTEX,
 242	sizeof(LLVector4), // TYPE_NORMAL,
 243	sizeof(LLVector2), // TYPE_TEXCOORD0,
 244	sizeof(LLVector2), // TYPE_TEXCOORD1,
 245	sizeof(LLVector2), // TYPE_TEXCOORD2,
 246	sizeof(LLVector2), // TYPE_TEXCOORD3,
 247	sizeof(LLColor4U), // TYPE_COLOR,
 248	sizeof(LLColor4U), // TYPE_EMISSIVE, only alpha is used currently
 249	sizeof(LLVector4), // TYPE_BINORMAL,
 250	sizeof(F32),	   // TYPE_WEIGHT,
 251	sizeof(LLVector4), // TYPE_WEIGHT4,
 252	sizeof(LLVector4), // TYPE_CLOTHWEIGHT,
 253	sizeof(LLVector4), // TYPE_TEXTURE_INDEX (actually exists as position.w), no extra data, but stride is 16 bytes
 254};
 255
 256U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] = 
 257{
 258	GL_TRIANGLES,
 259	GL_TRIANGLE_STRIP,
 260	GL_TRIANGLE_FAN,
 261	GL_POINTS,
 262	GL_LINES,
 263	GL_LINE_STRIP,
 264	GL_QUADS,
 265	GL_LINE_LOOP,
 266};
 267
 268
 269//static
 270void LLVertexBuffer::setupClientArrays(U32 data_mask)
 271{
 272	if (sLastMask != data_mask)
 273	{
 274		BOOL error = FALSE;
 275
 276		if (LLGLSLShader::sNoFixedFunction)
 277		{
 278			for (U32 i = 0; i < TYPE_MAX; ++i)
 279			{
 280				S32 loc = i;
 281										
 282				U32 mask = 1 << i;
 283
 284				if (sLastMask & (1 << i))
 285				{ //was enabled
 286					if (!(data_mask & mask))
 287					{ //needs to be disabled
 288						glDisableVertexAttribArrayARB(loc);
 289					}
 290				}
 291				else 
 292				{	//was disabled
 293					if (data_mask & mask)
 294					{ //needs to be enabled
 295						glEnableVertexAttribArrayARB(loc);
 296					}
 297				}
 298			}
 299		}
 300		else
 301		{
 302
 303			GLenum array[] =
 304			{
 305				GL_VERTEX_ARRAY,
 306				GL_NORMAL_ARRAY,
 307				GL_TEXTURE_COORD_ARRAY,
 308				GL_COLOR_ARRAY,
 309			};
 310
 311			GLenum mask[] = 
 312			{
 313				MAP_VERTEX,
 314				MAP_NORMAL,
 315				MAP_TEXCOORD0,
 316				MAP_COLOR
 317			};
 318
 319
 320
 321			for (U32 i = 0; i < 4; ++i)
 322			{
 323				if (sLastMask & mask[i])
 324				{ //was enabled
 325					if (!(data_mask & mask[i]))
 326					{ //needs to be disabled
 327						glDisableClientState(array[i]);
 328					}
 329					else if (gDebugGL)
 330					{ //needs to be enabled, make sure it was (DEBUG)
 331						if (!glIsEnabled(array[i]))
 332						{
 333							if (gDebugSession)
 334							{
 335								error = TRUE;
 336								gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl;
 337							}
 338							else
 339							{
 340								llerrs << "Bad client state! " << array[i] << " disabled." << llendl;
 341							}
 342						}
 343					}
 344				}
 345				else 
 346				{	//was disabled
 347					if (data_mask & mask[i])
 348					{ //needs to be enabled
 349						glEnableClientState(array[i]);
 350					}
 351					else if (gDebugGL && glIsEnabled(array[i]))
 352					{ //needs to be disabled, make sure it was (DEBUG TEMPORARY)
 353						if (gDebugSession)
 354						{
 355							error = TRUE;
 356							gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl;
 357						}
 358						else
 359						{
 360							llerrs << "Bad client state! " << array[i] << " enabled." << llendl;
 361						}
 362					}
 363				}
 364			}
 365		
 366			U32 map_tc[] = 
 367			{
 368				MAP_TEXCOORD1,
 369				MAP_TEXCOORD2,
 370				MAP_TEXCOORD3
 371			};
 372
 373			for (U32 i = 0; i < 3; i++)
 374			{
 375				if (sLastMask & map_tc[i])
 376				{
 377					if (!(data_mask & map_tc[i]))
 378					{ //disable
 379						glClientActiveTextureARB(GL_TEXTURE1_ARB+i);
 380						glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 381						glClientActiveTextureARB(GL_TEXTURE0_ARB);
 382					}
 383				}
 384				else if (data_mask & map_tc[i])
 385				{
 386					glClientActiveTextureARB(GL_TEXTURE1_ARB+i);
 387					glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 388					glClientActiveTextureARB(GL_TEXTURE0_ARB);
 389				}
 390			}
 391
 392			if (sLastMask & MAP_BINORMAL)
 393			{
 394				if (!(data_mask & MAP_BINORMAL))
 395				{
 396					glClientActiveTextureARB(GL_TEXTURE2_ARB);
 397					glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 398					glClientActiveTextureARB(GL_TEXTURE0_ARB);
 399				}
 400			}
 401			else if (data_mask & MAP_BINORMAL)
 402			{
 403				glClientActiveTextureARB(GL_TEXTURE2_ARB);
 404				glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 405				glClientActiveTextureARB(GL_TEXTURE0_ARB);
 406			}
 407		}
 408				
 409		sLastMask = data_mask;
 410	}
 411}
 412
 413//static
 414void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm)
 415{
 416	llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
 417	gGL.syncMatrices();
 418
 419	U32 count = pos.size();
 420	llassert_always(norm.size() >= pos.size());
 421	llassert_always(count > 0) ;
 422
 423	unbind();
 424	
 425	setupClientArrays(MAP_VERTEX | MAP_NORMAL);
 426
 427	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
 428
 429	if (shader)
 430	{
 431		S32 loc = LLVertexBuffer::TYPE_VERTEX;
 432		if (loc > -1)
 433		{
 434			glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, pos[0].mV);
 435		}
 436		loc = LLVertexBuffer::TYPE_NORMAL;
 437		if (loc > -1)
 438		{
 439			glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 0, norm[0].mV);
 440		}
 441	}
 442	else
 443	{
 444		glVertexPointer(3, GL_FLOAT, 0, pos[0].mV);
 445		glNormalPointer(GL_FLOAT, 0, norm[0].mV);
 446	}
 447
 448	glDrawArrays(sGLMode[mode], 0, count);
 449}
 450
 451//static
 452void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp)
 453{
 454	llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
 455
 456	gGL.syncMatrices();
 457
 458	U32 mask = LLVertexBuffer::MAP_VERTEX;
 459	if (tc)
 460	{
 461		mask = mask | LLVertexBuffer::MAP_TEXCOORD0;
 462	}
 463
 464	unbind();
 465	
 466	setupClientArrays(mask);
 467
 468	if (LLGLSLShader::sNoFixedFunction)
 469	{
 470		S32 loc = LLVertexBuffer::TYPE_VERTEX;
 471		glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, 16, pos);
 472
 473		if (tc)
 474		{
 475			loc = LLVertexBuffer::TYPE_TEXCOORD0;
 476			glVertexAttribPointerARB(loc, 2, GL_FLOAT, GL_FALSE, 0, tc);
 477		}
 478	}
 479	else
 480	{
 481		glTexCoordPointer(2, GL_FLOAT, 0, tc);
 482		glVertexPointer(3, GL_FLOAT, 16, pos);
 483	}
 484
 485	glDrawElements(sGLMode[mode], num_indices, GL_UNSIGNED_SHORT, indicesp);
 486}
 487
 488void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const
 489{
 490	if (start >= (U32) mNumVerts ||
 491	    end >= (U32) mNumVerts)
 492	{
 493		llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mNumVerts << llendl;
 494	}
 495
 496	llassert(mNumIndices >= 0);
 497
 498	if (indices_offset >= (U32) mNumIndices ||
 499	    indices_offset + count > (U32) mNumIndices)
 500	{
 501		llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
 502	}
 503
 504	if (gDebugGL && !useVBOs())
 505	{
 506		U16* idx = ((U16*) getIndicesPointer())+indices_offset;
 507		for (U32 i = 0; i < count; ++i)
 508		{
 509			if (idx[i] < start || idx[i] > end)
 510			{
 511				llerrs << "Index out of range: " << idx[i] << " not in [" << start << ", " << end << "]" << llendl;
 512			}
 513		}
 514
 515		LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
 516
 517		if (shader && shader->mFeatures.mIndexedTextureChannels > 1)
 518		{
 519			LLStrider<LLVector4a> v;
 520			//hack to get non-const reference
 521			LLVertexBuffer* vb = (LLVertexBuffer*) this;
 522			vb->getVertexStrider(v);
 523
 524			for (U32 i = start; i < end; i++)
 525			{
 526				S32 idx = (S32) (v[i][3]+0.25f);
 527				if (idx < 0 || idx >= shader->mFeatures.mIndexedTextureChannels)
 528				{
 529					llerrs << "Bad texture index found in vertex data stream." << llendl;
 530				}
 531			}
 532		}
 533	}
 534}
 535
 536void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
 537{
 538	validateRange(start, end, count, indices_offset);
 539
 540	gGL.syncMatrices();
 541
 542	llassert(mNumVerts >= 0);
 543	llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
 544
 545	if (mGLArray)
 546	{
 547		if (mGLArray != sGLRenderArray)
 548		{
 549			llerrs << "Wrong vertex array bound." << llendl;
 550		}
 551	}
 552	else
 553	{
 554		if (mGLIndices != sGLRenderIndices)
 555		{
 556			llerrs << "Wrong index buffer bound." << llendl;
 557		}
 558
 559		if (mGLBuffer != sGLRenderBuffer)
 560		{
 561			llerrs << "Wrong vertex buffer bound." << llendl;
 562		}
 563	}
 564
 565	if (gDebugGL && !mGLArray && useVBOs())
 566	{
 567		GLint elem = 0;
 568		glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
 569
 570		if (elem != mGLIndices)
 571		{
 572			llerrs << "Wrong index buffer bound!" << llendl;
 573		}
 574	}
 575
 576	if (mode >= LLRender::NUM_MODES)
 577	{
 578		llerrs << "Invalid draw mode: " << mode << llendl;
 579		return;
 580	}
 581
 582	U16* idx = ((U16*) getIndicesPointer())+indices_offset;
 583
 584	stop_glerror();
 585	glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, 
 586		idx);
 587	stop_glerror();
 588	placeFence();
 589}
 590
 591void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
 592{
 593	llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
 594
 595	gGL.syncMatrices();
 596
 597	llassert(mNumIndices >= 0);
 598	if (indices_offset >= (U32) mNumIndices ||
 599	    indices_offset + count > (U32) mNumIndices)
 600	{
 601		llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
 602	}
 603
 604	if (mGLArray)
 605	{
 606		if (mGLArray != sGLRenderArray)
 607		{
 608			llerrs << "Wrong vertex array bound." << llendl;
 609		}
 610	}
 611	else
 612	{
 613		if (mGLIndices != sGLRenderIndices)
 614		{
 615			llerrs << "Wrong index buffer bound." << llendl;
 616		}
 617
 618		if (mGLBuffer != sGLRenderBuffer)
 619		{
 620			llerrs << "Wrong vertex buffer bound." << llendl;
 621		}
 622	}
 623
 624	if (mode >= LLRender::NUM_MODES)
 625	{
 626		llerrs << "Invalid draw mode: " << mode << llendl;
 627		return;
 628	}
 629
 630	stop_glerror();
 631	glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
 632		((U16*) getIndicesPointer()) + indices_offset);
 633	stop_glerror();
 634	placeFence();
 635}
 636
 637void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
 638{
 639	llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
 640	
 641	gGL.syncMatrices();
 642	
 643	llassert(mNumVerts >= 0);
 644	if (first >= (U32) mNumVerts ||
 645	    first + count > (U32) mNumVerts)
 646	{
 647		llerrs << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl;
 648	}
 649
 650	if (mGLArray)
 651	{
 652		if (mGLArray != sGLRenderArray)
 653		{
 654			llerrs << "Wrong vertex array bound." << llendl;
 655		}
 656	}
 657	else
 658	{
 659		if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive)
 660		{
 661			llerrs << "Wrong vertex buffer bound." << llendl;
 662		}
 663	}
 664
 665	if (mode >= LLRender::NUM_MODES)
 666	{
 667		llerrs << "Invalid draw mode: " << mode << llendl;
 668		return;
 669	}
 670
 671	stop_glerror();
 672	glDrawArrays(sGLMode[mode], first, count);
 673	stop_glerror();
 674	placeFence();
 675}
 676
 677//static
 678void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
 679{
 680	sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject ;
 681	sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ;
 682
 683	if(!sPrivatePoolp)
 684	{ 
 685		sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC) ;
 686	}
 687
 688	sStreamVBOPool.mType = GL_ARRAY_BUFFER_ARB;
 689	sStreamVBOPool.mUsage= GL_STREAM_DRAW_ARB;
 690	sStreamIBOPool.mType = GL_ELEMENT_ARRAY_BUFFER_ARB;
 691	sStreamIBOPool.mUsage= GL_STREAM_DRAW_ARB;
 692
 693	sDynamicVBOPool.mType = GL_ARRAY_BUFFER_ARB;
 694	sDynamicVBOPool.mUsage= GL_DYNAMIC_DRAW_ARB;
 695	sDynamicIBOPool.mType = GL_ELEMENT_ARRAY_BUFFER_ARB;
 696	sDynamicIBOPool.mUsage= GL_DYNAMIC_DRAW_ARB;
 697}
 698
 699//static 
 700void LLVertexBuffer::unbind()
 701{
 702	if (sGLRenderArray)
 703	{
 704#if GL_ARB_vertex_array_object
 705		glBindVertexArray(0);
 706#endif
 707		sGLRenderArray = 0;
 708		sGLRenderIndices = 0;
 709		sIBOActive = FALSE;
 710	}
 711
 712	if (sVBOActive)
 713	{
 714		glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
 715		sVBOActive = FALSE;
 716	}
 717	if (sIBOActive)
 718	{
 719		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
 720		sIBOActive = FALSE;
 721	}
 722
 723	sGLRenderBuffer = 0;
 724	sGLRenderIndices = 0;
 725
 726	setupClientArrays(0);
 727}
 728
 729//static
 730void LLVertexBuffer::cleanupClass()
 731{
 732	LLMemType mt2(LLMemType::MTYPE_VERTEX_CLEANUP_CLASS);
 733	unbind();
 734	
 735	sStreamIBOPool.cleanup();
 736	sDynamicIBOPool.cleanup();
 737	sStreamVBOPool.cleanup();
 738	sDynamicVBOPool.cleanup();
 739
 740	if(sPrivatePoolp)
 741	{
 742		LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp) ;
 743		sPrivatePoolp = NULL ;
 744	}
 745}
 746
 747//----------------------------------------------------------------------------
 748
 749LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
 750	LLRefCount(),
 751
 752	mNumVerts(0),
 753	mNumIndices(0),
 754	mUsage(usage),
 755	mGLBuffer(0),
 756	mGLArray(0),
 757	mGLIndices(0), 
 758	mMappedData(NULL),
 759	mMappedIndexData(NULL), 
 760	mVertexLocked(FALSE),
 761	mIndexLocked(FALSE),
 762	mFinal(FALSE),
 763	mEmpty(TRUE),
 764	mFence(NULL)
 765{
 766	LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
 767	mFence = NULL;
 768	if (!sEnableVBOs)
 769	{
 770		mUsage = 0 ; 
 771	}
 772
 773	if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
 774	{
 775		mUsage = 0;
 776	}
 777	
 778	if (mUsage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw)
 779	{
 780		mUsage = GL_STREAM_DRAW_ARB;
 781	}
 782
 783	if (mUsage == 0 && LLRender::sGLCoreProfile)
 784	{ //MUST use VBOs for all rendering
 785		mUsage = GL_STREAM_DRAW_ARB;
 786	}
 787
 788	if (mUsage && mUsage != GL_STREAM_DRAW_ARB)
 789	{ //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default
 790		mUsage = GL_DYNAMIC_DRAW_ARB;
 791	}
 792		
 793	//zero out offsets
 794	for (U32 i = 0; i < TYPE_MAX; i++)
 795	{
 796		mOffsets[i] = 0;
 797	}
 798
 799	mTypeMask = typemask;
 800	mSize = 0;
 801	mIndicesSize = 0;
 802	mAlignedOffset = 0;
 803	mAlignedIndexOffset = 0;
 804
 805	sCount++;
 806}
 807
 808//static
 809S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices)
 810{
 811	S32 offset = 0;
 812	for (S32 i=0; i<TYPE_TEXTURE_INDEX; i++)
 813	{
 814		U32 mask = 1<<i;
 815		if (typemask & mask)
 816		{
 817			if (offsets && LLVertexBuffer::sTypeSize[i])
 818			{
 819				offsets[i] = offset;
 820				offset += LLVertexBuffer::sTypeSize[i]*num_vertices;
 821				offset = (offset + 0xF) & ~0xF;
 822			}
 823		}
 824	}
 825
 826	offsets[TYPE_TEXTURE_INDEX] = offsets[TYPE_VERTEX] + 12;
 827	
 828	return offset+16;
 829}
 830
 831//static 
 832S32 LLVertexBuffer::calcVertexSize(const U32& typemask)
 833{
 834	S32 size = 0;
 835	for (S32 i = 0; i < TYPE_TEXTURE_INDEX; i++)
 836	{
 837		U32 mask = 1<<i;
 838		if (typemask & mask)
 839		{
 840			size += LLVertexBuffer::sTypeSize[i];
 841		}
 842	}
 843
 844	return size;
 845}
 846
 847S32 LLVertexBuffer::getSize() const
 848{
 849	return mSize;
 850}
 851
 852// protected, use unref()
 853//virtual
 854LLVertexBuffer::~LLVertexBuffer()
 855{
 856	LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTRUCTOR);
 857	destroyGLBuffer();
 858	destroyGLIndices();
 859
 860	if (mGLArray)
 861	{
 862#if GL_ARB_vertex_array_object
 863		glDeleteVertexArrays(1, &mGLArray);
 864#endif
 865	}
 866
 867	sCount--;
 868
 869	if (mFence)
 870	{
 871		delete mFence;
 872	}
 873	
 874	mFence = NULL;
 875
 876	llassert_always(!mMappedData && !mMappedIndexData) ;
 877};
 878
 879void LLVertexBuffer::placeFence() const
 880{
 881	/*if (!mFence && useVBOs())
 882	{
 883		if (gGLManager.mHasSync)
 884		{
 885			mFence = new LLGLSyncFence();
 886		}
 887	}
 888
 889	if (mFence)
 890	{
 891		mFence->placeFence();
 892	}*/
 893}
 894
 895void LLVertexBuffer::waitFence() const
 896{
 897	/*if (mFence)
 898	{
 899		mFence->wait();
 900	}*/
 901}
 902
 903//----------------------------------------------------------------------------
 904
 905void LLVertexBuffer::genBuffer(U32 size)
 906{
 907	mSize = nhpo2(size);
 908
 909	if (mUsage == GL_STREAM_DRAW_ARB)
 910	{
 911		mMappedData = sStreamVBOPool.allocate(mGLBuffer, mSize);
 912	}
 913	else
 914	{
 915		mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize);
 916	}
 917	
 918	sGLCount++;
 919}
 920
 921void LLVertexBuffer::genIndices(U32 size)
 922{
 923	mIndicesSize = nhpo2(size);
 924
 925	if (mUsage == GL_STREAM_DRAW_ARB)
 926	{
 927		mMappedIndexData = sStreamIBOPool.allocate(mGLIndices, mIndicesSize);
 928	}
 929	else
 930	{
 931		mMappedIndexData = sDynamicIBOPool.allocate(mGLIndices, mIndicesSize);
 932	}
 933	
 934	sGLCount++;
 935}
 936
 937void LLVertexBuffer::releaseBuffer()
 938{
 939	if (mUsage == GL_STREAM_DRAW_ARB)
 940	{
 941		sStreamVBOPool.release(mGLBuffer, mMappedData, mSize);
 942	}
 943	else
 944	{
 945		sDynamicVBOPool.release(mGLBuffer, mMappedData, mSize);
 946	}
 947	
 948	mGLBuffer = 0;
 949	mMappedData = NULL;
 950
 951	sGLCount--;
 952}
 953
 954void LLVertexBuffer::releaseIndices()
 955{
 956	if (mUsage == GL_STREAM_DRAW_ARB)
 957	{
 958		sStreamIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
 959	}
 960	else
 961	{
 962		sDynamicIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
 963	}
 964
 965	mGLIndices = 0;
 966	mMappedIndexData = NULL;
 967	
 968	sGLCount--;
 969}
 970
 971void LLVertexBuffer::createGLBuffer(U32 size)
 972{
 973	LLMemType mt2(LLMemType::MTYPE_VERTEX_CREATE_VERTICES);
 974	
 975	if (mGLBuffer)
 976	{
 977		destroyGLBuffer();
 978	}
 979
 980	if (size == 0)
 981	{
 982		return;
 983	}
 984
 985	mEmpty = TRUE;
 986
 987	if (useVBOs())
 988	{
 989		genBuffer(size);
 990	}
 991	else
 992	{
 993		static int gl_buffer_idx = 0;
 994		mGLBuffer = ++gl_buffer_idx;
 995		mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
 996		mSize = size;
 997	}
 998}
 999
1000void LLVertexBuffer::createGLIndices(U32 size)
1001{
1002	LLMemType mt2(LLMemType::MTYPE_VERTEX_CREATE_INDICES);
1003	
1004	if (mGLIndices)
1005	{
1006		destroyGLIndices();
1007	}
1008	
1009	if (size == 0)
1010	{
1011		return;
1012	}
1013
1014	mEmpty = TRUE;
1015
1016	//pad by 16 bytes for aligned copies
1017	size += 16;
1018
1019	if (useVBOs())
1020	{
1021		//pad by another 16 bytes for VBO pointer adjustment
1022		size += 16;
1023		genIndices(size);
1024	}
1025	else
1026	{
1027		mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
1028		static int gl_buffer_idx = 0;
1029		mGLIndices = ++gl_buffer_idx;
1030		mIndicesSize = size;
1031	}
1032}
1033
1034void LLVertexBuffer::destroyGLBuffer()
1035{
1036	LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_BUFFER);
1037	if (mGLBuffer)
1038	{
1039		if (useVBOs())
1040		{
1041			releaseBuffer();
1042		}
1043		else
1044		{
1045			FREE_MEM(sPrivatePoolp, mMappedData) ;
1046			mMappedData = NULL;
1047			mEmpty = TRUE;
1048		}
1049	}
1050	
1051	mGLBuffer = 0;
1052	//unbind();
1053}
1054
1055void LLVertexBuffer::destroyGLIndices()
1056{
1057	LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_INDICES);
1058	if (mGLIndices)
1059	{
1060		if (useVBOs())
1061		{
1062			releaseIndices();
1063		}
1064		else
1065		{
1066			FREE_MEM(sPrivatePoolp, mMappedIndexData) ;
1067			mMappedIndexData = NULL;
1068			mEmpty = TRUE;
1069		}
1070	}
1071
1072	mGLIndices = 0;
1073	//unbind();
1074}
1075
1076void LLVertexBuffer::updateNumVerts(S32 nverts)
1077{
1078	LLMemType mt2(LLMemType::MTYPE_VERTEX_UPDATE_VERTS);
1079
1080	llassert(nverts >= 0);
1081
1082	if (nverts >= 65535)
1083	{
1084		llwarns << "Vertex buffer overflow!" << llendl;
1085		nverts = 65535;
1086	}
1087
1088	U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts);
1089
1090	if (needed_size > mSize || needed_size <= mSize/2)
1091	{
1092		createGLBuffer(needed_size);
1093	}
1094
1095	mNumVerts = nverts;
1096}
1097
1098void LLVertexBuffer::updateNumIndices(S32 nindices)
1099{
1100	LLMemType mt2(LLMemType::MTYPE_VERTEX_UPDATE_INDICES);
1101
1102	llassert(nindices >= 0);
1103
1104	U32 needed_size = sizeof(U16) * nindices;
1105
1106	if (needed_size > mIndicesSize || needed_size <= mIndicesSize/2)
1107	{
1108		createGLIndices(needed_size);
1109	}
1110
1111	mNumIndices = nindices;
1112}
1113
1114void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
1115{
1116	LLMemType mt2(LLMemType::MTYPE_VERTEX_ALLOCATE_BUFFER);
1117	
1118	stop_glerror();
1119
1120	if (nverts < 0 || nindices < 0 ||
1121		nverts > 65536)
1122	{
1123		llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl;
1124	}
1125
1126	updateNumVerts(nverts);
1127	updateNumIndices(nindices);
1128	
1129	if (create && (nverts || nindices))
1130	{
1131		//actually allocate space for the vertex buffer if using VBO mapping
1132		flush();
1133
1134		if (gGLManager.mHasVertexArrayObject && useVBOs() && (LLRender::sGLCoreProfile || sUseVAO))
1135		{
1136#if GL_ARB_vertex_array_object
1137			glGenVertexArrays(1, &mGLArray);
1138#endif
1139			setupVertexArray();
1140		}
1141	}
1142}
1143
1144static LLFastTimer::DeclareTimer FTM_SETUP_VERTEX_ARRAY("Setup VAO");
1145
1146void LLVertexBuffer::setupVertexArray()
1147{
1148	if (!mGLArray)
1149	{
1150		return;
1151	}
1152
1153	LLFastTimer t(FTM_SETUP_VERTEX_ARRAY);
1154#if GL_ARB_vertex_array_object
1155	glBindVertexArray(mGLArray);
1156#endif
1157	sGLRenderArray = mGLArray;
1158
1159	U32 attrib_size[] = 
1160	{
1161		3, //TYPE_VERTEX,
1162		3, //TYPE_NORMAL,
1163		2, //TYPE_TEXCOORD0,
1164		2, //TYPE_TEXCOORD1,
1165		2, //TYPE_TEXCOORD2,
1166		2, //TYPE_TEXCOORD3,
1167		4, //TYPE_COLOR,
1168		4, //TYPE_EMISSIVE,
1169		3, //TYPE_BINORMAL,
1170		1, //TYPE_WEIGHT,
1171		4, //TYPE_WEIGHT4,
1172		4, //TYPE_CLOTHWEIGHT,
1173		1, //TYPE_TEXTURE_INDEX
1174	};
1175
1176	U32 attrib_type[] =
1177	{
1178		GL_FLOAT, //TYPE_VERTEX,
1179		GL_FLOAT, //TYPE_NORMAL,
1180		GL_FLOAT, //TYPE_TEXCOORD0,
1181		GL_FLOAT, //TYPE_TEXCOORD1,
1182		GL_FLOAT, //TYPE_TEXCOORD2,
1183		GL_FLOAT, //TYPE_TEXCOORD3,
1184		GL_UNSIGNED_BYTE, //TYPE_COLOR,
1185		GL_UNSIGNED_BYTE, //TYPE_EMISSIVE,
1186		GL_FLOAT,   //TYPE_BINORMAL,
1187		GL_FLOAT, //TYPE_WEIGHT,
1188		GL_FLOAT, //TYPE_WEIGHT4,
1189		GL_FLOAT, //TYPE_CLOTHWEIGHT,
1190		GL_FLOAT, //TYPE_TEXTURE_INDEX
1191	};
1192
1193	U32 attrib_normalized[] =
1194	{
1195		GL_FALSE, //TYPE_VERTEX,
1196		GL_FALSE, //TYPE_NORMAL,
1197		GL_FALSE, //TYPE_TEXCOORD0,
1198		GL_FALSE, //TYPE_TEXCOORD1,
1199		GL_FALSE, //TYPE_TEXCOORD2,
1200		GL_FALSE, //TYPE_TEXCOORD3,
1201		GL_TRUE, //TYPE_COLOR,
1202		GL_TRUE, //TYPE_EMISSIVE,
1203		GL_FALSE,   //TYPE_BINORMAL,
1204		GL_FALSE, //TYPE_WEIGHT,
1205		GL_FALSE, //TYPE_WEIGHT4,
1206		GL_FALSE, //TYPE_CLOTHWEIGHT,
1207		GL_FALSE, //TYPE_TEXTURE_INDEX
1208	};
1209
1210	bindGLBuffer(true);
1211	bindGLIndices(true);
1212
1213	for (U32 i = 0; i < TYPE_MAX; ++i)
1214	{
1215		if (mTypeMask & (1 << i))
1216		{
1217			glEnableVertexAttribArrayARB(i);
1218			glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], (void*) mOffsets[i]); 
1219		}
1220		else
1221		{
1222			glDisableVertexAttribArrayARB(i);
1223		}
1224	}
1225
1226	//draw a dummy triangle to set index array pointer
1227	//glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, NULL);
1228
1229	unbind();
1230}
1231
1232void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
1233{
1234	llassert(newnverts >= 0);
1235	llassert(newnindices >= 0);
1236
1237	LLMemType mt2(LLMemType::MTYPE_VERTEX_RESIZE_BUFFER);
1238	
1239	updateNumVerts(newnverts);		
1240	updateNumIndices(newnindices);
1241	
1242	if (useVBOs())
1243	{
1244		flush();
1245
1246		if (mGLArray)
1247		{ //if size changed, offsets changed
1248			setupVertexArray();
1249		}
1250	}
1251}
1252
1253BOOL LLVertexBuffer::useVBOs() const
1254{
1255	//it's generally ineffective to use VBO for things that are streaming on apple
1256		
1257	if (!mUsage)
1258	{
1259		return FALSE;
1260	}
1261
1262	return TRUE;
1263}
1264
1265//----------------------------------------------------------------------------
1266
1267bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
1268{
1269	S32 end = index+count;
1270	S32 region_end = region.mIndex+region.mCount;
1271	
1272	if (end < region.mIndex ||
1273		index > region_end)
1274	{ //gap exists, do not merge
1275		return false;
1276	}
1277
1278	S32 new_end = llmax(end, region_end);
1279	S32 new_index = llmin(index, region.mIndex);
1280	region.mIndex = new_index;
1281	region.mCount = new_end-new_index;
1282	return true;
1283}
1284
1285// Map for data access
1286U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
1287{
1288	bindGLBuffer(true);
1289	LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
1290	if (mFinal)
1291	{
1292		llerrs << "LLVertexBuffer::mapVeretxBuffer() called on a finalized buffer." << llendl;
1293	}
1294	if (!useVBOs() && !mMappedData && !mMappedIndexData)
1295	{
1296		llerrs << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << llendl;
1297	}
1298		
1299	if (useVBOs())
1300	{
1301		if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
1302		{
1303			if (count == -1)
1304			{
1305				count = mNumVerts-index;
1306			}
1307
1308			bool mapped = false;
1309			//see if range is already mapped
1310			for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
1311			{
1312				MappedRegion& region = mMappedVertexRegions[i];
1313				if (region.mType == type)
1314				{
1315					if (expand_region(region, index, count))
1316					{
1317						mapped = true;
1318						break;
1319					}
1320				}
1321			}
1322
1323			if (!mapped)
1324			{
1325				//not already mapped, map new region
1326				MappedRegion region(type, !sDisableVBOMapping && map_range ? -1 : index, count);
1327				mMappedVertexRegions.push_back(region);
1328			}
1329		}
1330
1331		if (mVertexLocked && map_range)
1332		{
1333			llerrs << "Attempted to map a specific range of a buffer that was already mapped." << llendl;
1334		}
1335
1336		if (!mVertexLocked)
1337		{
1338			LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
1339			mVertexLocked = TRUE;
1340			sMappedCount++;
1341			stop_glerror();	
1342
1343			if(sDisableVBOMapping)
1344			{
1345				map_range = false;
1346			}
1347			else
1348			{
1349				U8* src = NULL;
1350				waitFence();
1351				if (gGLManager.mHasMapBufferRange)
1352				{
1353					if (map_range)
1354					{
1355#ifdef GL_ARB_map_buffer_range
1356						S32 offset = mOffsets[type] + sTypeSize[type]*index;
1357						S32 length = (sTypeSize[type]*count+0xF) & ~0xF;
1358						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, 
1359							GL_MAP_WRITE_BIT | 
1360							GL_MAP_FLUSH_EXPLICIT_BIT | 
1361							GL_MAP_INVALIDATE_RANGE_BIT);
1362#endif
1363					}
1364					else
1365					{
1366#ifdef GL_ARB_map_buffer_range
1367
1368						if (gDebugGL)
1369						{
1370							GLint size = 0;
1371							glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
1372
1373							if (size < mSize)
1374							{
1375								llerrs << "Invalid buffer size." << llendl;
1376							}
1377						}
1378
1379						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, 
1380							GL_MAP_WRITE_BIT | 
1381							GL_MAP_FLUSH_EXPLICIT_BIT);
1382#endif
1383					}
1384				}
1385				else if (gGLManager.mHasFlushBufferRange)
1386				{
1387					if (map_range)
1388					{
1389						glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
1390						glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
1391						src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1392					}
1393					else
1394					{
1395						src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1396					}
1397				}
1398				else
1399				{
1400					map_range = false;
1401					src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1402				}
1403
1404				llassert(src != NULL);
1405
1406				mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
1407				mAlignedOffset = mMappedData - src;
1408			
1409				stop_glerror();
1410			}
1411				
1412			if (!mMappedData)
1413			{
1414				log_glerror();
1415
1416			//check the availability of memory
1417			LLMemory::logMemoryInfo(TRUE) ; 
1418			
1419				if(!sDisableVBOMapping)
1420				{			
1421					//--------------------
1422					//print out more debug info before crash
1423					llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
1424					GLint size ;
1425					glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ;
1426					llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ;
1427					//--------------------
1428
1429					GLint buff;
1430					glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
1431					if ((GLuint)buff != mGLBuffer)
1432					{
1433						llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
1434					}
1435
1436							
1437					llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
1438				}
1439				else
1440				{
1441					llerrs << "memory allocation for vertex data failed." << llendl ;
1442				}
1443			}
1444		}
1445	}
1446	else
1447	{
1448		map_range = false;
1449	}
1450	
1451	if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping)
1452	{
1453		return mMappedData;
1454	}
1455	else
1456	{
1457		return mMappedData+mOffsets[type]+sTypeSize[type]*index;
1458	}
1459}
1460
1461U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
1462{
1463	LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
1464	bindGLIndices(true);
1465	if (mFinal)
1466	{
1467		llerrs << "LLVertexBuffer::mapIndexBuffer() called on a finalized buffer." << llendl;
1468	}
1469	if (!useVBOs() && !mMappedData && !mMappedIndexData)
1470	{
1471		llerrs << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << llendl;
1472	}
1473
1474	if (useVBOs())
1475	{
1476		if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
1477		{
1478			if (count == -1)
1479			{
1480				count = mNumIndices-index;
1481			}
1482
1483			bool mapped = false;
1484			//see if range is already mapped
1485			for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
1486			{
1487				MappedRegion& region = mMappedIndexRegions[i];
1488				if (expand_region(region, index, count))
1489				{
1490					mapped = true;
1491					break;
1492				}
1493			}
1494
1495			if (!mapped)
1496			{
1497				//not already mapped, map new region
1498				MappedRegion region(TYPE_INDEX, !sDisableVBOMapping && map_range ? -1 : index, count);
1499				mMappedIndexRegions.push_back(region);
1500			}
1501		}
1502
1503		if (mIndexLocked && map_range)
1504		{
1505			llerrs << "Attempted to map a specific range of a buffer that was already mapped." << llendl;
1506		}
1507
1508		if (!mIndexLocked)
1509		{
1510			LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES);
1511
1512			mIndexLocked = TRUE;
1513			sMappedCount++;
1514			stop_glerror();	
1515
1516			if (gDebugGL && useVBOs())
1517			{
1518				GLint elem = 0;
1519				glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
1520
1521				if (elem != mGLIndices)
1522				{
1523					llerrs << "Wrong index buffer bound!" << llendl;
1524				}
1525			}
1526
1527			if(sDisableVBOMapping)
1528			{
1529				map_range = false;
1530			}
1531			else
1532			{
1533				U8* src = NULL;
1534				waitFence();
1535				if (gGLManager.mHasMapBufferRange)
1536				{
1537					if (map_range)
1538					{
1539#ifdef GL_ARB_map_buffer_range
1540						S32 offset = sizeof(U16)*index;
1541						S32 length = sizeof(U16)*count;
1542						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, 
1543							GL_MAP_WRITE_BIT | 
1544							GL_MAP_FLUSH_EXPLICIT_BIT | 
1545							GL_MAP_INVALIDATE_RANGE_BIT);
1546#endif
1547					}
1548					else
1549					{
1550#ifdef GL_ARB_map_buffer_range
1551						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, 
1552							GL_MAP_WRITE_BIT | 
1553							GL_MAP_FLUSH_EXPLICIT_BIT);
1554#endif
1555					}
1556				}
1557				else if (gGLManager.mHasFlushBufferRange)
1558				{
1559					if (map_range)
1560					{
1561						glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
1562						glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
1563						src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1564					}
1565					else
1566					{
1567						src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1568					}
1569				}
1570				else
1571				{
1572					map_range = false;
1573					src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
1574				}
1575
1576				llassert(src != NULL);
1577
1578
1579				mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src);
1580				mAlignedIndexOffset = mMappedIndexData - src;
1581				stop_glerror();
1582			}
1583		}
1584
1585		if (!mMappedIndexData)
1586		{
1587			log_glerror();
1588			LLMemory::logMemoryInfo(TRUE) ;
1589
1590			if(!sDisableVBOMapping)
1591			{
1592				GLint buff;
1593				glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
1594				if ((GLuint)buff != mGLIndices)
1595				{
1596					llerrs << "Invalid GL index buffer bound: " << buff << llendl;
1597				}
1598
1599				llerrs << "glMapBuffer returned NULL (no index data)" << llendl;
1600			}
1601			else
1602			{
1603				llerrs << "memory allocation for Index data failed. " << llendl ;
1604			}
1605		}
1606	}
1607	else
1608	{
1609		map_range = false;
1610	}
1611
1612	if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping)
1613	{
1614		return mMappedIndexData;
1615	}
1616	else
1617	{
1618		return mMappedIndexData + sizeof(U16)*index;
1619	}
1620}
1621
1622void LLVertexBuffer::unmapBuffer()
1623{
1624	LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER);
1625	if (!useVBOs())
1626	{
1627		return ; //nothing to unmap
1628	}
1629
1630	bool updated_all = false ;
1631
1632	if (mMappedData && mVertexLocked)
1633	{
1634		bindGLBuffer(true);
1635		updated_all = mIndexLocked; //both vertex and index buffers done updating
1636
1637		if(sDisableVBOMapping)
1638		{
1639			if (!mMappedVertexRegions.empty())
1640			{
1641				stop_glerror();
1642				for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
1643				{
1644					const MappedRegion& region = mMappedVertexRegions[i];
1645					S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
1646					S32 length = sTypeSize[region.mType]*region.mCount;
1647					glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, mMappedData+offset);
1648					stop_glerror();
1649				}
1650
1651				mMappedVertexRegions.clear();
1652			}
1653			else
1654			{
1655				stop_glerror();
1656				glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
1657				stop_glerror();
1658			}
1659		}
1660		else
1661		{
1662			if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
1663			{
1664				if (!mMappedVertexRegions.empty())
1665				{
1666					stop_glerror();
1667					for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
1668					{
1669						const MappedRegion& region = mMappedVertexRegions[i];
1670						S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
1671						S32 length = sTypeSize[region.mType]*region.mCount;
1672						if (gGLManager.mHasMapBufferRange)
1673						{
1674#ifdef GL_ARB_map_buffer_range
1675							glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
1676#endif
1677						}
1678						else if (gGLManager.mHasFlushBufferRange)
1679						{
1680							glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER_ARB, offset, length);
1681						}
1682						stop_glerror();
1683					}
1684
1685					mMappedVertexRegions.clear();
1686				}
1687			}
1688			stop_glerror();
1689			glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
1690			stop_glerror();
1691
1692			mMappedData = NULL;
1693		}
1694
1695		mVertexLocked = FALSE ;
1696		sMappedCount--;
1697	}
1698	
1699	if (mMappedIndexData && mIndexLocked)
1700	{
1701		bindGLIndices();
1702		if(sDisableVBOMapping)
1703		{
1704			if (!mMappedIndexRegions.empty())
1705			{
1706				for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
1707				{
1708					const MappedRegion& region = mMappedIndexRegions[i];
1709					S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
1710					S32 length = sizeof(U16)*region.mCount;
1711					glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, mMappedIndexData+offset);
1712					stop_glerror();
1713				}
1714
1715				mMappedIndexRegions.clear();
1716			}
1717			else
1718			{
1719				stop_glerror();
1720				glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
1721				stop_glerror();
1722			}
1723		}
1724		else
1725		{
1726			if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
1727			{
1728				if (!mMappedIndexRegions.empty())
1729				{
1730					for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
1731					{
1732						const MappedRegion& region = mMappedIndexRegions[i];
1733						S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
1734						S32 length = sizeof(U16)*region.mCount;
1735						if (gGLManager.mHasMapBufferRange)
1736						{
1737#ifdef GL_ARB_map_buffer_range
1738							glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
1739#endif
1740						}
1741						else if (gGLManager.mHasFlushBufferRange)
1742						{
1743#ifdef GL_APPLE_flush_buffer_range
1744							glFlushMappedBufferRangeAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
1745#endif
1746						}
1747						stop_glerror();
1748					}
1749
1750					mMappedIndexRegions.clear();
1751				}
1752			}
1753			stop_glerror();
1754			glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
1755			stop_glerror();
1756
1757			mMappedIndexData = NULL ;
1758		}
1759
1760		mIndexLocked = FALSE ;
1761		sMappedCount--;
1762	}
1763
1764	if(updated_all)
1765	{
1766		mEmpty = FALSE;
1767	}
1768}
1769
1770//----------------------------------------------------------------------------
1771
1772template <class T,S32 type> struct VertexBufferStrider
1773{
1774	typedef LLStrider<T> strider_t;
1775	static bool get(LLVertexBuffer& vbo, 
1776					strider_t& strider, 
1777					S32 index, S32 count, bool map_range)
1778	{
1779		if (type == LLVertexBuffer::TYPE_INDEX)
1780		{
1781			U8* ptr = vbo.mapIndexBuffer(index, count, map_range);
1782
1783			if (ptr == NULL)
1784			{
1785				llwarns << "mapIndexBuffer failed!" << llendl;
1786				return FALSE;
1787			}
1788
1789			strider = (T*)ptr;
1790			strider.setStride(0);
1791			return TRUE;
1792		}
1793		else if (vbo.hasDataType(type))
1794		{
1795			S32 stride = LLVertexBuffer::sTypeSize[type];
1796
1797			U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range);
1798
1799			if (ptr == NULL)
1800			{
1801				llwarns << "mapVertexBuffer failed!" << llendl;
1802				return FALSE;
1803			}
1804
1805			strider = (T*)ptr;
1806			strider.setStride(stride);
1807			return TRUE;
1808		}
1809		else
1810		{
1811			llerrs << "VertexBufferStrider could not find valid vertex data." << llendl;
1812		}
1813		return FALSE;
1814	}
1815};
1816
1817bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
1818{
1819	return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index, count, map_range);
1820}
1821bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector4a>& strider, S32 index, S32 count, bool map_range)
1822{
1823	return VertexBufferStrider<LLVector4a,TYPE_VERTEX>::get(*this, strider, index, count, map_range);
1824}
1825bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index, S32 count, bool map_range)
1826{
1827	return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count, map_range);
1828}
1829bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
1830{
1831	return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index, count, map_range);
1832}
1833bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
1834{
1835	return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count, map_range);
1836}
1837
1838bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
1839{
1840	return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count, map_range);
1841}
1842bool LLVertexBuffer::getBinormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
1843{
1844	return VertexBufferStrider<LLVector3,TYPE_BINORMAL>::get(*this, strider, index, count, map_range);
1845}
1846bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index, S32 count, bool map_range)
1847{
1848	return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index, count, map_range);
1849}
1850bool LLVertexBuffer::getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index, S32 count, bool map_range)
1851{
1852	return VertexBufferStrider<LLColor4U,TYPE_EMISSIVE>::get(*this, strider, index, count, map_range);
1853}
1854bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index, S32 count, bool map_range)
1855{
1856	return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count, map_range);
1857}
1858
1859bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
1860{
1861	return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index, count, map_range);
1862}
1863
1864bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
1865{
1866	return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count, map_range);
1867}
1868
1869//----------------------------------------------------------------------------
1870
1871static LLFastTimer::DeclareTimer FTM_BIND_GL_ARRAY("Bind Array");
1872bool LLVertexBuffer::bindGLArray()
1873{
1874	if (mGLArray && sGLRenderArray != mGLArray)
1875	{
1876		{
1877			LLFastTimer t(FTM_BIND_GL_ARRAY);
1878#if GL_ARB_vertex_array_object
1879			glBindVertexArray(mGLArray);
1880#endif
1881			sGLRenderArray = mGLArray;
1882		}
1883
1884		//really shouldn't be necessary, but some drivers don't properly restore the
1885		//state of GL_ELEMENT_ARRAY_BUFFER_BINDING
1886		bindGLIndices();
1887		
1888		return true;
1889	}
1890		
1891	return false;
1892}
1893
1894static LLFastTimer::DeclareTimer FTM_BIND_GL_BUFFER("Bind Buffer");
1895
1896bool LLVertexBuffer::bindGLBuffer(bool force_bind)
1897{
1898	bindGLArray();
1899
1900	bool ret = false;
1901
1902	if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))))
1903	{
1904		LLFastTimer t(FTM_BIND_GL_BUFFER);
1905		/*if (sMapped)
1906		{
1907			llerrs << "VBO bound while another VBO mapped!" << llendl;
1908		}*/
1909		glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
1910		sGLRenderBuffer = mGLBuffer;
1911		sBindCount++;
1912		sVBOActive = TRUE;
1913
1914		if (mGLArray)
1915		{
1916			llassert(sGLRenderArray == mGLArray);
1917			//mCachedRenderBuffer = mGLBuffer;
1918		}
1919
1920		ret = true;
1921	}
1922
1923	return ret;
1924}
1925
1926static LLFastTimer::DeclareTimer FTM_BIND_GL_INDICES("Bind Indices");
1927
1928bool LLVertexBuffer::bindGLIndices(bool force_bind)
1929{
1930	bindGLArray();
1931
1932	bool ret = false;
1933	if (useVBOs() && (force_bind || (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive))))
1934	{
1935		LLFastTimer t(FTM_BIND_GL_INDICES);
1936		/*if (sMapped)
1937		{
1938			llerrs << "VBO bound while another VBO mapped!" << llendl;
1939		}*/
1940		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
1941		sGLRenderIndices = mGLIndices;
1942		stop_glerror();
1943		sBindCount++;
1944		sIBOActive = TRUE;
1945		ret = true;
1946	}
1947
1948	return ret;
1949}
1950
1951void LLVertexBuffer::flush()
1952{
1953	if (useVBOs())
1954	{
1955		unmapBuffer();
1956	}
1957}
1958
1959// Set for rendering
1960void LLVertexBuffer::setBuffer(U32 data_mask)
1961{
1962	flush();
1963
1964	LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_BUFFER);
1965	//set up pointers if the data mask is different ...
1966	BOOL setup = (sLastMask != data_mask);
1967
1968	if (gDebugGL && data_mask != 0)
1969	{ //make sure data requirements are fulfilled
1970		LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
1971		if (shader)
1972		{
1973			U32 required_mask = 0;
1974			for (U32 i = 0; i < LLVertexBuffer::TYPE_TEXTURE_INDEX; ++i)
1975			{
1976				if (shader->getAttribLocation(i) > -1)
1977				{
1978					U32 required = 1 << i;
1979					if ((data_mask & required) == 0)
1980					{
1981						llwarns << "Missing attribute: " << LLShaderMgr::instance()->mReservedAttribs[i] << llendl;
1982					}
1983
1984					required_mask |= required;
1985				}
1986			}
1987
1988			if ((data_mask & required_mask) != required_mask)
1989			{
1990				llerrs << "Shader consumption mismatches data provision." << llendl;
1991			}
1992		}
1993	}
1994
1995	if (useVBOs())
1996	{
1997		if (mGLArray)
1998		{
1999			bindGLArray();
2000			setup = FALSE; //do NOT perform pointer setup if using VAO
2001		}
2002		else
2003		{
2004			if (bindGLBuffer())
2005			{
2006				setup = TRUE;
2007			}
2008			if (bindGLIndices())
2009			{
2010				setup = TRUE;
2011			}
2012		}
2013
2014		BOOL error = FALSE;
2015		if (gDebugGL && !mGLArray)
2016		{
2017			GLint buff;
2018			glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
2019			if ((GLuint)buff != mGLBuffer)
2020			{
2021				if (gDebugSession)
2022				{
2023					error = TRUE;
2024					gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl;
2025				}
2026				else
2027				{
2028					llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
2029				}
2030			}
2031
2032			if (mGLIndices)
2033			{
2034				glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
2035				if ((GLuint)buff != mGLIndices)
2036				{
2037					if (gDebugSession)
2038					{
2039						error = TRUE;
2040						gFailLog << "Invalid GL index buffer bound: " << buff <<  std::endl;
2041					}
2042					else
2043					{
2044						llerrs << "Invalid GL index buffer bound: " << buff << llendl;
2045					}
2046				}
2047			}
2048		}
2049
2050		
2051	}
2052	else
2053	{	
2054		if (sGLRenderArray)
2055		{
2056#if GL_ARB_vertex_array_object
2057			glBindVertexArray(0);
2058#endif
2059			sGLRenderArray = 0;
2060			sGLRenderIndices = 0;
2061			sIBOActive = FALSE;
2062		}
2063
2064		if (mGLBuffer)
2065		{
2066			if (sVBOActive)
2067			{
2068				glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
2069				sBindCount++;
2070				sVBOActive = FALSE;
2071				setup = TRUE; // ... or a VBO is deactivated
2072			}
2073			if (sGLRenderBuffer != mGLBuffer)
2074			{
2075				sGLRenderBuffer = mGLBuffer;
2076				setup = TRUE; // ... or a client memory pointer changed
2077			}
2078		}
2079		if (mGLIndices)
2080		{
2081			if (sIBOActive)
2082			{
2083				glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
2084				sBindCount++;
2085				sIBOActive = FALSE;
2086			}
2087			
2088			sGLRenderIndices = mGLIndices;
2089		}
2090	}
2091
2092	if (!mGLArray)
2093	{
2094		setupClientArrays(data_mask);
2095	}
2096			
2097	if (mGLBuffer)
2098	{
2099		if (data_mask && setup)
2100		{
2101			setupVertexBuffer(data_mask); // subclass specific setup (virtual function)
2102			sSetCount++;
2103		}
2104	}
2105}
2106
2107// virtual (default)
2108void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
2109{
2110	LLMemType mt2(LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER);
2111	stop_glerror();
2112	U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
2113
2114	/*if ((data_mask & mTypeMask) != data_mask)
2115	{
2116		llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl;
2117	}*/
2118
2119	if (LLGLSLShader::sNoFixedFunction)
2120	{
2121		if (data_mask & MAP_NORMAL)
2122		{
2123			S32 loc = TYPE_NORMAL;
2124			void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]);
2125			glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr);
2126		}
2127		if (data_mask & MAP_TEXCOORD3)
2128		{
2129			S32 loc = TYPE_TEXCOORD3;
2130			void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]);
2131			glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr);
2132		}
2133		if (data_mask & MAP_TEXCOORD2)
2134		{
2135			S32 loc = TYPE_TEXCOORD2;
2136			void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]);
2137			glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr);
2138		}
2139		if (data_mask & MAP_TEXCOORD1)
2140		{
2141			S32 loc = TYPE_TEXCOORD1;
2142			void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]);
2143			glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr);
2144		}
2145		if (data_mask & MAP_BINORMAL)
2146		{
2147			S32 loc = TYPE_BINORMAL;
2148			void* ptr = (void*)(base + mOffsets[TYPE_BINORMAL]);
2149			glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], ptr);
2150		}
2151		if (data_mask & MAP_TEXCOORD0)
2152		{
2153			S32 loc = TYPE_TEXCOORD0;
2154			void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]);
2155			glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr);
2156		}
2157		if (data_mask & MAP_COLOR)
2158		{
2159			S32 loc = TYPE_COLOR;
2160			void* ptr = (void*)(base + mOffsets[TYPE_COLOR]);
2161			glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
2162		}
2163		if (data_mask & MAP_EMISSIVE)
2164		{
2165			S32 loc = TYPE_EMISSIVE;
2166			void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);
2167			glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
2168		}
2169		if (data_mask & MAP_WEIGHT)
2170		{
2171			S32 loc = TYPE_WEIGHT;
2172			void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]);
2173			glVertexAttribPointerARB(loc, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
2174		}
2175		if (data_mask & MAP_WEIGHT4)
2176		{
2177			S32 loc = TYPE_WEIGHT4;
2178			void* ptr = (void*)(base+mOffsets[TYPE_WEIGHT4]);
2179			glVertexAttribPointerARB(loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
2180		}
2181		if (data_mask & MAP_CLOTHWEIGHT)
2182		{
2183			S32 loc = TYPE_CLOTHWEIGHT;
2184			void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
2185			glVertexAttribPointerARB(loc, 4, GL_FLOAT, TRUE,  LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
2186		}
2187		if (data_mask & MAP_TEXTURE_INDEX)
2188		{
2189			S32 loc = TYPE_TEXTURE_INDEX;
2190			void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12);
2191			glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
2192		}
2193		if (data_mask & MAP_VERTEX)
2194		{
2195			S32 loc = TYPE_VERTEX;
2196			void* ptr = (void*)(base + mOffsets[TYPE_VERTEX]);
2197			glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr);
2198		}	
2199	}	
2200	else
2201	{
2202		if (data_mask & MAP_NORMAL)
2203		{
2204			glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL]));
2205		}
2206		if (data_mask & MAP_TEXCOORD3)
2207		{
2208			glClientActiveTextureARB(GL_TEXTURE3_ARB);
2209			glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], (void*)(base + mOffsets[TYPE_TEXCOORD3]));
2210			glClientActiveTextureARB(GL_TEXTURE0_ARB);
2211		}
2212		if (data_mask & MAP_TEXCOORD2)
2213		{
2214			glClientActiveTextureARB(GL_TEXTURE2_ARB);
2215			glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], (void*)(base + mOffsets[TYPE_TEXCOORD2]));
2216			glClientActiveTextureARB(GL_TEXTURE0_ARB);
2217		}
2218		if (data_mask & MAP_TEXCOORD1)
2219		{
2220			glClientActiveTextureARB(GL_TEXTURE1_ARB);
2221			glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1]));
2222			glClient

Large files files are truncated, but you can click here to view the full file