diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/lldrawpool.cpp | 1261 |
1 files changed, 221 insertions, 1040 deletions
diff --git a/linden/indra/newview/lldrawpool.cpp b/linden/indra/newview/lldrawpool.cpp index 18d6000..dc2e6ba 100644 --- a/linden/indra/newview/lldrawpool.cpp +++ b/linden/indra/newview/lldrawpool.cpp | |||
@@ -32,7 +32,6 @@ | |||
32 | #include "llfasttimer.h" | 32 | #include "llfasttimer.h" |
33 | #include "llviewercontrol.h" | 33 | #include "llviewercontrol.h" |
34 | 34 | ||
35 | #include "llagparray.h" | ||
36 | #include "lldrawable.h" | 35 | #include "lldrawable.h" |
37 | #include "lldrawpoolalpha.h" | 36 | #include "lldrawpoolalpha.h" |
38 | #include "lldrawpoolavatar.h" | 37 | #include "lldrawpoolavatar.h" |
@@ -43,53 +42,38 @@ | |||
43 | #include "lldrawpoolsky.h" | 42 | #include "lldrawpoolsky.h" |
44 | #include "lldrawpoolstars.h" | 43 | #include "lldrawpoolstars.h" |
45 | #include "lldrawpooltree.h" | 44 | #include "lldrawpooltree.h" |
46 | #include "lldrawpooltreenew.h" | ||
47 | #include "lldrawpoolterrain.h" | 45 | #include "lldrawpoolterrain.h" |
48 | #include "lldrawpoolwater.h" | 46 | #include "lldrawpoolwater.h" |
49 | #include "lldrawpoolhud.h" | ||
50 | #include "llface.h" | 47 | #include "llface.h" |
51 | #include "llviewerobjectlist.h" // For debug listing. | 48 | #include "llviewerobjectlist.h" // For debug listing. |
52 | #include "llvotreenew.h" | ||
53 | #include "pipeline.h" | 49 | #include "pipeline.h" |
54 | 50 | ||
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; | 51 | S32 LLDrawPool::sNumDrawPools = 0; |
72 | 52 | ||
53 | |||
54 | //============================= | ||
55 | // Draw Pool Implementation | ||
56 | //============================= | ||
73 | LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0) | 57 | LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0) |
74 | { | 58 | { |
75 | LLDrawPool *poolp = NULL; | 59 | LLDrawPool *poolp = NULL; |
76 | switch (type) | 60 | switch (type) |
77 | { | 61 | { |
78 | case POOL_SIMPLE: | 62 | case POOL_SIMPLE: |
79 | poolp = new LLDrawPoolSimple(tex0); | 63 | poolp = new LLDrawPoolSimple(); |
80 | break; | 64 | break; |
81 | case POOL_ALPHA: | 65 | case POOL_ALPHA: |
82 | poolp = new LLDrawPoolAlpha(); | 66 | poolp = new LLDrawPoolAlpha(); |
83 | break; | 67 | break; |
68 | case POOL_ALPHA_POST_WATER: | ||
69 | poolp = new LLDrawPoolAlphaPostWater(); | ||
70 | break; | ||
84 | case POOL_AVATAR: | 71 | case POOL_AVATAR: |
85 | poolp = new LLDrawPoolAvatar(); | 72 | poolp = new LLDrawPoolAvatar(); |
86 | break; | 73 | break; |
87 | case POOL_TREE: | 74 | case POOL_TREE: |
88 | poolp = new LLDrawPoolTree(tex0); | 75 | poolp = new LLDrawPoolTree(tex0); |
89 | break; | 76 | break; |
90 | case POOL_TREE_NEW: | ||
91 | poolp = new LLDrawPoolTreeNew(tex0); | ||
92 | break; | ||
93 | case POOL_TERRAIN: | 77 | case POOL_TERRAIN: |
94 | poolp = new LLDrawPoolTerrain(tex0); | 78 | poolp = new LLDrawPoolTerrain(tex0); |
95 | break; | 79 | break; |
@@ -99,9 +83,6 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0) | |||
99 | case POOL_STARS: | 83 | case POOL_STARS: |
100 | poolp = new LLDrawPoolStars(); | 84 | poolp = new LLDrawPoolStars(); |
101 | break; | 85 | break; |
102 | case POOL_CLOUDS: | ||
103 | poolp = new LLDrawPoolClouds(); | ||
104 | break; | ||
105 | case POOL_WATER: | 86 | case POOL_WATER: |
106 | poolp = new LLDrawPoolWater(); | 87 | poolp = new LLDrawPoolWater(); |
107 | break; | 88 | break; |
@@ -109,10 +90,7 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0) | |||
109 | poolp = new LLDrawPoolGround(); | 90 | poolp = new LLDrawPoolGround(); |
110 | break; | 91 | break; |
111 | case POOL_BUMP: | 92 | case POOL_BUMP: |
112 | poolp = new LLDrawPoolBump(tex0); | 93 | poolp = new LLDrawPoolBump(); |
113 | break; | ||
114 | case POOL_HUD: | ||
115 | poolp = new LLDrawPoolHUD(); | ||
116 | break; | 94 | break; |
117 | default: | 95 | default: |
118 | llerrs << "Unknown draw pool type!" << llendl; | 96 | llerrs << "Unknown draw pool type!" << llendl; |
@@ -123,183 +101,86 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0) | |||
123 | return poolp; | 101 | return poolp; |
124 | } | 102 | } |
125 | 103 | ||
126 | LLDrawPool::LLDrawPool(const U32 type, const U32 data_mask_il, const U32 data_mask_nil) | 104 | LLDrawPool::LLDrawPool(const U32 type) |
127 | { | 105 | { |
128 | llassert(data_mask_il & DATA_VERTICES_MASK); | ||
129 | S32 i; | ||
130 | mType = type; | 106 | mType = type; |
131 | sNumDrawPools++; | 107 | sNumDrawPools++; |
132 | mId = sNumDrawPools; | 108 | mId = sNumDrawPools; |
133 | 109 | mVertexShaderLevel = 0; | |
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; | 110 | mIndicesDrawn = 0; |
153 | mRebuildFreq = 128 + rand() % 5; | 111 | } |
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 | 112 | ||
171 | // JC: This must happen last, as setUseAGP reads many of the | 113 | LLDrawPool::~LLDrawPool() |
172 | // above variables. | 114 | { |
173 | mUseAGP = FALSE; | ||
174 | setUseAGP(gPipeline.usingAGP()); | ||
175 | 115 | ||
176 | for (i=0; i<NUM_BUCKETS; i++) | ||
177 | { | ||
178 | mFreeListGeomHead[i] = -1; | ||
179 | mFreeListIndHead[i] = -1; | ||
180 | } | ||
181 | mVertexShaderLevel = 0; | ||
182 | } | 116 | } |
183 | 117 | ||
184 | void LLDrawPool::destroy() | 118 | LLViewerImage *LLDrawPool::getDebugTexture() |
185 | { | 119 | { |
186 | if (!mReferences.empty()) | 120 | return NULL; |
187 | { | ||
188 | llinfos << mReferences.size() << " references left on deletion of draw pool!" << llendl; | ||
189 | } | ||
190 | } | 121 | } |
191 | 122 | ||
192 | 123 | //virtual | |
193 | LLDrawPool::~LLDrawPool() | 124 | void LLDrawPool::beginRenderPass( S32 pass ) |
194 | { | 125 | { |
195 | destroy(); | ||
196 | |||
197 | llassert( gPipeline.findPool( getType(), getTexture() ) == NULL ); | ||
198 | } | 126 | } |
199 | 127 | ||
200 | BOOL LLDrawPool::setUseAGP(BOOL use_agp) | 128 | //virtual |
129 | void LLDrawPool::endRenderPass( S32 pass ) | ||
201 | { | 130 | { |
202 | BOOL ok = TRUE; | 131 | glDisableClientState ( GL_TEXTURE_COORD_ARRAY ); |
203 | S32 vertex_count = mMemory.count() / mStride; | 132 | glDisableClientState ( GL_COLOR_ARRAY ); |
204 | if (vertex_count > mMaxVertices && use_agp) | 133 | glDisableClientState ( GL_NORMAL_ARRAY ); |
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 | } | 134 | } |
242 | 135 | ||
243 | void LLDrawPool::flushAGP() | 136 | U32 LLDrawPool::getTrianglesDrawn() const |
244 | { | 137 | { |
245 | mMemory.flushAGP(); | 138 | return mIndicesDrawn / 3; |
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 | } | 139 | } |
256 | 140 | ||
257 | void LLDrawPool::syncAGP() | 141 | void LLDrawPool::resetTrianglesDrawn() |
258 | { | 142 | { |
259 | if (!getVertexCount()) | 143 | mIndicesDrawn = 0; |
260 | { | 144 | } |
261 | return; | ||
262 | } | ||
263 | setUseAGP(gPipeline.usingAGP()); | ||
264 | 145 | ||
265 | BOOL all_agp_on = TRUE; | 146 | void LLDrawPool::addIndicesDrawn(const U32 indices) |
266 | mMemory.sync(); | 147 | { |
267 | all_agp_on &= mMemory.isAGP(); | 148 | mIndicesDrawn += indices; |
149 | } | ||
268 | 150 | ||
269 | if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK) | 151 | //============================= |
270 | { | 152 | // Face Pool Implementation |
271 | mWeights.sync(); | 153 | //============================= |
272 | all_agp_on &= mWeights.isAGP(); | 154 | LLFacePool::LLFacePool(const U32 type) |
273 | } | 155 | : LLDrawPool(type) |
156 | { | ||
157 | resetDrawOrders(); | ||
158 | } | ||
274 | 159 | ||
275 | if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK) | 160 | LLFacePool::~LLFacePool() |
276 | { | 161 | { |
277 | mClothingWeights.sync(); | 162 | destroy(); |
278 | all_agp_on &= mClothingWeights.isAGP(); | 163 | } |
279 | } | ||
280 | 164 | ||
281 | // Since sometimes AGP allocation is done during syncs, we need | 165 | void LLFacePool::destroy() |
282 | // to make sure that if AGP allocation fails, we fallback to non-agp. | 166 | { |
283 | if (mUseAGP && !all_agp_on) | 167 | if (!mReferences.empty()) |
284 | { | 168 | { |
285 | #ifdef DEBUG_AGP | 169 | llinfos << mReferences.size() << " references left on deletion of draw pool!" << llendl; |
286 | llinfos << "setUseAGP false because of AGP sync failure!" << llendl; | ||
287 | #endif | ||
288 | setUseAGP(FALSE); | ||
289 | } | 170 | } |
290 | } | 171 | } |
291 | 172 | ||
292 | void LLDrawPool::dirtyTexture(const LLViewerImage *imagep) | 173 | void LLFacePool::dirtyTextures(const std::set<LLViewerImage*>& textures) |
293 | { | 174 | { |
294 | } | 175 | } |
295 | 176 | ||
296 | BOOL LLDrawPool::moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data) | 177 | BOOL LLFacePool::moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data) |
297 | { | 178 | { |
298 | return TRUE; | 179 | return TRUE; |
299 | } | 180 | } |
300 | 181 | ||
301 | // static | 182 | // static |
302 | S32 LLDrawPool::drawLoop(face_array_t& face_list, const U32* index_array) | 183 | S32 LLFacePool::drawLoop(face_array_t& face_list) |
303 | { | 184 | { |
304 | S32 res = 0; | 185 | S32 res = 0; |
305 | if (!face_list.empty()) | 186 | if (!face_list.empty()) |
@@ -308,19 +189,15 @@ S32 LLDrawPool::drawLoop(face_array_t& face_list, const U32* index_array) | |||
308 | iter != face_list.end(); iter++) | 189 | iter != face_list.end(); iter++) |
309 | { | 190 | { |
310 | LLFace *facep = *iter; | 191 | LLFace *facep = *iter; |
311 | if (facep->mSkipRender) | 192 | //facep->enableLights(); |
312 | { | 193 | res += facep->renderIndexed(); |
313 | continue; | ||
314 | } | ||
315 | facep->enableLights(); | ||
316 | res += facep->renderIndexed(index_array); | ||
317 | } | 194 | } |
318 | } | 195 | } |
319 | return res; | 196 | return res; |
320 | } | 197 | } |
321 | 198 | ||
322 | // static | 199 | // static |
323 | S32 LLDrawPool::drawLoopSetTex(face_array_t& face_list, const U32* index_array, S32 stage) | 200 | S32 LLFacePool::drawLoopSetTex(face_array_t& face_list, S32 stage) |
324 | { | 201 | { |
325 | S32 res = 0; | 202 | S32 res = 0; |
326 | if (!face_list.empty()) | 203 | if (!face_list.empty()) |
@@ -329,117 +206,30 @@ S32 LLDrawPool::drawLoopSetTex(face_array_t& face_list, const U32* index_array, | |||
329 | iter != face_list.end(); iter++) | 206 | iter != face_list.end(); iter++) |
330 | { | 207 | { |
331 | LLFace *facep = *iter; | 208 | LLFace *facep = *iter; |
332 | if (facep->mSkipRender) | ||
333 | { | ||
334 | continue; | ||
335 | } | ||
336 | facep->bindTexture(stage); | 209 | facep->bindTexture(stage); |
337 | facep->enableLights(); | 210 | facep->enableLights(); |
338 | res += facep->renderIndexed(index_array); | 211 | res += facep->renderIndexed(); |
339 | } | 212 | } |
340 | } | 213 | } |
341 | return res; | 214 | return res; |
342 | } | 215 | } |
343 | 216 | ||
344 | void LLDrawPool::drawLoop() | 217 | void LLFacePool::drawLoop() |
345 | { | 218 | { |
346 | const U32* index_array = getRawIndices(); | ||
347 | if (!mDrawFace.empty()) | 219 | if (!mDrawFace.empty()) |
348 | { | 220 | { |
349 | mIndicesDrawn += drawLoop(mDrawFace, index_array); | 221 | mIndicesDrawn += drawLoop(mDrawFace); |
350 | } | 222 | } |
351 | } | 223 | } |
352 | 224 | ||
353 | BOOL LLDrawPool::getVertexStrider(LLStrider<LLVector3> &vertices, const U32 index) | 225 | void LLFacePool::renderFaceSelected(LLFace *facep, |
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, | 226 | LLImageGL *image, |
437 | const LLColor4 &color, | 227 | const LLColor4 &color, |
438 | const S32 index_offset, const S32 index_count) | 228 | const S32 index_offset, const S32 index_count) |
439 | { | 229 | { |
440 | } | 230 | } |
441 | 231 | ||
442 | void LLDrawPool::renderVisibility() | 232 | void LLFacePool::renderVisibility() |
443 | { | 233 | { |
444 | if (mDrawFace.empty()) | 234 | if (mDrawFace.empty()) |
445 | { | 235 | { |
@@ -525,893 +315,284 @@ void LLDrawPool::renderVisibility() | |||
525 | 315 | ||
526 | } | 316 | } |
527 | 317 | ||
528 | void LLDrawPool::enqueue(LLFace* facep) | 318 | void LLFacePool::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 | { | 319 | { |
575 | mMemory.bindGLColorPointer(getStride(DATA_COLORS), mDataOffsets[DATA_COLORS]); | 320 | mDrawFace.push_back(facep); |
576 | } | 321 | } |
577 | 322 | ||
578 | void LLDrawPool::bindGLVertexWeightPointer(S32 index) | 323 | // virtual |
579 | { | 324 | BOOL LLFacePool::addFace(LLFace *facep) |
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 | { | 325 | { |
604 | llassert(mDataMaskIL & (LLDrawPool::DATA_TEX_COORDS0_MASK << pass)); | 326 | addFaceReference(facep); |
605 | llassert(index < mMemory.count()); | 327 | return TRUE; |
606 | return *(LLVector2*)(mMemory.getMem() + mDataOffsets[DATA_TEX_COORDS0 + pass] + index * mStride); | ||
607 | } | 328 | } |
608 | 329 | ||
609 | const LLVector3& LLDrawPool::getNormal(const S32 index) | 330 | // virtual |
331 | BOOL LLFacePool::removeFace(LLFace *facep) | ||
610 | { | 332 | { |
611 | llassert(mDataMaskIL & DATA_NORMALS_MASK); | 333 | removeFaceReference(facep); |
612 | llassert(index < mMemory.count()); | ||
613 | return *(LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_NORMALS] + index * mStride); | ||
614 | } | ||
615 | 334 | ||
616 | const LLVector3& LLDrawPool::getBinormal(const S32 index) | 335 | vector_replace_with_last(mDrawFace, facep); |
617 | { | ||
618 | llassert(mDataMaskIL & DATA_BINORMALS_MASK); | ||
619 | llassert(index < mMemory.count()); | ||
620 | return *(LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_BINORMALS] + index * mStride); | ||
621 | } | ||
622 | 336 | ||
623 | const LLColor4U& LLDrawPool::getColor(const S32 index) | 337 | return TRUE; |
624 | { | ||
625 | llassert(mDataMaskIL & DATA_COLORS_MASK); | ||
626 | llassert(index < mMemory.count()); | ||
627 | return *(LLColor4U*)(mMemory.getMem() + mDataOffsets[DATA_COLORS] + index * mStride); | ||
628 | } | 338 | } |
629 | 339 | ||
630 | const F32& LLDrawPool::getVertexWeight(const S32 index) | 340 | // Not absolutely sure if we should be resetting all of the chained pools as well - djs |
341 | void LLFacePool::resetDrawOrders() | ||
631 | { | 342 | { |
632 | llassert(mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK); | 343 | mDrawFace.resize(0); |
633 | llassert(index < mWeights.count()); | ||
634 | llassert(mWeights.getMem()); | ||
635 | return mWeights[index]; | ||
636 | } | 344 | } |
637 | 345 | ||
638 | const LLVector4& LLDrawPool::getClothingWeight(const S32 index) | 346 | LLViewerImage *LLFacePool::getTexture() |
639 | { | 347 | { |
640 | llassert(mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK); | 348 | return NULL; |
641 | llassert(index < mClothingWeights.count()); | ||
642 | llassert(mClothingWeights.getMem()); | ||
643 | return mClothingWeights[index]; | ||
644 | } | 349 | } |
645 | 350 | ||
646 | ////////////////////////////////////////////////////////////////////////////// | 351 | void LLFacePool::removeFaceReference(LLFace *facep) |
647 | |||
648 | #define USE_FREE_LIST 0 | ||
649 | #define DEBUG_FREELIST 0 | ||
650 | |||
651 | struct tFreeListNode | ||
652 | { | 352 | { |
653 | U32 count; | 353 | if (facep->getReferenceIndex() != -1) |
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 | { | 354 | { |
664 | tFreeListNode *node = (tFreeListNode *)(pool + head*stride); | 355 | if (facep->getReferenceIndex() != (S32)mReferences.size()) |
665 | count++; | 356 | { |
666 | if ((count > max) || ((node->count>>20) != 0xabc) || ((node->count&0xfffff) < 2)) | 357 | LLFace *back = mReferences.back(); |
667 | llerrs << "Bad Ind List" << llendl; | 358 | mReferences[facep->getReferenceIndex()] = back; |
668 | head = node->next; | 359 | back->setReferenceIndex(facep->getReferenceIndex()); |
360 | } | ||
361 | mReferences.pop_back(); | ||
669 | } | 362 | } |
363 | facep->setReferenceIndex(-1); | ||
670 | } | 364 | } |
671 | #define CHECK_LIST(x) check_list##x | ||
672 | #else | ||
673 | #define CHECK_LIST(x) | ||
674 | #endif | ||
675 | 365 | ||
676 | // DEBUG! | 366 | void LLFacePool::addFaceReference(LLFace *facep) |
677 | void LLDrawPool::CheckIntegrity() | ||
678 | { | 367 | { |
679 | #if DEBUG_FREELIST | 368 | if (-1 == facep->getReferenceIndex()) |
680 | int bucket; | ||
681 | for (bucket=0; bucket<NUM_BUCKETS; bucket++) | ||
682 | { | 369 | { |
683 | CHECK_LIST(((U8 *)mMemory.getMem(), mStride, mFreeListGeomHead[bucket], mMemory.count() / mStride)); | 370 | facep->setReferenceIndex(mReferences.size()); |
684 | CHECK_LIST(((U8 *)mIndices.getMem(), 4, mFreeListIndHead[bucket], mIndices.count())); | 371 | mReferences.push_back(facep); |
685 | } | 372 | } |
686 | #endif | ||
687 | } | 373 | } |
688 | 374 | ||
689 | int LLDrawPool::freeListBucket(U32 count) | 375 | BOOL LLFacePool::verify() const |
690 | { | 376 | { |
691 | int bucket; | 377 | BOOL ok = TRUE; |
692 | |||
693 | // llassert(NUM_BUCKETS == 8) | ||
694 | 378 | ||
695 | if (count & ~511) // >= 512 | 379 | for (std::vector<LLFace*>::const_iterator iter = mDrawFace.begin(); |
696 | bucket = 7; | 380 | iter != mDrawFace.end(); iter++) |
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 | { | 381 | { |
773 | CheckIntegrity(); | 382 | const LLFace* facep = *iter; |
774 | if ((index + count)*mStride >= mMemory.count()) | 383 | if (facep->getPool() != this) |
775 | { | 384 | { |
776 | mMemory.shrinkTo(index*mStride); | 385 | llinfos << "Face in wrong pool!" << llendl; |
386 | facep->printDebugInfo(); | ||
387 | ok = FALSE; | ||
777 | } | 388 | } |
778 | else | 389 | else if (!facep->verify()) |
779 | { | 390 | { |
780 | int bucket = freeListBucket(count); | 391 | ok = FALSE; |
781 | FreeListNode *node = (FreeListNode *)(membase + index*mStride); | ||
782 | node->count = count | (0xabc<<20); | ||
783 | node->next = mFreeListGeomHead[bucket]; | ||
784 | mFreeListGeomHead[bucket] = index; | ||
785 | } | 392 | } |
786 | CheckIntegrity(); | ||
787 | } | 393 | } |
788 | #endif | ||
789 | } | ||
790 | 394 | ||
791 | void LLDrawPool::freeListAddInd(S32 index, U32 count) | 395 | return ok; |
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 | } | 396 | } |
853 | 397 | ||
854 | S32 LLDrawPool::freeListFindGeom(U32 count) | 398 | void LLFacePool::printDebugInfo() const |
855 | { | 399 | { |
856 | #if USE_FREE_LIST | 400 | llinfos << "Pool " << this << " Type: " << getType() << llendl; |
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 | } | 401 | } |
889 | 402 | ||
890 | S32 LLDrawPool::freeListFindInd(U32 count) | 403 | BOOL LLFacePool::LLOverrideFaceColor::sOverrideFaceColor = FALSE; |
404 | |||
405 | void LLFacePool::LLOverrideFaceColor::setColor(const LLColor4& color) | ||
891 | { | 406 | { |
892 | #if USE_FREE_LIST | 407 | if (mPool->getVertexShaderLevel() > 0 && mPool->getMaterialAttribIndex() > 0) |
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 | { | 408 | { |
898 | pidx = -1; | 409 | glVertexAttrib4fvARB(mPool->getMaterialAttribIndex(), color.mV); |
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 | } | 410 | } |
922 | #endif // USE_FREE_LIST | 411 | else |
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 | { | 412 | { |
936 | index = mMemory.count() / mStride; | 413 | glColor4fv(color.mV); |
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 | } | 414 | } |
967 | CHECK_LIST(((U8 *)mMemory.getMem(), mStride, mFreeListGeomHead[0], mMemory.count() / mStride)); | ||
968 | return index; | ||
969 | } | 415 | } |
970 | 416 | ||
971 | S32 LLDrawPool::reserveInd(U32 indCount) | 417 | void LLFacePool::LLOverrideFaceColor::setColor(const LLColor4U& color) |
972 | { | 418 | { |
973 | S32 index; | 419 | if (mPool->getVertexShaderLevel() > 0 && mPool->getMaterialAttribIndex() > 0) |
974 | index = freeListFindInd(indCount); | ||
975 | if (index < 0) | ||
976 | { | 420 | { |
977 | index = mIndices.count(); | 421 | glVertexAttrib4ubvARB(mPool->getMaterialAttribIndex(), color.mV); |
978 | |||
979 | if (indCount) | ||
980 | { | ||
981 | mIndices.reserve_block(indCount); | ||
982 | } | ||
983 | } | 422 | } |
984 | for (U32 i=0;i<indCount;i++) | 423 | else |
985 | { | 424 | { |
986 | mIndices[index+i]=0; | 425 | glColor4ubv(color.mV); |
987 | } | 426 | } |
988 | CHECK_LIST(((U8 *)mIndices.getMem(), 4, mFreeListIndHead[0], mIndices.count())); | ||
989 | return index; | ||
990 | } | 427 | } |
991 | 428 | ||
992 | S32 LLDrawPool::unReserveGeom(const S32 index, const U32 count) | 429 | void LLFacePool::LLOverrideFaceColor::setColor(F32 r, F32 g, F32 b, F32 a) |
993 | { | 430 | { |
994 | if (index < 0 || count == 0) | 431 | if (mPool->getVertexShaderLevel() > 0 && mPool->getMaterialAttribIndex() > 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 | { | 432 | { |
1015 | memp = (U32*)(&mWeights[index]); | 433 | glVertexAttrib4fARB(mPool->getMaterialAttribIndex(), r,g,b,a); |
1016 | for (i=0; i<words; i++) | ||
1017 | *memp++ = 0xffffffff; | ||
1018 | } | 434 | } |
1019 | if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK) | 435 | else |
1020 | { | 436 | { |
1021 | memp = (U32*)(&mClothingWeights[index]); | 437 | glColor4f(r,g,b,a); |
1022 | for (i=0; i<count; i++) | ||
1023 | *memp++ = 0xffffffff; | ||
1024 | } | 438 | } |
1025 | #endif | ||
1026 | return -1; | ||
1027 | } | 439 | } |
1028 | 440 | ||
1029 | S32 LLDrawPool::unReserveInd(const S32 index, const U32 count) | ||
1030 | { | ||
1031 | if (index < 0 || count == 0) | ||
1032 | return -1; | ||
1033 | 441 | ||
1034 | freeListAddInd(index, count); | 442 | //============================= |
1035 | 443 | // Render Pass Implementation | |
1036 | #if 0 | 444 | //============================= |
1037 | int i; | 445 | LLRenderPass::LLRenderPass(const U32 type) |
1038 | U32 *memp = &mIndices[index]; | 446 | : LLDrawPool(type) |
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 | { | 447 | { |
1049 | return mIndices.count(); | ||
1050 | } | ||
1051 | 448 | ||
1052 | const U32 LLDrawPool::getVertexCount() const | ||
1053 | { | ||
1054 | return mMemory.count() / mStride; | ||
1055 | } | 449 | } |
1056 | 450 | ||
1057 | const U32 LLDrawPool::getTexCoordCount(U32 pass) const | 451 | LLRenderPass::~LLRenderPass() |
1058 | { | 452 | { |
1059 | return mMemory.count() / mStride; | ||
1060 | } | ||
1061 | 453 | ||
1062 | |||
1063 | const U32 LLDrawPool::getNormalCount() const | ||
1064 | { | ||
1065 | return mMemory.count() / mStride; | ||
1066 | } | 454 | } |
1067 | 455 | ||
1068 | 456 | LLDrawPool* LLRenderPass::instancePool() | |
1069 | const U32 LLDrawPool::getBinormalCount() const | ||
1070 | { | 457 | { |
1071 | return mMemory.count() / mStride; | 458 | #if LL_RELEASE_FOR_DOWNLOAD |
1072 | } | 459 | llwarns << "Attempting to instance a render pass. Invalid operation." << llendl; |
1073 | 460 | #else | |
1074 | const U32 LLDrawPool::getColorCount() const | 461 | llerrs << "Attempting to instance a render pass. Invalid operation." << llendl; |
1075 | { | 462 | #endif |
1076 | return mMemory.count() / mStride; | 463 | return NULL; |
1077 | } | ||
1078 | |||
1079 | const U32 LLDrawPool::getVertexWeightCount() const | ||
1080 | { | ||
1081 | return mWeights.count(); | ||
1082 | } | 464 | } |
1083 | 465 | ||
1084 | // virtual | 466 | void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture) |
1085 | BOOL LLDrawPool::addFace(LLFace *facep) | 467 | { |
1086 | { | 468 | std::vector<LLDrawInfo*>& draw_info = group->mDrawMap[type]; |
1087 | addFaceReference(facep); | 469 | |
1088 | return TRUE; | 470 | for (std::vector<LLDrawInfo*>::const_iterator k = draw_info.begin(); k != draw_info.end(); ++k) |
471 | { | ||
472 | LLDrawInfo& params = **k; | ||
473 | pushBatch(params, mask, texture); | ||
474 | } | ||
1089 | } | 475 | } |
1090 | 476 | ||
1091 | // virtual | 477 | void LLRenderPass::renderInvisible(U32 mask) |
1092 | BOOL LLDrawPool::removeFace(LLFace *facep) | ||
1093 | { | 478 | { |
1094 | removeFaceReference(facep); | 479 | #if !LL_RELEASE_FOR_DOWNLOAD |
1095 | 480 | LLGLState::checkClientArrays(mask); | |
1096 | vector_replace_with_last(mDrawFace, facep); | 481 | #endif |
1097 | |||
1098 | facep->unReserve(); | ||
1099 | 482 | ||
1100 | return TRUE; | 483 | std::vector<LLDrawInfo*>& draw_info = gPipeline.mRenderMap[LLRenderPass::PASS_INVISIBLE]; |
1101 | } | ||
1102 | 484 | ||
1103 | // Not absolutely sure if we should be resetting all of the chained pools as well - djs | 485 | U32* indices_pointer = NULL; |
1104 | void LLDrawPool::resetDrawOrders() | 486 | for (std::vector<LLDrawInfo*>::iterator i = draw_info.begin(); i != draw_info.end(); ++i) |
1105 | { | 487 | { |
1106 | mDrawFace.resize(0); | 488 | LLDrawInfo& params = **i; |
489 | params.mVertexBuffer->setBuffer(mask); | ||
490 | indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer(); | ||
491 | glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount, | ||
492 | GL_UNSIGNED_INT, indices_pointer+params.mOffset); | ||
493 | gPipeline.mTrianglesDrawn += params.mCount/3; | ||
494 | } | ||
1107 | } | 495 | } |
1108 | 496 | ||
1109 | void LLDrawPool::resetIndices(S32 indices_count) | 497 | void LLRenderPass::renderTexture(U32 type, U32 mask) |
1110 | { | 498 | { |
1111 | mIndices.reset(indices_count); | 499 | #if !LL_RELEASE_FOR_DOWNLOAD |
1112 | for (S32 i=0; i<NUM_BUCKETS; i++) | 500 | LLGLState::checkClientArrays(mask); |
1113 | mFreeListIndHead[i] = -1; | 501 | #endif |
1114 | } | ||
1115 | 502 | ||
1116 | void LLDrawPool::resetVertexData(S32 reserve_count) | 503 | std::vector<LLDrawInfo*>& draw_info = gPipeline.mRenderMap[type]; |
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 | 504 | ||
1129 | if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK) | 505 | for (std::vector<LLDrawInfo*>::iterator i = draw_info.begin(); i != draw_info.end(); ++i) |
1130 | { | 506 | { |
1131 | mClothingWeights.reset(reserve_count); | 507 | LLDrawInfo& params = **i; |
508 | pushBatch(params, mask, TRUE); | ||
1132 | } | 509 | } |
1133 | } | 510 | } |
1134 | 511 | ||
1135 | void LLDrawPool::resetAll() | 512 | void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) |
1136 | { | ||
1137 | resetDrawOrders(); | ||
1138 | resetVertexData(0); | ||
1139 | mGeneration++; | ||
1140 | |||
1141 | } | ||
1142 | |||
1143 | S32 LLDrawPool::rebuild() | ||
1144 | { | 513 | { |
1145 | mRebuildTime++; | 514 | if (params.mVertexBuffer.isNull()) |
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 | { | 515 | { |
1167 | needs_rebuild = TRUE; | 516 | return; |
1168 | } | 517 | } |
1169 | 518 | ||
1170 | if (needs_rebuild) | 519 | if (texture) |
1171 | { | 520 | { |
1172 | mGeneration++; | 521 | if (params.mTexture.notNull()) |
1173 | |||
1174 | if (mReferences.empty()) | ||
1175 | { | 522 | { |
1176 | resetIndices(0); | 523 | params.mTexture->bind(); |
1177 | resetVertexData(0); | 524 | if (params.mTextureMatrix) |
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 | { | 525 | { |
1205 | LLFace *facep = *iter; | 526 | glMatrixMode(GL_TEXTURE); |
1206 | if (facep->isState(LLFace::BACKLIST)) | 527 | glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); |
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 | } | 528 | } |
529 | params.mTexture->addTextureStats(params.mVSize); | ||
1224 | } | 530 | } |
1225 | mRebuildTime = 0; | 531 | else |
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 | { | 532 | { |
1261 | LLFace *back = mReferences.back(); | 533 | LLImageGL::unbindTexture(0); |
1262 | mReferences[facep->getReferenceIndex()] = back; | ||
1263 | back->setReferenceIndex(facep->getReferenceIndex()); | ||
1264 | } | 534 | } |
1265 | mReferences.pop_back(); | ||
1266 | } | 535 | } |
1267 | facep->setReferenceIndex(-1); | 536 | |
1268 | } | 537 | params.mVertexBuffer->setBuffer(mask); |
538 | U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer(); | ||
539 | glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount, | ||
540 | GL_UNSIGNED_INT, indices_pointer+params.mOffset); | ||
541 | gPipeline.mTrianglesDrawn += params.mCount/3; | ||
1269 | 542 | ||
1270 | void LLDrawPool::addFaceReference(LLFace *facep) | 543 | if (params.mTextureMatrix && texture && params.mTexture.notNull()) |
1271 | { | ||
1272 | if (-1 == facep->getReferenceIndex()) | ||
1273 | { | 544 | { |
1274 | facep->setReferenceIndex(mReferences.size()); | 545 | glLoadIdentity(); |
1275 | mReferences.push_back(facep); | 546 | glMatrixMode(GL_MODELVIEW); |
1276 | } | 547 | } |
1277 | } | 548 | } |
1278 | 549 | ||
1279 | U32 LLDrawPool::getTrianglesDrawn() const | 550 | void LLRenderPass::renderActive(U32 type, U32 mask, BOOL texture) |
1280 | { | 551 | { |
1281 | return mIndicesDrawn / 3; | 552 | #if !LL_RELEASE_FOR_DOWNLOAD |
1282 | } | 553 | LLGLState::checkClientArrays(mask); |
1283 | 554 | #endif | |
1284 | void LLDrawPool::resetTrianglesDrawn() | ||
1285 | { | ||
1286 | mIndicesDrawn = 0; | ||
1287 | } | ||
1288 | |||
1289 | void LLDrawPool::addIndicesDrawn(const U32 indices) | ||
1290 | { | ||
1291 | mIndicesDrawn += indices; | ||
1292 | } | ||
1293 | 555 | ||
1294 | BOOL LLDrawPool::verify() const | 556 | LLSpatialBridge* last_bridge = NULL; |
1295 | { | 557 | glPushMatrix(); |
1296 | BOOL ok = TRUE; | 558 | |
1297 | // Verify all indices in the pool are in the right range | 559 | for (LLSpatialGroup::sg_vector_t::iterator i = gPipeline.mActiveGroups.begin(); i != gPipeline.mActiveGroups.end(); ++i) |
1298 | const U32 *indicesp = getRawIndices(); | ||
1299 | for (U32 i = 0; i < getIndexCount(); i++) | ||
1300 | { | 560 | { |
1301 | if (indicesp[i] > getVertexCount()) | 561 | LLSpatialGroup* group = *i; |
562 | if (!group->isDead() && | ||
563 | gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) && | ||
564 | group->mDrawMap.find(type) != group->mDrawMap.end()) | ||
1302 | { | 565 | { |
1303 | ok = FALSE; | 566 | LLSpatialBridge* bridge = (LLSpatialBridge*) group->mSpatialPartition; |
1304 | llinfos << "Bad index in tree pool!" << llendl; | 567 | if (bridge != last_bridge) |
1305 | } | 568 | { |
1306 | } | 569 | glPopMatrix(); |
570 | glPushMatrix(); | ||
571 | glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix); | ||
572 | last_bridge = bridge; | ||
573 | } | ||
1307 | 574 | ||
1308 | for (std::vector<LLFace*>::const_iterator iter = mDrawFace.begin(); | 575 | renderGroup(group,type,mask,texture); |
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 | } | 576 | } |
1322 | } | 577 | } |
1323 | 578 | ||
1324 | return ok; | 579 | glPopMatrix(); |
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 | } | 580 | } |
1382 | 581 | ||
1383 | void LLDrawPool::LLOverrideFaceColor::setColor(const LLColor4U& color) | 582 | void LLRenderPass::renderStatic(U32 type, U32 mask, BOOL texture) |
1384 | { | 583 | { |
1385 | if (mPool->mVertexShaderLevel > 0 && mPool->getMaterialAttribIndex() > 0) | 584 | #if !LL_RELEASE_FOR_DOWNLOAD |
1386 | { | 585 | LLGLState::checkClientArrays(mask); |
1387 | glVertexAttrib4ubvARB(mPool->getMaterialAttribIndex(), color.mV); | 586 | #endif |
1388 | } | ||
1389 | else | ||
1390 | { | ||
1391 | glColor4ubv(color.mV); | ||
1392 | } | ||
1393 | } | ||
1394 | 587 | ||
1395 | void LLDrawPool::LLOverrideFaceColor::setColor(F32 r, F32 g, F32 b, F32 a) | 588 | for (LLSpatialGroup::sg_vector_t::iterator i = gPipeline.mVisibleGroups.begin(); i != gPipeline.mVisibleGroups.end(); ++i) |
1396 | { | ||
1397 | if (mPool->mVertexShaderLevel > 0 && mPool->getMaterialAttribIndex() > 0) | ||
1398 | { | ||
1399 | glVertexAttrib4fARB(mPool->getMaterialAttribIndex(), r,g,b,a); | ||
1400 | } | ||
1401 | else | ||
1402 | { | 589 | { |
1403 | glColor4f(r,g,b,a); | 590 | LLSpatialGroup* group = *i; |
591 | if (!group->isDead() && | ||
592 | gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) && | ||
593 | group->mDrawMap.find(type) != group->mDrawMap.end()) | ||
594 | { | ||
595 | renderGroup(group,type,mask,texture); | ||
596 | } | ||
1404 | } | 597 | } |
1405 | } | 598 | } |
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 | { } | ||