llvertexbuffer.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include "llvertexbuffer.h"
00035 // #include "llrender.h"
00036 #include "llglheaders.h"
00037 #include "llmemory.h"
00038 #include "llmemtype.h"
00039 
00040 //============================================================================
00041 
00042 //static
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), // TYPE_VERTEX,
00060         sizeof(LLVector3), // TYPE_NORMAL,
00061         sizeof(LLVector2), // TYPE_TEXCOORD,
00062         sizeof(LLVector2), // TYPE_TEXCOORD2,
00063         sizeof(LLColor4U), // TYPE_COLOR,
00064         sizeof(LLVector3), // TYPE_BINORMAL,
00065         sizeof(F32),       // TYPE_WEIGHT,
00066         sizeof(LLVector4), // TYPE_CLOTHWEIGHT,
00067 };
00068 
00069 //static
00070 void LLVertexBuffer::initClass(bool use_vbo)
00071 {
00072         sEnableVBOs = use_vbo;
00073 }
00074 
00075 //static 
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 //static
00094 void LLVertexBuffer::cleanupClass()
00095 {
00096         LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00097         sLockedList.clear();
00098         startRender(); 
00099         stopRender();
00100         clientCopy(); // deletes GL buffers
00101 }
00102 
00103 //static, call before rendering VBOs
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(); //skip first copy (don't count pipeline stall)
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 // protected, use unref()
00202 //virtual
00203 LLVertexBuffer::~LLVertexBuffer()
00204 {
00205         LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00206         destroyGLBuffer();
00207         destroyGLIndices();
00208         sCount--;
00209         
00210         if (mLocked)
00211         {
00212                 //pull off of locked list
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         { //always delete/allocate static buffers on resize
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                         { //no buffer exists, create a new one
00467                                 createGLBuffer();
00468                         }
00469                         else
00470                         {
00471                                 //delete old buffer, keep GL buffer for now
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                                 //delete old buffer, keep GL buffer for now
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         //it's generally ineffective to use VBO for things that are streaming
00535         //when we already have a client buffer around
00536         if (mUsage == GL_STREAM_DRAW_ARB)
00537         {
00538                 return FALSE;
00539         }
00540 
00541         return sEnableVBOs && (!sRenderActive || !mLocked);
00542 }
00543 
00544 //----------------------------------------------------------------------------
00545 
00546 // Map for data access
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                         { //static draw buffers can only be mapped a single time
00636                                 //throw out client data (we won't be using it again)
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         // This code assumes that setStride() will only be called once per VBO per type.
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 // Set for rendering
00748 void LLVertexBuffer::setBuffer(U32 data_mask)
00749 {
00750         LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
00751         //set up pointers if the data mask is different ...
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; // ... or the bound buffer changed
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; // ... or a VBO is deactivated
00779                         }
00780                         if (sGLRenderBuffer != mGLBuffer)
00781                         {
00782                                 setup = TRUE; // ... or a client memory pointer changed
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); // subclass specific setup (virtual function)
00806                         sLastMask = data_mask;
00807                 }
00808         }
00809 }
00810 
00811 // virtual (default)
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                                 //this buffer has received multiple updates since the last copy, mark it filthy
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 

Generated on Thu Jul 1 06:09:25 2010 for Second Life Viewer by  doxygen 1.4.7