pipeline.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "pipeline.h"
00035 
00036 // library includes
00037 #include "audioengine.h" // For MAX_BUFFERS for debugging.
00038 #include "imageids.h"
00039 #include "llerror.h"
00040 #include "llviewercontrol.h"
00041 #include "llfasttimer.h"
00042 #include "llfontgl.h"
00043 #include "llmemory.h"
00044 #include "llmemtype.h"
00045 #include "llnamevalue.h"
00046 #include "llprimitive.h"
00047 #include "llvolume.h"
00048 #include "material_codes.h"
00049 #include "timing.h"
00050 #include "v3color.h"
00051 #include "llui.h" 
00052 #include "llglheaders.h"
00053 #include "llglimmediate.h"
00054 
00055 // newview includes
00056 #include "llagent.h"
00057 #include "lldrawable.h"
00058 #include "lldrawpoolalpha.h"
00059 #include "lldrawpoolavatar.h"
00060 #include "lldrawpoolground.h"
00061 #include "lldrawpoolbump.h"
00062 #include "lldrawpooltree.h"
00063 #include "lldrawpoolwater.h"
00064 #include "llface.h"
00065 #include "llfeaturemanager.h"
00066 #include "llfloatertelehub.h"
00067 #include "llframestats.h"
00068 #include "llgldbg.h"
00069 #include "llhudmanager.h"
00070 #include "lllightconstants.h"
00071 #include "llresmgr.h"
00072 #include "llselectmgr.h"
00073 #include "llsky.h"
00074 #include "lltracker.h"
00075 #include "lltool.h"
00076 #include "lltoolmgr.h"
00077 #include "llviewercamera.h"
00078 #include "llviewerimagelist.h"
00079 #include "llviewerobject.h"
00080 #include "llviewerobjectlist.h"
00081 #include "llviewerparcelmgr.h"
00082 #include "llviewerregion.h" // for audio debugging.
00083 #include "llviewerwindow.h" // For getSpinAxis
00084 #include "llvoavatar.h"
00085 #include "llvoground.h"
00086 #include "llvosky.h"
00087 #include "llvotree.h"
00088 #include "llvovolume.h"
00089 #include "llvosurfacepatch.h"
00090 #include "llvowater.h"
00091 #include "llvotree.h"
00092 #include "llvopartgroup.h"
00093 #include "llworld.h"
00094 #include "llcubemap.h"
00095 #include "lldebugmessagebox.h"
00096 #include "llglslshader.h"
00097 #include "llviewerjoystick.h"
00098 #include "llviewerdisplay.h"
00099 #include "llwlparammanager.h"
00100 #include "llwaterparammanager.h"
00101 #include "llspatialpartition.h"
00102 #include "llmutelist.h"
00103 
00104 #ifdef _DEBUG
00105 // Debug indices is disabled for now for debug performance - djs 4/24/02
00106 //#define DEBUG_INDICES
00107 #else
00108 //#define DEBUG_INDICES
00109 #endif
00110 
00111 void render_ui_and_swap_if_needed();
00112 
00113 const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f;
00114 const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f;
00115 const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
00116 const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
00117 const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40;
00118 const S32 MAX_OFFSCREEN_GEOMETRY_CHANGES_PER_FRAME = 10;
00119 const U32 REFLECTION_MAP_RES = 128;
00120 
00121 // Max number of occluders to search for. JC
00122 const S32 MAX_OCCLUDER_COUNT = 2;
00123 
00124 extern S32 gBoxFrame;
00125 extern BOOL gRenderLightGlows;
00126 extern BOOL gHideSelectedObjects;
00127 extern BOOL gDisplaySwapBuffers;
00128 extern BOOL gDebugGL;
00129 
00130 // hack counter for rendering a fixed number of frames after toggling
00131 // fullscreen to work around DEV-5361
00132 static S32 sDelayedVBOEnable = 0;
00133 
00134 BOOL    gAvatarBacklight = FALSE;
00135 
00136 BOOL    gRenderForSelect = FALSE;
00137 
00138 BOOL    gDebugPipeline = FALSE;
00139 LLPipeline gPipeline;
00140 const LLMatrix4* gGLLastMatrix = NULL;
00141 
00142 //----------------------------------------
00143 
00144 U32 nhpo2(U32 v) 
00145 {
00146         U32 r = 1;
00147         while (r < v) {
00148                 r *= 2;
00149         }
00150         return r;
00151 }
00152 
00153 glh::matrix4f glh_copy_matrix(GLdouble* src)
00154 {
00155         glh::matrix4f ret;
00156         for (U32 i = 0; i < 16; i++)
00157         {
00158                 ret.m[i] = (F32) src[i];
00159         }
00160         return ret;
00161 }
00162 
00163 glh::matrix4f glh_get_current_modelview()
00164 {
00165         return glh_copy_matrix(gGLModelView);
00166 }
00167 
00168 glh::matrix4f glh_get_current_projection()
00169 {
00170         return glh_copy_matrix(gGLProjection);
00171 }
00172 
00173 void glh_copy_matrix(const glh::matrix4f& src, GLdouble* dst)
00174 {
00175         for (U32 i = 0; i < 16; i++)
00176         {
00177                 dst[i] = src.m[i];
00178         }
00179 }
00180 
00181 void glh_set_current_modelview(const glh::matrix4f& mat)
00182 {
00183         glh_copy_matrix(mat, gGLModelView);
00184 }
00185 
00186 void glh_set_current_projection(glh::matrix4f& mat)
00187 {
00188         glh_copy_matrix(mat, gGLProjection);
00189 }
00190 
00191 glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar)
00192 {
00193         glh::matrix4f ret(
00194                 2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left),
00195                 0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom),
00196                 0.f, 0.f, -2.f/(zfar-znear),  -(zfar+znear)/(zfar-znear),
00197                 0.f, 0.f, 0.f, 1.f);
00198 
00199         return ret;
00200 }
00201 
00202 //----------------------------------------
00203 
00204 S32             LLPipeline::sCompiles = 0;
00205 
00206 BOOL    LLPipeline::sDynamicLOD = TRUE;
00207 BOOL    LLPipeline::sShowHUDAttachments = TRUE;
00208 BOOL    LLPipeline::sRenderPhysicalBeacons = TRUE;
00209 BOOL    LLPipeline::sRenderScriptedBeacons = FALSE;
00210 BOOL    LLPipeline::sRenderScriptedTouchBeacons = TRUE;
00211 BOOL    LLPipeline::sRenderParticleBeacons = FALSE;
00212 BOOL    LLPipeline::sRenderSoundBeacons = FALSE;
00213 BOOL    LLPipeline::sRenderBeacons = FALSE;
00214 BOOL    LLPipeline::sRenderHighlight = TRUE;
00215 BOOL    LLPipeline::sRenderProcessBeacons = FALSE;
00216 S32             LLPipeline::sUseOcclusion = 0;
00217 BOOL    LLPipeline::sFastAlpha = TRUE;
00218 BOOL    LLPipeline::sDisableShaders = FALSE;
00219 BOOL    LLPipeline::sRenderBump = TRUE;
00220 BOOL    LLPipeline::sUseFarClip = TRUE;
00221 BOOL    LLPipeline::sSkipUpdate = FALSE;
00222 BOOL    LLPipeline::sDynamicReflections = FALSE;
00223 BOOL    LLPipeline::sWaterReflections = FALSE;
00224 BOOL    LLPipeline::sRenderGlow = FALSE;
00225 BOOL    LLPipeline::sReflectionRender = FALSE;
00226 BOOL    LLPipeline::sImpostorRender = FALSE;
00227 BOOL    LLPipeline::sUnderWaterRender = FALSE;
00228 BOOL    LLPipeline::sTextureBindTest = FALSE;
00229 BOOL    LLPipeline::sRenderFrameTest = FALSE;
00230 
00231 static LLCullResult* sCull = NULL;
00232 
00233 static const U32 gl_cube_face[] = 
00234 {
00235         GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
00236         GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
00237         GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
00238         GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
00239         GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
00240         GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
00241 };
00242 
00243 void validate_framebuffer_object();
00244 
00245 LLPipeline::LLPipeline() :
00246         mCubeBuffer(NULL),
00247         mInitialized(FALSE),
00248         mVertexShadersEnabled(FALSE),
00249         mVertexShadersLoaded(0),
00250         mLastRebuildPool(NULL),
00251         mAlphaPool(NULL),
00252         mSkyPool(NULL),
00253         mTerrainPool(NULL),
00254         mWaterPool(NULL),
00255         mGroundPool(NULL),
00256         mSimplePool(NULL),
00257         mInvisiblePool(NULL),
00258         mGlowPool(NULL),
00259         mBumpPool(NULL),
00260         mWLSkyPool(NULL),
00261         mLightMask(0),
00262         mLightMovingMask(0)
00263 {
00264         //mFramebuffer[0] = mFramebuffer[1] = mFramebuffer[2] = mFramebuffer[3] = 0;
00265         mBlurCubeBuffer[0] = mBlurCubeBuffer[1] = mBlurCubeBuffer[2] = 0;
00266         mBlurCubeTexture[0] = mBlurCubeTexture[1] = mBlurCubeTexture[2] = 0;
00267 
00268         //mDepthbuffer[0] = mDepthbuffer[1] = 0;
00269         mCubeFrameBuffer = 0;
00270         mCubeDepth = 0;
00271 }
00272 
00273 void LLPipeline::init()
00274 {
00275         LLMemType mt(LLMemType::MTYPE_PIPELINE);
00276 
00277         sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
00278         sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
00279 
00280         mInitialized = TRUE;
00281         
00282         stop_glerror();
00283 
00284         //create render pass pools
00285         getPool(LLDrawPool::POOL_ALPHA);
00286         getPool(LLDrawPool::POOL_SIMPLE);
00287         getPool(LLDrawPool::POOL_INVISIBLE);
00288         getPool(LLDrawPool::POOL_BUMP);
00289         getPool(LLDrawPool::POOL_GLOW);
00290 
00291         mTrianglesDrawnStat.reset();
00292         resetFrameStats();
00293 
00294         mRenderTypeMask = 0xffffffff;   // All render types start on
00295         mRenderDebugFeatureMask = 0xffffffff; // All debugging features on
00296         mRenderDebugMask = 0;   // All debug starts off
00297 
00298         mOldRenderDebugMask = mRenderDebugMask;
00299         
00300         mBackfaceCull = TRUE;
00301 
00302         stop_glerror();
00303         
00304         // Enable features
00305                 
00306         LLShaderMgr::setShaders();
00307 
00308         stop_glerror();
00309 }
00310 
00311 LLPipeline::~LLPipeline()
00312 {
00313 
00314 }
00315 
00316 void LLPipeline::cleanup()
00317 {
00318         assertInitialized();
00319 
00320         for(pool_set_t::iterator iter = mPools.begin();
00321                 iter != mPools.end(); )
00322         {
00323                 pool_set_t::iterator curiter = iter++;
00324                 LLDrawPool* poolp = *curiter;
00325                 if (poolp->isFacePool())
00326                 {
00327                         LLFacePool* face_pool = (LLFacePool*) poolp;
00328                         if (face_pool->mReferences.empty())
00329                         {
00330                                 mPools.erase(curiter);
00331                                 removeFromQuickLookup( poolp );
00332                                 delete poolp;
00333                         }
00334                 }
00335                 else
00336                 {
00337                         mPools.erase(curiter);
00338                         removeFromQuickLookup( poolp );
00339                         delete poolp;
00340                 }
00341         }
00342         
00343         if (!mTerrainPools.empty())
00344         {
00345                 llwarns << "Terrain Pools not cleaned up" << llendl;
00346         }
00347         if (!mTreePools.empty())
00348         {
00349                 llwarns << "Tree Pools not cleaned up" << llendl;
00350         }
00351                 
00352         delete mAlphaPool;
00353         mAlphaPool = NULL;
00354         delete mSkyPool;
00355         mSkyPool = NULL;
00356         delete mTerrainPool;
00357         mTerrainPool = NULL;
00358         delete mWaterPool;
00359         mWaterPool = NULL;
00360         delete mGroundPool;
00361         mGroundPool = NULL;
00362         delete mSimplePool;
00363         mSimplePool = NULL;
00364         delete mInvisiblePool;
00365         mInvisiblePool = NULL;
00366         delete mGlowPool;
00367         mGlowPool = NULL;
00368         delete mBumpPool;
00369         mBumpPool = NULL;
00370         // don't delete wl sky pool it was handled above in the for loop
00371         //delete mWLSkyPool;
00372         mWLSkyPool = NULL;
00373 
00374         releaseGLBuffers();
00375 
00376         mBloomImagep = NULL;
00377         mBloomImage2p = NULL;
00378         mFaceSelectImagep = NULL;
00379 
00380         mMovedBridge.clear();
00381 
00382         mInitialized = FALSE;
00383 }
00384 
00385 //============================================================================
00386 
00387 void LLPipeline::destroyGL() 
00388 {
00389         stop_glerror();
00390         unloadShaders();
00391         mHighlightFaces.clear();
00392         
00393         resetDrawOrders();
00394 
00395         resetVertexBuffers();
00396 
00397         releaseGLBuffers();
00398 
00399         if (LLVertexBuffer::sEnableVBOs)
00400         {
00401                 // render 30 frames after switching to work around DEV-5361
00402                 sDelayedVBOEnable = 30;
00403                 LLVertexBuffer::sEnableVBOs = FALSE;
00404         }
00405 }
00406 
00407 void LLPipeline::resizeScreenTexture()
00408 {
00409         if (gPipeline.canUseVertexShaders() && assertInitialized())
00410         {
00411                 GLuint resX = gViewerWindow->getWindowDisplayWidth();
00412                 GLuint resY = gViewerWindow->getWindowDisplayHeight();
00413         
00414                 U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
00415                 if (res_mod > 1)
00416                 {
00417                         resX /= res_mod;
00418                         resY /= res_mod;
00419                 }
00420         
00421                 mScreen.release();
00422                 mScreen.allocate(resX, resY, GL_RGBA, TRUE, GL_TEXTURE_RECTANGLE_ARB);          
00423 
00424                 llinfos << "RESIZED SCREEN TEXTURE: " << resX << "x" << resY << llendl;
00425         }
00426 }
00427 
00428 
00429 void LLPipeline::releaseGLBuffers()
00430 {
00431         assertInitialized();
00432         
00433         if (mCubeBuffer)
00434         {
00435                 mCubeBuffer = NULL;
00436         }
00437 
00438         if (mCubeFrameBuffer)
00439         {
00440                 glDeleteFramebuffersEXT(1, &mCubeFrameBuffer);
00441                 glDeleteRenderbuffersEXT(1, &mCubeDepth);
00442                 mCubeDepth = mCubeFrameBuffer = 0;
00443         }
00444 
00445         /*if (mFramebuffer[0])
00446         {
00447                 glDeleteFramebuffersEXT(4, mFramebuffer);
00448                 mFramebuffer[0] = mFramebuffer[1] = mFramebuffer[2] = mFramebuffer[3] = 0;
00449         }*/
00450 
00451         if (mBlurCubeBuffer[0])
00452         {
00453                 glDeleteFramebuffersEXT(3, mBlurCubeBuffer);
00454                 mBlurCubeBuffer[0] = mBlurCubeBuffer[1] = mBlurCubeBuffer[2] = 0;
00455         }
00456 
00457         if (mBlurCubeTexture[0])
00458         {
00459                 glDeleteTextures(3, mBlurCubeTexture);
00460                 mBlurCubeTexture[0] = mBlurCubeTexture[1] = mBlurCubeTexture[2] = 0;
00461         }
00462 
00463         mWaterRef.release();
00464         mWaterDis.release();
00465         mScreen.release();
00466 
00467         for (U32 i = 0; i < 3; i++)
00468         {
00469                 mGlow[i].release();
00470         }
00471 
00472         LLVOAvatar::resetImpostors();
00473 }
00474 
00475 void LLPipeline::createGLBuffers()
00476 {
00477         assertInitialized();
00478 
00479         if (LLPipeline::sDynamicReflections ||
00480                 LLPipeline::sWaterReflections)
00481         { //water reflection texture
00482                 U32 res = (U32) gSavedSettings.getS32("RenderWaterRefResolution");
00483                         
00484                 mWaterRef.allocate(res,res,GL_RGBA,TRUE);
00485                 mWaterDis.allocate(res,res,GL_RGBA,TRUE);
00486 
00487                 if (LLPipeline::sDynamicReflections)
00488                 {
00489                         //reflection map generation buffers
00490                         if (mCubeFrameBuffer == 0)
00491                         {
00492                                 glGenFramebuffersEXT(1, &mCubeFrameBuffer);
00493                                 glGenRenderbuffersEXT(1, &mCubeDepth);
00494 
00495                                 U32 res = REFLECTION_MAP_RES;
00496 
00497                                 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mCubeDepth);
00498                                                 
00499                                 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT,res,res);
00500                                                         
00501                                 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
00502                         }
00503 
00504                         if (mCubeBuffer.isNull())
00505                         {
00506                                 res = 128;
00507                                 mCubeBuffer = new LLCubeMap();
00508                                 mCubeBuffer->initGL();
00509                                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCubeBuffer->getGLName());
00510                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00511                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00512                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00513                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00514                                         
00515                                 for (U32 i = 0; i < 6; i++)
00516                                 {
00517                                         glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL); 
00518                                 }
00519                         }
00520 
00521                         if (mBlurCubeBuffer[0] == 0)
00522                         {
00523                                 glGenFramebuffersEXT(3, mBlurCubeBuffer);
00524                         }
00525 
00526                         if (mBlurCubeTexture[0] == 0)
00527                         {
00528                                 glGenTextures(3, mBlurCubeTexture);
00529                         }
00530 
00531                         res = (U32) gSavedSettings.getS32("RenderReflectionRes");
00532 
00533                         for (U32 j = 0; j < 3; j++)
00534                         {
00535                                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mBlurCubeTexture[j]);
00536                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00537                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00538                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00539                                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00540                                         
00541                                 for (U32 i = 0; i < 6; i++)
00542                                 {
00543                                         glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL); 
00544                                 }
00545                         }
00546                 }
00547         }
00548 
00549         stop_glerror();
00550 
00551         if (LLPipeline::sRenderGlow)
00552         { //screen space glow buffers
00553                 const U32 glow_res = llmax(1, 
00554                         llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow")));
00555 
00556                 for (U32 i = 0; i < 3; i++)
00557                 {
00558                         mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE);
00559                 }
00560         }
00561 
00562         GLuint resX = gViewerWindow->getWindowDisplayWidth();
00563         GLuint resY = gViewerWindow->getWindowDisplayHeight();
00564         
00565         mScreen.allocate(resX, resY, GL_RGBA, TRUE, GL_TEXTURE_RECTANGLE_ARB);
00566 }
00567 
00568 void LLPipeline::restoreGL() 
00569 {
00570         assertInitialized();
00571 
00572         if (mVertexShadersEnabled)
00573         {
00574                 LLShaderMgr::setShaders();
00575         }
00576 
00577         for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
00578                         iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
00579         {
00580                 LLViewerRegion* region = *iter;
00581                 for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
00582                 {
00583                         LLSpatialPartition* part = region->getSpatialPartition(i);
00584                         if (part)
00585                         {
00586                                 part->restoreGL();
00587                         }
00588                 }
00589         }
00590 }
00591 
00592 
00593 BOOL LLPipeline::canUseVertexShaders()
00594 {
00595         if (!gGLManager.mHasVertexShader ||
00596                 !gGLManager.mHasFragmentShader ||
00597                 !LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") ||
00598                 (assertInitialized() && mVertexShadersLoaded != 1) )
00599         {
00600                 return FALSE;
00601         }
00602         else
00603         {
00604                 return TRUE;
00605         }
00606 }
00607 
00608 BOOL LLPipeline::canUseWindLightShaders() const
00609 {
00610         return (!LLPipeline::sDisableShaders &&
00611                         gWLSkyProgram.mProgramObject != 0 &&
00612                         LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_WINDLIGHT) > 1);
00613 }
00614 
00615 BOOL LLPipeline::canUseWindLightShadersOnObjects() const
00616 {
00617         return (canUseWindLightShaders() 
00618                 && LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT) > 0);
00619 }
00620 
00621 void LLPipeline::unloadShaders()
00622 {
00623         LLShaderMgr::unloadShaders();
00624 
00625         mVertexShadersLoaded = 0;
00626 }
00627 
00628 void LLPipeline::assertInitializedDoError()
00629 {
00630         llerrs << "LLPipeline used when uninitialized." << llendl;
00631 }
00632 
00633 //============================================================================
00634 
00635 void LLPipeline::enableShadows(const BOOL enable_shadows)
00636 {
00637         //should probably do something here to wrangle shadows....      
00638 }
00639 
00640 S32 LLPipeline::getMaxLightingDetail() const
00641 {
00642         /*if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)
00643         {
00644                 return 3;
00645         }
00646         else*/
00647         {
00648                 return 1;
00649         }
00650 }
00651 
00652 S32 LLPipeline::setLightingDetail(S32 level)
00653 {
00654         assertInitialized();
00655 
00656         if (level < 0)
00657         {
00658                 level = gSavedSettings.getS32("RenderLightingDetail");
00659         }
00660         level = llclamp(level, 0, getMaxLightingDetail());
00661         if (level != mLightingDetail)
00662         {
00663                 gSavedSettings.setS32("RenderLightingDetail", level);
00664                 
00665                 mLightingDetail = level;
00666 
00667                 if (mVertexShadersLoaded == 1)
00668                 {
00669                         LLShaderMgr::setShaders();
00670                 }
00671         }
00672         return mLightingDetail;
00673 }
00674 
00675 class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable>
00676 {
00677 public:
00678         const std::set<LLViewerImage*>& mTextures;
00679 
00680         LLOctreeDirtyTexture(const std::set<LLViewerImage*>& textures) : mTextures(textures) { }
00681 
00682         virtual void visit(const LLOctreeNode<LLDrawable>* node)
00683         {
00684                 LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
00685 
00686                 if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty())
00687                 {
00688                         for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
00689                         {
00690                                 for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) 
00691                                 {
00692                                         LLDrawInfo* params = *j;
00693                                         if (mTextures.find(params->mTexture) != mTextures.end())
00694                                         { 
00695                                                 group->setState(LLSpatialGroup::GEOM_DIRTY);
00696                                         }
00697                                 }
00698                         }
00699                 }
00700 
00701                 for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
00702                 {
00703                         LLSpatialBridge* bridge = *i;
00704                         traverse(bridge->mOctree);
00705                 }
00706         }
00707 };
00708 
00709 // Called when a texture changes # of channels (causes faces to move to alpha pool)
00710 void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerImage*>& textures)
00711 {
00712         assertInitialized();
00713 
00714         // *TODO: This is inefficient and causes frame spikes; need a better way to do this
00715         //        Most of the time is spent in dirty.traverse.
00716 
00717         for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
00718         {
00719                 LLDrawPool *poolp = *iter;
00720                 if (poolp->isFacePool())
00721                 {
00722                         ((LLFacePool*) poolp)->dirtyTextures(textures);
00723                 }
00724         }
00725         
00726         LLOctreeDirtyTexture dirty(textures);
00727         for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
00728                         iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
00729         {
00730                 LLViewerRegion* region = *iter;
00731                 for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
00732                 {
00733                         LLSpatialPartition* part = region->getSpatialPartition(i);
00734                         if (part)
00735                         {
00736                                 dirty.traverse(part->mOctree);
00737                         }
00738                 }
00739         }
00740 }
00741 
00742 LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0)
00743 {
00744         assertInitialized();
00745 
00746         LLDrawPool *poolp = NULL;
00747         switch( type )
00748         {
00749         case LLDrawPool::POOL_SIMPLE:
00750                 poolp = mSimplePool;
00751                 break;
00752 
00753         case LLDrawPool::POOL_INVISIBLE:
00754                 poolp = mInvisiblePool;
00755                 break;
00756 
00757         case LLDrawPool::POOL_GLOW:
00758                 poolp = mGlowPool;
00759                 break;
00760 
00761         case LLDrawPool::POOL_TREE:
00762                 poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 );
00763                 break;
00764 
00765         case LLDrawPool::POOL_TERRAIN:
00766                 poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 );
00767                 break;
00768 
00769         case LLDrawPool::POOL_BUMP:
00770                 poolp = mBumpPool;
00771                 break;
00772 
00773         case LLDrawPool::POOL_ALPHA:
00774                 poolp = mAlphaPool;
00775                 break;
00776 
00777         case LLDrawPool::POOL_AVATAR:
00778                 break; // Do nothing
00779 
00780         case LLDrawPool::POOL_SKY:
00781                 poolp = mSkyPool;
00782                 break;
00783 
00784         case LLDrawPool::POOL_WATER:
00785                 poolp = mWaterPool;
00786                 break;
00787 
00788         case LLDrawPool::POOL_GROUND:
00789                 poolp = mGroundPool;
00790                 break;
00791 
00792         case LLDrawPool::POOL_WL_SKY:
00793                 poolp = mWLSkyPool;
00794                 break;
00795 
00796         default:
00797                 llassert(0);
00798                 llerrs << "Invalid Pool Type in  LLPipeline::findPool() type=" << type << llendl;
00799                 break;
00800         }
00801 
00802         return poolp;
00803 }
00804 
00805 
00806 LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerImage *tex0)
00807 {
00808         LLMemType mt(LLMemType::MTYPE_PIPELINE);
00809         LLDrawPool *poolp = findPool(type, tex0);
00810         if (poolp)
00811         {
00812                 return poolp;
00813         }
00814 
00815         LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0);
00816         addPool( new_poolp );
00817 
00818         return new_poolp;
00819 }
00820 
00821 
00822 // static
00823 LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerImage* imagep)
00824 {
00825         LLMemType mt(LLMemType::MTYPE_PIPELINE);
00826         U32 type = getPoolTypeFromTE(te, imagep);
00827         return gPipeline.getPool(type, imagep);
00828 }
00829 
00830 //static 
00831 U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerImage* imagep)
00832 {
00833         LLMemType mt(LLMemType::MTYPE_PIPELINE);
00834         
00835         if (!te || !imagep)
00836         {
00837                 return 0;
00838         }
00839                 
00840         bool alpha = te->getColor().mV[3] < 0.999f;
00841         if (imagep)
00842         {
00843                 alpha = alpha || (imagep->getComponents() == 4 && ! imagep->mIsMediaTexture) || (imagep->getComponents() == 2);
00844         }
00845 
00846         if (alpha)
00847         {
00848                 return LLDrawPool::POOL_ALPHA;
00849         }
00850         else if ((te->getBumpmap() || te->getShiny()))
00851         {
00852                 return LLDrawPool::POOL_BUMP;
00853         }
00854         else
00855         {
00856                 return LLDrawPool::POOL_SIMPLE;
00857         }
00858 }
00859 
00860 
00861 void LLPipeline::addPool(LLDrawPool *new_poolp)
00862 {
00863         LLMemType mt(LLMemType::MTYPE_PIPELINE);
00864         assertInitialized();
00865         mPools.insert(new_poolp);
00866         addToQuickLookup( new_poolp );
00867 }
00868 
00869 void LLPipeline::allocDrawable(LLViewerObject *vobj)
00870 {
00871         LLMemType mt(LLMemType::MTYPE_DRAWABLE);
00872         LLDrawable *drawable = new LLDrawable();
00873         vobj->mDrawable = drawable;
00874         
00875         drawable->mVObjp     = vobj;
00876         
00877         //encompass completely sheared objects by taking 
00878         //the most extreme point possible (<1,1,0.5>)
00879         drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).magVec());
00880         if (vobj->isOrphaned())
00881         {
00882                 drawable->setState(LLDrawable::FORCE_INVISIBLE);
00883         }
00884         drawable->updateXform(TRUE);
00885 }
00886 
00887 
00888 void LLPipeline::unlinkDrawable(LLDrawable *drawable)
00889 {
00890         LLFastTimer t(LLFastTimer::FTM_PIPELINE);
00891 
00892         assertInitialized();
00893 
00894         LLPointer<LLDrawable> drawablep = drawable; // make sure this doesn't get deleted before we are done
00895         
00896         // Based on flags, remove the drawable from the queues that it's on.
00897         if (drawablep->isState(LLDrawable::ON_MOVE_LIST))
00898         {
00899                 LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep);
00900                 if (iter != mMovedList.end())
00901                 {
00902                         mMovedList.erase(iter);
00903                 }
00904         }
00905 
00906         if (drawablep->getSpatialGroup())
00907         {
00908                 if (!drawablep->getSpatialGroup()->mSpatialPartition->remove(drawablep, drawablep->getSpatialGroup()))
00909                 {
00910 #ifdef LL_RELEASE_FOR_DOWNLOAD
00911                         llwarns << "Couldn't remove object from spatial group!" << llendl;
00912 #else
00913                         llerrs << "Couldn't remove object from spatial group!" << llendl;
00914 #endif
00915                 }
00916         }
00917 
00918         mLights.erase(drawablep);
00919 }
00920 
00921 U32 LLPipeline::addObject(LLViewerObject *vobj)
00922 {
00923         LLMemType mt(LLMemType::MTYPE_DRAWABLE);
00924         if (gNoRender)
00925         {
00926                 return 0;
00927         }
00928 
00929         LLDrawable* drawablep = vobj->mDrawable;
00930 
00931         if (!drawablep)
00932         {
00933                 drawablep = vobj->createDrawable(this);
00934         }
00935         
00936         llassert(drawablep);
00937 
00938         if (vobj->getParent())
00939         {
00940                 vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1
00941         }
00942         else
00943         {
00944                 vobj->setDrawableParent(NULL); // LLPipeline::addObject 2
00945         }
00946 
00947         markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE);
00948 
00949         return 1;
00950 }
00951 
00952 
00953 void LLPipeline::resetFrameStats()
00954 {
00955         assertInitialized();
00956 
00957         mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f);
00958 
00959         if (mBatchCount > 0)
00960         {
00961                 mMeanBatchSize = gPipeline.mTrianglesDrawn/gPipeline.mBatchCount;
00962         }
00963         mTrianglesDrawn = 0;
00964         sCompiles        = 0;
00965         mVerticesRelit   = 0;
00966         mLightingChanges = 0;
00967         mGeometryChanges = 0;
00968         mNumVisibleFaces = 0;
00969 
00970         if (mOldRenderDebugMask != mRenderDebugMask)
00971         {
00972                 gObjectList.clearDebugText();
00973                 mOldRenderDebugMask = mRenderDebugMask;
00974         }
00975                 
00976 }
00977 
00978 //external functions for asynchronous updating
00979 void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep)
00980 {
00981         if (gSavedSettings.getBOOL("FreezeTime"))
00982         {
00983                 return;
00984         }
00985         if (!drawablep)
00986         {
00987                 llerrs << "updateMove called with NULL drawablep" << llendl;
00988                 return;
00989         }
00990         if (drawablep->isState(LLDrawable::EARLY_MOVE))
00991         {
00992                 return;
00993         }
00994 
00995         assertInitialized();
00996 
00997         // update drawable now
00998         drawablep->clearState(LLDrawable::MOVE_UNDAMPED); // force to DAMPED
00999         drawablep->updateMove(); // returns done
01000         drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
01001         // Put on move list so that EARLY_MOVE gets cleared
01002         if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
01003         {
01004                 mMovedList.push_back(drawablep);
01005                 drawablep->setState(LLDrawable::ON_MOVE_LIST);
01006         }
01007 }
01008 
01009 void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep)
01010 {
01011         if (gSavedSettings.getBOOL("FreezeTime"))
01012         {
01013                 return;
01014         }
01015         if (!drawablep)
01016         {
01017                 llerrs << "updateMove called with NULL drawablep" << llendl;
01018         }
01019         if (drawablep->isState(LLDrawable::EARLY_MOVE))
01020         {
01021                 return;
01022         }
01023 
01024         assertInitialized();
01025 
01026         // update drawable now
01027         drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED
01028         drawablep->updateMove();
01029         drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
01030         // Put on move list so that EARLY_MOVE gets cleared
01031         if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
01032         {
01033                 mMovedList.push_back(drawablep);
01034                 drawablep->setState(LLDrawable::ON_MOVE_LIST);
01035         }
01036 }
01037 
01038 void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)
01039 {
01040         for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin();
01041                  iter != moved_list.end(); )
01042         {
01043                 LLDrawable::drawable_vector_t::iterator curiter = iter++;
01044                 LLDrawable *drawablep = *curiter;
01045                 BOOL done = TRUE;
01046                 if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE)))
01047                 {
01048                         done = drawablep->updateMove();
01049                 }
01050                 drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);
01051                 if (done)
01052                 {
01053                         drawablep->clearState(LLDrawable::ON_MOVE_LIST);
01054                         iter = moved_list.erase(curiter);
01055                 }
01056         }
01057 }
01058 
01059 void LLPipeline::updateMove()
01060 {
01061         LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE);
01062         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01063 
01064         if (gSavedSettings.getBOOL("FreezeTime"))
01065         {
01066                 return;
01067         }
01068 
01069         assertInitialized();
01070 
01071         for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin();
01072                  iter != mRetexturedList.end(); ++iter)
01073         {
01074                 LLDrawable* drawablep = *iter;
01075                 if (drawablep && !drawablep->isDead())
01076                 {
01077                         drawablep->updateTexture();
01078                 }
01079         }
01080         mRetexturedList.clear();
01081 
01082         updateMovedList(mMovedList);
01083 
01084         for (LLDrawable::drawable_set_t::iterator iter = mActiveQ.begin();
01085                  iter != mActiveQ.end(); )
01086         {
01087                 LLDrawable::drawable_set_t::iterator curiter = iter++;
01088                 LLDrawable* drawablep = *curiter;
01089                 if (drawablep && !drawablep->isDead()) 
01090                 {
01091                         if (drawablep->isRoot() && 
01092                                 drawablep->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES && 
01093                                 (!drawablep->getParent() || !drawablep->getParent()->isActive()))
01094                         {
01095                                 drawablep->makeStatic(); // removes drawable and its children from mActiveQ
01096                                 iter = mActiveQ.upper_bound(drawablep); // next valid entry
01097                         }
01098                 }
01099                 else
01100                 {
01101                         mActiveQ.erase(curiter);
01102                 }
01103         }
01104 
01105         //balance octrees
01106         {
01107                 LLFastTimer ot(LLFastTimer::FTM_OCTREE_BALANCE);
01108 
01109                 for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
01110                         iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
01111                 {
01112                         LLViewerRegion* region = *iter;
01113                         for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
01114                         {
01115                                 LLSpatialPartition* part = region->getSpatialPartition(i);
01116                                 if (part)
01117                                 {
01118                                         part->mOctree->balance();
01119                                 }
01120                         }
01121                 }
01122         }
01123 }
01124 
01126 // Culling and occlusion testing
01128 
01129 //static
01130 F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
01131 {
01132         LLVector3 lookAt = center - camera.getOrigin();
01133         F32 dist = lookAt.magVec();
01134 
01135         //ramp down distance for nearby objects
01136         if (dist < 16.f)
01137         {
01138                 dist /= 16.f;
01139                 dist *= dist;
01140                 dist *= 16.f;
01141         }
01142 
01143         //get area of circle around node
01144         F32 app_angle = atanf(size.magVec()/dist);
01145         F32 radius = app_angle*LLDrawable::sCurPixelAngle;
01146         return radius*radius * 3.14159f;
01147 }
01148 
01149 void LLPipeline::grabReferences(LLCullResult& result)
01150 {
01151         sCull = &result;
01152 }
01153 
01154 void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip)
01155 {
01156         LLFastTimer t(LLFastTimer::FTM_CULL);
01157         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01158 
01159         grabReferences(result);
01160 
01161         sCull->clear();
01162 
01163         BOOL to_texture =       LLPipeline::sUseOcclusion > 1 &&
01164                                                 !hasRenderType(LLPipeline::RENDER_TYPE_HUD) && 
01165                                                 !sReflectionRender &&
01166                                                 gPipeline.canUseVertexShaders() &&
01167                                                 sRenderGlow;
01168 
01169         if (to_texture)
01170         {
01171                 mScreen.bindTarget();
01172         }
01173 
01174         glPushMatrix();
01175         gGLLastMatrix = NULL;
01176         glLoadMatrixd(gGLLastModelView);
01177 
01178         LLVertexBuffer::unbind();
01179         LLGLDisable blend(GL_BLEND);
01180         LLGLDisable test(GL_ALPHA_TEST);
01181         LLViewerImage::unbindTexture(0, GL_TEXTURE_2D);
01182 
01183         glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
01184         LLGLDepthTest depth(GL_TRUE, GL_FALSE);
01185 
01186         for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
01187                         iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
01188         {
01189                 LLViewerRegion* region = *iter;
01190                 if (water_clip != 0)
01191                 {
01192                         LLPlane plane(LLVector3(0,0, (F32) -water_clip), (F32) water_clip*region->getWaterHeight());
01193                         camera.setUserClipPlane(plane);
01194                 }
01195                 else
01196                 {
01197                         camera.disableUserClipPlane();
01198                 }
01199 
01200                 for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
01201                 {
01202                         LLSpatialPartition* part = region->getSpatialPartition(i);
01203                         if (part)
01204                         {
01205                                 if (hasRenderType(part->mDrawableType))
01206                                 {
01207                                         part->cull(camera);
01208                                 }
01209                         }
01210                 }
01211         }
01212 
01213         camera.disableUserClipPlane();
01214 
01215         if (gSky.mVOSkyp.notNull() && gSky.mVOSkyp->mDrawable.notNull())
01216         {
01217                 // Hack for sky - always visible.
01218                 if (hasRenderType(LLPipeline::RENDER_TYPE_SKY)) 
01219                 {
01220                         gSky.mVOSkyp->mDrawable->setVisible(camera);
01221                         sCull->pushDrawable(gSky.mVOSkyp->mDrawable);
01222                         gSky.updateCull();
01223                         stop_glerror();
01224                 }
01225         }
01226         else
01227         {
01228                 llinfos << "No sky drawable!" << llendl;
01229         }
01230 
01231         if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) && 
01232                 !gPipeline.canUseWindLightShaders() &&
01233                 gSky.mVOGroundp.notNull() && 
01234                 gSky.mVOGroundp->mDrawable.notNull() &&
01235                 !LLPipeline::sWaterReflections)
01236         {
01237                 gSky.mVOGroundp->mDrawable->setVisible(camera);
01238                 sCull->pushDrawable(gSky.mVOGroundp->mDrawable);
01239         }
01240         
01241         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
01242         glPopMatrix();
01243 
01244         if (to_texture)
01245         {
01246                 mScreen.flush();
01247                 LLRenderTarget::unbindTarget();
01248         }
01249         else if (LLPipeline::sUseOcclusion > 1)
01250         {
01251                 glFlush();
01252         }
01253 }
01254 
01255 void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
01256 {
01257         if (group->getData().empty())
01258         { 
01259                 return;
01260         }
01261         
01262         group->setVisible();
01263 
01264         if (!sSkipUpdate)
01265         {
01266                 group->updateDistance(camera);
01267         }
01268         
01269         const F32 MINIMUM_PIXEL_AREA = 16.f;
01270 
01271         if (group->mPixelArea < MINIMUM_PIXEL_AREA)
01272         {
01273                 return;
01274         }
01275 
01276         assertInitialized();
01277         
01278         if (!group->mSpatialPartition->mRenderByGroup)
01279         { //render by drawable
01280                 sCull->pushDrawableGroup(group);
01281         }
01282         else
01283         {   //render by group
01284                 sCull->pushVisibleGroup(group);
01285         }
01286 
01287         mNumVisibleNodes++;
01288 }
01289 
01290 void LLPipeline::markOccluder(LLSpatialGroup* group)
01291 {
01292         if (sUseOcclusion > 1 && group && !group->isState(LLSpatialGroup::ACTIVE_OCCLUSION))
01293         {
01294                 LLSpatialGroup* parent = group->getParent();
01295 
01296                 if (!parent || !parent->isState(LLSpatialGroup::OCCLUDED))
01297                 { //only mark top most occluders as active occlusion
01298                         sCull->pushOcclusionGroup(group);
01299                         group->setState(LLSpatialGroup::ACTIVE_OCCLUSION);
01300                                 
01301                         if (parent && 
01302                                 !parent->isState(LLSpatialGroup::ACTIVE_OCCLUSION) &&
01303                                 parent->getElementCount() == 0 &&
01304                                 parent->needsUpdate())
01305                         {
01306                                 sCull->pushOcclusionGroup(group);
01307                                 parent->setState(LLSpatialGroup::ACTIVE_OCCLUSION);
01308                         }
01309                 }
01310         }
01311 }
01312 
01313 void LLPipeline::doOcclusion(LLCamera& camera)
01314 {
01315         LLVertexBuffer::unbind();
01316         if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
01317         {
01318                 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
01319         }
01320         else
01321         {
01322                 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
01323         }
01324         LLGLDisable blend(GL_BLEND);
01325         LLGLDisable test(GL_ALPHA_TEST);
01326         LLViewerImage::unbindTexture(0, GL_TEXTURE_2D);
01327         LLGLDepthTest depth(GL_TRUE, GL_FALSE);
01328 
01329         if (LLPipeline::sUseOcclusion > 1)
01330         {
01331                 for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter)
01332                 {
01333                         LLSpatialGroup* group = *iter;
01334                         group->doOcclusion(&camera);
01335                         group->clearState(LLSpatialGroup::ACTIVE_OCCLUSION);
01336                 }
01337         }
01338 
01339         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
01340         glFlush();
01341 }
01342         
01343 BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
01344 {
01345         BOOL update_complete = drawablep->updateGeometry(priority);
01346         if (update_complete && assertInitialized())
01347         {
01348                 drawablep->setState(LLDrawable::BUILT);
01349                 mGeometryChanges++;
01350         }
01351         return update_complete;
01352 }
01353 
01354 void LLPipeline::updateGeom(F32 max_dtime)
01355 {
01356         LLTimer update_timer;
01357         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01358         LLPointer<LLDrawable> drawablep;
01359 
01360         LLFastTimer t(LLFastTimer::FTM_GEO_UPDATE);
01361 
01362         assertInitialized();
01363 
01364         if (sDelayedVBOEnable > 0)
01365         {
01366                 if (--sDelayedVBOEnable <= 0)
01367                 {
01368                         resetVertexBuffers();
01369                         LLVertexBuffer::sEnableVBOs = TRUE;
01370                 }
01371         }
01372 
01373         // notify various object types to reset internal cost metrics, etc.
01374         // for now, only LLVOVolume does this to throttle LOD changes
01375         LLVOVolume::preUpdateGeom();
01376 
01377         // Iterate through all drawables on the priority build queue,
01378         for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin();
01379                  iter != mBuildQ1.end();)
01380         {
01381                 LLDrawable::drawable_list_t::iterator curiter = iter++;
01382                 LLDrawable* drawablep = *curiter;
01383                 if (drawablep && !drawablep->isDead())
01384                 {
01385                         if (drawablep->isState(LLDrawable::IN_REBUILD_Q2))
01386                         {
01387                                 drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
01388                                 LLDrawable::drawable_list_t::iterator find = std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep);
01389                                 if (find != mBuildQ2.end())
01390                                 {
01391                                         mBuildQ2.erase(find);
01392                                 }
01393                         }
01394 
01395                         if (updateDrawableGeom(drawablep, TRUE))
01396                         {
01397                                 drawablep->clearState(LLDrawable::IN_REBUILD_Q1);
01398                                 mBuildQ1.erase(curiter);
01399                         }
01400                 }
01401                 else
01402                 {
01403                         mBuildQ1.erase(curiter);
01404                 }
01405         }
01406                 
01407         // Iterate through some drawables on the non-priority build queue
01408         S32 min_count = 16;
01409         S32 size = (S32) mBuildQ2.size();
01410         if (size > 1024)
01411         {
01412                 min_count = llclamp((S32) (size * (F32) size/4096), 16, size);
01413         }
01414                 
01415         S32 count = 0;
01416         
01417         max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime);
01418         LLSpatialGroup* last_group = NULL;
01419         LLSpatialBridge* last_bridge = NULL;
01420 
01421         for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin();
01422                  iter != mBuildQ2.end(); )
01423         {
01424                 LLDrawable::drawable_list_t::iterator curiter = iter++;
01425                 LLDrawable* drawablep = *curiter;
01426 
01427                 LLSpatialBridge* bridge = drawablep->isRoot() ? drawablep->getSpatialBridge() :
01428                                                                         drawablep->getParent()->getSpatialBridge();
01429 
01430                 if (drawablep->getSpatialGroup() != last_group && 
01431                         (!last_bridge || bridge != last_bridge) &&
01432                         (update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count)
01433                 {
01434                         break;
01435                 }
01436 
01437                 //make sure updates don't stop in the middle of a spatial group
01438                 //to avoid thrashing (objects are enqueued by group)
01439                 last_group = drawablep->getSpatialGroup();
01440                 last_bridge = bridge;
01441 
01442                 BOOL update_complete = TRUE;
01443                 if (!drawablep->isDead())
01444                 {
01445                         update_complete = updateDrawableGeom(drawablep, FALSE);
01446                         count++;
01447                 }
01448                 if (update_complete)
01449                 {
01450                         drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
01451                         mBuildQ2.erase(curiter);
01452                 }
01453         }       
01454 
01455         updateMovedList(mMovedBridge);
01456 }
01457 
01458 void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
01459 {
01460         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01461         if(!drawablep || drawablep->isDead())
01462         {
01463                 return;
01464         }
01465         
01466         if (drawablep->isSpatialBridge())
01467         {
01468                 sCull->pushBridge((LLSpatialBridge*) drawablep);
01469         }
01470         else
01471         {
01472                 sCull->pushDrawable(drawablep);
01473         }
01474 
01475         drawablep->setVisible(camera);
01476 }
01477 
01478 void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
01479 {
01480         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01481 
01482         if (!drawablep)
01483         {
01484                 llerrs << "Sending null drawable to moved list!" << llendl;
01485                 return;
01486         }
01487         
01488         if (drawablep->isDead())
01489         {
01490                 llwarns << "Marking NULL or dead drawable moved!" << llendl;
01491                 return;
01492         }
01493         
01494         if (drawablep->getParent()) 
01495         {
01496                 //ensure that parent drawables are moved first
01497                 markMoved(drawablep->getParent(), damped_motion);
01498         }
01499 
01500         assertInitialized();
01501 
01502         if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
01503         {
01504                 if (drawablep->isSpatialBridge())
01505                 {
01506                         mMovedBridge.push_back(drawablep);
01507                 }
01508                 else
01509                 {
01510                         mMovedList.push_back(drawablep);
01511                 }
01512                 drawablep->setState(LLDrawable::ON_MOVE_LIST);
01513         }
01514         if (damped_motion == FALSE)
01515         {
01516                 drawablep->setState(LLDrawable::MOVE_UNDAMPED); // UNDAMPED trumps DAMPED
01517         }
01518         else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
01519         {
01520                 drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
01521         }
01522 }
01523 
01524 void LLPipeline::markShift(LLDrawable *drawablep)
01525 {
01526         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01527 
01528         if (!drawablep || drawablep->isDead())
01529         {
01530                 return;
01531         }
01532 
01533         assertInitialized();
01534 
01535         if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST))
01536         {
01537                 drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE);
01538                 if (drawablep->getParent()) 
01539                 {
01540                         markShift(drawablep->getParent());
01541                 }
01542                 mShiftList.push_back(drawablep);
01543                 drawablep->setState(LLDrawable::ON_SHIFT_LIST);
01544         }
01545 }
01546 
01547 void LLPipeline::shiftObjects(const LLVector3 &offset)
01548 {
01549         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01550 
01551         assertInitialized();
01552 
01553         //do a swap to indicate an invalid previous frame camera
01554         render_ui_and_swap_if_needed();
01555         glClear(GL_DEPTH_BUFFER_BIT);
01556         gDisplaySwapBuffers = FALSE;
01557 
01558         for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin();
01559                  iter != mShiftList.end(); iter++)
01560         {
01561                 LLDrawable *drawablep = *iter;
01562                 if (drawablep->isDead())
01563                 {
01564                         continue;
01565                 }       
01566                 drawablep->shiftPos(offset);    
01567                 drawablep->clearState(LLDrawable::ON_SHIFT_LIST);
01568         }
01569         mShiftList.resize(0);
01570 
01571         for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
01572                         iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
01573         {
01574                 LLViewerRegion* region = *iter;
01575                 for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
01576                 {
01577                         LLSpatialPartition* part = region->getSpatialPartition(i);
01578                         if (part)
01579                         {
01580                                 part->shift(offset);
01581                         }
01582                 }
01583         }
01584 }
01585 
01586 void LLPipeline::markTextured(LLDrawable *drawablep)
01587 {
01588         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01589 
01590         if (drawablep && !drawablep->isDead() && assertInitialized())
01591         {
01592                 mRetexturedList.insert(drawablep);
01593         }
01594 }
01595 
01596 void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority)
01597 {
01598         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01599 
01600         if (drawablep && !drawablep->isDead() && assertInitialized())
01601         {
01602                 if (!drawablep->isState(LLDrawable::BUILT))
01603                 {
01604                         priority = TRUE;
01605                 }
01606                 if (priority)
01607                 {
01608                         if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1))
01609                         {
01610                                 mBuildQ1.push_back(drawablep);
01611                                 drawablep->setState(LLDrawable::IN_REBUILD_Q1); // mark drawable as being in priority queue
01612                         }
01613                 }
01614                 else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2))
01615                 {
01616                         mBuildQ2.push_back(drawablep);
01617                         drawablep->setState(LLDrawable::IN_REBUILD_Q2); // need flag here because it is just a list
01618                 }
01619                 if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION))
01620                 {
01621                         drawablep->getVObj()->setChanged(LLXform::SILHOUETTE);
01622                 }
01623                 drawablep->setState(flag);
01624         }
01625 }
01626 
01627 void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
01628 {
01629         const U32 face_mask = (1 << LLPipeline::RENDER_TYPE_AVATAR) |
01630                                                   (1 << LLPipeline::RENDER_TYPE_GROUND) |
01631                                                   (1 << LLPipeline::RENDER_TYPE_TERRAIN) |
01632                                                   (1 << LLPipeline::RENDER_TYPE_TREE) |
01633                                                   (1 << LLPipeline::RENDER_TYPE_SKY) |
01634                                                   (1 << LLPipeline::RENDER_TYPE_WATER);
01635 
01636         if (mRenderTypeMask & face_mask)
01637         {
01638                 //clear faces from face pools
01639                 LLFastTimer t(LLFastTimer::FTM_RESET_DRAWORDER);
01640                 gPipeline.resetDrawOrders();
01641         }
01642 
01643         LLFastTimer ftm(LLFastTimer::FTM_STATESORT);
01644         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01645 
01646         //LLVertexBuffer::unbind();
01647 
01648         grabReferences(result);
01649 
01650         {
01651                 for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
01652                 {
01653                         LLSpatialGroup* group = *iter;
01654                         group->checkOcclusion();
01655                         if (sUseOcclusion && group->isState(LLSpatialGroup::OCCLUDED))
01656                         {
01657                                 markOccluder(group);
01658                         }
01659                         else
01660                         {
01661                                 group->setVisible();
01662                                 for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
01663                                 {
01664                                         markVisible(*i, camera);
01665                                 }
01666                         }
01667                 }
01668 
01669                 for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
01670                 {
01671                         LLSpatialGroup* group = *iter;
01672                         group->checkOcclusion();
01673                         if (sUseOcclusion && group->isState(LLSpatialGroup::OCCLUDED))
01674                         {
01675                                 markOccluder(group);
01676                         }
01677                         else
01678                         {
01679                                 group->setVisible();
01680                                 stateSort(group, camera);
01681                         }
01682                 }
01683         }
01684 
01685         {
01686                 for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
01687                 {
01688                         LLCullResult::bridge_list_t::iterator cur_iter = i;
01689                         LLSpatialBridge* bridge = *cur_iter;
01690                         LLSpatialGroup* group = bridge->getSpatialGroup();
01691                         if (!bridge->isDead() && group && !group->isState(LLSpatialGroup::OCCLUDED))
01692                         {
01693                                 stateSort(bridge, camera);
01694                         }
01695                 }
01696         }
01697 
01698         {
01699                 LLFastTimer ftm(LLFastTimer::FTM_STATESORT_DRAWABLE);
01700                 for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList();
01701                          iter != sCull->endVisibleList(); ++iter)
01702                 {
01703                         LLDrawable *drawablep = *iter;
01704                         if (!drawablep->isDead())
01705                         {
01706                                 stateSort(drawablep, camera);
01707                         }
01708                 }
01709         }
01710 
01711         {
01712                 LLFastTimer ftm(LLFastTimer::FTM_CLIENT_COPY);
01713                 LLVertexBuffer::clientCopy();
01714         }
01715 
01716         postSort(camera);
01717 }
01718 
01719 void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
01720 {
01721         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01722         if (!sSkipUpdate && group->changeLOD())
01723         {
01724                 for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
01725                 {
01726                         LLDrawable* drawablep = *i;
01727                         stateSort(drawablep, camera);
01728                 }
01729         }
01730 }
01731 
01732 void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
01733 {
01734         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01735         if (!sSkipUpdate && bridge->getSpatialGroup()->changeLOD())
01736         {
01737                 bridge->updateDistance(camera);
01738         }
01739 }
01740 
01741 void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
01742 {
01743         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01744                 
01745         if (!drawablep
01746                 || drawablep->isDead() 
01747                 || !hasRenderType(drawablep->getRenderType()))
01748         {
01749                 return;
01750         }
01751         
01752         if (gHideSelectedObjects)
01753         {
01754                 if (drawablep->getVObj().notNull() &&
01755                         drawablep->getVObj()->isSelected())
01756                 {
01757                         return;
01758                 }
01759         }
01760 
01761         if (drawablep->isAvatar())
01762         { //don't draw avatars beyond render distance or if we don't have a spatial group.
01763                 if ((drawablep->getSpatialGroup() == NULL) || 
01764                         (drawablep->getSpatialGroup()->mDistance > LLVOAvatar::sRenderDistance))
01765                 {
01766                         return;
01767                 }
01768         }
01769 
01770         assertInitialized();
01771 
01772         if (hasRenderType(drawablep->mRenderType))
01773         {
01774                 if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE))
01775                 {
01776                         drawablep->setVisible(camera, NULL, FALSE);
01777                 }
01778                 else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE))
01779                 {
01780                         // clear invisible flag here to avoid single frame glitch
01781                         drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE);
01782                 }
01783         }
01784 
01785         LLSpatialGroup* group = drawablep->getSpatialGroup();
01786         if (!group || group->changeLOD())
01787         {
01788                 if (!drawablep->isActive() && drawablep->isVisible())
01789                 {
01790                         if (!sSkipUpdate)
01791                         {
01792                                 drawablep->updateDistance(camera);
01793                         }
01794                 }
01795                 else if (drawablep->isAvatar() && drawablep->isVisible())
01796                 {
01797                         LLVOAvatar* vobj = (LLVOAvatar*) drawablep->getVObj().get();
01798                         vobj->updateVisibility();
01799                 }
01800         }
01801 
01802         for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
01803                         iter != drawablep->mFaces.end(); iter++)
01804         {
01805                 LLFace* facep = *iter;
01806 
01807                 if (facep->hasGeometry())
01808                 {
01809                         if (facep->getPool())
01810                         {
01811                                 facep->getPool()->enqueue(facep);
01812                         }
01813                         else
01814                         {
01815                                 break;
01816                         }
01817                 }
01818         }
01819 
01820         mNumVisibleFaces += drawablep->getNumFaces();
01821 }
01822 
01823 
01824 void forAllDrawables(LLCullResult::sg_list_t::iterator begin, 
01825                                          LLCullResult::sg_list_t::iterator end,
01826                                          void (*func)(LLDrawable*))
01827 {
01828         for (LLCullResult::sg_list_t::iterator i = begin; i != end; ++i)
01829         {
01830                 for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j)
01831                 {
01832                         func(*j);       
01833                 }
01834         }
01835 }
01836 
01837 void LLPipeline::forAllVisibleDrawables(void (*func)(LLDrawable*))
01838 {
01839         forAllDrawables(sCull->beginDrawableGroups(), sCull->endDrawableGroups(), func);
01840         forAllDrawables(sCull->beginVisibleGroups(), sCull->endVisibleGroups(), func);
01841 }
01842 
01843 //function for creating scripted beacons
01844 void renderScriptedBeacons(LLDrawable* drawablep)
01845 {
01846         LLViewerObject *vobj = drawablep->getVObj();
01847         if (vobj 
01848                 && !vobj->isAvatar() 
01849                 && !vobj->getParent()
01850                 && vobj->flagScripted())
01851         {
01852                 if (gPipeline.sRenderBeacons)
01853                 {
01854                         gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01855                 }
01856 
01857                 if (gPipeline.sRenderHighlight)
01858                 {
01859                         S32 face_id;
01860                         S32 count = drawablep->getNumFaces();
01861                         for (face_id = 0; face_id < count; face_id++)
01862                         {
01863                                 gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
01864                         }
01865                 }
01866         }
01867 }
01868 
01869 void renderScriptedTouchBeacons(LLDrawable* drawablep)
01870 {
01871         LLViewerObject *vobj = drawablep->getVObj();
01872         if (vobj 
01873                 && !vobj->isAvatar() 
01874                 && !vobj->getParent()
01875                 && vobj->flagScripted()
01876                 && vobj->flagHandleTouch())
01877         {
01878                 if (gPipeline.sRenderBeacons)
01879                 {
01880                         gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01881                 }
01882 
01883                 if (gPipeline.sRenderHighlight)
01884                 {
01885                         S32 face_id;
01886                         S32 count = drawablep->getNumFaces();
01887                         for (face_id = 0; face_id < count; face_id++)
01888                         {
01889                                 gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
01890                         }
01891                 }
01892         }
01893 }
01894 
01895 void renderPhysicalBeacons(LLDrawable* drawablep)
01896 {
01897         LLViewerObject *vobj = drawablep->getVObj();
01898         if (vobj 
01899                 && !vobj->isAvatar() 
01900                 //&& !vobj->getParent()
01901                 && vobj->usePhysics())
01902         {
01903                 if (gPipeline.sRenderBeacons)
01904                 {
01905                         gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01906                 }
01907 
01908                 if (gPipeline.sRenderHighlight)
01909                 {
01910                         S32 face_id;
01911                         S32 count = drawablep->getNumFaces();
01912                         for (face_id = 0; face_id < count; face_id++)
01913                         {
01914                                 gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
01915                         }
01916                 }
01917         }
01918 }
01919 
01920 void renderParticleBeacons(LLDrawable* drawablep)
01921 {
01922         // Look for attachments, objects, etc.
01923         LLViewerObject *vobj = drawablep->getVObj();
01924         if (vobj 
01925                 && vobj->isParticleSource())
01926         {
01927                 if (gPipeline.sRenderBeacons)
01928                 {
01929                         LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f);
01930                         gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
01931                 }
01932 
01933                 if (gPipeline.sRenderHighlight)
01934                 {
01935                         S32 face_id;
01936                         S32 count = drawablep->getNumFaces();
01937                         for (face_id = 0; face_id < count; face_id++)
01938                         {
01939                                 gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
01940                         }
01941                 }
01942         }
01943 }
01944 
01945 void renderSoundHighlights(LLDrawable* drawablep)
01946 {
01947         // Look for attachments, objects, etc.
01948         LLViewerObject *vobj = drawablep->getVObj();
01949         if (vobj && vobj->isAudioSource())
01950         {
01951                 if (gPipeline.sRenderHighlight)
01952                 {
01953                         S32 face_id;
01954                         S32 count = drawablep->getNumFaces();
01955                         for (face_id = 0; face_id < count; face_id++)
01956                         {
01957                                 gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
01958                         }
01959                 }
01960         }
01961 }
01962 
01963 void LLPipeline::postSort(LLCamera& camera)
01964 {
01965         LLMemType mt(LLMemType::MTYPE_PIPELINE);
01966         LLFastTimer ftm(LLFastTimer::FTM_STATESORT_POSTSORT);
01967 
01968         assertInitialized();
01969 
01970         //rebuild drawable geometry
01971         for (LLCullResult::sg_list_t::iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
01972         {
01973                 LLSpatialGroup* group = *i;
01974                 if (!sUseOcclusion || 
01975                         !group->isState(LLSpatialGroup::OCCLUDED))
01976                 {
01977                         group->rebuildGeom();
01978                 }
01979         }
01980 
01981         //build render map
01982         for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
01983         {
01984                 LLSpatialGroup* group = *i;
01985                 if (sUseOcclusion && 
01986                         group->isState(LLSpatialGroup::OCCLUDED))
01987                 {
01988                         continue;
01989                 }
01990                 
01991                 group->rebuildGeom();
01992                 
01993                 for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
01994                 {
01995                         LLSpatialGroup::drawmap_elem_t& src_vec = j->second;    
01996                         
01997                         for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
01998                         {
01999                                 sCull->pushDrawInfo(j->first, *k);
02000                         }
02001                 }
02002                 
02003                 LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
02004                 
02005                 if (alpha != group->mDrawMap.end())
02006                 { //store alpha groups for sorting
02007                         LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
02008                         if (!sSkipUpdate)
02009                         {
02010                                 if (bridge)
02011                                 {
02012                                         LLCamera trans_camera = bridge->transformCamera(camera);
02013                                         group->updateDistance(trans_camera);
02014                                 }
02015                                 else
02016                                 {
02017                                         group->updateDistance(camera);
02018                                 }
02019                         }
02020                         
02021                         if (hasRenderType(LLDrawPool::POOL_ALPHA))
02022                         {
02023                                 sCull->pushAlphaGroup(group);
02024                         }
02025                 }
02026         }
02027                 
02028         {
02029                 //sort by texture or bump map
02030                 for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; ++i)
02031                 {
02032                         //if (!mRenderMap[i].empty())
02033                         {
02034                                 if (i == LLRenderPass::PASS_BUMP)
02035                                 {
02036                                         std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareBump());
02037                                 }
02038                                 else 
02039                                 {
02040                                         std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareTexturePtrMatrix());
02041                                 }
02042                         }
02043                 }
02044 
02045                 std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());
02046         }
02047 
02048         // only render if the flag is set. The flag is only set if the right key is pressed, we are in edit mode or the toggle is set in the menus
02049         if (sRenderProcessBeacons)
02050         {
02051                 if (sRenderScriptedTouchBeacons)
02052                 {
02053                         // Only show the beacon on the root object.
02054                         forAllVisibleDrawables(renderScriptedTouchBeacons);
02055                 }
02056                 else
02057                 if (sRenderScriptedBeacons)
02058                 {
02059                         // Only show the beacon on the root object.
02060                         forAllVisibleDrawables(renderScriptedBeacons);
02061                 }
02062 
02063                 if (sRenderPhysicalBeacons)
02064                 {
02065                         // Only show the beacon on the root object.
02066                         forAllVisibleDrawables(renderPhysicalBeacons);
02067                 }
02068 
02069                 if (sRenderParticleBeacons)
02070                 {
02071                         forAllVisibleDrawables(renderParticleBeacons);
02072                 }
02073 
02074                 // If god mode, also show audio cues
02075                 if (sRenderSoundBeacons && gAudiop)
02076                 {
02077                         // Walk all sound sources and render out beacons for them. Note, this isn't done in the ForAllVisibleDrawables function, because some are not visible.
02078                         LLAudioEngine::source_map::iterator iter;
02079                         for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
02080                         {
02081                                 LLAudioSource *sourcep = iter->second;
02082 
02083                                 LLVector3d pos_global = sourcep->getPositionGlobal();
02084                                 LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global);
02085                                 if (gPipeline.sRenderBeacons)
02086                                 {
02087                                         //pos += LLVector3(0.f, 0.f, 0.2f);
02088                                         gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
02089                                 }
02090                         }
02091                         // now deal with highlights for all those seeable sound sources
02092                         forAllVisibleDrawables(renderSoundHighlights);
02093                 }
02094         }
02095 
02096         // If managing your telehub, draw beacons at telehub and currently selected spawnpoint.
02097         if (LLFloaterTelehub::renderBeacons())
02098         {
02099                 LLFloaterTelehub::addBeacons();
02100         }
02101 
02102         mSelectedFaces.clear();
02103         
02104         // Draw face highlights for selected faces.
02105         if (LLSelectMgr::getInstance()->getTEMode())
02106         {
02107                 struct f : public LLSelectedTEFunctor
02108                 {
02109                         virtual bool apply(LLViewerObject* object, S32 te)
02110                         {
02111                                 if (object->mDrawable)
02112                                 {
02113                                         gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te));
02114                                 }
02115                                 return true;
02116                         }
02117                 } func;
02118                 LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
02119         }
02120 }
02121 
02122 
02123 void render_hud_elements()
02124 {
02125         LLFastTimer t(LLFastTimer::FTM_RENDER_UI);
02126         gPipeline.disableLights();              
02127         
02128         LLGLDisable fog(GL_FOG);
02129         LLGLSUIDefault gls_ui;
02130 
02131         LLGLEnable stencil(GL_STENCIL_TEST);
02132         glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF);
02133         glStencilMask(0xFFFFFFFF);
02134         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
02135         
02136         gGL.color4f(1,1,1,1);
02137         if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
02138         {
02139                 gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d()
02140         
02141                 // Draw the tracking overlays
02142                 LLTracker::render3D();
02143                 
02144                 // Show the property lines
02145                 LLWorld::getInstance()->renderPropertyLines();
02146                 LLViewerParcelMgr::getInstance()->render();
02147                 LLViewerParcelMgr::getInstance()->renderParcelCollision();
02148         
02149                 // Render debugging beacons.
02150                 //gObjectList.renderObjectBeacons();
02151                 //LLHUDObject::renderAll();
02152                 //gObjectList.resetObjectBeacons();
02153         }
02154         else if (gForceRenderLandFence)
02155         {
02156                 // This is only set when not rendering the UI, for parcel snapshots
02157                 LLViewerParcelMgr::getInstance()->render();
02158         }
02159         else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
02160         {
02161                 LLHUDText::renderAllHUD();
02162         }
02163         gGL.flush();
02164 }
02165 
02166 void LLPipeline::renderHighlights()
02167 {
02168         LLMemType mt(LLMemType::MTYPE_PIPELINE);
02169 
02170         assertInitialized();
02171 
02172         // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD)
02173         // Render highlighted faces.
02174         LLColor4 color(1.f, 1.f, 1.f, 0.5f);
02175         LLGLEnable color_mat(GL_COLOR_MATERIAL);
02176         disableLights();
02177 
02178         if ((LLShaderMgr::sVertexShaderLevel[LLShaderMgr::SHADER_INTERFACE] > 0))
02179         {
02180                 gHighlightProgram.bind();
02181                 gHighlightProgram.vertexAttrib4f(LLShaderMgr::MATERIAL_COLOR,1,1,1,0.5f);
02182         }
02183         
02184         if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
02185         {
02186                 // Make sure the selection image gets downloaded and decoded
02187                 if (!mFaceSelectImagep)
02188                 {
02189                         mFaceSelectImagep = gImageList.getImage(IMG_FACE_SELECT);
02190                 }
02191                 mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA);
02192 
02193                 U32 count = mSelectedFaces.size();
02194                 for (U32 i = 0; i < count; i++)
02195                 {
02196                         LLFace *facep = mSelectedFaces[i];
02197                         if (!facep || facep->getDrawable()->isDead())
02198                         {
02199                                 llerrs << "Bad face on selection" << llendl;
02200                                 return;
02201                         }
02202                         
02203                         facep->renderSelected(mFaceSelectImagep, color);
02204                 }
02205         }
02206 
02207         if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
02208         {
02209                 // Paint 'em red!
02210                 color.setVec(1.f, 0.f, 0.f, 0.5f);
02211                 if ((LLShaderMgr::sVertexShaderLevel[LLShaderMgr::SHADER_INTERFACE] > 0))
02212                 {
02213                         gHighlightProgram.vertexAttrib4f(LLShaderMgr::MATERIAL_COLOR,1,0,0,0.5f);
02214                 }
02215                 int count = mHighlightFaces.size();
02216                 for (S32 i = 0; i < count; i++)
02217                 {
02218                         LLFace* facep = mHighlightFaces[i];
02219                         facep->renderSelected(LLViewerImage::sNullImagep, color);
02220                 }
02221         }
02222 
02223         // Contains a list of the faces of objects that are physical or
02224         // have touch-handlers.
02225         mHighlightFaces.clear();
02226 
02227         if (LLShaderMgr::sVertexShaderLevel[LLShaderMgr::SHADER_INTERFACE] > 0)
02228         {
02229                 gHighlightProgram.unbind();
02230         }
02231 }
02232 
02233 void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
02234 {
02235         LLMemType mt(LLMemType::MTYPE_PIPELINE);
02236         LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY);
02237 
02238         assertInitialized();
02239 
02240         F64 saved_modelview[16];
02241         F64 saved_projection[16];
02242 
02243         //HACK: preserve/restore matrices around HUD render
02244         if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
02245         {
02246                 for (U32 i = 0; i < 16; i++)
02247                 {
02248                         saved_modelview[i] = gGLModelView[i];
02249                         saved_projection[i] = gGLProjection[i];
02250                 }
02251         }
02252 
02254         //
02255         // Sync and verify GL state
02256         //
02257         //
02258 
02259         stop_glerror();
02260         gFrameStats.start(LLFrameStats::RENDER_SYNC);
02261 
02262         glEnableClientState(GL_VERTEX_ARRAY);
02263 
02264         LLVertexBuffer::unbind();
02265 
02266         // Do verification of GL state
02267         LLGLState::checkStates();
02268         LLGLState::checkTextureChannels();
02269         LLGLState::checkClientArrays();
02270         if (mRenderDebugMask & RENDER_DEBUG_VERIFY)
02271         {
02272                 if (!verify())
02273                 {
02274                         llerrs << "Pipeline verification failed!" << llendl;
02275                 }
02276         }
02277 
02278         
02279         
02280         //by bao
02281         //fake vertex buffer updating
02282         //to guaranttee at least updating one VBO buffer every frame
02283         //to walk around the bug caused by ATI card --> DEV-3855
02284         //
02285         if(forceVBOUpdate)
02286                 gSky.mVOSkyp->updateDummyVertexBuffer() ;
02287 
02288         gFrameStats.start(LLFrameStats::RENDER_GEOM);
02289 
02290         // Initialize lots of GL state to "safe" values
02291         glMatrixMode(GL_TEXTURE);
02292         glLoadIdentity();
02293         glMatrixMode(GL_MODELVIEW);
02294 
02295         LLGLSPipeline gls_pipeline;
02296         LLGLEnable multisample(GL_MULTISAMPLE_ARB);
02297 
02298         LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2);
02299                                 
02300         // Toggle backface culling for debugging
02301         LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0);
02302         // Set fog
02303         BOOL use_fog = hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG);
02304         LLGLEnable fog_enable(use_fog &&
02305                                                   !gPipeline.canUseWindLightShadersOnObjects() ? GL_FOG : 0);
02306         gSky.updateFog(camera.getFar());
02307         if (!use_fog)
02308         {
02309                 sUnderWaterRender = FALSE;
02310         }
02311 
02312         LLViewerImage::sDefaultImagep->bind(0);
02313         LLViewerImage::sDefaultImagep->setClamp(FALSE, FALSE);
02314         
02316         //
02317         // Actually render all of the geometry
02318         //
02319         //      
02320         stop_glerror();
02321         BOOL occlude = sUseOcclusion > 1;
02322         
02323         U32 cur_type = 0;
02324 
02325         if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING))
02326         {
02327                 gObjectList.renderObjectsForSelect(camera);
02328         }
02329         else if (gSavedSettings.getBOOL("RenderDeferred"))
02330         {
02331                 renderGeomDeferred();
02332         }
02333         else
02334         {
02335                 for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
02336                 {
02337                         LLDrawPool *poolp = *iter;
02338                         if (hasRenderType(poolp->getType()))
02339                         {
02340                                 poolp->prerender();
02341                         }
02342                 }
02343 
02344 
02345                 LLFastTimer t(LLFastTimer::FTM_POOLS);
02346                 calcNearbyLights(camera);
02347                 setupHWLights(NULL);
02348 
02349                 pool_set_t::iterator iter1 = mPools.begin();
02350                 while ( iter1 != mPools.end() )
02351                 {
02352                         LLDrawPool *poolp = *iter1;
02353                         
02354                         cur_type = poolp->getType();
02355 
02356                         if (occlude && cur_type > LLDrawPool::POOL_AVATAR)
02357                         {
02358                                 occlude = FALSE;
02359                                 gGLLastMatrix = NULL;
02360                                 glLoadMatrixd(gGLModelView);
02361                                 doOcclusion(camera);
02362                         }
02363 
02364                         pool_set_t::iterator iter2 = iter1;
02365                         if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0)
02366                         {
02367                                 LLFastTimer t(LLFastTimer::FTM_POOLRENDER);
02368 
02369                                 gGLLastMatrix = NULL;
02370                                 glLoadMatrixd(gGLModelView);
02371                         
02372                                 for( S32 i = 0; i < poolp->getNumPasses(); i++ )
02373                                 {
02374                                         poolp->beginRenderPass(i);
02375                                         for (iter2 = iter1; iter2 != mPools.end(); iter2++)
02376                                         {
02377                                                 LLDrawPool *p = *iter2;
02378                                                 if (p->getType() != cur_type)
02379                                                 {
02380                                                         break;
02381                                                 }
02382                                                 
02383                                                 p->render(i);
02384                                         }
02385                                         poolp->endRenderPass(i);
02386                                         LLVertexBuffer::unbind();
02387                                         if (gDebugGL || gDebugPipeline)
02388                                         {
02389                                                 GLint depth;
02390                                                 glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
02391                                                 if (depth > 3)
02392                                                 {
02393                                                         llerrs << "GL matrix stack corrupted!" << llendl;
02394                                                 }
02395                                                 LLGLState::checkStates();
02396                                                 LLGLState::checkTextureChannels();
02397                                                 LLGLState::checkClientArrays();
02398                                         }
02399                                 }
02400                         }
02401                         else
02402                         {
02403                                 // Skip all pools of this type
02404                                 for (iter2 = iter1; iter2 != mPools.end(); iter2++)
02405                                 {
02406                                         LLDrawPool *p = *iter2;
02407                                         if (p->getType() != cur_type)
02408                                         {
02409                                                 break;
02410                                         }
02411                                 }
02412                         }
02413                         iter1 = iter2;
02414                         stop_glerror();
02415                 }
02416         }
02417 
02418         LLVertexBuffer::unbind();
02419         LLGLState::checkStates();
02420         LLGLState::checkTextureChannels();
02421         LLGLState::checkClientArrays();
02422 
02423         gGLLastMatrix = NULL;
02424         glLoadMatrixd(gGLModelView);
02425 
02426         if (occlude)
02427         {
02428                 occlude = FALSE;
02429                 gGLLastMatrix = NULL;
02430                 glLoadMatrixd(gGLModelView);
02431                 doOcclusion(camera);
02432         }
02433 
02434         stop_glerror();
02435                 
02436         LLGLState::checkStates();
02437         LLGLState::checkTextureChannels();
02438         LLGLState::checkClientArrays();
02439 
02440         if (!sReflectionRender)
02441         {
02442                 renderHighlights();
02443         }
02444 
02445         // Contains a list of the faces of objects that are physical or
02446         // have touch-handlers.
02447         mHighlightFaces.clear();
02448 
02449         renderDebug();
02450 
02451         LLVertexBuffer::unbind();
02452         
02453         if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
02454         {
02455                 // Render debugging beacons.
02456                 gObjectList.renderObjectBeacons();
02457                 LLHUDObject::renderAll();
02458                 gObjectList.resetObjectBeacons();
02459         }
02460 
02461         //HACK: preserve/restore matrices around HUD render
02462         if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
02463         {
02464                 for (U32 i = 0; i < 16; i++)
02465                 {
02466                         gGLModelView[i] = saved_modelview[i];
02467                         gGLProjection[i] = saved_projection[i];
02468                 }
02469         }
02470 
02471         LLVertexBuffer::unbind();
02472 
02473         LLGLState::checkStates();
02474         LLGLState::checkTextureChannels();
02475         LLGLState::checkClientArrays();
02476 }
02477 
02478 void LLPipeline::renderGeomDeferred()
02479 {
02480         gDeferredDiffuseProgram.bind();
02481         gPipeline.renderObjects(LLRenderPass::PASS_SIMPLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL, TRUE);
02482         gDeferredDiffuseProgram.unbind();
02483 }
02484 
02485 void LLPipeline::addTrianglesDrawn(S32 count)
02486 {
02487         assertInitialized();
02488         mTrianglesDrawn += count;
02489         mBatchCount++;
02490         mMaxBatchSize = llmax(mMaxBatchSize, count);
02491         mMinBatchSize = llmin(mMinBatchSize, count);
02492 
02493         if (LLPipeline::sRenderFrameTest)
02494         {
02495                 gViewerWindow->getWindow()->swapBuffers();
02496                 ms_sleep(16);
02497         }
02498 }
02499 
02500 void LLPipeline::renderDebug()
02501 {
02502         LLMemType mt(LLMemType::MTYPE_PIPELINE);
02503 
02504         assertInitialized();
02505 
02506         gGL.color4f(1,1,1,1);
02507 
02508         gGLLastMatrix = NULL;
02509         glLoadMatrixd(gGLModelView);
02510         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
02511 
02512         // Debug stuff.
02513         for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
02514                         iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
02515         {
02516                 LLViewerRegion* region = *iter;
02517                 for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
02518                 {
02519                         LLSpatialPartition* part = region->getSpatialPartition(i);
02520                         if (part)
02521                         {
02522                                 if (hasRenderType(part->mDrawableType))
02523                                 {
02524                                         part->renderDebug();
02525                                 }
02526                         }
02527                 }
02528         }
02529 
02530         for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
02531         {
02532                 LLSpatialBridge* bridge = *i;
02533                 if (!bridge->isDead() && !bridge->isState(LLSpatialGroup::OCCLUDED) && hasRenderType(bridge->mDrawableType))
02534                 {
02535                         glPushMatrix();
02536                         glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
02537                         bridge->renderDebug();
02538                         glPopMatrix();
02539                 }
02540         }
02541 
02542         if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION)
02543         {
02544                 // Debug composition layers
02545                 F32 x, y;
02546 
02547                 LLGLSNoTexture gls_no_texture;
02548 
02549                 if (gAgent.getRegion())
02550                 {
02551                         gGL.begin(LLVertexBuffer::POINTS);
02552                         // Draw the composition layer for the region that I'm in.
02553                         for (x = 0; x <= 260; x++)
02554                         {
02555                                 for (y = 0; y <= 260; y++)
02556                                 {
02557                                         if ((x > 255) || (y > 255))
02558                                         {
02559                                                 gGL.color4f(1.f, 0.f, 0.f, 1.f);
02560                                         }
02561                                         else
02562                                         {
02563                                                 gGL.color4f(0.f, 0.f, 1.f, 1.f);
02564                                         }
02565                                         F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y);
02566                                         z *= 5.f;
02567                                         z += 50.f;
02568                                         gGL.vertex3f(x, y, z);
02569                                 }
02570                         }
02571                         gGL.end();
02572                 }
02573         }
02574         gGL.flush();
02575 }
02576 
02577 void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects)
02578 {
02579         assertInitialized();
02580 
02581         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
02582         gPipeline.resetDrawOrders();
02583 
02584         for (std::set<LLViewerObject*>::iterator iter = objects.begin(); iter != objects.end(); ++iter)
02585         {
02586                 stateSort((*iter)->mDrawable, *LLViewerCamera::getInstance());
02587         }
02588 
02589         LLMemType mt(LLMemType::MTYPE_PIPELINE);
02590         
02591         
02592         
02593         glMatrixMode(GL_MODELVIEW);
02594 
02595         LLGLSDefault gls_default;
02596         LLGLSObjectSelect gls_object_select;
02597         LLGLDepthTest gls_depth(GL_TRUE,GL_TRUE);
02598         disableLights();
02599         
02600         LLVertexBuffer::unbind();
02601 
02602         //for each drawpool
02603         LLGLState::checkStates();
02604         LLGLState::checkTextureChannels();
02605         LLGLState::checkClientArrays();
02606         U32 last_type = 0;
02607         
02608         for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
02609         {
02610                 LLDrawPool *poolp = *iter;
02611                 if (poolp->isFacePool() && hasRenderType(poolp->getType()))
02612                 {
02613                         LLFacePool* face_pool = (LLFacePool*) poolp;
02614                         face_pool->renderForSelect();
02615                         LLVertexBuffer::unbind();
02616                         gGLLastMatrix = NULL;
02617                         glLoadMatrixd(gGLModelView);
02618 
02619                         if (poolp->getType() != last_type)
02620                         {
02621                                 last_type = poolp->getType();
02622                                 LLGLState::checkStates();
02623                                 LLGLState::checkTextureChannels();
02624                                 LLGLState::checkClientArrays();
02625                         }
02626                 }
02627         }       
02628 
02629         LLGLEnable alpha_test(GL_ALPHA_TEST);
02630         if (gPickTransparent)
02631         {
02632                 glAlphaFunc(GL_GEQUAL, 0.0f);
02633         }
02634         else
02635         {
02636                 glAlphaFunc(GL_GREATER, 0.2f);
02637         }
02638 
02639         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,          GL_COMBINE_ARB);
02640         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,           GL_REPLACE);
02641         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB,         GL_MODULATE);
02642 
02643         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB,           GL_PRIMARY_COLOR);
02644         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB,          GL_SRC_COLOR);
02645 
02646         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB,         GL_TEXTURE);
02647         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,        GL_SRC_ALPHA);
02648 
02649         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB,         GL_PRIMARY_COLOR_ARB);
02650         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB,        GL_SRC_ALPHA);
02651 
02652         U32 prim_mask = LLVertexBuffer::MAP_VERTEX | 
02653                                         LLVertexBuffer::MAP_TEXCOORD;
02654 
02655         for (std::set<LLViewerObject*>::iterator i = objects.begin(); i != objects.end(); ++i)
02656         {
02657                 LLViewerObject* vobj = *i;
02658                 LLDrawable* drawable = vobj->mDrawable;
02659                 if (vobj->isDead() || 
02660                         vobj->isHUDAttachment() ||
02661                         (gHideSelectedObjects && vobj->isSelected()) ||
02662                         drawable->isDead() || 
02663                         !hasRenderType(drawable->getRenderType()))
02664                 {
02665                         continue;
02666                 }
02667 
02668                 for (S32 j = 0; j < drawable->getNumFaces(); ++j)
02669                 {
02670                         LLFace* facep = drawable->getFace(j);
02671                         if (!facep->getPool())
02672                         {
02673                                 facep->renderForSelect(prim_mask);
02674                         }
02675                 }
02676         }
02677 
02678         // pick HUD objects
02679         LLVOAvatar* avatarp = gAgent.getAvatarObject();
02680         if (avatarp && sShowHUDAttachments)
02681         {
02682                 glh::matrix4f save_proj(glh_get_current_projection());
02683                 glh::matrix4f save_model(glh_get_current_modelview());
02684 
02685                 U32 viewport[4];
02686 
02687                 for (U32 i = 0; i < 4; i++)
02688                 {
02689                         viewport[i] = gGLViewport[i];
02690                 }
02691                 
02692                 setup_hud_matrices(TRUE);
02693                 for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); 
02694                          iter != avatarp->mAttachmentPoints.end(); )
02695                 {
02696                         LLVOAvatar::attachment_map_t::iterator curiter = iter++;
02697                         LLViewerJointAttachment* attachmentp = curiter->second;
02698                         if (attachmentp->getIsHUDAttachment())
02699                         {
02700                                 LLViewerObject* objectp = attachmentp->getObject();
02701                                 if (objectp)
02702                                 {
02703                                         LLDrawable* drawable = objectp->mDrawable;
02704                                         if (drawable->isDead())
02705                                         {
02706                                                 continue;
02707                                         }
02708 
02709                                         for (S32 j = 0; j < drawable->getNumFaces(); ++j)
02710                                         {
02711                                                 LLFace* facep = drawable->getFace(j);
02712                                                 if (!facep->getPool())
02713                                                 {
02714                                                         facep->renderForSelect(prim_mask);
02715                                                 }
02716                                         }
02717 
02718                                         //render child faces
02719                                         for (U32 k = 0; k < drawable->getChildCount(); ++k)
02720                                         {
02721                                                 LLDrawable* child = drawable->getChild(k);
02722                                                 for (S32 l = 0; l < child->getNumFaces(); ++l)
02723                                                 {
02724                                                         LLFace* facep = child->getFace(l);
02725                                                         if (!facep->getPool())
02726                                                         {
02727                                                                 facep->renderForSelect(prim_mask);
02728                                                         }
02729                                                 }
02730                                         }
02731                                 }       
02732                         }
02733                 }
02734 
02735                 glMatrixMode(GL_PROJECTION);
02736                 glLoadMatrixf(save_proj.m);
02737                 glh_set_current_projection(save_proj);
02738 
02739                 glMatrixMode(GL_MODELVIEW);
02740                 glLoadMatrixf(save_model.m);
02741                 glh_set_current_modelview(save_model);
02742 
02743         
02744                 for (U32 i = 0; i < 4; i++)
02745                 {
02746                         gGLViewport[i] = viewport[i];
02747                 }
02748                 glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
02749         }
02750 
02751         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
02752         
02753         LLVertexBuffer::unbind();
02754         
02755         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
02756 }
02757 
02758 void LLPipeline::renderFaceForUVSelect(LLFace* facep)
02759 {
02760         if (facep) facep->renderSelectedUV();
02761 }
02762 
02763 void LLPipeline::rebuildPools()
02764 {
02765         LLMemType mt(LLMemType::MTYPE_PIPELINE);
02766 
02767         assertInitialized();
02768 
02769         S32 max_count = mPools.size();
02770         pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool);
02771         while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS)
02772         {
02773                 if (iter1 == mPools.end())
02774                 {
02775                         iter1 = mPools.begin();
02776                 }
02777                 LLDrawPool* poolp = *iter1;
02778 
02779                 if (poolp->isDead())
02780                 {
02781                         mPools.erase(iter1++);
02782                         removeFromQuickLookup( poolp );
02783                         if (poolp == mLastRebuildPool)
02784                         {
02785                                 mLastRebuildPool = NULL;
02786                         }
02787                         delete poolp;
02788                 }
02789                 else
02790                 {
02791                         mLastRebuildPool = poolp;
02792                         iter1++;
02793                 }
02794                 max_count--;
02795         }
02796 
02797         if (gAgent.getAvatarObject())
02798         {
02799                 gAgent.getAvatarObject()->rebuildHUD();
02800         }
02801 }
02802 
02803 void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
02804 {
02805         LLMemType mt(LLMemType::MTYPE_PIPELINE);
02806 
02807         assertInitialized();
02808 
02809         switch( new_poolp->getType() )
02810         {
02811         case LLDrawPool::POOL_SIMPLE:
02812                 if (mSimplePool)
02813                 {
02814                         llassert(0);
02815                         llwarns << "Ignoring duplicate simple pool." << llendl;
02816                 }
02817                 else
02818                 {
02819                         mSimplePool = (LLRenderPass*) new_poolp;
02820                 }
02821                 break;
02822 
02823         case LLDrawPool::POOL_INVISIBLE:
02824                 if (mInvisiblePool)
02825                 {
02826                         llassert(0);
02827                         llwarns << "Ignoring duplicate simple pool." << llendl;
02828                 }
02829                 else
02830                 {
02831                         mInvisiblePool = (LLRenderPass*) new_poolp;
02832                 }
02833                 break;
02834 
02835         case LLDrawPool::POOL_GLOW:
02836                 if (mGlowPool)
02837                 {
02838                         llassert(0);
02839                         llwarns << "Ignoring duplicate glow pool." << llendl;
02840                 }
02841                 else
02842                 {
02843                         mGlowPool = (LLRenderPass*) new_poolp;
02844                 }
02845                 break;
02846 
02847         case LLDrawPool::POOL_TREE:
02848                 mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
02849                 break;
02850  
02851         case LLDrawPool::POOL_TERRAIN:
02852                 mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
02853                 break;
02854 
02855         case LLDrawPool::POOL_BUMP:
02856                 if (mBumpPool)
02857                 {
02858                         llassert(0);
02859                         llwarns << "Ignoring duplicate bump pool." << llendl;
02860                 }
02861                 else
02862                 {
02863                         mBumpPool = new_poolp;
02864                 }
02865                 break;
02866 
02867         case LLDrawPool::POOL_ALPHA:
02868                 if( mAlphaPool )
02869                 {
02870                         llassert(0);
02871                         llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl;
02872                 }
02873                 else
02874                 {
02875                         mAlphaPool = new_poolp;
02876                 }
02877                 break;
02878 
02879         case LLDrawPool::POOL_AVATAR:
02880                 break; // Do nothing
02881 
02882         case LLDrawPool::POOL_SKY:
02883                 if( mSkyPool )
02884                 {
02885                         llassert(0);
02886                         llwarns << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << llendl;
02887                 }
02888                 else
02889                 {
02890                         mSkyPool = new_poolp;
02891                 }
02892                 break;
02893         
02894         case LLDrawPool::POOL_WATER:
02895                 if( mWaterPool )
02896                 {
02897                         llassert(0);
02898                         llwarns << "LLPipeline::addPool(): Ignoring duplicate Water pool" << llendl;
02899                 }
02900                 else
02901                 {
02902                         mWaterPool = new_poolp;
02903                 }
02904                 break;
02905 
02906         case LLDrawPool::POOL_GROUND:
02907                 if( mGroundPool )
02908                 {
02909                         llassert(0);
02910                         llwarns << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << llendl;
02911                 }
02912                 else
02913                 { 
02914                         mGroundPool = new_poolp;
02915                 }
02916                 break;
02917 
02918         case LLDrawPool::POOL_WL_SKY:
02919                 if( mWLSkyPool )
02920                 {
02921                         llassert(0);
02922                         llwarns << "LLPipeline::addPool(): Ignoring duplicate WLSky Pool" << llendl;
02923                 }
02924                 else
02925                 { 
02926                         mWLSkyPool = new_poolp;
02927                 }
02928                 break;
02929 
02930         default:
02931                 llassert(0);
02932                 llwarns << "Invalid Pool Type in  LLPipeline::addPool()" << llendl;
02933                 break;
02934         }
02935 }
02936 
02937 void LLPipeline::removePool( LLDrawPool* poolp )
02938 {
02939         assertInitialized();
02940         removeFromQuickLookup(poolp);
02941         mPools.erase(poolp);
02942         delete poolp;
02943 }
02944 
02945 void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
02946 {
02947         assertInitialized();
02948         LLMemType mt(LLMemType::MTYPE_PIPELINE);
02949         switch( poolp->getType() )
02950         {
02951         case LLDrawPool::POOL_SIMPLE:
02952                 llassert(mSimplePool == poolp);
02953                 mSimplePool = NULL;
02954                 break;
02955 
02956         case LLDrawPool::POOL_INVISIBLE:
02957                 llassert(mInvisiblePool == poolp);
02958                 mInvisiblePool = NULL;
02959                 break;
02960 
02961         case LLDrawPool::POOL_WL_SKY:
02962                 llassert(mWLSkyPool == poolp);
02963                 mWLSkyPool = NULL;
02964                 break;
02965 
02966         case LLDrawPool::POOL_GLOW:
02967                 llassert(mGlowPool == poolp);
02968                 mGlowPool = NULL;
02969                 break;
02970 
02971         case LLDrawPool::POOL_TREE:
02972                 #ifdef _DEBUG
02973                         {
02974                                 BOOL found = mTreePools.erase( (uintptr_t)poolp->getTexture() );
02975                                 llassert( found );
02976                         }
02977                 #else
02978                         mTreePools.erase( (uintptr_t)poolp->getTexture() );
02979                 #endif
02980                 break;
02981 
02982         case LLDrawPool::POOL_TERRAIN:
02983                 #ifdef _DEBUG
02984                         {
02985                                 BOOL found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
02986                                 llassert( found );
02987                         }
02988                 #else
02989                         mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
02990                 #endif
02991                 break;
02992 
02993         case LLDrawPool::POOL_BUMP:
02994                 llassert( poolp == mBumpPool );
02995                 mBumpPool = NULL;
02996                 break;
02997         
02998         case LLDrawPool::POOL_ALPHA:
02999                 llassert( poolp == mAlphaPool );
03000                 mAlphaPool = NULL;
03001                 break;
03002 
03003         case LLDrawPool::POOL_AVATAR:
03004                 break; // Do nothing
03005 
03006         case LLDrawPool::POOL_SKY:
03007                 llassert( poolp == mSkyPool );
03008                 mSkyPool = NULL;
03009                 break;
03010 
03011         case LLDrawPool::POOL_WATER:
03012                 llassert( poolp == mWaterPool );
03013                 mWaterPool = NULL;
03014                 break;
03015 
03016         case LLDrawPool::POOL_GROUND:
03017                 llassert( poolp == mGroundPool );
03018                 mGroundPool = NULL;
03019                 break;
03020 
03021         default:
03022                 llassert(0);
03023                 llwarns << "Invalid Pool Type in  LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl;
03024                 break;
03025         }
03026 }
03027 
03028 void LLPipeline::resetDrawOrders()
03029 {
03030         assertInitialized();
03031         // Iterate through all of the draw pools and rebuild them.
03032         for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
03033         {
03034                 LLDrawPool *poolp = *iter;
03035                 poolp->resetDrawOrders();
03036         }
03037 }
03038 
03039 //============================================================================
03040 // Once-per-frame setup of hardware lights,
03041 // including sun/moon, avatar backlight, and up to 6 local lights
03042 
03043 void LLPipeline::setupAvatarLights(BOOL for_edit)
03044 {
03045         assertInitialized();
03046 
03047         if (for_edit)
03048         {
03049                 LLColor4 diffuse(0.8f, 0.8f, 0.8f, 0.f);
03050                 LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f);  // w==0 => directional light
03051                 LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview();
03052                 LLMatrix4 camera_rot(camera_mat.getMat3());
03053                 camera_rot.invert();
03054                 LLVector4 light_pos = light_pos_cam * camera_rot;
03055                 
03056                 light_pos.normVec();
03057 
03058                 mHWLightColors[1] = diffuse;
03059                 glLightfv(GL_LIGHT1, GL_DIFFUSE,  diffuse.mV);
03060                 glLightfv(GL_LIGHT1, GL_AMBIENT,  LLColor4::black.mV);
03061                 glLightfv(GL_LIGHT1, GL_SPECULAR, LLColor4::black.mV);
03062                 glLightfv(GL_LIGHT1, GL_POSITION, light_pos.mV); 
03063                 glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION,  1.0f);
03064                 glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION,      0.0f);
03065                 glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f);
03066                 glLightf (GL_LIGHT1, GL_SPOT_EXPONENT,           0.0f);
03067                 glLightf (GL_LIGHT1, GL_SPOT_CUTOFF,                     180.0f);
03068         }
03069         else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini)
03070         {
03071                 LLVector3 opposite_pos = -1.f * mSunDir;
03072                 LLVector3 orthog_light_pos = mSunDir % LLVector3::z_axis;
03073                 LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f);
03074                 backlight_pos.normVec();
03075                         
03076                 LLColor4 light_diffuse = mSunDiffuse;
03077                 LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f);
03078                 F32 max_component = 0.001f;
03079                 for (S32 i = 0; i < 3; i++)
03080                 {
03081                         if (backlight_diffuse.mV[i] > max_component)
03082                         {
03083                                 max_component = backlight_diffuse.mV[i];
03084                         }
03085                 }
03086                 F32 backlight_mag;
03087                 if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS)
03088                 {
03089                         backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT;
03090                 }
03091                 else
03092                 {
03093                         backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT;
03094                 }
03095                 backlight_diffuse *= backlight_mag / max_component;
03096 
03097                 mHWLightColors[1] = backlight_diffuse;
03098                 glLightfv(GL_LIGHT1, GL_POSITION, backlight_pos.mV); // this is just sun/moon direction
03099                 glLightfv(GL_LIGHT1, GL_DIFFUSE,  backlight_diffuse.mV);
03100                 glLightfv(GL_LIGHT1, GL_AMBIENT,  LLColor4::black.mV);
03101                 glLightfv(GL_LIGHT1, GL_SPECULAR, LLColor4::black.mV);
03102                 glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION,  1.0f);
03103                 glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION,    0.0f);
03104                 glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f);
03105                 glLightf (GL_LIGHT1, GL_SPOT_EXPONENT,         0.0f);
03106                 glLightf (GL_LIGHT1, GL_SPOT_CUTOFF,           180.0f);
03107         }
03108         else
03109         {
03110                 mHWLightColors[1] = LLColor4::black;
03111                 glLightfv(GL_LIGHT1, GL_DIFFUSE,  LLColor4::black.mV);
03112                 glLightfv(GL_LIGHT1, GL_AMBIENT,  LLColor4::black.mV);
03113                 glLightfv(GL_LIGHT1, GL_SPECULAR, LLColor4::black.mV);
03114         }
03115 }
03116 
03117 static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist)
03118 {
03119         F32 inten = light->getLightIntensity();
03120         if (inten < .001f)
03121         {
03122                 return max_dist;
03123         }
03124         F32 radius = light->getLightRadius();
03125         BOOL selected = light->isSelected();
03126         LLVector3 dpos = light->getRenderPosition() - cam_pos;
03127         F32 dist2 = dpos.magVecSquared();
03128         if (!selected && dist2 > (max_dist + radius)*(max_dist + radius))
03129         {
03130                 return max_dist;
03131         }
03132         F32 dist = fsqrtf(dist2);
03133         dist *= 1.f / inten;
03134         dist -= radius;
03135         if (selected)
03136         {
03137                 dist -= 10000.f; // selected lights get highest priority
03138         }
03139         if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE))
03140         {
03141                 // moving lights get a little higher priority (too much causes artifacts)
03142                 dist -= light->getLightRadius()*0.25f;
03143         }
03144         return dist;
03145 }
03146 
03147 void LLPipeline::calcNearbyLights(LLCamera& camera)
03148 {
03149         assertInitialized();
03150 
03151         if (mLightingDetail >= 1)
03152         {
03153                 // mNearbyLight (and all light_set_t's) are sorted such that
03154                 // begin() == the closest light and rbegin() == the farthest light
03155                 const S32 MAX_LOCAL_LIGHTS = 6;
03156 //              LLVector3 cam_pos = gAgent.getCameraPositionAgent();
03157                 LLVector3 cam_pos = LLViewerJoystick::getInstance()->getOverrideCamera() ?
03158                                                 camera.getOrigin() : 
03159                                                 gAgent.getPositionAgent();
03160 
03161                 F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad
03162                 
03163                 // UPDATE THE EXISTING NEARBY LIGHTS
03164                 if (!LLPipeline::sSkipUpdate)
03165                 {
03166                         light_set_t cur_nearby_lights;
03167                         for (light_set_t::iterator iter = mNearbyLights.begin();
03168                                 iter != mNearbyLights.end(); iter++)
03169                         {
03170                                 const Light* light = &(*iter);
03171                                 LLDrawable* drawable = light->drawable;
03172                                 LLVOVolume* volight = drawable->getVOVolume();
03173                                 if (!volight || !drawable->isState(LLDrawable::LIGHT))
03174                                 {
03175                                         drawable->clearState(LLDrawable::NEARBY_LIGHT);
03176                                         continue;
03177                                 }
03178                                 if (light->fade <= -LIGHT_FADE_TIME)
03179                                 {
03180                                         drawable->clearState(LLDrawable::NEARBY_LIGHT);
03181                                 }
03182                                 else
03183                                 {
03184                                         F32 dist = calc_light_dist(volight, cam_pos, max_dist);
03185                                         cur_nearby_lights.insert(Light(drawable, dist, light->fade));
03186                                 }
03187                         }
03188                         mNearbyLights = cur_nearby_lights;
03189                 }
03190                 
03191                 // FIND NEW LIGHTS THAT ARE IN RANGE
03192                 light_set_t new_nearby_lights;
03193                 for (LLDrawable::drawable_set_t::iterator iter = mLights.begin();
03194                          iter != mLights.end(); ++iter)
03195                 {
03196                         LLDrawable* drawable = *iter;
03197                         LLVOVolume* light = drawable->getVOVolume();
03198                         if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT))
03199                         {
03200                                 continue;
03201                         }
03202                         if (light->isHUDAttachment())
03203                         {
03204                                 continue; // no lighting from HUD objects
03205                         }
03206                         F32 dist = calc_light_dist(light, cam_pos, max_dist);
03207                         if (dist >= max_dist)
03208                         {
03209                                 continue;
03210                         }
03211                         new_nearby_lights.insert(Light(drawable, dist, 0.f));
03212                         if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS)
03213                         {
03214                                 new_nearby_lights.erase(--new_nearby_lights.end());
03215                                 const Light& last = *new_nearby_lights.rbegin();
03216                                 max_dist = last.dist;
03217                         }
03218                 }
03219 
03220                 // INSERT ANY NEW LIGHTS
03221                 for (light_set_t::iterator iter = new_nearby_lights.begin();
03222                          iter != new_nearby_lights.end(); iter++)
03223                 {
03224                         const Light* light = &(*iter);
03225                         if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS)
03226                         {
03227                                 mNearbyLights.insert(*light);
03228                                 ((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT);
03229                         }
03230                         else
03231                         {
03232                                 // crazy cast so that we can overwrite the fade value
03233                                 // even though gcc enforces sets as const
03234                                 // (fade value doesn't affect sort so this is safe)
03235                                 Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin()))));
03236                                 if (light->dist < farthest_light->dist)
03237                                 {
03238                                         if (farthest_light->fade >= 0.f)
03239                                         {
03240                                                 farthest_light->fade = -gFrameIntervalSeconds;
03241                                         }
03242                                 }
03243                                 else
03244                                 {
03245                                         break; // none of the other lights are closer
03246                                 }
03247                         }
03248                 }
03249                 
03250         }
03251 }
03252 
03253 void LLPipeline::setupHWLights(LLDrawPool* pool)
03254 {
03255         assertInitialized();
03256 
03257         // Ambient
03258         LLColor4 ambient = gSky.getTotalAmbientColor();
03259         glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV);
03260 
03261         // Light 0 = Sun or Moon (All objects)
03262         {
03263                 if (gSky.getSunDirection().mV[2] >= NIGHTTIME_ELEVATION_COS)
03264                 {
03265                         mSunDir.setVec(gSky.getSunDirection());
03266                         mSunDiffuse.setVec(gSky.getSunDiffuseColor());
03267                 }
03268                 else
03269                 {
03270                         mSunDir.setVec(gSky.getMoonDirection());
03271                         mSunDiffuse.setVec(gSky.getMoonDiffuseColor());
03272                 }
03273 
03274                 F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]);
03275                 if (max_color > 1.f)
03276                 {
03277                         mSunDiffuse *= 1.f/max_color;
03278                 }
03279                 mSunDiffuse.clamp();
03280 
03281                 LLVector4 light_pos(mSunDir, 0.0f);
03282                 LLColor4 light_diffuse = mSunDiffuse;
03283                 mHWLightColors[0] = light_diffuse;
03284                 glLightfv(GL_LIGHT0, GL_POSITION, light_pos.mV); // this is just sun/moon direction
03285                 glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diffuse.mV);
03286                 glLightfv(GL_LIGHT0, GL_AMBIENT,  LLColor4::black.mV);
03287                 glLightfv(GL_LIGHT0, GL_SPECULAR, LLColor4::black.mV);
03288                 glLightf (GL_LIGHT0, GL_CONSTANT_ATTENUATION,  1.0f);
03289                 glLightf (GL_LIGHT0, GL_LINEAR_ATTENUATION,    0.0f);
03290                 glLightf (GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0f);
03291                 glLightf (GL_LIGHT0, GL_SPOT_EXPONENT,         0.0f);
03292                 glLightf (GL_LIGHT0, GL_SPOT_CUTOFF,           180.0f);
03293         }
03294         
03295         // Light 1 = Backlight (for avatars)
03296         // (set by enableLightsAvatar)
03297         
03298         S32 cur_light = 2;
03299         
03300         // Nearby lights = LIGHT 2-7
03301 
03302         mLightMovingMask = 0;
03303         
03304         if (mLightingDetail >= 1)
03305         {
03306                 for (light_set_t::iterator iter = mNearbyLights.begin();
03307                          iter != mNearbyLights.end(); ++iter)
03308                 {
03309                         LLDrawable* drawable = iter->drawable;
03310                         LLVOVolume* light = drawable->getVOVolume();
03311                         if (!light)
03312                         {
03313                                 continue;
03314                         }
03315                         if (drawable->isState(LLDrawable::ACTIVE))
03316                         {
03317                                 mLightMovingMask |= (1<<cur_light);
03318                         }
03319                         
03320                         LLColor4  light_color = light->getLightColor();
03321                         light_color.mV[3] = 0.0f;
03322 
03323                         F32 fade = iter->fade;
03324                         if (fade < LIGHT_FADE_TIME)
03325                         {
03326                                 // fade in/out light
03327                                 if (fade >= 0.f)
03328                                 {
03329                                         fade = fade / LIGHT_FADE_TIME;
03330                                         ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds;
03331                                 }
03332                                 else
03333                                 {
03334                                         fade = 1.f + fade / LIGHT_FADE_TIME;
03335                                         ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds;
03336                                 }
03337                                 fade = llclamp(fade,0.f,1.f);
03338                                 light_color *= fade;
03339                         }
03340 
03341                         LLVector3 light_pos(light->getRenderPosition());
03342                         LLVector4 light_pos_gl(light_pos, 1.0f);
03343         
03344                         F32 light_radius = llmax(light->getLightRadius(), 0.001f);
03345                         F32 atten, quad;
03346 
03347 #if 0 //1.9.1
03348                         if (pool->getVertexShaderLevel() > 0)
03349                         {
03350                                 atten = light_radius;
03351                                 quad = llmax(light->getLightFalloff(), 0.0001f);
03352                         }
03353                         else
03354 #endif
03355                         {
03356                                 F32 x = (3.f * (1.f + light->getLightFalloff()));
03357                                 atten = x / (light_radius); // % of brightness at radius
03358                                 quad = 0.0f;
03359                         }
03360                         mHWLightColors[cur_light] = light_color;
03361                         S32 gllight = GL_LIGHT0+cur_light;
03362                         glLightfv(gllight, GL_POSITION, light_pos_gl.mV);
03363                         glLightfv(gllight, GL_DIFFUSE,  light_color.mV);
03364                         glLightfv(gllight, GL_AMBIENT,  LLColor4::black.mV);
03365                         glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV);
03366                         glLightf (gllight, GL_CONSTANT_ATTENUATION,   0.0f);
03367                         glLightf (gllight, GL_LINEAR_ATTENUATION,     atten);
03368                         glLightf (gllight, GL_QUADRATIC_ATTENUATION,  quad);
03369                         glLightf (gllight, GL_SPOT_EXPONENT,          0.0f);
03370                         glLightf (gllight, GL_SPOT_CUTOFF,            180.0f);
03371                         cur_light++;
03372                         if (cur_light >= 8)
03373                         {
03374                                 break; // safety
03375                         }
03376                 }
03377         }
03378         for ( ; cur_light < 8 ; cur_light++)
03379         {
03380                 mHWLightColors[cur_light] = LLColor4::black;
03381                 S32 gllight = GL_LIGHT0+cur_light;
03382                 glLightfv(gllight, GL_DIFFUSE,  LLColor4::black.mV);
03383                 glLightfv(gllight, GL_AMBIENT,  LLColor4::black.mV);
03384                 glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV);
03385         }
03386 
03387         if (gAgent.getAvatarObject() &&
03388                 gAgent.getAvatarObject()->mSpecialRenderMode == 3)
03389         {
03390                 LLColor4  light_color = LLColor4::white;
03391                 light_color.mV[3] = 0.0f;
03392 
03393                 LLVector3 light_pos(LLViewerCamera::getInstance()->getOrigin());
03394                 LLVector4 light_pos_gl(light_pos, 1.0f);
03395 
03396                 F32 light_radius = 16.f;
03397                 F32 atten, quad;
03398 
03399                 {
03400                         F32 x = 3.f;
03401                         atten = x / (light_radius); // % of brightness at radius
03402                         quad = 0.0f;
03403                 }
03404                 //mHWLightColors[cur_light] = light_color;
03405                 S32 gllight = GL_LIGHT2;
03406                 glLightfv(gllight, GL_POSITION, light_pos_gl.mV);
03407                 glLightfv(gllight, GL_DIFFUSE,  light_color.mV);
03408                 glLightfv(gllight, GL_AMBIENT,  LLColor4::black.mV);
03409                 glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV);
03410                 glLightf (gllight, GL_CONSTANT_ATTENUATION,   0.0f);
03411                 glLightf (gllight, GL_LINEAR_ATTENUATION,     atten);
03412                 glLightf (gllight, GL_QUADRATIC_ATTENUATION,  quad);
03413                 glLightf (gllight, GL_SPOT_EXPONENT,          0.0f);
03414                 glLightf (gllight, GL_SPOT_CUTOFF,            180.0f);
03415         }
03416 
03417         // Init GL state
03418         glDisable(GL_LIGHTING);
03419         for (S32 gllight=GL_LIGHT0; gllight<=GL_LIGHT7; gllight++)
03420         {
03421                 glDisable(gllight);
03422         }
03423         mLightMask = 0;
03424 }
03425 
03426 void LLPipeline::enableLights(U32 mask)
03427 {
03428         assertInitialized();
03429         if (mLightingDetail == 0)
03430         {
03431                 mask &= 0xf003; // sun and backlight only (and fullbright bit)
03432         }
03433         if (mLightMask != mask)
03434         {
03435                 if (!mLightMask)
03436                 {
03437                         glEnable(GL_LIGHTING);
03438                 }
03439                 if (mask)
03440                 {
03441                         for (S32 i=0; i<8; i++)
03442                         {
03443                                 if (mask & (1<<i))
03444                                 {
03445                                         glEnable(GL_LIGHT0 + i);
03446                                         glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  mHWLightColors[i].mV);
03447                                 }
03448                                 else
03449                                 {
03450                                         glDisable(GL_LIGHT0 + i);
03451                                         glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  LLColor4::black.mV);
03452                                 }
03453                         }
03454                 }
03455                 else
03456                 {
03457                         glDisable(GL_LIGHTING);
03458                 }
03459                 mLightMask = mask;
03460                 LLColor4 ambient = gSky.getTotalAmbientColor();
03461                 glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV);
03462         }
03463 }
03464 
03465 void LLPipeline::enableLightsStatic()
03466 {
03467         assertInitialized();
03468         U32 mask = 0x01; // Sun
03469         if (mLightingDetail >= 2)
03470         {
03471                 mask |= mLightMovingMask; // Hardware moving lights
03472                 glColor4f(0.f, 0.f, 0.f, 1.0f); // no local lighting by default
03473         }
03474         else
03475         {
03476                 mask |= 0xff & (~2); // Hardware local lights
03477         }
03478         enableLights(mask);
03479 }
03480 
03481 void LLPipeline::enableLightsDynamic()
03482 {
03483         assertInitialized();
03484         U32 mask = 0xff & (~2); // Local lights
03485         enableLights(mask);
03486         if (mLightingDetail >= 2)
03487         {
03488                 glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default
03489         }
03490 
03491         LLVOAvatar* avatarp = gAgent.getAvatarObject();
03492 
03493         if (avatarp && getLightingDetail() <= 0)
03494         {
03495                 if (avatarp->mSpecialRenderMode == 0) // normal
03496                 {
03497                         gPipeline.enableLightsAvatar();
03498                 }
03499                 else if (avatarp->mSpecialRenderMode >= 1)  // anim preview
03500                 {
03501                         gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f));
03502                 }
03503         }
03504 }
03505 
03506 void LLPipeline::enableLightsAvatar()
03507 {
03508         U32 mask = 0xff; // All lights
03509         setupAvatarLights(FALSE);
03510         enableLights(mask);
03511 }
03512 
03513 void LLPipeline::enableLightsAvatarEdit(const LLColor4& color)
03514 {
03515         U32 mask = 0x2002; // Avatar backlight only, set ambient
03516         setupAvatarLights(TRUE);
03517         enableLights(mask);
03518 
03519         glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV);
03520 }
03521 
03522 void LLPipeline::enableLightsFullbright(const LLColor4& color)
03523 {
03524         assertInitialized();
03525         U32 mask = 0x1000; // Non-0 mask, set ambient
03526         enableLights(mask);
03527 
03528         glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV);
03529         if (mLightingDetail >= 2)
03530         {
03531                 glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default
03532         }
03533 }
03534 
03535 void LLPipeline::disableLights()
03536 {
03537         enableLights(0); // no lighting (full bright)
03538         glColor4f(1.f, 1.f, 1.f, 1.f); // lighting color = white by default
03539 }
03540 
03541 //============================================================================
03542 
03543 class LLMenuItemGL;
03544 class LLInvFVBridge;
03545 struct cat_folder_pair;
03546 class LLVOBranch;
03547 class LLVOLeaf;
03548 
03549 void LLPipeline::findReferences(LLDrawable *drawablep)
03550 {
03551         assertInitialized();
03552         if (mLights.find(drawablep) != mLights.end())
03553         {
03554                 llinfos << "In mLights" << llendl;
03555         }
03556         if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end())
03557         {
03558                 llinfos << "In mMovedList" << llendl;
03559         }
03560         if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end())
03561         {
03562                 llinfos << "In mShiftList" << llendl;
03563         }
03564         if (mRetexturedList.find(drawablep) != mRetexturedList.end())
03565         {
03566                 llinfos << "In mRetexturedList" << llendl;
03567         }
03568         
03569         if (mActiveQ.find(drawablep) != mActiveQ.end())
03570         {
03571                 llinfos << "In mActiveQ" << llendl;
03572         }
03573         if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end())
03574         {
03575                 llinfos << "In mBuildQ1" << llendl;
03576         }
03577         if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end())
03578         {
03579                 llinfos << "In mBuildQ2" << llendl;
03580         }
03581 
03582         S32 count;
03583         
03584         count = gObjectList.findReferences(drawablep);
03585         if (count)
03586         {
03587                 llinfos << "In other drawables: " << count << " references" << llendl;
03588         }
03589 }
03590 
03591 BOOL LLPipeline::verify()
03592 {
03593         BOOL ok = assertInitialized();
03594         if (ok) 
03595         {
03596                 for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
03597                 {
03598                         LLDrawPool *poolp = *iter;
03599                         if (!poolp->verify())
03600                         {
03601                                 ok = FALSE;
03602                         }
03603                 }
03604         }
03605 
03606         if (!ok)
03607         {
03608                 llwarns << "Pipeline verify failed!" << llendl;
03609         }
03610         return ok;
03611 }
03612 
03614 //
03615 // Collision detection
03616 //
03617 //
03618 
03620 
03640 
03641 //#define RAYAABB_EPSILON 0.00001f
03642 #define IR(x)   ((U32&)x)
03643 
03644 bool LLRayAABB(const LLVector3 &center, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon)
03645 {
03646         BOOL Inside = TRUE;
03647         LLVector3 MinB = center - size;
03648         LLVector3 MaxB = center + size;
03649         LLVector3 MaxT;
03650         MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f;
03651 
03652         // Find candidate planes.
03653         for(U32 i=0;i<3;i++)
03654         {
03655                 if(origin.mV[i] < MinB.mV[i])
03656                 {
03657                         coord.mV[i]     = MinB.mV[i];
03658                         Inside          = FALSE;
03659 
03660                         // Calculate T distances to candidate planes
03661                         if(IR(dir.mV[i]))       MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i];
03662                 }
03663                 else if(origin.mV[i] > MaxB.mV[i])
03664                 {
03665                         coord.mV[i]     = MaxB.mV[i];
03666                         Inside          = FALSE;
03667 
03668                         // Calculate T distances to candidate planes
03669                         if(IR(dir.mV[i]))       MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i];
03670                 }
03671         }
03672 
03673         // Ray origin inside bounding box
03674         if(Inside)
03675         {
03676                 coord = origin;
03677                 return true;
03678         }
03679 
03680         // Get largest of the maxT's for final choice of intersection
03681         U32 WhichPlane = 0;
03682         if(MaxT.mV[1] > MaxT.mV[WhichPlane])    WhichPlane = 1;
03683         if(MaxT.mV[2] > MaxT.mV[WhichPlane])    WhichPlane = 2;
03684 
03685         // Check final candidate actually inside box
03686         if(IR(MaxT.mV[WhichPlane])&0x80000000) return false;
03687 
03688         for(U32 i=0;i<3;i++)
03689         {
03690                 if(i!=WhichPlane)
03691                 {
03692                         coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i];
03693                         if (epsilon > 0)
03694                         {
03695                                 if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon)    return false;
03696                         }
03697                         else
03698                         {
03699                                 if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i])        return false;
03700                         }
03701                 }
03702         }
03703         return true;    // ray hits box
03704 }
03705 
03707 //
03708 // Macros, functions, and inline methods from other classes
03709 //
03710 //
03711 
03712 void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)
03713 {
03714         if (drawablep && assertInitialized())
03715         {
03716                 if (is_light)
03717                 {
03718                         mLights.insert(drawablep);
03719                         drawablep->setState(LLDrawable::LIGHT);
03720                 }
03721                 else
03722                 {
03723                         drawablep->clearState(LLDrawable::LIGHT);
03724                         mLights.erase(drawablep);
03725                 }
03726         }
03727 }
03728 
03729 void LLPipeline::setActive(LLDrawable *drawablep, BOOL active)
03730 {
03731         assertInitialized();
03732         if (active)
03733         {
03734                 mActiveQ.insert(drawablep);
03735         }
03736         else
03737         {
03738                 mActiveQ.erase(drawablep);
03739         }
03740 }
03741 
03742 //static
03743 void LLPipeline::toggleRenderType(U32 type)
03744 {
03745         U32 bit = (1<<type);
03746         gPipeline.mRenderTypeMask ^= bit;
03747 }
03748 
03749 //static
03750 void LLPipeline::toggleRenderTypeControl(void* data)
03751 {
03752         U32 type = (U32)(intptr_t)data;
03753         U32 bit = (1<<type);
03754         if (gPipeline.hasRenderType(type))
03755         {
03756                 llinfos << "Toggling render type mask " << std::hex << bit << " off" << std::dec << llendl;
03757         }
03758         else
03759         {
03760                 llinfos << "Toggling render type mask " << std::hex << bit << " on" << std::dec << llendl;
03761         }
03762         gPipeline.toggleRenderType(type);
03763 }
03764 
03765 //static
03766 BOOL LLPipeline::hasRenderTypeControl(void* data)
03767 {
03768         U32 type = (U32)(intptr_t)data;
03769         return gPipeline.hasRenderType(type);
03770 }
03771 
03772 // Allows UI items labeled "Hide foo" instead of "Show foo"
03773 //static
03774 BOOL LLPipeline::toggleRenderTypeControlNegated(void* data)
03775 {
03776         S32 type = (S32)(intptr_t)data;
03777         return !gPipeline.hasRenderType(type);
03778 }
03779 
03780 //static
03781 void LLPipeline::toggleRenderDebug(void* data)
03782 {
03783         U32 bit = (U32)(intptr_t)data;
03784         if (gPipeline.hasRenderDebugMask(bit))
03785         {
03786                 llinfos << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << llendl;
03787         }
03788         else
03789         {
03790                 llinfos << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << llendl;
03791         }
03792         gPipeline.mRenderDebugMask ^= bit;
03793 }
03794 
03795 
03796 //static
03797 BOOL LLPipeline::toggleRenderDebugControl(void* data)
03798 {
03799         U32 bit = (U32)(intptr_t)data;
03800         return gPipeline.hasRenderDebugMask(bit);
03801 }
03802 
03803 //static
03804 void LLPipeline::toggleRenderDebugFeature(void* data)
03805 {
03806         U32 bit = (U32)(intptr_t)data;
03807         gPipeline.mRenderDebugFeatureMask ^= bit;
03808 }
03809 
03810 
03811 //static
03812 BOOL LLPipeline::toggleRenderDebugFeatureControl(void* data)
03813 {
03814         U32 bit = (U32)(intptr_t)data;
03815         return gPipeline.hasRenderDebugFeatureMask(bit);
03816 }
03817 
03818 // static
03819 void LLPipeline::setRenderScriptedBeacons(BOOL val)
03820 {
03821         sRenderScriptedBeacons = val;
03822 }
03823 
03824 // static
03825 void LLPipeline::toggleRenderScriptedBeacons(void*)
03826 {
03827         sRenderScriptedBeacons = !sRenderScriptedBeacons;
03828 }
03829 
03830 // static
03831 BOOL LLPipeline::getRenderScriptedBeacons(void*)
03832 {
03833         return sRenderScriptedBeacons;
03834 }
03835 
03836 // static
03837 void LLPipeline::setRenderScriptedTouchBeacons(BOOL val)
03838 {
03839         sRenderScriptedTouchBeacons = val;
03840 }
03841 
03842 // static
03843 void LLPipeline::toggleRenderScriptedTouchBeacons(void*)
03844 {
03845         sRenderScriptedTouchBeacons = !sRenderScriptedTouchBeacons;
03846 }
03847 
03848 // static
03849 BOOL LLPipeline::getRenderScriptedTouchBeacons(void*)
03850 {
03851         return sRenderScriptedTouchBeacons;
03852 }
03853 
03854 // static
03855 void LLPipeline::setRenderPhysicalBeacons(BOOL val)
03856 {
03857         sRenderPhysicalBeacons = val;
03858 }
03859 
03860 // static
03861 void LLPipeline::toggleRenderPhysicalBeacons(void*)
03862 {
03863         sRenderPhysicalBeacons = !sRenderPhysicalBeacons;
03864 }
03865 
03866 // static
03867 BOOL LLPipeline::getRenderPhysicalBeacons(void*)
03868 {
03869         return sRenderPhysicalBeacons;
03870 }
03871 
03872 // static
03873 void LLPipeline::setRenderParticleBeacons(BOOL val)
03874 {
03875         sRenderParticleBeacons = val;
03876 }
03877 
03878 // static
03879 void LLPipeline::toggleRenderParticleBeacons(void*)
03880 {
03881         sRenderParticleBeacons = !sRenderParticleBeacons;
03882 }
03883 
03884 // static
03885 BOOL LLPipeline::getRenderParticleBeacons(void*)
03886 {
03887         return sRenderParticleBeacons;
03888 }
03889 
03890 // static
03891 void LLPipeline::setRenderSoundBeacons(BOOL val)
03892 {
03893         sRenderSoundBeacons = val;
03894 }
03895 
03896 // static
03897 void LLPipeline::toggleRenderSoundBeacons(void*)
03898 {
03899         sRenderSoundBeacons = !sRenderSoundBeacons;
03900 }
03901 
03902 // static
03903 BOOL LLPipeline::getRenderSoundBeacons(void*)
03904 {
03905         return sRenderSoundBeacons;
03906 }
03907 
03908 // static
03909 void LLPipeline::setRenderBeacons(BOOL val)
03910 {
03911         sRenderBeacons = val;
03912 }
03913 
03914 // static
03915 void LLPipeline::toggleRenderBeacons(void*)
03916 {
03917         sRenderBeacons = !sRenderBeacons;
03918 }
03919 
03920 // static
03921 BOOL LLPipeline::getRenderBeacons(void*)
03922 {
03923         return sRenderBeacons;
03924 }
03925 
03926 // static
03927 void LLPipeline::setRenderHighlights(BOOL val)
03928 {
03929         sRenderHighlight = val;
03930 }
03931 
03932 // static
03933 void LLPipeline::toggleRenderHighlights(void*)
03934 {
03935         sRenderHighlight = !sRenderHighlight;
03936 }
03937 
03938 // static
03939 BOOL LLPipeline::getRenderHighlights(void*)
03940 {
03941         return sRenderHighlight;
03942 }
03943 
03944 // static
03945 BOOL LLPipeline::getProcessBeacons(void* data)
03946 {
03947         return sRenderProcessBeacons;
03948 }
03949 
03950 LLViewerObject* LLPipeline::pickObject(const LLVector3 &start, const LLVector3 &end, LLVector3 &collision)
03951 {
03952         LLDrawable* drawable = NULL;
03953 
03954         for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
03955                         iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
03956         {
03957                 LLViewerRegion* region = *iter;
03958                 LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_VOLUME);
03959                 if (part)
03960                 {
03961                         LLDrawable* hit = part->pickDrawable(start, end, collision);
03962                         if (hit)
03963                         {
03964                                 drawable = hit;
03965                         }
03966                 }
03967         }
03968         return drawable ? drawable->getVObj().get() : NULL;
03969 }
03970 
03971 LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj)
03972 {
03973         if (vobj)
03974         {
03975                 LLViewerRegion* region = vobj->getRegion();
03976                 if (region)
03977                 {
03978                         return region->getSpatialPartition(vobj->getPartitionType());
03979                 }
03980         }
03981         return NULL;
03982 }
03983 
03984 
03985 void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
03986 {
03987         if (!drawable || drawable->isDead())
03988         {
03989                 return;
03990         }
03991 
03992         if (!drawable)
03993         {
03994                 return;
03995         }
03996 
03997         for (S32 i = 0; i < drawable->getNumFaces(); i++)
03998         {
03999                 LLFace* facep = drawable->getFace(i);
04000                 facep->mVertexBuffer = NULL;
04001                 facep->mLastVertexBuffer = NULL;
04002         }
04003 }
04004 
04005 void LLPipeline::resetVertexBuffers()
04006 {
04007         sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
04008 
04009         for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
04010                         iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
04011         {
04012                 LLViewerRegion* region = *iter;
04013                 for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
04014                 {
04015                         LLSpatialPartition* part = region->getSpatialPartition(i);
04016                         if (part)
04017                         {
04018                                 part->resetVertexBuffers();
04019                         }
04020                 }
04021         }
04022 
04023         resetDrawOrders();
04024 
04025         gSky.resetVertexBuffers();
04026 
04027         if (LLVertexBuffer::sGLCount > 0)
04028         {
04029                 LLVertexBuffer::cleanupClass();
04030         }
04031 
04032         //delete all name pool caches
04033         LLGLNamePool::cleanupPools();
04034 
04035         if (LLVertexBuffer::sGLCount > 0)
04036         {
04037                 llwarns << "VBO wipe failed." << llendl;
04038         }
04039 
04040         if (!LLVertexBuffer::sStreamIBOPool.mNameList.empty() ||
04041                 !LLVertexBuffer::sStreamVBOPool.mNameList.empty() ||
04042                 !LLVertexBuffer::sDynamicIBOPool.mNameList.empty() ||
04043                 !LLVertexBuffer::sDynamicVBOPool.mNameList.empty())
04044         {
04045                 llwarns << "VBO name pool cleanup failed." << llendl;
04046         }
04047 
04048         LLVertexBuffer::unbind();
04049 
04050         LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind");
04051 }
04052 
04053 void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture)
04054 {
04055         assertInitialized();
04056         gGLLastMatrix = NULL;
04057         glLoadMatrixd(gGLLastModelView);
04058         mSimplePool->renderGroups(type, mask, texture);
04059         gGLLastMatrix = NULL;
04060         glLoadMatrixd(gGLLastModelView);
04061 }
04062 
04063 void LLPipeline::setUseVBO(BOOL use_vbo)
04064 {
04065         if (use_vbo != LLVertexBuffer::sEnableVBOs)
04066         {
04067                 if (use_vbo)
04068                 {
04069                         llinfos << "Enabling VBO." << llendl;
04070                 }
04071                 else
04072                 { 
04073                         llinfos << "Disabling VBO." << llendl;
04074                 }
04075                 
04076                 resetVertexBuffers();
04077                 LLVertexBuffer::initClass(use_vbo);
04078         }
04079 }
04080 
04081 void apply_cube_face_rotation(U32 face)
04082 {
04083         switch (face)
04084         {
04085                 case 0: 
04086                         glRotatef(90.f, 0, 1, 0);
04087                         glRotatef(180.f, 1, 0, 0);
04088                 break;
04089                 case 2: 
04090                         glRotatef(-90.f, 1, 0, 0);
04091                 break;
04092                 case 4:
04093                         glRotatef(180.f, 0, 1, 0);
04094                         glRotatef(180.f, 0, 0, 1);
04095                 break;
04096                 case 1: 
04097                         glRotatef(-90.f, 0, 1, 0);
04098                         glRotatef(180.f, 1, 0, 0);
04099                 break;
04100                 case 3:
04101                         glRotatef(90, 1, 0, 0);
04102                 break;
04103                 case 5: 
04104                         glRotatef(180, 0, 0, 1);
04105                 break;
04106         }
04107 }
04108 void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam)
04109 {
04110         LLGLState::checkStates();
04111         LLGLState::checkTextureChannels();
04112         LLGLState::checkClientArrays();
04113 
04114         assertInitialized();
04115 
04116         //render dynamic cube map
04117         U32 type_mask = gPipeline.getRenderTypeMask();
04118         S32 use_occlusion = LLPipeline::sUseOcclusion;
04119         LLPipeline::sUseOcclusion = 0;
04120         LLPipeline::sSkipUpdate = TRUE;
04121         U32 res = REFLECTION_MAP_RES;
04122 
04123         LLPipeline::sReflectionRender = TRUE;
04124 
04125         cube_map->bind();
04126         GLint width;
04127         glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_TEXTURE_WIDTH, &width);
04128         if (width != res)
04129         {
04130                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
04131                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
04132                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
04133                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
04134                 
04135                 for (U32 i = 0; i < 6; i++)
04136                 {
04137                         glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL); 
04138                 }
04139         }
04140         glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);
04141         cube_map->disable();
04142 
04143         BOOL toggle_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
04144         if (toggle_ui)
04145         {
04146                 gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
04147         }
04148         
04149         U32 cube_mask = (1 << LLPipeline::RENDER_TYPE_SIMPLE) |
04150                                         (1 << LLPipeline::RENDER_TYPE_WATER) |
04151                                         //(1 << LLPipeline::RENDER_TYPE_BUMP) |
04152                                         (1 << LLPipeline::RENDER_TYPE_ALPHA) |
04153                                         (1 << LLPipeline::RENDER_TYPE_TREE) |
04154                                         //(1 << LLPipeline::RENDER_TYPE_PARTICLES) |
04155                                         (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
04156                                         //(1 << LLPipeline::RENDER_TYPE_STARS) |
04157                                         //(1 << LLPipeline::RENDER_TYPE_AVATAR) |
04158                                         (1 << LLPipeline::RENDER_TYPE_GLOW) |
04159                                         (1 << LLPipeline::RENDER_TYPE_GRASS) |
04160                                         (1 << LLPipeline::RENDER_TYPE_VOLUME) |
04161                                         (1 << LLPipeline::RENDER_TYPE_TERRAIN) |
04162                                         (1 << LLPipeline::RENDER_TYPE_SKY) |
04163                                         (1 << LLPipeline::RENDER_TYPE_WL_SKY) |
04164                                         (1 << LLPipeline::RENDER_TYPE_GROUND);
04165         
04166         LLDrawPoolWater::sSkipScreenCopy = TRUE;
04167         LLPipeline::sSkipUpdate = TRUE;
04168         cube_mask = cube_mask & type_mask;
04169         gPipeline.setRenderTypeMask(cube_mask);
04170 
04171         glMatrixMode(GL_PROJECTION);
04172         glPushMatrix();
04173         glMatrixMode(GL_MODELVIEW);
04174         glPushMatrix();
04175 
04176         glViewport(0,0,res,res);
04177         
04178         glClearColor(0,0,0,0);                  
04179         
04180         LLVector3 origin = cube_cam.getOrigin();
04181 
04182         gPipeline.calcNearbyLights(cube_cam);
04183 
04184         stop_glerror();
04185         LLViewerImage::unbindTexture(0, GL_TEXTURE_2D);
04186         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mCubeFrameBuffer);
04187         glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
04188                                                                                 GL_RENDERBUFFER_EXT, mCubeDepth);               
04189         stop_glerror();
04190 
04191         for (S32 i = 0; i < 6; i++)
04192         {
04193                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mCubeFrameBuffer);
04194                 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
04195                                                                         gl_cube_face[i], cube_map->getGLName(), 0);
04196                 validate_framebuffer_object();
04197                 glMatrixMode(GL_PROJECTION);
04198                 glLoadIdentity();
04199                 gluPerspective(90.f, 1.f, 0.1f, 1024.f);
04200                 glMatrixMode(GL_MODELVIEW);
04201                 glLoadIdentity();
04202                 
04203                 apply_cube_face_rotation(i);
04204 
04205                 glTranslatef(-origin.mV[0], -origin.mV[1], -origin.mV[2]);
04206                 cube_cam.setOrigin(origin);
04207                 LLViewerCamera::updateFrustumPlanes(cube_cam);
04208                 cube_cam.setOrigin(LLViewerCamera::getInstance()->getOrigin());
04209                 static LLCullResult result;
04210                 gPipeline.updateCull(cube_cam, result);
04211                 gPipeline.stateSort(cube_cam, result);
04212                 
04213                 glClearColor(0,0,0,0);
04214                 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
04215                 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
04216                 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_FALSE);
04217                 stop_glerror();
04218                 gPipeline.renderGeom(cube_cam);
04219         }
04220 
04221         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
04222 
04223         cube_cam.setOrigin(origin);
04224         gShinyOrigin.setVec(cube_cam.getOrigin(), cube_cam.getFar()*2.f);
04225         glMatrixMode(GL_PROJECTION);
04226         glPopMatrix();
04227         glMatrixMode(GL_MODELVIEW);
04228         glPopMatrix();
04229 
04230         gViewerWindow->setupViewport();
04231 
04232         gPipeline.setRenderTypeMask(type_mask);
04233         LLPipeline::sUseOcclusion = use_occlusion;
04234         LLPipeline::sSkipUpdate = FALSE;
04235 
04236         if (toggle_ui)
04237         {
04238                 gPipeline.toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
04239         }
04240         LLDrawPoolWater::sSkipScreenCopy = FALSE;
04241         LLPipeline::sSkipUpdate = FALSE;
04242         LLPipeline::sReflectionRender = FALSE;
04243 
04244         LLGLState::checkStates();
04245         LLGLState::checkTextureChannels();
04246         LLGLState::checkClientArrays();
04247 }
04248 
04249 //send cube map vertices and texture coordinates
04250 void render_cube_map()
04251 {
04252         U16 idx[36];
04253 
04254         idx[0] = 1; idx[1] = 0; idx[2] = 2; //front
04255         idx[3] = 3; idx[4] = 2; idx[5] = 0;
04256 
04257         idx[6] = 4; idx[7] = 5; idx[8] = 1; //top
04258         idx[9] = 0; idx[10] = 1; idx[11] = 5; 
04259 
04260         idx[12] = 5; idx[13] = 4; idx[14] = 6; //back
04261         idx[15] = 7; idx[16] = 6; idx[17] = 4;
04262 
04263         idx[18] = 6; idx[19] = 7; idx[20] = 3; //bottom
04264         idx[21] = 2; idx[22] = 3; idx[23] = 7;
04265 
04266         idx[24] = 0; idx[25] = 5; idx[26] = 3; //left
04267         idx[27] = 6; idx[28] = 3; idx[29] = 5;
04268 
04269         idx[30] = 4; idx[31] = 1; idx[32] = 7; //right
04270         idx[33] = 2; idx[34] = 7; idx[35] = 1;
04271 
04272         LLVector3 vert[8];
04273         LLVector3 r = LLVector3(1,1,1);
04274 
04275         vert[0] = r.scaledVec(LLVector3(-1,1,1)); //   0 - left top front
04276         vert[1] = r.scaledVec(LLVector3(1,1,1));  //   1 - right top front
04277         vert[2] = r.scaledVec(LLVector3(1,-1,1)); //   2 - right bottom front
04278         vert[3] = r.scaledVec(LLVector3(-1,-1,1)); //  3 - left bottom front
04279 
04280         vert[4] = r.scaledVec(LLVector3(1,1,-1)); //  4 - left top back
04281         vert[5] = r.scaledVec(LLVector3(-1,1,-1)); //   5 - right top back
04282         vert[6] = r.scaledVec(LLVector3(-1,-1,-1)); //  6 - right bottom back
04283         vert[7] = r.scaledVec(LLVector3(1,-1,-1)); // 7 -left bottom back
04284 
04285         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
04286         glTexCoordPointer(3, GL_FLOAT, 0, vert);
04287         glVertexPointer(3, GL_FLOAT, 0, vert);
04288 
04289         glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (GLushort*) idx);
04290 
04291         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
04292 }
04293 
04294 void validate_framebuffer_object()
04295 {                                                           
04296         GLenum status;                                            
04297         status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 
04298         switch(status) 
04299         {                                          
04300                 case GL_FRAMEBUFFER_COMPLETE_EXT:                       
04301                         //framebuffer OK, no error.
04302                         break;
04303                 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
04304                         // frame buffer not OK: probably means unsupported depth buffer format
04305                         llerrs << "Framebuffer Incomplete Dimensions." << llendl;
04306                         break;
04307                 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
04308                         // frame buffer not OK: probably means unsupported depth buffer format
04309                         llerrs << "Framebuffer Incomplete Attachment." << llendl;
04310                         break; 
04311                 case GL_FRAMEBUFFER_UNSUPPORTED_EXT:                    
04312                         /* choose different formats */                        
04313                         llerrs << "Framebuffer unsupported." << llendl;
04314                         break;                                                
04315                 default:                                                
04316                         llerrs << "Unknown framebuffer status." << llendl;
04317                         break;
04318         }
04319 }
04320 
04321 void LLPipeline::blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out)
04322 {
04323         LLGLState::checkStates();
04324         LLGLState::checkTextureChannels();
04325         LLGLState::checkClientArrays();
04326 
04327         assertInitialized();
04328 
04329         U32 res = (U32) gSavedSettings.getS32("RenderReflectionRes");
04330         enableLightsFullbright(LLColor4::white);
04331         LLGLDepthTest depth(GL_FALSE);
04332         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
04333         glMatrixMode(GL_PROJECTION);
04334         glPushMatrix();
04335         glLoadIdentity();
04336         gluPerspective(90.f+45.f/res, 1.f, 0.1f, 1024.f);
04337         glMatrixMode(GL_MODELVIEW);
04338         glPushMatrix();
04339 
04340         cube_out->enableTexture(0);
04341         cube_out->bind();
04342         GLint width;
04343         glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_TEXTURE_WIDTH, &width);
04344         if (width != res)
04345         {
04346                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
04347                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
04348                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
04349                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
04350                 
04351                 for (U32 i = 0; i < 6; i++)
04352                 {
04353                         glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL); 
04354                 }
04355         }
04356         glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);
04357 
04358         glViewport(0, 0, res, res);
04359         LLGLEnable blend(GL_BLEND);
04360         
04361         S32 kernel = 2;
04362         F32 step = 90.f/res;
04363         F32 alpha = 1.f / ((kernel*2)+1);
04364 
04365         gGL.color4f(alpha,alpha,alpha,alpha*1.25f);
04366         
04367         LLVector3 axis[] = 
04368         {
04369                 LLVector3(1,0,0),
04370                 LLVector3(0,1,0),
04371                 LLVector3(0,0,1)
04372         };
04373 
04374         stop_glerror();
04375         glViewport(0,0,res, res);
04376         gGL.blendFunc(GL_ONE, GL_ONE);
04377         cube_in->enableTexture(0);
04378         //3-axis blur
04379         for (U32 j = 0; j < 3; j++)
04380         {
04381                 stop_glerror();
04382 
04383                 if (j == 0)
04384                 {
04385                         cube_in->bind();
04386                 }
04387                 else
04388                 {
04389                         glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mBlurCubeTexture[j-1]);
04390                 }
04391 
04392                 stop_glerror();
04393 
04394                 LLViewerImage::unbindTexture(0, GL_TEXTURE_2D);
04395                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mBlurCubeBuffer[j]);
04396                 stop_glerror();
04397 
04398                 for (U32 i = 0; i < 6; i++)
04399                 {
04400                         stop_glerror();
04401                         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 
04402                                                                 GL_COLOR_ATTACHMENT0_EXT,
04403                                                                 gl_cube_face[i], 
04404                                                                 j < 2 ? mBlurCubeTexture[j] : cube_out->getGLName(), 0);
04405                         validate_framebuffer_object();
04406                         glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
04407                         glClear(GL_COLOR_BUFFER_BIT);
04408                         glLoadIdentity();
04409                         apply_cube_face_rotation(i);
04410                         for (S32 x = -kernel; x <= kernel; ++x)
04411                         {
04412                                 glPushMatrix();
04413                                 glRotatef(x*step, axis[j].mV[0], axis[j].mV[1], axis[j].mV[2]);
04414                                 render_cube_map();
04415                                 glPopMatrix();
04416                         }
04417                         stop_glerror();
04418                 }       
04419         }
04420 
04421         stop_glerror();
04422 
04423         glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);
04424         
04425         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
04426         glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_FALSE);
04427         glMatrixMode(GL_PROJECTION);
04428         glPopMatrix();
04429         glMatrixMode(GL_MODELVIEW);
04430         glPopMatrix();
04431 
04432         cube_in->disableTexture();
04433         gViewerWindow->setupViewport();
04434         gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
04435 
04436         LLGLState::checkStates();
04437         LLGLState::checkTextureChannels();
04438         LLGLState::checkClientArrays();
04439 }
04440 
04441 void LLPipeline::bindScreenToTexture() 
04442 {
04443         
04444 }
04445 
04446 void LLPipeline::renderBloom(BOOL for_snapshot)
04447 {
04448         if (!(gPipeline.canUseVertexShaders() &&
04449                 sRenderGlow))
04450         {
04451                 return;
04452         }
04453 
04454         LLGLState::checkStates();
04455         LLGLState::checkTextureChannels();
04456 
04457         assertInitialized();
04458 
04459         if (gUseWireframe)
04460         {
04461                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
04462         }
04463 
04464         U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
04465 
04466         LLVector2 tc1(0,0);
04467         LLVector2 tc2((F32) gViewerWindow->getWindowDisplayWidth(),
04468                                         (F32) gViewerWindow->getWindowDisplayHeight());
04469 
04470         if (res_mod > 1)
04471         {
04472                 tc2 /= (F32) res_mod;
04473         }
04474 
04475         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
04476                 
04477         LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM);
04478         gGL.color4f(1,1,1,1);
04479         LLGLDepthTest depth(GL_FALSE);
04480         LLGLDisable blend(GL_BLEND);
04481         LLGLDisable cull(GL_CULL_FACE);
04482         
04483         enableLightsFullbright(LLColor4(1,1,1,1));
04484 
04485         glMatrixMode(GL_PROJECTION);
04486         glPushMatrix();
04487         glLoadIdentity();
04488         glMatrixMode(GL_MODELVIEW);
04489         glPushMatrix();
04490         glLoadIdentity();
04491 
04492         LLGLDisable test(GL_ALPHA_TEST);
04493 
04494         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
04495         glClearColor(0,0,0,0);
04496 
04497         if (for_snapshot)
04498         {
04499                 mGlow[1].bindTexture();
04500                 {
04501                         //LLGLEnable stencil(GL_STENCIL_TEST);
04502                         //glStencilFunc(GL_NOTEQUAL, 255, 0xFFFFFFFF);
04503                         //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
04504                         //LLGLDisable blend(GL_BLEND);
04505                         LLGLEnable blend(GL_BLEND);
04506                         gGL.blendFunc(GL_ONE, GL_ONE);
04507                         tc2.setVec(1,1);                                
04508                         gGL.begin(LLVertexBuffer::TRIANGLE_STRIP);
04509                         gGL.color4f(1,1,1,1);
04510                         gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
04511                         gGL.vertex2f(-1,-1);
04512                         
04513                         gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
04514                         gGL.vertex2f(-1,1);
04515                         
04516                         gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
04517                         gGL.vertex2f(1,-1);
04518                         
04519                         gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
04520                         gGL.vertex2f(1,1);
04521                         gGL.end();
04522 
04523                         gGL.flush();
04524                         gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
04525                 }
04526 
04527                 gGL.flush();
04528                 glMatrixMode(GL_PROJECTION);
04529                 glPopMatrix();
04530                 glMatrixMode(GL_MODELVIEW);
04531                 glPopMatrix();
04532 
04533                 return;
04534         }
04535         
04536         {
04537                 {
04538                         LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM_FBO);
04539                         mGlow[2].bindTarget();
04540                         mGlow[2].clear();
04541                 }
04542                 
04543                 gGlowExtractProgram.bind();
04544                 F32 minLum = llclamp(gSavedSettings.getF32("RenderGlowMinLuminance"), 0.0f, 1.0f);
04545                 F32 maxAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha");              
04546                 F32 warmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount");     
04547                 LLVector3 lumWeights = gSavedSettings.getVector3("RenderGlowLumWeights");
04548                 LLVector3 warmthWeights = gSavedSettings.getVector3("RenderGlowWarmthWeights");
04549                 gGlowExtractProgram.uniform1f("minLuminance", minLum);
04550                 gGlowExtractProgram.uniform1f("maxExtractAlpha", maxAlpha);
04551                 gGlowExtractProgram.uniform3f("lumWeights", lumWeights.mV[0], lumWeights.mV[1], lumWeights.mV[2]);
04552                 gGlowExtractProgram.uniform3f("warmthWeights", warmthWeights.mV[0], warmthWeights.mV[1], warmthWeights.mV[2]);
04553                 gGlowExtractProgram.uniform1f("warmthAmount", warmthAmount);
04554                 LLGLEnable blend_on(GL_BLEND);
04555                 LLGLEnable test(GL_ALPHA_TEST);
04556                 glAlphaFunc(GL_GREATER, 0.f);
04557                 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE);
04558                 LLViewerImage::unbindTexture(0, GL_TEXTURE_2D);
04559                 
04560                 glDisable(GL_TEXTURE_2D);
04561                 glEnable(GL_TEXTURE_RECTANGLE_ARB);
04562                 mScreen.bindTexture();
04563 
04564                 gGL.color4f(1,1,1,1);
04565                 gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
04566                 gGL.begin(LLVertexBuffer::TRIANGLE_STRIP);
04567                 gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
04568                 gGL.vertex2f(-1,-1);
04569                 
04570                 gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
04571                 gGL.vertex2f(-1,1);
04572                 
04573                 gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
04574                 gGL.vertex2f(1,-1);
04575                 
04576                 gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
04577                 gGL.vertex2f(1,1);
04578                 gGL.end();
04579                 
04580                 glEnable(GL_TEXTURE_2D);
04581                 glDisable(GL_TEXTURE_RECTANGLE_ARB);
04582 
04583                 mGlow[2].flush();
04584         }
04585 
04586         tc1.setVec(0,0);
04587         tc2.setVec(1,1);
04588 
04589 
04590 
04591         // power of two between 1 and 1024
04592         U32 glowResPow = gSavedSettings.getS32("RenderGlowResolutionPow");
04593         const U32 glow_res = llmax(1, 
04594                 llmin(1024, 1 << glowResPow));
04595 
04596         S32 kernel = gSavedSettings.getS32("RenderGlowIterations")*2;
04597         F32 delta = gSavedSettings.getF32("RenderGlowWidth") / glow_res;
04598         // Use half the glow width if we have the res set to less than 9 so that it looks
04599         // almost the same in either case.
04600         if (glowResPow < 9)
04601         {
04602                 delta *= 0.5f;
04603         }
04604         F32 strength = gSavedSettings.getF32("RenderGlowStrength");
04605 
04606         gGlowProgram.bind();
04607         gGlowProgram.uniform1f("glowStrength", strength);
04608 
04609         for (S32 i = 0; i < kernel; i++)
04610         {
04611                 LLViewerImage::unbindTexture(0, GL_TEXTURE_2D);
04612                 {
04613                         LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM_FBO);
04614                         mGlow[i%2].bindTarget();
04615                         mGlow[i%2].clear();
04616                 }
04617                         
04618                 if (i == 0)
04619                 {
04620                         mGlow[2].bindTexture();
04621                 }
04622                 else
04623                 {
04624                         mGlow[(i-1)%2].bindTexture();
04625                 }
04626 
04627                 if (i%2 == 0)
04628                 {
04629                         gGlowProgram.uniform2f("glowDelta", delta, 0);
04630                 }
04631                 else
04632                 {
04633                         gGlowProgram.uniform2f("glowDelta", 0, delta);
04634                 }
04635 
04636                 gGL.begin(LLVertexBuffer::TRIANGLE_STRIP);
04637                 gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
04638                 gGL.vertex2f(-1,-1);
04639                 
04640                 gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
04641                 gGL.vertex2f(-1,1);
04642                 
04643                 gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
04644                 gGL.vertex2f(1,-1);
04645                 
04646                 gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
04647                 gGL.vertex2f(1,1);
04648                 gGL.end();
04649                 
04650                 mGlow[i%2].flush();
04651         }
04652 
04653         gGlowProgram.unbind();
04654 
04655         if (LLRenderTarget::sUseFBO)
04656         {
04657                 LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM_FBO);
04658                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
04659         }
04660 
04661         gViewerWindow->setupViewport();
04662 
04663         /*mGlow[1].bindTexture();
04664         {
04665                 LLGLEnable stencil(GL_STENCIL_TEST);
04666                 glStencilFunc(GL_NOTEQUAL, 255, 0xFFFFFFFF);
04667                 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
04668                 LLGLDisable blend(GL_BLEND);
04669                         
04670                 gGL.begin(LLVertexBuffer::TRIANGLE_STRIP);
04671                 gGL.color4f(1,1,1,1);
04672                 gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
04673                 gGL.vertex2f(-1,-1);
04674                 
04675                 gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
04676                 gGL.vertex2f(-1,1);
04677                 
04678                 gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
04679                 gGL.vertex2f(1,-1);
04680                 
04681                 gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
04682                 gGL.vertex2f(1,1);
04683                 gGL.end();
04684 
04685                 gGL.flush();
04686         }
04687 
04688         if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_GLOW))
04689         {
04690                 tc2.setVec((F32) gViewerWindow->getWindowDisplayWidth(),
04691                                 (F32) gViewerWindow->getWindowDisplayHeight());
04692 
04693                 if (res_mod > 1)
04694                 {
04695                         tc2 /= (F32) res_mod;
04696                 }
04697 
04698                 LLGLEnable blend(GL_BLEND);
04699                 gGL.blendFunc(GL_ONE, GL_ONE);
04700 
04701                 glDisable(GL_TEXTURE_2D);
04702                 glEnable(GL_TEXTURE_RECTANGLE_ARB);
04703                 mScreen.bindTexture();
04704                 
04705                 gGL.begin(LLVertexBuffer::TRIANGLE_STRIP);
04706                 gGL.color4f(1,1,1,1);
04707                 gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
04708                 gGL.vertex2f(-1,-1);
04709                 
04710                 gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
04711                 gGL.vertex2f(-1,1);
04712                 
04713                 gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
04714                 gGL.vertex2f(1,-1);
04715                 
04716                 gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
04717                 gGL.vertex2f(1,1);
04718                 gGL.end();
04719 
04720                 gGL.flush();
04721                 
04722                 glEnable(GL_TEXTURE_2D);
04723                 glDisable(GL_TEXTURE_RECTANGLE_ARB);
04724 
04725                 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
04726         }*/
04727         gGL.flush();
04728         
04729         {
04730                 LLVertexBuffer::unbind();
04731 
04732                 F32 uv0[] = 
04733                 {
04734                                 tc1.mV[0], tc1.mV[1],
04735                                 tc1.mV[0], tc2.mV[1],
04736                                 tc2.mV[0], tc1.mV[1],
04737                                 tc2.mV[0], tc2.mV[1]
04738                 };
04739                 
04740                 tc2.setVec((F32) gViewerWindow->getWindowDisplayWidth(),
04741                         (F32) gViewerWindow->getWindowDisplayHeight());
04742 
04743                 if (res_mod > 1)
04744                 {
04745                         tc2 /= (F32) res_mod;
04746                 }
04747 
04748                 F32 uv1[] = 
04749                 {
04750                                 tc1.mV[0], tc1.mV[1],
04751                                 tc1.mV[0], tc2.mV[1],
04752                                 tc2.mV[0], tc1.mV[1],
04753                                 tc2.mV[0], tc2.mV[1]
04754                 };
04755 
04756                 F32 v[] = 
04757                 {
04758                         -1,-1,
04759                         -1,1,
04760                         1,-1,
04761                         1,1
04762                 };
04763                 
04764                 LLGLDisable blend(GL_BLEND);
04765 
04766                 //tex unit 0
04767                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
04768                 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
04769                 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
04770                 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
04771                 
04772                 mGlow[1].bindTexture();
04773                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
04774                 glTexCoordPointer(2, GL_FLOAT, 0, uv0);
04775                 glActiveTextureARB(GL_TEXTURE1_ARB);
04776                 glEnable(GL_TEXTURE_RECTANGLE_ARB);
04777                 
04778                 //tex unit 1
04779                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
04780                 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
04781                 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
04782                 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
04783                 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
04784                 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
04785                 
04786                 glClientActiveTextureARB(GL_TEXTURE1_ARB);
04787                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
04788                 glTexCoordPointer(2, GL_FLOAT, 0, uv1);
04789 
04790                 glVertexPointer(2, GL_FLOAT, 0, v);
04791                 
04792                 mScreen.bindTexture();
04793                 
04794                 LLGLEnable multisample(GL_MULTISAMPLE_ARB);
04795                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
04796                 
04797                 glDisable(GL_TEXTURE_RECTANGLE_ARB);
04798                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
04799                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
04800                 glClientActiveTextureARB(GL_TEXTURE0_ARB);
04801                 glActiveTextureARB(GL_TEXTURE0_ARB);
04802                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
04803                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
04804         }
04805         
04806         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
04807         glMatrixMode(GL_PROJECTION);
04808         glPopMatrix();
04809         glMatrixMode(GL_MODELVIEW);
04810         glPopMatrix();
04811 
04812         LLVertexBuffer::unbind();
04813 
04814         LLGLState::checkStates();
04815         LLGLState::checkTextureChannels();
04816 
04817 }
04818 
04819 void LLPipeline::processImagery(LLCamera& camera)
04820 {
04821         for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
04822                         iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
04823         {
04824                 LLViewerRegion* region = *iter;
04825                 LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_VOLUME);
04826                 if (part)
04827                 {
04828                         part->processImagery(&camera);  
04829                 }
04830         }
04831 }
04832 
04833 
04834 inline float sgn(float a)
04835 {
04836     if (a > 0.0F) return (1.0F);
04837     if (a < 0.0F) return (-1.0F);
04838     return (0.0F);
04839 }
04840 
04841 void LLPipeline::generateWaterReflection(LLCamera& camera_in)
04842 {
04843         if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate)
04844         {
04845                 LLVertexBuffer::unbind();
04846 
04847                 LLGLState::checkStates();
04848                 LLGLState::checkTextureChannels();
04849                 LLGLState::checkClientArrays();
04850 
04851                 LLCamera camera = camera_in;
04852                 camera.setFar(camera.getFar()*0.87654321f);
04853                 LLPipeline::sReflectionRender = TRUE;
04854                 S32 occlusion = LLPipeline::sUseOcclusion;
04855                 LLPipeline::sUseOcclusion = llmin(occlusion, 1);
04856                 U32 type_mask = gPipeline.mRenderTypeMask;
04857 
04858                 glh::matrix4f projection = glh_get_current_projection();
04859                 glh::matrix4f mat;
04860 
04861                 stop_glerror();
04862                 LLPlane plane;
04863 
04864                 F32 height = gAgent.getRegion()->getWaterHeight(); 
04865                 F32 to_clip = fabsf(camera.getOrigin().mV[2]-height);
04866                 F32 pad = -to_clip*0.05f; //amount to "pad" clip plane by
04867 
04868                 //plane params
04869                 LLVector3 pnorm;
04870                 F32 pd;
04871 
04872                 S32 water_clip = 0;
04873                 if (!LLViewerCamera::getInstance()->cameraUnderWater())
04874                 { //camera is above water, clip plane points up
04875                         pnorm.setVec(0,0,1);
04876                         pd = -height;
04877                         plane.setVec(pnorm, pd);
04878                         water_clip = -1;
04879                 }
04880                 else
04881                 {       //camera is below water, clip plane points down
04882                         pnorm = LLVector3(0,0,-1);
04883                         pd = height;
04884                         plane.setVec(pnorm, pd);
04885                         water_clip = 1;
04886                 }
04887 
04888 
04889 
04890                 if (!LLViewerCamera::getInstance()->cameraUnderWater())
04891                 {       //generate planar reflection map
04892                         LLViewerImage::unbindTexture(0, GL_TEXTURE_2D);
04893                         glClearColor(0,0,0,0);
04894                         glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
04895                         mWaterRef.bindTarget();
04896                         mWaterRef.getViewport(gGLViewport);
04897                         mWaterRef.clear();
04898                         glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_FALSE);
04899 
04900                         stop_glerror();
04901 
04902                         LLVector3 origin = camera.getOrigin();
04903 
04904                         glPushMatrix();
04905 
04906                         mat.set_scale(glh::vec3f(1,1,-1));
04907                         mat.set_translate(glh::vec3f(0,0,height*2.f));
04908                         
04909                         glh::matrix4f current = glh_get_current_modelview();
04910 
04911                         mat = current * mat;
04912 
04913                         glh_set_current_modelview(mat);
04914                         glLoadMatrixf(mat.m);
04915 
04916                         LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
04917 
04918                         glCullFace(GL_FRONT);
04919 
04920                         //initial sky pass (no user clip plane)
04921                         { //mask out everything but the sky
04922                                 U32 tmp = mRenderTypeMask;
04923                                 mRenderTypeMask &= ((1 << LLPipeline::RENDER_TYPE_SKY) |
04924                                                                         (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
04925                                                                         (1 << LLPipeline::RENDER_TYPE_WL_SKY));
04926 
04927                                 static LLCullResult result;
04928                                 updateCull(camera, result);
04929                                 stateSort(camera, result);
04930                                 renderGeom(camera, TRUE);
04931 
04932                                 mRenderTypeMask = tmp;
04933                         }
04934 
04935                         if (LLDrawPoolWater::sNeedsDistortionUpdate)
04936                         {
04937                                 mRenderTypeMask &=      ~((1<<LLPipeline::RENDER_TYPE_WATER) |
04938                                                                           (1<<LLPipeline::RENDER_TYPE_GROUND) |
04939                                                                           (1<<LLPipeline::RENDER_TYPE_SKY) |
04940                                                                           (1<<LLPipeline::RENDER_TYPE_CLOUDS)); 
04941 
04942                                 if (gSavedSettings.getBOOL("RenderWaterReflections"))
04943                                 { //mask out selected geometry based on reflection detail
04944 
04945                                         S32 detail = gSavedSettings.getS32("RenderReflectionDetail");
04946                                         if (detail < 3)
04947                                         {
04948                                                 mRenderTypeMask &= ~(1 << LLPipeline::RENDER_TYPE_PARTICLES);
04949                                                 if (detail < 2)
04950                                                 {
04951                                                         mRenderTypeMask &= ~(1 << LLPipeline::RENDER_TYPE_AVATAR);
04952                                                         if (detail < 1)
04953                                                         {
04954                                                                 mRenderTypeMask &= ~(1 << LLPipeline::RENDER_TYPE_VOLUME);
04955                                                         }
04956                                                 }
04957                                         }
04958 
04959                                         LLSpatialPartition::sFreezeState = TRUE;
04960                                         LLPipeline::sSkipUpdate = TRUE;
04961                                         LLGLUserClipPlane clip_plane(plane, mat, projection);
04962                                         static LLCullResult result;
04963                                         updateCull(camera, result, 1);
04964                                         stateSort(camera, result);
04965                                         renderGeom(camera);
04966                                         LLSpatialPartition::sFreezeState = FALSE;
04967                                         LLPipeline::sSkipUpdate = FALSE;
04968                                 }
04969                         }       
04970                         glCullFace(GL_BACK);
04971                         glPopMatrix();
04972                         mWaterRef.flush();
04973 
04974                         glh_set_current_modelview(current);
04975                 }
04976 
04977                 //render distortion map
04978                 static BOOL last_update = TRUE;
04979                 if (last_update)
04980                 {
04981                         camera.setFar(camera_in.getFar());
04982                         mRenderTypeMask = type_mask & (~(1<<LLPipeline::RENDER_TYPE_WATER) |
04983                                                                                         (1<<LLPipeline::RENDER_TYPE_GROUND));   
04984                         stop_glerror();
04985 
04986                         LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? FALSE : TRUE;
04987 
04988                         if (LLPipeline::sUnderWaterRender)
04989                         {
04990                                 mRenderTypeMask &=      ~((1<<LLPipeline::RENDER_TYPE_GROUND) |
04991                                                                           (1<<LLPipeline::RENDER_TYPE_SKY) |
04992                                                                           (1<<LLPipeline::RENDER_TYPE_CLOUDS) |
04993                                                                           (1<<LLPipeline::RENDER_TYPE_WL_SKY));         
04994                         }
04995                         LLViewerCamera::updateFrustumPlanes(camera);
04996 
04997                         LLViewerImage::unbindTexture(0, GL_TEXTURE_2D);
04998                         LLColor4& col = LLDrawPoolWater::sWaterFogColor;
04999                         glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
05000                         glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
05001                         mWaterDis.bindTarget();
05002                         mWaterDis.getViewport(gGLViewport);
05003                         mWaterDis.clear();
05004                         glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_FALSE);
05005 
05006                         if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate)
05007                         {
05008                                 //clip out geometry on the same side of water as the camera
05009                                 mat = glh_get_current_modelview();
05010                                 LLGLUserClipPlane clip_plane(LLPlane(-pnorm, -(pd+pad)), mat, projection);
05011                                 static LLCullResult result;
05012                                 updateCull(camera, result, water_clip);
05013                                 stateSort(camera, result);
05014                                 renderGeom(camera);
05015                         }
05016 
05017                         LLPipeline::sUnderWaterRender = FALSE;
05018                         mWaterDis.flush();
05019                 }
05020                 last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
05021 
05022                 LLRenderTarget::unbindTarget();
05023                 LLPipeline::sReflectionRender = FALSE;
05024 
05025                 if (!LLRenderTarget::sUseFBO)
05026                 {
05027                         glClear(GL_DEPTH_BUFFER_BIT);
05028                 }
05029                 glClearColor(0.f, 0.f, 0.f, 0.f);
05030 
05031                 gViewerWindow->setupViewport();
05032                 mRenderTypeMask = type_mask;
05033                 LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
05034                 LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
05035                 LLViewerCamera::getInstance()->setUserClipPlane(LLPlane(-pnorm, -pd));
05036                 LLPipeline::sUseOcclusion = occlusion;
05037                 
05038                 LLGLState::checkStates();
05039                 LLGLState::checkTextureChannels();
05040                 LLGLState::checkClientArrays();
05041         }
05042 }
05043 
05044 LLCubeMap* LLPipeline::findReflectionMap(const LLVector3& location)
05045 {
05046         LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosAgent(location);
05047         if (region)
05048         {
05049                 LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_VOLUME);
05050                 if (part)
05051                 {
05052                         LLSpatialGroup::OctreeNode* node = part->mOctree->getNodeAt(LLVector3d(location), 32.0);
05053                         if (node)
05054                         {
05055                                 LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
05056                                 return group->mReflectionMap;
05057                         }
05058                 }
05059         }
05060 
05061         return NULL;
05062 }
05063 
05064 void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture)
05065 {
05066         for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
05067         {
05068                 LLSpatialGroup* group = *i;
05069                 if (!group->isDead() &&
05070                         (!sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) &&
05071                         gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
05072                         group->mDrawMap.find(type) != group->mDrawMap.end())
05073                 {
05074                         pass->renderGroup(group,type,mask,texture);
05075                 }
05076         }
05077 }
05078 
05079 void LLPipeline::generateImpostor(LLVOAvatar* avatar)
05080 {
05081         static LLCullResult result;
05082         result.clear();
05083         grabReferences(result);
05084         
05085         if (!avatar || !avatar->mDrawable)
05086         {
05087                 return;
05088         }
05089 
05090         assertInitialized();
05091 
05092         U32 mask;
05093         BOOL muted = LLMuteList::getInstance()->isMuted(avatar->getID());
05094 
05095         if (muted)
05096         {
05097                 mask  = 1 << LLPipeline::RENDER_TYPE_AVATAR;
05098         }
05099         else
05100         {
05101                 mask  = (1<<LLPipeline::RENDER_TYPE_VOLUME) |
05102                                 (1<<LLPipeline::RENDER_TYPE_AVATAR) |
05103                                 (1<<LLPipeline::RENDER_TYPE_BUMP) |
05104                                 (1<<LLPipeline::RENDER_TYPE_GRASS) |
05105                                 (1<<LLPipeline::RENDER_TYPE_SIMPLE) |
05106                                 (1<<LLPipeline::RENDER_TYPE_ALPHA) | 
05107                                 (1<<LLPipeline::RENDER_TYPE_INVISIBLE);
05108         }
05109         
05110         mask = mask & gPipeline.getRenderTypeMask();
05111         U32 saved_mask = gPipeline.mRenderTypeMask;
05112         gPipeline.mRenderTypeMask = mask;
05113 
05114         S32 occlusion = sUseOcclusion;
05115         sUseOcclusion = 0;
05116         sReflectionRender = TRUE;
05117         sImpostorRender = TRUE;
05118 
05119         markVisible(avatar->mDrawable, *LLViewerCamera::getInstance());
05120         LLVOAvatar::sUseImpostors = FALSE;
05121 
05122         LLVOAvatar::attachment_map_t::iterator iter;
05123         for (iter = avatar->mAttachmentPoints.begin();
05124                 iter != avatar->mAttachmentPoints.end();
05125                 ++iter)
05126         {
05127                 LLViewerObject* object = iter->second->getObject();
05128                 if (object)
05129                 {
05130                         markVisible(object->mDrawable->getSpatialBridge(), *LLViewerCamera::getInstance());
05131                 }
05132         }
05133 
05134         stateSort(*LLViewerCamera::getInstance(), result);
05135         
05136         const LLVector3* ext = avatar->mDrawable->getSpatialExtents();
05137         LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset());
05138 
05139         LLCamera camera = *LLViewerCamera::getInstance();
05140 
05141         camera.lookAt(LLViewerCamera::getInstance()->getOrigin(), pos, LLViewerCamera::getInstance()->getUpAxis());
05142         
05143         LLVector2 tdim;
05144 
05145         LLVector3 half_height = (ext[1]-ext[0])*0.5f;
05146 
05147         LLVector3 left = camera.getLeftAxis();
05148         left *= left;
05149         left.normVec();
05150 
05151         LLVector3 up = camera.getUpAxis();
05152         up *= up;
05153         up.normVec();
05154 
05155         tdim.mV[0] = fabsf(half_height * left);
05156         tdim.mV[1] = fabsf(half_height * up);
05157 
05158         glMatrixMode(GL_PROJECTION);
05159         glPushMatrix();
05160         //glh::matrix4f ortho = gl_ortho(-tdim.mV[0], tdim.mV[0], -tdim.mV[1], tdim.mV[1], 1.0, 256.0);
05161         F32 distance = (pos-camera.getOrigin()).magVec();
05162         F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG;
05163         F32 aspect = tdim.mV[0]/tdim.mV[1]; //128.f/256.f;
05164         glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f);
05165         glh_set_current_projection(persp);
05166         glLoadMatrixf(persp.m);
05167 
05168         glMatrixMode(GL_MODELVIEW);
05169         glPushMatrix();
05170         glh::matrix4f mat;
05171         camera.getOpenGLTransform(mat.m);
05172 
05173         mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat;
05174 
05175         glLoadMatrixf(mat.m);
05176         glh_set_current_modelview(mat);
05177 
05178         glClearColor(0.0f,0.0f,0.0f,0.0f);
05179         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
05180         glStencilMask(0xFFFFFFFF);
05181         glClearStencil(0);
05182 
05183         // get the number of pixels per angle
05184         F32 pa = gViewerWindow->getWindowDisplayHeight() / (RAD_TO_DEG * LLViewerCamera::getInstance()->getView());
05185 
05186         //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing)
05187         U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512);
05188         U32 resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512);
05189 
05190         if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() ||
05191                 resY != avatar->mImpostor.getHeight())
05192         {
05193                 avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE);
05194                 avatar->mImpostor.bindTexture();
05195                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
05196                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
05197                 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
05198         }
05199 
05200         {
05201                 LLGLEnable scissor(GL_SCISSOR_TEST);
05202                 glScissor(0, 0, resX, resY);
05203                 avatar->mImpostor.bindTarget();
05204                 avatar->mImpostor.getViewport(gGLViewport);
05205                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
05206         }
05207         
05208         LLGLEnable stencil(GL_STENCIL_TEST);
05209 
05210         glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
05211         glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
05212 
05213         renderGeom(camera);
05214         
05215         glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
05216         glStencilFunc(GL_EQUAL, 1, 0xFFFFFF);
05217 
05218         {
05219                 LLVector3 left = camera.getLeftAxis()*tdim.mV[0]*2.f;
05220                 LLVector3 up = camera.getUpAxis()*tdim.mV[1]*2.f;
05221 
05222                 LLGLEnable blend(muted ? 0 : GL_BLEND);
05223 
05224                 if (muted)
05225                 {
05226                         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
05227                 }
05228                 else
05229                 {
05230                         glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
05231                 }
05232                 
05233                 gGL.blendFunc(GL_ONE, GL_ONE);
05234                 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
05235 
05236                 LLGLDepthTest depth(GL_FALSE, GL_FALSE);
05237 
05238                 gGL.color4f(1,1,1,1);
05239                 gGL.color4ub(64,64,64,1);
05240                 gGL.begin(LLVertexBuffer::QUADS);
05241                 gGL.vertex3fv((pos+left-up).mV);
05242                 gGL.vertex3fv((pos-left-up).mV);
05243                 gGL.vertex3fv((pos-left+up).mV);
05244                 gGL.vertex3fv((pos+left+up).mV);
05245                 gGL.end();
05246                 gGL.flush();
05247 
05248 
05249                 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
05250         }
05251 
05252 
05253         avatar->mImpostor.flush();
05254 
05255         avatar->setImpostorDim(tdim);
05256 
05257         LLVOAvatar::sUseImpostors = TRUE;
05258         sUseOcclusion = occlusion;
05259         sReflectionRender = FALSE;
05260         sImpostorRender = FALSE;
05261         gPipeline.mRenderTypeMask = saved_mask;
05262 
05263         glMatrixMode(GL_PROJECTION);
05264         glPopMatrix();
05265         glMatrixMode(GL_MODELVIEW);
05266         glPopMatrix();
05267 
05268         avatar->mNeedsImpostorUpdate = FALSE;
05269         avatar->cacheImpostorValues();
05270 }
05271 
05272 BOOL LLPipeline::hasRenderBatches(const U32 type) const
05273 {
05274         return sCull->getRenderMapSize(type) > 0;
05275 }
05276 
05277 LLCullResult::drawinfo_list_t::iterator LLPipeline::beginRenderMap(U32 type)
05278 {
05279         return sCull->beginRenderMap(type);
05280 }
05281 
05282 LLCullResult::drawinfo_list_t::iterator LLPipeline::endRenderMap(U32 type)
05283 {
05284         return sCull->endRenderMap(type);
05285 }
05286 
05287 LLCullResult::sg_list_t::iterator LLPipeline::beginAlphaGroups()
05288 {
05289         return sCull->beginAlphaGroups();
05290 }
05291 
05292 LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups()
05293 {
05294         return sCull->endAlphaGroups();
05295 }
05296 

Generated on Fri May 16 08:34:28 2008 for SecondLife by  doxygen 1.5.5