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/pipeline.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 '')
-rw-r--r-- | linden/indra/newview/pipeline.cpp | 5337 |
1 files changed, 5337 insertions, 0 deletions
diff --git a/linden/indra/newview/pipeline.cpp b/linden/indra/newview/pipeline.cpp new file mode 100644 index 0000000..a7b4d47 --- /dev/null +++ b/linden/indra/newview/pipeline.cpp | |||
@@ -0,0 +1,5337 @@ | |||
1 | /** | ||
2 | * @file pipeline.cpp | ||
3 | * @brief Rendering pipeline. | ||
4 | * | ||
5 | * Copyright (c) 2005-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 "pipeline.h" | ||
31 | |||
32 | // library includes | ||
33 | #include "audioengine.h" // For MAX_BUFFERS for debugging. | ||
34 | #include "imageids.h" | ||
35 | #include "llagpmempool.h" | ||
36 | #include "llerror.h" | ||
37 | #include "llviewercontrol.h" | ||
38 | #include "llfasttimer.h" | ||
39 | #include "llfontgl.h" | ||
40 | #include "llmemory.h" | ||
41 | #include "llnamevalue.h" | ||
42 | #include "llprimitive.h" | ||
43 | #include "llvolume.h" | ||
44 | #include "material_codes.h" | ||
45 | #include "timing.h" | ||
46 | #include "v3color.h" | ||
47 | #include "llui.h" | ||
48 | |||
49 | // newview includes | ||
50 | #include "llagent.h" | ||
51 | #include "llagparray.h" | ||
52 | #include "lldrawable.h" | ||
53 | #include "lldrawpoolalpha.h" | ||
54 | #include "lldrawpoolavatar.h" | ||
55 | #include "lldrawpoolground.h" | ||
56 | #include "lldrawpoolsimple.h" | ||
57 | #include "lldrawpooltree.h" | ||
58 | #include "lldrawpoolhud.h" | ||
59 | #include "lldrawpoolwater.h" | ||
60 | #include "llface.h" | ||
61 | #include "llfeaturemanager.h" | ||
62 | #include "llfloatertelehub.h" | ||
63 | #include "llframestats.h" | ||
64 | #include "llgldbg.h" | ||
65 | #include "llhudmanager.h" | ||
66 | #include "lllightconstants.h" | ||
67 | #include "llresmgr.h" | ||
68 | #include "llselectmgr.h" | ||
69 | #include "llsky.h" | ||
70 | #include "lltracker.h" | ||
71 | #include "lltool.h" | ||
72 | #include "lltoolmgr.h" | ||
73 | #include "llviewercamera.h" | ||
74 | #include "llviewerimagelist.h" | ||
75 | #include "llviewerobject.h" | ||
76 | #include "llviewerobjectlist.h" | ||
77 | #include "llviewerparcelmgr.h" | ||
78 | #include "llviewerregion.h" // for audio debugging. | ||
79 | #include "llviewerwindow.h" // For getSpinAxis | ||
80 | #include "llvoavatar.h" | ||
81 | #include "llvoground.h" | ||
82 | #include "llvosky.h" | ||
83 | #include "llvotree.h" | ||
84 | #include "llvovolume.h" | ||
85 | #include "llworld.h" | ||
86 | #include "viewer.h" | ||
87 | #include "llagpmempoolarb.h" | ||
88 | #include "llagparray.inl" | ||
89 | |||
90 | #ifdef _DEBUG | ||
91 | // Debug indices is disabled for now for debug performance - djs 4/24/02 | ||
92 | //#define DEBUG_INDICES | ||
93 | #else | ||
94 | //#define DEBUG_INDICES | ||
95 | #endif | ||
96 | |||
97 | const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f; | ||
98 | const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f; | ||
99 | const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f; | ||
100 | const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f; | ||
101 | const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40; | ||
102 | const S32 MAX_OFFSCREEN_GEOMETRY_CHANGES_PER_FRAME = 10; | ||
103 | |||
104 | // Guess on the number of visible objects in the scene, used to | ||
105 | // pre-size std::vector and other arrays. JC | ||
106 | const S32 ESTIMATED_VISIBLE_OBJECT_COUNT = 8192; | ||
107 | |||
108 | // If the sum of the X + Y + Z scale of an object exceeds this number, | ||
109 | // it will be considered a potential occluder. For instance, | ||
110 | // a box of size 6 x 6 x 1 has sum 13, which might be an occluder. JC | ||
111 | const F32 OCCLUDE_SCALE_SUM_THRESHOLD = 8.f; | ||
112 | |||
113 | // Max number of occluders to search for. JC | ||
114 | const S32 MAX_OCCLUDER_COUNT = 2; | ||
115 | |||
116 | extern S32 gBoxFrame; | ||
117 | extern BOOL gRenderLightGlows; | ||
118 | extern BOOL gHideSelectedObjects; | ||
119 | |||
120 | |||
121 | BOOL gAvatarBacklight = FALSE; | ||
122 | |||
123 | F32 gMinObjectDistance = MIN_NEAR_PLANE; | ||
124 | S32 gTrivialAccepts = 0; | ||
125 | |||
126 | BOOL gRenderForSelect = FALSE; | ||
127 | |||
128 | BOOL gUsePickAlpha = TRUE; | ||
129 | F32 gPickAlphaThreshold = 0.f; | ||
130 | F32 gPickAlphaTargetThreshold = 0.f; | ||
131 | |||
132 | //glsl parameter tables | ||
133 | const char* LLPipeline::sReservedAttribs[] = | ||
134 | { | ||
135 | "materialColor", | ||
136 | "specularColor", | ||
137 | "binormal" | ||
138 | }; | ||
139 | |||
140 | U32 LLPipeline::sReservedAttribCount = LLPipeline::GLSL_END_RESERVED_ATTRIBS; | ||
141 | |||
142 | const char* LLPipeline::sAvatarAttribs[] = | ||
143 | { | ||
144 | "weight", | ||
145 | "clothing", | ||
146 | "gWindDir", | ||
147 | "gSinWaveParams", | ||
148 | "gGravity" | ||
149 | }; | ||
150 | |||
151 | U32 LLPipeline::sAvatarAttribCount = sizeof(LLPipeline::sAvatarAttribs)/sizeof(char*); | ||
152 | |||
153 | const char* LLPipeline::sAvatarUniforms[] = | ||
154 | { | ||
155 | "matrixPalette" | ||
156 | }; | ||
157 | |||
158 | U32 LLPipeline::sAvatarUniformCount = 1; | ||
159 | |||
160 | const char* LLPipeline::sReservedUniforms[] = | ||
161 | { | ||
162 | "diffuseMap", | ||
163 | "specularMap", | ||
164 | "bumpMap", | ||
165 | "environmentMap", | ||
166 | "scatterMap" | ||
167 | }; | ||
168 | |||
169 | U32 LLPipeline::sReservedUniformCount = LLPipeline::GLSL_END_RESERVED_UNIFORMS; | ||
170 | |||
171 | const char* LLPipeline::sTerrainUniforms[] = | ||
172 | { | ||
173 | "detail0", | ||
174 | "detail1", | ||
175 | "alphaRamp" | ||
176 | }; | ||
177 | |||
178 | U32 LLPipeline::sTerrainUniformCount = sizeof(LLPipeline::sTerrainUniforms)/sizeof(char*); | ||
179 | |||
180 | const char* LLPipeline::sWaterUniforms[] = | ||
181 | { | ||
182 | "screenTex", | ||
183 | "eyeVec", | ||
184 | "time", | ||
185 | "d1", | ||
186 | "d2", | ||
187 | "lightDir", | ||
188 | "specular", | ||
189 | "lightExp", | ||
190 | "fbScale", | ||
191 | "refScale" | ||
192 | }; | ||
193 | |||
194 | U32 LLPipeline::sWaterUniformCount = sizeof(LLPipeline::sWaterUniforms)/sizeof(char*); | ||
195 | |||
196 | // the SSE variable is dependent on software blending being enabled. | ||
197 | |||
198 | //---------------------------------------- | ||
199 | |||
200 | void stamp(F32 x, F32 y, F32 xs, F32 ys) | ||
201 | { | ||
202 | glBegin(GL_QUADS); | ||
203 | glTexCoord2f(0,0); | ||
204 | glVertex3f(x, y, 0.0f); | ||
205 | glTexCoord2f(1,0); | ||
206 | glVertex3f(x+xs,y, 0.0f); | ||
207 | glTexCoord2f(1,1); | ||
208 | glVertex3f(x+xs,y+ys,0.0f); | ||
209 | glTexCoord2f(0,1); | ||
210 | glVertex3f(x, y+ys,0.0f); | ||
211 | glEnd(); | ||
212 | } | ||
213 | |||
214 | |||
215 | |||
216 | //---------------------------------------- | ||
217 | |||
218 | S32 LLPipeline::sCompiles = 0; | ||
219 | S32 LLPipeline::sAGPMaxPoolSize = 1 << 25; // 32MB | ||
220 | BOOL LLPipeline::sRenderPhysicalBeacons = FALSE; | ||
221 | BOOL LLPipeline::sRenderScriptedBeacons = FALSE; | ||
222 | BOOL LLPipeline::sRenderParticleBeacons = FALSE; | ||
223 | BOOL LLPipeline::sRenderSoundBeacons = FALSE; | ||
224 | |||
225 | LLPipeline::LLPipeline() : | ||
226 | mVertexShadersEnabled(FALSE), | ||
227 | mVertexShadersLoaded(0), | ||
228 | mLastRebuildPool(NULL), | ||
229 | mAlphaPool(NULL), | ||
230 | mSkyPool(NULL), | ||
231 | mStarsPool(NULL), | ||
232 | mCloudsPool(NULL), | ||
233 | mTerrainPool(NULL), | ||
234 | mWaterPool(NULL), | ||
235 | mGroundPool(NULL), | ||
236 | mHUDPool(NULL), | ||
237 | mAGPMemPool(NULL), | ||
238 | mGlobalFence(0), | ||
239 | mBufferIndex(0), | ||
240 | mBufferCount(kMaxBufferCount), | ||
241 | mUseOcclusionCulling(FALSE), | ||
242 | mLightMask(0), | ||
243 | mLightMovingMask(0) | ||
244 | { | ||
245 | for(S32 i = 0; i < kMaxBufferCount; i++) | ||
246 | { | ||
247 | mBufferMemory[i] = NULL; | ||
248 | } | ||
249 | for (S32 i = 0; i < kMaxBufferCount; i++) | ||
250 | { | ||
251 | mBufferFence[i] = 0; | ||
252 | } | ||
253 | } | ||
254 | |||
255 | void LLPipeline::init() | ||
256 | { | ||
257 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
258 | |||
259 | stop_glerror(); | ||
260 | |||
261 | mAGPBound = FALSE; | ||
262 | mObjectPartition = new LLSpatialPartition; | ||
263 | mTrianglesDrawnStat.reset(); | ||
264 | resetFrameStats(); | ||
265 | |||
266 | mRenderTypeMask = 0xffffffff; // All render types start on | ||
267 | mRenderDebugFeatureMask = 0xffffffff; // All debugging features on | ||
268 | mRenderFeatureMask = 0; // All features start off | ||
269 | mRenderDebugMask = 0; // All debug starts off | ||
270 | |||
271 | mBackfaceCull = TRUE; | ||
272 | |||
273 | // Disable AGP initially. | ||
274 | mRenderFeatureMask &= ~RENDER_FEATURE_AGP; | ||
275 | |||
276 | stop_glerror(); | ||
277 | |||
278 | // Enable features | ||
279 | |||
280 | mUseVBO = gSavedSettings.getBOOL("RenderUseVBO"); | ||
281 | |||
282 | // Allocate the shared buffers for software skinning | ||
283 | for(S32 i=0; i < mBufferCount; i++) | ||
284 | { | ||
285 | mBufferMemory[i] = new LLAGPArray<U8>; | ||
286 | mBufferMemory[i]->reserve_block(AVATAR_VERTEX_BYTES*AVATAR_BUFFER_ELEMENTS); | ||
287 | } | ||
288 | |||
289 | if (gFeatureManagerp->isFeatureAvailable("RenderAGP")) | ||
290 | { | ||
291 | setUseAGP(gSavedSettings.getBOOL("RenderUseAGP") && gGLManager.mHasAnyAGP); | ||
292 | } | ||
293 | else | ||
294 | { | ||
295 | setUseAGP(FALSE); | ||
296 | } | ||
297 | |||
298 | stop_glerror(); | ||
299 | |||
300 | for(S32 i=0; i < mBufferCount; i++) | ||
301 | { | ||
302 | if (!mBufferMemory[i]->isAGP() && usingAGP()) | ||
303 | { | ||
304 | llwarns << "pipeline buffer memory is non-AGP when AGP available!" << llendl; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | setShaders(); | ||
309 | } | ||
310 | |||
311 | void LLPipeline::LLScatterShader::init(GLhandleARB shader, int map_stage) | ||
312 | { | ||
313 | glUseProgramObjectARB(shader); | ||
314 | glUniform1iARB(glGetUniformLocationARB(shader, "scatterMap"), map_stage); | ||
315 | glUseProgramObjectARB(0); | ||
316 | } | ||
317 | |||
318 | LLPipeline::~LLPipeline() | ||
319 | { | ||
320 | |||
321 | } | ||
322 | |||
323 | void LLPipeline::cleanup() | ||
324 | { | ||
325 | for(pool_set_t::iterator iter = mPools.begin(); | ||
326 | iter != mPools.end(); ) | ||
327 | { | ||
328 | pool_set_t::iterator curiter = iter++; | ||
329 | LLDrawPool* poolp = *curiter; | ||
330 | if (poolp->mReferences.empty()) | ||
331 | { | ||
332 | mPools.erase(curiter); | ||
333 | removeFromQuickLookup( poolp ); | ||
334 | delete poolp; | ||
335 | } | ||
336 | } | ||
337 | |||
338 | if (!mSimplePools.empty()) | ||
339 | { | ||
340 | llwarns << "Simple Pools not cleaned up" << llendl; | ||
341 | } | ||
342 | if (!mTerrainPools.empty()) | ||
343 | { | ||
344 | llwarns << "Terrain Pools not cleaned up" << llendl; | ||
345 | } | ||
346 | if (!mTreePools.empty()) | ||
347 | { | ||
348 | llwarns << "Tree Pools not cleaned up" << llendl; | ||
349 | } | ||
350 | if (!mTreeNewPools.empty()) | ||
351 | { | ||
352 | llwarns << "TreeNew Pools not cleaned up" << llendl; | ||
353 | } | ||
354 | if (!mBumpPools.empty()) | ||
355 | { | ||
356 | llwarns << "Bump Pools not cleaned up" << llendl; | ||
357 | } | ||
358 | delete mAlphaPool; | ||
359 | mAlphaPool = NULL; | ||
360 | delete mSkyPool; | ||
361 | mSkyPool = NULL; | ||
362 | delete mStarsPool; | ||
363 | mStarsPool = NULL; | ||
364 | delete mCloudsPool; | ||
365 | mCloudsPool = NULL; | ||
366 | delete mTerrainPool; | ||
367 | mTerrainPool = NULL; | ||
368 | delete mWaterPool; | ||
369 | mWaterPool = NULL; | ||
370 | delete mGroundPool; | ||
371 | mGroundPool = NULL; | ||
372 | delete mHUDPool; | ||
373 | mHUDPool = NULL; | ||
374 | |||
375 | mBloomImagep = NULL; | ||
376 | mBloomImage2p = NULL; | ||
377 | mFaceSelectImagep = NULL; | ||
378 | mAlphaSizzleImagep = NULL; | ||
379 | |||
380 | for(S32 i=0; i < mBufferCount; i++) | ||
381 | { | ||
382 | delete mBufferMemory[i]; | ||
383 | mBufferMemory[i] = NULL; | ||
384 | } | ||
385 | |||
386 | delete mObjectPartition; | ||
387 | mObjectPartition = NULL; | ||
388 | |||
389 | if (mAGPMemPool && mGlobalFence) | ||
390 | { | ||
391 | mAGPMemPool->deleteFence(mGlobalFence); | ||
392 | mGlobalFence = 0; | ||
393 | } | ||
394 | delete mAGPMemPool; | ||
395 | mAGPMemPool = NULL; | ||
396 | } | ||
397 | |||
398 | //============================================================================ | ||
399 | |||
400 | BOOL LLPipeline::initAGP() | ||
401 | { | ||
402 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
403 | |||
404 | mAGPMemPool = LLAGPMemPool::createPool(sAGPMaxPoolSize, mUseVBO); | ||
405 | |||
406 | if (!mAGPMemPool) | ||
407 | { | ||
408 | llinfos << "Warning! Couldn't allocate AGP memory!" << llendl; | ||
409 | llinfos << "Disabling AGP!" << llendl; | ||
410 | mAGPMemPool = NULL; | ||
411 | mRenderFeatureMask &= ~RENDER_FEATURE_AGP; // Need to disable the using AGP flag | ||
412 | return FALSE; | ||
413 | } | ||
414 | else if (!mAGPMemPool->getSize()) | ||
415 | { | ||
416 | llinfos << "Warning! Unable to allocate AGP memory! Disabling AGP" << llendl; | ||
417 | delete mAGPMemPool; | ||
418 | mAGPMemPool = NULL; | ||
419 | mRenderFeatureMask &= ~RENDER_FEATURE_AGP; // Need to disable the using AGP flag | ||
420 | return FALSE; | ||
421 | } | ||
422 | else | ||
423 | { | ||
424 | llinfos << "Allocated " << mAGPMemPool->getSize() << " bytes of AGP memory" << llendl; | ||
425 | mAGPMemPool->bind(); | ||
426 | |||
427 | if (mAGPMemPool->getSize() < MIN_AGP_SIZE) | ||
428 | { | ||
429 | llwarns << "Not enough AGP memory!" << llendl; | ||
430 | delete mAGPMemPool; | ||
431 | mAGPMemPool = NULL; | ||
432 | mRenderFeatureMask &= ~RENDER_FEATURE_AGP; // Need to disable the using AGP flag | ||
433 | return FALSE; | ||
434 | } | ||
435 | |||
436 | |||
437 | if (mAGPMemPool) | ||
438 | { | ||
439 | // Create the fence that we use for global synchronization. | ||
440 | mGlobalFence = mAGPMemPool->createFence(); | ||
441 | } | ||
442 | return TRUE; | ||
443 | } | ||
444 | |||
445 | } | ||
446 | |||
447 | void LLPipeline::cleanupAGP() | ||
448 | { | ||
449 | int i; | ||
450 | for(i=0; i < mBufferCount; i++) | ||
451 | { | ||
452 | mBufferMemory[i]->deleteFence(mBufferFence[i]); | ||
453 | mBufferMemory[i]->setUseAGP(FALSE); | ||
454 | } | ||
455 | |||
456 | flushAGPMemory(); | ||
457 | if (mAGPMemPool && mGlobalFence) | ||
458 | { | ||
459 | mAGPMemPool->deleteFence(mGlobalFence); | ||
460 | mGlobalFence = 0; | ||
461 | } | ||
462 | delete mAGPMemPool; | ||
463 | mAGPMemPool = NULL; | ||
464 | } | ||
465 | |||
466 | BOOL LLPipeline::usingAGP() const | ||
467 | { | ||
468 | return (mRenderFeatureMask & RENDER_FEATURE_AGP) ? TRUE : FALSE; | ||
469 | } | ||
470 | |||
471 | void LLPipeline::setUseAGP(const BOOL use_agp) | ||
472 | { | ||
473 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
474 | |||
475 | if (use_agp == usingAGP()) | ||
476 | { | ||
477 | return; | ||
478 | } | ||
479 | else if (use_agp) | ||
480 | { | ||
481 | mRenderFeatureMask |= RENDER_FEATURE_AGP; | ||
482 | initAGP(); | ||
483 | |||
484 | // Forces us to allocate an AGP memory block immediately. | ||
485 | int i; | ||
486 | for(i=0; i < mBufferCount; i++) | ||
487 | { | ||
488 | mBufferMemory[i]->setUseAGP(use_agp); | ||
489 | mBufferMemory[i]->realloc(mBufferMemory[i]->getMax()); | ||
490 | mBufferFence[i] = mBufferMemory[i]->createFence(); | ||
491 | } | ||
492 | |||
493 | // Must be done AFTER you initialize AGP | ||
494 | for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) | ||
495 | { | ||
496 | LLDrawPool *poolp = *iter; | ||
497 | poolp->setUseAGP(use_agp); | ||
498 | } | ||
499 | } | ||
500 | else | ||
501 | { | ||
502 | unbindAGP(); | ||
503 | mRenderFeatureMask &= ~RENDER_FEATURE_AGP; | ||
504 | |||
505 | // Must be done BEFORE you blow away AGP | ||
506 | for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) | ||
507 | { | ||
508 | LLDrawPool *poolp = *iter; | ||
509 | poolp->setUseAGP(use_agp); | ||
510 | } | ||
511 | |||
512 | int i; | ||
513 | for(i=0; i < mBufferCount; i++) | ||
514 | { | ||
515 | if (mBufferMemory[i]) | ||
516 | { | ||
517 | mBufferMemory[i]->setUseAGP(use_agp); | ||
518 | mBufferMemory[i]->deleteFence(mBufferFence[i]); | ||
519 | mBufferFence[i] = 0; | ||
520 | } | ||
521 | else | ||
522 | { | ||
523 | llerrs << "setUseAGP without buffer memory" << llendl; | ||
524 | } | ||
525 | } | ||
526 | |||
527 | cleanupAGP(); | ||
528 | } | ||
529 | |||
530 | } | ||
531 | |||
532 | //============================================================================ | ||
533 | |||
534 | void LLPipeline::destroyGL() | ||
535 | { | ||
536 | setUseAGP(FALSE); | ||
537 | stop_glerror(); | ||
538 | unloadShaders(); | ||
539 | mHighlightFaces.reset(); | ||
540 | } | ||
541 | |||
542 | void LLPipeline::restoreGL() | ||
543 | { | ||
544 | if (mVertexShadersEnabled) | ||
545 | { | ||
546 | setShaders(); | ||
547 | } | ||
548 | |||
549 | if (mObjectPartition) | ||
550 | { | ||
551 | mObjectPartition->restoreGL(); | ||
552 | } | ||
553 | } | ||
554 | |||
555 | //============================================================================ | ||
556 | // Load Shader | ||
557 | |||
558 | static LLString get_object_log(GLhandleARB ret) | ||
559 | { | ||
560 | LLString res; | ||
561 | |||
562 | //get log length | ||
563 | GLint length; | ||
564 | glGetObjectParameterivARB(ret, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); | ||
565 | if (length > 0) | ||
566 | { | ||
567 | //the log could be any size, so allocate appropriately | ||
568 | GLcharARB* log = new GLcharARB[length]; | ||
569 | glGetInfoLogARB(ret, length, &length, log); | ||
570 | res = LLString(log); | ||
571 | delete[] log; | ||
572 | } | ||
573 | return res; | ||
574 | } | ||
575 | |||
576 | void LLPipeline::dumpObjectLog(GLhandleARB ret, BOOL warns) | ||
577 | { | ||
578 | LLString log = get_object_log(ret); | ||
579 | if (warns) | ||
580 | { | ||
581 | llwarns << log << llendl; | ||
582 | } | ||
583 | else | ||
584 | { | ||
585 | llinfos << log << llendl; | ||
586 | } | ||
587 | } | ||
588 | |||
589 | GLhandleARB LLPipeline::loadShader(const LLString& filename, S32 cls, GLenum type) | ||
590 | { | ||
591 | GLenum error; | ||
592 | error = glGetError(); | ||
593 | if (error != GL_NO_ERROR) | ||
594 | { | ||
595 | llwarns << "GL ERROR entering loadShader(): " << error << llendl; | ||
596 | } | ||
597 | |||
598 | llinfos << "Loading shader file: " << filename << llendl; | ||
599 | |||
600 | if (filename.empty()) | ||
601 | { | ||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | |||
606 | //read in from file | ||
607 | FILE* file = NULL; | ||
608 | |||
609 | S32 try_gpu_class = mVertexShaderLevel[cls]; | ||
610 | S32 gpu_class; | ||
611 | |||
612 | //find the most relevant file | ||
613 | for (gpu_class = try_gpu_class; gpu_class > 0; gpu_class--) | ||
614 | { //search from the current gpu class down to class 1 to find the most relevant shader | ||
615 | std::stringstream fname; | ||
616 | fname << gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class"); | ||
617 | fname << gpu_class << "/" << filename; | ||
618 | |||
619 | llinfos << "Looking in " << fname.str().c_str() << llendl; | ||
620 | file = fopen(fname.str().c_str(), "r"); | ||
621 | if (file) | ||
622 | { | ||
623 | break; // done | ||
624 | } | ||
625 | } | ||
626 | |||
627 | if (file == NULL) | ||
628 | { | ||
629 | llinfos << "GLSL Shader file not found: " << filename << llendl; | ||
630 | return 0; | ||
631 | } | ||
632 | |||
633 | //we can't have any lines longer than 1024 characters | ||
634 | //or any shaders longer than 1024 lines... deal - DaveP | ||
635 | GLcharARB buff[1024]; | ||
636 | GLcharARB* text[1024]; | ||
637 | GLuint count = 0; | ||
638 | |||
639 | //copy file into memory | ||
640 | while(fgets(buff, 1024, file) != NULL) | ||
641 | { | ||
642 | text[count++] = strdup(buff); | ||
643 | } | ||
644 | fclose(file); | ||
645 | |||
646 | //create shader object | ||
647 | GLhandleARB ret = glCreateShaderObjectARB(type); | ||
648 | error = glGetError(); | ||
649 | if (error != GL_NO_ERROR) | ||
650 | { | ||
651 | llwarns << "GL ERROR in glCreateShaderObjectARB: " << error << llendl; | ||
652 | } | ||
653 | else | ||
654 | { | ||
655 | //load source | ||
656 | glShaderSourceARB(ret, count, (const GLcharARB**) text, NULL); | ||
657 | error = glGetError(); | ||
658 | if (error != GL_NO_ERROR) | ||
659 | { | ||
660 | llwarns << "GL ERROR in glShaderSourceARB: " << error << llendl; | ||
661 | } | ||
662 | else | ||
663 | { | ||
664 | //compile source | ||
665 | glCompileShaderARB(ret); | ||
666 | error = glGetError(); | ||
667 | if (error != GL_NO_ERROR) | ||
668 | { | ||
669 | llwarns << "GL ERROR in glCompileShaderARB: " << error << llendl; | ||
670 | } | ||
671 | } | ||
672 | } | ||
673 | //free memory | ||
674 | for (GLuint i = 0; i < count; i++) | ||
675 | { | ||
676 | free(text[i]); | ||
677 | } | ||
678 | if (error == GL_NO_ERROR) | ||
679 | { | ||
680 | //check for errors | ||
681 | GLint success = GL_TRUE; | ||
682 | glGetObjectParameterivARB(ret, GL_OBJECT_COMPILE_STATUS_ARB, &success); | ||
683 | error = glGetError(); | ||
684 | if (error != GL_NO_ERROR || success == GL_FALSE) | ||
685 | { | ||
686 | //an error occured, print log | ||
687 | llwarns << "GLSL Compilation Error: (" << error << ") in " << filename << llendl; | ||
688 | dumpObjectLog(ret); | ||
689 | ret = 0; | ||
690 | } | ||
691 | } | ||
692 | else | ||
693 | { | ||
694 | ret = 0; | ||
695 | } | ||
696 | stop_glerror(); | ||
697 | |||
698 | //successfully loaded, save results | ||
699 | #if 1 // 1.9.1 | ||
700 | if (ret) | ||
701 | { | ||
702 | mVertexShaderLevel[cls] = try_gpu_class; | ||
703 | } | ||
704 | else | ||
705 | { | ||
706 | if (mVertexShaderLevel[cls] > 1) | ||
707 | { | ||
708 | mVertexShaderLevel[cls] = mVertexShaderLevel[cls] - 1; | ||
709 | ret = loadShader(filename,cls,type); | ||
710 | if (ret && mMaxVertexShaderLevel[cls] > mVertexShaderLevel[cls]) | ||
711 | { | ||
712 | mMaxVertexShaderLevel[cls] = mVertexShaderLevel[cls]; | ||
713 | } | ||
714 | } | ||
715 | } | ||
716 | #else | ||
717 | if (ret) | ||
718 | { | ||
719 | S32 max = -1; | ||
720 | /*if (try_gpu_class == mMaxVertexShaderLevel[cls]) | ||
721 | { | ||
722 | max = gpu_class; | ||
723 | }*/ | ||
724 | saveVertexShaderLevel(cls,try_gpu_class,max); | ||
725 | } | ||
726 | else | ||
727 | { | ||
728 | if (mVertexShaderLevel[cls] > 1) | ||
729 | { | ||
730 | mVertexShaderLevel[cls] = mVertexShaderLevel[cls] - 1; | ||
731 | ret = loadShader(f,cls,type); | ||
732 | if (ret && mMaxVertexShaderLevel[cls] > mVertexShaderLevel[cls]) | ||
733 | { | ||
734 | saveVertexShaderLevel(cls, mVertexShaderLevel[cls], mVertexShaderLevel[cls]); | ||
735 | } | ||
736 | } | ||
737 | } | ||
738 | #endif | ||
739 | return ret; | ||
740 | } | ||
741 | |||
742 | BOOL LLPipeline::linkProgramObject(GLhandleARB obj, BOOL suppress_errors) | ||
743 | { | ||
744 | //check for errors | ||
745 | glLinkProgramARB(obj); | ||
746 | GLint success = GL_TRUE; | ||
747 | glGetObjectParameterivARB(obj, GL_OBJECT_LINK_STATUS_ARB, &success); | ||
748 | if (!suppress_errors && success == GL_FALSE) | ||
749 | { | ||
750 | //an error occured, print log | ||
751 | llwarns << "GLSL Linker Error:" << llendl; | ||
752 | } | ||
753 | |||
754 | LLString log = get_object_log(obj); | ||
755 | LLString::toLower(log); | ||
756 | if (log.find("software") != LLString::npos) | ||
757 | { | ||
758 | llwarns << "GLSL Linker: Running in Software:" << llendl; | ||
759 | success = GL_FALSE; | ||
760 | suppress_errors = FALSE; | ||
761 | } | ||
762 | if (!suppress_errors) | ||
763 | { | ||
764 | dumpObjectLog(obj, !success); | ||
765 | } | ||
766 | |||
767 | return success; | ||
768 | } | ||
769 | |||
770 | BOOL LLPipeline::validateProgramObject(GLhandleARB obj) | ||
771 | { | ||
772 | //check program validity against current GL | ||
773 | glValidateProgramARB(obj); | ||
774 | GLint success = GL_TRUE; | ||
775 | glGetObjectParameterivARB(obj, GL_OBJECT_VALIDATE_STATUS_ARB, &success); | ||
776 | if (success == GL_FALSE) | ||
777 | { | ||
778 | llwarns << "GLSL program not valid: " << llendl; | ||
779 | dumpObjectLog(obj); | ||
780 | } | ||
781 | else | ||
782 | { | ||
783 | dumpObjectLog(obj, FALSE); | ||
784 | } | ||
785 | |||
786 | return success; | ||
787 | } | ||
788 | |||
789 | //============================================================================ | ||
790 | // Shader Management | ||
791 | |||
792 | void LLPipeline::setShaders() | ||
793 | { | ||
794 | if (gViewerWindow) | ||
795 | { | ||
796 | gViewerWindow->setCursor(UI_CURSOR_WAIT); | ||
797 | } | ||
798 | |||
799 | // Lighting | ||
800 | setLightingDetail(-1); | ||
801 | |||
802 | // Shaders | ||
803 | for (S32 i=0; i<SHADER_COUNT; i++) | ||
804 | { | ||
805 | mVertexShaderLevel[i] = 0; | ||
806 | mMaxVertexShaderLevel[i] = 0; | ||
807 | } | ||
808 | if (canUseVertexShaders()) | ||
809 | { | ||
810 | S32 light_class = 2; | ||
811 | S32 env_class = 2; | ||
812 | if (getLightingDetail() == 0) | ||
813 | { | ||
814 | light_class = 1; | ||
815 | } | ||
816 | // Load lighting shaders | ||
817 | mVertexShaderLevel[SHADER_LIGHTING] = light_class; | ||
818 | mMaxVertexShaderLevel[SHADER_LIGHTING] = light_class; | ||
819 | mVertexShaderLevel[SHADER_ENVIRONMENT] = env_class; | ||
820 | mMaxVertexShaderLevel[SHADER_ENVIRONMENT] = env_class; | ||
821 | BOOL loaded = loadShadersLighting(); | ||
822 | if (loaded) | ||
823 | { | ||
824 | mVertexShadersEnabled = TRUE; | ||
825 | mVertexShadersLoaded = 1; | ||
826 | |||
827 | // Load all shaders to set max levels | ||
828 | loadShadersEnvironment(); | ||
829 | |||
830 | // Load max avatar shaders to set the max level | ||
831 | mVertexShaderLevel[SHADER_AVATAR] = 3; | ||
832 | mMaxVertexShaderLevel[SHADER_AVATAR] = 3; | ||
833 | loadShadersAvatar(); | ||
834 | |||
835 | // Load shaders to correct levels | ||
836 | if (!gSavedSettings.getBOOL("RenderRippleWater")) | ||
837 | { | ||
838 | mVertexShaderLevel[SHADER_ENVIRONMENT] = 0; | ||
839 | loadShadersEnvironment(); // unloads | ||
840 | } | ||
841 | |||
842 | #if LL_DARWIN // force avatar shaders off for mac | ||
843 | mVertexShaderLevel[SHADER_AVATAR] = 0; | ||
844 | mMaxVertexShaderLevel[SHADER_AVATAR] = 0; | ||
845 | #else | ||
846 | if (gSavedSettings.getBOOL("RenderAvatarVP")) | ||
847 | { | ||
848 | S32 avatar = gSavedSettings.getS32("RenderAvatarMode"); | ||
849 | S32 avatar_class = 1 + avatar; | ||
850 | // Set the actual level | ||
851 | mVertexShaderLevel[SHADER_AVATAR] = avatar_class; | ||
852 | loadShadersAvatar(); | ||
853 | if (mVertexShaderLevel[SHADER_AVATAR] != avatar_class) | ||
854 | { | ||
855 | if (mVertexShaderLevel[SHADER_AVATAR] == 0) | ||
856 | { | ||
857 | gSavedSettings.setBOOL("RenderAvatarVP", FALSE); | ||
858 | } | ||
859 | avatar = llmax(mVertexShaderLevel[SHADER_AVATAR]-1,0); | ||
860 | gSavedSettings.setS32("RenderAvatarMode", avatar); | ||
861 | } | ||
862 | } | ||
863 | else | ||
864 | { | ||
865 | mVertexShaderLevel[SHADER_AVATAR] = 0; | ||
866 | gSavedSettings.setS32("RenderAvatarMode", 0); | ||
867 | loadShadersAvatar(); // unloads | ||
868 | } | ||
869 | #endif | ||
870 | } | ||
871 | else | ||
872 | { | ||
873 | mVertexShadersEnabled = FALSE; | ||
874 | mVertexShadersLoaded = 0; | ||
875 | } | ||
876 | } | ||
877 | if (gViewerWindow) | ||
878 | { | ||
879 | gViewerWindow->setCursor(UI_CURSOR_ARROW); | ||
880 | } | ||
881 | } | ||
882 | |||
883 | BOOL LLPipeline::canUseVertexShaders() | ||
884 | { | ||
885 | if (!gGLManager.mHasVertexShader || | ||
886 | !gGLManager.mHasFragmentShader || | ||
887 | !gFeatureManagerp->isFeatureAvailable("VertexShaderEnable") || | ||
888 | mVertexShadersLoaded == -1) | ||
889 | { | ||
890 | return FALSE; | ||
891 | } | ||
892 | else | ||
893 | { | ||
894 | return TRUE; | ||
895 | } | ||
896 | } | ||
897 | |||
898 | void LLPipeline::unloadShaders() | ||
899 | { | ||
900 | mObjectSimpleProgram.unload(); | ||
901 | mObjectBumpProgram.unload(); | ||
902 | mObjectAlphaProgram.unload(); | ||
903 | mWaterProgram.unload(); | ||
904 | mTerrainProgram.unload(); | ||
905 | mGroundProgram.unload(); | ||
906 | mAvatarProgram.unload(); | ||
907 | mAvatarEyeballProgram.unload(); | ||
908 | mAvatarPickProgram.unload(); | ||
909 | mHighlightProgram.unload(); | ||
910 | |||
911 | mVertexShaderLevel[SHADER_LIGHTING] = 0; | ||
912 | mVertexShaderLevel[SHADER_OBJECT] = 0; | ||
913 | mVertexShaderLevel[SHADER_AVATAR] = 0; | ||
914 | mVertexShaderLevel[SHADER_ENVIRONMENT] = 0; | ||
915 | mVertexShaderLevel[SHADER_INTERFACE] = 0; | ||
916 | |||
917 | mLightVertex = mLightFragment = mScatterVertex = mScatterFragment = 0; | ||
918 | mVertexShadersLoaded = 0; | ||
919 | } | ||
920 | |||
921 | #if 0 // 1.9.2 | ||
922 | // Any time shader options change | ||
923 | BOOL LLPipeline::loadShaders() | ||
924 | { | ||
925 | unloadShaders(); | ||
926 | |||
927 | if (!canUseVertexShaders()) | ||
928 | { | ||
929 | return FALSE; | ||
930 | } | ||
931 | |||
932 | S32 light_class = mMaxVertexShaderLevel[SHADER_LIGHTING]; | ||
933 | if (getLightingDetail() == 0) | ||
934 | { | ||
935 | light_class = 1; // Use minimum lighting shader | ||
936 | } | ||
937 | else if (getLightingDetail() == 1) | ||
938 | { | ||
939 | light_class = 2; // Use medium lighting shader | ||
940 | } | ||
941 | mVertexShaderLevel[SHADER_LIGHTING] = light_class; | ||
942 | mVertexShaderLevel[SHADER_OBJECT] = llmin(mMaxVertexShaderLevel[SHADER_OBJECT], gSavedSettings.getS32("VertexShaderLevelObject")); | ||
943 | mVertexShaderLevel[SHADER_AVATAR] = llmin(mMaxVertexShaderLevel[SHADER_AVATAR], gSavedSettings.getS32("VertexShaderLevelAvatar")); | ||
944 | mVertexShaderLevel[SHADER_ENVIRONMENT] = llmin(mMaxVertexShaderLevel[SHADER_ENVIRONMENT], gSavedSettings.getS32("VertexShaderLevelEnvironment")); | ||
945 | mVertexShaderLevel[SHADER_INTERFACE] = mMaxVertexShaderLevel[SHADER_INTERFACE]; | ||
946 | |||
947 | BOOL loaded = loadShadersLighting(); | ||
948 | if (loaded) | ||
949 | { | ||
950 | loadShadersEnvironment(); // Must load this before object/avatar for scatter | ||
951 | loadShadersObject(); | ||
952 | loadShadersAvatar(); | ||
953 | loadShadersInterface(); | ||
954 | mVertexShadersLoaded = 1; | ||
955 | } | ||
956 | else | ||
957 | { | ||
958 | unloadShaders(); | ||
959 | mVertexShadersEnabled = FALSE; | ||
960 | mVertexShadersLoaded = 0; //-1; // -1 = failed | ||
961 | setLightingDetail(-1); | ||
962 | } | ||
963 | |||
964 | return loaded; | ||
965 | } | ||
966 | #endif | ||
967 | |||
968 | BOOL LLPipeline::loadShadersLighting() | ||
969 | { | ||
970 | // Load light dependency shaders first | ||
971 | // All of these have to load for any shaders to function | ||
972 | |||
973 | std::string lightvertex = "lighting/lightV.glsl"; | ||
974 | //get default light function implementation | ||
975 | mLightVertex = loadShader(lightvertex, SHADER_LIGHTING, GL_VERTEX_SHADER_ARB); | ||
976 | if( !mLightVertex ) | ||
977 | { | ||
978 | llwarns << "Failed to load " << lightvertex << llendl; | ||
979 | return FALSE; | ||
980 | } | ||
981 | |||
982 | std::string lightfragment = "lighting/lightF.glsl"; | ||
983 | mLightFragment = loadShader(lightfragment, SHADER_LIGHTING, GL_FRAGMENT_SHADER_ARB); | ||
984 | if ( !mLightFragment ) | ||
985 | { | ||
986 | llwarns << "Failed to load " << lightfragment << llendl; | ||
987 | return FALSE; | ||
988 | } | ||
989 | |||
990 | // NOTE: Scatter shaders use the ENVIRONMENT detail level | ||
991 | |||
992 | std::string scattervertex = "environment/scatterV.glsl"; | ||
993 | mScatterVertex = loadShader(scattervertex, SHADER_ENVIRONMENT, GL_VERTEX_SHADER_ARB); | ||
994 | if ( !mScatterVertex ) | ||
995 | { | ||
996 | llwarns << "Failed to load " << scattervertex << llendl; | ||
997 | return FALSE; | ||
998 | } | ||
999 | |||
1000 | std::string scatterfragment = "environment/scatterF.glsl"; | ||
1001 | mScatterFragment = loadShader(scatterfragment, SHADER_ENVIRONMENT, GL_FRAGMENT_SHADER_ARB); | ||
1002 | if ( !mScatterFragment ) | ||
1003 | { | ||
1004 | llwarns << "Failed to load " << scatterfragment << llendl; | ||
1005 | return FALSE; | ||
1006 | } | ||
1007 | |||
1008 | return TRUE; | ||
1009 | } | ||
1010 | |||
1011 | BOOL LLPipeline::loadShadersEnvironment() | ||
1012 | { | ||
1013 | GLhandleARB baseObjects[] = | ||
1014 | { | ||
1015 | mLightFragment, | ||
1016 | mLightVertex, | ||
1017 | mScatterFragment, | ||
1018 | mScatterVertex | ||
1019 | }; | ||
1020 | S32 baseCount = 4; | ||
1021 | |||
1022 | BOOL success = TRUE; | ||
1023 | |||
1024 | if (mVertexShaderLevel[SHADER_ENVIRONMENT] == 0) | ||
1025 | { | ||
1026 | mWaterProgram.unload(); | ||
1027 | mGroundProgram.unload(); | ||
1028 | mTerrainProgram.unload(); | ||
1029 | return FALSE; | ||
1030 | } | ||
1031 | |||
1032 | if (success) | ||
1033 | { | ||
1034 | //load water vertex shader | ||
1035 | std::string waterfragment = "environment/waterF.glsl"; | ||
1036 | std::string watervertex = "environment/waterV.glsl"; | ||
1037 | mWaterProgram.mProgramObject = glCreateProgramObjectARB(); | ||
1038 | mWaterProgram.attachObjects(baseObjects, baseCount); | ||
1039 | mWaterProgram.attachObject(loadShader(watervertex, SHADER_ENVIRONMENT, GL_VERTEX_SHADER_ARB)); | ||
1040 | mWaterProgram.attachObject(loadShader(waterfragment, SHADER_ENVIRONMENT, GL_FRAGMENT_SHADER_ARB)); | ||
1041 | |||
1042 | success = mWaterProgram.mapAttributes(); | ||
1043 | if (success) | ||
1044 | { | ||
1045 | success = mWaterProgram.mapUniforms(sWaterUniforms, sWaterUniformCount); | ||
1046 | } | ||
1047 | if (!success) | ||
1048 | { | ||
1049 | llwarns << "Failed to load " << watervertex << llendl; | ||
1050 | } | ||
1051 | } | ||
1052 | if (success) | ||
1053 | { | ||
1054 | //load ground vertex shader | ||
1055 | std::string groundvertex = "environment/groundV.glsl"; | ||
1056 | std::string groundfragment = "environment/groundF.glsl"; | ||
1057 | mGroundProgram.mProgramObject = glCreateProgramObjectARB(); | ||
1058 | mGroundProgram.attachObjects(baseObjects, baseCount); | ||
1059 | mGroundProgram.attachObject(loadShader(groundvertex, SHADER_ENVIRONMENT, GL_VERTEX_SHADER_ARB)); | ||
1060 | mGroundProgram.attachObject(loadShader(groundfragment, SHADER_ENVIRONMENT, GL_FRAGMENT_SHADER_ARB)); | ||
1061 | |||
1062 | success = mGroundProgram.mapAttributes(); | ||
1063 | if (success) | ||
1064 | { | ||
1065 | success = mGroundProgram.mapUniforms(); | ||
1066 | } | ||
1067 | if (!success) | ||
1068 | { | ||
1069 | llwarns << "Failed to load " << groundvertex << llendl; | ||
1070 | } | ||
1071 | } | ||
1072 | |||
1073 | if (success) | ||
1074 | { | ||
1075 | //load terrain vertex shader | ||
1076 | std::string terrainvertex = "environment/terrainV.glsl"; | ||
1077 | std::string terrainfragment = "environment/terrainF.glsl"; | ||
1078 | mTerrainProgram.mProgramObject = glCreateProgramObjectARB(); | ||
1079 | mTerrainProgram.attachObjects(baseObjects, baseCount); | ||
1080 | mTerrainProgram.attachObject(loadShader(terrainvertex, SHADER_ENVIRONMENT, GL_VERTEX_SHADER_ARB)); | ||
1081 | mTerrainProgram.attachObject(loadShader(terrainfragment, SHADER_ENVIRONMENT, GL_FRAGMENT_SHADER_ARB)); | ||
1082 | success = mTerrainProgram.mapAttributes(); | ||
1083 | if (success) | ||
1084 | { | ||
1085 | success = mTerrainProgram.mapUniforms(sTerrainUniforms, sTerrainUniformCount); | ||
1086 | } | ||
1087 | if (!success) | ||
1088 | { | ||
1089 | llwarns << "Failed to load " << terrainvertex << llendl; | ||
1090 | } | ||
1091 | } | ||
1092 | |||
1093 | if( !success ) | ||
1094 | { | ||
1095 | mVertexShaderLevel[SHADER_ENVIRONMENT] = 0; | ||
1096 | mMaxVertexShaderLevel[SHADER_ENVIRONMENT] = 0; | ||
1097 | return FALSE; | ||
1098 | } | ||
1099 | |||
1100 | if (gWorldPointer) | ||
1101 | { | ||
1102 | gWorldPointer->updateWaterObjects(); | ||
1103 | } | ||
1104 | |||
1105 | return TRUE; | ||
1106 | } | ||
1107 | |||
1108 | BOOL LLPipeline::loadShadersObject() | ||
1109 | { | ||
1110 | GLhandleARB baseObjects[] = | ||
1111 | { | ||
1112 | mLightFragment, | ||
1113 | mLightVertex, | ||
1114 | mScatterFragment, | ||
1115 | mScatterVertex | ||
1116 | }; | ||
1117 | S32 baseCount = 4; | ||
1118 | |||
1119 | BOOL success = TRUE; | ||
1120 | |||
1121 | if (mVertexShaderLevel[SHADER_OBJECT] == 0) | ||
1122 | { | ||
1123 | mObjectSimpleProgram.unload(); | ||
1124 | mObjectBumpProgram.unload(); | ||
1125 | mObjectAlphaProgram.unload(); | ||
1126 | return FALSE; | ||
1127 | } | ||
1128 | |||
1129 | if (success) | ||
1130 | { | ||
1131 | //load object (volume/tree) vertex shader | ||
1132 | std::string simplevertex = "objects/simpleV.glsl"; | ||
1133 | std::string simplefragment = "objects/simpleF.glsl"; | ||
1134 | mObjectSimpleProgram.mProgramObject = glCreateProgramObjectARB(); | ||
1135 | mObjectSimpleProgram.attachObjects(baseObjects, baseCount); | ||
1136 | mObjectSimpleProgram.attachObject(loadShader(simplevertex, SHADER_OBJECT, GL_VERTEX_SHADER_ARB)); | ||
1137 | mObjectSimpleProgram.attachObject(loadShader(simplefragment, SHADER_OBJECT, GL_FRAGMENT_SHADER_ARB)); | ||
1138 | success = mObjectSimpleProgram.mapAttributes(); | ||
1139 | if (success) | ||
1140 | { | ||
1141 | success = mObjectSimpleProgram.mapUniforms(); | ||
1142 | } | ||
1143 | if( !success ) | ||
1144 | { | ||
1145 | llwarns << "Failed to load " << simplevertex << llendl; | ||
1146 | } | ||
1147 | } | ||
1148 | |||
1149 | if (success) | ||
1150 | { | ||
1151 | //load object bumpy vertex shader | ||
1152 | std::string bumpshinyvertex = "objects/bumpshinyV.glsl"; | ||
1153 | std::string bumpshinyfragment = "objects/bumpshinyF.glsl"; | ||
1154 | mObjectBumpProgram.mProgramObject = glCreateProgramObjectARB(); | ||
1155 | mObjectBumpProgram.attachObjects(baseObjects, baseCount); | ||
1156 | mObjectBumpProgram.attachObject(loadShader(bumpshinyvertex, SHADER_OBJECT, GL_VERTEX_SHADER_ARB)); | ||
1157 | mObjectBumpProgram.attachObject(loadShader(bumpshinyfragment, SHADER_OBJECT, GL_FRAGMENT_SHADER_ARB)); | ||
1158 | success = mObjectBumpProgram.mapAttributes(); | ||
1159 | if (success) | ||
1160 | { | ||
1161 | success = mObjectBumpProgram.mapUniforms(); | ||
1162 | } | ||
1163 | if( !success ) | ||
1164 | { | ||
1165 | llwarns << "Failed to load " << bumpshinyvertex << llendl; | ||
1166 | } | ||
1167 | } | ||
1168 | |||
1169 | if (success) | ||
1170 | { | ||
1171 | //load object alpha vertex shader | ||
1172 | std::string alphavertex = "objects/alphaV.glsl"; | ||
1173 | std::string alphafragment = "objects/alphaF.glsl"; | ||
1174 | mObjectAlphaProgram.mProgramObject = glCreateProgramObjectARB(); | ||
1175 | mObjectAlphaProgram.attachObjects(baseObjects, baseCount); | ||
1176 | mObjectAlphaProgram.attachObject(loadShader(alphavertex, SHADER_OBJECT, GL_VERTEX_SHADER_ARB)); | ||
1177 | mObjectAlphaProgram.attachObject(loadShader(alphafragment, SHADER_OBJECT, GL_FRAGMENT_SHADER_ARB)); | ||
1178 | |||
1179 | success = mObjectAlphaProgram.mapAttributes(); | ||
1180 | if (success) | ||
1181 | { | ||
1182 | success = mObjectAlphaProgram.mapUniforms(); | ||
1183 | } | ||
1184 | if( !success ) | ||
1185 | { | ||
1186 | llwarns << "Failed to load " << alphavertex << llendl; | ||
1187 | } | ||
1188 | } | ||
1189 | |||
1190 | if( !success ) | ||
1191 | { | ||
1192 | mVertexShaderLevel[SHADER_OBJECT] = 0; | ||
1193 | mMaxVertexShaderLevel[SHADER_OBJECT] = 0; | ||
1194 | return FALSE; | ||
1195 | } | ||
1196 | |||
1197 | return TRUE; | ||
1198 | } | ||
1199 | |||
1200 | BOOL LLPipeline::loadShadersAvatar() | ||
1201 | { | ||
1202 | GLhandleARB baseObjects[] = | ||
1203 | { | ||
1204 | mLightFragment, | ||
1205 | mLightVertex, | ||
1206 | mScatterFragment, | ||
1207 | mScatterVertex | ||
1208 | }; | ||
1209 | S32 baseCount = 4; | ||
1210 | |||
1211 | BOOL success = TRUE; | ||
1212 | |||
1213 | if (mVertexShaderLevel[SHADER_AVATAR] == 0) | ||
1214 | { | ||
1215 | mAvatarProgram.unload(); | ||
1216 | mAvatarEyeballProgram.unload(); | ||
1217 | mAvatarPickProgram.unload(); | ||
1218 | return FALSE; | ||
1219 | } | ||
1220 | |||
1221 | if (success) | ||
1222 | { | ||
1223 | //load specular (eyeball) vertex program | ||
1224 | std::string eyeballvertex = "avatar/eyeballV.glsl"; | ||
1225 | std::string eyeballfragment = "avatar/eyeballF.glsl"; | ||
1226 | mAvatarEyeballProgram.mProgramObject = glCreateProgramObjectARB(); | ||
1227 | mAvatarEyeballProgram.attachObjects(baseObjects, baseCount); | ||
1228 | mAvatarEyeballProgram.attachObject(loadShader(eyeballvertex, SHADER_AVATAR, GL_VERTEX_SHADER_ARB)); | ||
1229 | mAvatarEyeballProgram.attachObject(loadShader(eyeballfragment, SHADER_AVATAR, GL_FRAGMENT_SHADER_ARB)); | ||
1230 | success = mAvatarEyeballProgram.mapAttributes(); | ||
1231 | if (success) | ||
1232 | { | ||
1233 | success = mAvatarEyeballProgram.mapUniforms(); | ||
1234 | } | ||
1235 | if( !success ) | ||
1236 | { | ||
1237 | llwarns << "Failed to load " << eyeballvertex << llendl; | ||
1238 | } | ||
1239 | } | ||
1240 | |||
1241 | if (success) | ||
1242 | { | ||
1243 | mAvatarSkinVertex = loadShader("avatar/avatarSkinV.glsl", SHADER_AVATAR, GL_VERTEX_SHADER_ARB); | ||
1244 | //load avatar vertex shader | ||
1245 | std::string avatarvertex = "avatar/avatarV.glsl"; | ||
1246 | std::string avatarfragment = "avatar/avatarF.glsl"; | ||
1247 | |||
1248 | mAvatarProgram.mProgramObject = glCreateProgramObjectARB(); | ||
1249 | mAvatarProgram.attachObjects(baseObjects, baseCount); | ||
1250 | mAvatarProgram.attachObject(mAvatarSkinVertex); | ||
1251 | mAvatarProgram.attachObject(loadShader(avatarvertex, SHADER_AVATAR, GL_VERTEX_SHADER_ARB)); | ||
1252 | mAvatarProgram.attachObject(loadShader(avatarfragment, SHADER_AVATAR, GL_FRAGMENT_SHADER_ARB)); | ||
1253 | |||
1254 | success = mAvatarProgram.mapAttributes(sAvatarAttribs, sAvatarAttribCount); | ||
1255 | if (success) | ||
1256 | { | ||
1257 | success = mAvatarProgram.mapUniforms(sAvatarUniforms, sAvatarUniformCount); | ||
1258 | } | ||
1259 | if( !success ) | ||
1260 | { | ||
1261 | llwarns << "Failed to load " << avatarvertex << llendl; | ||
1262 | } | ||
1263 | } | ||
1264 | |||
1265 | if (success) | ||
1266 | { | ||
1267 | //load avatar picking shader | ||
1268 | std::string pickvertex = "avatar/pickAvatarV.glsl"; | ||
1269 | std::string pickfragment = "avatar/pickAvatarF.glsl"; | ||
1270 | mAvatarPickProgram.mProgramObject = glCreateProgramObjectARB(); | ||
1271 | mAvatarPickProgram.attachObject(loadShader(pickvertex, SHADER_AVATAR, GL_VERTEX_SHADER_ARB)); | ||
1272 | mAvatarPickProgram.attachObject(loadShader(pickfragment, SHADER_AVATAR, GL_FRAGMENT_SHADER_ARB)); | ||
1273 | mAvatarPickProgram.attachObject(mAvatarSkinVertex); | ||
1274 | |||
1275 | success = mAvatarPickProgram.mapAttributes(sAvatarAttribs, sAvatarAttribCount); | ||
1276 | if (success) | ||
1277 | { | ||
1278 | success = mAvatarPickProgram.mapUniforms(sAvatarUniforms, sAvatarUniformCount); | ||
1279 | } | ||
1280 | if( !success ) | ||
1281 | { | ||
1282 | llwarns << "Failed to load " << pickvertex << llendl; | ||
1283 | } | ||
1284 | } | ||
1285 | |||
1286 | if( !success ) | ||
1287 | { | ||
1288 | mVertexShaderLevel[SHADER_AVATAR] = 0; | ||
1289 | mMaxVertexShaderLevel[SHADER_AVATAR] = 0; | ||
1290 | return FALSE; | ||
1291 | } | ||
1292 | |||
1293 | return TRUE; | ||
1294 | } | ||
1295 | |||
1296 | BOOL LLPipeline::loadShadersInterface() | ||
1297 | { | ||
1298 | BOOL success = TRUE; | ||
1299 | |||
1300 | if (mVertexShaderLevel[SHADER_INTERFACE] == 0) | ||
1301 | { | ||
1302 | mHighlightProgram.unload(); | ||
1303 | return FALSE; | ||
1304 | } | ||
1305 | |||
1306 | if (success) | ||
1307 | { | ||
1308 | //load highlighting shader | ||
1309 | std::string highlightvertex = "interface/highlightV.glsl"; | ||
1310 | std::string highlightfragment = "interface/highlightF.glsl"; | ||
1311 | mHighlightProgram.mProgramObject = glCreateProgramObjectARB(); | ||
1312 | mHighlightProgram.attachObject(loadShader(highlightvertex, SHADER_INTERFACE, GL_VERTEX_SHADER_ARB)); | ||
1313 | mHighlightProgram.attachObject(loadShader(highlightfragment, SHADER_INTERFACE, GL_FRAGMENT_SHADER_ARB)); | ||
1314 | |||
1315 | success = mHighlightProgram.mapAttributes(); | ||
1316 | if (success) | ||
1317 | { | ||
1318 | success = mHighlightProgram.mapUniforms(); | ||
1319 | } | ||
1320 | if( !success ) | ||
1321 | { | ||
1322 | llwarns << "Failed to load " << highlightvertex << llendl; | ||
1323 | } | ||
1324 | } | ||
1325 | |||
1326 | if( !success ) | ||
1327 | { | ||
1328 | mVertexShaderLevel[SHADER_INTERFACE] = 0; | ||
1329 | mMaxVertexShaderLevel[SHADER_INTERFACE] = 0; | ||
1330 | return FALSE; | ||
1331 | } | ||
1332 | |||
1333 | return TRUE; | ||
1334 | } | ||
1335 | |||
1336 | //============================================================================ | ||
1337 | |||
1338 | void LLPipeline::enableShadows(const BOOL enable_shadows) | ||
1339 | { | ||
1340 | //should probably do something here to wrangle shadows.... | ||
1341 | } | ||
1342 | |||
1343 | S32 LLPipeline::getMaxLightingDetail() const | ||
1344 | { | ||
1345 | if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS) | ||
1346 | { | ||
1347 | return 3; | ||
1348 | } | ||
1349 | else | ||
1350 | { | ||
1351 | return 1; | ||
1352 | } | ||
1353 | } | ||
1354 | |||
1355 | S32 LLPipeline::setLightingDetail(S32 level) | ||
1356 | { | ||
1357 | if (level < 0) | ||
1358 | { | ||
1359 | level = gSavedSettings.getS32("RenderLightingDetail"); | ||
1360 | } | ||
1361 | level = llclamp(level, 0, getMaxLightingDetail()); | ||
1362 | if (level != mLightingDetail) | ||
1363 | { | ||
1364 | gSavedSettings.setS32("RenderLightingDetail", level); | ||
1365 | if (level >= 2) | ||
1366 | { | ||
1367 | gObjectList.relightAllObjects(); | ||
1368 | } | ||
1369 | mLightingDetail = level; | ||
1370 | |||
1371 | if (mVertexShadersLoaded == 1) | ||
1372 | { | ||
1373 | gPipeline.setShaders(); | ||
1374 | } | ||
1375 | } | ||
1376 | return mLightingDetail; | ||
1377 | } | ||
1378 | |||
1379 | LLAGPMemBlock *LLPipeline::allocAGPFromPool(const S32 bytes, const U32 target) | ||
1380 | { | ||
1381 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
1382 | |||
1383 | if (!mAGPMemPool) | ||
1384 | { | ||
1385 | llwarns << "Attempting to allocate AGP memory when AGP disabled!" << llendl; | ||
1386 | return NULL; | ||
1387 | } | ||
1388 | else | ||
1389 | { | ||
1390 | if (mUseVBO) | ||
1391 | { | ||
1392 | return ((LLAGPMemPoolARB*) mAGPMemPool)->allocBlock(bytes, target); | ||
1393 | } | ||
1394 | else | ||
1395 | { | ||
1396 | return mAGPMemPool->allocBlock(bytes); | ||
1397 | } | ||
1398 | } | ||
1399 | } | ||
1400 | |||
1401 | |||
1402 | void LLPipeline::unbindAGP() | ||
1403 | { | ||
1404 | if (mAGPMemPool && mAGPBound) | ||
1405 | { | ||
1406 | mAGPMemPool->disable(); | ||
1407 | mAGPBound = FALSE; | ||
1408 | } | ||
1409 | } | ||
1410 | |||
1411 | void LLPipeline::bindAGP() | ||
1412 | { | ||
1413 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
1414 | |||
1415 | if (mAGPMemPool && !mAGPBound && usingAGP()) | ||
1416 | { | ||
1417 | mAGPMemPool->enable(); | ||
1418 | mAGPBound = TRUE; | ||
1419 | } | ||
1420 | } | ||
1421 | |||
1422 | U8* LLPipeline::bufferGetScratchMemory(void) | ||
1423 | { | ||
1424 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
1425 | return(mBufferMemory[mBufferIndex]->getScratchMemory()); | ||
1426 | } | ||
1427 | |||
1428 | void LLPipeline::bufferWaitFence(void) | ||
1429 | { | ||
1430 | mBufferMemory[mBufferIndex]->waitFence(mBufferFence[mBufferIndex]); | ||
1431 | } | ||
1432 | |||
1433 | void LLPipeline::bufferSendFence(void) | ||
1434 | { | ||
1435 | mBufferMemory[mBufferIndex]->sendFence(mBufferFence[mBufferIndex]); | ||
1436 | } | ||
1437 | |||
1438 | void LLPipeline::bufferRotate(void) | ||
1439 | { | ||
1440 | mBufferIndex++; | ||
1441 | if(mBufferIndex >= mBufferCount) | ||
1442 | mBufferIndex = 0; | ||
1443 | } | ||
1444 | |||
1445 | // Called when a texture changes # of channels (rare, may cause faces to move to alpha pool) | ||
1446 | void LLPipeline::dirtyPoolObjectTextures(const LLViewerImage *texturep) | ||
1447 | { | ||
1448 | for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) | ||
1449 | { | ||
1450 | LLDrawPool *poolp = *iter; | ||
1451 | poolp->dirtyTexture(texturep); | ||
1452 | } | ||
1453 | } | ||
1454 | |||
1455 | LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0) | ||
1456 | { | ||
1457 | LLDrawPool *poolp = NULL; | ||
1458 | switch( type ) | ||
1459 | { | ||
1460 | case LLDrawPool::POOL_SIMPLE: | ||
1461 | poolp = get_if_there(mSimplePools, (uintptr_t)tex0, (LLDrawPool*)0 ); | ||
1462 | break; | ||
1463 | |||
1464 | case LLDrawPool::POOL_TREE: | ||
1465 | poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 ); | ||
1466 | break; | ||
1467 | |||
1468 | case LLDrawPool::POOL_TREE_NEW: | ||
1469 | poolp = get_if_there(mTreeNewPools, (uintptr_t)tex0, (LLDrawPool*)0 ); | ||
1470 | break; | ||
1471 | |||
1472 | case LLDrawPool::POOL_TERRAIN: | ||
1473 | poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 ); | ||
1474 | break; | ||
1475 | |||
1476 | case LLDrawPool::POOL_BUMP: | ||
1477 | poolp = get_if_there(mBumpPools, (uintptr_t)tex0, (LLDrawPool*)0 ); | ||
1478 | break; | ||
1479 | |||
1480 | case LLDrawPool::POOL_MEDIA: | ||
1481 | poolp = get_if_there(mMediaPools, (uintptr_t)tex0, (LLDrawPool*)0 ); | ||
1482 | break; | ||
1483 | |||
1484 | case LLDrawPool::POOL_ALPHA: | ||
1485 | poolp = mAlphaPool; | ||
1486 | break; | ||
1487 | |||
1488 | case LLDrawPool::POOL_AVATAR: | ||
1489 | break; // Do nothing | ||
1490 | |||
1491 | case LLDrawPool::POOL_SKY: | ||
1492 | poolp = mSkyPool; | ||
1493 | break; | ||
1494 | |||
1495 | case LLDrawPool::POOL_STARS: | ||
1496 | poolp = mStarsPool; | ||
1497 | break; | ||
1498 | |||
1499 | case LLDrawPool::POOL_CLOUDS: | ||
1500 | poolp = mCloudsPool; | ||
1501 | break; | ||
1502 | |||
1503 | case LLDrawPool::POOL_WATER: | ||
1504 | poolp = mWaterPool; | ||
1505 | break; | ||
1506 | |||
1507 | case LLDrawPool::POOL_GROUND: | ||
1508 | poolp = mGroundPool; | ||
1509 | break; | ||
1510 | |||
1511 | case LLDrawPool::POOL_HUD: | ||
1512 | poolp = mHUDPool; | ||
1513 | break; | ||
1514 | |||
1515 | default: | ||
1516 | llassert(0); | ||
1517 | llerrs << "Invalid Pool Type in LLPipeline::findPool() type=" << type << llendl; | ||
1518 | break; | ||
1519 | } | ||
1520 | |||
1521 | return poolp; | ||
1522 | } | ||
1523 | |||
1524 | |||
1525 | LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerImage *tex0) | ||
1526 | { | ||
1527 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
1528 | LLDrawPool *poolp = findPool(type, tex0); | ||
1529 | if (poolp) | ||
1530 | { | ||
1531 | return poolp; | ||
1532 | } | ||
1533 | |||
1534 | LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0); | ||
1535 | addPool( new_poolp ); | ||
1536 | |||
1537 | return new_poolp; | ||
1538 | } | ||
1539 | |||
1540 | |||
1541 | // static | ||
1542 | LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerImage* imagep) | ||
1543 | { | ||
1544 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
1545 | bool alpha = te->getColor().mV[3] < 0.999f; | ||
1546 | if (imagep) | ||
1547 | { | ||
1548 | alpha = alpha || (imagep->getComponents() == 4) || (imagep->getComponents() == 2); | ||
1549 | } | ||
1550 | #if 0 // Not currently used | ||
1551 | if (te->getMediaFlags() == LLTextureEntry::MF_WEB_PAGE) | ||
1552 | { | ||
1553 | return gPipeline.getPool(LLDrawPool::POOL_MEDIA, imagep); | ||
1554 | } | ||
1555 | else | ||
1556 | #endif | ||
1557 | if (alpha) | ||
1558 | { | ||
1559 | return gPipeline.getPool(LLDrawPool::POOL_ALPHA); | ||
1560 | } | ||
1561 | else if ((te->getBumpmap() || te->getShiny())) | ||
1562 | { | ||
1563 | return gPipeline.getPool(LLDrawPool::POOL_BUMP, imagep); | ||
1564 | } | ||
1565 | else | ||
1566 | { | ||
1567 | return gPipeline.getPool(LLDrawPool::POOL_SIMPLE, imagep); | ||
1568 | } | ||
1569 | } | ||
1570 | |||
1571 | |||
1572 | void LLPipeline::addPool(LLDrawPool *new_poolp) | ||
1573 | { | ||
1574 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
1575 | mPools.insert(new_poolp); | ||
1576 | addToQuickLookup( new_poolp ); | ||
1577 | } | ||
1578 | |||
1579 | void LLPipeline::allocDrawable(LLViewerObject *vobj) | ||
1580 | { | ||
1581 | LLMemType mt(LLMemType::MTYPE_DRAWABLE); | ||
1582 | LLDrawable *drawable = new LLDrawable(); | ||
1583 | vobj->mDrawable = drawable; | ||
1584 | |||
1585 | drawable->mVObjp = vobj; | ||
1586 | |||
1587 | //encompass completely sheared objects by taking | ||
1588 | //the most extreme point possible (<1,1,0.5>) | ||
1589 | drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).magVec()); | ||
1590 | if (vobj->isOrphaned()) | ||
1591 | { | ||
1592 | drawable->setState(LLDrawable::FORCE_INVISIBLE); | ||
1593 | } | ||
1594 | drawable->updateXform(TRUE); | ||
1595 | } | ||
1596 | |||
1597 | |||
1598 | void LLPipeline::unlinkDrawable(LLDrawable *drawablep) | ||
1599 | { | ||
1600 | LLFastTimer t(LLFastTimer::FTM_PIPELINE); | ||
1601 | |||
1602 | // Based on flags, remove the drawable from the queues that it's on. | ||
1603 | if (drawablep->isState(LLDrawable::ON_MOVE_LIST)) | ||
1604 | { | ||
1605 | mMovedList.erase(drawablep); | ||
1606 | } | ||
1607 | |||
1608 | if (drawablep->getSpatialGroup()) | ||
1609 | { | ||
1610 | if (!drawablep->getSpatialGroup()->mSpatialPartition->remove(drawablep, drawablep->getSpatialGroup())) | ||
1611 | { | ||
1612 | #ifdef LL_RELEASE_FOR_DOWNLOAD | ||
1613 | llwarns << "Couldn't remove object from spatial group!" << llendl; | ||
1614 | #else | ||
1615 | llerrs << "Couldn't remove object from spatial group!" << llendl; | ||
1616 | #endif | ||
1617 | } | ||
1618 | } | ||
1619 | |||
1620 | mLights.erase(drawablep); | ||
1621 | } | ||
1622 | |||
1623 | U32 LLPipeline::addObject(LLViewerObject *vobj) | ||
1624 | { | ||
1625 | LLMemType mt(LLMemType::MTYPE_DRAWABLE); | ||
1626 | if (gNoRender) | ||
1627 | { | ||
1628 | return 0; | ||
1629 | } | ||
1630 | |||
1631 | LLDrawable *drawablep = vobj->createDrawable(this); | ||
1632 | |||
1633 | llassert(drawablep); | ||
1634 | |||
1635 | //mCompleteSet.put(drawable); | ||
1636 | //gResyncObjects = TRUE; | ||
1637 | |||
1638 | if (vobj->getParent()) | ||
1639 | { | ||
1640 | vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1 | ||
1641 | } | ||
1642 | else | ||
1643 | { | ||
1644 | vobj->setDrawableParent(NULL); // LLPipeline::addObject 2 | ||
1645 | } | ||
1646 | |||
1647 | |||
1648 | if ((!drawablep->getVOVolume()) && | ||
1649 | (vobj->getPCode() != LLViewerObject::LL_VO_SKY) && | ||
1650 | (vobj->getPCode() != LLViewerObject::LL_VO_STARS) && | ||
1651 | (vobj->getPCode() != LLViewerObject::LL_VO_GROUND)) | ||
1652 | { | ||
1653 | drawablep->getSpatialPartition()->put(drawablep); | ||
1654 | if (!drawablep->getSpatialGroup()) | ||
1655 | { | ||
1656 | #ifdef LL_RELEASE_FOR_DOWNLOAD | ||
1657 | llwarns << "Failure adding drawable to object partition!" << llendl; | ||
1658 | #else | ||
1659 | llerrs << "Failure adding drawable to object partition!" << llendl; | ||
1660 | #endif | ||
1661 | } | ||
1662 | } | ||
1663 | else | ||
1664 | { | ||
1665 | markMoved(drawablep); | ||
1666 | } | ||
1667 | |||
1668 | markMaterialed(drawablep); | ||
1669 | markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE); | ||
1670 | |||
1671 | return 1; | ||
1672 | } | ||
1673 | |||
1674 | |||
1675 | void LLPipeline::resetFrameStats() | ||
1676 | { | ||
1677 | sCompiles = 0; | ||
1678 | mVerticesRelit = 0; | ||
1679 | mLightingChanges = 0; | ||
1680 | mGeometryChanges = 0; | ||
1681 | mNumVisibleFaces = 0; | ||
1682 | } | ||
1683 | |||
1684 | //external functions for asynchronous updating | ||
1685 | void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep) | ||
1686 | { | ||
1687 | if (gSavedSettings.getBOOL("FreezeTime")) | ||
1688 | { | ||
1689 | return; | ||
1690 | } | ||
1691 | if (!drawablep) | ||
1692 | { | ||
1693 | llerrs << "updateMove called with NULL drawablep" << llendl; | ||
1694 | } | ||
1695 | if (drawablep->isState(LLDrawable::EARLY_MOVE)) | ||
1696 | { | ||
1697 | return; | ||
1698 | } | ||
1699 | // update drawable now | ||
1700 | drawablep->clearState(LLDrawable::MOVE_UNDAMPED); // force to DAMPED | ||
1701 | drawablep->updateMove(); // returns done | ||
1702 | drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame | ||
1703 | // Put on move list so that EARLY_MOVE gets cleared | ||
1704 | if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) | ||
1705 | { | ||
1706 | mMovedList.insert(drawablep); | ||
1707 | drawablep->setState(LLDrawable::ON_MOVE_LIST); | ||
1708 | } | ||
1709 | } | ||
1710 | |||
1711 | void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep) | ||
1712 | { | ||
1713 | if (gSavedSettings.getBOOL("FreezeTime")) | ||
1714 | { | ||
1715 | return; | ||
1716 | } | ||
1717 | if (!drawablep) | ||
1718 | { | ||
1719 | llerrs << "updateMove called with NULL drawablep" << llendl; | ||
1720 | } | ||
1721 | if (drawablep->isState(LLDrawable::EARLY_MOVE)) | ||
1722 | { | ||
1723 | return; | ||
1724 | } | ||
1725 | // update drawable now | ||
1726 | drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED | ||
1727 | drawablep->updateMove(); | ||
1728 | drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame | ||
1729 | // Put on move list so that EARLY_MOVE gets cleared | ||
1730 | if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) | ||
1731 | { | ||
1732 | mMovedList.insert(drawablep); | ||
1733 | drawablep->setState(LLDrawable::ON_MOVE_LIST); | ||
1734 | } | ||
1735 | } | ||
1736 | |||
1737 | void LLPipeline::updateMove() | ||
1738 | { | ||
1739 | mObjectPartition->mOctree->validate(); | ||
1740 | LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE); | ||
1741 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
1742 | |||
1743 | if (gSavedSettings.getBOOL("FreezeTime")) | ||
1744 | { | ||
1745 | return; | ||
1746 | } | ||
1747 | |||
1748 | mMoveChangesStat.addValue((F32)mMovedList.size()); | ||
1749 | |||
1750 | for (LLDrawable::drawable_set_t::iterator iter = mMovedList.begin(); | ||
1751 | iter != mMovedList.end(); ) | ||
1752 | { | ||
1753 | LLDrawable::drawable_set_t::iterator curiter = iter++; | ||
1754 | LLDrawable *drawablep = *curiter; | ||
1755 | BOOL done = TRUE; | ||
1756 | if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE))) | ||
1757 | { | ||
1758 | done = drawablep->updateMove(); | ||
1759 | } | ||
1760 | drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED); | ||
1761 | if (done) | ||
1762 | { | ||
1763 | mMovedList.erase(curiter); | ||
1764 | drawablep->clearState(LLDrawable::ON_MOVE_LIST); | ||
1765 | } | ||
1766 | } | ||
1767 | |||
1768 | for (LLDrawable::drawable_set_t::iterator iter = mActiveQ.begin(); | ||
1769 | iter != mActiveQ.end(); ) | ||
1770 | { | ||
1771 | LLDrawable::drawable_set_t::iterator curiter = iter++; | ||
1772 | LLDrawable* drawablep = *curiter; | ||
1773 | if (drawablep && !drawablep->isDead()) | ||
1774 | { | ||
1775 | if (drawablep->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES && | ||
1776 | (!drawablep->getParent() || !drawablep->getParent()->isActive())) | ||
1777 | { | ||
1778 | drawablep->makeStatic(); // removes drawable and its children from mActiveQ | ||
1779 | iter = mActiveQ.upper_bound(drawablep); // next valid entry | ||
1780 | } | ||
1781 | } | ||
1782 | else | ||
1783 | { | ||
1784 | mActiveQ.erase(curiter); | ||
1785 | } | ||
1786 | } | ||
1787 | |||
1788 | for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin(); | ||
1789 | iter != mRetexturedList.end(); ++iter) | ||
1790 | { | ||
1791 | LLDrawable* drawablep = *iter; | ||
1792 | if (drawablep && !drawablep->isDead()) | ||
1793 | { | ||
1794 | drawablep->updateTexture(); | ||
1795 | } | ||
1796 | } | ||
1797 | mRetexturedList.clear(); | ||
1798 | |||
1799 | for (LLDrawable::drawable_set_t::iterator iter = mRematerialedList.begin(); | ||
1800 | iter != mRematerialedList.end(); ++iter) | ||
1801 | { | ||
1802 | LLDrawable* drawablep = *iter; | ||
1803 | if (drawablep && !drawablep->isDead()) | ||
1804 | { | ||
1805 | drawablep->updateMaterial(); | ||
1806 | } | ||
1807 | } | ||
1808 | mRematerialedList.clear(); | ||
1809 | |||
1810 | if (mObjectPartition->mOctree) | ||
1811 | { | ||
1812 | //balance octree | ||
1813 | LLFastTimer ot(LLFastTimer::FTM_OCTREE_BALANCE); | ||
1814 | mObjectPartition->mOctree->validate(); | ||
1815 | mObjectPartition->mOctree->balance(); | ||
1816 | mObjectPartition->mOctree->validate(); | ||
1817 | } | ||
1818 | } | ||
1819 | |||
1820 | ///////////////////////////////////////////////////////////////////////////// | ||
1821 | // Culling and occlusion testing | ||
1822 | ///////////////////////////////////////////////////////////////////////////// | ||
1823 | |||
1824 | void LLPipeline::updateCull() | ||
1825 | { | ||
1826 | LLFastTimer t(LLFastTimer::FTM_CULL); | ||
1827 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
1828 | |||
1829 | LLDrawable::incrementVisible(); | ||
1830 | mVisibleList.resize(0); | ||
1831 | mVisibleList.reserve(ESTIMATED_VISIBLE_OBJECT_COUNT); | ||
1832 | |||
1833 | gTrivialAccepts = 0; | ||
1834 | |||
1835 | if (mObjectPartition) | ||
1836 | { | ||
1837 | if (gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) | ||
1838 | { | ||
1839 | mObjectPartition->processOcclusion(gCamera); | ||
1840 | stop_glerror(); | ||
1841 | } | ||
1842 | mObjectPartition->cull(*gCamera); | ||
1843 | } | ||
1844 | |||
1845 | // Hack for avatars - warning - this is really FRAGILE! - djs 05/06/02 | ||
1846 | LLVOAvatar::updateAllAvatarVisiblity(); | ||
1847 | |||
1848 | // If there are any other hacks here, make sure to add them to the | ||
1849 | // standard pick code. | ||
1850 | |||
1851 | gMinObjectDistance = llclamp(gMinObjectDistance, MIN_NEAR_PLANE, MAX_NEAR_PLANE); | ||
1852 | |||
1853 | F32 water_height = gAgent.getRegion()->getWaterHeight(); | ||
1854 | F32 camera_height = gAgent.getCameraPositionAgent().mV[2]; | ||
1855 | if (fabs(camera_height - water_height) < 2.f) | ||
1856 | { | ||
1857 | gMinObjectDistance = MIN_NEAR_PLANE; | ||
1858 | } | ||
1859 | |||
1860 | gCamera->setNear(gMinObjectDistance); | ||
1861 | |||
1862 | // Disable near clip stuff for now... | ||
1863 | |||
1864 | // now push it back out to max value | ||
1865 | gMinObjectDistance = MIN_NEAR_PLANE; | ||
1866 | |||
1867 | if (gSky.mVOSkyp.notNull() && gSky.mVOSkyp->mDrawable.notNull()) | ||
1868 | { | ||
1869 | // Hack for sky - always visible. | ||
1870 | gSky.mVOSkyp->mDrawable->setVisible(*gCamera); | ||
1871 | mVisibleList.push_back(gSky.mVOSkyp->mDrawable); | ||
1872 | gSky.updateCull(); | ||
1873 | stop_glerror(); | ||
1874 | } | ||
1875 | else | ||
1876 | { | ||
1877 | llinfos << "No sky drawable!" << llendl; | ||
1878 | } | ||
1879 | |||
1880 | if (gSky.mVOGroundp.notNull() && gSky.mVOGroundp->mDrawable.notNull()) | ||
1881 | { | ||
1882 | gSky.mVOGroundp->mDrawable->setVisible(*gCamera); | ||
1883 | mVisibleList.push_back(gSky.mVOGroundp->mDrawable); | ||
1884 | } | ||
1885 | |||
1886 | // add all HUD attachments | ||
1887 | LLVOAvatar* my_avatarp = gAgent.getAvatarObject(); | ||
1888 | if (my_avatarp && my_avatarp->hasHUDAttachment()) | ||
1889 | { | ||
1890 | for (LLViewerJointAttachment* attachmentp = my_avatarp->mAttachmentPoints.getFirstData(); | ||
1891 | attachmentp; | ||
1892 | attachmentp = my_avatarp->mAttachmentPoints.getNextData()) | ||
1893 | { | ||
1894 | if (attachmentp->getIsHUDAttachment() && attachmentp->getObject(0)) | ||
1895 | { | ||
1896 | LLViewerObject* objectp = attachmentp->getObject(0); | ||
1897 | markVisible(objectp->mDrawable); | ||
1898 | objectp->mDrawable->updateDistance(*gCamera); | ||
1899 | for (S32 i = 0; i < (S32)objectp->mChildList.size(); i++) | ||
1900 | { | ||
1901 | LLViewerObject* childp = objectp->mChildList[i]; | ||
1902 | if (childp->mDrawable.notNull()) | ||
1903 | { | ||
1904 | markVisible(childp->mDrawable); | ||
1905 | childp->mDrawable->updateDistance(*gCamera); | ||
1906 | } | ||
1907 | } | ||
1908 | } | ||
1909 | } | ||
1910 | } | ||
1911 | } | ||
1912 | |||
1913 | void LLPipeline::markNotCulled(LLDrawable* drawablep, LLCamera& camera) | ||
1914 | { | ||
1915 | if (drawablep->isVisible()) | ||
1916 | { | ||
1917 | return; | ||
1918 | } | ||
1919 | |||
1920 | // Tricky render mode to hide selected objects, but we definitely | ||
1921 | // don't want to do any unnecessary pointer dereferences. JC | ||
1922 | if (gHideSelectedObjects) | ||
1923 | { | ||
1924 | if (drawablep->getVObj() && drawablep->getVObj()->isSelected()) | ||
1925 | { | ||
1926 | return; | ||
1927 | } | ||
1928 | } | ||
1929 | |||
1930 | if (drawablep && (hasRenderType(drawablep->mRenderType))) | ||
1931 | { | ||
1932 | if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE)) | ||
1933 | { | ||
1934 | mVisibleList.push_back(drawablep); | ||
1935 | drawablep->setVisible(camera, NULL, FALSE); | ||
1936 | } | ||
1937 | else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE)) | ||
1938 | { | ||
1939 | // clear invisible flag here to avoid single frame glitch | ||
1940 | drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE); | ||
1941 | } | ||
1942 | } | ||
1943 | } | ||
1944 | |||
1945 | void LLPipeline::doOcclusion() | ||
1946 | { | ||
1947 | if (gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) | ||
1948 | { | ||
1949 | mObjectPartition->doOcclusion(gCamera); | ||
1950 | } | ||
1951 | } | ||
1952 | |||
1953 | |||
1954 | BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) | ||
1955 | { | ||
1956 | BOOL update_complete = drawablep->updateGeometry(priority); | ||
1957 | if (update_complete) | ||
1958 | { | ||
1959 | drawablep->setState(LLDrawable::BUILT); | ||
1960 | mGeometryChanges++; | ||
1961 | } | ||
1962 | return update_complete; | ||
1963 | } | ||
1964 | |||
1965 | void LLPipeline::updateGeom(F32 max_dtime) | ||
1966 | { | ||
1967 | LLTimer update_timer; | ||
1968 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
1969 | LLPointer<LLDrawable> drawablep; | ||
1970 | |||
1971 | LLFastTimer t(LLFastTimer::FTM_GEO_UPDATE); | ||
1972 | |||
1973 | // notify various object types to reset internal cost metrics, etc. | ||
1974 | // for now, only LLVOVolume does this to throttle LOD changes | ||
1975 | LLVOVolume::preUpdateGeom(); | ||
1976 | |||
1977 | // Iterate through all drawables on the priority build queue, | ||
1978 | for (LLDrawable::drawable_set_t::iterator iter = mBuildQ1.begin(); | ||
1979 | iter != mBuildQ1.end();) | ||
1980 | { | ||
1981 | LLDrawable::drawable_set_t::iterator curiter = iter++; | ||
1982 | LLDrawable* drawablep = *curiter; | ||
1983 | BOOL update_complete = TRUE; | ||
1984 | if (drawablep && !drawablep->isDead()) | ||
1985 | { | ||
1986 | update_complete = updateDrawableGeom(drawablep, TRUE); | ||
1987 | } | ||
1988 | if (update_complete) | ||
1989 | { | ||
1990 | drawablep->clearState(LLDrawable::IN_REBUILD_Q1); | ||
1991 | mBuildQ1.erase(curiter); | ||
1992 | } | ||
1993 | } | ||
1994 | |||
1995 | // Iterate through some drawables on the non-priority build queue | ||
1996 | S32 min_count = 16; | ||
1997 | if (mBuildQ2.size() > 1000) | ||
1998 | { | ||
1999 | min_count = mBuildQ2.size(); | ||
2000 | } | ||
2001 | else | ||
2002 | { | ||
2003 | mBuildQ2.sort(LLDrawable::CompareDistanceGreaterVisibleFirst()); | ||
2004 | } | ||
2005 | |||
2006 | S32 count = 0; | ||
2007 | |||
2008 | max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime); | ||
2009 | |||
2010 | for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin(); | ||
2011 | iter != mBuildQ2.end(); ) | ||
2012 | { | ||
2013 | LLDrawable::drawable_list_t::iterator curiter = iter++; | ||
2014 | LLDrawable* drawablep = *curiter; | ||
2015 | BOOL update_complete = TRUE; | ||
2016 | if (drawablep && !drawablep->isDead()) | ||
2017 | { | ||
2018 | update_complete = updateDrawableGeom(drawablep, FALSE); | ||
2019 | count++; | ||
2020 | } | ||
2021 | if (update_complete) | ||
2022 | { | ||
2023 | drawablep->clearState(LLDrawable::IN_REBUILD_Q2); | ||
2024 | mBuildQ2.erase(curiter); | ||
2025 | } | ||
2026 | if ((update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count) | ||
2027 | { | ||
2028 | break; | ||
2029 | } | ||
2030 | } | ||
2031 | } | ||
2032 | |||
2033 | void LLPipeline::markVisible(LLDrawable *drawablep) | ||
2034 | { | ||
2035 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
2036 | if(!drawablep || drawablep->isDead()) | ||
2037 | { | ||
2038 | llwarns << "LLPipeline::markVisible called with NULL drawablep" << llendl; | ||
2039 | return; | ||
2040 | } | ||
2041 | if (!drawablep->isVisible()) | ||
2042 | { | ||
2043 | drawablep->setVisible(*gCamera); | ||
2044 | mVisibleList.push_back(drawablep); | ||
2045 | } | ||
2046 | } | ||
2047 | |||
2048 | void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion) | ||
2049 | { | ||
2050 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
2051 | if (!drawablep) | ||
2052 | { | ||
2053 | llerrs << "Sending null drawable to moved list!" << llendl; | ||
2054 | return; | ||
2055 | } | ||
2056 | |||
2057 | if (drawablep->isDead()) | ||
2058 | { | ||
2059 | llwarns << "Marking NULL or dead drawable moved!" << llendl; | ||
2060 | return; | ||
2061 | } | ||
2062 | |||
2063 | if (drawablep->getParent()) | ||
2064 | { | ||
2065 | //ensure that parent drawables are moved first | ||
2066 | markMoved(drawablep->getParent(), damped_motion); | ||
2067 | } | ||
2068 | |||
2069 | |||
2070 | if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) | ||
2071 | { | ||
2072 | mMovedList.insert(drawablep); | ||
2073 | drawablep->setState(LLDrawable::ON_MOVE_LIST); | ||
2074 | } | ||
2075 | if (damped_motion == FALSE) | ||
2076 | { | ||
2077 | drawablep->setState(LLDrawable::MOVE_UNDAMPED); // UNDAMPED trumps DAMPED | ||
2078 | } | ||
2079 | else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) | ||
2080 | { | ||
2081 | drawablep->clearState(LLDrawable::MOVE_UNDAMPED); | ||
2082 | } | ||
2083 | } | ||
2084 | |||
2085 | void LLPipeline::markShift(LLDrawable *drawablep) | ||
2086 | { | ||
2087 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
2088 | if (!drawablep || drawablep->isDead()) | ||
2089 | { | ||
2090 | return; | ||
2091 | } | ||
2092 | |||
2093 | if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST)) | ||
2094 | { | ||
2095 | drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE); | ||
2096 | if (drawablep->getParent()) | ||
2097 | { | ||
2098 | markShift(drawablep->getParent()); | ||
2099 | } | ||
2100 | mShiftList.push_back(drawablep); | ||
2101 | drawablep->setState(LLDrawable::ON_SHIFT_LIST); | ||
2102 | } | ||
2103 | } | ||
2104 | |||
2105 | void LLPipeline::shiftObjects(const LLVector3 &offset) | ||
2106 | { | ||
2107 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
2108 | for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); | ||
2109 | iter != mShiftList.end(); iter++) | ||
2110 | { | ||
2111 | LLDrawable *drawablep = *iter; | ||
2112 | if (drawablep->isDead()) | ||
2113 | { | ||
2114 | continue; | ||
2115 | } | ||
2116 | drawablep->shiftPos(offset); | ||
2117 | drawablep->clearState(LLDrawable::ON_SHIFT_LIST); | ||
2118 | } | ||
2119 | mShiftList.resize(0); | ||
2120 | |||
2121 | mObjectPartition->shift(offset); | ||
2122 | } | ||
2123 | |||
2124 | void LLPipeline::markTextured(LLDrawable *drawablep) | ||
2125 | { | ||
2126 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
2127 | if (!drawablep->isDead()) | ||
2128 | { | ||
2129 | mRetexturedList.insert(drawablep); | ||
2130 | } | ||
2131 | } | ||
2132 | |||
2133 | void LLPipeline::markMaterialed(LLDrawable *drawablep) | ||
2134 | { | ||
2135 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
2136 | if (!drawablep->isDead()) | ||
2137 | { | ||
2138 | mRematerialedList.insert(drawablep); | ||
2139 | } | ||
2140 | } | ||
2141 | |||
2142 | void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority) | ||
2143 | { | ||
2144 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
2145 | if (drawablep && !drawablep->isDead()) | ||
2146 | { | ||
2147 | if (!drawablep->isState(LLDrawable::BUILT)) | ||
2148 | { | ||
2149 | priority = TRUE; | ||
2150 | } | ||
2151 | if (priority) | ||
2152 | { | ||
2153 | mBuildQ1.insert(drawablep); | ||
2154 | drawablep->setState(LLDrawable::IN_REBUILD_Q1); // flag is not needed, just for debugging | ||
2155 | } | ||
2156 | else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2)) | ||
2157 | { | ||
2158 | mBuildQ2.push_back(drawablep); | ||
2159 | drawablep->setState(LLDrawable::IN_REBUILD_Q2); // need flag here because it is just a list | ||
2160 | } | ||
2161 | if (flag & LLDrawable::REBUILD_VOLUME) | ||
2162 | { | ||
2163 | drawablep->getVObj()->setChanged(LLXform::SILHOUETTE); | ||
2164 | } | ||
2165 | drawablep->setState(flag); | ||
2166 | if ((flag & LLDrawable::REBUILD_LIGHTING) && drawablep->getLit()) | ||
2167 | { | ||
2168 | if (drawablep->isLight()) | ||
2169 | { | ||
2170 | drawablep->clearState(LLDrawable::LIGHTING_BUILT); | ||
2171 | } | ||
2172 | else | ||
2173 | { | ||
2174 | drawablep->clearState(LLDrawable::LIGHTING_BUILT); | ||
2175 | } | ||
2176 | } | ||
2177 | } | ||
2178 | } | ||
2179 | |||
2180 | void LLPipeline::markRelight(LLDrawable *drawablep, const BOOL priority) | ||
2181 | { | ||
2182 | if (getLightingDetail() >= 2) | ||
2183 | { | ||
2184 | markRebuild(drawablep, LLDrawable::REBUILD_LIGHTING, FALSE); | ||
2185 | } | ||
2186 | } | ||
2187 | |||
2188 | void LLPipeline::stateSort() | ||
2189 | { | ||
2190 | LLFastTimer ftm(LLFastTimer::FTM_STATESORT); | ||
2191 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
2192 | |||
2193 | for (LLDrawable::drawable_vector_t::iterator iter = mVisibleList.begin(); | ||
2194 | iter != mVisibleList.end(); iter++) | ||
2195 | { | ||
2196 | LLDrawable *drawablep = *iter; | ||
2197 | if (drawablep->isDead()) | ||
2198 | { | ||
2199 | continue; | ||
2200 | } | ||
2201 | |||
2202 | if (!drawablep->isActive()) | ||
2203 | { | ||
2204 | drawablep->updateDistance(*gCamera); | ||
2205 | } | ||
2206 | |||
2207 | /* | ||
2208 | if (!drawablep->isState(LLDrawable::BUILT)) | ||
2209 | { | ||
2210 | // This geometry hasn't been rebuilt but it's visible, make sure it gets put on the rebuild list. | ||
2211 | llerrs << "Visible object " << drawablep << ":" << drawablep->getVObj()->getPCodeString(); | ||
2212 | llcont << " visible but not built, put on rebuild" << llendl; | ||
2213 | markRebuild(drawablep); | ||
2214 | continue; | ||
2215 | } | ||
2216 | */ | ||
2217 | |||
2218 | for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin(); | ||
2219 | iter != drawablep->mFaces.end(); iter++) | ||
2220 | { | ||
2221 | LLFace* facep = *iter; | ||
2222 | if (facep->hasGeometry()) | ||
2223 | { | ||
2224 | facep->getPool()->enqueue(facep); | ||
2225 | } | ||
2226 | } | ||
2227 | |||
2228 | if (sRenderPhysicalBeacons) | ||
2229 | { | ||
2230 | // Only show the beacon on the root object. | ||
2231 | LLViewerObject *vobj = drawablep->getVObj(); | ||
2232 | if (vobj | ||
2233 | && !vobj->isAvatar() | ||
2234 | && !vobj->getParent() | ||
2235 | && vobj->usePhysics()) | ||
2236 | { | ||
2237 | gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f)); | ||
2238 | } | ||
2239 | } | ||
2240 | |||
2241 | if (sRenderScriptedBeacons) | ||
2242 | { | ||
2243 | // Only show the beacon on the root object. | ||
2244 | LLViewerObject *vobj = drawablep->getVObj(); | ||
2245 | if (vobj | ||
2246 | && !vobj->isAvatar() | ||
2247 | && !vobj->getParent() | ||
2248 | && vobj->flagScripted()) | ||
2249 | { | ||
2250 | gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f)); | ||
2251 | } | ||
2252 | } | ||
2253 | |||
2254 | if (sRenderParticleBeacons) | ||
2255 | { | ||
2256 | // Look for attachments, objects, etc. | ||
2257 | LLViewerObject *vobj = drawablep->getVObj(); | ||
2258 | if (vobj | ||
2259 | && vobj->isParticleSource()) | ||
2260 | { | ||
2261 | LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f); | ||
2262 | gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f)); | ||
2263 | } | ||
2264 | } | ||
2265 | |||
2266 | // Draw physical objects in red. | ||
2267 | if (gHUDManager->getShowPhysical()) | ||
2268 | { | ||
2269 | LLViewerObject *vobj; | ||
2270 | vobj = drawablep->getVObj(); | ||
2271 | if (vobj && !vobj->isAvatar()) | ||
2272 | { | ||
2273 | if (!vobj->isAvatar() && | ||
2274 | (vobj->usePhysics() || vobj->flagHandleTouch())) | ||
2275 | { | ||
2276 | if (!drawablep->isVisible()) | ||
2277 | { | ||
2278 | // Skip objects that aren't visible. | ||
2279 | continue; | ||
2280 | } | ||
2281 | S32 face_id; | ||
2282 | for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++) | ||
2283 | { | ||
2284 | mHighlightFaces.put(drawablep->getFace(face_id) ); | ||
2285 | } | ||
2286 | } | ||
2287 | } | ||
2288 | } | ||
2289 | |||
2290 | mNumVisibleFaces += drawablep->getNumFaces(); | ||
2291 | } | ||
2292 | |||
2293 | // If god mode, also show audio cues | ||
2294 | if (sRenderSoundBeacons && gAudiop) | ||
2295 | { | ||
2296 | // Update all of our audio sources, clean up dead ones. | ||
2297 | LLAudioEngine::source_map::iterator iter; | ||
2298 | for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter) | ||
2299 | { | ||
2300 | LLAudioSource *sourcep = iter->second; | ||
2301 | |||
2302 | LLVector3d pos_global = sourcep->getPositionGlobal(); | ||
2303 | LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global); | ||
2304 | //pos += LLVector3(0.f, 0.f, 0.2f); | ||
2305 | gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f)); | ||
2306 | } | ||
2307 | } | ||
2308 | |||
2309 | // If managing your telehub, draw beacons at telehub and currently selected spawnpoint. | ||
2310 | if (LLFloaterTelehub::renderBeacons()) | ||
2311 | { | ||
2312 | LLFloaterTelehub::addBeacons(); | ||
2313 | } | ||
2314 | |||
2315 | mSelectedFaces.reset(); | ||
2316 | |||
2317 | // Draw face highlights for selected faces. | ||
2318 | if (gSelectMgr->getTEMode()) | ||
2319 | { | ||
2320 | LLViewerObject *vobjp; | ||
2321 | S32 te; | ||
2322 | gSelectMgr->getFirstTE(&vobjp,&te); | ||
2323 | |||
2324 | while (vobjp) | ||
2325 | { | ||
2326 | LLDrawable *drawablep = vobjp->mDrawable; | ||
2327 | if (!drawablep || drawablep->isDead() || (!vobjp->isHUDAttachment() && !drawablep->isVisible())) | ||
2328 | { | ||
2329 | llwarns << "Dead drawable on selected face list!" << llendl; | ||
2330 | } | ||
2331 | else | ||
2332 | { | ||
2333 | LLVOVolume *volp = drawablep->getVOVolume(); | ||
2334 | if (volp) | ||
2335 | { | ||
2336 | if (volp->getAllTEsSame()) | ||
2337 | { | ||
2338 | SelectedFaceInfo* faceinfo = mSelectedFaces.reserve_block(1); | ||
2339 | faceinfo->mFacep = drawablep->getFace(vobjp->getFaceIndexOffset()); | ||
2340 | faceinfo->mTE = te; | ||
2341 | } | ||
2342 | else | ||
2343 | { | ||
2344 | // This is somewhat inefficient, but works correctly. | ||
2345 | S32 face_id; | ||
2346 | for (face_id = 0; face_id < vobjp->getVolume()->getNumFaces(); face_id++) | ||
2347 | { | ||
2348 | LLFace *facep = drawablep->getFace(face_id + vobjp->getFaceIndexOffset()); | ||
2349 | if (te == facep->getTEOffset()) | ||
2350 | { | ||
2351 | SelectedFaceInfo* faceinfo = mSelectedFaces.reserve_block(1); | ||
2352 | faceinfo->mFacep = facep; | ||
2353 | faceinfo->mTE = -1; | ||
2354 | } | ||
2355 | } | ||
2356 | } | ||
2357 | } | ||
2358 | else | ||
2359 | { | ||
2360 | // This is somewhat inefficient, but works correctly. | ||
2361 | S32 face_id; | ||
2362 | for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++) | ||
2363 | { | ||
2364 | LLFace *facep = drawablep->getFace(face_id + vobjp->getFaceIndexOffset()); | ||
2365 | if (te == facep->getTEOffset()) | ||
2366 | { | ||
2367 | SelectedFaceInfo* faceinfo = mSelectedFaces.reserve_block(1); | ||
2368 | faceinfo->mFacep = facep; | ||
2369 | faceinfo->mTE = -1; | ||
2370 | } | ||
2371 | } | ||
2372 | } | ||
2373 | } | ||
2374 | gSelectMgr->getNextTE(&vobjp,&te); | ||
2375 | } | ||
2376 | } | ||
2377 | } | ||
2378 | |||
2379 | |||
2380 | static void render_hud_elements() | ||
2381 | { | ||
2382 | LLFastTimer t(LLFastTimer::FTM_RENDER_UI); | ||
2383 | gPipeline.disableLights(); | ||
2384 | |||
2385 | gPipeline.renderDebug(); | ||
2386 | |||
2387 | LLGLDisable fog(GL_FOG); | ||
2388 | LLGLSUIDefault gls_ui; | ||
2389 | |||
2390 | if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) | ||
2391 | { | ||
2392 | gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD bersion in render_ui_3d() | ||
2393 | |||
2394 | // Draw the tracking overlays | ||
2395 | LLTracker::render3D(); | ||
2396 | |||
2397 | // Show the property lines | ||
2398 | if (gWorldp) | ||
2399 | { | ||
2400 | gWorldp->renderPropertyLines(); | ||
2401 | } | ||
2402 | if (gParcelMgr) | ||
2403 | { | ||
2404 | gParcelMgr->render(); | ||
2405 | gParcelMgr->renderParcelCollision(); | ||
2406 | } | ||
2407 | |||
2408 | // Render debugging beacons. | ||
2409 | gObjectList.renderObjectBeacons(); | ||
2410 | LLHUDObject::renderAll(); | ||
2411 | gObjectList.resetObjectBeacons(); | ||
2412 | } | ||
2413 | else if (gForceRenderLandFence) | ||
2414 | { | ||
2415 | // This is only set when not rendering the UI, for parcel snapshots | ||
2416 | gParcelMgr->render(); | ||
2417 | } | ||
2418 | |||
2419 | } | ||
2420 | |||
2421 | void LLPipeline::renderHighlights() | ||
2422 | { | ||
2423 | // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) | ||
2424 | // Render highlighted faces. | ||
2425 | LLColor4 color(1.f, 1.f, 1.f, 0.5f); | ||
2426 | LLGLEnable color_mat(GL_COLOR_MATERIAL); | ||
2427 | disableLights(); | ||
2428 | |||
2429 | if ((mVertexShaderLevel[SHADER_INTERFACE] > 0)) | ||
2430 | { | ||
2431 | mHighlightProgram.bind(); | ||
2432 | gPipeline.mHighlightProgram.vertexAttrib4f(LLPipeline::GLSL_MATERIAL_COLOR,1,0,0,0.5f); | ||
2433 | } | ||
2434 | |||
2435 | if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) | ||
2436 | { | ||
2437 | // Make sure the selection image gets downloaded and decoded | ||
2438 | if (!mFaceSelectImagep) | ||
2439 | { | ||
2440 | mFaceSelectImagep = gImageList.getImage(IMG_FACE_SELECT); | ||
2441 | } | ||
2442 | mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); | ||
2443 | |||
2444 | for (S32 i = 0; i < mSelectedFaces.count(); i++) | ||
2445 | { | ||
2446 | LLFace *facep = mSelectedFaces[i].mFacep; | ||
2447 | if (!facep || facep->getDrawable()->isDead()) | ||
2448 | { | ||
2449 | llerrs << "Bad face on selection" << llendl; | ||
2450 | } | ||
2451 | |||
2452 | LLDrawPool* poolp = facep->getPool(); | ||
2453 | |||
2454 | if (!poolp->canUseAGP()) | ||
2455 | { | ||
2456 | unbindAGP(); | ||
2457 | } | ||
2458 | else if (usingAGP()) | ||
2459 | { | ||
2460 | bindAGP(); | ||
2461 | } | ||
2462 | |||
2463 | if (mSelectedFaces[i].mTE == -1) | ||
2464 | { | ||
2465 | // Yes, I KNOW this is stupid... | ||
2466 | poolp->renderFaceSelected(facep, mFaceSelectImagep, color); | ||
2467 | } | ||
2468 | else | ||
2469 | { | ||
2470 | LLVOVolume *volp = (LLVOVolume *)facep->getViewerObject(); | ||
2471 | // Do the special coalesced face mode. | ||
2472 | S32 j; | ||
2473 | S32 offset = 0; | ||
2474 | S32 count = volp->getVolume()->getVolumeFace(0).mIndices.size(); | ||
2475 | for (j = 0; j <= mSelectedFaces[i].mTE; j++) | ||
2476 | { | ||
2477 | count = volp->getVolume()->getVolumeFace(j).mIndices.size(); | ||
2478 | if (j < mSelectedFaces[i].mTE) | ||
2479 | { | ||
2480 | offset += count; | ||
2481 | } | ||
2482 | } | ||
2483 | |||
2484 | poolp->renderFaceSelected(facep, mFaceSelectImagep, color, offset, count); | ||
2485 | } | ||
2486 | } | ||
2487 | } | ||
2488 | |||
2489 | if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) | ||
2490 | { | ||
2491 | // Paint 'em red! | ||
2492 | color.setVec(1.f, 0.f, 0.f, 0.5f); | ||
2493 | for (S32 i = 0; i < mHighlightFaces.count(); i++) | ||
2494 | { | ||
2495 | LLFace* facep = mHighlightFaces[i]; | ||
2496 | LLDrawPool* poolp = facep->getPool(); | ||
2497 | if (!poolp->canUseAGP()) | ||
2498 | { | ||
2499 | unbindAGP(); | ||
2500 | } | ||
2501 | else if (usingAGP()) | ||
2502 | { | ||
2503 | bindAGP(); | ||
2504 | } | ||
2505 | |||
2506 | poolp->renderFaceSelected(facep, LLViewerImage::sNullImagep, color); | ||
2507 | } | ||
2508 | } | ||
2509 | |||
2510 | // Contains a list of the faces of objects that are physical or | ||
2511 | // have touch-handlers. | ||
2512 | mHighlightFaces.reset(); | ||
2513 | |||
2514 | if (mVertexShaderLevel[SHADER_INTERFACE] > 0) | ||
2515 | { | ||
2516 | mHighlightProgram.unbind(); | ||
2517 | } | ||
2518 | } | ||
2519 | |||
2520 | void LLPipeline::renderGeom() | ||
2521 | { | ||
2522 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
2523 | LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY); | ||
2524 | |||
2525 | if (!mAlphaSizzleImagep) | ||
2526 | { | ||
2527 | mAlphaSizzleImagep = gImageList.getImage(LLUUID(gViewerArt.getString("alpha_sizzle.tga")), MIPMAP_TRUE, TRUE); | ||
2528 | } | ||
2529 | |||
2530 | /////////////////////////////////////////// | ||
2531 | // | ||
2532 | // Sync and verify GL state | ||
2533 | // | ||
2534 | // | ||
2535 | |||
2536 | stop_glerror(); | ||
2537 | gFrameStats.start(LLFrameStats::RENDER_SYNC); | ||
2538 | |||
2539 | // Do verification of GL state | ||
2540 | #ifndef LL_RELEASE_FOR_DOWNLOAD | ||
2541 | LLGLState::checkStates(); | ||
2542 | LLGLState::checkTextureChannels(); | ||
2543 | #endif | ||
2544 | if (mRenderDebugMask & RENDER_DEBUG_VERIFY) | ||
2545 | { | ||
2546 | if (!verify()) | ||
2547 | { | ||
2548 | llerrs << "Pipeline verification failed!" << llendl; | ||
2549 | } | ||
2550 | } | ||
2551 | |||
2552 | if (mAGPMemPool) | ||
2553 | { | ||
2554 | mAGPMemPool->waitFence(mGlobalFence); | ||
2555 | } | ||
2556 | |||
2557 | unbindAGP(); | ||
2558 | for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) | ||
2559 | { | ||
2560 | LLDrawPool *poolp = *iter; | ||
2561 | if (hasRenderType(poolp->getType())) | ||
2562 | { | ||
2563 | poolp->prerender(); | ||
2564 | poolp->syncAGP(); | ||
2565 | } | ||
2566 | } | ||
2567 | |||
2568 | gFrameStats.start(LLFrameStats::RENDER_GEOM); | ||
2569 | |||
2570 | // Initialize lots of GL state to "safe" values | ||
2571 | mTrianglesDrawn = 0; | ||
2572 | |||
2573 | glMatrixMode(GL_TEXTURE); | ||
2574 | glLoadIdentity(); | ||
2575 | glMatrixMode(GL_MODELVIEW); | ||
2576 | |||
2577 | LLGLSPipeline gls_pipeline; | ||
2578 | |||
2579 | LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2); | ||
2580 | LLGLState normalize(GL_NORMALIZE, TRUE); | ||
2581 | |||
2582 | // Toggle backface culling for debugging | ||
2583 | LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0); | ||
2584 | // Set fog | ||
2585 | LLGLEnable fog_enable(hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG) ? GL_FOG : 0); | ||
2586 | |||
2587 | |||
2588 | LLViewerImage::sDefaultImagep->bind(0); | ||
2589 | LLViewerImage::sDefaultImagep->setClamp(FALSE, FALSE); | ||
2590 | |||
2591 | ////////////////////////////////////////////// | ||
2592 | // | ||
2593 | // Actually render all of the geometry | ||
2594 | // | ||
2595 | // | ||
2596 | |||
2597 | stop_glerror(); | ||
2598 | BOOL non_agp = FALSE; | ||
2599 | BOOL did_hud_elements = FALSE; | ||
2600 | |||
2601 | U32 cur_type = 0; | ||
2602 | |||
2603 | S32 skipped_vertices = 0; | ||
2604 | { | ||
2605 | LLFastTimer t(LLFastTimer::FTM_POOLS); | ||
2606 | BOOL occlude = TRUE; | ||
2607 | |||
2608 | calcNearbyLights(); | ||
2609 | |||
2610 | pool_set_t::iterator iter1 = mPools.begin(); | ||
2611 | while ( iter1 != mPools.end() ) | ||
2612 | { | ||
2613 | LLDrawPool *poolp = *iter1; | ||
2614 | |||
2615 | cur_type = poolp->getType(); | ||
2616 | |||
2617 | if (cur_type >= LLDrawPool::POOL_TREE && occlude) | ||
2618 | { //all the occluders have been drawn, do occlusion queries | ||
2619 | if (mVertexShadersEnabled) | ||
2620 | { | ||
2621 | glUseProgramObjectARB(0); | ||
2622 | } | ||
2623 | doOcclusion(); | ||
2624 | occlude = FALSE; | ||
2625 | } | ||
2626 | |||
2627 | if (cur_type >= LLDrawPool::POOL_HUD && !did_hud_elements) | ||
2628 | { | ||
2629 | renderHighlights(); | ||
2630 | // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) | ||
2631 | if (mVertexShadersEnabled) | ||
2632 | { | ||
2633 | glUseProgramObjectARB(0); | ||
2634 | } | ||
2635 | render_hud_elements(); | ||
2636 | did_hud_elements = TRUE; | ||
2637 | } | ||
2638 | |||
2639 | pool_set_t::iterator iter2 = iter1; | ||
2640 | if (hasRenderType(poolp->getType())) | ||
2641 | { | ||
2642 | LLFastTimer t(LLFastTimer::FTM_POOLRENDER); | ||
2643 | |||
2644 | setupHWLights(poolp); | ||
2645 | |||
2646 | if (mVertexShadersEnabled && poolp->getVertexShaderLevel() == 0) | ||
2647 | { | ||
2648 | glUseProgramObjectARB(0); | ||
2649 | } | ||
2650 | else if (mVertexShadersEnabled) | ||
2651 | { | ||
2652 | mMaterialIndex = mSpecularIndex = 0; | ||
2653 | switch(cur_type) | ||
2654 | { | ||
2655 | case LLDrawPool::POOL_SKY: | ||
2656 | case LLDrawPool::POOL_STARS: | ||
2657 | case LLDrawPool::POOL_CLOUDS: | ||
2658 | glUseProgramObjectARB(0); | ||
2659 | break; | ||
2660 | case LLDrawPool::POOL_TERRAIN: | ||
2661 | mTerrainProgram.bind(); | ||
2662 | break; | ||
2663 | case LLDrawPool::POOL_GROUND: | ||
2664 | mGroundProgram.bind(); | ||
2665 | break; | ||
2666 | case LLDrawPool::POOL_TREE: | ||
2667 | case LLDrawPool::POOL_TREE_NEW: | ||
2668 | case LLDrawPool::POOL_SIMPLE: | ||
2669 | case LLDrawPool::POOL_MEDIA: | ||
2670 | mObjectSimpleProgram.bind(); | ||
2671 | break; | ||
2672 | case LLDrawPool::POOL_BUMP: | ||
2673 | mObjectBumpProgram.bind(); | ||
2674 | break; | ||
2675 | case LLDrawPool::POOL_AVATAR: | ||
2676 | glUseProgramObjectARB(0); | ||
2677 | break; | ||
2678 | case LLDrawPool::POOL_WATER: | ||
2679 | glUseProgramObjectARB(0); | ||
2680 | break; | ||
2681 | case LLDrawPool::POOL_ALPHA: | ||
2682 | mObjectAlphaProgram.bind(); | ||
2683 | break; | ||
2684 | case LLDrawPool::POOL_HUD: | ||
2685 | default: | ||
2686 | glUseProgramObjectARB(0); | ||
2687 | break; | ||
2688 | } | ||
2689 | } | ||
2690 | |||
2691 | for( S32 i = 0; i < poolp->getNumPasses(); i++ ) | ||
2692 | { | ||
2693 | poolp->beginRenderPass(i); | ||
2694 | for (iter2 = iter1; iter2 != mPools.end(); iter2++) | ||
2695 | { | ||
2696 | LLDrawPool *p = *iter2; | ||
2697 | if (p->getType() != cur_type) | ||
2698 | { | ||
2699 | break; | ||
2700 | } | ||
2701 | if (p->getType() != LLDrawPool::POOL_AVATAR | ||
2702 | && p->getType() != LLDrawPool::POOL_ALPHA | ||
2703 | && p->getType() != LLDrawPool::POOL_HUD | ||
2704 | && (!p->getIndexCount() || !p->getVertexCount())) | ||
2705 | { | ||
2706 | continue; | ||
2707 | } | ||
2708 | |||
2709 | if (p->canUseAGP() && usingAGP()) | ||
2710 | { | ||
2711 | bindAGP(); | ||
2712 | } | ||
2713 | else | ||
2714 | { | ||
2715 | //llinfos << "Rendering pool type " << p->getType() << " without AGP!" << llendl; | ||
2716 | unbindAGP(); | ||
2717 | non_agp = TRUE; | ||
2718 | } | ||
2719 | |||
2720 | p->resetTrianglesDrawn(); | ||
2721 | p->render(i); | ||
2722 | mTrianglesDrawn += p->getTrianglesDrawn(); | ||
2723 | skipped_vertices += p->mSkippedVertices; | ||
2724 | p->mSkippedVertices = 0; | ||
2725 | } | ||
2726 | poolp->endRenderPass(i); | ||
2727 | #ifndef LL_RELEASE_FOR_DOWNLOAD | ||
2728 | LLGLState::checkStates(); | ||
2729 | LLGLState::checkTextureChannels(); | ||
2730 | LLGLState::checkClientArrays(); | ||
2731 | #endif | ||
2732 | } | ||
2733 | } | ||
2734 | else | ||
2735 | { | ||
2736 | // Skip all pools of this type | ||
2737 | for (iter2 = iter1; iter2 != mPools.end(); iter2++) | ||
2738 | { | ||
2739 | LLDrawPool *p = *iter2; | ||
2740 | if (p->getType() != cur_type) | ||
2741 | { | ||
2742 | break; | ||
2743 | } | ||
2744 | } | ||
2745 | } | ||
2746 | iter1 = iter2; | ||
2747 | stop_glerror(); | ||
2748 | } | ||
2749 | |||
2750 | if (occlude) | ||
2751 | { | ||
2752 | if (mVertexShadersEnabled) | ||
2753 | { | ||
2754 | glUseProgramObjectARB(0); | ||
2755 | } | ||
2756 | doOcclusion(); | ||
2757 | } | ||
2758 | } | ||
2759 | stop_glerror(); | ||
2760 | |||
2761 | if (mVertexShadersEnabled) | ||
2762 | { | ||
2763 | glUseProgramObjectARB(0); | ||
2764 | } | ||
2765 | |||
2766 | if (!did_hud_elements) | ||
2767 | { | ||
2768 | renderHighlights(); | ||
2769 | render_hud_elements(); | ||
2770 | } | ||
2771 | |||
2772 | static S32 agp_mix_count = 0; | ||
2773 | if (non_agp && usingAGP()) | ||
2774 | { | ||
2775 | if (0 == agp_mix_count % 16) | ||
2776 | { | ||
2777 | lldebugs << "Mixing AGP and non-AGP pools, slow!" << llendl; | ||
2778 | } | ||
2779 | agp_mix_count++; | ||
2780 | } | ||
2781 | else | ||
2782 | { | ||
2783 | agp_mix_count = 0; | ||
2784 | } | ||
2785 | |||
2786 | // Contains a list of the faces of objects that are physical or | ||
2787 | // have touch-handlers. | ||
2788 | mHighlightFaces.reset(); | ||
2789 | |||
2790 | // This wait is in case we try to do multiple renders of a frame, | ||
2791 | // I don't know what happens when we send a fence multiple times without | ||
2792 | // checking it. | ||
2793 | if (mAGPMemPool) | ||
2794 | { | ||
2795 | mAGPMemPool->waitFence(mGlobalFence); | ||
2796 | mAGPMemPool->sendFence(mGlobalFence); | ||
2797 | } | ||
2798 | } | ||
2799 | |||
2800 | void LLPipeline::renderDebug() | ||
2801 | { | ||
2802 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
2803 | |||
2804 | // Disable all client state | ||
2805 | glDisableClientState(GL_VERTEX_ARRAY); | ||
2806 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
2807 | glDisableClientState(GL_NORMAL_ARRAY); | ||
2808 | glDisableClientState(GL_VERTEX_ARRAY); | ||
2809 | |||
2810 | // Debug stuff. | ||
2811 | mObjectPartition->renderDebug(); | ||
2812 | |||
2813 | if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_LIGHT_TRACE) | ||
2814 | { | ||
2815 | LLGLSNoTexture no_texture; | ||
2816 | |||
2817 | LLVector3 pos, pos1; | ||
2818 | |||
2819 | for (LLDrawable::drawable_vector_t::iterator iter = mVisibleList.begin(); | ||
2820 | iter != mVisibleList.end(); iter++) | ||
2821 | { | ||
2822 | LLDrawable *drawablep = *iter; | ||
2823 | if (drawablep->isDead()) | ||
2824 | { | ||
2825 | continue; | ||
2826 | } | ||
2827 | for (LLDrawable::drawable_set_t::iterator iter = drawablep->mLightSet.begin(); | ||
2828 | iter != drawablep->mLightSet.end(); iter++) | ||
2829 | { | ||
2830 | LLDrawable *targetp = *iter; | ||
2831 | if (targetp->isDead() || !targetp->getVObj()->getNumTEs()) | ||
2832 | { | ||
2833 | continue; | ||
2834 | } | ||
2835 | else | ||
2836 | { | ||
2837 | if (targetp->getTextureEntry(0)) | ||
2838 | { | ||
2839 | if (drawablep->getVObj()->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) | ||
2840 | { | ||
2841 | glColor4f(0.f, 1.f, 0.f, 1.f); | ||
2842 | gObjectList.addDebugBeacon(drawablep->getPositionAgent(), "TC"); | ||
2843 | } | ||
2844 | else | ||
2845 | { | ||
2846 | glColor4fv (targetp->getTextureEntry(0)->getColor().mV); | ||
2847 | } | ||
2848 | glBegin(GL_LINES); | ||
2849 | glVertex3fv(targetp->getPositionAgent().mV); | ||
2850 | glVertex3fv(drawablep->getPositionAgent().mV); | ||
2851 | glEnd(); | ||
2852 | } | ||
2853 | } | ||
2854 | } | ||
2855 | } | ||
2856 | } | ||
2857 | |||
2858 | mCompilesStat.addValue(sCompiles); | ||
2859 | mLightingChangesStat.addValue(mLightingChanges); | ||
2860 | mGeometryChangesStat.addValue(mGeometryChanges); | ||
2861 | mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f); | ||
2862 | mVerticesRelitStat.addValue(mVerticesRelit); | ||
2863 | mNumVisibleFacesStat.addValue(mNumVisibleFaces); | ||
2864 | mNumVisibleDrawablesStat.addValue((S32)mVisibleList.size()); | ||
2865 | |||
2866 | if (gRenderLightGlows) | ||
2867 | { | ||
2868 | displaySSBB(); | ||
2869 | } | ||
2870 | |||
2871 | /*if (mRenderDebugMask & RENDER_DEBUG_BBOXES) | ||
2872 | { | ||
2873 | LLGLSPipelineAlpha gls_pipeline_alpha; | ||
2874 | LLGLSNoTexture no_texture; | ||
2875 | |||
2876 | for (LLDrawable::drawable_vector_t::iterator iter = mVisibleList.begin(); iter != mVisibleList.end(); iter++) | ||
2877 | { | ||
2878 | LLDrawable *drawablep = *iter; | ||
2879 | if (drawablep->isDead()) | ||
2880 | { | ||
2881 | continue; | ||
2882 | } | ||
2883 | LLVector3 min, max; | ||
2884 | |||
2885 | if (drawablep->getVObj() && drawablep->getVObj()->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) | ||
2886 | { | ||
2887 | // Render drawable bbox | ||
2888 | drawablep->getBounds(min, max); | ||
2889 | glColor4f(0.f, 1.f, 0.f, 0.25f); | ||
2890 | render_bbox(min, max); | ||
2891 | |||
2892 | // Render object bbox | ||
2893 | LLVector3 scale = drawablep->getVObj()->getScale(); | ||
2894 | LLVector3 pos = drawablep->getVObj()->getPositionAgent(); | ||
2895 | min = pos - scale * 0.5f; | ||
2896 | max = pos + scale * 0.5f; | ||
2897 | glColor4f(1.f, 0.f, 0.f, 0.25f); | ||
2898 | render_bbox(min, max); | ||
2899 | } | ||
2900 | } | ||
2901 | }*/ | ||
2902 | |||
2903 | /* | ||
2904 | // Debugging code for parcel sound. | ||
2905 | F32 x, y; | ||
2906 | |||
2907 | LLGLSNoTexture gls_no_texture; | ||
2908 | |||
2909 | glBegin(GL_POINTS); | ||
2910 | if (gAgent.getRegion()) | ||
2911 | { | ||
2912 | // Draw the composition layer for the region that I'm in. | ||
2913 | for (x = 0; x <= 260; x++) | ||
2914 | { | ||
2915 | for (y = 0; y <= 260; y++) | ||
2916 | { | ||
2917 | if (gParcelMgr->isSoundLocal(gAgent.getRegion()->getOriginGlobal() + LLVector3d(x, y, 0.f))) | ||
2918 | { | ||
2919 | glColor4f(1.f, 0.f, 0.f, 1.f); | ||
2920 | } | ||
2921 | else | ||
2922 | { | ||
2923 | glColor4f(0.f, 0.f, 1.f, 1.f); | ||
2924 | } | ||
2925 | |||
2926 | glVertex3f(x, y, gAgent.getRegion()->getLandHeightRegion(LLVector3(x, y, 0.f))); | ||
2927 | } | ||
2928 | } | ||
2929 | } | ||
2930 | glEnd(); | ||
2931 | */ | ||
2932 | |||
2933 | if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION) | ||
2934 | { | ||
2935 | // Debug composition layers | ||
2936 | F32 x, y; | ||
2937 | |||
2938 | LLGLSNoTexture gls_no_texture; | ||
2939 | |||
2940 | glBegin(GL_POINTS); | ||
2941 | if (gAgent.getRegion()) | ||
2942 | { | ||
2943 | // Draw the composition layer for the region that I'm in. | ||
2944 | for (x = 0; x <= 260; x++) | ||
2945 | { | ||
2946 | for (y = 0; y <= 260; y++) | ||
2947 | { | ||
2948 | if ((x > 255) || (y > 255)) | ||
2949 | { | ||
2950 | glColor4f(1.f, 0.f, 0.f, 1.f); | ||
2951 | } | ||
2952 | else | ||
2953 | { | ||
2954 | glColor4f(0.f, 0.f, 1.f, 1.f); | ||
2955 | } | ||
2956 | F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y); | ||
2957 | z *= 5.f; | ||
2958 | z += 50.f; | ||
2959 | glVertex3f(x, y, z); | ||
2960 | } | ||
2961 | } | ||
2962 | } | ||
2963 | glEnd(); | ||
2964 | } | ||
2965 | |||
2966 | if (mRenderDebugMask & RENDER_DEBUG_AGP_MEM) | ||
2967 | { | ||
2968 | displayAGP(); | ||
2969 | } | ||
2970 | |||
2971 | if (mRenderDebugMask & RENDER_DEBUG_POOLS) | ||
2972 | { | ||
2973 | displayPools(); | ||
2974 | } | ||
2975 | |||
2976 | // if (mRenderDebugMask & RENDER_DEBUG_QUEUES) | ||
2977 | // { | ||
2978 | // displayQueues(); | ||
2979 | // } | ||
2980 | |||
2981 | if (mRenderDebugMask & RENDER_DEBUG_MAP) | ||
2982 | { | ||
2983 | displayMap(); | ||
2984 | } | ||
2985 | } | ||
2986 | |||
2987 | |||
2988 | |||
2989 | |||
2990 | BOOL compute_min_max(LLMatrix4& box, LLVector2& min, LLVector2& max) | ||
2991 | { | ||
2992 | min.setVec(1000,1000); | ||
2993 | max.setVec(-1000,-1000); | ||
2994 | |||
2995 | if (box.mMatrix[3][3] <= 0.0f) return FALSE; | ||
2996 | |||
2997 | const F32 vec[8][3] = { | ||
2998 | { -0.5f,-0.5f,-0.5f }, | ||
2999 | { -0.5f,-0.5f,+0.5f }, | ||
3000 | { -0.5f,+0.5f,-0.5f }, | ||
3001 | { -0.5f,+0.5f,+0.5f }, | ||
3002 | { +0.5f,-0.5f,-0.5f }, | ||
3003 | { +0.5f,-0.5f,+0.5f }, | ||
3004 | { +0.5f,+0.5f,-0.5f }, | ||
3005 | { +0.5f,+0.5f,+0.5f } }; | ||
3006 | |||
3007 | LLVector4 v; | ||
3008 | |||
3009 | for (S32 i=0;i<8;i++) | ||
3010 | { | ||
3011 | v.setVec(vec[i][0],vec[i][1],vec[i][2],1); | ||
3012 | v = v * box; | ||
3013 | F32 iw = 1.0f / v.mV[3]; | ||
3014 | v.mV[0] *= iw; | ||
3015 | v.mV[1] *= iw; | ||
3016 | |||
3017 | min.mV[0] = llmin(min.mV[0],v.mV[0]); | ||
3018 | max.mV[0] = llmax(max.mV[0],v.mV[0]); | ||
3019 | |||
3020 | min.mV[1] = llmin(min.mV[1],v.mV[1]); | ||
3021 | max.mV[1] = llmax(max.mV[1],v.mV[1]); | ||
3022 | } | ||
3023 | |||
3024 | /* | ||
3025 | min.mV[0] = max.mV[0] = box.mMatrix[3][0]; | ||
3026 | min.mV[1] = max.mV[1] = box.mMatrix[3][1]; | ||
3027 | F32 iw = 1.0f / box.mMatrix[3][3]; | ||
3028 | |||
3029 | F32 f0 = (fabs(box.mMatrix[0][0])+fabs(box.mMatrix[1][0])+fabs(box.mMatrix[2][0])) * 0.5f; | ||
3030 | F32 f1 = (fabs(box.mMatrix[0][1])+fabs(box.mMatrix[1][1])+fabs(box.mMatrix[2][1])) * 0.5f; | ||
3031 | F32 f2 = (fabs(box.mMatrix[0][2])+fabs(box.mMatrix[1][2])+fabs(box.mMatrix[2][2])) * 0.5f; | ||
3032 | |||
3033 | min.mV[0] -= f0; | ||
3034 | min.mV[1] -= f1; | ||
3035 | |||
3036 | max.mV[0] += f0; | ||
3037 | max.mV[1] += f1; | ||
3038 | |||
3039 | min.mV[0] *= iw; | ||
3040 | min.mV[1] *= iw; | ||
3041 | |||
3042 | max.mV[0] *= iw; | ||
3043 | max.mV[1] *= iw; | ||
3044 | */ | ||
3045 | return TRUE; | ||
3046 | } | ||
3047 | |||
3048 | void LLPipeline::displaySSBB() | ||
3049 | { | ||
3050 | LLMatrix4 proj; | ||
3051 | LLMatrix4 cfr(OGL_TO_CFR_ROTATION); | ||
3052 | LLMatrix4 camera; | ||
3053 | LLMatrix4 comb; | ||
3054 | |||
3055 | gCamera->getMatrixToLocal(camera); | ||
3056 | |||
3057 | if (!mBloomImagep) | ||
3058 | { | ||
3059 | mBloomImagep = gImageList.getImage(IMG_BLOOM1); | ||
3060 | } | ||
3061 | |||
3062 | // don't write to depth buffer with light glows so that chat bubbles can pop through | ||
3063 | LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); | ||
3064 | LLViewerImage::bindTexture(mBloomImagep); | ||
3065 | |||
3066 | glGetFloatv(GL_PROJECTION_MATRIX,(float*)proj.mMatrix); | ||
3067 | |||
3068 | glMatrixMode(GL_PROJECTION); | ||
3069 | glPushMatrix(); | ||
3070 | glLoadIdentity(); | ||
3071 | |||
3072 | glMatrixMode(GL_MODELVIEW); | ||
3073 | glPushMatrix(); | ||
3074 | glLoadIdentity(); | ||
3075 | |||
3076 | LLGLSPipelineAlpha gls_pipeline_alpha; | ||
3077 | |||
3078 | //glScalef(0.25,0.25,0.25); | ||
3079 | |||
3080 | S32 sizex = gViewerWindow->getWindowWidth() / 2; | ||
3081 | S32 sizey = gViewerWindow->getWindowHeight() / 2; | ||
3082 | |||
3083 | F32 aspect = (float)sizey / (float)sizex; | ||
3084 | |||
3085 | for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); | ||
3086 | iter != mLights.end(); iter++) | ||
3087 | { | ||
3088 | LLDrawable *lightp = *iter; | ||
3089 | if (lightp->isDead()) | ||
3090 | { | ||
3091 | continue; | ||
3092 | } | ||
3093 | |||
3094 | LLMatrix4 mat = lightp->mXform.getWorldMatrix(); | ||
3095 | |||
3096 | mat *= camera; | ||
3097 | mat *= cfr; | ||
3098 | mat *= proj; | ||
3099 | |||
3100 | U8 color[64]; | ||
3101 | |||
3102 | LLVector2 min,max; | ||
3103 | if (mat.mMatrix[3][3] < 160 && compute_min_max(mat,min,max)) | ||
3104 | { | ||
3105 | F32 cx = (max.mV[0] + min.mV[0]) * 0.5f; | ||
3106 | F32 cy = (max.mV[1] + min.mV[1]) * 0.5f; | ||
3107 | F32 sx = (max.mV[0] - min.mV[0]) * 2.0f; | ||
3108 | F32 sy = (max.mV[1] - min.mV[1]) * 2.0f; | ||
3109 | S32 x = (S32)(cx * (F32)sizex) + sizex; | ||
3110 | S32 y = (S32)(cy * (F32)sizey) + sizey; | ||
3111 | |||
3112 | if (cx > -1 && cx < 1 && cy > -1 && cy < 1) | ||
3113 | { | ||
3114 | glReadPixels(x-2,y-2,4,4,GL_RGBA,GL_UNSIGNED_BYTE,&color[0]); | ||
3115 | |||
3116 | S32 total = 0; | ||
3117 | for (S32 i=0;i<64;i++) | ||
3118 | { | ||
3119 | total += color[i]; | ||
3120 | } | ||
3121 | total /= 64; | ||
3122 | |||
3123 | sx = (sy = (sx + sy) * 0.5f * ((float)total/255.0f)) * aspect; | ||
3124 | |||
3125 | |||
3126 | if (total > 60) | ||
3127 | { | ||
3128 | color[3+32] = total >> 1; | ||
3129 | glBegin(GL_QUADS); | ||
3130 | glColor4ubv(&color[32]); | ||
3131 | glTexCoord2f(0,0); | ||
3132 | glVertex3f(cx-sx,cy-sy,0); | ||
3133 | glTexCoord2f(1,0); | ||
3134 | glVertex3f(cx+sx,cy-sy,0); | ||
3135 | glTexCoord2f(1,1); | ||
3136 | glVertex3f(cx+sx,cy+sy,0); | ||
3137 | glTexCoord2f(0,1); | ||
3138 | glVertex3f(cx-sx,cy+sy,0); | ||
3139 | glEnd(); | ||
3140 | } | ||
3141 | } | ||
3142 | } | ||
3143 | |||
3144 | } | ||
3145 | |||
3146 | // sun | ||
3147 | { | ||
3148 | LLVector4 sdir(gSky.getSunDirection() * 10000.0f + gAgent.getPositionAgent()); | ||
3149 | sdir.mV[3] = 1.0f; | ||
3150 | sdir = sdir * camera; | ||
3151 | sdir = sdir * cfr; | ||
3152 | sdir = sdir * proj; // todo: preconcat | ||
3153 | |||
3154 | sdir.mV[0] /= sdir.mV[3]; | ||
3155 | sdir.mV[1] /= sdir.mV[3]; | ||
3156 | |||
3157 | U8 color[64]; | ||
3158 | |||
3159 | if (sdir.mV[3] > 0) | ||
3160 | { | ||
3161 | F32 cx = sdir.mV[0]; | ||
3162 | F32 cy = sdir.mV[1]; | ||
3163 | F32 sx, sy; | ||
3164 | S32 x = (S32)(cx * (F32)sizex) + sizex; | ||
3165 | S32 y = (S32)(cy * (F32)sizey) + sizey; | ||
3166 | |||
3167 | if (cx > -1 && cx < 1 && cy > -1 && cy < 1) | ||
3168 | { | ||
3169 | glReadPixels(x-2,y-2,4,4,GL_RGBA,GL_UNSIGNED_BYTE,&color[0]); | ||
3170 | |||
3171 | S32 total = 0; | ||
3172 | for (S32 i=0;i<64;i++) | ||
3173 | { | ||
3174 | total += color[i]; | ||
3175 | } | ||
3176 | total >>= 7; | ||
3177 | |||
3178 | sx = (sy = ((float)total/255.0f)) * aspect; | ||
3179 | |||
3180 | const F32 fix = -0.1f; | ||
3181 | |||
3182 | color[32] = (U8)(color[32] * 0.5f + 255 * 0.5f); | ||
3183 | color[33] = (U8)(color[33] * 0.5f + 255 * 0.5f); | ||
3184 | color[34] = (U8)(color[34] * 0.5f + 255 * 0.5f); | ||
3185 | |||
3186 | if (total > 80) | ||
3187 | { | ||
3188 | color[32+3] = (U8)total; | ||
3189 | glBegin(GL_QUADS); | ||
3190 | glColor4ubv(&color[32]); | ||
3191 | glTexCoord2f(0,0); | ||
3192 | glVertex3f(cx-sx,cy-sy+fix,0); | ||
3193 | glTexCoord2f(1,0); | ||
3194 | glVertex3f(cx+sx,cy-sy+fix,0); | ||
3195 | glTexCoord2f(1,1); | ||
3196 | glVertex3f(cx+sx,cy+sy+fix,0); | ||
3197 | glTexCoord2f(0,1); | ||
3198 | glVertex3f(cx-sx,cy+sy+fix,0); | ||
3199 | glEnd(); | ||
3200 | } | ||
3201 | } | ||
3202 | } | ||
3203 | } | ||
3204 | |||
3205 | glMatrixMode(GL_PROJECTION); | ||
3206 | glPopMatrix(); | ||
3207 | glMatrixMode(GL_MODELVIEW); | ||
3208 | glPopMatrix(); | ||
3209 | } | ||
3210 | |||
3211 | void LLPipeline::displayMap() | ||
3212 | { | ||
3213 | LLGLSPipelineAlpha gls_pipeline_alpha; | ||
3214 | LLGLSNoTexture no_texture; | ||
3215 | LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); | ||
3216 | |||
3217 | glMatrixMode(GL_MODELVIEW); | ||
3218 | glPushMatrix(); | ||
3219 | glLoadIdentity(); | ||
3220 | |||
3221 | glMatrixMode(GL_PROJECTION); | ||
3222 | glPushMatrix(); | ||
3223 | glLoadIdentity(); | ||
3224 | |||
3225 | glTranslatef(-1,-1,0); | ||
3226 | glScalef(2,2,0); | ||
3227 | |||
3228 | glColor4f(0,0,0,0.5); | ||
3229 | glBegin(GL_QUADS); | ||
3230 | glVertex3f(0,0,0); | ||
3231 | glVertex3f(1,0,0); | ||
3232 | glVertex3f(1,1,0); | ||
3233 | glVertex3f(0,1,0); | ||
3234 | glEnd(); | ||
3235 | |||
3236 | static F32 totalW = 1.5f; | ||
3237 | static F32 offset = 0.5f; | ||
3238 | static F32 scale = 1.0f; | ||
3239 | |||
3240 | S32 mousex = gViewerWindow->getCurrentMouseX(); | ||
3241 | S32 mousey = gViewerWindow->getCurrentMouseY(); | ||
3242 | S32 w = gViewerWindow->getWindowWidth(); | ||
3243 | S32 h = gViewerWindow->getWindowHeight(); | ||
3244 | |||
3245 | if (mousex < 20 && offset > 0) offset -= (20 - mousex) * 0.02f; | ||
3246 | if (mousex > (w - 20)) offset += (20 - (w - mousex)) * 0.02f; | ||
3247 | if (offset > (totalW-1)) offset = (totalW-1); | ||
3248 | |||
3249 | if (mousey < 20 && scale > 0.1) scale -= (20 - mousey) * 0.001f; | ||
3250 | if (mousey > (h - 20) && scale < 1.0f) scale += (20 - (h - mousey)) * 0.001f; | ||
3251 | |||
3252 | glScalef(scale*scale,scale,1); | ||
3253 | glTranslatef(-offset,0,0); | ||
3254 | //totalW = mStaticTree->render2D(0,0.8f/scale); | ||
3255 | //mDynamicTree->render2D(0,0.4f/scale); | ||
3256 | |||
3257 | glMatrixMode(GL_PROJECTION); | ||
3258 | glPopMatrix(); | ||
3259 | glMatrixMode(GL_MODELVIEW); | ||
3260 | glPopMatrix(); | ||
3261 | } | ||
3262 | |||
3263 | void LLPipeline::renderForSelect() | ||
3264 | { | ||
3265 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
3266 | //for each drawpool | ||
3267 | |||
3268 | glMatrixMode(GL_MODELVIEW); | ||
3269 | |||
3270 | LLGLSDefault gls_default; | ||
3271 | LLGLSObjectSelect gls_object_select; | ||
3272 | LLGLDepthTest gls_depth(GL_TRUE); | ||
3273 | disableLights(); | ||
3274 | |||
3275 | glEnableClientState ( GL_VERTEX_ARRAY ); | ||
3276 | glDisableClientState( GL_NORMAL_ARRAY ); | ||
3277 | glDisableClientState( GL_TEXTURE_COORD_ARRAY ); | ||
3278 | |||
3279 | #ifndef LL_RELEASE_FOR_DOWNLOAD | ||
3280 | LLGLState::checkStates(); | ||
3281 | LLGLState::checkTextureChannels(); | ||
3282 | LLGLState::checkClientArrays(); | ||
3283 | U32 last_type = 0; | ||
3284 | #endif | ||
3285 | for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) | ||
3286 | { | ||
3287 | LLDrawPool *poolp = *iter; | ||
3288 | if (poolp->canUseAGP() && usingAGP()) | ||
3289 | { | ||
3290 | bindAGP(); | ||
3291 | } | ||
3292 | else | ||
3293 | { | ||
3294 | //llinfos << "Rendering pool type " << p->getType() << " without AGP!" << llendl; | ||
3295 | unbindAGP(); | ||
3296 | } | ||
3297 | poolp->renderForSelect(); | ||
3298 | #ifndef LL_RELEASE_FOR_DOWNLOAD | ||
3299 | if (poolp->getType() != last_type) | ||
3300 | { | ||
3301 | last_type = poolp->getType(); | ||
3302 | LLGLState::checkStates(); | ||
3303 | LLGLState::checkTextureChannels(); | ||
3304 | LLGLState::checkClientArrays(); | ||
3305 | } | ||
3306 | #endif | ||
3307 | } | ||
3308 | |||
3309 | // Disable all of the client state | ||
3310 | glDisableClientState( GL_VERTEX_ARRAY ); | ||
3311 | |||
3312 | if (mAGPMemPool) | ||
3313 | { | ||
3314 | mAGPMemPool->waitFence(mGlobalFence); | ||
3315 | mAGPMemPool->sendFence(mGlobalFence); | ||
3316 | } | ||
3317 | } | ||
3318 | |||
3319 | void LLPipeline::renderFaceForUVSelect(LLFace* facep) | ||
3320 | { | ||
3321 | if (facep) facep->renderSelectedUV(); | ||
3322 | } | ||
3323 | |||
3324 | void LLPipeline::rebuildPools() | ||
3325 | { | ||
3326 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
3327 | S32 max_count = mPools.size(); | ||
3328 | S32 num_rebuilds = 0; | ||
3329 | pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool); | ||
3330 | while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS) | ||
3331 | { | ||
3332 | if (iter1 == mPools.end()) | ||
3333 | { | ||
3334 | iter1 = mPools.begin(); | ||
3335 | } | ||
3336 | LLDrawPool* poolp = *iter1; | ||
3337 | num_rebuilds += poolp->rebuild(); | ||
3338 | if (poolp->mReferences.empty()) | ||
3339 | { | ||
3340 | mPools.erase(iter1++); | ||
3341 | removeFromQuickLookup( poolp ); | ||
3342 | if (poolp == mLastRebuildPool) | ||
3343 | { | ||
3344 | mLastRebuildPool = NULL; | ||
3345 | } | ||
3346 | delete poolp; | ||
3347 | } | ||
3348 | else | ||
3349 | { | ||
3350 | mLastRebuildPool = poolp; | ||
3351 | iter1++; | ||
3352 | } | ||
3353 | max_count--; | ||
3354 | } | ||
3355 | |||
3356 | if (gAgent.getAvatarObject()) | ||
3357 | { | ||
3358 | gAgent.getAvatarObject()->rebuildHUD(); | ||
3359 | } | ||
3360 | } | ||
3361 | |||
3362 | void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) | ||
3363 | { | ||
3364 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
3365 | switch( new_poolp->getType() ) | ||
3366 | { | ||
3367 | case LLDrawPool::POOL_SIMPLE: | ||
3368 | mSimplePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; | ||
3369 | break; | ||
3370 | |||
3371 | case LLDrawPool::POOL_TREE: | ||
3372 | mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; | ||
3373 | break; | ||
3374 | |||
3375 | case LLDrawPool::POOL_TREE_NEW: | ||
3376 | mTreeNewPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; | ||
3377 | break; | ||
3378 | |||
3379 | case LLDrawPool::POOL_TERRAIN: | ||
3380 | mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; | ||
3381 | break; | ||
3382 | |||
3383 | case LLDrawPool::POOL_BUMP: | ||
3384 | mBumpPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; | ||
3385 | break; | ||
3386 | |||
3387 | case LLDrawPool::POOL_MEDIA: | ||
3388 | mMediaPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; | ||
3389 | break; | ||
3390 | |||
3391 | case LLDrawPool::POOL_ALPHA: | ||
3392 | if( mAlphaPool ) | ||
3393 | { | ||
3394 | llassert(0); | ||
3395 | llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl; | ||
3396 | } | ||
3397 | else | ||
3398 | { | ||
3399 | mAlphaPool = new_poolp; | ||
3400 | } | ||
3401 | break; | ||
3402 | |||
3403 | case LLDrawPool::POOL_AVATAR: | ||
3404 | break; // Do nothing | ||
3405 | |||
3406 | case LLDrawPool::POOL_SKY: | ||
3407 | if( mSkyPool ) | ||
3408 | { | ||
3409 | llassert(0); | ||
3410 | llwarns << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << llendl; | ||
3411 | } | ||
3412 | else | ||
3413 | { | ||
3414 | mSkyPool = new_poolp; | ||
3415 | } | ||
3416 | break; | ||
3417 | |||
3418 | case LLDrawPool::POOL_STARS: | ||
3419 | if( mStarsPool ) | ||
3420 | { | ||
3421 | llassert(0); | ||
3422 | llwarns << "LLPipeline::addPool(): Ignoring duplicate Stars pool" << llendl; | ||
3423 | } | ||
3424 | else | ||
3425 | { | ||
3426 | mStarsPool = new_poolp; | ||
3427 | } | ||
3428 | break; | ||
3429 | |||
3430 | case LLDrawPool::POOL_CLOUDS: | ||
3431 | if( mCloudsPool ) | ||
3432 | { | ||
3433 | llassert(0); | ||
3434 | llwarns << "LLPipeline::addPool(): Ignoring duplicate Clouds pool" << llendl; | ||
3435 | } | ||
3436 | else | ||
3437 | { | ||
3438 | mCloudsPool = new_poolp; | ||
3439 | } | ||
3440 | break; | ||
3441 | |||
3442 | case LLDrawPool::POOL_WATER: | ||
3443 | if( mWaterPool ) | ||
3444 | { | ||
3445 | llassert(0); | ||
3446 | llwarns << "LLPipeline::addPool(): Ignoring duplicate Water pool" << llendl; | ||
3447 | } | ||
3448 | else | ||
3449 | { | ||
3450 | mWaterPool = new_poolp; | ||
3451 | } | ||
3452 | break; | ||
3453 | |||
3454 | case LLDrawPool::POOL_GROUND: | ||
3455 | if( mGroundPool ) | ||
3456 | { | ||
3457 | llassert(0); | ||
3458 | llwarns << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << llendl; | ||
3459 | } | ||
3460 | else | ||
3461 | { | ||
3462 | mGroundPool = new_poolp; | ||
3463 | } | ||
3464 | break; | ||
3465 | |||
3466 | case LLDrawPool::POOL_HUD: | ||
3467 | if( mHUDPool ) | ||
3468 | { | ||
3469 | llerrs << "LLPipeline::addPool(): Duplicate HUD Pool!" << llendl; | ||
3470 | } | ||
3471 | mHUDPool = new_poolp; | ||
3472 | break; | ||
3473 | |||
3474 | default: | ||
3475 | llassert(0); | ||
3476 | llwarns << "Invalid Pool Type in LLPipeline::addPool()" << llendl; | ||
3477 | break; | ||
3478 | } | ||
3479 | } | ||
3480 | |||
3481 | void LLPipeline::removePool( LLDrawPool* poolp ) | ||
3482 | { | ||
3483 | removeFromQuickLookup(poolp); | ||
3484 | mPools.erase(poolp); | ||
3485 | delete poolp; | ||
3486 | } | ||
3487 | |||
3488 | void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) | ||
3489 | { | ||
3490 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
3491 | switch( poolp->getType() ) | ||
3492 | { | ||
3493 | case LLDrawPool::POOL_SIMPLE: | ||
3494 | #ifdef _DEBUG | ||
3495 | { | ||
3496 | BOOL found = mSimplePools.erase( (uintptr_t)poolp->getTexture() ); | ||
3497 | llassert( found ); | ||
3498 | } | ||
3499 | #else | ||
3500 | mSimplePools.erase( (uintptr_t)poolp->getTexture() ); | ||
3501 | #endif | ||
3502 | break; | ||
3503 | |||
3504 | case LLDrawPool::POOL_TREE: | ||
3505 | #ifdef _DEBUG | ||
3506 | { | ||
3507 | BOOL found = mTreePools.erase( (uintptr_t)poolp->getTexture() ); | ||
3508 | llassert( found ); | ||
3509 | } | ||
3510 | #else | ||
3511 | mTreePools.erase( (uintptr_t)poolp->getTexture() ); | ||
3512 | #endif | ||
3513 | break; | ||
3514 | |||
3515 | case LLDrawPool::POOL_TREE_NEW: | ||
3516 | #ifdef _DEBUG | ||
3517 | { | ||
3518 | BOOL found = mTreeNewPools.erase( (uintptr_t)poolp->getTexture() ); | ||
3519 | llassert( found ); | ||
3520 | } | ||
3521 | #else | ||
3522 | mTreeNewPools.erase( (uintptr_t)poolp->getTexture() ); | ||
3523 | #endif | ||
3524 | break; | ||
3525 | |||
3526 | case LLDrawPool::POOL_TERRAIN: | ||
3527 | #ifdef _DEBUG | ||
3528 | { | ||
3529 | BOOL found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); | ||
3530 | llassert( found ); | ||
3531 | } | ||
3532 | #else | ||
3533 | mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); | ||
3534 | #endif | ||
3535 | break; | ||
3536 | |||
3537 | case LLDrawPool::POOL_BUMP: | ||
3538 | #ifdef _DEBUG | ||
3539 | { | ||
3540 | BOOL found = mBumpPools.erase( (uintptr_t)poolp->getTexture() ); | ||
3541 | llassert( found ); | ||
3542 | } | ||
3543 | #else | ||
3544 | mBumpPools.erase( (uintptr_t)poolp->getTexture() ); | ||
3545 | #endif | ||
3546 | break; | ||
3547 | |||
3548 | case LLDrawPool::POOL_MEDIA: | ||
3549 | #ifdef _DEBUG | ||
3550 | { | ||
3551 | BOOL found = mMediaPools.erase( (uintptr_t)poolp->getTexture() ); | ||
3552 | llassert( found ); | ||
3553 | } | ||
3554 | #else | ||
3555 | mMediaPools.erase( (uintptr_t)poolp->getTexture() ); | ||
3556 | #endif | ||
3557 | break; | ||
3558 | |||
3559 | case LLDrawPool::POOL_ALPHA: | ||
3560 | llassert( poolp == mAlphaPool ); | ||
3561 | mAlphaPool = NULL; | ||
3562 | break; | ||
3563 | |||
3564 | case LLDrawPool::POOL_AVATAR: | ||
3565 | break; // Do nothing | ||
3566 | |||
3567 | case LLDrawPool::POOL_SKY: | ||
3568 | llassert( poolp == mSkyPool ); | ||
3569 | mSkyPool = NULL; | ||
3570 | break; | ||
3571 | |||
3572 | case LLDrawPool::POOL_STARS: | ||
3573 | llassert( poolp == mStarsPool ); | ||
3574 | mStarsPool = NULL; | ||
3575 | break; | ||
3576 | |||
3577 | case LLDrawPool::POOL_CLOUDS: | ||
3578 | llassert( poolp == mCloudsPool ); | ||
3579 | mCloudsPool = NULL; | ||
3580 | break; | ||
3581 | |||
3582 | case LLDrawPool::POOL_WATER: | ||
3583 | llassert( poolp == mWaterPool ); | ||
3584 | mWaterPool = NULL; | ||
3585 | break; | ||
3586 | |||
3587 | case LLDrawPool::POOL_GROUND: | ||
3588 | llassert( poolp == mGroundPool ); | ||
3589 | mGroundPool = NULL; | ||
3590 | break; | ||
3591 | |||
3592 | case LLDrawPool::POOL_HUD: | ||
3593 | llassert( poolp == mHUDPool ); | ||
3594 | mHUDPool = NULL; | ||
3595 | break; | ||
3596 | |||
3597 | default: | ||
3598 | llassert(0); | ||
3599 | llwarns << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl; | ||
3600 | break; | ||
3601 | } | ||
3602 | } | ||
3603 | |||
3604 | void LLPipeline::flushAGPMemory() | ||
3605 | { | ||
3606 | LLMemType mt(LLMemType::MTYPE_PIPELINE); | ||
3607 | |||
3608 | for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) | ||
3609 | { | ||
3610 | LLDrawPool *poolp = *iter; | ||
3611 | poolp->flushAGP(); | ||
3612 | } | ||
3613 | } | ||
3614 | |||
3615 | void LLPipeline::resetDrawOrders() | ||
3616 | { | ||
3617 | // Iterate through all of the draw pools and rebuild them. | ||
3618 | for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) | ||
3619 | { | ||
3620 | LLDrawPool *poolp = *iter; | ||
3621 | poolp->resetDrawOrders(); | ||
3622 | } | ||
3623 | } | ||
3624 | |||
3625 | //------------------------------- | ||
3626 | |||
3627 | |||
3628 | LLViewerObject *LLPipeline::nearestObjectAt(F32 yaw, F32 pitch) | ||
3629 | { | ||
3630 | // Stub to find nearest Object at given yaw and pitch | ||
3631 | |||
3632 | /* | ||
3633 | LLEdge *vd = NULL; | ||
3634 | |||
3635 | if (vd) | ||
3636 | { | ||
3637 | return (LLViewerObject*)vd->mDrawablep->getVObj(); | ||
3638 | } | ||
3639 | */ | ||
3640 | |||
3641 | return NULL; | ||
3642 | } | ||
3643 | |||
3644 | void LLPipeline::printPools() | ||
3645 | { | ||
3646 | /* | ||
3647 | // Iterate through all of the draw pools and rebuild them. | ||
3648 | for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) | ||
3649 | { | ||
3650 | LLDrawPool *poolp = *iter; | ||
3651 | if (pool->mTexturep[0]) | ||
3652 | { | ||
3653 | llinfos << "Op pool " << pool->mTexturep[0]->mID << llendflush; | ||
3654 | } | ||
3655 | else | ||
3656 | { | ||
3657 | llinfos << "Opaque pool NULL" << llendflush; | ||
3658 | } | ||
3659 | llinfos << " Vertices: \t" << pool->getVertexCount() << llendl; | ||
3660 | } | ||
3661 | |||
3662 | |||
3663 | for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) | ||
3664 | { | ||
3665 | LLDrawPool *poolp = *iter; | ||
3666 | llinfos << "Al pool " << pool; | ||
3667 | llcont << " Vertices: \t" << pool->getVertexCount() << llendl; | ||
3668 | } | ||
3669 | |||
3670 | pool = mHighlightPools.getFirst(); | ||
3671 | llinfos << "Si pool " << pool; | ||
3672 | llcont << " Vertices: \t" << pool->getVertexCount() << llendl; | ||
3673 | */ | ||
3674 | } | ||
3675 | |||
3676 | |||
3677 | void LLPipeline::displayPools() | ||
3678 | { | ||
3679 | // Needs to be fixed to handle chained pools - djs | ||
3680 | LLUI::setLineWidth(1.0); | ||
3681 | glMatrixMode(GL_PROJECTION); | ||
3682 | glPushMatrix(); | ||
3683 | glLoadIdentity(); | ||
3684 | glMatrixMode(GL_MODELVIEW); | ||
3685 | glPushMatrix(); | ||
3686 | glLoadIdentity(); | ||
3687 | |||
3688 | LLGLSPipelineAlpha gls_pipeline_alpha; | ||
3689 | LLGLSNoTexture no_texture; | ||
3690 | LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); | ||
3691 | |||
3692 | glScalef(2,2,1); | ||
3693 | glTranslatef(-0.5f,-0.5f,0); | ||
3694 | |||
3695 | F32 x = 0.0f, y = 0.05f; | ||
3696 | F32 xs = 0.01f, ys = 0.01f; | ||
3697 | F32 xs2 = xs*0.1f, ys2 = ys * 0.1f; | ||
3698 | |||
3699 | for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) | ||
3700 | { | ||
3701 | LLGLSTexture gls_texture; | ||
3702 | LLDrawPool *poolp = *iter; | ||
3703 | if (poolp->getDebugTexture()) | ||
3704 | { | ||
3705 | poolp->getDebugTexture()->bind(); | ||
3706 | glColor4f(1,1,1,1); | ||
3707 | stamp(x,y,xs*4,ys*4); | ||
3708 | } | ||
3709 | |||
3710 | LLGLSNoTexture no_texture; | ||
3711 | |||
3712 | F32 a = 1.f - (F32)poolp->mRebuildTime / (F32)poolp->mRebuildFreq; | ||
3713 | glColor4f(a,a,a,1); | ||
3714 | stamp(x,y,xs,ys); | ||
3715 | |||
3716 | x = (xs + xs2) * 4.0f; | ||
3717 | |||
3718 | F32 h = ys * 0.5f; | ||
3719 | |||
3720 | S32 total = 0; | ||
3721 | |||
3722 | for (std::vector<LLFace*>::iterator iter = poolp->mReferences.begin(); | ||
3723 | iter != poolp->mReferences.end(); iter++) | ||
3724 | { | ||
3725 | LLFace *face = *iter; | ||
3726 | F32 w = xs; | ||
3727 | |||
3728 | if (!face || !face->getDrawable()) | ||
3729 | { | ||
3730 | w = 16 / 3000.0f; | ||
3731 | |||
3732 | stamp(x,y,w,h); | ||
3733 | |||
3734 | if (x+w > 0.95f) | ||
3735 | { | ||
3736 | x = (xs + xs2) * 4.0f; | ||
3737 | y += h + ys2; | ||
3738 | } | ||
3739 | else | ||
3740 | { | ||
3741 | if (w) x += w + xs2; | ||
3742 | } | ||
3743 | |||
3744 | continue; | ||
3745 | } | ||
3746 | |||
3747 | if (face->getDrawable()->isVisible()) | ||
3748 | { | ||
3749 | if (face->isState(LLFace::BACKLIST)) | ||
3750 | { | ||
3751 | glColor4f(1,0,1,1); | ||
3752 | } | ||
3753 | else if (total > poolp->getMaxVertices()) | ||
3754 | { | ||
3755 | glColor4f(1,0,0,1); | ||
3756 | } | ||
3757 | else | ||
3758 | { | ||
3759 | glColor4f(0,1,0,1); | ||
3760 | total += face->getGeomCount(); | ||
3761 | } | ||
3762 | } | ||
3763 | else | ||
3764 | { | ||
3765 | if (face->isState(LLFace::BACKLIST)) | ||
3766 | { | ||
3767 | glColor4f(0,0,1,1); | ||
3768 | } | ||
3769 | else | ||
3770 | { | ||
3771 | glColor4f(1,1,0,1); | ||
3772 | } | ||
3773 | } | ||
3774 | |||
3775 | w = face->getGeomCount() / 3000.0f; | ||
3776 | |||
3777 | stamp(x,y,w,h); | ||
3778 | |||
3779 | if (x+w > 0.95f) | ||
3780 | { | ||
3781 | x = (xs + xs2) * 4.0f; | ||
3782 | y += h + ys2; | ||
3783 | } | ||
3784 | else | ||
3785 | { | ||
3786 | if (w) x += w + xs2; | ||
3787 | } | ||
3788 | } | ||
3789 | |||
3790 | y += ys + ys2; | ||
3791 | x = 0; | ||
3792 | } | ||
3793 | |||
3794 | glPopMatrix(); | ||
3795 | glMatrixMode(GL_PROJECTION); | ||
3796 | glPopMatrix(); | ||
3797 | glMatrixMode(GL_MODELVIEW); | ||
3798 | } | ||
3799 | |||
3800 | static F32 xs = 0.01f, ys = 0.01f; | ||
3801 | static F32 xs2 = xs*0.1f, ys2 = ys * 0.1f; | ||
3802 | static F32 winx, winy; | ||
3803 | |||
3804 | void displayDrawable(F32 &x, F32 &y, LLDrawable *drawable, F32 alpha = 0.5f) | ||
3805 | { | ||
3806 | F32 w = 0; | ||
3807 | F32 h = ys * 0.5f; | ||
3808 | |||
3809 | if (drawable && !drawable->isDead()) | ||
3810 | { | ||
3811 | for (S32 f=0;f < drawable->getNumFaces(); f++) | ||
3812 | { | ||
3813 | w += drawable->getFace(f)->getGeomCount() / 30000.0f; | ||
3814 | } | ||
3815 | w+=xs; | ||
3816 | glColor4f(1,1,0, alpha); | ||
3817 | } | ||
3818 | else | ||
3819 | { | ||
3820 | w = 0.01f; | ||
3821 | glColor4f(0,0,0,alpha); | ||
3822 | } | ||
3823 | |||
3824 | // const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF_SMALL ); | ||
3825 | |||
3826 | // U8 pcode = drawable->getVObj()->getPCode(); | ||
3827 | |||
3828 | //char *string = (char*)LLPrimitive::pCodeToString(pcode); | ||
3829 | //if (pcode == 0x3e) string = "terrain"; | ||
3830 | //else if (pcode == 0x2e) string = "cloud"; | ||
3831 | //string[3] = 0; | ||
3832 | |||
3833 | stamp(x * winx,y * winy,w * winx,h * winy); | ||
3834 | |||
3835 | /* | ||
3836 | glColor4f(0,0,0,1); | ||
3837 | font->render(string,x*winx+1,y*winy+1); | ||
3838 | LLGLSNoTexture no_texture; | ||
3839 | */ | ||
3840 | |||
3841 | if (x+w > 0.95f) | ||
3842 | { | ||
3843 | x = (xs + xs2) * 4.0f; | ||
3844 | y += h + ys2; | ||
3845 | } | ||
3846 | else | ||
3847 | { | ||
3848 | if (w) x += w + xs2; | ||
3849 | } | ||
3850 | |||
3851 | } | ||
3852 | |||
3853 | #if 0 // No longer up date | ||
3854 | |||
3855 | void displayQueue(F32 &x, F32 &y, LLDynamicArray<LLDrawable*>& processed, LLDynamicQueuePtr<LLPointer<LLDrawable> >& remaining) | ||
3856 | { | ||
3857 | S32 i; | ||
3858 | for (i=0;i<processed.count();i++) | ||
3859 | { | ||
3860 | displayDrawable(x,y,processed[i],1); | ||
3861 | } | ||
3862 | |||
3863 | x += xs * 2; | ||
3864 | |||
3865 | S32 count = remaining.count(); | ||
3866 | for (i=0;i<count;i++) | ||
3867 | { | ||
3868 | LLDrawable* drawablep = remaining[(i + remaining.getFirst()) % remaining.getMax()]; | ||
3869 | if (drawablep && !drawablep->isDead()) | ||
3870 | { | ||
3871 | displayDrawable(x,y,drawable,0.5); | ||
3872 | } | ||
3873 | } | ||
3874 | |||
3875 | y += ys * 4; | ||
3876 | x = (xs + xs2) * 4.0f; | ||
3877 | |||
3878 | } | ||
3879 | |||
3880 | void LLPipeline::displayQueues() | ||
3881 | { | ||
3882 | LLUI::setLineWidth(1.0); | ||
3883 | glMatrixMode(GL_PROJECTION); | ||
3884 | glPushMatrix(); | ||
3885 | glLoadIdentity(); | ||
3886 | glMatrixMode(GL_MODELVIEW); | ||
3887 | glPushMatrix(); | ||
3888 | glLoadIdentity(); | ||
3889 | |||
3890 | LLGLSPipelineAlpha gls_pipeline_alpha; | ||
3891 | LLGLSNoTexture no_texture; | ||
3892 | LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); | ||
3893 | |||
3894 | glScalef(2,2,1); | ||
3895 | glTranslatef(-0.5f,-0.5f,0); | ||
3896 | |||
3897 | winx = (F32)gViewerWindow->getWindowWidth(); | ||
3898 | winy = (F32)gViewerWindow->getWindowHeight(); | ||
3899 | |||
3900 | glScalef(1.0f/winx,1.0f/winy,1); | ||
3901 | |||
3902 | F32 x = (xs + xs2) * 4.0f; | ||
3903 | F32 y = 0.1f; | ||
3904 | |||
3905 | const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF ); | ||
3906 | |||
3907 | font->renderUTF8("Build1", 0,0,(S32)(y*winy),LLColor4(1,1,1,1)); | ||
3908 | displayQueue(x,y, gBuildProcessed, mBuildQ1); | ||
3909 | |||
3910 | glPopMatrix(); | ||
3911 | glMatrixMode(GL_PROJECTION); | ||
3912 | glPopMatrix(); | ||
3913 | glMatrixMode(GL_MODELVIEW); | ||
3914 | |||
3915 | } | ||
3916 | |||
3917 | #endif | ||
3918 | |||
3919 | // static | ||
3920 | void render_bbox(const LLVector3 &min, const LLVector3 &max) | ||
3921 | { | ||
3922 | S32 i; | ||
3923 | LLVector3 verticesp[16]; | ||
3924 | |||
3925 | verticesp[0].setVec(min.mV[0],min.mV[1],max.mV[2]); | ||
3926 | verticesp[1].setVec(min.mV[0],min.mV[1],min.mV[2]); | ||
3927 | verticesp[2].setVec(min.mV[0],max.mV[1],min.mV[2]); | ||
3928 | verticesp[3].setVec(min.mV[0],max.mV[1],max.mV[2]); | ||
3929 | verticesp[4].setVec(max.mV[0],max.mV[1],max.mV[2]); | ||
3930 | verticesp[5].setVec(max.mV[0],max.mV[1],min.mV[2]); | ||
3931 | verticesp[6].setVec(max.mV[0],min.mV[1],min.mV[2]); | ||
3932 | verticesp[7].setVec(max.mV[0],min.mV[1],max.mV[2]); | ||
3933 | verticesp[8 ] = verticesp[0]; | ||
3934 | verticesp[9 ] = verticesp[1]; | ||
3935 | verticesp[10] = verticesp[6]; | ||
3936 | verticesp[11] = verticesp[7]; | ||
3937 | verticesp[12] = verticesp[4]; | ||
3938 | verticesp[13] = verticesp[5]; | ||
3939 | verticesp[14] = verticesp[2]; | ||
3940 | verticesp[15] = verticesp[3]; | ||
3941 | |||
3942 | LLGLSNoTexture gls_no_texture; | ||
3943 | { | ||
3944 | LLUI::setLineWidth(1.f); | ||
3945 | glBegin(GL_LINE_LOOP); | ||
3946 | for (i = 0; i < 16; i++) | ||
3947 | { | ||
3948 | glVertex3fv(verticesp[i].mV); | ||
3949 | } | ||
3950 | glEnd(); | ||
3951 | } | ||
3952 | { | ||
3953 | LLGLDepthTest gls_depth(GL_TRUE); | ||
3954 | LLUI::setLineWidth(3.0f); | ||
3955 | glBegin(GL_LINE_LOOP); | ||
3956 | for (i = 0; i < 16; i++) | ||
3957 | { | ||
3958 | glVertex3fv(verticesp[i].mV); | ||
3959 | } | ||
3960 | glEnd(); | ||
3961 | } | ||
3962 | LLUI::setLineWidth(1.0f); | ||
3963 | } | ||
3964 | |||
3965 | //============================================================================ | ||
3966 | // Once-per-frame setup of hardware lights, | ||
3967 | // including sun/moon, avatar backlight, and up to 6 local lights | ||
3968 | |||
3969 | void LLPipeline::setupAvatarLights(BOOL for_edit) | ||
3970 | { | ||
3971 | const LLColor4 black(0,0,0,1); | ||
3972 | |||
3973 | if (for_edit) | ||
3974 | { | ||
3975 | LLColor4 diffuse(0.8f, 0.8f, 0.8f, 0.f); | ||
3976 | LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f); // w==0 => directional light | ||
3977 | LLMatrix4 camera_mat = gCamera->getModelview(); | ||
3978 | LLMatrix4 camera_rot(camera_mat.getMat3()); | ||
3979 | camera_rot.invert(); | ||
3980 | LLVector4 light_pos = light_pos_cam * camera_rot; | ||
3981 | |||
3982 | light_pos.normVec(); | ||
3983 | |||
3984 | mHWLightColors[1] = diffuse; | ||
3985 | glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse.mV); | ||
3986 | glLightfv(GL_LIGHT1, GL_AMBIENT, black.mV); | ||
3987 | glLightfv(GL_LIGHT1, GL_SPECULAR, black.mV); | ||
3988 | glLightfv(GL_LIGHT1, GL_POSITION, light_pos.mV); | ||
3989 | glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0f); | ||
3990 | glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.0f); | ||
3991 | glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f); | ||
3992 | glLightf (GL_LIGHT1, GL_SPOT_EXPONENT, 0.0f); | ||
3993 | glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 180.0f); | ||
3994 | } | ||
3995 | else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini) | ||
3996 | { | ||
3997 | LLVector3 opposite_pos = -1.f * mSunDir; | ||
3998 | LLVector3 orthog_light_pos = mSunDir % LLVector3::z_axis; | ||
3999 | LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f); | ||
4000 | backlight_pos.normVec(); | ||
4001 | |||
4002 | LLColor4 light_diffuse = mSunDiffuse * mSunShadowFactor; | ||
4003 | LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f); | ||
4004 | F32 max_component = 0.001f; | ||
4005 | for (S32 i = 0; i < 3; i++) | ||
4006 | { | ||
4007 | if (backlight_diffuse.mV[i] > max_component) | ||
4008 | { | ||
4009 | max_component = backlight_diffuse.mV[i]; | ||
4010 | } | ||
4011 | } | ||
4012 | F32 backlight_mag; | ||
4013 | if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS) | ||
4014 | { | ||
4015 | backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT; | ||
4016 | } | ||
4017 | else | ||
4018 | { | ||
4019 | backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT; | ||
4020 | } | ||
4021 | backlight_diffuse *= backlight_mag / max_component; | ||
4022 | |||
4023 | mHWLightColors[1] = backlight_diffuse; | ||
4024 | glLightfv(GL_LIGHT1, GL_POSITION, backlight_pos.mV); // this is just sun/moon direction | ||
4025 | glLightfv(GL_LIGHT1, GL_DIFFUSE, backlight_diffuse.mV); | ||
4026 | glLightfv(GL_LIGHT1, GL_AMBIENT, black.mV); | ||
4027 | glLightfv(GL_LIGHT1, GL_SPECULAR, black.mV); | ||
4028 | glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0f); | ||
4029 | glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.0f); | ||
4030 | glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f); | ||
4031 | glLightf (GL_LIGHT1, GL_SPOT_EXPONENT, 0.0f); | ||
4032 | glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 180.0f); | ||
4033 | } | ||
4034 | else | ||
4035 | { | ||
4036 | mHWLightColors[1] = black; | ||
4037 | glLightfv(GL_LIGHT1, GL_DIFFUSE, black.mV); | ||
4038 | glLightfv(GL_LIGHT1, GL_AMBIENT, black.mV); | ||
4039 | glLightfv(GL_LIGHT1, GL_SPECULAR, black.mV); | ||
4040 | } | ||
4041 | } | ||
4042 | |||
4043 | static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist) | ||
4044 | { | ||
4045 | F32 inten = light->getLightIntensity(); | ||
4046 | if (inten < .001f) | ||
4047 | { | ||
4048 | return max_dist; | ||
4049 | } | ||
4050 | F32 radius = light->getLightRadius(); | ||
4051 | BOOL selected = light->isSelected(); | ||
4052 | LLVector3 dpos = light->getRenderPosition() - cam_pos; | ||
4053 | F32 dist2 = dpos.magVecSquared(); | ||
4054 | if (!selected && dist2 > (max_dist + radius)*(max_dist + radius)) | ||
4055 | { | ||
4056 | return max_dist; | ||
4057 | } | ||
4058 | F32 dist = fsqrtf(dist2); | ||
4059 | dist *= 1.f / inten; | ||
4060 | dist -= radius; | ||
4061 | if (selected) | ||
4062 | { | ||
4063 | dist -= 10000.f; // selected lights get highest priority | ||
4064 | } | ||
4065 | if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE)) | ||
4066 | { | ||
4067 | // moving lights get a little higher priority (too much causes artifacts) | ||
4068 | dist -= light->getLightRadius()*0.25f; | ||
4069 | } | ||
4070 | return dist; | ||
4071 | } | ||
4072 | |||
4073 | void LLPipeline::calcNearbyLights() | ||
4074 | { | ||
4075 | if (mLightingDetail >= 1) | ||
4076 | { | ||
4077 | // mNearbyLight (and all light_set_t's) are sorted such that | ||
4078 | // begin() == the closest light and rbegin() == the farthest light | ||
4079 | const S32 MAX_LOCAL_LIGHTS = 6; | ||
4080 | // LLVector3 cam_pos = gAgent.getCameraPositionAgent(); | ||
4081 | LLVector3 cam_pos = gAgent.getPositionAgent(); | ||
4082 | |||
4083 | F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad | ||
4084 | |||
4085 | // UPDATE THE EXISTING NEARBY LIGHTS | ||
4086 | light_set_t cur_nearby_lights; | ||
4087 | for (light_set_t::iterator iter = mNearbyLights.begin(); | ||
4088 | iter != mNearbyLights.end(); iter++) | ||
4089 | { | ||
4090 | const Light* light = &(*iter); | ||
4091 | LLDrawable* drawable = light->drawable; | ||
4092 | LLVOVolume* volight = drawable->getVOVolume(); | ||
4093 | if (!volight || !drawable->isState(LLDrawable::LIGHT)) | ||
4094 | { | ||
4095 | drawable->clearState(LLDrawable::NEARBY_LIGHT); | ||
4096 | continue; | ||
4097 | } | ||
4098 | if (light->fade <= -LIGHT_FADE_TIME) | ||
4099 | { | ||
4100 | drawable->clearState(LLDrawable::NEARBY_LIGHT); | ||
4101 | } | ||
4102 | else | ||
4103 | { | ||
4104 | F32 dist = calc_light_dist(volight, cam_pos, max_dist); | ||
4105 | cur_nearby_lights.insert(Light(drawable, dist, light->fade)); | ||
4106 | } | ||
4107 | } | ||
4108 | mNearbyLights = cur_nearby_lights; | ||
4109 | |||
4110 | // FIND NEW LIGHTS THAT ARE IN RANGE | ||
4111 | light_set_t new_nearby_lights; | ||
4112 | for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); | ||
4113 | iter != mLights.end(); ++iter) | ||
4114 | { | ||
4115 | LLDrawable* drawable = *iter; | ||
4116 | LLVOVolume* light = drawable->getVOVolume(); | ||
4117 | if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT)) | ||
4118 | { | ||
4119 | continue; | ||
4120 | } | ||
4121 | if (light->isHUDAttachment()) | ||
4122 | { | ||
4123 | continue; // no lighting from HUD objects | ||
4124 | } | ||
4125 | F32 dist = calc_light_dist(light, cam_pos, max_dist); | ||
4126 | if (dist >= max_dist) | ||
4127 | { | ||
4128 | continue; | ||
4129 | } | ||
4130 | new_nearby_lights.insert(Light(drawable, dist, 0.f)); | ||
4131 | if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS) | ||
4132 | { | ||
4133 | new_nearby_lights.erase(--new_nearby_lights.end()); | ||
4134 | const Light& last = *new_nearby_lights.rbegin(); | ||
4135 | max_dist = last.dist; | ||
4136 | } | ||
4137 | } | ||
4138 | |||
4139 | // INSERT ANY NEW LIGHTS | ||
4140 | for (light_set_t::iterator iter = new_nearby_lights.begin(); | ||
4141 | iter != new_nearby_lights.end(); iter++) | ||
4142 | { | ||
4143 | const Light* light = &(*iter); | ||
4144 | if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS) | ||
4145 | { | ||
4146 | mNearbyLights.insert(*light); | ||
4147 | ((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT); | ||
4148 | } | ||
4149 | else | ||
4150 | { | ||
4151 | // crazy cast so that we can overwrite the fade value | ||
4152 | // even though gcc enforces sets as const | ||
4153 | // (fade value doesn't affect sort so this is safe) | ||
4154 | Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin())))); | ||
4155 | if (light->dist < farthest_light->dist) | ||
4156 | { | ||
4157 | if (farthest_light->fade >= 0.f) | ||
4158 | { | ||
4159 | farthest_light->fade = -gFrameIntervalSeconds; | ||
4160 | } | ||
4161 | } | ||
4162 | else | ||
4163 | { | ||
4164 | break; // none of the other lights are closer | ||
4165 | } | ||
4166 | } | ||
4167 | } | ||
4168 | |||
4169 | } | ||
4170 | } | ||
4171 | |||
4172 | void LLPipeline::setupHWLights(LLDrawPool* pool) | ||
4173 | { | ||
4174 | const LLColor4 black(0,0,0,1); | ||
4175 | |||
4176 | setLightingDetail(-1); // update | ||
4177 | |||
4178 | // Ambient | ||
4179 | LLColor4 ambient = gSky.getTotalAmbientColor(); | ||
4180 | glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV); | ||
4181 | |||
4182 | // Light 0 = Sun or Moon (All objects) | ||
4183 | { | ||
4184 | mSunShadowFactor = 1.f; // no shadowing by defailt | ||
4185 | if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS) | ||
4186 | { | ||
4187 | mSunDir.setVec(gSky.getSunDirection()); | ||
4188 | mSunDiffuse.setVec(gSky.getSunDiffuseColor()); | ||
4189 | } | ||
4190 | else | ||
4191 | { | ||
4192 | mSunDir.setVec(gSky.getMoonDirection()); | ||
4193 | mSunDiffuse.setVec(gSky.getMoonDiffuseColor() * 1.5f); | ||
4194 | } | ||
4195 | |||
4196 | F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]); | ||
4197 | if (max_color > 1.f) | ||
4198 | { | ||
4199 | mSunDiffuse *= 1.f/max_color; | ||
4200 | } | ||
4201 | mSunDiffuse.clamp(); | ||
4202 | |||
4203 | LLVector4 light_pos(mSunDir, 0.0f); | ||
4204 | LLColor4 light_diffuse = mSunDiffuse * mSunShadowFactor; | ||
4205 | mHWLightColors[0] = light_diffuse; | ||
4206 | glLightfv(GL_LIGHT0, GL_POSITION, light_pos.mV); // this is just sun/moon direction | ||
4207 | glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse.mV); | ||
4208 | glLightfv(GL_LIGHT0, GL_AMBIENT, black.mV); | ||
4209 | glLightfv(GL_LIGHT0, GL_SPECULAR, black.mV); | ||
4210 | glLightf (GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0f); | ||
4211 | glLightf (GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.0f); | ||
4212 | glLightf (GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0f); | ||
4213 | glLightf (GL_LIGHT0, GL_SPOT_EXPONENT, 0.0f); | ||
4214 | glLightf (GL_LIGHT0, GL_SPOT_CUTOFF, 180.0f); | ||
4215 | } | ||
4216 | |||
4217 | // Light 1 = Backlight (for avatars) | ||
4218 | // (set by enableLightsAvatar) | ||
4219 | |||
4220 | S32 cur_light = 2; | ||
4221 | |||
4222 | // Nearby lights = LIGHT 2-7 | ||
4223 | |||
4224 | mLightMovingMask = 0; | ||
4225 | |||
4226 | if (mLightingDetail >= 1) | ||
4227 | { | ||
4228 | for (light_set_t::iterator iter = mNearbyLights.begin(); | ||
4229 | iter != mNearbyLights.end(); ++iter) | ||
4230 | { | ||
4231 | LLDrawable* drawable = iter->drawable; | ||
4232 | LLVOVolume* light = drawable->getVOVolume(); | ||
4233 | if (!light) | ||
4234 | { | ||
4235 | continue; | ||
4236 | } | ||
4237 | if (drawable->isState(LLDrawable::ACTIVE)) | ||
4238 | { | ||
4239 | mLightMovingMask |= (1<<cur_light); | ||
4240 | } | ||
4241 | |||
4242 | LLColor4 light_color = light->getLightColor(); | ||
4243 | light_color.mV[3] = 0.0f; | ||
4244 | |||
4245 | F32 fade = iter->fade; | ||
4246 | if (fade < LIGHT_FADE_TIME) | ||
4247 | { | ||
4248 | // fade in/out light | ||
4249 | if (fade >= 0.f) | ||
4250 | { | ||
4251 | fade = fade / LIGHT_FADE_TIME; | ||
4252 | ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds; | ||
4253 | } | ||
4254 | else | ||
4255 | { | ||
4256 | fade = 1.f + fade / LIGHT_FADE_TIME; | ||
4257 | ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds; | ||
4258 | } | ||
4259 | fade = llclamp(fade,0.f,1.f); | ||
4260 | light_color *= fade; | ||
4261 | } | ||
4262 | |||
4263 | LLVector3 light_pos(light->getRenderPosition()); | ||
4264 | LLVector4 light_pos_gl(light_pos, 1.0f); | ||
4265 | |||
4266 | F32 light_radius = llmax(light->getLightRadius(), 0.001f); | ||
4267 | F32 atten, quad; | ||
4268 | |||
4269 | #if 0 //1.9.1 | ||
4270 | if (pool->getVertexShaderLevel() > 0) | ||
4271 | { | ||
4272 | atten = light_radius; | ||
4273 | quad = llmax(light->getLightFalloff(), 0.0001f); | ||
4274 | } | ||
4275 | else | ||
4276 | #endif | ||
4277 | { | ||
4278 | F32 x = (3.f * (1.f + light->getLightFalloff())); | ||
4279 | atten = x / (light_radius); // % of brightness at radius | ||
4280 | quad = 0.0f; | ||
4281 | } | ||
4282 | mHWLightColors[cur_light] = light_color; | ||
4283 | S32 gllight = GL_LIGHT0+cur_light; | ||
4284 | glLightfv(gllight, GL_POSITION, light_pos_gl.mV); | ||
4285 | glLightfv(gllight, GL_DIFFUSE, light_color.mV); | ||
4286 | glLightfv(gllight, GL_AMBIENT, black.mV); | ||
4287 | glLightfv(gllight, GL_SPECULAR, black.mV); | ||
4288 | glLightf (gllight, GL_CONSTANT_ATTENUATION, 0.0f); | ||
4289 | glLightf (gllight, GL_LINEAR_ATTENUATION, atten); | ||
4290 | glLightf (gllight, GL_QUADRATIC_ATTENUATION, quad); | ||
4291 | glLightf (gllight, GL_SPOT_EXPONENT, 0.0f); | ||
4292 | glLightf (gllight, GL_SPOT_CUTOFF, 180.0f); | ||
4293 | cur_light++; | ||
4294 | if (cur_light >= 8) | ||
4295 | { | ||
4296 | break; // safety | ||
4297 | } | ||
4298 | } | ||
4299 | } | ||
4300 | for ( ; cur_light < 8 ; cur_light++) | ||
4301 | { | ||
4302 | mHWLightColors[cur_light] = black; | ||
4303 | S32 gllight = GL_LIGHT0+cur_light; | ||
4304 | glLightfv(gllight, GL_DIFFUSE, black.mV); | ||
4305 | glLightfv(gllight, GL_AMBIENT, black.mV); | ||
4306 | glLightfv(gllight, GL_SPECULAR, black.mV); | ||
4307 | } | ||
4308 | |||
4309 | // Init GL state | ||
4310 | glDisable(GL_LIGHTING); | ||
4311 | for (S32 gllight=GL_LIGHT0; gllight<=GL_LIGHT7; gllight++) | ||
4312 | { | ||
4313 | glDisable(gllight); | ||
4314 | } | ||
4315 | mLightMask = 0; | ||
4316 | } | ||
4317 | |||
4318 | void LLPipeline::enableLights(U32 mask, F32 shadow_factor) | ||
4319 | { | ||
4320 | if (mLightingDetail == 0) | ||
4321 | { | ||
4322 | mask &= 0xf003; // sun and backlight only (and fullbright bit) | ||
4323 | } | ||
4324 | if (mLightMask != mask) | ||
4325 | { | ||
4326 | if (!mLightMask) | ||
4327 | { | ||
4328 | glEnable(GL_LIGHTING); | ||
4329 | } | ||
4330 | if (mask) | ||
4331 | { | ||
4332 | for (S32 i=0; i<8; i++) | ||
4333 | { | ||
4334 | if (mask & (1<<i)) | ||
4335 | { | ||
4336 | glEnable(GL_LIGHT0 + i); | ||
4337 | glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, mHWLightColors[i].mV); | ||
4338 | } | ||
4339 | else | ||
4340 | { | ||
4341 | glDisable(GL_LIGHT0 + i); | ||
4342 | glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, LLColor4::black.mV); | ||
4343 | } | ||
4344 | } | ||
4345 | } | ||
4346 | else | ||
4347 | { | ||
4348 | glDisable(GL_LIGHTING); | ||
4349 | } | ||
4350 | mLightMask = mask; | ||
4351 | LLColor4 ambient = gSky.getTotalAmbientColor(); | ||
4352 | glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV); | ||
4353 | } | ||
4354 | } | ||
4355 | |||
4356 | void LLPipeline::enableLightsStatic(F32 shadow_factor) | ||
4357 | { | ||
4358 | U32 mask = 0x01; // Sun | ||
4359 | if (mLightingDetail >= 2) | ||
4360 | { | ||
4361 | mask |= mLightMovingMask; // Hardware moving lights | ||
4362 | glColor4f(0.f, 0.f, 0.f, 1.0f); // no local lighting by default | ||
4363 | } | ||
4364 | else | ||
4365 | { | ||
4366 | mask |= 0xff & (~2); // Hardware local lights | ||
4367 | } | ||
4368 | enableLights(mask, shadow_factor); | ||
4369 | } | ||
4370 | |||
4371 | void LLPipeline::enableLightsDynamic(F32 shadow_factor) | ||
4372 | { | ||
4373 | U32 mask = 0xff & (~2); // Local lights | ||
4374 | enableLights(mask, shadow_factor); | ||
4375 | if (mLightingDetail >= 2) | ||
4376 | { | ||
4377 | glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default | ||
4378 | } | ||
4379 | } | ||
4380 | |||
4381 | void LLPipeline::enableLightsAvatar(F32 shadow_factor) | ||
4382 | { | ||
4383 | U32 mask = 0xff; // All lights | ||
4384 | setupAvatarLights(FALSE); | ||
4385 | enableLights(mask, shadow_factor); | ||
4386 | } | ||
4387 | |||
4388 | void LLPipeline::enableLightsAvatarEdit(const LLColor4& color) | ||
4389 | { | ||
4390 | U32 mask = 0x2002; // Avatar backlight only, set ambient | ||
4391 | setupAvatarLights(TRUE); | ||
4392 | enableLights(mask, 1.0f); | ||
4393 | |||
4394 | glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV); | ||
4395 | } | ||
4396 | |||
4397 | void LLPipeline::enableLightsFullbright(const LLColor4& color) | ||
4398 | { | ||
4399 | U32 mask = 0x1000; // Non-0 mask, set ambient | ||
4400 | enableLights(mask, 1.f); | ||
4401 | |||
4402 | glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV); | ||
4403 | if (mLightingDetail >= 2) | ||
4404 | { | ||
4405 | glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default | ||
4406 | } | ||
4407 | } | ||
4408 | |||
4409 | void LLPipeline::disableLights() | ||
4410 | { | ||
4411 | enableLights(0, 0.f); // no lighting (full bright) | ||
4412 | glColor4f(1.f, 1.f, 1.f, 1.f); // lighting color = white by default | ||
4413 | } | ||
4414 | |||
4415 | // Call *after*s etting up lights | ||
4416 | void LLPipeline::setAmbient(const LLColor4& ambient) | ||
4417 | { | ||
4418 | mLightMask |= 0x4000; // tweak mask so that ambient will get reset | ||
4419 | LLColor4 amb = ambient + gSky.getTotalAmbientColor(); | ||
4420 | amb.clamp(); | ||
4421 | glLightModelfv(GL_LIGHT_MODEL_AMBIENT,amb.mV); | ||
4422 | } | ||
4423 | |||
4424 | //============================================================================ | ||
4425 | |||
4426 | class LLMenuItemGL; | ||
4427 | class LLInvFVBridge; | ||
4428 | struct cat_folder_pair; | ||
4429 | class LLVOBranch; | ||
4430 | class LLVOLeaf; | ||
4431 | class Foo; | ||
4432 | |||
4433 | template<> char* LLAGPArray<U8>::sTypeName = "U8 [AGP]"; | ||
4434 | template<> char* LLAGPArray<U32>::sTypeName = "U32 [AGP]"; | ||
4435 | template<> char* LLAGPArray<F32>::sTypeName = "F32 [AGP]"; | ||
4436 | template<> char* LLAGPArray<LLColor4>::sTypeName = "LLColor4 [AGP]"; | ||
4437 | template<> char* LLAGPArray<LLColor4U>::sTypeName = "LLColor4U [AGP]"; | ||
4438 | template<> char* LLAGPArray<LLVector4>::sTypeName = "LLVector4 [AGP]"; | ||
4439 | template<> char* LLAGPArray<LLVector3>::sTypeName = "LLVector3 [AGP]"; | ||
4440 | template<> char* LLAGPArray<LLVector2>::sTypeName = "LLVector2 [AGP]"; | ||
4441 | template<> char* LLAGPArray<LLFace*>::sTypeName = "LLFace* [AGP]"; | ||
4442 | |||
4443 | void scale_stamp(const F32 x, const F32 y, const F32 xs, const F32 ys) | ||
4444 | { | ||
4445 | stamp(0.25f + 0.5f*x, | ||
4446 | 0.5f + 0.45f*y, | ||
4447 | 0.5f*xs, | ||
4448 | 0.45f*ys); | ||
4449 | } | ||
4450 | |||
4451 | void drawBars(const F32 begin, const F32 end, const F32 height = 1.f) | ||
4452 | { | ||
4453 | if (begin >= 0 && end <=1) | ||
4454 | { | ||
4455 | F32 lines = 40.0f; | ||
4456 | S32 ibegin = (S32)(begin * lines); | ||
4457 | S32 iend = (S32)(end * lines); | ||
4458 | F32 fbegin = begin * lines - ibegin; | ||
4459 | F32 fend = end * lines - iend; | ||
4460 | |||
4461 | F32 line_height = height/lines; | ||
4462 | |||
4463 | if (iend == ibegin) | ||
4464 | { | ||
4465 | scale_stamp(fbegin, (F32)ibegin/lines,fend-fbegin, line_height); | ||
4466 | } | ||
4467 | else | ||
4468 | { | ||
4469 | // Beginning row | ||
4470 | scale_stamp(fbegin, (F32)ibegin/lines, 1.0f-fbegin, line_height); | ||
4471 | |||
4472 | // End row | ||
4473 | scale_stamp(0.0, (F32)iend/lines, fend, line_height); | ||
4474 | |||
4475 | // Middle rows | ||
4476 | for (S32 l = (ibegin+1); l < iend; l++) | ||
4477 | { | ||
4478 | scale_stamp(0.0f, (F32)l/lines, 1.0f, line_height); | ||
4479 | } | ||
4480 | } | ||
4481 | } | ||
4482 | } | ||
4483 | |||
4484 | void LLPipeline::displayAGP() | ||
4485 | { | ||
4486 | LLUI::setLineWidth(1.0); | ||
4487 | glMatrixMode(GL_PROJECTION); | ||
4488 | glPushMatrix(); | ||
4489 | glLoadIdentity(); | ||
4490 | glMatrixMode(GL_MODELVIEW); | ||
4491 | glPushMatrix(); | ||
4492 | glLoadIdentity(); | ||
4493 | |||
4494 | LLGLSPipelineAlpha gls_alpha; | ||
4495 | LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); | ||
4496 | |||
4497 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
4498 | glScalef(2,2,1); | ||
4499 | glTranslatef(-0.5f,-0.5f,0); | ||
4500 | |||
4501 | glColor4f(0,0,0,0.5f); | ||
4502 | scale_stamp(0,0,1,1); | ||
4503 | |||
4504 | F32 x = 0.0f, y = 0.05f; | ||
4505 | F32 xs = 0.015f, ys = 0.015f; | ||
4506 | F32 xs2 = xs*0.1f, ys2 = ys * 0.1f; | ||
4507 | F32 w = xs+xs2, h = ys + ys2; | ||
4508 | S32 i=0; | ||
4509 | |||
4510 | F32 agp_size = 1.f; | ||
4511 | if (mAGPMemPool) | ||
4512 | { | ||
4513 | agp_size = (F32)mAGPMemPool->getSize(); | ||
4514 | } | ||
4515 | |||
4516 | x = (xs + xs2) * 4.0f; | ||
4517 | |||
4518 | static float c = 0.0f; | ||
4519 | c += 0.0001f; | ||
4520 | |||
4521 | LLAGPMemBlock *blockp = mBufferMemory[mBufferIndex]->getAGPMemBlock(); | ||
4522 | |||
4523 | pool_set_t::iterator iter = mPools.begin(); | ||
4524 | LLDrawPool *poolp = *iter; | ||
4525 | |||
4526 | // Dump the shared AGP buffer | ||
4527 | if (blockp) | ||
4528 | { | ||
4529 | F32 begin = blockp->getOffset()/agp_size; | ||
4530 | F32 end = begin + (blockp->getSize()/agp_size); | ||
4531 | F32 used = begin + (poolp->mMemory.count()/agp_size); | ||
4532 | |||
4533 | LLViewerImage::bindTexture(NULL); | ||
4534 | glColor4f(0.5f, 0.5f, 0.5f, 0.5f); | ||
4535 | drawBars(begin,end); | ||
4536 | |||
4537 | LLViewerImage::bindTexture(NULL); | ||
4538 | glColor4f(0.5f, 0.5f, 0.5f, 0.5f); | ||
4539 | drawBars(begin,end); | ||
4540 | |||
4541 | LLViewerImage::bindTexture(NULL); | ||
4542 | glColor4f(0.5f, 0.5f, 0.5f, 0.5f); | ||
4543 | drawBars(begin,used, 0.5f); | ||
4544 | |||
4545 | glColor4f(0.5f, 0.5f, 0.5f, 0.5f); | ||
4546 | drawBars(begin,end, 0.25f); | ||
4547 | } | ||
4548 | |||
4549 | S32 used_bytes = 0; | ||
4550 | S32 total_bytes = 0; | ||
4551 | while (iter != mPools.end()) | ||
4552 | { | ||
4553 | poolp = *iter++; | ||
4554 | |||
4555 | BOOL synced = FALSE; | ||
4556 | i++; | ||
4557 | total_bytes += poolp->mMemory.getMax(); | ||
4558 | used_bytes += poolp->mMemory.count(); | ||
4559 | LLViewerImage *texturep = poolp->getDebugTexture(); | ||
4560 | |||
4561 | |||
4562 | if (poolp->mMemory.mSynced) | ||
4563 | { | ||
4564 | poolp->mMemory.mSynced = FALSE; | ||
4565 | synced = TRUE; | ||
4566 | } | ||
4567 | |||
4568 | LLAGPMemBlock *blockp = poolp->mMemory.getAGPMemBlock(); | ||
4569 | if (blockp) | ||
4570 | { | ||
4571 | F32 begin = blockp->getOffset()/agp_size; | ||
4572 | F32 end = begin + (blockp->getSize()/agp_size); | ||
4573 | F32 used = begin + (poolp->mMemory.count()/agp_size); | ||
4574 | |||
4575 | LLViewerImage::bindTexture(NULL); | ||
4576 | glColor4f(1.f, 0.5f, 0.5f, 0.5f); | ||
4577 | drawBars(begin,end); | ||
4578 | |||
4579 | LLViewerImage::bindTexture(texturep); | ||
4580 | glColor4f(1.f, 0.75f, 0.75f, 0.5f); | ||
4581 | drawBars(begin,end); | ||
4582 | |||
4583 | LLViewerImage::bindTexture(NULL); | ||
4584 | glColor4f(1.f, 0.75f, 0.75f, 1.f); | ||
4585 | drawBars(begin,used, 0.5f); | ||
4586 | |||
4587 | glColor3fv(poolp->getDebugColor().mV); | ||
4588 | drawBars(begin,end, 0.25f); | ||
4589 | |||
4590 | if (synced) | ||
4591 | { | ||
4592 | LLViewerImage::bindTexture(NULL); | ||
4593 | glColor4f(1.f, 1.f, 1.f, 0.4f); | ||
4594 | drawBars(begin,end); | ||
4595 | } | ||
4596 | } | ||
4597 | |||
4598 | synced = FALSE; | ||
4599 | if (poolp->mWeights.mSynced) | ||
4600 | { | ||
4601 | poolp->mWeights.mSynced = FALSE; | ||
4602 | synced = TRUE; | ||
4603 | } | ||
4604 | blockp = poolp->mWeights.getAGPMemBlock(); | ||
4605 | if (blockp) | ||
4606 | { | ||
4607 | F32 begin = blockp->getOffset()/agp_size; | ||
4608 | F32 end = begin + (blockp->getSize()/agp_size); | ||
4609 | F32 used = begin + (poolp->mWeights.count()*sizeof(float)/agp_size); | ||
4610 | |||
4611 | LLViewerImage::bindTexture(NULL); | ||
4612 | glColor4f(0.0f, 0.f, 0.75f, 0.5f); | ||
4613 | drawBars(begin,end); | ||
4614 | |||
4615 | LLViewerImage::bindTexture(texturep); | ||
4616 | glColor4f(0.0, 0.f, 0.75f, 0.5f); | ||
4617 | drawBars(begin,end); | ||
4618 | |||
4619 | LLViewerImage::bindTexture(NULL); | ||
4620 | glColor4f(0.0, 0.f, 0.75f, 1.f); | ||
4621 | drawBars(begin,used, 0.5f); | ||
4622 | |||
4623 | LLViewerImage::bindTexture(NULL); | ||
4624 | glColor3fv(poolp->getDebugColor().mV); | ||
4625 | drawBars(begin,end, 0.25f); | ||
4626 | |||
4627 | if (synced) | ||
4628 | { | ||
4629 | LLViewerImage::bindTexture(NULL); | ||
4630 | glColor4f(1.f, 1.f, 1.f, 0.4f); | ||
4631 | drawBars(begin,end); | ||
4632 | } | ||
4633 | } | ||
4634 | |||
4635 | synced = FALSE; | ||
4636 | if (poolp->mClothingWeights.mSynced) | ||
4637 | { | ||
4638 | poolp->mClothingWeights.mSynced = FALSE; | ||
4639 | synced = TRUE; | ||
4640 | } | ||
4641 | blockp = poolp->mClothingWeights.getAGPMemBlock(); | ||
4642 | if (blockp) | ||
4643 | { | ||
4644 | F32 begin = blockp->getOffset()/agp_size; | ||
4645 | F32 end = begin + (blockp->getSize()/agp_size); | ||
4646 | F32 used = begin + (poolp->mClothingWeights.count()*sizeof(LLVector4)/agp_size); | ||
4647 | |||
4648 | LLViewerImage::bindTexture(NULL); | ||
4649 | glColor4f(0.75f, 0.f, 0.75f, 0.5f); | ||
4650 | drawBars(begin,end); | ||
4651 | |||
4652 | LLViewerImage::bindTexture(texturep); | ||
4653 | glColor4f(0.75f, 0.f, 0.75f, 0.5f); | ||
4654 | drawBars(begin,end); | ||
4655 | |||
4656 | LLViewerImage::bindTexture(NULL); | ||
4657 | glColor4f(0.75f, 0.f, 0.75f, 0.5f); | ||
4658 | drawBars(begin,used, 0.5f); | ||
4659 | |||
4660 | LLViewerImage::bindTexture(NULL); | ||
4661 | glColor3fv(poolp->getDebugColor().mV); | ||
4662 | drawBars(begin,end, 0.25f); | ||
4663 | |||
4664 | if (synced) | ||
4665 | { | ||
4666 | LLViewerImage::bindTexture(NULL); | ||
4667 | glColor4f(1.f, 1.f, 1.f, 0.5f); | ||
4668 | drawBars(begin,end); | ||
4669 | } | ||
4670 | } | ||
4671 | |||
4672 | // | ||
4673 | // Stamps on bottom of screen | ||
4674 | // | ||
4675 | LLViewerImage::bindTexture(texturep); | ||
4676 | glColor4f(1.f, 1.f, 1.f, 1.f); | ||
4677 | stamp(x,y,xs,ys); | ||
4678 | |||
4679 | LLViewerImage::bindTexture(NULL); | ||
4680 | glColor3fv(poolp->getDebugColor().mV); | ||
4681 | stamp(x,y,xs, ys*0.25f); | ||
4682 | if (x+w > 0.95f) | ||
4683 | { | ||
4684 | x = (xs + xs2) * 4.0f; | ||
4685 | y += h; | ||
4686 | } | ||
4687 | else | ||
4688 | { | ||
4689 | x += w + xs2; | ||
4690 | } | ||
4691 | } | ||
4692 | |||
4693 | glPopMatrix(); | ||
4694 | glMatrixMode(GL_PROJECTION); | ||
4695 | glPopMatrix(); | ||
4696 | glMatrixMode(GL_MODELVIEW); | ||
4697 | } | ||
4698 | |||
4699 | void LLPipeline::findReferences(LLDrawable *drawablep) | ||
4700 | { | ||
4701 | if (std::find(mVisibleList.begin(), mVisibleList.end(), drawablep) != mVisibleList.end()) | ||
4702 | { | ||
4703 | llinfos << "In mVisibleList" << llendl; | ||
4704 | } | ||
4705 | if (mLights.find(drawablep) != mLights.end()) | ||
4706 | { | ||
4707 | llinfos << "In mLights" << llendl; | ||
4708 | } | ||
4709 | if (mMovedList.find(drawablep) != mMovedList.end()) | ||
4710 | { | ||
4711 | llinfos << "In mMovedList" << llendl; | ||
4712 | } | ||
4713 | if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end()) | ||
4714 | { | ||
4715 | llinfos << "In mShiftList" << llendl; | ||
4716 | } | ||
4717 | if (mRetexturedList.find(drawablep) != mRetexturedList.end()) | ||
4718 | { | ||
4719 | llinfos << "In mRetexturedList" << llendl; | ||
4720 | } | ||
4721 | if (mRematerialedList.find(drawablep) != mRematerialedList.end()) | ||
4722 | { | ||
4723 | llinfos << "In mRematerialedList" << llendl; | ||
4724 | } | ||
4725 | |||
4726 | if (mActiveQ.find(drawablep) != mActiveQ.end()) | ||
4727 | { | ||
4728 | llinfos << "In mActiveQ" << llendl; | ||
4729 | } | ||
4730 | if (mBuildQ1.find(drawablep) != mBuildQ1.end()) | ||
4731 | { | ||
4732 | llinfos << "In mBuildQ2" << llendl; | ||
4733 | } | ||
4734 | if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end()) | ||
4735 | { | ||
4736 | llinfos << "In mBuildQ2" << llendl; | ||
4737 | } | ||
4738 | |||
4739 | S32 count; | ||
4740 | /* | ||
4741 | count = mStaticTree->count(drawablep); | ||
4742 | if (count) | ||
4743 | { | ||
4744 | llinfos << "In mStaticTree: " << count << " references" << llendl; | ||
4745 | } | ||
4746 | |||
4747 | count = mDynamicTree->count(drawablep); | ||
4748 | if (count) | ||
4749 | { | ||
4750 | llinfos << "In mStaticTree: " << count << " references" << llendl; | ||
4751 | } | ||
4752 | */ | ||
4753 | count = gObjectList.findReferences(drawablep); | ||
4754 | if (count) | ||
4755 | { | ||
4756 | llinfos << "In other drawables: " << count << " references" << llendl; | ||
4757 | } | ||
4758 | } | ||
4759 | |||
4760 | BOOL LLPipeline::verify() | ||
4761 | { | ||
4762 | BOOL ok = TRUE; | ||
4763 | for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) | ||
4764 | { | ||
4765 | LLDrawPool *poolp = *iter; | ||
4766 | if (!poolp->verify()) | ||
4767 | { | ||
4768 | ok = FALSE; | ||
4769 | } | ||
4770 | } | ||
4771 | |||
4772 | if (!ok) | ||
4773 | { | ||
4774 | llwarns << "Pipeline verify failed!" << llendl; | ||
4775 | } | ||
4776 | return ok; | ||
4777 | } | ||
4778 | |||
4779 | S32 LLPipeline::getAGPMemUsage() | ||
4780 | { | ||
4781 | if (mAGPMemPool) | ||
4782 | { | ||
4783 | return mAGPMemPool->getSize(); | ||
4784 | } | ||
4785 | else | ||
4786 | { | ||
4787 | return 0; | ||
4788 | } | ||
4789 | } | ||
4790 | |||
4791 | S32 LLPipeline::getMemUsage(const BOOL print) | ||
4792 | { | ||
4793 | S32 mem_usage = 0; | ||
4794 | |||
4795 | if (mAGPMemPool) | ||
4796 | { | ||
4797 | S32 agp_usage = 0; | ||
4798 | agp_usage = mAGPMemPool->getSize(); | ||
4799 | if (print) | ||
4800 | { | ||
4801 | llinfos << "AGP Mem: " << agp_usage << llendl; | ||
4802 | llinfos << "AGP Mem used: " << mAGPMemPool->getTotalAllocated() << llendl; | ||
4803 | } | ||
4804 | mem_usage += agp_usage; | ||
4805 | } | ||
4806 | |||
4807 | |||
4808 | S32 pool_usage = 0; | ||
4809 | for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) | ||
4810 | { | ||
4811 | LLDrawPool *poolp = *iter; | ||
4812 | pool_usage += poolp->getMemUsage(print); | ||
4813 | } | ||
4814 | |||
4815 | if (print) | ||
4816 | { | ||
4817 | llinfos << "Pool Mem: " << pool_usage << llendl; | ||
4818 | } | ||
4819 | |||
4820 | mem_usage += pool_usage; | ||
4821 | |||
4822 | return mem_usage; | ||
4823 | |||
4824 | } | ||
4825 | |||
4826 | ////////////////////////////// | ||
4827 | // | ||
4828 | // Collision detection | ||
4829 | // | ||
4830 | // | ||
4831 | |||
4832 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
4833 | /** | ||
4834 | * A method to compute a ray-AABB intersection. | ||
4835 | * Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990 | ||
4836 | * Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500) | ||
4837 | * Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only) | ||
4838 | * | ||
4839 | * Hence this version is faster as well as more robust than the original one. | ||
4840 | * | ||
4841 | * Should work provided: | ||
4842 | * 1) the integer representation of 0.0f is 0x00000000 | ||
4843 | * 2) the sign bit of the float is the most significant one | ||
4844 | * | ||
4845 | * Report bugs: p.terdiman@codercorner.com | ||
4846 | * | ||
4847 | * \param aabb [in] the axis-aligned bounding box | ||
4848 | * \param origin [in] ray origin | ||
4849 | * \param dir [in] ray direction | ||
4850 | * \param coord [out] impact coordinates | ||
4851 | * \return true if ray intersects AABB | ||
4852 | */ | ||
4853 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
4854 | //#define RAYAABB_EPSILON 0.00001f | ||
4855 | #define IR(x) ((U32&)x) | ||
4856 | |||
4857 | bool LLRayAABB(const LLVector3 ¢er, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon) | ||
4858 | { | ||
4859 | BOOL Inside = TRUE; | ||
4860 | LLVector3 MinB = center - size; | ||
4861 | LLVector3 MaxB = center + size; | ||
4862 | LLVector3 MaxT; | ||
4863 | MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f; | ||
4864 | |||
4865 | // Find candidate planes. | ||
4866 | for(U32 i=0;i<3;i++) | ||
4867 | { | ||
4868 | if(origin.mV[i] < MinB.mV[i]) | ||
4869 | { | ||
4870 | coord.mV[i] = MinB.mV[i]; | ||
4871 | Inside = FALSE; | ||
4872 | |||
4873 | // Calculate T distances to candidate planes | ||
4874 | if(IR(dir.mV[i])) MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i]; | ||
4875 | } | ||
4876 | else if(origin.mV[i] > MaxB.mV[i]) | ||
4877 | { | ||
4878 | coord.mV[i] = MaxB.mV[i]; | ||
4879 | Inside = FALSE; | ||
4880 | |||
4881 | // Calculate T distances to candidate planes | ||
4882 | if(IR(dir.mV[i])) MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i]; | ||
4883 | } | ||
4884 | } | ||
4885 | |||
4886 | // Ray origin inside bounding box | ||
4887 | if(Inside) | ||
4888 | { | ||
4889 | coord = origin; | ||
4890 | return true; | ||
4891 | } | ||
4892 | |||
4893 | // Get largest of the maxT's for final choice of intersection | ||
4894 | U32 WhichPlane = 0; | ||
4895 | if(MaxT.mV[1] > MaxT.mV[WhichPlane]) WhichPlane = 1; | ||
4896 | if(MaxT.mV[2] > MaxT.mV[WhichPlane]) WhichPlane = 2; | ||
4897 | |||
4898 | // Check final candidate actually inside box | ||
4899 | if(IR(MaxT.mV[WhichPlane])&0x80000000) return false; | ||
4900 | |||
4901 | for(U32 i=0;i<3;i++) | ||
4902 | { | ||
4903 | if(i!=WhichPlane) | ||
4904 | { | ||
4905 | coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i]; | ||
4906 | if (epsilon > 0) | ||
4907 | { | ||
4908 | if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon) return false; | ||
4909 | } | ||
4910 | else | ||
4911 | { | ||
4912 | if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i]) return false; | ||
4913 | } | ||
4914 | } | ||
4915 | } | ||
4916 | return true; // ray hits box | ||
4917 | } | ||
4918 | |||
4919 | ////////////////////////////// | ||
4920 | // | ||
4921 | // Macros, functions, and inline methods from other classes | ||
4922 | // | ||
4923 | // | ||
4924 | |||
4925 | void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light) | ||
4926 | { | ||
4927 | if (drawablep) | ||
4928 | { | ||
4929 | if (is_light) | ||
4930 | { | ||
4931 | mLights.insert(drawablep); | ||
4932 | drawablep->setState(LLDrawable::LIGHT); | ||
4933 | } | ||
4934 | else | ||
4935 | { | ||
4936 | mLights.erase(drawablep); | ||
4937 | drawablep->clearState(LLDrawable::LIGHT); | ||
4938 | } | ||
4939 | markRelight(drawablep); | ||
4940 | } | ||
4941 | } | ||
4942 | |||
4943 | void LLPipeline::setActive(LLDrawable *drawablep, BOOL active) | ||
4944 | { | ||
4945 | if (active) | ||
4946 | { | ||
4947 | mActiveQ.insert(drawablep); | ||
4948 | } | ||
4949 | else | ||
4950 | { | ||
4951 | mActiveQ.erase(drawablep); | ||
4952 | } | ||
4953 | } | ||
4954 | |||
4955 | //static | ||
4956 | void LLPipeline::toggleRenderType(void* data) | ||
4957 | { | ||
4958 | S32 type = (S32)(intptr_t)data; | ||
4959 | U32 bit = (1<<type); | ||
4960 | if (gPipeline.hasRenderType(type)) | ||
4961 | { | ||
4962 | llinfos << "Toggling render type mask " << std::hex << bit << " off" << std::dec << llendl; | ||
4963 | } | ||
4964 | else | ||
4965 | { | ||
4966 | llinfos << "Toggling render type mask " << std::hex << bit << " on" << std::dec << llendl; | ||
4967 | } | ||
4968 | gPipeline.mRenderTypeMask ^= bit; | ||
4969 | } | ||
4970 | |||
4971 | //static | ||
4972 | BOOL LLPipeline::toggleRenderTypeControl(void* data) | ||
4973 | { | ||
4974 | S32 type = (S32)(intptr_t)data; | ||
4975 | return gPipeline.hasRenderType(type); | ||
4976 | } | ||
4977 | |||
4978 | // Allows UI items labeled "Hide foo" instead of "Show foo" | ||
4979 | //static | ||
4980 | BOOL LLPipeline::toggleRenderTypeControlNegated(void* data) | ||
4981 | { | ||
4982 | S32 type = (S32)(intptr_t)data; | ||
4983 | return !gPipeline.hasRenderType(type); | ||
4984 | } | ||
4985 | |||
4986 | //static | ||
4987 | void LLPipeline::toggleRenderDebug(void* data) | ||
4988 | { | ||
4989 | U32 bit = (U32)(intptr_t)data; | ||
4990 | if (gPipeline.hasRenderDebugMask(bit)) | ||
4991 | { | ||
4992 | llinfos << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << llendl; | ||
4993 | } | ||
4994 | else | ||
4995 | { | ||
4996 | llinfos << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << llendl; | ||
4997 | } | ||
4998 | gPipeline.mRenderDebugMask ^= bit; | ||
4999 | } | ||
5000 | |||
5001 | |||
5002 | //static | ||
5003 | BOOL LLPipeline::toggleRenderDebugControl(void* data) | ||
5004 | { | ||
5005 | U32 bit = (U32)(intptr_t)data; | ||
5006 | return gPipeline.hasRenderDebugMask(bit); | ||
5007 | } | ||
5008 | |||
5009 | //static | ||
5010 | void LLPipeline::toggleRenderDebugFeature(void* data) | ||
5011 | { | ||
5012 | U32 bit = (U32)(intptr_t)data; | ||
5013 | if (gPipeline.hasRenderDebugFeatureMask(bit)) | ||
5014 | { | ||
5015 | llinfos << "Toggling render debug feature mask " << std::hex << bit << " off" << std::dec << llendl; | ||
5016 | } | ||
5017 | else | ||
5018 | { | ||
5019 | llinfos << "Toggling render debug feature mask " << std::hex << bit << " on" << std::dec << llendl; | ||
5020 | } | ||
5021 | gPipeline.mRenderDebugFeatureMask ^= bit; | ||
5022 | } | ||
5023 | |||
5024 | |||
5025 | //static | ||
5026 | BOOL LLPipeline::toggleRenderDebugFeatureControl(void* data) | ||
5027 | { | ||
5028 | U32 bit = (U32)(intptr_t)data; | ||
5029 | return gPipeline.hasRenderDebugFeatureMask(bit); | ||
5030 | } | ||
5031 | |||
5032 | // static | ||
5033 | void LLPipeline::toggleRenderScriptedBeacons(void*) | ||
5034 | { | ||
5035 | sRenderScriptedBeacons = !sRenderScriptedBeacons; | ||
5036 | } | ||
5037 | |||
5038 | // static | ||
5039 | BOOL LLPipeline::getRenderScriptedBeacons(void*) | ||
5040 | { | ||
5041 | return sRenderScriptedBeacons; | ||
5042 | } | ||
5043 | |||
5044 | // static | ||
5045 | void LLPipeline::toggleRenderPhysicalBeacons(void*) | ||
5046 | { | ||
5047 | sRenderPhysicalBeacons = !sRenderPhysicalBeacons; | ||
5048 | } | ||
5049 | |||
5050 | // static | ||
5051 | BOOL LLPipeline::getRenderPhysicalBeacons(void*) | ||
5052 | { | ||
5053 | return sRenderPhysicalBeacons; | ||
5054 | } | ||
5055 | |||
5056 | // static | ||
5057 | void LLPipeline::toggleRenderParticleBeacons(void*) | ||
5058 | { | ||
5059 | sRenderParticleBeacons = !sRenderParticleBeacons; | ||
5060 | } | ||
5061 | |||
5062 | // static | ||
5063 | BOOL LLPipeline::getRenderParticleBeacons(void*) | ||
5064 | { | ||
5065 | return sRenderParticleBeacons; | ||
5066 | } | ||
5067 | |||
5068 | // static | ||
5069 | void LLPipeline::toggleRenderSoundBeacons(void*) | ||
5070 | { | ||
5071 | sRenderSoundBeacons = !sRenderSoundBeacons; | ||
5072 | } | ||
5073 | |||
5074 | // static | ||
5075 | BOOL LLPipeline::getRenderSoundBeacons(void*) | ||
5076 | { | ||
5077 | return sRenderSoundBeacons; | ||
5078 | } | ||
5079 | |||
5080 | //=============================== | ||
5081 | // LLGLSL Shader implementation | ||
5082 | //=============================== | ||
5083 | LLGLSLShader::LLGLSLShader() | ||
5084 | : mProgramObject(0) | ||
5085 | { } | ||
5086 | |||
5087 | void LLGLSLShader::unload() | ||
5088 | { | ||
5089 | stop_glerror(); | ||
5090 | mAttribute.clear(); | ||
5091 | mTexture.clear(); | ||
5092 | mUniform.clear(); | ||
5093 | |||
5094 | if (mProgramObject) | ||
5095 | { | ||
5096 | GLhandleARB obj[1024]; | ||
5097 | GLsizei count; | ||
5098 | |||
5099 | glGetAttachedObjectsARB(mProgramObject, 1024, &count, obj); | ||
5100 | for (GLsizei i = 0; i < count; i++) | ||
5101 | { | ||
5102 | glDeleteObjectARB(obj[i]); | ||
5103 | } | ||
5104 | |||
5105 | glDeleteObjectARB(mProgramObject); | ||
5106 | |||
5107 | mProgramObject = 0; | ||
5108 | } | ||
5109 | |||
5110 | //hack to make apple not complain | ||
5111 | glGetError(); | ||
5112 | |||
5113 | stop_glerror(); | ||
5114 | } | ||
5115 | |||
5116 | void LLGLSLShader::attachObject(GLhandleARB object) | ||
5117 | { | ||
5118 | if (object != 0) | ||
5119 | { | ||
5120 | stop_glerror(); | ||
5121 | glAttachObjectARB(mProgramObject, object); | ||
5122 | stop_glerror(); | ||
5123 | } | ||
5124 | else | ||
5125 | { | ||
5126 | llwarns << "Attempting to attach non existing shader object. " << llendl; | ||
5127 | } | ||
5128 | } | ||
5129 | |||
5130 | void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count) | ||
5131 | { | ||
5132 | for (S32 i = 0; i < count; i++) | ||
5133 | { | ||
5134 | attachObject(objects[i]); | ||
5135 | } | ||
5136 | } | ||
5137 | |||
5138 | BOOL LLGLSLShader::mapAttributes(const char** attrib_names, S32 count) | ||
5139 | { | ||
5140 | //link the program | ||
5141 | BOOL res = link(); | ||
5142 | |||
5143 | mAttribute.clear(); | ||
5144 | mAttribute.resize(LLPipeline::sReservedAttribCount + count, -1); | ||
5145 | |||
5146 | if (res) | ||
5147 | { //read back channel locations | ||
5148 | |||
5149 | //read back reserved channels first | ||
5150 | for (S32 i = 0; i < (S32) LLPipeline::sReservedAttribCount; i++) | ||
5151 | { | ||
5152 | const char* name = LLPipeline::sReservedAttribs[i]; | ||
5153 | S32 index = glGetAttribLocationARB(mProgramObject, name); | ||
5154 | if (index != -1) | ||
5155 | { | ||
5156 | mAttribute[i] = index; | ||
5157 | llinfos << "Attribute " << name << " assigned to channel " << index << llendl; | ||
5158 | } | ||
5159 | } | ||
5160 | |||
5161 | for (S32 i = 0; i < count; i++) | ||
5162 | { | ||
5163 | const char* name = attrib_names[i]; | ||
5164 | S32 index = glGetAttribLocationARB(mProgramObject, name); | ||
5165 | if (index != -1) | ||
5166 | { | ||
5167 | mAttribute[LLPipeline::sReservedAttribCount + i] = index; | ||
5168 | llinfos << "Attribute " << name << " assigned to channel " << index << llendl; | ||
5169 | } | ||
5170 | } | ||
5171 | |||
5172 | return TRUE; | ||
5173 | } | ||
5174 | |||
5175 | return FALSE; | ||
5176 | } | ||
5177 | |||
5178 | void LLGLSLShader::mapUniform(GLint index, const char** uniform_names, S32 count) | ||
5179 | { | ||
5180 | if (index == -1) | ||
5181 | { | ||
5182 | return; | ||
5183 | } | ||
5184 | |||
5185 | GLenum type; | ||
5186 | GLsizei length; | ||
5187 | GLint size; | ||
5188 | char name[1024]; | ||
5189 | name[0] = 0; | ||
5190 | |||
5191 | glGetActiveUniformARB(mProgramObject, index, 1024, &length, &size, &type, name); | ||
5192 | |||
5193 | //find the index of this uniform | ||
5194 | for (S32 i = 0; i < (S32) LLPipeline::sReservedUniformCount; i++) | ||
5195 | { | ||
5196 | if (mUniform[i] == -1 && !strncmp(LLPipeline::sReservedUniforms[i],name, strlen(LLPipeline::sReservedUniforms[i]))) | ||
5197 | { | ||
5198 | //found it | ||
5199 | S32 location = glGetUniformLocationARB(mProgramObject, name); | ||
5200 | mUniform[i] = location; | ||
5201 | llinfos << "Uniform " << name << " is at location " << location << llendl; | ||
5202 | mTexture[i] = mapUniformTextureChannel(location, type); | ||
5203 | return; | ||
5204 | } | ||
5205 | } | ||
5206 | |||
5207 | for (S32 i = 0; i < count; i++) | ||
5208 | { | ||
5209 | if (mUniform[i+LLPipeline::sReservedUniformCount] == -1 && | ||
5210 | !strncmp(uniform_names[i],name, strlen(uniform_names[i]))) | ||
5211 | { | ||
5212 | //found it | ||
5213 | S32 location = glGetUniformLocationARB(mProgramObject, name); | ||
5214 | mUniform[i+LLPipeline::sReservedUniformCount] = location; | ||
5215 | llinfos << "Uniform " << name << " is at location " << location << " stored in index " << | ||
5216 | (i+LLPipeline::sReservedUniformCount) << llendl; | ||
5217 | mTexture[i+LLPipeline::sReservedUniformCount] = mapUniformTextureChannel(location, type); | ||
5218 | return; | ||
5219 | } | ||
5220 | } | ||
5221 | |||
5222 | //llinfos << "Unknown uniform: " << name << llendl; | ||
5223 | } | ||
5224 | |||
5225 | GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type) | ||
5226 | { | ||
5227 | if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) | ||
5228 | { //this here is a texture | ||
5229 | glUniform1iARB(location, mActiveTextureChannels); | ||
5230 | llinfos << "Assigned to texture channel " << mActiveTextureChannels << llendl; | ||
5231 | return mActiveTextureChannels++; | ||
5232 | } | ||
5233 | return -1; | ||
5234 | } | ||
5235 | |||
5236 | BOOL LLGLSLShader::mapUniforms(const char** uniform_names, S32 count) | ||
5237 | { | ||
5238 | BOOL res = TRUE; | ||
5239 | |||
5240 | mActiveTextureChannels = 0; | ||
5241 | mUniform.clear(); | ||
5242 | mTexture.clear(); | ||
5243 | |||
5244 | //initialize arrays | ||
5245 | mUniform.resize(count + LLPipeline::sReservedUniformCount, -1); | ||
5246 | mTexture.resize(count + LLPipeline::sReservedUniformCount, -1); | ||
5247 | |||
5248 | |||
5249 | |||
5250 | bind(); | ||
5251 | |||
5252 | //get the number of active uniforms | ||
5253 | GLint activeCount; | ||
5254 | glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount); | ||
5255 | |||
5256 | for (S32 i = 0; i < activeCount; i++) | ||
5257 | { | ||
5258 | mapUniform(i, uniform_names, count); | ||
5259 | } | ||
5260 | |||
5261 | unbind(); | ||
5262 | |||
5263 | return res; | ||
5264 | } | ||
5265 | |||
5266 | BOOL LLGLSLShader::link(BOOL suppress_errors) | ||
5267 | { | ||
5268 | return gPipeline.linkProgramObject(mProgramObject, suppress_errors); | ||
5269 | } | ||
5270 | |||
5271 | void LLGLSLShader::bind() | ||
5272 | { | ||
5273 | glUseProgramObjectARB(mProgramObject); | ||
5274 | if (mAttribute.size() > 0) | ||
5275 | { | ||
5276 | gPipeline.mMaterialIndex = mAttribute[0]; | ||
5277 | } | ||
5278 | } | ||
5279 | |||
5280 | void LLGLSLShader::unbind() | ||
5281 | { | ||
5282 | for (U32 i = 0; i < mAttribute.size(); ++i) | ||
5283 | { | ||
5284 | vertexAttrib4f(i, 0,0,0,1); | ||
5285 | } | ||
5286 | glUseProgramObjectARB(0); | ||
5287 | } | ||
5288 | |||
5289 | S32 LLGLSLShader::enableTexture(S32 uniform, S32 mode) | ||
5290 | { | ||
5291 | if (uniform < 0 || uniform >= (S32)mTexture.size()) | ||
5292 | { | ||
5293 | llerrs << "LLGLSLShader::enableTexture: uniform out of range: " << uniform << llendl; | ||
5294 | } | ||
5295 | S32 index = mTexture[uniform]; | ||
5296 | if (index != -1) | ||
5297 | { | ||
5298 | glActiveTextureARB(GL_TEXTURE0_ARB+index); | ||
5299 | glEnable(mode); | ||
5300 | } | ||
5301 | return index; | ||
5302 | } | ||
5303 | |||
5304 | S32 LLGLSLShader::disableTexture(S32 uniform, S32 mode) | ||
5305 | { | ||
5306 | S32 index = mTexture[uniform]; | ||
5307 | if (index != -1) | ||
5308 | { | ||
5309 | glActiveTextureARB(GL_TEXTURE0_ARB+index); | ||
5310 | glDisable(mode); | ||
5311 | } | ||
5312 | return index; | ||
5313 | } | ||
5314 | |||
5315 | void LLGLSLShader::vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) | ||
5316 | { | ||
5317 | if (mAttribute[index] > 0) | ||
5318 | { | ||
5319 | glVertexAttrib4fARB(mAttribute[index], x, y, z, w); | ||
5320 | } | ||
5321 | } | ||
5322 | |||
5323 | void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v) | ||
5324 | { | ||
5325 | if (mAttribute[index] > 0) | ||
5326 | { | ||
5327 | glVertexAttrib4fvARB(mAttribute[index], v); | ||
5328 | } | ||
5329 | } | ||
5330 | |||
5331 | LLViewerObject* LLPipeline::pickObject(const LLVector3 &start, const LLVector3 &end, LLVector3 &collision) | ||
5332 | { | ||
5333 | LLDrawable* drawable = mObjectPartition->pickDrawable(start, end, collision); | ||
5334 | return drawable ? drawable->getVObj() : NULL; | ||
5335 | } | ||
5336 | |||
5337 | |||