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;
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;
BOOL LLVertexBuffer::sPreferStreamDraw = FALSE;
std::vector<U32> LLVertexBuffer::sDeleteList;
S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
{
sizeof(LLVector4), // TYPE_VERTEX,
sizeof(LLVector4), // TYPE_NORMAL,
sizeof(LLVector2), // TYPE_TEXCOORD0,
sizeof(LLVector2), // TYPE_TEXCOORD1,
sizeof(LLVector2), // TYPE_TEXCOORD2,
sizeof(LLVector2), // TYPE_TEXCOORD3,
sizeof(LLColor4U), // TYPE_COLOR,
sizeof(LLVector4), // TYPE_BINORMAL,
sizeof(F32), // TYPE_WEIGHT,
sizeof(LLVector4), // TYPE_WEIGHT4,
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
David Parks
committed
if (data_mask & mask[i] && i > 0)
{ //needs to be enabled
glEnableClientState(array[i]);
}
else if (gDebugGL && i > 0 && 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);
}
if (sLastMask & MAP_WEIGHT4)
{
if (sWeight4Loc < 0)
{
llerrs << "Weighting disabled but vertex buffer still bound!" << llendl;
}
if (!(data_mask & MAP_WEIGHT4))
{ //disable 4-component skin weight
glDisableVertexAttribArrayARB(sWeight4Loc);
}
}
else if (data_mask & MAP_WEIGHT4)
{
if (sWeight4Loc >= 0)
{ //enable 4-component skin weight
glEnableVertexAttribArrayARB(sWeight4Loc);
}
}
sLastMask = data_mask;
}
}
void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const
{
if (start >= (U32) mRequestedNumVerts ||
llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mRequestedNumVerts << llendl;
if (indices_offset >= (U32) mRequestedNumIndices ||
{
llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
}
if (gDebugGL && !useVBOs())
{
U16* idx = ((U16*) getIndicesPointer())+indices_offset;
for (U32 i = 0; i < count; ++i)
{
if (idx[i] < start || idx[i] > end)
{
llerrs << "Index out of range: " << idx[i] << " not in [" << start << ", " << end << "]" << llendl;
}
}
}
}
void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
{
validateRange(start, end, count, indices_offset);
llassert(mRequestedNumVerts >= 0);
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,
}
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
{
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
{
{
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 && gGLManager.mHasVertexBufferObject ;
if(sEnableVBOs)
{
Merov Linden
committed
//llassert_always(glBindBufferARB) ; //double check the extention for VBO is loaded.
llinfos << "VBO is enabled." << llendl ;
}
else
{
llinfos << "VBO is disabled." << llendl ;
}
Xiaohong Bao
committed
sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ;
LLGLNamePool::registerPool(&sDynamicVBOPool);
LLGLNamePool::registerPool(&sDynamicIBOPool);
LLGLNamePool::registerPool(&sStreamVBOPool);
LLGLNamePool::registerPool(&sStreamIBOPool);
}
//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);
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),
mDynamicSize(FALSE)
LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
if (!sEnableVBOs)
{
mUsage = 0 ;
if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
{
mUsage = 0;
if (mUsage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw)
mUsage = GL_STREAM_DRAW_ARB;
//zero out offsets
for (U32 i = 0; i < TYPE_MAX; i++)
{
mOffsets[i] = 0;
}
mTypeMask = typemask;
mSize = 0;
sCount++;
}
//static
S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices)
{
S32 offset = 0;
for (S32 i=0; i<TYPE_MAX; i++)
{
U32 mask = 1<<i;
if (typemask & mask)
{
if (offsets)
{
offsets[i] = offset;
offset += LLVertexBuffer::sTypeSize[i]*num_vertices;
offset = (offset + 0xF) & ~0xF;
}
}
}
return offset+16;
}
//static
S32 LLVertexBuffer::calcVertexSize(const U32& typemask)
{
S32 size = 0;
for (S32 i = 0; i < TYPE_MAX; i++)
{
U32 mask = 1<<i;
if (typemask & mask)
{
size += LLVertexBuffer::sTypeSize[i];
return size;
{
return mSize;
// protected, use unref()
//virtual
LLVertexBuffer::~LLVertexBuffer()
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTRUCTOR);
destroyGLBuffer();
destroyGLIndices();
sCount--;
Xiaohong Bao
committed
llassert_always(!mMappedData && !mMappedIndexData) ;
};
//----------------------------------------------------------------------------
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
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;
David Parks
committed
mMappedData = (U8*) malloc(size);
}
}
void LLVertexBuffer::createGLIndices()
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_CREATE_INDICES);
U32 size = getIndicesSize();
if (mGLIndices)
{
destroyGLIndices();
}
if (size == 0)
{
return;
}
mEmpty = TRUE;
//pad by 16 bytes for aligned copies
size += 16;
//pad by another 16 bytes for VBO pointer adjustment
size += 16;
mMappedIndexData = NULL;
genIndices();
mResized = TRUE;
}
else
{
David Parks
committed
mMappedIndexData = (U8*) malloc(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
{
David Parks
committed
free(mMappedData);
mMappedData = NULL;
mEmpty = TRUE;
sAllocatedBytes -= getSize();
}
mGLBuffer = 0;
//unbind();
}
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;
}
Loren Shih
committed
releaseIndices();
}
else
{
David Parks
committed
free(mMappedIndexData);
mMappedIndexData = NULL;
mEmpty = TRUE;
sAllocatedBytes -= getIndicesSize();
}
mGLIndices = 0;
//unbind();
}
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;
}
mSize = calcOffsets(mTypeMask, mOffsets, mNumVerts);
}
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);
if (nverts < 0 || nindices < 0 ||
nverts > 65536)
{
llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl;
}
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);
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
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();
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
{
if (!useVBOs())
{
David Parks
committed
free(mMappedData);
mMappedData = (U8*) malloc(newsize);
}
mResized = TRUE;
}
}
else if (mGLBuffer)
{
destroyGLBuffer();
}
if (new_index_size)
{
if (!mGLIndices)
{
createGLIndices();
}
else
{
if (!useVBOs())
{
David Parks
committed
free(mMappedIndexData);
mMappedIndexData = (U8*) malloc(new_index_size);
}
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))
{
Xiaohong Bao
committed
mMappedData = NULL ;
mMappedIndexData = NULL ;
}
}
Xiaohong Bao
committed
void LLVertexBuffer::allocateClientVertexBuffer()
Xiaohong Bao
committed
{
if(!mMappedData)
{
Xiaohong Bao
committed
}
Xiaohong Bao
committed
}
Xiaohong Bao
committed
Xiaohong Bao
committed
void LLVertexBuffer::allocateClientIndexBuffer()
{
Xiaohong Bao
committed
if(!mMappedIndexData)
{
Xiaohong Bao
committed
}
}
// 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
{
U8* src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
mAlignedOffset = mMappedData - src;
Loren Shih
committed
Xiaohong Bao
committed
}
Xiaohong Bao
committed
log_glerror();
//check the availability of memory
U32 avail_phy_mem, avail_vir_mem;
LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ;
llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ;
llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl;
Xiaohong Bao
committed
if(!sDisableVBOMapping)
Xiaohong Bao
committed
//--------------------
//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 ;
//--------------------
Loren Shih
committed
Xiaohong Bao
committed
GLint buff;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
if ((GLuint)buff != mGLBuffer)
{
llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
}
Xiaohong Bao
committed
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;
}