aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/pipeline.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/pipeline.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/pipeline.cpp5337
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
97const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f;
98const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f;
99const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
100const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
101const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40;
102const 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
106const 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
111const F32 OCCLUDE_SCALE_SUM_THRESHOLD = 8.f;
112
113// Max number of occluders to search for. JC
114const S32 MAX_OCCLUDER_COUNT = 2;
115
116extern S32 gBoxFrame;
117extern BOOL gRenderLightGlows;
118extern BOOL gHideSelectedObjects;
119
120
121BOOL gAvatarBacklight = FALSE;
122
123F32 gMinObjectDistance = MIN_NEAR_PLANE;
124S32 gTrivialAccepts = 0;
125
126BOOL gRenderForSelect = FALSE;
127
128BOOL gUsePickAlpha = TRUE;
129F32 gPickAlphaThreshold = 0.f;
130F32 gPickAlphaTargetThreshold = 0.f;
131
132//glsl parameter tables
133const char* LLPipeline::sReservedAttribs[] =
134{
135 "materialColor",
136 "specularColor",
137 "binormal"
138};
139
140U32 LLPipeline::sReservedAttribCount = LLPipeline::GLSL_END_RESERVED_ATTRIBS;
141
142const char* LLPipeline::sAvatarAttribs[] =
143{
144 "weight",
145 "clothing",
146 "gWindDir",
147 "gSinWaveParams",
148 "gGravity"
149};
150
151U32 LLPipeline::sAvatarAttribCount = sizeof(LLPipeline::sAvatarAttribs)/sizeof(char*);
152
153const char* LLPipeline::sAvatarUniforms[] =
154{
155 "matrixPalette"
156};
157
158U32 LLPipeline::sAvatarUniformCount = 1;
159
160const char* LLPipeline::sReservedUniforms[] =
161{
162 "diffuseMap",
163 "specularMap",
164 "bumpMap",
165 "environmentMap",
166 "scatterMap"
167};
168
169U32 LLPipeline::sReservedUniformCount = LLPipeline::GLSL_END_RESERVED_UNIFORMS;
170
171const char* LLPipeline::sTerrainUniforms[] =
172{
173 "detail0",
174 "detail1",
175 "alphaRamp"
176};
177
178U32 LLPipeline::sTerrainUniformCount = sizeof(LLPipeline::sTerrainUniforms)/sizeof(char*);
179
180const 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
194U32 LLPipeline::sWaterUniformCount = sizeof(LLPipeline::sWaterUniforms)/sizeof(char*);
195
196// the SSE variable is dependent on software blending being enabled.
197
198//----------------------------------------
199
200void 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
218S32 LLPipeline::sCompiles = 0;
219S32 LLPipeline::sAGPMaxPoolSize = 1 << 25; // 32MB
220BOOL LLPipeline::sRenderPhysicalBeacons = FALSE;
221BOOL LLPipeline::sRenderScriptedBeacons = FALSE;
222BOOL LLPipeline::sRenderParticleBeacons = FALSE;
223BOOL LLPipeline::sRenderSoundBeacons = FALSE;
224
225LLPipeline::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
255void 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
311void LLPipeline::LLScatterShader::init(GLhandleARB shader, int map_stage)
312{
313 glUseProgramObjectARB(shader);
314 glUniform1iARB(glGetUniformLocationARB(shader, "scatterMap"), map_stage);
315 glUseProgramObjectARB(0);
316}
317
318LLPipeline::~LLPipeline()
319{
320
321}
322
323void 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
400BOOL 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
447void 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
466BOOL LLPipeline::usingAGP() const
467{
468 return (mRenderFeatureMask & RENDER_FEATURE_AGP) ? TRUE : FALSE;
469}
470
471void 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
534void LLPipeline::destroyGL()
535{
536 setUseAGP(FALSE);
537 stop_glerror();
538 unloadShaders();
539 mHighlightFaces.reset();
540}
541
542void 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
558static 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
576void 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
589GLhandleARB 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
742BOOL 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
770BOOL 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
792void 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
883BOOL 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
898void 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
923BOOL 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
968BOOL 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
1011BOOL 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
1108BOOL 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
1200BOOL 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
1296BOOL 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
1338void LLPipeline::enableShadows(const BOOL enable_shadows)
1339{
1340 //should probably do something here to wrangle shadows....
1341}
1342
1343S32 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
1355S32 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
1379LLAGPMemBlock *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
1402void LLPipeline::unbindAGP()
1403{
1404 if (mAGPMemPool && mAGPBound)
1405 {
1406 mAGPMemPool->disable();
1407 mAGPBound = FALSE;
1408 }
1409}
1410
1411void 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
1422U8* LLPipeline::bufferGetScratchMemory(void)
1423{
1424 LLMemType mt(LLMemType::MTYPE_PIPELINE);
1425 return(mBufferMemory[mBufferIndex]->getScratchMemory());
1426}
1427
1428void LLPipeline::bufferWaitFence(void)
1429{
1430 mBufferMemory[mBufferIndex]->waitFence(mBufferFence[mBufferIndex]);
1431}
1432
1433void LLPipeline::bufferSendFence(void)
1434{
1435 mBufferMemory[mBufferIndex]->sendFence(mBufferFence[mBufferIndex]);
1436}
1437
1438void 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)
1446void 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
1455LLDrawPool *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
1525LLDrawPool *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
1542LLDrawPool* 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
1572void LLPipeline::addPool(LLDrawPool *new_poolp)
1573{
1574 LLMemType mt(LLMemType::MTYPE_PIPELINE);
1575 mPools.insert(new_poolp);
1576 addToQuickLookup( new_poolp );
1577}
1578
1579void 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
1598void 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
1623U32 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
1675void 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
1685void 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
1711void 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
1737void 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
1824void 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
1913void 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
1945void LLPipeline::doOcclusion()
1946{
1947 if (gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery)
1948 {
1949 mObjectPartition->doOcclusion(gCamera);
1950 }
1951}
1952
1953
1954BOOL 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
1965void 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
2033void 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
2048void 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
2085void 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
2105void 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
2124void LLPipeline::markTextured(LLDrawable *drawablep)
2125{
2126 LLMemType mt(LLMemType::MTYPE_PIPELINE);
2127 if (!drawablep->isDead())
2128 {
2129 mRetexturedList.insert(drawablep);
2130 }
2131}
2132
2133void LLPipeline::markMaterialed(LLDrawable *drawablep)
2134{
2135 LLMemType mt(LLMemType::MTYPE_PIPELINE);
2136 if (!drawablep->isDead())
2137 {
2138 mRematerialedList.insert(drawablep);
2139 }
2140}
2141
2142void 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
2180void LLPipeline::markRelight(LLDrawable *drawablep, const BOOL priority)
2181{
2182 if (getLightingDetail() >= 2)
2183 {
2184 markRebuild(drawablep, LLDrawable::REBUILD_LIGHTING, FALSE);
2185 }
2186}
2187
2188void 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
2380static 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
2421void 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
2520void 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
2800void 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
2990BOOL 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
3048void 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
3211void 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
3263void 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
3319void LLPipeline::renderFaceForUVSelect(LLFace* facep)
3320{
3321 if (facep) facep->renderSelectedUV();
3322}
3323
3324void 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
3362void 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
3481void LLPipeline::removePool( LLDrawPool* poolp )
3482{
3483 removeFromQuickLookup(poolp);
3484 mPools.erase(poolp);
3485 delete poolp;
3486}
3487
3488void 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
3604void 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
3615void 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
3628LLViewerObject *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
3644void 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
3677void 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
3800static F32 xs = 0.01f, ys = 0.01f;
3801static F32 xs2 = xs*0.1f, ys2 = ys * 0.1f;
3802static F32 winx, winy;
3803
3804void 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
3855void 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
3880void 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
3920void 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
3969void 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
4043static 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
4073void 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
4172void 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
4318void 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
4356void 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
4371void 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
4381void LLPipeline::enableLightsAvatar(F32 shadow_factor)
4382{
4383 U32 mask = 0xff; // All lights
4384 setupAvatarLights(FALSE);
4385 enableLights(mask, shadow_factor);
4386}
4387
4388void 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
4397void 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
4409void 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
4416void 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
4426class LLMenuItemGL;
4427class LLInvFVBridge;
4428struct cat_folder_pair;
4429class LLVOBranch;
4430class LLVOLeaf;
4431class Foo;
4432
4433template<> char* LLAGPArray<U8>::sTypeName = "U8 [AGP]";
4434template<> char* LLAGPArray<U32>::sTypeName = "U32 [AGP]";
4435template<> char* LLAGPArray<F32>::sTypeName = "F32 [AGP]";
4436template<> char* LLAGPArray<LLColor4>::sTypeName = "LLColor4 [AGP]";
4437template<> char* LLAGPArray<LLColor4U>::sTypeName = "LLColor4U [AGP]";
4438template<> char* LLAGPArray<LLVector4>::sTypeName = "LLVector4 [AGP]";
4439template<> char* LLAGPArray<LLVector3>::sTypeName = "LLVector3 [AGP]";
4440template<> char* LLAGPArray<LLVector2>::sTypeName = "LLVector2 [AGP]";
4441template<> char* LLAGPArray<LLFace*>::sTypeName = "LLFace* [AGP]";
4442
4443void 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
4451void 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
4484void 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
4699void 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
4760BOOL 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
4779S32 LLPipeline::getAGPMemUsage()
4780{
4781 if (mAGPMemPool)
4782 {
4783 return mAGPMemPool->getSize();
4784 }
4785 else
4786 {
4787 return 0;
4788 }
4789}
4790
4791S32 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
4857bool LLRayAABB(const LLVector3 &center, 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
4925void 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
4943void 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
4956void 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
4972BOOL 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
4980BOOL LLPipeline::toggleRenderTypeControlNegated(void* data)
4981{
4982 S32 type = (S32)(intptr_t)data;
4983 return !gPipeline.hasRenderType(type);
4984}
4985
4986//static
4987void 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
5003BOOL LLPipeline::toggleRenderDebugControl(void* data)
5004{
5005 U32 bit = (U32)(intptr_t)data;
5006 return gPipeline.hasRenderDebugMask(bit);
5007}
5008
5009//static
5010void 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
5026BOOL LLPipeline::toggleRenderDebugFeatureControl(void* data)
5027{
5028 U32 bit = (U32)(intptr_t)data;
5029 return gPipeline.hasRenderDebugFeatureMask(bit);
5030}
5031
5032// static
5033void LLPipeline::toggleRenderScriptedBeacons(void*)
5034{
5035 sRenderScriptedBeacons = !sRenderScriptedBeacons;
5036}
5037
5038// static
5039BOOL LLPipeline::getRenderScriptedBeacons(void*)
5040{
5041 return sRenderScriptedBeacons;
5042}
5043
5044// static
5045void LLPipeline::toggleRenderPhysicalBeacons(void*)
5046{
5047 sRenderPhysicalBeacons = !sRenderPhysicalBeacons;
5048}
5049
5050// static
5051BOOL LLPipeline::getRenderPhysicalBeacons(void*)
5052{
5053 return sRenderPhysicalBeacons;
5054}
5055
5056// static
5057void LLPipeline::toggleRenderParticleBeacons(void*)
5058{
5059 sRenderParticleBeacons = !sRenderParticleBeacons;
5060}
5061
5062// static
5063BOOL LLPipeline::getRenderParticleBeacons(void*)
5064{
5065 return sRenderParticleBeacons;
5066}
5067
5068// static
5069void LLPipeline::toggleRenderSoundBeacons(void*)
5070{
5071 sRenderSoundBeacons = !sRenderSoundBeacons;
5072}
5073
5074// static
5075BOOL LLPipeline::getRenderSoundBeacons(void*)
5076{
5077 return sRenderSoundBeacons;
5078}
5079
5080//===============================
5081// LLGLSL Shader implementation
5082//===============================
5083LLGLSLShader::LLGLSLShader()
5084: mProgramObject(0)
5085{ }
5086
5087void 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
5116void 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
5130void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count)
5131{
5132 for (S32 i = 0; i < count; i++)
5133 {
5134 attachObject(objects[i]);
5135 }
5136}
5137
5138BOOL 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
5178void 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
5225GLint 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
5236BOOL 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
5266BOOL LLGLSLShader::link(BOOL suppress_errors)
5267{
5268 return gPipeline.linkProgramObject(mProgramObject, suppress_errors);
5269}
5270
5271void LLGLSLShader::bind()
5272{
5273 glUseProgramObjectARB(mProgramObject);
5274 if (mAttribute.size() > 0)
5275 {
5276 gPipeline.mMaterialIndex = mAttribute[0];
5277 }
5278}
5279
5280void 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
5289S32 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
5304S32 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
5315void 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
5323void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v)
5324{
5325 if (mAttribute[index] > 0)
5326 {
5327 glVertexAttrib4fvARB(mAttribute[index], v);
5328 }
5329}
5330
5331LLViewerObject* 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