// Map for data access U8* LLVertexBuffer::mapBuffer(S32 access) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mFinal) { llwarns << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl; } if (!useVBOs() && !mMappedData && !mMappedIndexData) { llwarns << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl; } if (!mLocked && useVBOs()) { setBuffer(0); mLocked = TRUE; stop_glerror(); mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); stop_glerror(); mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); stop_glerror(); if (!mMappedData) { //-------------------- //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 ; //-------------------- GLint buff; glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); if (buff != mGLBuffer) { llwarns << "Invalid GL vertex buffer bound: " << buff << llendl; } llwarns << "glMapBuffer returned NULL (no vertex data)" << llendl; } if (!mMappedIndexData) { GLint buff; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if (buff != mGLIndices) { llwarns << "Invalid GL index buffer bound: " << buff << llendl; } llwarns << "glMapBuffer returned NULL (no index data)" << llendl; } sMappedCount++; } return mMappedData; }
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(); if(!sDisableVBOMapping) { GLint buff; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLIndices) { llerrs << "Invalid GL index buffer bound: " << buff << llendl; } llerrs << "glMapBuffer returned NULL (no index data)" << llendl; } else { llerrs << "memory allocation for Index data failed. " << llendl ; } } sMappedCount++; } return mMappedIndexData ; }
void LLVertexBuffer::destroyGLBuffer() { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mGLBuffer) { if (useVBOs()) { freeClientBuffer() ; if (mMappedData || mMappedIndexData) { llerrs << "Vertex buffer destroyed while mapped!" << llendl; } releaseBuffer(); } else { ll_aligned_free_16((void*)mMappedData); mMappedData = NULL; mEmpty = TRUE; } sAllocatedBytes -= getSize(); } mGLBuffer = 0; //unbind(); }
void LLVertexBuffer::createGLBuffer() { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); 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*) ll_aligned_malloc_16(size); if(!sOmitBlank) memset((void*)mMappedData, 0, size); } }
void LLVertexBuffer::destroyGLIndices() { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mGLIndices) { if (useVBOs()) { freeClientBuffer() ; if (mMappedData || mMappedIndexData) { llerrs << "Vertex buffer destroyed while mapped." << llendl; } releaseIndices(); } else { delete [] mMappedIndexData; mMappedIndexData = NULL; mEmpty = TRUE; } sAllocatedBytes -= getIndicesSize(); } mGLIndices = 0; unbind(); }
// virtual void setupVertexBuffer(U32 data_mask) { if (LLGLSLShader::sNoFixedFunction) { //just use default if shaders are in play LLVertexBuffer::setupVertexBuffer(data_mask & ~(MAP_TEXCOORD2 | MAP_TEXCOORD3)); return; } volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; //assume tex coords 2 and 3 are present U32 type_mask = mTypeMask | MAP_TEXCOORD2 | MAP_TEXCOORD3; if ((data_mask & type_mask) != data_mask) { llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; } if (data_mask & MAP_NORMAL) { glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); } if (data_mask & MAP_TEXCOORD3) { //substitute tex coord 1 for tex coord 3 glClientActiveTextureARB(GL_TEXTURE3_ARB); glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD2) { //substitute tex coord 0 for tex coord 2 glClientActiveTextureARB(GL_TEXTURE2_ARB); glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD1) { glClientActiveTextureARB(GL_TEXTURE1_ARB); glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TANGENT) { glClientActiveTextureARB(GL_TEXTURE2_ARB); glTexCoordPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TANGENT], (void*)(base + mOffsets[TYPE_TANGENT])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD0) { glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); } if (data_mask & MAP_COLOR) { glColorPointer(4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR])); } if (data_mask & MAP_VERTEX) { glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); } }
void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const { if (start >= (U32) mRequestedNumVerts || end >= (U32) mRequestedNumVerts) { llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mRequestedNumVerts << llendl; } llassert(mRequestedNumIndices >= 0); if (indices_offset >= (U32) mRequestedNumIndices || indices_offset + count > (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 LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const { if (sRenderingSkinned) { U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_VERTEX], (void*)(base + 0)); glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); set_vertex_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT], LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_WEIGHT], (F32*)(base + mOffsets[TYPE_WEIGHT])); if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_BUMP) { set_binormals(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL], LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_BINORMAL], (LLVector3*)(base + mOffsets[TYPE_BINORMAL])); } if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH) { set_vertex_clothing_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING], LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_CLOTHWEIGHT], (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT])); } } else { LLVertexBuffer::setupVertexBuffer(data_mask); } }
void LLVertexBuffer::createGLIndices() { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); U32 size = getIndicesSize(); if (mGLIndices) { destroyGLIndices(); } if (size == 0) { return; } mMappedIndexData = new U8[size]; memset(mMappedIndexData, 0, size); mEmpty = TRUE; if (useVBOs()) { glGenBuffersARB(1, (GLuint*) &mGLIndices); mResized = TRUE; sGLCount++; } else { static int gl_buffer_idx = 0; mGLIndices = ++gl_buffer_idx; } }
void LLVertexBuffer::createGLIndices() { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); U32 size = getIndicesSize(); if (mGLIndices) { destroyGLIndices(); } if (size == 0) { return; } mEmpty = TRUE; if (useVBOs()) { mMappedIndexData = NULL; genIndices(); mResized = TRUE; } else { mMappedIndexData = new U8[size]; if(!sOmitBlank) memset((void*)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()) { freeClientBuffer() ; if (mMappedData || mMappedIndexData) { llerrs << "Vertex buffer destroyed while mapped!" << llendl; } releaseBuffer(); } else { delete [] mMappedData; mMappedData = NULL; mEmpty = TRUE; } sAllocatedBytes -= getSize(); } mGLBuffer = 0; unbind(); }
// Map for data access U8* LLVertexBuffer::mapBuffer(S32 access) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (sRenderActive) { llwarns << "Buffer mapped during render frame!" << llendl; } if (!mGLBuffer && !mGLIndices) { llerrs << "LLVertexBuffer::mapBuffer() called before createGLBuffer" << llendl; } if (mFinal) { llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl; } if (!mMappedData && !mMappedIndexData) { llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl; } if (!mLocked && useVBOs()) { mLocked = TRUE; sLockedList.push_back(this); } return mMappedData; }
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 = new U8[size]; memset(mMappedData, 0, size); } }
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { llassert(mRequestedNumVerts >= 0); if (first >= (U32) mRequestedNumVerts || first + count > (U32) mRequestedNumVerts) { llerrs << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl; } if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive) { llerrs << "Wrong vertex buffer bound." << llendl; } if (mode >= LLRender::NUM_MODES) { llerrs << "Invalid draw mode: " << mode << llendl; return; } stop_glerror(); glDrawArrays(sGLMode[mode], first, count); stop_glerror(); }
void operator()(ResourceDatabase* db) { if (stripfy()) setRemoveDoubles(true); std::vector< vl::ref<vl::Geometry> > geom; db->get<Geometry>(geom); for(unsigned int i=0; i<geom.size(); ++i) { if (discardOriginalNormals()) geom[i]->setNormalArray(NULL); if (computeNormals() && !geom[i]->normalArray()) geom[i]->computeNormals(); if (removeDoubles()) DoubleVertexRemover().removeDoubles(geom[i].get()); if (sortVertices()) geom[i]->sortVertices(); if (stripfy()) TriangleStripGenerator().stripfy(geom[i].get(), 22, true, false, true); if (convertToDrawArrays()) geom[i]->convertDrawCallToDrawArrays(); geom[i]->setDisplayListEnabled(useDisplayLists()); geom[i]->setVBOEnabled(useVBOs()); if (transformGeometry()) geom[i]->transform(transformMatrix(),true); } }
void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count) { if (useVBOs() && !mFilthy) { if (!mDirtyRegions.empty()) { DirtyRegion& region = *(mDirtyRegions.rbegin()); if (region.mIndex+region.mCount > vert_index) { //this buffer has received multiple updates since the last copy, mark it filthy mFilthy = TRUE; mDirtyRegions.clear(); return; } if (region.mIndex + region.mCount == vert_index && region.mIndicesIndex + region.mIndicesCount == indices_index) { region.mCount += vert_count; region.mIndicesCount += indices_count; return; } } mDirtyRegions.push_back(DirtyRegion(vert_index,vert_count,indices_index,indices_count)); } }
//---------------------------------------------------------------------------- void LLVertexBuffer::freeClientBuffer() { if(useVBOs() && sDisableVBOMapping && (mMappedData || mMappedIndexData)) { delete[] mMappedData ; delete[] mMappedIndexData ; mMappedData = NULL ; mMappedIndexData = NULL ; } }
//---------------------------------------------------------------------------- void LLVertexBuffer::freeClientBuffer() { if(useVBOs() && sDisableVBOMapping && (mMappedData || mMappedIndexData)) { ll_aligned_free_16((void*)mMappedData) ; ll_aligned_free_16((void*)mMappedIndexData) ; mMappedData = NULL ; mMappedIndexData = NULL ; } }
// virtual (default) void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); stop_glerror(); U8* base = useVBOs() ? NULL : mMappedData; S32 stride = mStride; if ((data_mask & mTypeMask) != data_mask) { llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; } if (data_mask & MAP_VERTEX) { glVertexPointer(3,GL_FLOAT, stride, (void*)(base + 0)); } if (data_mask & MAP_NORMAL) { glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL])); } if (data_mask & MAP_TEXCOORD2) { glClientActiveTextureARB(GL_TEXTURE1_ARB); glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); } if (data_mask & MAP_TEXCOORD) { glClientActiveTextureARB(GL_TEXTURE0_ARB); glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD])); } if (data_mask & MAP_COLOR) { glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)(base + mOffsets[TYPE_COLOR])); } if (data_mask & MAP_BINORMAL) { glVertexAttribPointerARB(6, 3, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_BINORMAL])); } if (data_mask & MAP_WEIGHT) { glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_WEIGHT])); } if (data_mask & MAP_CLOTHWEIGHT) { glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); } llglassertok(); }
void LLVertexBuffer::makeStatic() { if (!sEnableVBOs) { return; } if (sRenderActive) { llerrs << "Make static called during render." << llendl; } if (mUsage != GL_STATIC_DRAW_ARB) { if (useVBOs()) { if (mGLBuffer) { sDeleteList.push_back(mGLBuffer); } if (mGLIndices) { sDeleteList.push_back(mGLIndices); } } if (mGLBuffer) { sGLCount++; glGenBuffersARB(1, (GLuint*) &mGLBuffer); } if (mGLIndices) { sGLCount++; glGenBuffersARB(1, (GLuint*) &mGLIndices); } mUsage = GL_STATIC_DRAW_ARB; mResized = TRUE; if (!mLocked) { mLocked = TRUE; sLockedList.push_back(this); } } }
void LLVertexBuffer::destroyGLIndices() { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mGLIndices) { if (useVBOs()) { sDeleteList.push_back(mGLIndices); } delete [] mMappedIndexData; mMappedIndexData = NULL; mEmpty = TRUE; sAllocatedBytes -= getIndicesSize(); } mGLIndices = 0; }
void LLVertexBuffer::unmapBuffer() { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mMappedData || mMappedIndexData) { if (useVBOs() && mLocked) { stop_glerror(); glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); stop_glerror(); glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); stop_glerror(); /*if (!sMapped) { llwarns << "Redundantly unmapped VBO!" << llendl; } sMapped = FALSE;*/ sMappedCount--; if (mUsage == GL_STATIC_DRAW_ARB) { //static draw buffers can only be mapped a single time //throw out client data (we won't be using it again) mEmpty = TRUE; mFinal = TRUE; } else { mEmpty = FALSE; } mMappedIndexData = NULL; mMappedData = NULL; mLocked = FALSE; } } }
void LLVertexBuffer::createGLIndices() { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); U32 size = getIndicesSize(); if (mGLIndices) { destroyGLIndices(); } if (size == 0) { return; } mEmpty = TRUE; //pad by 16 bytes for aligned copies size += 16; if (useVBOs()) { //pad by another 16 bytes for VBO pointer adjustment size += 16; mMappedIndexData = NULL; genIndices(); mResized = TRUE; } else { mMappedIndexData = (U8*) ll_aligned_malloc_16(size); if(!sOmitBlank) memset((void*)mMappedIndexData, 0, size); static int gl_buffer_idx = 0; mGLIndices = ++gl_buffer_idx; } }
// Set for rendering void LLVertexBuffer::setBuffer(U32 data_mask) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); //set up pointers if the data mask is different ... BOOL setup = (sLastMask != data_mask); if (useVBOs()) { if (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive)) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer); sVBOActive = TRUE; setup = TRUE; // ... or the bound buffer changed } if (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive)) { glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices); sIBOActive = TRUE; } unmapBuffer(); } else { if (mGLBuffer) { if (sEnableVBOs && sVBOActive) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); sVBOActive = FALSE; setup = TRUE; // ... or a VBO is deactivated } if (sGLRenderBuffer != mGLBuffer) { setup = TRUE; // ... or a client memory pointer changed } } if (sEnableVBOs && mGLIndices && sIBOActive) { glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); sIBOActive = FALSE; } } if (mGLIndices) { sGLRenderIndices = mGLIndices; } if (mGLBuffer) { sGLRenderBuffer = mGLBuffer; if (data_mask && setup) { if (!sRenderActive) { llwarns << "Vertex buffer set for rendering outside of render frame." << llendl; } setupVertexBuffer(data_mask); // subclass specific setup (virtual function) sLastMask = data_mask; } } }
void LLVertexBuffer::unmapBuffer() { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mMappedData || mMappedIndexData) { if (useVBOs() && mLocked) { if (mGLBuffer) { if (mResized) { glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), mMappedData, mUsage); } else { if (mEmpty || mDirtyRegions.empty()) { glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData); } else { for (std::vector<DirtyRegion>::iterator i = mDirtyRegions.begin(); i != mDirtyRegions.end(); ++i) { DirtyRegion& region = *i; glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, region.mIndex*mStride, region.mCount*mStride, mMappedData + region.mIndex*mStride); } } } } if (mGLIndices) { if (mResized) { glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), mMappedIndexData, mUsage); } else { if (mEmpty || mDirtyRegions.empty()) { glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData); } else { for (std::vector<DirtyRegion>::iterator i = mDirtyRegions.begin(); i != mDirtyRegions.end(); ++i) { DirtyRegion& region = *i; glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, region.mIndicesIndex*sizeof(U32), region.mIndicesCount*sizeof(U32), mMappedIndexData + region.mIndicesIndex*sizeof(U32)); } } } } mDirtyRegions.clear(); mFilthy = FALSE; mResized = FALSE; if (mUsage == GL_STATIC_DRAW_ARB) { //static draw buffers can only be mapped a single time //throw out client data (we won't be using it again) delete [] mMappedData; delete [] mMappedIndexData; mMappedIndexData = NULL; mMappedData = NULL; mEmpty = TRUE; mFinal = TRUE; } else { mEmpty = FALSE; } mLocked = FALSE; glFlush(); } } }
// Set for rendering void LLVertexBuffer::setBuffer(U32 data_mask, S32 type) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); //set up pointers if the data mask is different ... BOOL setup = (sLastMask != data_mask); if (useVBOs()) { if (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive)) { /*if (sMapped) { llerrs << "VBO bound while another VBO mapped!" << llendl; }*/ stop_glerror(); glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer); stop_glerror(); sBindCount++; sVBOActive = TRUE; setup = TRUE; // ... or the bound buffer changed } if (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive)) { /*if (sMapped) { llerrs << "VBO bound while another VBO mapped!" << llendl; }*/ stop_glerror(); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices); stop_glerror(); sBindCount++; sIBOActive = TRUE; } BOOL error = FALSE; if (gDebugGL) { GLint buff; glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLBuffer) { llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; } if (mGLIndices) { glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLIndices) { llerrs << "Invalid GL index buffer bound: " << buff << llendl; } } } if (mResized) { if (gDebugGL) { GLint buff; glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLBuffer) { llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; } if (mGLIndices != 0) { glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLIndices) { llerrs << "Invalid GL index buffer bound: " << buff << llendl; } } } if (mGLBuffer) { stop_glerror(); glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), NULL, mUsage); stop_glerror(); } if (mGLIndices) { stop_glerror(); glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), NULL, mUsage); stop_glerror(); } mEmpty = TRUE; mResized = FALSE; if (data_mask != 0) { llerrs << "Buffer set for rendering before being filled after resize." << llendl; } } if (error) { llerrs << "LLVertexBuffer::mapBuffer failed" << llendl; } unmapBuffer(type); } else { if (mGLBuffer) { if (sVBOActive) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); sBindCount++; sVBOActive = FALSE; setup = TRUE; // ... or a VBO is deactivated } if (sGLRenderBuffer != mGLBuffer) { setup = TRUE; // ... or a client memory pointer changed } } if (mGLIndices && sIBOActive) { /*if (sMapped) { llerrs << "VBO unbound while potentially mapped!" << llendl; }*/ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); sBindCount++; sIBOActive = FALSE; } } setupClientArrays(data_mask); if (mGLIndices) { sGLRenderIndices = mGLIndices; } if (mGLBuffer) { sGLRenderBuffer = mGLBuffer; if (data_mask && setup) { setupVertexBuffer(data_mask); // subclass specific setup (virtual function) sSetCount++; } } }
void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) { mRequestedNumVerts = newnverts; mRequestedNumIndices = newnindices; LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); 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()) { volatile U8* old = mMappedData; mMappedData = new U8[newsize]; if (old) { memcpy((void*)mMappedData, (void*)old, llmin(newsize, oldsize)); if ((newsize > oldsize) && !sOmitBlank) { memset((void*)(mMappedData+oldsize), 0, newsize-oldsize); } delete [] old; } else { if (!sOmitBlank) memset((void*)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 volatile U8* old = mMappedIndexData; mMappedIndexData = new U8[new_index_size]; if (old) { memcpy((void*)mMappedIndexData, (void*)old, llmin(new_index_size, old_index_size)); if ((new_index_size > old_index_size) && !sOmitBlank) { memset((void*)(mMappedIndexData+old_index_size), 0, new_index_size - old_index_size); } delete [] old; } else { if (!sOmitBlank) memset((void*)mMappedIndexData, 0, new_index_size); mEmpty = TRUE; } } mResized = TRUE; } } else if (mGLIndices) { destroyGLIndices(); } } if (mResized && useVBOs()) { freeClientBuffer() ; setBuffer(0); } }
void LLVertexBuffer::unmapBuffer(S32 type) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (!useVBOs()) { return ; //nothing to unmap } bool updated_all = false ; if (mMappedData && mVertexLocked && type != TYPE_INDEX) { updated_all = (mIndexLocked && type < 0) ; //both vertex and index buffers done updating if(sDisableVBOMapping) { stop_glerror(); glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), (void*)mMappedData); stop_glerror(); } else { stop_glerror(); glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); stop_glerror(); mMappedData = NULL; } mVertexLocked = FALSE ; sMappedCount--; } if(mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX)) { if(sDisableVBOMapping) { stop_glerror(); glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), (void*)mMappedIndexData); stop_glerror(); } else { stop_glerror(); glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); stop_glerror(); mMappedIndexData = NULL ; } mIndexLocked = FALSE ; sMappedCount--; } if(updated_all) { if(mUsage == GL_STATIC_DRAW_ARB) { //static draw buffers can only be mapped a single time //throw out client data (we won't be using it again) mEmpty = TRUE; mFinal = TRUE; if(sDisableVBOMapping) { freeClientBuffer() ; } } else { mEmpty = FALSE; } } }
// virtual (default) void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); stop_glerror(); volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; if ((data_mask & mTypeMask) != data_mask) { llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask. Missing: "; static const char* mask_names[] = {"VERTEX","NORMAL","TEXCOORD0","TEXCOORD1","TEXCOORD2","TEXCOORD3","COLOR","BINORMAL","WEIGHT","WEIGHT4","CLOTH_WEIGHT"}; for(int i = 0; i < 32; ++i) { if((data_mask & (1<<i)) && !(mTypeMask & (1<<i))) { if(i < (sizeof(mask_names)/sizeof(mask_names[0]))) llcont << "MAP_" << mask_names[i] << ", "; else llcont << "MAP_UNKNOWN (1<<" << i << "), "; } } llcont << "\n Has: "; for(int i = 0; i < 32; ++i) { if(mTypeMask & (1<<i)) { if(i < (sizeof(mask_names)/sizeof(mask_names[0]))) llcont << "MASK_" << mask_names[i] << ", "; else llcont << "MAP_UNKNOWN (1<<" << i << "), "; } } llcont << llendl; } if (data_mask & MAP_NORMAL) { glNormalPointer(GL_FLOAT, getStride(TYPE_NORMAL), (void*)(base + mOffsets[TYPE_NORMAL])); } if (data_mask & MAP_TEXCOORD3) { glClientActiveTextureARB(GL_TEXTURE3_ARB); glTexCoordPointer(2,GL_FLOAT, getStride(TYPE_TEXCOORD3), (void*)(base + mOffsets[TYPE_TEXCOORD3])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD2) { glClientActiveTextureARB(GL_TEXTURE2_ARB); glTexCoordPointer(2,GL_FLOAT, getStride(TYPE_TEXCOORD2), (void*)(base + mOffsets[TYPE_TEXCOORD2])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD1) { glClientActiveTextureARB(GL_TEXTURE1_ARB); glTexCoordPointer(2,GL_FLOAT, getStride(TYPE_TEXCOORD1), (void*)(base + mOffsets[TYPE_TEXCOORD1])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_BINORMAL) { glClientActiveTextureARB(GL_TEXTURE2_ARB); glTexCoordPointer(3,GL_FLOAT, getStride(TYPE_BINORMAL), (void*)(base + mOffsets[TYPE_BINORMAL])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD0) { glTexCoordPointer(2,GL_FLOAT, getStride(TYPE_TEXCOORD0), (void*)(base + mOffsets[TYPE_TEXCOORD0])); } if (data_mask & MAP_COLOR) { glColorPointer(4, GL_UNSIGNED_BYTE, getStride(TYPE_COLOR), (void*)(base + mOffsets[TYPE_COLOR])); } if (data_mask & MAP_WEIGHT) { glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, getStride(TYPE_WEIGHT), (void*)(base + mOffsets[TYPE_WEIGHT])); } if (data_mask & MAP_WEIGHT4 && sWeight4Loc != -1) { glVertexAttribPointerARB(sWeight4Loc, 4, GL_FLOAT, FALSE, getStride(TYPE_WEIGHT4), (void*)(base+mOffsets[TYPE_WEIGHT4])); } if (data_mask & MAP_CLOTHWEIGHT) { glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, getStride(TYPE_CLOTHWEIGHT), (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); } if (data_mask & MAP_VERTEX) { glVertexPointer(3,GL_FLOAT, getStride(TYPE_VERTEX), (void*)(base + 0)); } llglassertok(); }
// Map for data access volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mFinal) { llerrs << "LLVertexBuffer::mapVeretxBuffer() called on a finalized buffer." << llendl; } if (!useVBOs() && !mMappedData && !mMappedIndexData) { llerrs << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << llendl; } if (!mVertexLocked && useVBOs()) { { setBuffer(0, type); mVertexLocked = TRUE; stop_glerror(); if(sDisableVBOMapping) { allocateClientVertexBuffer() ; } else { mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); } stop_glerror(); } if (!mMappedData) { 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 ; //-------------------- 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 { llerrs << "memory allocation for vertex data failed." << llendl ; } } sMappedCount++; } return mMappedData; }