aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/lldrawpool.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/lldrawpool.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/lldrawpool.cpp')
-rw-r--r--linden/indra/newview/lldrawpool.cpp1417
1 files changed, 1417 insertions, 0 deletions
diff --git a/linden/indra/newview/lldrawpool.cpp b/linden/indra/newview/lldrawpool.cpp
new file mode 100644
index 0000000..18d6000
--- /dev/null
+++ b/linden/indra/newview/lldrawpool.cpp
@@ -0,0 +1,1417 @@
1/**
2 * @file lldrawpool.cpp
3 * @brief LLDrawPool class implementation
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "lldrawpool.h"
31
32#include "llfasttimer.h"
33#include "llviewercontrol.h"
34
35#include "llagparray.h"
36#include "lldrawable.h"
37#include "lldrawpoolalpha.h"
38#include "lldrawpoolavatar.h"
39#include "lldrawpoolbump.h"
40#include "lldrawpoolclouds.h"
41#include "lldrawpoolground.h"
42#include "lldrawpoolsimple.h"
43#include "lldrawpoolsky.h"
44#include "lldrawpoolstars.h"
45#include "lldrawpooltree.h"
46#include "lldrawpooltreenew.h"
47#include "lldrawpoolterrain.h"
48#include "lldrawpoolwater.h"
49#include "lldrawpoolhud.h"
50#include "llface.h"
51#include "llviewerobjectlist.h" // For debug listing.
52#include "llvotreenew.h"
53#include "pipeline.h"
54
55#include "llagparray.inl"
56
57U32 LLDrawPool::sDataSizes[LLDrawPool::DATA_MAX_TYPES] =
58{
59 12, // DATA_VERTICES
60 8, // DATA_TEX_COORDS0
61 8, // DATA_TEX_COORDS1
62 8, // DATA_TEX_COORDS2
63 8, // DATA_TEX_COORDS3
64 12, // DATA_NORMALS
65 4, // DATA_VERTEX_WEIGHTS,
66 16, // DATA_CLOTHING_WEIGHTS
67 12, // DATA_BINORMALS
68 4, // DATA_COLORS
69};
70
71S32 LLDrawPool::sNumDrawPools = 0;
72
73LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0)
74{
75 LLDrawPool *poolp = NULL;
76 switch (type)
77 {
78 case POOL_SIMPLE:
79 poolp = new LLDrawPoolSimple(tex0);
80 break;
81 case POOL_ALPHA:
82 poolp = new LLDrawPoolAlpha();
83 break;
84 case POOL_AVATAR:
85 poolp = new LLDrawPoolAvatar();
86 break;
87 case POOL_TREE:
88 poolp = new LLDrawPoolTree(tex0);
89 break;
90 case POOL_TREE_NEW:
91 poolp = new LLDrawPoolTreeNew(tex0);
92 break;
93 case POOL_TERRAIN:
94 poolp = new LLDrawPoolTerrain(tex0);
95 break;
96 case POOL_SKY:
97 poolp = new LLDrawPoolSky();
98 break;
99 case POOL_STARS:
100 poolp = new LLDrawPoolStars();
101 break;
102 case POOL_CLOUDS:
103 poolp = new LLDrawPoolClouds();
104 break;
105 case POOL_WATER:
106 poolp = new LLDrawPoolWater();
107 break;
108 case POOL_GROUND:
109 poolp = new LLDrawPoolGround();
110 break;
111 case POOL_BUMP:
112 poolp = new LLDrawPoolBump(tex0);
113 break;
114 case POOL_HUD:
115 poolp = new LLDrawPoolHUD();
116 break;
117 default:
118 llerrs << "Unknown draw pool type!" << llendl;
119 return NULL;
120 }
121
122 llassert(poolp->mType == type);
123 return poolp;
124}
125
126LLDrawPool::LLDrawPool(const U32 type, const U32 data_mask_il, const U32 data_mask_nil)
127{
128 llassert(data_mask_il & DATA_VERTICES_MASK);
129 S32 i;
130 mType = type;
131 sNumDrawPools++;
132 mId = sNumDrawPools;
133
134 mDataMaskIL = data_mask_il;
135 mDataMaskNIL = data_mask_nil;
136
137 U32 cur_mask = 0x01;
138 U32 cur_offset = 0;
139 for (i = 0; i < DATA_MAX_TYPES; i++)
140 {
141 mDataOffsets[i] = cur_offset;
142 if (cur_mask & mDataMaskIL)
143 {
144 cur_offset += sDataSizes[i];
145 }
146 cur_mask <<= 1;
147 }
148
149 mStride = cur_offset;
150
151 mCleanupUnused = FALSE;
152 mIndicesDrawn = 0;
153 mRebuildFreq = 128 + rand() % 5;
154 mRebuildTime = 0;
155 mGeneration = 1;
156 mSkippedVertices = 0;
157
158 resetDrawOrders();
159 resetVertexData(0);
160
161 if (gGLManager.mHasATIVAO && !gGLManager.mIsRadeon9700)
162 {
163 // ATI 8500 doesn't like indices > 15 bit.
164 mMaxVertices = DEFAULT_MAX_VERTICES/2;
165 }
166 else
167 {
168 mMaxVertices = DEFAULT_MAX_VERTICES;
169 }
170
171 // JC: This must happen last, as setUseAGP reads many of the
172 // above variables.
173 mUseAGP = FALSE;
174 setUseAGP(gPipeline.usingAGP());
175
176 for (i=0; i<NUM_BUCKETS; i++)
177 {
178 mFreeListGeomHead[i] = -1;
179 mFreeListIndHead[i] = -1;
180 }
181 mVertexShaderLevel = 0;
182}
183
184void LLDrawPool::destroy()
185{
186 if (!mReferences.empty())
187 {
188 llinfos << mReferences.size() << " references left on deletion of draw pool!" << llendl;
189 }
190}
191
192
193LLDrawPool::~LLDrawPool()
194{
195 destroy();
196
197 llassert( gPipeline.findPool( getType(), getTexture() ) == NULL );
198}
199
200BOOL LLDrawPool::setUseAGP(BOOL use_agp)
201{
202 BOOL ok = TRUE;
203 S32 vertex_count = mMemory.count() / mStride;
204 if (vertex_count > mMaxVertices && use_agp)
205 {
206#ifdef DEBUG_AGP
207 llwarns << "Allocating " << vertex_count << " vertices in pool type " << getType() << ", disabling AGP!" << llendl
208#endif
209 use_agp = FALSE;
210 ok = FALSE;
211 }
212
213 if (mUseAGP != use_agp)
214 {
215 mUseAGP = use_agp;
216
217 BOOL ok = TRUE;
218 ok &= mMemory.setUseAGP(use_agp);
219
220 if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK)
221 {
222 ok &= mWeights.setUseAGP(use_agp);
223 }
224 if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK)
225 {
226 ok &= mClothingWeights.setUseAGP(use_agp);
227 }
228
229 if (!ok)
230 {
231 // Disable AGP if any one of these doesn't have AGP, we don't want to try
232 // mixing AGP and non-agp arrays in a single pool.
233#ifdef DEBUG_AGP
234 llinfos << "Aborting using AGP because set failed on a mem block!" << llendl;
235#endif
236 setUseAGP(FALSE);
237 ok = FALSE;
238 }
239 }
240 return ok;
241}
242
243void LLDrawPool::flushAGP()
244{
245 mMemory.flushAGP();
246
247 if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK)
248 {
249 mWeights.flushAGP();
250 }
251 if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK)
252 {
253 mClothingWeights.flushAGP();
254 }
255}
256
257void LLDrawPool::syncAGP()
258{
259 if (!getVertexCount())
260 {
261 return;
262 }
263 setUseAGP(gPipeline.usingAGP());
264
265 BOOL all_agp_on = TRUE;
266 mMemory.sync();
267 all_agp_on &= mMemory.isAGP();
268
269 if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK)
270 {
271 mWeights.sync();
272 all_agp_on &= mWeights.isAGP();
273 }
274
275 if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK)
276 {
277 mClothingWeights.sync();
278 all_agp_on &= mClothingWeights.isAGP();
279 }
280
281 // Since sometimes AGP allocation is done during syncs, we need
282 // to make sure that if AGP allocation fails, we fallback to non-agp.
283 if (mUseAGP && !all_agp_on)
284 {
285#ifdef DEBUG_AGP
286 llinfos << "setUseAGP false because of AGP sync failure!" << llendl;
287#endif
288 setUseAGP(FALSE);
289 }
290}
291
292void LLDrawPool::dirtyTexture(const LLViewerImage *imagep)
293{
294}
295
296BOOL LLDrawPool::moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data)
297{
298 return TRUE;
299}
300
301// static
302S32 LLDrawPool::drawLoop(face_array_t& face_list, const U32* index_array)
303{
304 S32 res = 0;
305 if (!face_list.empty())
306 {
307 for (std::vector<LLFace*>::iterator iter = face_list.begin();
308 iter != face_list.end(); iter++)
309 {
310 LLFace *facep = *iter;
311 if (facep->mSkipRender)
312 {
313 continue;
314 }
315 facep->enableLights();
316 res += facep->renderIndexed(index_array);
317 }
318 }
319 return res;
320}
321
322// static
323S32 LLDrawPool::drawLoopSetTex(face_array_t& face_list, const U32* index_array, S32 stage)
324{
325 S32 res = 0;
326 if (!face_list.empty())
327 {
328 for (std::vector<LLFace*>::iterator iter = face_list.begin();
329 iter != face_list.end(); iter++)
330 {
331 LLFace *facep = *iter;
332 if (facep->mSkipRender)
333 {
334 continue;
335 }
336 facep->bindTexture(stage);
337 facep->enableLights();
338 res += facep->renderIndexed(index_array);
339 }
340 }
341 return res;
342}
343
344void LLDrawPool::drawLoop()
345{
346 const U32* index_array = getRawIndices();
347 if (!mDrawFace.empty())
348 {
349 mIndicesDrawn += drawLoop(mDrawFace, index_array);
350 }
351}
352
353BOOL LLDrawPool::getVertexStrider(LLStrider<LLVector3> &vertices, const U32 index)
354{
355 llassert(mDataMaskIL & LLDrawPool::DATA_VERTICES_MASK);
356 vertices = (LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_VERTICES] + index * mStride);
357 vertices.setStride(mStride);
358 return TRUE;
359}
360
361BOOL LLDrawPool::getTexCoordStrider(LLStrider<LLVector2> &tex_coords, const U32 index, const U32 pass)
362{
363 llassert(mDataMaskIL & (LLDrawPool::DATA_TEX_COORDS0_MASK << pass));
364 tex_coords = (LLVector2*)(mMemory.getMem() + mDataOffsets[DATA_TEX_COORDS0 + pass] + index * mStride);
365 tex_coords.setStride(mStride);
366 return TRUE;
367}
368
369
370BOOL LLDrawPool::getVertexWeightStrider(LLStrider<F32> &vertex_weights, const U32 index)
371{
372 llassert(mDataMaskNIL & LLDrawPool::DATA_VERTEX_WEIGHTS_MASK);
373
374 vertex_weights = &mWeights[index];
375 vertex_weights.setStride( 0 );
376 return TRUE;
377}
378
379BOOL LLDrawPool::getClothingWeightStrider(LLStrider<LLVector4> &clothing_weights, const U32 index)
380{
381 llassert(mDataMaskNIL & LLDrawPool::DATA_CLOTHING_WEIGHTS_MASK);
382
383 clothing_weights= &mClothingWeights[index];
384 clothing_weights.setStride( 0 );
385
386 return TRUE;
387}
388
389BOOL LLDrawPool::getNormalStrider(LLStrider<LLVector3> &normals, const U32 index)
390{
391 llassert((mDataMaskIL) & LLDrawPool::DATA_NORMALS_MASK);
392
393 normals = (LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_NORMALS] + index * mStride);
394
395 normals.setStride( mStride );
396
397 return TRUE;
398}
399
400
401BOOL LLDrawPool::getBinormalStrider(LLStrider<LLVector3> &binormals, const U32 index)
402{
403 llassert((mDataMaskIL) & LLDrawPool::DATA_BINORMALS_MASK);
404
405 binormals = (LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_BINORMALS] + index * mStride);
406
407 binormals.setStride( mStride );
408
409 return TRUE;
410}
411
412BOOL LLDrawPool::getColorStrider(LLStrider<LLColor4U> &colors, const U32 index)
413{
414 llassert((mDataMaskIL) & LLDrawPool::DATA_COLORS_MASK);
415
416 colors = (LLColor4U*)(mMemory.getMem() + mDataOffsets[DATA_COLORS] + index * mStride);
417
418 colors.setStride( mStride );
419
420 return TRUE;
421}
422
423//virtual
424void LLDrawPool::beginRenderPass( S32 pass )
425{
426}
427
428//virtual
429void LLDrawPool::endRenderPass( S32 pass )
430{
431 glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
432 glDisableClientState ( GL_COLOR_ARRAY );
433 glDisableClientState ( GL_NORMAL_ARRAY );
434}
435void LLDrawPool::renderFaceSelected(LLFace *facep,
436 LLImageGL *image,
437 const LLColor4 &color,
438 const S32 index_offset, const S32 index_count)
439{
440}
441
442void LLDrawPool::renderVisibility()
443{
444 if (mDrawFace.empty())
445 {
446 return;
447 }
448
449 // SJB: Note: This may be broken now. If you need it, fix it :)
450
451 glLineWidth(1.0);
452 glMatrixMode(GL_PROJECTION);
453 glPushMatrix();
454 glLoadIdentity();
455 glMatrixMode(GL_MODELVIEW);
456 glPushMatrix();
457 glLoadIdentity();
458
459 glTranslatef(-0.4f,-0.3f,0);
460
461 float table[7][3] = {
462 { 1,0,0 },
463 { 0,1,0 },
464 { 1,1,0 },
465 { 0,0,1 },
466 { 1,0,1 },
467 { 0,1,1 },
468 { 1,1,1 }
469 };
470
471 glColor4f(0,0,0,0.5);
472 glBegin(GL_POLYGON);
473 glVertex3f(-0.5f,-0.5f,1.0f);
474 glVertex3f(+0.5f,-0.5f,1.0f);
475 glVertex3f(+0.5f,+0.5f,1.0f);
476 glVertex3f(-0.5f,+0.5f,1.0f);
477 glVertex3f(-0.5f,-0.5f,1.0f);
478 glEnd();
479
480 for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
481 iter != mDrawFace.end(); iter++)
482 {
483 LLFace *face = *iter;
484
485 S32 geom_count = face->getGeomCount();
486 for (S32 j=0;j<geom_count;j++)
487 {
488 LLVector3 p1;
489 LLVector3 p2;
490
491 intptr_t p = ((intptr_t)face*13) % 7;
492 F32 r = table[p][0];
493 F32 g = table[p][1];
494 F32 b = table[p][2];
495
496 //p1.mV[1] = y;
497 //p2.mV[1] = y;
498
499 p1.mV[2] = 1.0;
500 p2.mV[2] = 1.0;
501
502 glColor4f(r,g,b,0.5f);
503
504 glBegin(GL_LINE_STRIP);
505 glVertex3fv(p1.mV);
506 glVertex3fv(p2.mV);
507 glEnd();
508
509 }
510 }
511
512 glColor4f(1,1,1,1);
513 glBegin(GL_LINE_STRIP);
514 glVertex3f(-0.5f,-0.5f,1.0f);
515 glVertex3f(+0.5f,-0.5f,1.0f);
516 glVertex3f(+0.5f,+0.5f,1.0f);
517 glVertex3f(-0.5f,+0.5f,1.0f);
518 glVertex3f(-0.5f,-0.5f,1.0f);
519 glEnd();
520
521 glPopMatrix();
522 glMatrixMode(GL_PROJECTION);
523 glPopMatrix();
524 glMatrixMode(GL_MODELVIEW);
525
526}
527
528void LLDrawPool::enqueue(LLFace* facep)
529{
530 if (facep->isState(LLFace::BACKLIST))
531 {
532 mMoveFace.put(facep);
533 }
534 else
535 {
536#if ENABLE_FACE_LINKING
537 facep->mSkipRender = FALSE;
538 facep->mNextFace = NULL;
539
540 if (mDrawFace.size() > 0)
541 {
542 LLFace* last_face = mDrawFace[mDrawFace.size()-1];
543 if (match(last_face, facep))
544 {
545 last_face->link(facep);
546 }
547 }
548#endif
549 mDrawFace.put(facep);
550 }
551}
552
553void LLDrawPool::bindGLVertexPointer()
554{
555 mMemory.bindGLVertexPointer(getStride(DATA_VERTICES), mDataOffsets[DATA_VERTICES]);
556}
557
558void LLDrawPool::bindGLTexCoordPointer(const U32 pass)
559{
560 mMemory.bindGLTexCoordPointer(getStride(DATA_TEX_COORDS0+pass), mDataOffsets[DATA_TEX_COORDS0+pass]);
561}
562
563void LLDrawPool::bindGLNormalPointer()
564{
565 mMemory.bindGLNormalPointer(getStride(DATA_NORMALS), mDataOffsets[DATA_NORMALS]);
566}
567
568void LLDrawPool::bindGLBinormalPointer(S32 index)
569{
570 mMemory.bindGLBinormalPointer(index, getStride(DATA_BINORMALS), mDataOffsets[DATA_BINORMALS]);
571}
572
573void LLDrawPool::bindGLColorPointer()
574{
575 mMemory.bindGLColorPointer(getStride(DATA_COLORS), mDataOffsets[DATA_COLORS]);
576}
577
578void LLDrawPool::bindGLVertexWeightPointer(S32 index)
579{
580 mWeights.bindGLVertexWeightPointer(index, 0, 0);
581}
582
583void LLDrawPool::bindGLVertexClothingWeightPointer(S32 index)
584{
585 mClothingWeights.bindGLVertexClothingWeightPointer(index, 0, 0);
586}
587
588
589U32* LLDrawPool::getIndices(S32 index)
590{
591 return &mIndices[index];
592}
593
594const LLVector3& LLDrawPool::getVertex(const S32 index)
595{
596 llassert(mDataMaskIL & DATA_VERTICES_MASK);
597 llassert(index < mMemory.count());
598 llassert(mMemory.getMem());
599 return *(LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_VERTICES] + index * mStride);
600}
601
602const LLVector2& LLDrawPool::getTexCoord(const S32 index, const U32 pass)
603{
604 llassert(mDataMaskIL & (LLDrawPool::DATA_TEX_COORDS0_MASK << pass));
605 llassert(index < mMemory.count());
606 return *(LLVector2*)(mMemory.getMem() + mDataOffsets[DATA_TEX_COORDS0 + pass] + index * mStride);
607}
608
609const LLVector3& LLDrawPool::getNormal(const S32 index)
610{
611 llassert(mDataMaskIL & DATA_NORMALS_MASK);
612 llassert(index < mMemory.count());
613 return *(LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_NORMALS] + index * mStride);
614}
615
616const LLVector3& LLDrawPool::getBinormal(const S32 index)
617{
618 llassert(mDataMaskIL & DATA_BINORMALS_MASK);
619 llassert(index < mMemory.count());
620 return *(LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_BINORMALS] + index * mStride);
621}
622
623const LLColor4U& LLDrawPool::getColor(const S32 index)
624{
625 llassert(mDataMaskIL & DATA_COLORS_MASK);
626 llassert(index < mMemory.count());
627 return *(LLColor4U*)(mMemory.getMem() + mDataOffsets[DATA_COLORS] + index * mStride);
628}
629
630const F32& LLDrawPool::getVertexWeight(const S32 index)
631{
632 llassert(mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK);
633 llassert(index < mWeights.count());
634 llassert(mWeights.getMem());
635 return mWeights[index];
636}
637
638const LLVector4& LLDrawPool::getClothingWeight(const S32 index)
639{
640 llassert(mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK);
641 llassert(index < mClothingWeights.count());
642 llassert(mClothingWeights.getMem());
643 return mClothingWeights[index];
644}
645
646//////////////////////////////////////////////////////////////////////////////
647
648#define USE_FREE_LIST 0
649#define DEBUG_FREELIST 0
650
651struct tFreeListNode
652{
653 U32 count;
654 S32 next;
655};
656
657#if DEBUG_FREELIST
658static void check_list(U8 *pool, S32 stride, S32 head, S32 max)
659{
660 int count = 0;
661
662 while (head >= 0)
663 {
664 tFreeListNode *node = (tFreeListNode *)(pool + head*stride);
665 count++;
666 if ((count > max) || ((node->count>>20) != 0xabc) || ((node->count&0xfffff) < 2))
667 llerrs << "Bad Ind List" << llendl;
668 head = node->next;
669 }
670}
671#define CHECK_LIST(x) check_list##x
672#else
673#define CHECK_LIST(x)
674#endif
675
676// DEBUG!
677void LLDrawPool::CheckIntegrity()
678{
679#if DEBUG_FREELIST
680 int bucket;
681 for (bucket=0; bucket<NUM_BUCKETS; bucket++)
682 {
683 CHECK_LIST(((U8 *)mMemory.getMem(), mStride, mFreeListGeomHead[bucket], mMemory.count() / mStride));
684 CHECK_LIST(((U8 *)mIndices.getMem(), 4, mFreeListIndHead[bucket], mIndices.count()));
685 }
686#endif
687}
688
689int LLDrawPool::freeListBucket(U32 count)
690{
691 int bucket;
692
693 // llassert(NUM_BUCKETS == 8)
694
695 if (count & ~511) // >= 512
696 bucket = 7;
697 else if (count & 256) // 256-511
698 bucket = 6;
699 else if (count & 128)
700 bucket = 5;
701 else if (count & 64)
702 bucket = 4;
703 else if (count & 32)
704 bucket = 3;
705 else if (count & 16)
706 bucket = 2;
707 else if (count & 8) // 8-15
708 bucket = 1;
709 else // 0-7
710 bucket = 0;
711 return bucket;
712}
713
714void remove_node(int nodeidx, int pidx, U8 *membase, int stride, int *head)
715{
716 LLDrawPool::FreeListNode *node = (LLDrawPool::FreeListNode *)(membase + nodeidx*stride);
717 if (pidx >= 0)
718 {
719 LLDrawPool::FreeListNode *pnode = (LLDrawPool::FreeListNode *)(membase + pidx*stride);
720 pnode->next = node->next;
721 }
722 else
723 {
724 *head = node->next;
725 }
726}
727
728void LLDrawPool::freeListAddGeom(S32 index, U32 count)
729{
730#if USE_FREE_LIST
731 int i;
732 U8 *membase = (U8*)mMemory.getMem();
733 // See if next block or previous block is free, if so combine them
734 for (i=0; i<NUM_BUCKETS; i++)
735 {
736 int pidx = -1;
737 int nodeidx = mFreeListGeomHead[i];
738 while(nodeidx >= 0)
739 {
740 int change = 0;
741 FreeListNode *node = (FreeListNode *)(membase + nodeidx*mStride);
742 int nodecount = node->count & 0xffff;
743 // Check for prev block
744 if (nodeidx + nodecount == index)
745 {
746 remove_node(nodeidx, pidx, membase, mStride, &mFreeListGeomHead[i]);
747 // Combine nodes
748 index = nodeidx;
749 count += nodecount;
750 i = 0; // start over ; i = NUM_BUCKETS // done
751 change = 1;
752 //break;
753 }
754 // Check for next block
755 if (nodeidx == index + count)
756 {
757 remove_node(nodeidx, pidx, membase, mStride, &mFreeListGeomHead[i]);
758 // Combine nodes
759 count += nodecount;
760 i = 0; // start over ; i = NUM_BUCKETS // done
761 change = 1;
762 //break;
763 }
764 if (change)
765 break;
766 pidx = nodeidx;
767 nodeidx = node->next;
768 }
769 }
770 // Add (extended) block to free list
771 if (count >= 2) // need 2 words to store free list (theoreticly mStride could = 4)
772 {
773 CheckIntegrity();
774 if ((index + count)*mStride >= mMemory.count())
775 {
776 mMemory.shrinkTo(index*mStride);
777 }
778 else
779 {
780 int bucket = freeListBucket(count);
781 FreeListNode *node = (FreeListNode *)(membase + index*mStride);
782 node->count = count | (0xabc<<20);
783 node->next = mFreeListGeomHead[bucket];
784 mFreeListGeomHead[bucket] = index;
785 }
786 CheckIntegrity();
787 }
788#endif
789}
790
791void LLDrawPool::freeListAddInd(S32 index, U32 count)
792{
793#if USE_FREE_LIST
794 int i;
795 const U32 *membase = mIndices.getMem();
796 // See if next block or previous block is free, if so combine them
797 for (i=0; i<NUM_BUCKETS; i++)
798 {
799 int pidx = -1;
800 int nodeidx = mFreeListIndHead[i];
801 while(nodeidx >= 0)
802 {
803 int change = 0;
804 FreeListNode *node = (FreeListNode *)(membase + nodeidx);
805 int nodecount = node->count & 0xffff;
806 // Check for prev block
807 if (nodeidx + nodecount == index)
808 {
809 remove_node(nodeidx, pidx, (U8*)membase, 4, &mFreeListIndHead[i]);
810 // Combine nodes
811 index = nodeidx;
812 count += nodecount;
813 i = 0; // start over ; i = NUM_BUCKETS // done
814 change = 1;
815 //break;
816 }
817 // Check for next block
818 if (nodeidx == index + count)
819 {
820 remove_node(nodeidx, pidx, (U8*)membase, 4, &mFreeListIndHead[i]);
821 // Combine nodes
822 count += nodecount;
823 i = 0; // start over ; i = NUM_BUCKETS // done
824 change = 1;
825 //break;
826 }
827 if (change)
828 break;
829 pidx = nodeidx;
830 nodeidx = node->next;
831 }
832 }
833 // Add (extended) block to free list
834 if (count >= 2) // need 2 words to store free list
835 {
836 CheckIntegrity();
837 if (index + count >= mIndices.count())
838 {
839 mIndices.shrinkTo(index);
840 }
841 else
842 {
843 int bucket = freeListBucket(count);
844 FreeListNode *node = (FreeListNode *)(membase + index);
845 node->count = count | (0xabc<<20);
846 node->next = mFreeListIndHead[bucket];
847 mFreeListIndHead[bucket] = index;
848 }
849 CheckIntegrity();
850 }
851#endif
852}
853
854S32 LLDrawPool::freeListFindGeom(U32 count)
855{
856#if USE_FREE_LIST
857 int i, nodeidx, pidx;
858 int firstbucket = freeListBucket(count);
859 U8 *membase = (U8*)mMemory.getMem();
860 for (i=firstbucket; i<NUM_BUCKETS; i++)
861 {
862 pidx = -1;
863 nodeidx = mFreeListGeomHead[i];
864 CHECK_LIST(((U8 *)mMemory.getMem(), mStride, mFreeListGeomHead[i], mMemory.count() / mStride));
865 while(nodeidx >= 0)
866 {
867 FreeListNode *node = (FreeListNode *)(membase + nodeidx*mStride);
868 int nodecount = node->count & 0xffff;
869 llassert((node->count>>20) == 0xabc);
870 if (nodecount >= count)
871 {
872 remove_node(nodeidx, pidx, membase, mStride, &mFreeListGeomHead[i]);
873#if 1
874 if (nodecount > count)
875 {
876 int leftover = nodecount - count;
877 freeListAddGeom(nodeidx + count, leftover);
878 }
879#endif
880 return nodeidx;
881 }
882 pidx = nodeidx;
883 nodeidx = node->next;
884 }
885 }
886#endif // USE_FREE_LIST
887 return -1;
888}
889
890S32 LLDrawPool::freeListFindInd(U32 count)
891{
892#if USE_FREE_LIST
893 int i, nodeidx, pidx;
894 int firstbucket = freeListBucket(count);
895 U32 *membase = (U32 *)mIndices.getMem();
896 for (i=firstbucket; i<NUM_BUCKETS; i++)
897 {
898 pidx = -1;
899 nodeidx = mFreeListIndHead[i];
900 CHECK_LIST(((U8 *)mIndices.getMem(), 4, mFreeListIndHead[i], mIndices.count()));
901 while(nodeidx >= 0)
902 {
903 FreeListNode *node = (FreeListNode *)(membase + nodeidx);
904 int nodecount = node->count & 0xffff;
905 llassert((node->count>>20) == 0xabc);
906 if (nodecount >= count)
907 {
908 remove_node(nodeidx, pidx, (U8*)membase, 4, &mFreeListIndHead[i]);
909#if 1
910 if (nodecount > count)
911 {
912 int leftover = nodecount - count;
913 freeListAddInd(nodeidx + count, leftover);
914 }
915#endif
916 return nodeidx;
917 }
918 pidx = nodeidx;
919 nodeidx = node->next;
920 }
921 }
922#endif // USE_FREE_LIST
923 return -1;
924}
925
926//////////////////////////////////////////////////////////////////////////////
927
928S32 LLDrawPool::reserveGeom(const U32 geom_count)
929{
930 LLFastTimer t(LLFastTimer::FTM_GEO_RESERVE);
931
932 S32 index;
933 index = freeListFindGeom(geom_count);
934 if (index < 0)
935 {
936 index = mMemory.count() / mStride;
937 if (!geom_count)
938 {
939 llwarns << "Attempting to reserve zero bytes!" << llendl;
940 return index;
941 }
942
943 S32 bytes = geom_count * mStride;
944
945 if ((index + (S32)geom_count) > (S32)mMaxVertices)
946 {
947 //
948 // Various drivers have issues with the number of indices being greater than a certain number.
949 // if you're using AGP. Disable AGP if we've got more vertices than in the pool.
950 //
951#ifdef DEBUG_AGP
952 llinfos << "setUseAGP false because of large vertex count in reserveGeom" << llendl;
953#endif
954 setUseAGP(FALSE);
955 }
956
957 mMemory.reserve_block(bytes);
958 if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK)
959 {
960 mWeights.reserve_block(geom_count);
961 }
962 if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK)
963 {
964 mClothingWeights.reserve_block(geom_count);
965 }
966 }
967 CHECK_LIST(((U8 *)mMemory.getMem(), mStride, mFreeListGeomHead[0], mMemory.count() / mStride));
968 return index;
969}
970
971S32 LLDrawPool::reserveInd(U32 indCount)
972{
973 S32 index;
974 index = freeListFindInd(indCount);
975 if (index < 0)
976 {
977 index = mIndices.count();
978
979 if (indCount)
980 {
981 mIndices.reserve_block(indCount);
982 }
983 }
984 for (U32 i=0;i<indCount;i++)
985 {
986 mIndices[index+i]=0;
987 }
988 CHECK_LIST(((U8 *)mIndices.getMem(), 4, mFreeListIndHead[0], mIndices.count()));
989 return index;
990}
991
992S32 LLDrawPool::unReserveGeom(const S32 index, const U32 count)
993{
994 if (index < 0 || count == 0)
995 return -1;
996
997 freeListAddGeom(index, count);
998
999#if 0
1000 int i;
1001 S32 bytes,words;
1002 U32 *memp;
1003 // Fill mem with bad data (for testing only)
1004 bytes = count * mStride;
1005 bytes -= sizeof(FreeListNode);
1006 memp = (U32*)(mMemory.getMem() + index * mStride);
1007 memp += sizeof(FreeListNode)>>2;
1008 words = bytes >> 2;
1009 for (i=0; i<words; i++)
1010 *memp++ = 0xffffffff;
1011
1012 words = count; // (sizeof each array is a word)
1013 if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK)
1014 {
1015 memp = (U32*)(&mWeights[index]);
1016 for (i=0; i<words; i++)
1017 *memp++ = 0xffffffff;
1018 }
1019 if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK)
1020 {
1021 memp = (U32*)(&mClothingWeights[index]);
1022 for (i=0; i<count; i++)
1023 *memp++ = 0xffffffff;
1024 }
1025#endif
1026 return -1;
1027}
1028
1029S32 LLDrawPool::unReserveInd(const S32 index, const U32 count)
1030{
1031 if (index < 0 || count == 0)
1032 return -1;
1033
1034 freeListAddInd(index, count);
1035
1036#if 0
1037 int i;
1038 U32 *memp = &mIndices[index];
1039 for (i=0; i<count; i++)
1040 *memp++ = 0xffffffff;
1041#endif
1042 return -1;
1043}
1044
1045//////////////////////////////////////////////////////////////////////////////
1046
1047const U32 LLDrawPool::getIndexCount() const
1048{
1049 return mIndices.count();
1050}
1051
1052const U32 LLDrawPool::getVertexCount() const
1053{
1054 return mMemory.count() / mStride;
1055}
1056
1057const U32 LLDrawPool::getTexCoordCount(U32 pass) const
1058{
1059 return mMemory.count() / mStride;
1060}
1061
1062
1063const U32 LLDrawPool::getNormalCount() const
1064{
1065 return mMemory.count() / mStride;
1066}
1067
1068
1069const U32 LLDrawPool::getBinormalCount() const
1070{
1071 return mMemory.count() / mStride;
1072}
1073
1074const U32 LLDrawPool::getColorCount() const
1075{
1076 return mMemory.count() / mStride;
1077}
1078
1079const U32 LLDrawPool::getVertexWeightCount() const
1080{
1081 return mWeights.count();
1082}
1083
1084// virtual
1085BOOL LLDrawPool::addFace(LLFace *facep)
1086{
1087 addFaceReference(facep);
1088 return TRUE;
1089}
1090
1091// virtual
1092BOOL LLDrawPool::removeFace(LLFace *facep)
1093{
1094 removeFaceReference(facep);
1095
1096 vector_replace_with_last(mDrawFace, facep);
1097
1098 facep->unReserve();
1099
1100 return TRUE;
1101}
1102
1103// Not absolutely sure if we should be resetting all of the chained pools as well - djs
1104void LLDrawPool::resetDrawOrders()
1105{
1106 mDrawFace.resize(0);
1107}
1108
1109void LLDrawPool::resetIndices(S32 indices_count)
1110{
1111 mIndices.reset(indices_count);
1112 for (S32 i=0; i<NUM_BUCKETS; i++)
1113 mFreeListIndHead[i] = -1;
1114}
1115
1116void LLDrawPool::resetVertexData(S32 reserve_count)
1117{
1118 mMemory.reset(reserve_count*mStride);
1119
1120 for (S32 i=0; i<NUM_BUCKETS; i++)
1121 {
1122 mFreeListGeomHead[i] = -1;
1123 }
1124 if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK)
1125 {
1126 mWeights.reset(reserve_count);
1127 }
1128
1129 if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK)
1130 {
1131 mClothingWeights.reset(reserve_count);
1132 }
1133}
1134
1135void LLDrawPool::resetAll()
1136{
1137 resetDrawOrders();
1138 resetVertexData(0);
1139 mGeneration++;
1140
1141}
1142
1143S32 LLDrawPool::rebuild()
1144{
1145 mRebuildTime++;
1146
1147 BOOL needs_rebuild = FALSE;
1148 S32 rebuild_cost = 0;
1149
1150 if (mUseAGP)
1151 {
1152 if (getVertexCount() > 0.75f*DEFAULT_MAX_VERTICES)
1153 {
1154 if (mRebuildTime > 8)
1155 {
1156 needs_rebuild = TRUE;
1157 }
1158#ifdef DEBUG_AGP
1159 llwarns << "More than " << DEFAULT_MAX_VERTICES << " in pool type " << (S32)mType << " at rebuild!" << llendl;
1160#endif
1161 }
1162 }
1163
1164 // rebuild de-allocates 'stale' objects, so we still need to do a rebuild periodically
1165 if (mRebuildFreq > 0 && mRebuildTime >= mRebuildFreq)
1166 {
1167 needs_rebuild = TRUE;
1168 }
1169
1170 if (needs_rebuild)
1171 {
1172 mGeneration++;
1173
1174 if (mReferences.empty())
1175 {
1176 resetIndices(0);
1177 resetVertexData(0);
1178 }
1179 else
1180 {
1181 for (std::vector<LLFace*>::iterator iter = mReferences.begin();
1182 iter != mReferences.end(); iter++)
1183 {
1184 LLFace *facep = *iter;
1185 if (facep->hasGeometry() && !facep->isState(LLFace::BACKLIST | LLFace::SHARED_GEOM))
1186 {
1187 facep->backup();
1188 }
1189 }
1190 S32 tot_verts = 0;
1191 S32 tot_indices = 0;
1192 for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
1193 iter != mDrawFace.end(); iter++)
1194 {
1195 LLFace *facep = *iter;
1196 if (facep->isState(LLFace::BACKLIST))
1197 {
1198 tot_verts += facep->getGeomCount();
1199 tot_indices += facep->getIndicesCount();
1200 }
1201 }
1202 for (std::vector<LLFace*>::iterator iter = mMoveFace.begin();
1203 iter != mMoveFace.end(); iter++)
1204 {
1205 LLFace *facep = *iter;
1206 if (facep->isState(LLFace::BACKLIST))
1207 {
1208 tot_verts += facep->getGeomCount();
1209 tot_indices += facep->getIndicesCount();
1210 }
1211 }
1212
1213 resetIndices(tot_indices);
1214 flushAGP();
1215 resetVertexData(tot_verts);
1216
1217 for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
1218 iter != mDrawFace.end(); iter++)
1219 {
1220 LLFace *facep = *iter;
1221 llassert(facep->getPool() == this);
1222 facep->restore();
1223 }
1224 }
1225 mRebuildTime = 0;
1226 setDirty();
1227 }
1228
1229 if (!mMoveFace.empty())
1230 {
1231 for (std::vector<LLFace*>::iterator iter = mMoveFace.begin();
1232 iter != mMoveFace.end(); iter++)
1233 {
1234 LLFace *facep = *iter;
1235 facep->restore();
1236 enqueue(facep);
1237 }
1238 setDirty();
1239 mMoveFace.reset();
1240 rebuild_cost++;
1241 }
1242 return rebuild_cost;
1243}
1244
1245LLViewerImage *LLDrawPool::getTexture()
1246{
1247 return NULL;
1248}
1249
1250LLViewerImage *LLDrawPool::getDebugTexture()
1251{
1252 return NULL;
1253}
1254
1255void LLDrawPool::removeFaceReference(LLFace *facep)
1256{
1257 if (facep->getReferenceIndex() != -1)
1258 {
1259 if (facep->getReferenceIndex() != (S32)mReferences.size())
1260 {
1261 LLFace *back = mReferences.back();
1262 mReferences[facep->getReferenceIndex()] = back;
1263 back->setReferenceIndex(facep->getReferenceIndex());
1264 }
1265 mReferences.pop_back();
1266 }
1267 facep->setReferenceIndex(-1);
1268}
1269
1270void LLDrawPool::addFaceReference(LLFace *facep)
1271{
1272 if (-1 == facep->getReferenceIndex())
1273 {
1274 facep->setReferenceIndex(mReferences.size());
1275 mReferences.push_back(facep);
1276 }
1277}
1278
1279U32 LLDrawPool::getTrianglesDrawn() const
1280{
1281 return mIndicesDrawn / 3;
1282}
1283
1284void LLDrawPool::resetTrianglesDrawn()
1285{
1286 mIndicesDrawn = 0;
1287}
1288
1289void LLDrawPool::addIndicesDrawn(const U32 indices)
1290{
1291 mIndicesDrawn += indices;
1292}
1293
1294BOOL LLDrawPool::verify() const
1295{
1296 BOOL ok = TRUE;
1297 // Verify all indices in the pool are in the right range
1298 const U32 *indicesp = getRawIndices();
1299 for (U32 i = 0; i < getIndexCount(); i++)
1300 {
1301 if (indicesp[i] > getVertexCount())
1302 {
1303 ok = FALSE;
1304 llinfos << "Bad index in tree pool!" << llendl;
1305 }
1306 }
1307
1308 for (std::vector<LLFace*>::const_iterator iter = mDrawFace.begin();
1309 iter != mDrawFace.end(); iter++)
1310 {
1311 const LLFace* facep = *iter;
1312 if (facep->getPool() != this)
1313 {
1314 llinfos << "Face in wrong pool!" << llendl;
1315 facep->printDebugInfo();
1316 ok = FALSE;
1317 }
1318 else if (!facep->verify())
1319 {
1320 ok = FALSE;
1321 }
1322 }
1323
1324 return ok;
1325}
1326
1327void LLDrawPool::printDebugInfo() const
1328{
1329 llinfos << "Pool " << this << " Type: " << getType() << llendl;
1330 llinfos << "--------------------" << llendl;
1331 llinfos << "Vertex count: " << getVertexCount() << llendl;
1332 llinfos << "Normal count: " << getNormalCount() << llendl;
1333 llinfos << "Indices count: " << getIndexCount() << llendl;
1334 llinfos << llendl;
1335}
1336
1337
1338S32 LLDrawPool::getMemUsage(const BOOL print)
1339{
1340 S32 mem_usage = 0;
1341
1342 mem_usage += sizeof(this);
1343
1344 // Usage beyond the pipeline allocated data (color and mMemory)
1345 mem_usage += mIndices.getMax() * sizeof(U32);
1346 mem_usage += mDrawFace.capacity() * sizeof(LLFace *);
1347 mem_usage += mMoveFace.capacity() * sizeof(LLFace *);
1348 mem_usage += mReferences.capacity() * sizeof(LLFace *);
1349
1350 mem_usage += mMemory.getSysMemUsage();
1351 mem_usage += mWeights.getSysMemUsage();
1352 mem_usage += mClothingWeights.getSysMemUsage();
1353
1354 return mem_usage;
1355}
1356
1357LLColor3 LLDrawPool::getDebugColor() const
1358{
1359 return LLColor3(0.f, 0.f, 0.f);
1360}
1361
1362void LLDrawPool::setDirty()
1363{
1364 mMemory.setDirty();
1365 mWeights.setDirty();
1366 mClothingWeights.setDirty();
1367}
1368
1369BOOL LLDrawPool::LLOverrideFaceColor::sOverrideFaceColor = FALSE;
1370
1371void LLDrawPool::LLOverrideFaceColor::setColor(const LLColor4& color)
1372{
1373 if (mPool->mVertexShaderLevel > 0 && mPool->getMaterialAttribIndex() > 0)
1374 {
1375 glVertexAttrib4fvARB(mPool->getMaterialAttribIndex(), color.mV);
1376 }
1377 else
1378 {
1379 glColor4fv(color.mV);
1380 }
1381}
1382
1383void LLDrawPool::LLOverrideFaceColor::setColor(const LLColor4U& color)
1384{
1385 if (mPool->mVertexShaderLevel > 0 && mPool->getMaterialAttribIndex() > 0)
1386 {
1387 glVertexAttrib4ubvARB(mPool->getMaterialAttribIndex(), color.mV);
1388 }
1389 else
1390 {
1391 glColor4ubv(color.mV);
1392 }
1393}
1394
1395void LLDrawPool::LLOverrideFaceColor::setColor(F32 r, F32 g, F32 b, F32 a)
1396{
1397 if (mPool->mVertexShaderLevel > 0 && mPool->getMaterialAttribIndex() > 0)
1398 {
1399 glVertexAttrib4fARB(mPool->getMaterialAttribIndex(), r,g,b,a);
1400 }
1401 else
1402 {
1403 glColor4f(r,g,b,a);
1404 }
1405}
1406
1407// virtual
1408void LLDrawPool::enableShade()
1409{ }
1410
1411// virtual
1412void LLDrawPool::disableShade()
1413{ }
1414
1415// virtual
1416void LLDrawPool::setShade(F32 shade)
1417{ }