Newer
Older
/**
* @file llvertexbuffer.cpp
* @brief LLVertexBuffer implementation
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
#include "linden_common.h"
#include <boost/static_assert.hpp>
#include "llsys.h"
#include "llvertexbuffer.h"
// #include "llrender.h"
#include "llglheaders.h"
#include "llmemtype.h"
#include "llrender.h"
//============================================================================
//static
LLVBOPool LLVertexBuffer::sStreamVBOPool;
LLVBOPool LLVertexBuffer::sDynamicVBOPool;
LLVBOPool LLVertexBuffer::sStreamIBOPool;
LLVBOPool LLVertexBuffer::sDynamicIBOPool;
LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL ;
U32 LLVertexBuffer::sBindCount = 0;
U32 LLVertexBuffer::sSetCount = 0;
S32 LLVertexBuffer::sCount = 0;
S32 LLVertexBuffer::sGLCount = 0;
S32 LLVertexBuffer::sMappedCount = 0;
Xiaohong Bao
committed
BOOL LLVertexBuffer::sDisableVBOMapping = FALSE ;
BOOL LLVertexBuffer::sEnableVBOs = TRUE;
Josh Bell
committed
U32 LLVertexBuffer::sGLRenderBuffer = 0;
U32 LLVertexBuffer::sGLRenderIndices = 0;
U32 LLVertexBuffer::sLastMask = 0;
BOOL LLVertexBuffer::sVBOActive = FALSE;
BOOL LLVertexBuffer::sIBOActive = FALSE;
U32 LLVertexBuffer::sAllocatedBytes = 0;
BOOL LLVertexBuffer::sMapped = FALSE;
BOOL LLVertexBuffer::sUseStreamDraw = TRUE;
std::vector<U32> LLVertexBuffer::sDeleteList;
S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] =
{
sizeof(LLVector3), // TYPE_VERTEX,
sizeof(LLVector3), // TYPE_NORMAL,
sizeof(LLVector2), // TYPE_TEXCOORD0,
sizeof(LLVector2), // TYPE_TEXCOORD1,
sizeof(LLVector2), // TYPE_TEXCOORD2,
sizeof(LLVector2), // TYPE_TEXCOORD3,
sizeof(LLColor4U), // TYPE_COLOR,
sizeof(LLVector3), // TYPE_BINORMAL,
sizeof(F32), // TYPE_WEIGHT,
sizeof(LLVector4), // TYPE_CLOTHWEIGHT,
};
U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =
{
GL_TRIANGLES,
GL_TRIANGLE_STRIP,
GL_TRIANGLE_FAN,
GL_POINTS,
GL_LINES,
GL_LINE_STRIP,
GL_QUADS,
GL_LINE_LOOP,
};
//static
void LLVertexBuffer::setupClientArrays(U32 data_mask)
{
{
llerrs << "Cannot use LLGLImmediate and LLVertexBuffer simultaneously!" << llendl;
if (sLastMask != data_mask)
{
U32 mask[] =
{
MAP_VERTEX,
MAP_NORMAL,
MAP_TEXCOORD0,
MAP_COLOR,
};
GLenum array[] =
{
GL_VERTEX_ARRAY,
GL_NORMAL_ARRAY,
GL_TEXTURE_COORD_ARRAY,
GL_COLOR_ARRAY,
BOOL error = FALSE;
for (U32 i = 0; i < 4; ++i)
{
if (sLastMask & mask[i])
{ //was enabled
if (!(data_mask & mask[i]) && i > 0)
{ //needs to be disabled
glDisableClientState(array[i]);
}
else if (gDebugGL)
{ //needs to be enabled, make sure it was (DEBUG TEMPORARY)
if (i > 0 && !glIsEnabled(array[i]))
{
if (gDebugSession)
{
error = TRUE;
gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl;
}
else
{
llerrs << "Bad client state! " << array[i] << " disabled." << llendl;
}
}
}
}
else
{ //was disabled
if (data_mask & mask[i])
{ //needs to be enabled
glEnableClientState(array[i]);
}
else if (gDebugGL && glIsEnabled(array[i]))
{ //needs to be disabled, make sure it was (DEBUG TEMPORARY)
if (gDebugSession)
{
error = TRUE;
gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl;
}
else
{
llerrs << "Bad client state! " << array[i] << " enabled." << llendl;
}
if (error)
{
ll_fail("LLVertexBuffer::setupClientArrays failed");
}
U32 map_tc[] =
MAP_TEXCOORD1,
MAP_TEXCOORD2,
MAP_TEXCOORD3
};
for (U32 i = 0; i < 3; i++)
{
if (sLastMask & map_tc[i])
if (!(data_mask & map_tc[i]))
{
glClientActiveTextureARB(GL_TEXTURE1_ARB+i);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
}
else if (data_mask & map_tc[i])
{
glClientActiveTextureARB(GL_TEXTURE1_ARB+i);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
}
if (sLastMask & MAP_BINORMAL)
{
if (!(data_mask & MAP_BINORMAL))
{
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
}
else if (data_mask & MAP_BINORMAL)
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
}
sLastMask = data_mask;
}
}
void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
{
if (start >= (U32) mRequestedNumVerts ||
{
llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl;
}
if (indices_offset >= (U32) mRequestedNumIndices ||
{
llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
}
if (mGLIndices != sGLRenderIndices)
{
llerrs << "Wrong index buffer bound." << llendl;
}
if (mGLBuffer != sGLRenderBuffer)
{
llerrs << "Wrong vertex buffer bound." << llendl;
}
{
llerrs << "Invalid draw mode: " << mode << llendl;
stop_glerror();
glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
((U16*) getIndicesPointer()) + indices_offset);
}
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
{
Xiaohong Bao
committed
if (indices_offset >= (U32) mRequestedNumIndices ||
{
llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
}
if (mGLIndices != sGLRenderIndices)
{
llerrs << "Wrong index buffer bound." << llendl;
}
if (mGLBuffer != sGLRenderBuffer)
{
llerrs << "Wrong vertex buffer bound." << llendl;
}
{
llerrs << "Invalid draw mode: " << mode << llendl;
stop_glerror();
glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
((U16*) getIndicesPointer()) + indices_offset);
stop_glerror();
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
{
Xiaohong Bao
committed
{
llerrs << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl;
}
if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive)
{
llerrs << "Wrong vertex buffer bound." << llendl;
}
{
llerrs << "Invalid draw mode: " << mode << llendl;
stop_glerror();
glDrawArrays(sGLMode[mode], first, count);
Xiaohong Bao
committed
void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
{
sEnableVBOs = use_vbo;
Xiaohong Bao
committed
sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ;
LLGLNamePool::registerPool(&sDynamicVBOPool);
LLGLNamePool::registerPool(&sDynamicIBOPool);
LLGLNamePool::registerPool(&sStreamVBOPool);
LLGLNamePool::registerPool(&sStreamIBOPool);
if(!sPrivatePoolp)
{
sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC) ;
}
}
//static
void LLVertexBuffer::unbind()
{
if (sVBOActive)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
sVBOActive = FALSE;
}
if (sIBOActive)
{
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
sIBOActive = FALSE;
}
sGLRenderBuffer = 0;
sGLRenderIndices = 0;
}
//static
void LLVertexBuffer::cleanupClass()
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_CLEANUP_CLASS);
if(sPrivatePoolp)
{
LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp) ;
sPrivatePoolp = NULL ;
}
Josh Bell
committed
void LLVertexBuffer::clientCopy(F64 max_time)
{
if (!sDeleteList.empty())
{
glDeleteBuffersARB(sDeleteList.size(), (GLuint*) &(sDeleteList[0]));
sDeleteList.clear();
}
}
//----------------------------------------------------------------------------
LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
LLRefCount(),
mNumVerts(0),
mNumIndices(0),
mRequestedNumVerts(-1),
mRequestedNumIndices(-1),
mUsage(usage),
mGLBuffer(0),
mGLIndices(0),
Xiaohong Bao
committed
mMappedIndexData(NULL),
mVertexLocked(FALSE),
mIndexLocked(FALSE),
Josh Bell
committed
mFinal(FALSE),
mFilthy(FALSE),
mEmpty(TRUE),
mResized(FALSE),
Xiaohong Bao
committed
mDynamicSize(FALSE)
LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
if (!sEnableVBOs)
{
mUsage = 0 ;
if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
{
mUsage = 0;
}
if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
{
mUsage = 0;
S32 stride = calcStride(typemask, mOffsets);
mTypeMask = typemask;
mStride = stride;
sCount++;
}
//static
S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets)
{
S32 stride = 0;
for (S32 i=0; i<TYPE_MAX; i++)
{
U32 mask = 1<<i;
if (typemask & mask)
{
if (offsets)
{
offsets[i] = stride;
}
stride += sTypeOffsets[i];
}
}
return stride;
}
// protected, use unref()
//virtual
LLVertexBuffer::~LLVertexBuffer()
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTRUCTOR);
destroyGLBuffer();
destroyGLIndices();
sCount--;
Xiaohong Bao
committed
llassert_always(!mMappedData && !mMappedIndexData) ;
};
//----------------------------------------------------------------------------
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
void LLVertexBuffer::genBuffer()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
mGLBuffer = sStreamVBOPool.allocate();
}
else if (mUsage == GL_DYNAMIC_DRAW_ARB)
{
mGLBuffer = sDynamicVBOPool.allocate();
}
else
{
BOOST_STATIC_ASSERT(sizeof(mGLBuffer) == sizeof(GLuint));
glGenBuffersARB(1, (GLuint*)&mGLBuffer);
}
sGLCount++;
}
void LLVertexBuffer::genIndices()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
mGLIndices = sStreamIBOPool.allocate();
}
else if (mUsage == GL_DYNAMIC_DRAW_ARB)
{
mGLIndices = sDynamicIBOPool.allocate();
}
else
{
BOOST_STATIC_ASSERT(sizeof(mGLBuffer) == sizeof(GLuint));
glGenBuffersARB(1, (GLuint*)&mGLIndices);
}
sGLCount++;
}
void LLVertexBuffer::releaseBuffer()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
sStreamVBOPool.release(mGLBuffer);
}
else if (mUsage == GL_DYNAMIC_DRAW_ARB)
{
sDynamicVBOPool.release(mGLBuffer);
}
else
{
sDeleteList.push_back(mGLBuffer);
}
sGLCount--;
}
void LLVertexBuffer::releaseIndices()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
sStreamIBOPool.release(mGLIndices);
}
else if (mUsage == GL_DYNAMIC_DRAW_ARB)
{
sDynamicIBOPool.release(mGLIndices);
}
else
{
sDeleteList.push_back(mGLIndices);
}
sGLCount--;
}
void LLVertexBuffer::createGLBuffer()
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_CREATE_VERTICES);
U32 size = getSize();
if (mGLBuffer)
{
destroyGLBuffer();
}
if (size == 0)
{
return;
}
mEmpty = TRUE;
if (useVBOs())
{
mMappedData = NULL;
genBuffer();
mResized = TRUE;
}
else
{
static int gl_buffer_idx = 0;
mGLBuffer = ++gl_buffer_idx;
mMappedData = (U8*)sPrivatePoolp->allocate(size);
memset(mMappedData, 0, size);
}
}
void LLVertexBuffer::createGLIndices()
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_CREATE_INDICES);
U32 size = getIndicesSize();
if (mGLIndices)
{
destroyGLIndices();
}
if (size == 0)
{
return;
}
mEmpty = TRUE;
if (useVBOs())
{
mMappedIndexData = NULL;
genIndices();
mResized = TRUE;
}
else
{
mMappedIndexData = (U8*)sPrivatePoolp->allocate(size);
memset(mMappedIndexData, 0, size);
static int gl_buffer_idx = 0;
mGLIndices = ++gl_buffer_idx;
}
}
void LLVertexBuffer::destroyGLBuffer()
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_BUFFER);
if (mGLBuffer)
{
if (useVBOs())
{
Xiaohong Bao
committed
freeClientBuffer() ;
if (mMappedData || mMappedIndexData)
{
llerrs << "Vertex buffer destroyed while mapped!" << llendl;
}
releaseBuffer();
}
else
{
sPrivatePoolp->freeMem(mMappedData) ;
mMappedData = NULL;
mEmpty = TRUE;
sAllocatedBytes -= getSize();
}
mGLBuffer = 0;
}
void LLVertexBuffer::destroyGLIndices()
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_INDICES);
if (mGLIndices)
{
if (useVBOs())
{
Xiaohong Bao
committed
freeClientBuffer() ;
if (mMappedData || mMappedIndexData)
{
llerrs << "Vertex buffer destroyed while mapped." << llendl;
}
Xiaohong Bao
committed
releaseIndices();
}
else
{
sPrivatePoolp->freeMem(mMappedIndexData) ;
mMappedIndexData = NULL;
mEmpty = TRUE;
sAllocatedBytes -= getIndicesSize();
}
mGLIndices = 0;
}
void LLVertexBuffer::updateNumVerts(S32 nverts)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_UPDATE_VERTS);
if (nverts >= 65535)
{
llwarns << "Vertex buffer overflow!" << llendl;
nverts = 65535;
}
mRequestedNumVerts = nverts;
if (!mDynamicSize)
{
mNumVerts = nverts;
}
else if (mUsage == GL_STATIC_DRAW_ARB ||
nverts > mNumVerts ||
nverts < mNumVerts/2)
{
if (mUsage != GL_STATIC_DRAW_ARB && nverts + nverts/4 <= 65535)
{
nverts += nverts/4;
}
mNumVerts = nverts;
}
}
void LLVertexBuffer::updateNumIndices(S32 nindices)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_UPDATE_INDICES);
mRequestedNumIndices = nindices;
if (!mDynamicSize)
{
mNumIndices = nindices;
}
else if (mUsage == GL_STATIC_DRAW_ARB ||
nindices > mNumIndices ||
nindices < mNumIndices/2)
{
if (mUsage != GL_STATIC_DRAW_ARB)
{
nindices += nindices/4;
}
mNumIndices = nindices;
}
}
void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_ALLOCATE_BUFFER);
updateNumVerts(nverts);
updateNumIndices(nindices);
if (mMappedData)
{
llerrs << "LLVertexBuffer::allocateBuffer() called redundantly." << llendl;
}
if (create && (nverts || nindices))
{
createGLBuffer();
createGLIndices();
}
sAllocatedBytes += getSize() + getIndicesSize();
}
void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
{
mRequestedNumVerts = newnverts;
mRequestedNumIndices = newnindices;
LLMemType mt2(LLMemType::MTYPE_VERTEX_RESIZE_BUFFER);
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
mDynamicSize = TRUE;
if (mUsage == GL_STATIC_DRAW_ARB)
{ //always delete/allocate static buffers on resize
destroyGLBuffer();
destroyGLIndices();
allocateBuffer(newnverts, newnindices, TRUE);
mFinal = FALSE;
}
else if (newnverts > mNumVerts || newnindices > mNumIndices ||
newnverts < mNumVerts/2 || newnindices < mNumIndices/2)
{
sAllocatedBytes -= getSize() + getIndicesSize();
S32 oldsize = getSize();
S32 old_index_size = getIndicesSize();
updateNumVerts(newnverts);
updateNumIndices(newnindices);
S32 newsize = getSize();
S32 new_index_size = getIndicesSize();
sAllocatedBytes += newsize + new_index_size;
if (newsize)
{
if (!mGLBuffer)
{ //no buffer exists, create a new one
createGLBuffer();
}
else
{
//delete old buffer, keep GL buffer for now
if (!useVBOs())
{
U8* old = mMappedData;
mMappedData = (U8*)sPrivatePoolp->allocate(newsize);
if (old)
{
memcpy(mMappedData, old, llmin(newsize, oldsize));
if (newsize > oldsize)
{
memset(mMappedData+oldsize, 0, newsize-oldsize);
}
sPrivatePoolp->freeMem(old);
}
else
memset(mMappedData, 0, newsize);
mEmpty = TRUE;
}
}
mResized = TRUE;
}
}
else if (mGLBuffer)
{
destroyGLBuffer();
}
if (new_index_size)
{
if (!mGLIndices)
{
createGLIndices();
}
else
{
if (!useVBOs())
{
//delete old buffer, keep GL buffer for now
U8* old = mMappedIndexData;
mMappedIndexData = (U8*)sPrivatePoolp->allocate(new_index_size);
if (old)
{
memcpy(mMappedIndexData, old, llmin(new_index_size, old_index_size));
if (new_index_size > old_index_size)
{
memset(mMappedIndexData+old_index_size, 0, new_index_size - old_index_size);
}
sPrivatePoolp->freeMem(old);
}
else
memset(mMappedIndexData, 0, new_index_size);
mEmpty = TRUE;
}
}
mResized = TRUE;
}
}
else if (mGLIndices)
{
destroyGLIndices();
}
}
if (mResized && useVBOs())
{
Xiaohong Bao
committed
freeClientBuffer() ;
setBuffer(0);
}
}
BOOL LLVertexBuffer::useVBOs() const
{
//it's generally ineffective to use VBO for things that are streaming on apple
#if LL_DARWIN
if (!mUsage || mUsage == GL_STREAM_DRAW_ARB)
{
return FALSE;
}
#else
if (!mUsage)
{
return FALSE;
}
#endif
}
//----------------------------------------------------------------------------
Xiaohong Bao
committed
void LLVertexBuffer::freeClientBuffer()
{
if(useVBOs() && sDisableVBOMapping && (mMappedData || mMappedIndexData))
{
sPrivatePoolp->freeMem(mMappedData) ;
sPrivatePoolp->freeMem(mMappedIndexData) ;
Xiaohong Bao
committed
mMappedData = NULL ;
mMappedIndexData = NULL ;
}
}
Xiaohong Bao
committed
void LLVertexBuffer::allocateClientVertexBuffer()
Xiaohong Bao
committed
{
if(!mMappedData)
{
U32 size = getSize() ;
mMappedData = (U8*)sPrivatePoolp->allocate(size);
Xiaohong Bao
committed
memset(mMappedData, 0, size);
}
Xiaohong Bao
committed
}
Xiaohong Bao
committed
Xiaohong Bao
committed
void LLVertexBuffer::allocateClientIndexBuffer()
{
Xiaohong Bao
committed
if(!mMappedIndexData)
{
U32 size = getIndicesSize();
mMappedIndexData = (U8*)sPrivatePoolp->allocate(size);
Xiaohong Bao
committed
memset(mMappedIndexData, 0, size);
}
}
// Map for data access
Xiaohong Bao
committed
U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
Xiaohong Bao
committed
llerrs << "LLVertexBuffer::mapVeretxBuffer() called on a finalized buffer." << llendl;
if (!useVBOs() && !mMappedData && !mMappedIndexData)
Xiaohong Bao
committed
llerrs << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << llendl;
Xiaohong Bao
committed
if (!mVertexLocked && useVBOs())
{
LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
Xiaohong Bao
committed
setBuffer(0, type);
mVertexLocked = TRUE;
stop_glerror();
Xiaohong Bao
committed
if(sDisableVBOMapping)
{
allocateClientVertexBuffer() ;
}
else
{
mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
stop_glerror();
}
Xiaohong Bao
committed
log_glerror();
//check the availability of memory
Xiaohong Bao
committed
if(!sDisableVBOMapping)
{
//--------------------
//print out more debug info before crash
llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
GLint size ;
glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ;
llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ;
//--------------------
Xiaohong Bao
committed
GLint buff;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
if ((GLuint)buff != mGLBuffer)
{
llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
}
llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
}
else
Xiaohong Bao
committed
llerrs << "memory allocation for vertex data failed." << llendl ;
Xiaohong Bao
committed
sMappedCount++;
}
return mMappedData;
}
Xiaohong Bao
committed
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
U8* LLVertexBuffer::mapIndexBuffer(S32 access)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
if (mFinal)
{
llerrs << "LLVertexBuffer::mapIndexBuffer() called on a finalized buffer." << llendl;
}
if (!useVBOs() && !mMappedData && !mMappedIndexData)
{
llerrs << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << llendl;
}
if (!mIndexLocked && useVBOs())
{
{
LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES);
setBuffer(0, TYPE_INDEX);
mIndexLocked = TRUE;
stop_glerror();
if(sDisableVBOMapping)
{
allocateClientIndexBuffer() ;
}
else
{
mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
stop_glerror();
}
if (!mMappedIndexData)
{
log_glerror();
Xiaohong Bao
committed
if(!sDisableVBOMapping)
Xiaohong Bao
committed
GLint buff;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
if ((GLuint)buff != mGLIndices)
{
llerrs << "Invalid GL index buffer bound: " << buff << llendl;
}
Xiaohong Bao
committed
llerrs << "glMapBuffer returned NULL (no index data)" << llendl;
}
else