diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/lldrawpool.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 1417 |
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 | |||
57 | U32 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 | |||
71 | S32 LLDrawPool::sNumDrawPools = 0; | ||
72 | |||
73 | LLDrawPool *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 | |||
126 | LLDrawPool::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 | |||
184 | void LLDrawPool::destroy() | ||
185 | { | ||
186 | if (!mReferences.empty()) | ||
187 | { | ||
188 | llinfos << mReferences.size() << " references left on deletion of draw pool!" << llendl; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | |||
193 | LLDrawPool::~LLDrawPool() | ||
194 | { | ||
195 | destroy(); | ||
196 | |||
197 | llassert( gPipeline.findPool( getType(), getTexture() ) == NULL ); | ||
198 | } | ||
199 | |||
200 | BOOL 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 | |||
243 | void 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 | |||
257 | void 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 | |||
292 | void LLDrawPool::dirtyTexture(const LLViewerImage *imagep) | ||
293 | { | ||
294 | } | ||
295 | |||
296 | BOOL LLDrawPool::moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data) | ||
297 | { | ||
298 | return TRUE; | ||
299 | } | ||
300 | |||
301 | // static | ||
302 | S32 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 | ||
323 | S32 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 | |||
344 | void LLDrawPool::drawLoop() | ||
345 | { | ||
346 | const U32* index_array = getRawIndices(); | ||
347 | if (!mDrawFace.empty()) | ||
348 | { | ||
349 | mIndicesDrawn += drawLoop(mDrawFace, index_array); | ||
350 | } | ||
351 | } | ||
352 | |||
353 | BOOL 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 | |||
361 | BOOL 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 | |||
370 | BOOL 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 | |||
379 | BOOL 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 | |||
389 | BOOL 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 | |||
401 | BOOL 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 | |||
412 | BOOL 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 | ||
424 | void LLDrawPool::beginRenderPass( S32 pass ) | ||
425 | { | ||
426 | } | ||
427 | |||
428 | //virtual | ||
429 | void LLDrawPool::endRenderPass( S32 pass ) | ||
430 | { | ||
431 | glDisableClientState ( GL_TEXTURE_COORD_ARRAY ); | ||
432 | glDisableClientState ( GL_COLOR_ARRAY ); | ||
433 | glDisableClientState ( GL_NORMAL_ARRAY ); | ||
434 | } | ||
435 | void LLDrawPool::renderFaceSelected(LLFace *facep, | ||
436 | LLImageGL *image, | ||
437 | const LLColor4 &color, | ||
438 | const S32 index_offset, const S32 index_count) | ||
439 | { | ||
440 | } | ||
441 | |||
442 | void 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 | |||
528 | void 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 | |||
553 | void LLDrawPool::bindGLVertexPointer() | ||
554 | { | ||
555 | mMemory.bindGLVertexPointer(getStride(DATA_VERTICES), mDataOffsets[DATA_VERTICES]); | ||
556 | } | ||
557 | |||
558 | void LLDrawPool::bindGLTexCoordPointer(const U32 pass) | ||
559 | { | ||
560 | mMemory.bindGLTexCoordPointer(getStride(DATA_TEX_COORDS0+pass), mDataOffsets[DATA_TEX_COORDS0+pass]); | ||
561 | } | ||
562 | |||
563 | void LLDrawPool::bindGLNormalPointer() | ||
564 | { | ||
565 | mMemory.bindGLNormalPointer(getStride(DATA_NORMALS), mDataOffsets[DATA_NORMALS]); | ||
566 | } | ||
567 | |||
568 | void LLDrawPool::bindGLBinormalPointer(S32 index) | ||
569 | { | ||
570 | mMemory.bindGLBinormalPointer(index, getStride(DATA_BINORMALS), mDataOffsets[DATA_BINORMALS]); | ||
571 | } | ||
572 | |||
573 | void LLDrawPool::bindGLColorPointer() | ||
574 | { | ||
575 | mMemory.bindGLColorPointer(getStride(DATA_COLORS), mDataOffsets[DATA_COLORS]); | ||
576 | } | ||
577 | |||
578 | void LLDrawPool::bindGLVertexWeightPointer(S32 index) | ||
579 | { | ||
580 | mWeights.bindGLVertexWeightPointer(index, 0, 0); | ||
581 | } | ||
582 | |||
583 | void LLDrawPool::bindGLVertexClothingWeightPointer(S32 index) | ||
584 | { | ||
585 | mClothingWeights.bindGLVertexClothingWeightPointer(index, 0, 0); | ||
586 | } | ||
587 | |||
588 | |||
589 | U32* LLDrawPool::getIndices(S32 index) | ||
590 | { | ||
591 | return &mIndices[index]; | ||
592 | } | ||
593 | |||
594 | const 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 | |||
602 | const 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 | |||
609 | const 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 | |||
616 | const 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 | |||
623 | const 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 | |||
630 | const 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 | |||
638 | const 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 | |||
651 | struct tFreeListNode | ||
652 | { | ||
653 | U32 count; | ||
654 | S32 next; | ||
655 | }; | ||
656 | |||
657 | #if DEBUG_FREELIST | ||
658 | static 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! | ||
677 | void 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 | |||
689 | int 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 | |||
714 | void 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 | |||
728 | void 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 | |||
791 | void 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 | |||
854 | S32 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 | |||
890 | S32 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 | |||
928 | S32 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 | |||
971 | S32 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 | |||
992 | S32 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 | |||
1029 | S32 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 | |||
1047 | const U32 LLDrawPool::getIndexCount() const | ||
1048 | { | ||
1049 | return mIndices.count(); | ||
1050 | } | ||
1051 | |||
1052 | const U32 LLDrawPool::getVertexCount() const | ||
1053 | { | ||
1054 | return mMemory.count() / mStride; | ||
1055 | } | ||
1056 | |||
1057 | const U32 LLDrawPool::getTexCoordCount(U32 pass) const | ||
1058 | { | ||
1059 | return mMemory.count() / mStride; | ||
1060 | } | ||
1061 | |||
1062 | |||
1063 | const U32 LLDrawPool::getNormalCount() const | ||
1064 | { | ||
1065 | return mMemory.count() / mStride; | ||
1066 | } | ||
1067 | |||
1068 | |||
1069 | const U32 LLDrawPool::getBinormalCount() const | ||
1070 | { | ||
1071 | return mMemory.count() / mStride; | ||
1072 | } | ||
1073 | |||
1074 | const U32 LLDrawPool::getColorCount() const | ||
1075 | { | ||
1076 | return mMemory.count() / mStride; | ||
1077 | } | ||
1078 | |||
1079 | const U32 LLDrawPool::getVertexWeightCount() const | ||
1080 | { | ||
1081 | return mWeights.count(); | ||
1082 | } | ||
1083 | |||
1084 | // virtual | ||
1085 | BOOL LLDrawPool::addFace(LLFace *facep) | ||
1086 | { | ||
1087 | addFaceReference(facep); | ||
1088 | return TRUE; | ||
1089 | } | ||
1090 | |||
1091 | // virtual | ||
1092 | BOOL 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 | ||
1104 | void LLDrawPool::resetDrawOrders() | ||
1105 | { | ||
1106 | mDrawFace.resize(0); | ||
1107 | } | ||
1108 | |||
1109 | void 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 | |||
1116 | void 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 | |||
1135 | void LLDrawPool::resetAll() | ||
1136 | { | ||
1137 | resetDrawOrders(); | ||
1138 | resetVertexData(0); | ||
1139 | mGeneration++; | ||
1140 | |||
1141 | } | ||
1142 | |||
1143 | S32 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 | |||
1245 | LLViewerImage *LLDrawPool::getTexture() | ||
1246 | { | ||
1247 | return NULL; | ||
1248 | } | ||
1249 | |||
1250 | LLViewerImage *LLDrawPool::getDebugTexture() | ||
1251 | { | ||
1252 | return NULL; | ||
1253 | } | ||
1254 | |||
1255 | void 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 | |||
1270 | void LLDrawPool::addFaceReference(LLFace *facep) | ||
1271 | { | ||
1272 | if (-1 == facep->getReferenceIndex()) | ||
1273 | { | ||
1274 | facep->setReferenceIndex(mReferences.size()); | ||
1275 | mReferences.push_back(facep); | ||
1276 | } | ||
1277 | } | ||
1278 | |||
1279 | U32 LLDrawPool::getTrianglesDrawn() const | ||
1280 | { | ||
1281 | return mIndicesDrawn / 3; | ||
1282 | } | ||
1283 | |||
1284 | void LLDrawPool::resetTrianglesDrawn() | ||
1285 | { | ||
1286 | mIndicesDrawn = 0; | ||
1287 | } | ||
1288 | |||
1289 | void LLDrawPool::addIndicesDrawn(const U32 indices) | ||
1290 | { | ||
1291 | mIndicesDrawn += indices; | ||
1292 | } | ||
1293 | |||
1294 | BOOL 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 | |||
1327 | void 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 | |||
1338 | S32 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 | |||
1357 | LLColor3 LLDrawPool::getDebugColor() const | ||
1358 | { | ||
1359 | return LLColor3(0.f, 0.f, 0.f); | ||
1360 | } | ||
1361 | |||
1362 | void LLDrawPool::setDirty() | ||
1363 | { | ||
1364 | mMemory.setDirty(); | ||
1365 | mWeights.setDirty(); | ||
1366 | mClothingWeights.setDirty(); | ||
1367 | } | ||
1368 | |||
1369 | BOOL LLDrawPool::LLOverrideFaceColor::sOverrideFaceColor = FALSE; | ||
1370 | |||
1371 | void 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 | |||
1383 | void 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 | |||
1395 | void 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 | ||
1408 | void LLDrawPool::enableShade() | ||
1409 | { } | ||
1410 | |||
1411 | // virtual | ||
1412 | void LLDrawPool::disableShade() | ||
1413 | { } | ||
1414 | |||
1415 | // virtual | ||
1416 | void LLDrawPool::setShade(F32 shade) | ||
1417 | { } | ||