aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llrender/llvertexbuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llrender/llvertexbuffer.cpp')
-rw-r--r--linden/indra/llrender/llvertexbuffer.cpp538
1 files changed, 273 insertions, 265 deletions
diff --git a/linden/indra/llrender/llvertexbuffer.cpp b/linden/indra/llrender/llvertexbuffer.cpp
index d19e885..f3c6997 100644
--- a/linden/indra/llrender/llvertexbuffer.cpp
+++ b/linden/indra/llrender/llvertexbuffer.cpp
@@ -31,6 +31,8 @@
31 31
32#include "linden_common.h" 32#include "linden_common.h"
33 33
34#include <boost/static_assert.hpp>
35
34#include "llvertexbuffer.h" 36#include "llvertexbuffer.h"
35// #include "llrender.h" 37// #include "llrender.h"
36#include "llglheaders.h" 38#include "llglheaders.h"
@@ -40,8 +42,16 @@
40//============================================================================ 42//============================================================================
41 43
42//static 44//static
45LLVBOPool LLVertexBuffer::sStreamVBOPool;
46LLVBOPool LLVertexBuffer::sDynamicVBOPool;
47LLVBOPool LLVertexBuffer::sStreamIBOPool;
48LLVBOPool LLVertexBuffer::sDynamicIBOPool;
49
50U32 LLVertexBuffer::sBindCount = 0;
51U32 LLVertexBuffer::sSetCount = 0;
43S32 LLVertexBuffer::sCount = 0; 52S32 LLVertexBuffer::sCount = 0;
44S32 LLVertexBuffer::sGLCount = 0; 53S32 LLVertexBuffer::sGLCount = 0;
54S32 LLVertexBuffer::sMappedCount = 0;
45BOOL LLVertexBuffer::sEnableVBOs = TRUE; 55BOOL LLVertexBuffer::sEnableVBOs = TRUE;
46U32 LLVertexBuffer::sGLRenderBuffer = 0; 56U32 LLVertexBuffer::sGLRenderBuffer = 0;
47U32 LLVertexBuffer::sGLRenderIndices = 0; 57U32 LLVertexBuffer::sGLRenderIndices = 0;
@@ -50,9 +60,9 @@ BOOL LLVertexBuffer::sVBOActive = FALSE;
50BOOL LLVertexBuffer::sIBOActive = FALSE; 60BOOL LLVertexBuffer::sIBOActive = FALSE;
51U32 LLVertexBuffer::sAllocatedBytes = 0; 61U32 LLVertexBuffer::sAllocatedBytes = 0;
52BOOL LLVertexBuffer::sRenderActive = FALSE; 62BOOL LLVertexBuffer::sRenderActive = FALSE;
63BOOL LLVertexBuffer::sMapped = FALSE;
53 64
54std::vector<U32> LLVertexBuffer::sDeleteList; 65std::vector<U32> LLVertexBuffer::sDeleteList;
55LLVertexBuffer::buffer_list_t LLVertexBuffer::sLockedList;
56 66
57S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = 67S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] =
58{ 68{
@@ -70,6 +80,10 @@ S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] =
70void LLVertexBuffer::initClass(bool use_vbo) 80void LLVertexBuffer::initClass(bool use_vbo)
71{ 81{
72 sEnableVBOs = use_vbo; 82 sEnableVBOs = use_vbo;
83 LLGLNamePool::registerPool(&sDynamicVBOPool);
84 LLGLNamePool::registerPool(&sDynamicIBOPool);
85 LLGLNamePool::registerPool(&sStreamVBOPool);
86 LLGLNamePool::registerPool(&sStreamIBOPool);
73} 87}
74 88
75//static 89//static
@@ -88,13 +102,13 @@ void LLVertexBuffer::unbind()
88 102
89 sGLRenderBuffer = 0; 103 sGLRenderBuffer = 0;
90 sGLRenderIndices = 0; 104 sGLRenderIndices = 0;
105 sLastMask = 0;
91} 106}
92 107
93//static 108//static
94void LLVertexBuffer::cleanupClass() 109void LLVertexBuffer::cleanupClass()
95{ 110{
96 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); 111 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
97 sLockedList.clear();
98 startRender(); 112 startRender();
99 stopRender(); 113 stopRender();
100 clientCopy(); // deletes GL buffers 114 clientCopy(); // deletes GL buffers
@@ -127,41 +141,8 @@ void LLVertexBuffer::clientCopy(F64 max_time)
127{ 141{
128 if (!sDeleteList.empty()) 142 if (!sDeleteList.empty())
129 { 143 {
130 size_t num = sDeleteList.size();
131 glDeleteBuffersARB(sDeleteList.size(), (GLuint*) &(sDeleteList[0])); 144 glDeleteBuffersARB(sDeleteList.size(), (GLuint*) &(sDeleteList[0]));
132 sDeleteList.clear(); 145 sDeleteList.clear();
133 sGLCount -= num;
134 }
135
136 if (sEnableVBOs)
137 {
138 LLTimer timer;
139 BOOL reset = TRUE;
140 buffer_list_t::iterator iter = sLockedList.begin();
141 while(iter != sLockedList.end())
142 {
143 LLVertexBuffer* buffer = *iter;
144 if (buffer->isLocked() && buffer->useVBOs())
145 {
146 buffer->setBuffer(0);
147 }
148 ++iter;
149 if (reset)
150 {
151 reset = FALSE;
152 timer.reset(); //skip first copy (don't count pipeline stall)
153 }
154 else
155 {
156 if (timer.getElapsedTimeF64() > max_time)
157 {
158 break;
159 }
160 }
161
162 }
163
164 sLockedList.erase(sLockedList.begin(), iter);
165 } 146 }
166} 147}
167 148
@@ -175,27 +156,40 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
175 mFinal(FALSE), 156 mFinal(FALSE),
176 mFilthy(FALSE), 157 mFilthy(FALSE),
177 mEmpty(TRUE), 158 mEmpty(TRUE),
178 mResized(FALSE) 159 mResized(FALSE),
160 mDynamicSize(FALSE)
179{ 161{
180 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); 162 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
181 if (!sEnableVBOs) 163 if (!sEnableVBOs)
182 { 164 {
183 mUsage = GL_STREAM_DRAW_ARB; 165 mUsage = 0 ;
184 } 166 }
185 167
168 S32 stride = calcStride(typemask, mOffsets);
169
170 mTypeMask = typemask;
171 mStride = stride;
172 sCount++;
173}
174
175//static
176S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets)
177{
186 S32 stride = 0; 178 S32 stride = 0;
187 for (S32 i=0; i<TYPE_MAX; i++) 179 for (S32 i=0; i<TYPE_MAX; i++)
188 { 180 {
189 U32 mask = 1<<i; 181 U32 mask = 1<<i;
190 if (typemask & mask) 182 if (typemask & mask)
191 { 183 {
192 mOffsets[i] = stride; 184 if (offsets)
185 {
186 offsets[i] = stride;
187 }
193 stride += sTypeOffsets[i]; 188 stride += sTypeOffsets[i];
194 } 189 }
195 } 190 }
196 mTypeMask = typemask; 191
197 mStride = stride; 192 return stride;
198 sCount++;
199} 193}
200 194
201// protected, use unref() 195// protected, use unref()
@@ -206,23 +200,80 @@ LLVertexBuffer::~LLVertexBuffer()
206 destroyGLBuffer(); 200 destroyGLBuffer();
207 destroyGLIndices(); 201 destroyGLIndices();
208 sCount--; 202 sCount--;
209
210 if (mLocked)
211 {
212 //pull off of locked list
213 for (buffer_list_t::iterator i = sLockedList.begin(); i != sLockedList.end(); ++i)
214 {
215 if (*i == this)
216 {
217 sLockedList.erase(i);
218 break;
219 }
220 }
221 }
222}; 203};
223 204
224//---------------------------------------------------------------------------- 205//----------------------------------------------------------------------------
225 206
207void LLVertexBuffer::genBuffer()
208{
209 if (mUsage == GL_STREAM_DRAW_ARB)
210 {
211 mGLBuffer = sStreamVBOPool.allocate();
212 }
213 else if (mUsage == GL_DYNAMIC_DRAW_ARB)
214 {
215 mGLBuffer = sDynamicVBOPool.allocate();
216 }
217 else
218 {
219 BOOST_STATIC_ASSERT(sizeof(mGLBuffer) == sizeof(GLuint));
220 glGenBuffersARB(1, (GLuint*)&mGLBuffer);
221 }
222 sGLCount++;
223}
224
225void LLVertexBuffer::genIndices()
226{
227 if (mUsage == GL_STREAM_DRAW_ARB)
228 {
229 mGLIndices = sStreamIBOPool.allocate();
230 }
231 else if (mUsage == GL_DYNAMIC_DRAW_ARB)
232 {
233 mGLIndices = sDynamicIBOPool.allocate();
234 }
235 else
236 {
237 BOOST_STATIC_ASSERT(sizeof(mGLBuffer) == sizeof(GLuint));
238 glGenBuffersARB(1, (GLuint*)&mGLIndices);
239 }
240 sGLCount++;
241}
242
243void LLVertexBuffer::releaseBuffer()
244{
245 if (mUsage == GL_STREAM_DRAW_ARB)
246 {
247 sStreamVBOPool.release(mGLBuffer);
248 }
249 else if (mUsage == GL_DYNAMIC_DRAW_ARB)
250 {
251 sDynamicVBOPool.release(mGLBuffer);
252 }
253 else
254 {
255 sDeleteList.push_back(mGLBuffer);
256 }
257 sGLCount--;
258}
259
260void LLVertexBuffer::releaseIndices()
261{
262 if (mUsage == GL_STREAM_DRAW_ARB)
263 {
264 sStreamIBOPool.release(mGLIndices);
265 }
266 else if (mUsage == GL_DYNAMIC_DRAW_ARB)
267 {
268 sDynamicIBOPool.release(mGLIndices);
269 }
270 else
271 {
272 sDeleteList.push_back(mGLIndices);
273 }
274 sGLCount--;
275}
276
226void LLVertexBuffer::createGLBuffer() 277void LLVertexBuffer::createGLBuffer()
227{ 278{
228 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); 279 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
@@ -238,20 +289,20 @@ void LLVertexBuffer::createGLBuffer()
238 return; 289 return;
239 } 290 }
240 291
241 mMappedData = new U8[size];
242 memset(mMappedData, 0, size);
243 mEmpty = TRUE; 292 mEmpty = TRUE;
244 293
245 if (useVBOs()) 294 if (useVBOs())
246 { 295 {
247 glGenBuffersARB(1, (GLuint*) &mGLBuffer); 296 mMappedData = NULL;
297 genBuffer();
248 mResized = TRUE; 298 mResized = TRUE;
249 sGLCount++;
250 } 299 }
251 else 300 else
252 { 301 {
253 static int gl_buffer_idx = 0; 302 static int gl_buffer_idx = 0;
254 mGLBuffer = ++gl_buffer_idx; 303 mGLBuffer = ++gl_buffer_idx;
304 mMappedData = new U8[size];
305 memset(mMappedData, 0, size);
255 } 306 }
256} 307}
257 308
@@ -270,18 +321,18 @@ void LLVertexBuffer::createGLIndices()
270 return; 321 return;
271 } 322 }
272 323
273 mMappedIndexData = new U8[size];
274 memset(mMappedIndexData, 0, size);
275 mEmpty = TRUE; 324 mEmpty = TRUE;
276 325
277 if (useVBOs()) 326 if (useVBOs())
278 { 327 {
279 glGenBuffersARB(1, (GLuint*) &mGLIndices); 328 mMappedIndexData = NULL;
329 genIndices();
280 mResized = TRUE; 330 mResized = TRUE;
281 sGLCount++;
282 } 331 }
283 else 332 else
284 { 333 {
334 mMappedIndexData = new U8[size];
335 memset(mMappedIndexData, 0, size);
285 static int gl_buffer_idx = 0; 336 static int gl_buffer_idx = 0;
286 mGLIndices = ++gl_buffer_idx; 337 mGLIndices = ++gl_buffer_idx;
287 } 338 }
@@ -294,12 +345,19 @@ void LLVertexBuffer::destroyGLBuffer()
294 { 345 {
295 if (useVBOs()) 346 if (useVBOs())
296 { 347 {
297 sDeleteList.push_back(mGLBuffer); 348 if (mMappedData || mMappedIndexData)
349 {
350 llerrs << "Vertex buffer destroyed while mapped!" << llendl;
351 }
352 releaseBuffer();
353 }
354 else
355 {
356 delete [] mMappedData;
357 mMappedData = NULL;
358 mEmpty = TRUE;
298 } 359 }
299 360
300 delete [] mMappedData;
301 mMappedData = NULL;
302 mEmpty = TRUE;
303 sAllocatedBytes -= getSize(); 361 sAllocatedBytes -= getSize();
304 } 362 }
305 363
@@ -313,12 +371,19 @@ void LLVertexBuffer::destroyGLIndices()
313 { 371 {
314 if (useVBOs()) 372 if (useVBOs())
315 { 373 {
316 sDeleteList.push_back(mGLIndices); 374 if (mMappedData || mMappedIndexData)
375 {
376 llerrs << "Vertex buffer destroyed while mapped." << llendl;
377 }
378 releaseIndices();
379 }
380 else
381 {
382 delete [] mMappedIndexData;
383 mMappedIndexData = NULL;
384 mEmpty = TRUE;
317 } 385 }
318 386
319 delete [] mMappedIndexData;
320 mMappedIndexData = NULL;
321 mEmpty = TRUE;
322 sAllocatedBytes -= getIndicesSize(); 387 sAllocatedBytes -= getIndicesSize();
323 } 388 }
324 389
@@ -328,6 +393,15 @@ void LLVertexBuffer::destroyGLIndices()
328void LLVertexBuffer::updateNumVerts(S32 nverts) 393void LLVertexBuffer::updateNumVerts(S32 nverts)
329{ 394{
330 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); 395 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
396
397 if (nverts >= 65535)
398 {
399 llwarns << "Vertex buffer overflow!" << llendl;
400 nverts = 65535;
401 }
402
403 mRequestedNumVerts = nverts;
404
331 if (!mDynamicSize) 405 if (!mDynamicSize)
332 { 406 {
333 mNumVerts = nverts; 407 mNumVerts = nverts;
@@ -336,18 +410,19 @@ void LLVertexBuffer::updateNumVerts(S32 nverts)
336 nverts > mNumVerts || 410 nverts > mNumVerts ||
337 nverts < mNumVerts/2) 411 nverts < mNumVerts/2)
338 { 412 {
339 if (mUsage != GL_STATIC_DRAW_ARB) 413 if (mUsage != GL_STATIC_DRAW_ARB && nverts + nverts/4 <= 65535)
340 { 414 {
341 nverts += nverts/4; 415 nverts += nverts/4;
342 } 416 }
343
344 mNumVerts = nverts; 417 mNumVerts = nverts;
345 } 418 }
419
346} 420}
347 421
348void LLVertexBuffer::updateNumIndices(S32 nindices) 422void LLVertexBuffer::updateNumIndices(S32 nindices)
349{ 423{
350 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); 424 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
425 mRequestedNumIndices = nindices;
351 if (!mDynamicSize) 426 if (!mDynamicSize)
352 { 427 {
353 mNumIndices = nindices; 428 mNumIndices = nindices;
@@ -365,54 +440,6 @@ void LLVertexBuffer::updateNumIndices(S32 nindices)
365 } 440 }
366} 441}
367 442
368void LLVertexBuffer::makeStatic()
369{
370 if (!sEnableVBOs)
371 {
372 return;
373 }
374
375 if (sRenderActive)
376 {
377 llerrs << "Make static called during render." << llendl;
378 }
379
380 if (mUsage != GL_STATIC_DRAW_ARB)
381 {
382 if (useVBOs())
383 {
384 if (mGLBuffer)
385 {
386 sDeleteList.push_back(mGLBuffer);
387 }
388 if (mGLIndices)
389 {
390 sDeleteList.push_back(mGLIndices);
391 }
392 }
393
394 if (mGLBuffer)
395 {
396 sGLCount++;
397 glGenBuffersARB(1, (GLuint*) &mGLBuffer);
398 }
399 if (mGLIndices)
400 {
401 sGLCount++;
402 glGenBuffersARB(1, (GLuint*) &mGLIndices);
403 }
404
405 mUsage = GL_STATIC_DRAW_ARB;
406 mResized = TRUE;
407
408 if (!mLocked)
409 {
410 mLocked = TRUE;
411 sLockedList.push_back(this);
412 }
413 }
414}
415
416void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) 443void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
417{ 444{
418 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); 445 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
@@ -435,6 +462,9 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
435 462
436void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) 463void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
437{ 464{
465 mRequestedNumVerts = newnverts;
466 mRequestedNumIndices = newnindices;
467
438 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); 468 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
439 mDynamicSize = TRUE; 469 mDynamicSize = TRUE;
440 if (mUsage == GL_STATIC_DRAW_ARB) 470 if (mUsage == GL_STATIC_DRAW_ARB)
@@ -469,22 +499,25 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
469 else 499 else
470 { 500 {
471 //delete old buffer, keep GL buffer for now 501 //delete old buffer, keep GL buffer for now
472 U8* old = mMappedData; 502 if (!useVBOs())
473 mMappedData = new U8[newsize]; 503 {
474 if (old) 504 U8* old = mMappedData;
475 { 505 mMappedData = new U8[newsize];
476 memcpy(mMappedData, old, llmin(newsize, oldsize)); 506 if (old)
477 if (newsize > oldsize) 507 {
508 memcpy(mMappedData, old, llmin(newsize, oldsize));
509 if (newsize > oldsize)
510 {
511 memset(mMappedData+oldsize, 0, newsize-oldsize);
512 }
513
514 delete [] old;
515 }
516 else
478 { 517 {
479 memset(mMappedData+oldsize, 0, newsize-oldsize); 518 memset(mMappedData, 0, newsize);
519 mEmpty = TRUE;
480 } 520 }
481
482 delete [] old;
483 }
484 else
485 {
486 memset(mMappedData, 0, newsize);
487 mEmpty = TRUE;
488 } 521 }
489 mResized = TRUE; 522 mResized = TRUE;
490 } 523 }
@@ -502,22 +535,26 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
502 } 535 }
503 else 536 else
504 { 537 {
505 //delete old buffer, keep GL buffer for now 538 if (!useVBOs())
506 U8* old = mMappedIndexData; 539 {
507 mMappedIndexData = new U8[new_index_size]; 540 //delete old buffer, keep GL buffer for now
508 if (old) 541 U8* old = mMappedIndexData;
509 { 542 mMappedIndexData = new U8[new_index_size];
510 memcpy(mMappedIndexData, old, llmin(new_index_size, old_index_size)); 543
511 if (new_index_size > old_index_size) 544 if (old)
545 {
546 memcpy(mMappedIndexData, old, llmin(new_index_size, old_index_size));
547 if (new_index_size > old_index_size)
548 {
549 memset(mMappedIndexData+old_index_size, 0, new_index_size - old_index_size);
550 }
551 delete [] old;
552 }
553 else
512 { 554 {
513 memset(mMappedIndexData+old_index_size, 0, new_index_size - old_index_size); 555 memset(mMappedIndexData, 0, new_index_size);
556 mEmpty = TRUE;
514 } 557 }
515 delete [] old;
516 }
517 else
518 {
519 memset(mMappedIndexData, 0, new_index_size);
520 mEmpty = TRUE;
521 } 558 }
522 mResized = TRUE; 559 mResized = TRUE;
523 } 560 }
@@ -527,18 +564,29 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
527 destroyGLIndices(); 564 destroyGLIndices();
528 } 565 }
529 } 566 }
567
568 if (mResized && useVBOs())
569 {
570 setBuffer(0);
571 }
530} 572}
531 573
532BOOL LLVertexBuffer::useVBOs() const 574BOOL LLVertexBuffer::useVBOs() const
533{ 575{
534 //it's generally ineffective to use VBO for things that are streaming 576 //it's generally ineffective to use VBO for things that are streaming on apple
535 //when we already have a client buffer around 577
536 if (mUsage == GL_STREAM_DRAW_ARB) 578#if LL_DARWIN
579 if (!mUsage || mUsage == GL_STREAM_DRAW_ARB)
537 { 580 {
538 return FALSE; 581 return FALSE;
539 } 582 }
540 583#else
541 return sEnableVBOs && (!sRenderActive || !mLocked); 584 if (!mUsage)
585 {
586 return FALSE;
587 }
588#endif
589 return sEnableVBOs; // && (!sRenderActive || !mLocked);
542} 590}
543 591
544//---------------------------------------------------------------------------- 592//----------------------------------------------------------------------------
@@ -547,27 +595,27 @@ BOOL LLVertexBuffer::useVBOs() const
547U8* LLVertexBuffer::mapBuffer(S32 access) 595U8* LLVertexBuffer::mapBuffer(S32 access)
548{ 596{
549 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); 597 LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
550 if (sRenderActive)
551 {
552 llwarns << "Buffer mapped during render frame!" << llendl;
553 }
554 if (!mGLBuffer && !mGLIndices)
555 {
556 llerrs << "LLVertexBuffer::mapBuffer() called before createGLBuffer" << llendl;
557 }
558 if (mFinal) 598 if (mFinal)
559 { 599 {
560 llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl; 600 llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl;
561 } 601 }
562 if (!mMappedData && !mMappedIndexData) 602 if (!useVBOs() && !mMappedData && !mMappedIndexData)
563 { 603 {
564 llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl; 604 llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl;
565 } 605 }
566 606
567 if (!mLocked && useVBOs()) 607 if (!mLocked && useVBOs())
568 { 608 {
609 setBuffer(0);
569 mLocked = TRUE; 610 mLocked = TRUE;
570 sLockedList.push_back(this); 611 mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
612 mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
613 /*if (sMapped)
614 {
615 llerrs << "Mapped two VBOs at the same time!" << llendl;
616 }
617 sMapped = TRUE;*/
618 sMappedCount++;
571 } 619 }
572 620
573 return mMappedData; 621 return mMappedData;
@@ -580,64 +628,19 @@ void LLVertexBuffer::unmapBuffer()
580 { 628 {
581 if (useVBOs() && mLocked) 629 if (useVBOs() && mLocked)
582 { 630 {
583 if (mGLBuffer) 631 glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
584 { 632 glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
585 if (mResized) 633
586 { 634 /*if (!sMapped)
587 glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), mMappedData, mUsage);
588 }
589 else
590 {
591 if (mEmpty || mDirtyRegions.empty())
592 {
593 glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
594 }
595 else
596 {
597 for (std::vector<DirtyRegion>::iterator i = mDirtyRegions.begin(); i != mDirtyRegions.end(); ++i)
598 {
599 DirtyRegion& region = *i;
600 glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, region.mIndex*mStride, region.mCount*mStride, mMappedData + region.mIndex*mStride);
601 }
602 }
603 }
604 }
605
606 if (mGLIndices)
607 { 635 {
608 if (mResized) 636 llerrs << "Redundantly unmapped VBO!" << llendl;
609 {
610 glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), mMappedIndexData, mUsage);
611 }
612 else
613 {
614 if (mEmpty || mDirtyRegions.empty())
615 {
616 glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
617 }
618 else
619 {
620 for (std::vector<DirtyRegion>::iterator i = mDirtyRegions.begin(); i != mDirtyRegions.end(); ++i)
621 {
622 DirtyRegion& region = *i;
623 glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, region.mIndicesIndex*sizeof(U32),
624 region.mIndicesCount*sizeof(U32), mMappedIndexData + region.mIndicesIndex*sizeof(U32));
625 }
626 }
627 }
628 } 637 }
629 638 sMapped = FALSE;*/
630 mDirtyRegions.clear(); 639 sMappedCount--;
631 mFilthy = FALSE;
632 mResized = FALSE;
633 640
634 if (mUsage == GL_STATIC_DRAW_ARB) 641 if (mUsage == GL_STATIC_DRAW_ARB)
635 { //static draw buffers can only be mapped a single time 642 { //static draw buffers can only be mapped a single time
636 //throw out client data (we won't be using it again) 643 //throw out client data (we won't be using it again)
637 delete [] mMappedData;
638 delete [] mMappedIndexData;
639 mMappedIndexData = NULL;
640 mMappedData = NULL;
641 mEmpty = TRUE; 644 mEmpty = TRUE;
642 mFinal = TRUE; 645 mFinal = TRUE;
643 } 646 }
@@ -645,10 +648,11 @@ void LLVertexBuffer::unmapBuffer()
645 { 648 {
646 mEmpty = FALSE; 649 mEmpty = FALSE;
647 } 650 }
651
652 mMappedIndexData = NULL;
653 mMappedData = NULL;
648 654
649 mLocked = FALSE; 655 mLocked = FALSE;
650
651 glFlush();
652 } 656 }
653 } 657 }
654} 658}
@@ -690,9 +694,9 @@ bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index)
690{ 694{
691 return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index); 695 return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index);
692} 696}
693bool LLVertexBuffer::getIndexStrider(LLStrider<U32>& strider, S32 index) 697bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index)
694{ 698{
695 return VertexBufferStrider<U32,TYPE_INDEX>::get(*this, strider, index); 699 return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index);
696} 700}
697bool LLVertexBuffer::getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index) 701bool LLVertexBuffer::getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index)
698{ 702{
@@ -755,16 +759,46 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
755 { 759 {
756 if (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive)) 760 if (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))
757 { 761 {
762 /*if (sMapped)
763 {
764 llerrs << "VBO bound while another VBO mapped!" << llendl;
765 }*/
758 glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer); 766 glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
767 sBindCount++;
759 sVBOActive = TRUE; 768 sVBOActive = TRUE;
760 setup = TRUE; // ... or the bound buffer changed 769 setup = TRUE; // ... or the bound buffer changed
761 } 770 }
762 if (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive)) 771 if (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive))
763 { 772 {
773 /*if (sMapped)
774 {
775 llerrs << "VBO bound while another VBO mapped!" << llendl;
776 }*/
764 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices); 777 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
778 sBindCount++;
765 sIBOActive = TRUE; 779 sIBOActive = TRUE;
766 } 780 }
767 781
782 if (mResized)
783 {
784 if (mGLBuffer)
785 {
786 glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), NULL, mUsage);
787 }
788 if (mGLIndices)
789 {
790 glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), NULL, mUsage);
791 }
792
793 mEmpty = TRUE;
794 mResized = FALSE;
795
796 if (data_mask != 0)
797 {
798 llerrs << "Buffer set for rendering before being filled after resize." << llendl;
799 }
800 }
801
768 unmapBuffer(); 802 unmapBuffer();
769 } 803 }
770 else 804 else
@@ -774,6 +808,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
774 if (sEnableVBOs && sVBOActive) 808 if (sEnableVBOs && sVBOActive)
775 { 809 {
776 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); 810 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
811 sBindCount++;
777 sVBOActive = FALSE; 812 sVBOActive = FALSE;
778 setup = TRUE; // ... or a VBO is deactivated 813 setup = TRUE; // ... or a VBO is deactivated
779 } 814 }
@@ -784,7 +819,12 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
784 } 819 }
785 if (sEnableVBOs && mGLIndices && sIBOActive) 820 if (sEnableVBOs && mGLIndices && sIBOActive)
786 { 821 {
822 /*if (sMapped)
823 {
824 llerrs << "VBO unbound while potentially mapped!" << llendl;
825 }*/
787 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); 826 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
827 sBindCount++;
788 sIBOActive = FALSE; 828 sIBOActive = FALSE;
789 } 829 }
790 } 830 }
@@ -803,9 +843,11 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
803 llwarns << "Vertex buffer set for rendering outside of render frame." << llendl; 843 llwarns << "Vertex buffer set for rendering outside of render frame." << llendl;
804 } 844 }
805 setupVertexBuffer(data_mask); // subclass specific setup (virtual function) 845 setupVertexBuffer(data_mask); // subclass specific setup (virtual function)
806 sLastMask = data_mask; 846 sSetCount++;
807 } 847 }
808 } 848 }
849
850 sLastMask = data_mask;
809} 851}
810 852
811// virtual (default) 853// virtual (default)
@@ -821,10 +863,6 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
821 llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; 863 llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl;
822 } 864 }
823 865
824 if (data_mask & MAP_VERTEX)
825 {
826 glVertexPointer(3,GL_FLOAT, stride, (void*)(base + 0));
827 }
828 if (data_mask & MAP_NORMAL) 866 if (data_mask & MAP_NORMAL)
829 { 867 {
830 glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL])); 868 glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL]));
@@ -855,49 +893,19 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
855 { 893 {
856 glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); 894 glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]));
857 } 895 }
896 if (data_mask & MAP_VERTEX)
897 {
898 glVertexPointer(3,GL_FLOAT, stride, (void*)(base + 0));
899 }
858 900
859 llglassertok(); 901 llglassertok();
860} 902}
861 903
862void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count) 904void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count)
863{ 905{
864 if (useVBOs() && !mFilthy) 906 // TODO: use GL_APPLE_flush_buffer_range here
865 { 907 /*if (useVBOs() && !mFilthy)
866 if (!mDirtyRegions.empty())
867 {
868 DirtyRegion& region = *(mDirtyRegions.rbegin());
869
870 if (region.mIndex+region.mCount > vert_index)
871 {
872 //this buffer has received multiple updates since the last copy, mark it filthy
873 mFilthy = TRUE;
874 mDirtyRegions.clear();
875 return;
876 }
877
878 if (region.mIndex + region.mCount == vert_index &&
879 region.mIndicesIndex + region.mIndicesCount == indices_index)
880 {
881 region.mCount += vert_count;
882 region.mIndicesCount += indices_count;
883 return;
884 }
885 }
886
887 mDirtyRegions.push_back(DirtyRegion(vert_index,vert_count,indices_index,indices_count));
888 }
889}
890
891void LLVertexBuffer::markClean()
892{
893 if (!mResized && !mEmpty && !mFilthy)
894 { 908 {
895 buffer_list_t::reverse_iterator iter = sLockedList.rbegin(); 909
896 if (*iter == this) 910 }*/
897 {
898 mLocked = FALSE;
899 sLockedList.pop_back();
900 }
901 }
902} 911}
903