00001
00032 #include "linden_common.h"
00033
00034 #include "llvertexbuffer.h"
00035
00036 #include "llglheaders.h"
00037 #include "llmemory.h"
00038 #include "llmemtype.h"
00039
00040
00041
00042
00043 S32 LLVertexBuffer::sCount = 0;
00044 S32 LLVertexBuffer::sGLCount = 0;
00045 BOOL LLVertexBuffer::sEnableVBOs = TRUE;
00046 U32 LLVertexBuffer::sGLRenderBuffer = 0;
00047 U32 LLVertexBuffer::sGLRenderIndices = 0;
00048 U32 LLVertexBuffer::sLastMask = 0;
00049 BOOL LLVertexBuffer::sVBOActive = FALSE;
00050 BOOL LLVertexBuffer::sIBOActive = FALSE;
00051 U32 LLVertexBuffer::sAllocatedBytes = 0;
00052 BOOL LLVertexBuffer::sRenderActive = FALSE;
00053
00054 std::vector<U32> LLVertexBuffer::sDeleteList;
00055 LLVertexBuffer::buffer_list_t LLVertexBuffer::sLockedList;
00056
00057 S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] =
00058 {
00059 sizeof(LLVector3),
00060 sizeof(LLVector3),
00061 sizeof(LLVector2),
00062 sizeof(LLVector2),
00063 sizeof(LLColor4U),
00064 sizeof(LLVector3),
00065 sizeof(F32),
00066 sizeof(LLVector4),
00067 };
00068
00069
00070 void LLVertexBuffer::initClass(bool use_vbo)
00071 {
00072 sEnableVBOs = use_vbo;
00073 }
00074
00075
00076 void LLVertexBuffer::unbind()
00077 {
00078 if (sVBOActive)
00079 {
00080 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
00081 sVBOActive = FALSE;
00082 }
00083 if (sIBOActive)
00084 {
00085 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
00086 sIBOActive = FALSE;
00087 }
00088
00089 sGLRenderBuffer = 0;
00090 sGLRenderIndices = 0;
00091 }
00092
00093
00094 void LLVertexBuffer::cleanupClass()
00095 {
00096 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00097 sLockedList.clear();
00098 startRender();
00099 stopRender();
00100 clientCopy();
00101 }
00102
00103
00104 void LLVertexBuffer::startRender()
00105 {
00106 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00107 if (sEnableVBOs)
00108 {
00109 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
00110 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
00111 sVBOActive = FALSE;
00112 sIBOActive = FALSE;
00113 }
00114
00115 sRenderActive = TRUE;
00116 sGLRenderBuffer = 0;
00117 sGLRenderIndices = 0;
00118 sLastMask = 0;
00119 }
00120
00121 void LLVertexBuffer::stopRender()
00122 {
00123 sRenderActive = FALSE;
00124 }
00125
00126 void LLVertexBuffer::clientCopy(F64 max_time)
00127 {
00128 if (!sDeleteList.empty())
00129 {
00130 size_t num = sDeleteList.size();
00131 glDeleteBuffersARB(sDeleteList.size(), (GLuint*) &(sDeleteList[0]));
00132 sDeleteList.clear();
00133 sGLCount -= num;
00134 }
00135
00136 if (sEnableVBOs)
00137 {
00138 LLTimer timer;
00139 BOOL reset = TRUE;
00140 buffer_list_t::iterator iter = sLockedList.begin();
00141 while(iter != sLockedList.end())
00142 {
00143 LLVertexBuffer* buffer = *iter;
00144 if (buffer->isLocked() && buffer->useVBOs())
00145 {
00146 buffer->setBuffer(0);
00147 }
00148 ++iter;
00149 if (reset)
00150 {
00151 reset = FALSE;
00152 timer.reset();
00153 }
00154 else
00155 {
00156 if (timer.getElapsedTimeF64() > max_time)
00157 {
00158 break;
00159 }
00160 }
00161
00162 }
00163
00164 sLockedList.erase(sLockedList.begin(), iter);
00165 }
00166 }
00167
00168
00169
00170 LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
00171 LLRefCount(),
00172 mNumVerts(0), mNumIndices(0), mUsage(usage), mGLBuffer(0), mGLIndices(0),
00173 mMappedData(NULL),
00174 mMappedIndexData(NULL), mLocked(FALSE),
00175 mFinal(FALSE),
00176 mFilthy(FALSE),
00177 mEmpty(TRUE),
00178 mResized(FALSE)
00179 {
00180 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00181 if (!sEnableVBOs)
00182 {
00183 mUsage = GL_STREAM_DRAW_ARB;
00184 }
00185
00186 S32 stride = 0;
00187 for (S32 i=0; i<TYPE_MAX; i++)
00188 {
00189 U32 mask = 1<<i;
00190 if (typemask & mask)
00191 {
00192 mOffsets[i] = stride;
00193 stride += sTypeOffsets[i];
00194 }
00195 }
00196 mTypeMask = typemask;
00197 mStride = stride;
00198 sCount++;
00199 }
00200
00201
00202
00203 LLVertexBuffer::~LLVertexBuffer()
00204 {
00205 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00206 destroyGLBuffer();
00207 destroyGLIndices();
00208 sCount--;
00209
00210 if (mLocked)
00211 {
00212
00213 for (buffer_list_t::iterator i = sLockedList.begin(); i != sLockedList.end(); ++i)
00214 {
00215 if (*i == this)
00216 {
00217 sLockedList.erase(i);
00218 break;
00219 }
00220 }
00221 }
00222 };
00223
00224
00225
00226 void LLVertexBuffer::createGLBuffer()
00227 {
00228 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00229
00230 U32 size = getSize();
00231 if (mGLBuffer)
00232 {
00233 destroyGLBuffer();
00234 }
00235
00236 if (size == 0)
00237 {
00238 return;
00239 }
00240
00241 mMappedData = new U8[size];
00242 memset(mMappedData, 0, size);
00243 mEmpty = TRUE;
00244
00245 if (useVBOs())
00246 {
00247 glGenBuffersARB(1, (GLuint*) &mGLBuffer);
00248 mResized = TRUE;
00249 sGLCount++;
00250 }
00251 else
00252 {
00253 static int gl_buffer_idx = 0;
00254 mGLBuffer = ++gl_buffer_idx;
00255 }
00256 }
00257
00258 void LLVertexBuffer::createGLIndices()
00259 {
00260 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00261 U32 size = getIndicesSize();
00262
00263 if (mGLIndices)
00264 {
00265 destroyGLIndices();
00266 }
00267
00268 if (size == 0)
00269 {
00270 return;
00271 }
00272
00273 mMappedIndexData = new U8[size];
00274 memset(mMappedIndexData, 0, size);
00275 mEmpty = TRUE;
00276
00277 if (useVBOs())
00278 {
00279 glGenBuffersARB(1, (GLuint*) &mGLIndices);
00280 mResized = TRUE;
00281 sGLCount++;
00282 }
00283 else
00284 {
00285 static int gl_buffer_idx = 0;
00286 mGLIndices = ++gl_buffer_idx;
00287 }
00288 }
00289
00290 void LLVertexBuffer::destroyGLBuffer()
00291 {
00292 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00293 if (mGLBuffer)
00294 {
00295 if (useVBOs())
00296 {
00297 sDeleteList.push_back(mGLBuffer);
00298 }
00299
00300 delete [] mMappedData;
00301 mMappedData = NULL;
00302 mEmpty = TRUE;
00303 sAllocatedBytes -= getSize();
00304 }
00305
00306 mGLBuffer = 0;
00307 }
00308
00309 void LLVertexBuffer::destroyGLIndices()
00310 {
00311 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00312 if (mGLIndices)
00313 {
00314 if (useVBOs())
00315 {
00316 sDeleteList.push_back(mGLIndices);
00317 }
00318
00319 delete [] mMappedIndexData;
00320 mMappedIndexData = NULL;
00321 mEmpty = TRUE;
00322 sAllocatedBytes -= getIndicesSize();
00323 }
00324
00325 mGLIndices = 0;
00326 }
00327
00328 void LLVertexBuffer::updateNumVerts(S32 nverts)
00329 {
00330 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00331 if (!mDynamicSize)
00332 {
00333 mNumVerts = nverts;
00334 }
00335 else if (mUsage == GL_STATIC_DRAW_ARB ||
00336 nverts > mNumVerts ||
00337 nverts < mNumVerts/2)
00338 {
00339 if (mUsage != GL_STATIC_DRAW_ARB)
00340 {
00341 nverts += nverts/4;
00342 }
00343
00344 mNumVerts = nverts;
00345 }
00346 }
00347
00348 void LLVertexBuffer::updateNumIndices(S32 nindices)
00349 {
00350 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00351 if (!mDynamicSize)
00352 {
00353 mNumIndices = nindices;
00354 }
00355 else if (mUsage == GL_STATIC_DRAW_ARB ||
00356 nindices > mNumIndices ||
00357 nindices < mNumIndices/2)
00358 {
00359 if (mUsage != GL_STATIC_DRAW_ARB)
00360 {
00361 nindices += nindices/4;
00362 }
00363
00364 mNumIndices = nindices;
00365 }
00366 }
00367
00368 void LLVertexBuffer::makeStatic()
00369 {
00370 if (!sEnableVBOs)
00371 {
00372 return;
00373 }
00374
00375 if (sRenderActive)
00376 {
00377 llerrs << "Make static called during render." << llendl;
00378 }
00379
00380 if (mUsage != GL_STATIC_DRAW_ARB)
00381 {
00382 if (useVBOs())
00383 {
00384 if (mGLBuffer)
00385 {
00386 sDeleteList.push_back(mGLBuffer);
00387 }
00388 if (mGLIndices)
00389 {
00390 sDeleteList.push_back(mGLIndices);
00391 }
00392 }
00393
00394 if (mGLBuffer)
00395 {
00396 sGLCount++;
00397 glGenBuffersARB(1, (GLuint*) &mGLBuffer);
00398 }
00399 if (mGLIndices)
00400 {
00401 sGLCount++;
00402 glGenBuffersARB(1, (GLuint*) &mGLIndices);
00403 }
00404
00405 mUsage = GL_STATIC_DRAW_ARB;
00406 mResized = TRUE;
00407
00408 if (!mLocked)
00409 {
00410 mLocked = TRUE;
00411 sLockedList.push_back(this);
00412 }
00413 }
00414 }
00415
00416 void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
00417 {
00418 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00419
00420 updateNumVerts(nverts);
00421 updateNumIndices(nindices);
00422
00423 if (mMappedData)
00424 {
00425 llerrs << "LLVertexBuffer::allocateBuffer() called redundantly." << llendl;
00426 }
00427 if (create && (nverts || nindices))
00428 {
00429 createGLBuffer();
00430 createGLIndices();
00431 }
00432
00433 sAllocatedBytes += getSize() + getIndicesSize();
00434 }
00435
00436 void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
00437 {
00438 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00439 mDynamicSize = TRUE;
00440 if (mUsage == GL_STATIC_DRAW_ARB)
00441 {
00442 destroyGLBuffer();
00443 destroyGLIndices();
00444 allocateBuffer(newnverts, newnindices, TRUE);
00445 mFinal = FALSE;
00446 }
00447 else if (newnverts > mNumVerts || newnindices > mNumIndices ||
00448 newnverts < mNumVerts/2 || newnindices < mNumIndices/2)
00449 {
00450 sAllocatedBytes -= getSize() + getIndicesSize();
00451
00452 S32 oldsize = getSize();
00453 S32 old_index_size = getIndicesSize();
00454
00455 updateNumVerts(newnverts);
00456 updateNumIndices(newnindices);
00457
00458 S32 newsize = getSize();
00459 S32 new_index_size = getIndicesSize();
00460
00461 sAllocatedBytes += newsize + new_index_size;
00462
00463 if (newsize)
00464 {
00465 if (!mGLBuffer)
00466 {
00467 createGLBuffer();
00468 }
00469 else
00470 {
00471
00472 U8* old = mMappedData;
00473 mMappedData = new U8[newsize];
00474 if (old)
00475 {
00476 memcpy(mMappedData, old, llmin(newsize, oldsize));
00477 if (newsize > oldsize)
00478 {
00479 memset(mMappedData+oldsize, 0, newsize-oldsize);
00480 }
00481
00482 delete [] old;
00483 }
00484 else
00485 {
00486 memset(mMappedData, 0, newsize);
00487 mEmpty = TRUE;
00488 }
00489 mResized = TRUE;
00490 }
00491 }
00492 else if (mGLBuffer)
00493 {
00494 destroyGLBuffer();
00495 }
00496
00497 if (new_index_size)
00498 {
00499 if (!mGLIndices)
00500 {
00501 createGLIndices();
00502 }
00503 else
00504 {
00505
00506 U8* old = mMappedIndexData;
00507 mMappedIndexData = new U8[new_index_size];
00508 if (old)
00509 {
00510 memcpy(mMappedIndexData, old, llmin(new_index_size, old_index_size));
00511 if (new_index_size > old_index_size)
00512 {
00513 memset(mMappedIndexData+old_index_size, 0, new_index_size - old_index_size);
00514 }
00515 delete [] old;
00516 }
00517 else
00518 {
00519 memset(mMappedIndexData, 0, new_index_size);
00520 mEmpty = TRUE;
00521 }
00522 mResized = TRUE;
00523 }
00524 }
00525 else if (mGLIndices)
00526 {
00527 destroyGLIndices();
00528 }
00529 }
00530 }
00531
00532 BOOL LLVertexBuffer::useVBOs() const
00533 {
00534
00535
00536 if (mUsage == GL_STREAM_DRAW_ARB)
00537 {
00538 return FALSE;
00539 }
00540
00541 return sEnableVBOs && (!sRenderActive || !mLocked);
00542 }
00543
00544
00545
00546
00547 U8* LLVertexBuffer::mapBuffer(S32 access)
00548 {
00549 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00550 if (sRenderActive)
00551 {
00552 llwarns << "Buffer mapped during render frame!" << llendl;
00553 }
00554 if (!mGLBuffer && !mGLIndices)
00555 {
00556 llerrs << "LLVertexBuffer::mapBuffer() called before createGLBuffer" << llendl;
00557 }
00558 if (mFinal)
00559 {
00560 llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl;
00561 }
00562 if (!mMappedData && !mMappedIndexData)
00563 {
00564 llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl;
00565 }
00566
00567 if (!mLocked && useVBOs())
00568 {
00569 mLocked = TRUE;
00570 sLockedList.push_back(this);
00571 }
00572
00573 return mMappedData;
00574 }
00575
00576 void LLVertexBuffer::unmapBuffer()
00577 {
00578 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00579 if (mMappedData || mMappedIndexData)
00580 {
00581 if (useVBOs() && mLocked)
00582 {
00583 if (mGLBuffer)
00584 {
00585 if (mResized)
00586 {
00587 glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), mMappedData, mUsage);
00588 }
00589 else
00590 {
00591 if (mEmpty || mDirtyRegions.empty())
00592 {
00593 glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
00594 }
00595 else
00596 {
00597 for (std::vector<DirtyRegion>::iterator i = mDirtyRegions.begin(); i != mDirtyRegions.end(); ++i)
00598 {
00599 DirtyRegion& region = *i;
00600 glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, region.mIndex*mStride, region.mCount*mStride, mMappedData + region.mIndex*mStride);
00601 }
00602 }
00603 }
00604 }
00605
00606 if (mGLIndices)
00607 {
00608 if (mResized)
00609 {
00610 glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), mMappedIndexData, mUsage);
00611 }
00612 else
00613 {
00614 if (mEmpty || mDirtyRegions.empty())
00615 {
00616 glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
00617 }
00618 else
00619 {
00620 for (std::vector<DirtyRegion>::iterator i = mDirtyRegions.begin(); i != mDirtyRegions.end(); ++i)
00621 {
00622 DirtyRegion& region = *i;
00623 glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, region.mIndicesIndex*sizeof(U32),
00624 region.mIndicesCount*sizeof(U32), mMappedIndexData + region.mIndicesIndex*sizeof(U32));
00625 }
00626 }
00627 }
00628 }
00629
00630 mDirtyRegions.clear();
00631 mFilthy = FALSE;
00632 mResized = FALSE;
00633
00634 if (mUsage == GL_STATIC_DRAW_ARB)
00635 {
00636
00637 delete [] mMappedData;
00638 delete [] mMappedIndexData;
00639 mMappedIndexData = NULL;
00640 mMappedData = NULL;
00641 mEmpty = TRUE;
00642 mFinal = TRUE;
00643 }
00644 else
00645 {
00646 mEmpty = FALSE;
00647 }
00648
00649 mLocked = FALSE;
00650
00651 glFlush();
00652 }
00653 }
00654 }
00655
00656
00657
00658 template <class T,S32 type> struct VertexBufferStrider
00659 {
00660 typedef LLStrider<T> strider_t;
00661 static bool get(LLVertexBuffer& vbo,
00662 strider_t& strider,
00663 S32 index)
00664 {
00665 vbo.mapBuffer();
00666 if (type == LLVertexBuffer::TYPE_INDEX)
00667 {
00668 S32 stride = sizeof(T);
00669 strider = (T*)(vbo.getMappedIndices() + index*stride);
00670 strider.setStride(0);
00671 return TRUE;
00672 }
00673 else if (vbo.hasDataType(type))
00674 {
00675 S32 stride = vbo.getStride();
00676 strider = (T*)(vbo.getMappedData() + vbo.getOffset(type) + index*stride);
00677 strider.setStride(stride);
00678 return TRUE;
00679 }
00680 else
00681 {
00682 llerrs << "VertexBufferStrider could not find valid vertex data." << llendl;
00683 }
00684 return FALSE;
00685 }
00686 };
00687
00688
00689 bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index)
00690 {
00691 return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index);
00692 }
00693 bool LLVertexBuffer::getIndexStrider(LLStrider<U32>& strider, S32 index)
00694 {
00695 return VertexBufferStrider<U32,TYPE_INDEX>::get(*this, strider, index);
00696 }
00697 bool LLVertexBuffer::getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index)
00698 {
00699 return VertexBufferStrider<LLVector2,TYPE_TEXCOORD>::get(*this, strider, index);
00700 }
00701 bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index)
00702 {
00703 return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index);
00704 }
00705 bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index)
00706 {
00707 return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index);
00708 }
00709 bool LLVertexBuffer::getBinormalStrider(LLStrider<LLVector3>& strider, S32 index)
00710 {
00711 return VertexBufferStrider<LLVector3,TYPE_BINORMAL>::get(*this, strider, index);
00712 }
00713 bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index)
00714 {
00715 return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index);
00716 }
00717 bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index)
00718 {
00719 return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index);
00720 }
00721 bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index)
00722 {
00723 return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index);
00724 }
00725
00726 void LLVertexBuffer::setStride(S32 type, S32 new_stride)
00727 {
00728 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00729 if (mNumVerts)
00730 {
00731 llerrs << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl;
00732 }
00733
00734 S32 delta = new_stride - sTypeOffsets[type];
00735 for (S32 i=type+1; i<TYPE_MAX; i++)
00736 {
00737 if (mTypeMask & (1<<i))
00738 {
00739 mOffsets[i] += delta;
00740 }
00741 }
00742 mStride += delta;
00743 }
00744
00745
00746
00747
00748 void LLVertexBuffer::setBuffer(U32 data_mask)
00749 {
00750 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00751
00752 BOOL setup = (sLastMask != data_mask);
00753
00754 if (useVBOs())
00755 {
00756 if (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))
00757 {
00758 glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
00759 sVBOActive = TRUE;
00760 setup = TRUE;
00761 }
00762 if (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive))
00763 {
00764 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
00765 sIBOActive = TRUE;
00766 }
00767
00768 unmapBuffer();
00769 }
00770 else
00771 {
00772 if (mGLBuffer)
00773 {
00774 if (sEnableVBOs && sVBOActive)
00775 {
00776 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
00777 sVBOActive = FALSE;
00778 setup = TRUE;
00779 }
00780 if (sGLRenderBuffer != mGLBuffer)
00781 {
00782 setup = TRUE;
00783 }
00784 }
00785 if (sEnableVBOs && mGLIndices && sIBOActive)
00786 {
00787 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
00788 sIBOActive = FALSE;
00789 }
00790 }
00791
00792 if (mGLIndices)
00793 {
00794 sGLRenderIndices = mGLIndices;
00795 }
00796 if (mGLBuffer)
00797 {
00798 sGLRenderBuffer = mGLBuffer;
00799 if (data_mask && setup)
00800 {
00801 if (!sRenderActive)
00802 {
00803 llwarns << "Vertex buffer set for rendering outside of render frame." << llendl;
00804 }
00805 setupVertexBuffer(data_mask);
00806 sLastMask = data_mask;
00807 }
00808 }
00809 }
00810
00811
00812 void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
00813 {
00814 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00815 stop_glerror();
00816 U8* base = useVBOs() ? NULL : mMappedData;
00817 S32 stride = mStride;
00818
00819 if ((data_mask & mTypeMask) != data_mask)
00820 {
00821 llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl;
00822 }
00823
00824 if (data_mask & MAP_VERTEX)
00825 {
00826 glVertexPointer(3,GL_FLOAT, stride, (void*)(base + 0));
00827 }
00828 if (data_mask & MAP_NORMAL)
00829 {
00830 glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL]));
00831 }
00832 if (data_mask & MAP_TEXCOORD2)
00833 {
00834 glClientActiveTextureARB(GL_TEXTURE1_ARB);
00835 glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD2]));
00836 }
00837 if (data_mask & MAP_TEXCOORD)
00838 {
00839 glClientActiveTextureARB(GL_TEXTURE0_ARB);
00840 glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD]));
00841 }
00842 if (data_mask & MAP_COLOR)
00843 {
00844 glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)(base + mOffsets[TYPE_COLOR]));
00845 }
00846 if (data_mask & MAP_BINORMAL)
00847 {
00848 glVertexAttribPointerARB(6, 3, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_BINORMAL]));
00849 }
00850 if (data_mask & MAP_WEIGHT)
00851 {
00852 glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_WEIGHT]));
00853 }
00854 if (data_mask & MAP_CLOTHWEIGHT)
00855 {
00856 glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]));
00857 }
00858
00859 llglassertok();
00860 }
00861
00862 void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count)
00863 {
00864 if (useVBOs() && !mFilthy)
00865 {
00866 if (!mDirtyRegions.empty())
00867 {
00868 DirtyRegion& region = *(mDirtyRegions.rbegin());
00869
00870 if (region.mIndex+region.mCount > vert_index)
00871 {
00872
00873 mFilthy = TRUE;
00874 mDirtyRegions.clear();
00875 return;
00876 }
00877
00878 if (region.mIndex + region.mCount == vert_index &&
00879 region.mIndicesIndex + region.mIndicesCount == indices_index)
00880 {
00881 region.mCount += vert_count;
00882 region.mIndicesCount += indices_count;
00883 return;
00884 }
00885 }
00886
00887 mDirtyRegions.push_back(DirtyRegion(vert_index,vert_count,indices_index,indices_count));
00888 }
00889 }
00890
00891 void LLVertexBuffer::markClean()
00892 {
00893 if (!mResized && !mEmpty && !mFilthy)
00894 {
00895 buffer_list_t::reverse_iterator iter = sLockedList.rbegin();
00896 if (*iter == this)
00897 {
00898 mLocked = FALSE;
00899 sLockedList.pop_back();
00900 }
00901 }
00902 }
00903