00001
00032 #include "linden_common.h"
00033
00034 #include <boost/static_assert.hpp>
00035
00036 #include "llvertexbuffer.h"
00037
00038 #include "llglheaders.h"
00039 #include "llmemory.h"
00040 #include "llmemtype.h"
00041 #include "llglimmediate.h"
00042
00043
00044
00045
00046 LLVBOPool LLVertexBuffer::sStreamVBOPool;
00047 LLVBOPool LLVertexBuffer::sDynamicVBOPool;
00048 LLVBOPool LLVertexBuffer::sStreamIBOPool;
00049 LLVBOPool LLVertexBuffer::sDynamicIBOPool;
00050
00051 U32 LLVertexBuffer::sBindCount = 0;
00052 U32 LLVertexBuffer::sSetCount = 0;
00053 S32 LLVertexBuffer::sCount = 0;
00054 S32 LLVertexBuffer::sGLCount = 0;
00055 S32 LLVertexBuffer::sMappedCount = 0;
00056 BOOL LLVertexBuffer::sEnableVBOs = TRUE;
00057 U32 LLVertexBuffer::sGLRenderBuffer = 0;
00058 U32 LLVertexBuffer::sGLRenderIndices = 0;
00059 U32 LLVertexBuffer::sLastMask = 0;
00060 BOOL LLVertexBuffer::sVBOActive = FALSE;
00061 BOOL LLVertexBuffer::sIBOActive = FALSE;
00062 U32 LLVertexBuffer::sAllocatedBytes = 0;
00063 BOOL LLVertexBuffer::sMapped = FALSE;
00064
00065 std::vector<U32> LLVertexBuffer::sDeleteList;
00066
00067 S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] =
00068 {
00069 sizeof(LLVector3),
00070 sizeof(LLVector3),
00071 sizeof(LLVector2),
00072 sizeof(LLVector2),
00073 sizeof(LLColor4U),
00074 sizeof(LLVector3),
00075 sizeof(F32),
00076 sizeof(LLVector4),
00077 };
00078
00079 U32 LLVertexBuffer::sGLMode[LLVertexBuffer::NUM_MODES] =
00080 {
00081 GL_TRIANGLES,
00082 GL_TRIANGLE_STRIP,
00083 GL_TRIANGLE_FAN,
00084 GL_POINTS,
00085 GL_LINES,
00086 GL_LINE_STRIP,
00087 GL_QUADS,
00088 GL_LINE_LOOP,
00089 };
00090
00091
00092 void LLVertexBuffer::setupClientArrays(U32 data_mask)
00093 {
00094
00095
00096
00097
00098
00099 if (sLastMask != data_mask)
00100 {
00101 U32 mask[] =
00102 {
00103 MAP_VERTEX,
00104 MAP_NORMAL,
00105 MAP_TEXCOORD,
00106 MAP_COLOR
00107 };
00108
00109 GLenum array[] =
00110 {
00111 GL_VERTEX_ARRAY,
00112 GL_NORMAL_ARRAY,
00113 GL_TEXTURE_COORD_ARRAY,
00114 GL_COLOR_ARRAY
00115 };
00116
00117 for (U32 i = 0; i < 4; ++i)
00118 {
00119 if (sLastMask & mask[i])
00120 {
00121 if (!(data_mask & mask[i]) && i > 0)
00122 {
00123 glDisableClientState(array[i]);
00124 }
00125 else
00126 {
00127 if (i > 0 && !glIsEnabled(array[i]))
00128 {
00129 llerrs << "Bad client state! " << array[i] << " disabled." << llendl;
00130 }
00131 }
00132 }
00133 else
00134 {
00135 if (data_mask & mask[i])
00136 {
00137 glEnableClientState(array[i]);
00138 }
00139 else if (glIsEnabled(array[i]))
00140 {
00141 llerrs << "Bad client state! " << array[i] << " enabled." << llendl;
00142 }
00143 }
00144 }
00145
00146 if (sLastMask & MAP_TEXCOORD2)
00147 {
00148 if (!(data_mask & MAP_TEXCOORD2))
00149 {
00150 glClientActiveTextureARB(GL_TEXTURE1_ARB);
00151 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00152 glClientActiveTextureARB(GL_TEXTURE0_ARB);
00153 }
00154 }
00155 else if (data_mask & MAP_TEXCOORD2)
00156 {
00157 glClientActiveTextureARB(GL_TEXTURE1_ARB);
00158 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00159 glClientActiveTextureARB(GL_TEXTURE0_ARB);
00160 }
00161
00162 sLastMask = data_mask;
00163 }
00164 }
00165
00166 void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
00167 {
00168 if (start >= (U32) mRequestedNumVerts ||
00169 end >= (U32) mRequestedNumVerts)
00170 {
00171 llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl;
00172 }
00173
00174 if (indices_offset >= (U32) mRequestedNumIndices ||
00175 indices_offset + count > (U32) mRequestedNumIndices)
00176 {
00177 llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
00178 }
00179
00180 if (mGLIndices != sGLRenderIndices)
00181 {
00182 llerrs << "Wrong index buffer bound." << llendl;
00183 }
00184
00185 if (mGLBuffer != sGLRenderBuffer)
00186 {
00187 llerrs << "Wrong vertex buffer bound." << llendl;
00188 }
00189
00190 if (mode > NUM_MODES)
00191 {
00192 llerrs << "Invalid draw mode: " << mode << llendl;
00193 }
00194
00195 glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
00196 ((U16*) getIndicesPointer()) + indices_offset);
00197 }
00198
00199 void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
00200 {
00201 if (indices_offset >= (U32) mRequestedNumIndices ||
00202 indices_offset + count > (U32) mRequestedNumIndices)
00203 {
00204 llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
00205 }
00206
00207 if (mGLIndices != sGLRenderIndices)
00208 {
00209 llerrs << "Wrong index buffer bound." << llendl;
00210 }
00211
00212 if (mGLBuffer != sGLRenderBuffer)
00213 {
00214 llerrs << "Wrong vertex buffer bound." << llendl;
00215 }
00216
00217 if (mode > NUM_MODES)
00218 {
00219 llerrs << "Invalid draw mode: " << mode << llendl;
00220 }
00221
00222 glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
00223 ((U16*) getIndicesPointer()) + indices_offset);
00224 }
00225
00226 void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
00227 {
00228
00229 if (first >= (U32) mRequestedNumVerts ||
00230 first + count > (U32) mRequestedNumVerts)
00231 {
00232 llerrs << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl;
00233 }
00234
00235 if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive)
00236 {
00237 llerrs << "Wrong vertex buffer bound." << llendl;
00238 }
00239
00240 if (mode > NUM_MODES)
00241 {
00242 llerrs << "Invalid draw mode: " << mode << llendl;
00243 }
00244
00245 glDrawArrays(sGLMode[mode], first, count);
00246 }
00247
00248
00249 void LLVertexBuffer::initClass(bool use_vbo)
00250 {
00251 sEnableVBOs = use_vbo;
00252 LLGLNamePool::registerPool(&sDynamicVBOPool);
00253 LLGLNamePool::registerPool(&sDynamicIBOPool);
00254 LLGLNamePool::registerPool(&sStreamVBOPool);
00255 LLGLNamePool::registerPool(&sStreamIBOPool);
00256 }
00257
00258
00259 void LLVertexBuffer::unbind()
00260 {
00261 if (sVBOActive)
00262 {
00263 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
00264 sVBOActive = FALSE;
00265 }
00266 if (sIBOActive)
00267 {
00268 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
00269 sIBOActive = FALSE;
00270 }
00271
00272 sGLRenderBuffer = 0;
00273 sGLRenderIndices = 0;
00274
00275 setupClientArrays(0);
00276 }
00277
00278
00279 void LLVertexBuffer::cleanupClass()
00280 {
00281 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00282 unbind();
00283 clientCopy();
00284 }
00285
00286 void LLVertexBuffer::clientCopy(F64 max_time)
00287 {
00288 if (!sDeleteList.empty())
00289 {
00290 glDeleteBuffersARB(sDeleteList.size(), (GLuint*) &(sDeleteList[0]));
00291 sDeleteList.clear();
00292 }
00293 }
00294
00295
00296
00297 LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
00298 LLRefCount(),
00299 mNumVerts(0), mNumIndices(0), mUsage(usage), mGLBuffer(0), mGLIndices(0),
00300 mMappedData(NULL),
00301 mMappedIndexData(NULL), mLocked(FALSE),
00302 mFinal(FALSE),
00303 mFilthy(FALSE),
00304 mEmpty(TRUE),
00305 mResized(FALSE),
00306 mDynamicSize(FALSE)
00307 {
00308 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00309 if (!sEnableVBOs)
00310 {
00311 mUsage = 0 ;
00312 }
00313
00314 S32 stride = calcStride(typemask, mOffsets);
00315
00316 mTypeMask = typemask;
00317 mStride = stride;
00318 sCount++;
00319 }
00320
00321
00322 S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets)
00323 {
00324 S32 stride = 0;
00325 for (S32 i=0; i<TYPE_MAX; i++)
00326 {
00327 U32 mask = 1<<i;
00328 if (typemask & mask)
00329 {
00330 if (offsets)
00331 {
00332 offsets[i] = stride;
00333 }
00334 stride += sTypeOffsets[i];
00335 }
00336 }
00337
00338 return stride;
00339 }
00340
00341
00342
00343 LLVertexBuffer::~LLVertexBuffer()
00344 {
00345 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00346 destroyGLBuffer();
00347 destroyGLIndices();
00348 sCount--;
00349 };
00350
00351
00352
00353 void LLVertexBuffer::genBuffer()
00354 {
00355 if (mUsage == GL_STREAM_DRAW_ARB)
00356 {
00357 mGLBuffer = sStreamVBOPool.allocate();
00358 }
00359 else if (mUsage == GL_DYNAMIC_DRAW_ARB)
00360 {
00361 mGLBuffer = sDynamicVBOPool.allocate();
00362 }
00363 else
00364 {
00365 BOOST_STATIC_ASSERT(sizeof(mGLBuffer) == sizeof(GLuint));
00366 glGenBuffersARB(1, (GLuint*)&mGLBuffer);
00367 }
00368 sGLCount++;
00369 }
00370
00371 void LLVertexBuffer::genIndices()
00372 {
00373 if (mUsage == GL_STREAM_DRAW_ARB)
00374 {
00375 mGLIndices = sStreamIBOPool.allocate();
00376 }
00377 else if (mUsage == GL_DYNAMIC_DRAW_ARB)
00378 {
00379 mGLIndices = sDynamicIBOPool.allocate();
00380 }
00381 else
00382 {
00383 BOOST_STATIC_ASSERT(sizeof(mGLBuffer) == sizeof(GLuint));
00384 glGenBuffersARB(1, (GLuint*)&mGLIndices);
00385 }
00386 sGLCount++;
00387 }
00388
00389 void LLVertexBuffer::releaseBuffer()
00390 {
00391 if (mUsage == GL_STREAM_DRAW_ARB)
00392 {
00393 sStreamVBOPool.release(mGLBuffer);
00394 }
00395 else if (mUsage == GL_DYNAMIC_DRAW_ARB)
00396 {
00397 sDynamicVBOPool.release(mGLBuffer);
00398 }
00399 else
00400 {
00401 sDeleteList.push_back(mGLBuffer);
00402 }
00403 sGLCount--;
00404 }
00405
00406 void LLVertexBuffer::releaseIndices()
00407 {
00408 if (mUsage == GL_STREAM_DRAW_ARB)
00409 {
00410 sStreamIBOPool.release(mGLIndices);
00411 }
00412 else if (mUsage == GL_DYNAMIC_DRAW_ARB)
00413 {
00414 sDynamicIBOPool.release(mGLIndices);
00415 }
00416 else
00417 {
00418 sDeleteList.push_back(mGLIndices);
00419 }
00420 sGLCount--;
00421 }
00422
00423 void LLVertexBuffer::createGLBuffer()
00424 {
00425 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00426
00427 U32 size = getSize();
00428 if (mGLBuffer)
00429 {
00430 destroyGLBuffer();
00431 }
00432
00433 if (size == 0)
00434 {
00435 return;
00436 }
00437
00438 mEmpty = TRUE;
00439
00440 if (useVBOs())
00441 {
00442 mMappedData = NULL;
00443 genBuffer();
00444 mResized = TRUE;
00445 }
00446 else
00447 {
00448 static int gl_buffer_idx = 0;
00449 mGLBuffer = ++gl_buffer_idx;
00450 mMappedData = new U8[size];
00451 memset(mMappedData, 0, size);
00452 }
00453 }
00454
00455 void LLVertexBuffer::createGLIndices()
00456 {
00457 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00458 U32 size = getIndicesSize();
00459
00460 if (mGLIndices)
00461 {
00462 destroyGLIndices();
00463 }
00464
00465 if (size == 0)
00466 {
00467 return;
00468 }
00469
00470 mEmpty = TRUE;
00471
00472 if (useVBOs())
00473 {
00474 mMappedIndexData = NULL;
00475 genIndices();
00476 mResized = TRUE;
00477 }
00478 else
00479 {
00480 mMappedIndexData = new U8[size];
00481 memset(mMappedIndexData, 0, size);
00482 static int gl_buffer_idx = 0;
00483 mGLIndices = ++gl_buffer_idx;
00484 }
00485 }
00486
00487 void LLVertexBuffer::destroyGLBuffer()
00488 {
00489 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00490 if (mGLBuffer)
00491 {
00492 if (useVBOs())
00493 {
00494 if (mMappedData || mMappedIndexData)
00495 {
00496 llerrs << "Vertex buffer destroyed while mapped!" << llendl;
00497 }
00498 releaseBuffer();
00499 }
00500 else
00501 {
00502 delete [] mMappedData;
00503 mMappedData = NULL;
00504 mEmpty = TRUE;
00505 }
00506
00507 sAllocatedBytes -= getSize();
00508 }
00509
00510 mGLBuffer = 0;
00511 unbind();
00512 }
00513
00514 void LLVertexBuffer::destroyGLIndices()
00515 {
00516 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00517 if (mGLIndices)
00518 {
00519 if (useVBOs())
00520 {
00521 if (mMappedData || mMappedIndexData)
00522 {
00523 llerrs << "Vertex buffer destroyed while mapped." << llendl;
00524 }
00525 releaseIndices();
00526 }
00527 else
00528 {
00529 delete [] mMappedIndexData;
00530 mMappedIndexData = NULL;
00531 mEmpty = TRUE;
00532 }
00533
00534 sAllocatedBytes -= getIndicesSize();
00535 }
00536
00537 mGLIndices = 0;
00538 unbind();
00539 }
00540
00541 void LLVertexBuffer::updateNumVerts(S32 nverts)
00542 {
00543 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00544
00545 if (nverts >= 65535)
00546 {
00547 llwarns << "Vertex buffer overflow!" << llendl;
00548 nverts = 65535;
00549 }
00550
00551 mRequestedNumVerts = nverts;
00552
00553 if (!mDynamicSize)
00554 {
00555 mNumVerts = nverts;
00556 }
00557 else if (mUsage == GL_STATIC_DRAW_ARB ||
00558 nverts > mNumVerts ||
00559 nverts < mNumVerts/2)
00560 {
00561 if (mUsage != GL_STATIC_DRAW_ARB && nverts + nverts/4 <= 65535)
00562 {
00563 nverts += nverts/4;
00564 }
00565 mNumVerts = nverts;
00566 }
00567
00568 }
00569
00570 void LLVertexBuffer::updateNumIndices(S32 nindices)
00571 {
00572 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00573 mRequestedNumIndices = nindices;
00574 if (!mDynamicSize)
00575 {
00576 mNumIndices = nindices;
00577 }
00578 else if (mUsage == GL_STATIC_DRAW_ARB ||
00579 nindices > mNumIndices ||
00580 nindices < mNumIndices/2)
00581 {
00582 if (mUsage != GL_STATIC_DRAW_ARB)
00583 {
00584 nindices += nindices/4;
00585 }
00586
00587 mNumIndices = nindices;
00588 }
00589 }
00590
00591 void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
00592 {
00593 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00594
00595 updateNumVerts(nverts);
00596 updateNumIndices(nindices);
00597
00598 if (mMappedData)
00599 {
00600 llerrs << "LLVertexBuffer::allocateBuffer() called redundantly." << llendl;
00601 }
00602 if (create && (nverts || nindices))
00603 {
00604 createGLBuffer();
00605 createGLIndices();
00606 }
00607
00608 sAllocatedBytes += getSize() + getIndicesSize();
00609 }
00610
00611 void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
00612 {
00613 mRequestedNumVerts = newnverts;
00614 mRequestedNumIndices = newnindices;
00615
00616 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00617 mDynamicSize = TRUE;
00618 if (mUsage == GL_STATIC_DRAW_ARB)
00619 {
00620 destroyGLBuffer();
00621 destroyGLIndices();
00622 allocateBuffer(newnverts, newnindices, TRUE);
00623 mFinal = FALSE;
00624 }
00625 else if (newnverts > mNumVerts || newnindices > mNumIndices ||
00626 newnverts < mNumVerts/2 || newnindices < mNumIndices/2)
00627 {
00628 sAllocatedBytes -= getSize() + getIndicesSize();
00629
00630 S32 oldsize = getSize();
00631 S32 old_index_size = getIndicesSize();
00632
00633 updateNumVerts(newnverts);
00634 updateNumIndices(newnindices);
00635
00636 S32 newsize = getSize();
00637 S32 new_index_size = getIndicesSize();
00638
00639 sAllocatedBytes += newsize + new_index_size;
00640
00641 if (newsize)
00642 {
00643 if (!mGLBuffer)
00644 {
00645 createGLBuffer();
00646 }
00647 else
00648 {
00649
00650 if (!useVBOs())
00651 {
00652 U8* old = mMappedData;
00653 mMappedData = new U8[newsize];
00654 if (old)
00655 {
00656 memcpy(mMappedData, old, llmin(newsize, oldsize));
00657 if (newsize > oldsize)
00658 {
00659 memset(mMappedData+oldsize, 0, newsize-oldsize);
00660 }
00661
00662 delete [] old;
00663 }
00664 else
00665 {
00666 memset(mMappedData, 0, newsize);
00667 mEmpty = TRUE;
00668 }
00669 }
00670 mResized = TRUE;
00671 }
00672 }
00673 else if (mGLBuffer)
00674 {
00675 destroyGLBuffer();
00676 }
00677
00678 if (new_index_size)
00679 {
00680 if (!mGLIndices)
00681 {
00682 createGLIndices();
00683 }
00684 else
00685 {
00686 if (!useVBOs())
00687 {
00688
00689 U8* old = mMappedIndexData;
00690 mMappedIndexData = new U8[new_index_size];
00691
00692 if (old)
00693 {
00694 memcpy(mMappedIndexData, old, llmin(new_index_size, old_index_size));
00695 if (new_index_size > old_index_size)
00696 {
00697 memset(mMappedIndexData+old_index_size, 0, new_index_size - old_index_size);
00698 }
00699 delete [] old;
00700 }
00701 else
00702 {
00703 memset(mMappedIndexData, 0, new_index_size);
00704 mEmpty = TRUE;
00705 }
00706 }
00707 mResized = TRUE;
00708 }
00709 }
00710 else if (mGLIndices)
00711 {
00712 destroyGLIndices();
00713 }
00714 }
00715
00716 if (mResized && useVBOs())
00717 {
00718 setBuffer(0);
00719 }
00720 }
00721
00722 BOOL LLVertexBuffer::useVBOs() const
00723 {
00724
00725
00726 #if LL_DARWIN
00727 if (!mUsage || mUsage == GL_STREAM_DRAW_ARB)
00728 {
00729 return FALSE;
00730 }
00731 #else
00732 if (!mUsage)
00733 {
00734 return FALSE;
00735 }
00736 #endif
00737 return sEnableVBOs;
00738 }
00739
00740
00741
00742
00743 U8* LLVertexBuffer::mapBuffer(S32 access)
00744 {
00745 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00746 if (mFinal)
00747 {
00748 llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl;
00749 }
00750 if (!useVBOs() && !mMappedData && !mMappedIndexData)
00751 {
00752 llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl;
00753 }
00754
00755 if (!mLocked && useVBOs())
00756 {
00757 setBuffer(0);
00758 mLocked = TRUE;
00759 stop_glerror();
00760 mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
00761 stop_glerror();
00762 mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
00763 stop_glerror();
00764
00765
00766
00767
00768
00769 if (!mMappedData)
00770 {
00771 llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
00772 }
00773
00774 if (!mMappedIndexData)
00775 {
00776 llerrs << "glMapBuffer returned NULL (no index data)" << llendl;
00777 }
00778
00779 sMappedCount++;
00780 }
00781
00782 return mMappedData;
00783 }
00784
00785 void LLVertexBuffer::unmapBuffer()
00786 {
00787 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00788 if (mMappedData || mMappedIndexData)
00789 {
00790 if (useVBOs() && mLocked)
00791 {
00792 stop_glerror();
00793 glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
00794 stop_glerror();
00795 glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
00796 stop_glerror();
00797
00798
00799
00800
00801
00802
00803 sMappedCount--;
00804
00805 if (mUsage == GL_STATIC_DRAW_ARB)
00806 {
00807
00808 mEmpty = TRUE;
00809 mFinal = TRUE;
00810 }
00811 else
00812 {
00813 mEmpty = FALSE;
00814 }
00815
00816 mMappedIndexData = NULL;
00817 mMappedData = NULL;
00818
00819 mLocked = FALSE;
00820 }
00821 }
00822 }
00823
00824
00825
00826 template <class T,S32 type> struct VertexBufferStrider
00827 {
00828 typedef LLStrider<T> strider_t;
00829 static bool get(LLVertexBuffer& vbo,
00830 strider_t& strider,
00831 S32 index)
00832 {
00833 if (vbo.mapBuffer() == NULL)
00834 {
00835 llwarns << "mapBuffer failed!" << llendl;
00836 return FALSE;
00837 }
00838
00839 if (type == LLVertexBuffer::TYPE_INDEX)
00840 {
00841 S32 stride = sizeof(T);
00842 strider = (T*)(vbo.getMappedIndices() + index*stride);
00843 strider.setStride(0);
00844 return TRUE;
00845 }
00846 else if (vbo.hasDataType(type))
00847 {
00848 S32 stride = vbo.getStride();
00849 strider = (T*)(vbo.getMappedData() + vbo.getOffset(type) + index*stride);
00850 strider.setStride(stride);
00851 return TRUE;
00852 }
00853 else
00854 {
00855 llerrs << "VertexBufferStrider could not find valid vertex data." << llendl;
00856 }
00857 return FALSE;
00858 }
00859 };
00860
00861
00862 bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index)
00863 {
00864 return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index);
00865 }
00866 bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index)
00867 {
00868 return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index);
00869 }
00870 bool LLVertexBuffer::getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index)
00871 {
00872 return VertexBufferStrider<LLVector2,TYPE_TEXCOORD>::get(*this, strider, index);
00873 }
00874 bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index)
00875 {
00876 return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index);
00877 }
00878 bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index)
00879 {
00880 return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index);
00881 }
00882 bool LLVertexBuffer::getBinormalStrider(LLStrider<LLVector3>& strider, S32 index)
00883 {
00884 return VertexBufferStrider<LLVector3,TYPE_BINORMAL>::get(*this, strider, index);
00885 }
00886 bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index)
00887 {
00888 return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index);
00889 }
00890 bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index)
00891 {
00892 return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index);
00893 }
00894 bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index)
00895 {
00896 return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index);
00897 }
00898
00899 void LLVertexBuffer::setStride(S32 type, S32 new_stride)
00900 {
00901 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00902 if (mNumVerts)
00903 {
00904 llerrs << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl;
00905 }
00906
00907 S32 delta = new_stride - sTypeOffsets[type];
00908 for (S32 i=type+1; i<TYPE_MAX; i++)
00909 {
00910 if (mTypeMask & (1<<i))
00911 {
00912 mOffsets[i] += delta;
00913 }
00914 }
00915 mStride += delta;
00916 }
00917
00918
00919
00920
00921 void LLVertexBuffer::setBuffer(U32 data_mask)
00922 {
00923 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00924
00925 BOOL setup = (sLastMask != data_mask);
00926
00927 if (useVBOs())
00928 {
00929 if (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))
00930 {
00931
00932
00933
00934
00935 stop_glerror();
00936 glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
00937 stop_glerror();
00938 sBindCount++;
00939 sVBOActive = TRUE;
00940 setup = TRUE;
00941 }
00942 if (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive))
00943 {
00944
00945
00946
00947
00948 stop_glerror();
00949 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
00950 stop_glerror();
00951 sBindCount++;
00952 sIBOActive = TRUE;
00953 }
00954
00955 if (mResized)
00956 {
00957 if (gDebugGL)
00958 {
00959 GLint buff;
00960 glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
00961 if (buff != mGLBuffer)
00962 {
00963 llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
00964 }
00965
00966 glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
00967 if (buff != mGLIndices)
00968 {
00969 llerrs << "Invalid GL index buffer bound: " << buff << llendl;
00970 }
00971 }
00972
00973 if (mGLBuffer)
00974 {
00975 stop_glerror();
00976 glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), NULL, mUsage);
00977 stop_glerror();
00978 }
00979 if (mGLIndices)
00980 {
00981 stop_glerror();
00982 glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), NULL, mUsage);
00983 stop_glerror();
00984 }
00985
00986 mEmpty = TRUE;
00987 mResized = FALSE;
00988
00989 if (data_mask != 0)
00990 {
00991 llerrs << "Buffer set for rendering before being filled after resize." << llendl;
00992 }
00993 }
00994
00995 unmapBuffer();
00996 }
00997 else
00998 {
00999 if (mGLBuffer)
01000 {
01001 if (sEnableVBOs && sVBOActive)
01002 {
01003 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
01004 sBindCount++;
01005 sVBOActive = FALSE;
01006 setup = TRUE;
01007 }
01008 if (sGLRenderBuffer != mGLBuffer)
01009 {
01010 setup = TRUE;
01011 }
01012 }
01013 if (sEnableVBOs && mGLIndices && sIBOActive)
01014 {
01015
01016
01017
01018
01019 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
01020 sBindCount++;
01021 sIBOActive = FALSE;
01022 }
01023 }
01024
01025 setupClientArrays(data_mask);
01026
01027 if (mGLIndices)
01028 {
01029 sGLRenderIndices = mGLIndices;
01030 }
01031 if (mGLBuffer)
01032 {
01033 sGLRenderBuffer = mGLBuffer;
01034 if (data_mask && setup)
01035 {
01036 setupVertexBuffer(data_mask);
01037 sSetCount++;
01038 }
01039 }
01040 }
01041
01042
01043 void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
01044 {
01045 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
01046 stop_glerror();
01047 U8* base = useVBOs() ? NULL : mMappedData;
01048 S32 stride = mStride;
01049
01050 if ((data_mask & mTypeMask) != data_mask)
01051 {
01052 llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl;
01053 }
01054
01055 if (data_mask & MAP_NORMAL)
01056 {
01057 glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL]));
01058 }
01059 if (data_mask & MAP_TEXCOORD2)
01060 {
01061 glClientActiveTextureARB(GL_TEXTURE1_ARB);
01062 glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD2]));
01063 glClientActiveTextureARB(GL_TEXTURE0_ARB);
01064 }
01065 if (data_mask & MAP_TEXCOORD)
01066 {
01067 glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD]));
01068 }
01069 if (data_mask & MAP_COLOR)
01070 {
01071 glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)(base + mOffsets[TYPE_COLOR]));
01072 }
01073 if (data_mask & MAP_BINORMAL)
01074 {
01075 glVertexAttribPointerARB(6, 3, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_BINORMAL]));
01076 }
01077 if (data_mask & MAP_WEIGHT)
01078 {
01079 glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_WEIGHT]));
01080 }
01081 if (data_mask & MAP_CLOTHWEIGHT)
01082 {
01083 glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]));
01084 }
01085 if (data_mask & MAP_VERTEX)
01086 {
01087 glVertexPointer(3,GL_FLOAT, stride, (void*)(base + 0));
01088 }
01089
01090 llglassertok();
01091 }
01092
01093 void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count)
01094 {
01095
01096
01097
01098
01099
01100 }