Newer
Older
for (S32 i=0; i<TYPE_TEXTURE_INDEX; i++)
{
U32 mask = 1<<i;
if (typemask & mask)
{
if (offsets && LLVertexBuffer::sTypeSize[i])
{
offset += LLVertexBuffer::sTypeSize[i]*num_vertices;
}
offsets[TYPE_TEXTURE_INDEX] = offsets[TYPE_VERTEX] + 12;
//static
S32 LLVertexBuffer::calcVertexSize(const U32& typemask)
{
S32 size = 0;
for (S32 i = 0; i < TYPE_TEXTURE_INDEX; i++)
{
U32 mask = 1<<i;
if (typemask & mask)
{
size += LLVertexBuffer::sTypeSize[i];
return size;
{
return mSize;
}
// protected, use unref()
//virtual
LLVertexBuffer::~LLVertexBuffer()
{
destroyGLBuffer();
destroyGLIndices();
if (mGLArray)
{
David Parks
committed
releaseVAOName(mGLArray);
}
Xiaohong Bao
committed
David Parks
committed
if (mFence)
{
delete mFence;
}
mFence = NULL;
sVertexCount -= mNumVerts;
sIndexCount -= mNumIndices;
if (mMappedData)
{
LL_ERRS() << "Failed to clear vertex buffer's vertices" << LL_ENDL;
}
if (mMappedIndexData)
{
LL_ERRS() << "Failed to clear vertex buffer's indices" << LL_ENDL;
}
David Parks
committed
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
void LLVertexBuffer::placeFence() const
{
/*if (!mFence && useVBOs())
{
if (gGLManager.mHasSync)
{
mFence = new LLGLSyncFence();
}
}
if (mFence)
{
mFence->placeFence();
}*/
}
void LLVertexBuffer::waitFence() const
{
/*if (mFence)
{
mFence->wait();
}*/
}
//----------------------------------------------------------------------------
void LLVertexBuffer::genBuffer(U32 size)
{
disclaimMem(mSize);
mSize = vbo_block_size(size);
if (mUsage == GL_STREAM_DRAW_ARB)
{
mMappedData = sStreamVBOPool.allocate(mGLBuffer, mSize);
}
else if (mUsage == GL_DYNAMIC_DRAW_ARB)
{
mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize);
}
else
{
mMappedData = sDynamicCopyVBOPool.allocate(mGLBuffer, mSize);
}
sGLCount++;
}
void LLVertexBuffer::genIndices(U32 size)
{
mIndicesSize = vbo_block_size(size);
if (mUsage == GL_STREAM_DRAW_ARB)
{
mMappedIndexData = sStreamIBOPool.allocate(mGLIndices, mIndicesSize);
}
else
{
mMappedIndexData = sDynamicIBOPool.allocate(mGLIndices, mIndicesSize);
}
sGLCount++;
}
void LLVertexBuffer::releaseBuffer()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
sStreamVBOPool.release(mGLBuffer, mMappedData, mSize);
}
else
{
sDynamicVBOPool.release(mGLBuffer, mMappedData, mSize);
}
mGLBuffer = 0;
mMappedData = NULL;
sGLCount--;
}
void LLVertexBuffer::releaseIndices()
{
if (mUsage == GL_STREAM_DRAW_ARB)
{
sStreamIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
}
{
sDynamicIBOPool.release(mGLIndices, mMappedIndexData, mIndicesSize);
}
mGLIndices = 0;
mMappedIndexData = NULL;
sGLCount--;
}
bool LLVertexBuffer::createGLBuffer(U32 size)
{
if (mGLBuffer)
{
destroyGLBuffer();
}
if (size == 0)
{
return true;
bool sucsess = true;
Leslie Linden
committed
mEmpty = true;
Leslie Linden
committed
mMappedDataUsingVBOs = useVBOs();
if (mMappedDataUsingVBOs)
genBuffer(size);
}
else
{
static int gl_buffer_idx = 0;
mGLBuffer = ++gl_buffer_idx;
mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
disclaimMem(mSize);
mSize = size;
if (!mMappedData)
{
sucsess = false;
}
return sucsess;
bool LLVertexBuffer::createGLIndices(U32 size)
{
if (mGLIndices)
{
destroyGLIndices();
}
if (size == 0)
{
return true;
bool sucsess = true;
Leslie Linden
committed
mEmpty = true;
//pad by 16 bytes for aligned copies
size += 16;
Leslie Linden
committed
mMappedIndexDataUsingVBOs = useVBOs();
if (mMappedIndexDataUsingVBOs)
//pad by another 16 bytes for VBO pointer adjustment
size += 16;
genIndices(size);
mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
static int gl_buffer_idx = 0;
mGLIndices = ++gl_buffer_idx;
mIndicesSize = size;
if (!mMappedIndexData)
{
sucsess = false;
}
return sucsess;
}
void LLVertexBuffer::destroyGLBuffer()
{
AndreyL ProductEngine
committed
if (mGLBuffer || mMappedData)
Leslie Linden
committed
if (mMappedDataUsingVBOs)
releaseBuffer();
}
else
{
Leslie Linden
committed
FREE_MEM(sPrivatePoolp, (void*) mMappedData);
mMappedData = NULL;
Leslie Linden
committed
mEmpty = true;
}
}
mGLBuffer = 0;
//unbind();
}
void LLVertexBuffer::destroyGLIndices()
{
AndreyL ProductEngine
committed
if (mGLIndices || mMappedIndexData)
Leslie Linden
committed
if (mMappedIndexDataUsingVBOs)
Loren Shih
committed
releaseIndices();
}
else
{
Leslie Linden
committed
FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData);
mMappedIndexData = NULL;
Leslie Linden
committed
mEmpty = true;
}
}
mGLIndices = 0;
//unbind();
bool LLVertexBuffer::updateNumVerts(S32 nverts)
bool sucsess = true;
{
LL_WARNS() << "Vertex buffer overflow!" << LL_ENDL;
}
U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts);
if (needed_size > mSize || needed_size <= mSize/2)
sucsess &= createGLBuffer(needed_size);
sVertexCount -= mNumVerts;
mNumVerts = nverts;
sVertexCount += mNumVerts;
return sucsess;
bool LLVertexBuffer::updateNumIndices(S32 nindices)
bool sucsess = true;
U32 needed_size = sizeof(U16) * nindices;
if (needed_size > mIndicesSize || needed_size <= mIndicesSize/2)
sucsess &= createGLIndices(needed_size);
sIndexCount -= mNumIndices;
mNumIndices = nindices;
sIndexCount += mNumIndices;
return sucsess;
bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
stop_glerror();
if (nverts < 0 || nindices < 0 ||
nverts > 65536)
{
LL_ERRS() << "Bad vertex buffer allocation: " << nverts << " : " << nindices << LL_ENDL;
bool sucsess = true;
sucsess &= updateNumVerts(nverts);
sucsess &= updateNumIndices(nindices);
if (create && (nverts || nindices))
//actually allocate space for the vertex buffer if using VBO mapping
flush(); //unmap
David Parks
committed
if (gGLManager.mHasVertexArrayObject && useVBOs() && sUseVAO)
{
David Parks
committed
mGLArray = getVAOName();
David Parks
committed
setupVertexArray();
}
return sucsess;
static LLTrace::BlockTimerStatHandle FTM_SETUP_VERTEX_ARRAY("Setup VAO");
David Parks
committed
void LLVertexBuffer::setupVertexArray()
{
if (!mGLArray)
{
return;
}
LL_RECORD_BLOCK_TIME(FTM_SETUP_VERTEX_ARRAY);
#if GL_ARB_vertex_array_object
glBindVertexArray(mGLArray);
#endif
sGLRenderArray = mGLArray;
David Parks
committed
U32 attrib_size[] =
{
3, //TYPE_VERTEX,
3, //TYPE_NORMAL,
2, //TYPE_TEXCOORD0,
2, //TYPE_TEXCOORD1,
2, //TYPE_TEXCOORD2,
2, //TYPE_TEXCOORD3,
4, //TYPE_COLOR,
David Parks
committed
4, //TYPE_EMISSIVE,
David Parks
committed
4, //TYPE_TANGENT,
David Parks
committed
1, //TYPE_WEIGHT,
4, //TYPE_WEIGHT4,
4, //TYPE_CLOTHWEIGHT,
David Parks
committed
1, //TYPE_TEXTURE_INDEX
David Parks
committed
};
U32 attrib_type[] =
{
GL_FLOAT, //TYPE_VERTEX,
GL_FLOAT, //TYPE_NORMAL,
GL_FLOAT, //TYPE_TEXCOORD0,
GL_FLOAT, //TYPE_TEXCOORD1,
GL_FLOAT, //TYPE_TEXCOORD2,
GL_FLOAT, //TYPE_TEXCOORD3,
GL_UNSIGNED_BYTE, //TYPE_COLOR,
GL_UNSIGNED_BYTE, //TYPE_EMISSIVE,
David Parks
committed
GL_FLOAT, //TYPE_TANGENT,
David Parks
committed
GL_FLOAT, //TYPE_WEIGHT,
GL_FLOAT, //TYPE_WEIGHT4,
GL_FLOAT, //TYPE_CLOTHWEIGHT,
David Parks
committed
GL_UNSIGNED_INT, //TYPE_TEXTURE_INDEX
David Parks
committed
};
bool attrib_integer[] =
{
false, //TYPE_VERTEX,
false, //TYPE_NORMAL,
false, //TYPE_TEXCOORD0,
false, //TYPE_TEXCOORD1,
false, //TYPE_TEXCOORD2,
false, //TYPE_TEXCOORD3,
false, //TYPE_COLOR,
false, //TYPE_EMISSIVE,
David Parks
committed
false, //TYPE_TANGENT,
David Parks
committed
false, //TYPE_WEIGHT,
false, //TYPE_WEIGHT4,
false, //TYPE_CLOTHWEIGHT,
true, //TYPE_TEXTURE_INDEX
David Parks
committed
};
U32 attrib_normalized[] =
{
GL_FALSE, //TYPE_VERTEX,
GL_FALSE, //TYPE_NORMAL,
GL_FALSE, //TYPE_TEXCOORD0,
GL_FALSE, //TYPE_TEXCOORD1,
GL_FALSE, //TYPE_TEXCOORD2,
GL_FALSE, //TYPE_TEXCOORD3,
GL_TRUE, //TYPE_COLOR,
GL_TRUE, //TYPE_EMISSIVE,
David Parks
committed
GL_FALSE, //TYPE_TANGENT,
David Parks
committed
GL_FALSE, //TYPE_WEIGHT,
GL_FALSE, //TYPE_WEIGHT4,
GL_FALSE, //TYPE_CLOTHWEIGHT,
GL_FALSE, //TYPE_TEXTURE_INDEX
David Parks
committed
};
bindGLBuffer(true);
bindGLIndices(true);
for (U32 i = 0; i < TYPE_MAX; ++i)
{
if (mTypeMask & (1 << i))
{
glEnableVertexAttribArrayARB(i);
David Parks
committed
David Parks
committed
{
David Parks
committed
//glVertexattribIPointer requires GLSL 1.30 or later
if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30)
{
glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i], (const GLvoid*) mOffsets[i]);
David Parks
committed
}
David Parks
committed
}
else
{
// nat 2016-12-16: With 64-bit clang compile, the compiler
// produces an error if we simply cast mOffsets[i] -- an S32
// -- to (GLvoid *), the type of the parameter. It correctly
// points out that there's no way an S32 could fit a real
// pointer value. Ruslan asserts that in this case the last
// param is interpreted as an array data offset within the VBO
// rather than as an actual pointer, so it's okay.
glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i],
attrib_normalized[i], sTypeSize[i],
reinterpret_cast<GLvoid*>(mOffsets[i]));
David Parks
committed
}
David Parks
committed
}
else
{
glDisableVertexAttribArrayARB(i);
}
}
//draw a dummy triangle to set index array pointer
//glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, NULL);
David Parks
committed
unbind();
David Parks
committed
}
bool LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
bool sucsess = true;
sucsess &= updateNumVerts(newnverts);
sucsess &= updateNumIndices(newnindices);
if (useVBOs())
{
flush(); //unmap
David Parks
committed
if (mGLArray)
{ //if size changed, offsets changed
setupVertexArray();
}
}
return sucsess;
Leslie Linden
committed
bool LLVertexBuffer::useVBOs() const
//it's generally ineffective to use VBO for things that are streaming on apple
Leslie Linden
committed
return (mUsage != 0);
}
//----------------------------------------------------------------------------
bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
{
S32 end = index+count;
S32 region_end = region.mIndex+region.mCount;
if (end < region.mIndex ||
index > region_end)
{ //gap exists, do not merge
return false;
}
S32 new_end = llmax(end, region_end);
S32 new_index = llmin(index, region.mIndex);
region.mIndex = new_index;
region.mCount = new_end-new_index;
return true;
}
static LLTrace::BlockTimerStatHandle FTM_VBO_MAP_BUFFER_RANGE("VBO Map Range");
static LLTrace::BlockTimerStatHandle FTM_VBO_MAP_BUFFER("VBO Map");
// Map for data access
volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
David Parks
committed
bindGLBuffer(true);
LL_ERRS() << "LLVertexBuffer::mapVeretxBuffer() called on a finalized buffer." << LL_ENDL;
if (!useVBOs() && !mMappedData && !mMappedIndexData)
LL_ERRS() << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << LL_ENDL;
if (useVBOs())
if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
{
if (count == -1)
{
David Parks
committed
count = mNumVerts-index;
}
bool mapped = false;
//see if range is already mapped
for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
{
MappedRegion& region = mMappedVertexRegions[i];
if (region.mType == type)
{
if (expand_region(region, index, count))
{
mapped = true;
David Parks
committed
break;
}
}
}
if (!mapped)
{
//not already mapped, map new region
MappedRegion region(type, mMappable && map_range ? -1 : index, count);
mMappedVertexRegions.push_back(region);
}
}
if (mVertexLocked && map_range)
{
LL_ERRS() << "Attempted to map a specific range of a buffer that was already mapped." << LL_ENDL;
}
if (!mVertexLocked)
Leslie Linden
committed
mVertexLocked = true;
David Parks
committed
sMappedCount++;
stop_glerror();
Xiaohong Bao
committed
Xiaohong Bao
committed
{
map_range = false;
Xiaohong Bao
committed
}
else
{
volatile U8* src = NULL;
David Parks
committed
waitFence();
if (gGLManager.mHasMapBufferRange)
{
if (map_range)
{
LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_BUFFER_RANGE);
S32 offset = mOffsets[type] + sTypeSize[type]*index;
S32 length = (sTypeSize[type]*count+0xF) & ~0xF;
David Parks
committed
src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length,
GL_MAP_WRITE_BIT |
GL_MAP_FLUSH_EXPLICIT_BIT |
GL_MAP_INVALIDATE_RANGE_BIT);
}
else
{
if (gDebugGL)
{
GLint size = 0;
glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
if (size < mSize)
{
LL_ERRS() << "Invalid buffer size." << LL_ENDL;
}
}
LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_BUFFER);
David Parks
committed
src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize,
GL_MAP_WRITE_BIT |
GL_MAP_FLUSH_EXPLICIT_BIT);
#endif
}
}
else if (gGLManager.mHasFlushBufferRange)
{
if (map_range)
{
Nyx Linden
committed
#ifndef LL_MESA_HEADLESS
glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
Nyx Linden
committed
#endif
src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
else
{
src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
}
else
{
map_range = false;
src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
mMappedData = LL_NEXT_ALIGNED_ADDRESS<volatile U8>(src);
Loren Shih
committed
Xiaohong Bao
committed
}
if (!mMappedData)
{
log_glerror();
Leslie Linden
committed
//check the availability of memory
LLMemory::logMemoryInfo(true);
{
//--------------------
//print out more debug info before crash
LL_INFOS() << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << LL_ENDL;
GLint size;
glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
LL_INFOS() << "GL_ARRAY_BUFFER_ARB size is " << size << LL_ENDL;
//--------------------
GLint buff;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
if ((GLuint)buff != mGLBuffer)
{
LL_ERRS() << "Invalid GL vertex buffer bound: " << buff << LL_ENDL;
}
LL_ERRS() << "glMapBuffer returned NULL (no vertex data)" << LL_ENDL;
}
else
Xiaohong Bao
committed
{
LL_ERRS() << "memory allocation for vertex data failed." << LL_ENDL;
Xiaohong Bao
committed
}
}
else
{
map_range = false;
Xiaohong Bao
committed
}
if (map_range && gGLManager.mHasMapBufferRange && mMappable)
{
return mMappedData;
}
else
{
return mMappedData+mOffsets[type]+sTypeSize[type]*index;
}
Xiaohong Bao
committed
}
static LLTrace::BlockTimerStatHandle FTM_VBO_MAP_INDEX_RANGE("IBO Map Range");
static LLTrace::BlockTimerStatHandle FTM_VBO_MAP_INDEX("IBO Map");
volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
Xiaohong Bao
committed
{
David Parks
committed
bindGLIndices(true);
Xiaohong Bao
committed
if (mFinal)
{
LL_ERRS() << "LLVertexBuffer::mapIndexBuffer() called on a finalized buffer." << LL_ENDL;
Xiaohong Bao
committed
}
if (!useVBOs() && !mMappedData && !mMappedIndexData)
{
LL_ERRS() << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << LL_ENDL;
Xiaohong Bao
committed
}
if (useVBOs())
Xiaohong Bao
committed
{
if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
{
if (count == -1)
{
David Parks
committed
count = mNumIndices-index;
}
bool mapped = false;
//see if range is already mapped
for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
{
MappedRegion& region = mMappedIndexRegions[i];
if (expand_region(region, index, count))
{
mapped = true;
David Parks
committed
break;
}
}
if (!mapped)
{
//not already mapped, map new region
MappedRegion region(TYPE_INDEX, mMappable && map_range ? -1 : index, count);
mMappedIndexRegions.push_back(region);
}
}
if (mIndexLocked && map_range)
{
LL_ERRS() << "Attempted to map a specific range of a buffer that was already mapped." << LL_ENDL;
}
if (!mIndexLocked)
Xiaohong Bao
committed
{
Leslie Linden
committed
mIndexLocked = true;
David Parks
committed
sMappedCount++;
Xiaohong Bao
committed
stop_glerror();
David Parks
committed
if (gDebugGL && useVBOs())
{
GLint elem = 0;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
if (elem != mGLIndices)
{
LL_ERRS() << "Wrong index buffer bound!" << LL_ENDL;
David Parks
committed
}
}
Xiaohong Bao
committed
{
map_range = false;
Xiaohong Bao
committed
}
else
{
volatile U8* src = NULL;
David Parks
committed
waitFence();
if (gGLManager.mHasMapBufferRange)
{
if (map_range)
{
LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_INDEX_RANGE);
S32 offset = sizeof(U16)*index;
S32 length = sizeof(U16)*count;
David Parks
committed
src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length,
GL_MAP_WRITE_BIT |
GL_MAP_FLUSH_EXPLICIT_BIT |
GL_MAP_INVALIDATE_RANGE_BIT);
}
else
{
LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_INDEX);
David Parks
committed
src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices,
GL_MAP_WRITE_BIT |
GL_MAP_FLUSH_EXPLICIT_BIT);
#endif
}
}
else if (gGLManager.mHasFlushBufferRange)
{
if (map_range)
{
Nyx Linden
committed
#ifndef LL_MESA_HEADLESS
glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
Nyx Linden
committed
#endif
src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
else
{
src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
}
else
{
LL_RECORD_BLOCK_TIME(FTM_VBO_MAP_INDEX);
map_range = false;
src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src);
mAlignedIndexOffset = mMappedIndexData - src;
stop_glerror();
Xiaohong Bao
committed
}
}
if (!mMappedIndexData)
{
log_glerror();
LLMemory::logMemoryInfo(true);
Xiaohong Bao
committed
GLint buff;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
if ((GLuint)buff != mGLIndices)
{
LL_ERRS() << "Invalid GL index buffer bound: " << buff << LL_ENDL;
Xiaohong Bao
committed
}
LL_ERRS() << "glMapBuffer returned NULL (no index data)" << LL_ENDL;
Xiaohong Bao
committed
}
else
{
LL_ERRS() << "memory allocation for Index data failed. " << LL_ENDL;
Xiaohong Bao
committed
}
else
{
map_range = false;
}
Xiaohong Bao
committed
if (map_range && gGLManager.mHasMapBufferRange && mMappable)
{
return mMappedIndexData;
}
else
{
return mMappedIndexData + sizeof(U16)*index;
}
static LLTrace::BlockTimerStatHandle FTM_VBO_UNMAP("VBO Unmap");
static LLTrace::BlockTimerStatHandle FTM_VBO_FLUSH_RANGE("Flush VBO Range");
static LLTrace::BlockTimerStatHandle FTM_IBO_UNMAP("IBO Unmap");
static LLTrace::BlockTimerStatHandle FTM_IBO_FLUSH_RANGE("Flush IBO Range");
David Parks
committed
void LLVertexBuffer::unmapBuffer()
David Parks
committed
if (!useVBOs())
Xiaohong Bao
committed
{
return; //nothing to unmap
Xiaohong Bao
committed
}
bool updated_all = false;
David Parks
committed
if (mMappedData && mVertexLocked)
LL_RECORD_BLOCK_TIME(FTM_VBO_UNMAP);
David Parks
committed
bindGLBuffer(true);
updated_all = mIndexLocked; //both vertex and index buffers done updating
Xiaohong Bao
committed
Xiaohong Bao
committed
{
David Parks
committed
if (!mMappedVertexRegions.empty())
{
stop_glerror();
for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
{
const MappedRegion& region = mMappedVertexRegions[i];
S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
S32 length = sTypeSize[region.mType]*region.mCount;
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedData+offset);
David Parks
committed
stop_glerror();
}
mMappedVertexRegions.clear();
}
else
{
stop_glerror();
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), (U8*) mMappedData);
David Parks
committed
stop_glerror();
}
Xiaohong Bao
committed
}
else
{
if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
{
if (!mMappedVertexRegions.empty())
{
stop_glerror();
for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
{
const MappedRegion& region = mMappedVertexRegions[i];
S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
S32 length = sTypeSize[region.mType]*region.mCount;
if (gGLManager.mHasMapBufferRange)
{
LL_RECORD_BLOCK_TIME(FTM_VBO_FLUSH_RANGE);
#ifdef GL_ARB_map_buffer_range
glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
#endif
}
else if (gGLManager.mHasFlushBufferRange)
{
Nyx Linden
committed
#ifndef LL_MESA_HEADLESS
glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER_ARB, offset, length);
Nyx Linden
committed
#endif
stop_glerror();
}
mMappedVertexRegions.clear();
}
}
Xiaohong Bao
committed
stop_glerror();
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
stop_glerror();
Xiaohong Bao
committed
mMappedData = NULL;
}
Leslie Linden
committed
mVertexLocked = false;
Xiaohong Bao
committed
sMappedCount--;
}
David Parks
committed
if (mMappedIndexData && mIndexLocked)
Xiaohong Bao
committed
{
LL_RECORD_BLOCK_TIME(FTM_IBO_UNMAP);
David Parks
committed
bindGLIndices();
Xiaohong Bao
committed
{
David Parks
committed
if (!mMappedIndexRegions.empty())
{
for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
{
const MappedRegion& region = mMappedIndexRegions[i];
S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
S32 length = sizeof(U16)*region.mCount;