PageRenderTime 1213ms CodeModel.GetById 242ms app.highlight 718ms RepoModel.GetById 237ms app.codeStats 1ms

/indra/newview/llviewerdisplay.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1560 lines | 1085 code | 257 blank | 218 comment | 107 complexity | d0a8819b752d55bb193cd990c2345858 MD5 | raw file
   1/** 
   2 * @file llviewerdisplay.cpp
   3 * @brief LLViewerDisplay class implementation
   4 *
   5 * $LicenseInfo:firstyear=2004&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#include "llviewerprecompiledheaders.h"
  28
  29#include "llviewerdisplay.h"
  30
  31#include "llgl.h"
  32#include "llrender.h"
  33#include "llglheaders.h"
  34#include "llagent.h"
  35#include "llagentcamera.h"
  36#include "llviewercontrol.h"
  37#include "llcoord.h"
  38#include "llcriticaldamp.h"
  39#include "lldir.h"
  40#include "lldynamictexture.h"
  41#include "lldrawpoolalpha.h"
  42#include "llfeaturemanager.h"
  43//#include "llfirstuse.h"
  44#include "llhudmanager.h"
  45#include "llimagebmp.h"
  46#include "llmemory.h"
  47#include "llselectmgr.h"
  48#include "llsky.h"
  49#include "llstartup.h"
  50#include "lltoolfocus.h"
  51#include "lltoolmgr.h"
  52#include "lltooldraganddrop.h"
  53#include "lltoolpie.h"
  54#include "lltracker.h"
  55#include "lltrans.h"
  56#include "llui.h"
  57#include "llviewercamera.h"
  58#include "llviewerobjectlist.h"
  59#include "llviewerparcelmgr.h"
  60#include "llviewerwindow.h"
  61#include "llvoavatarself.h"
  62#include "llvograss.h"
  63#include "llworld.h"
  64#include "pipeline.h"
  65#include "llspatialpartition.h"
  66#include "llappviewer.h"
  67#include "llstartup.h"
  68#include "llviewershadermgr.h"
  69#include "llfasttimer.h"
  70#include "llfloatertools.h"
  71#include "llviewertexturelist.h"
  72#include "llfocusmgr.h"
  73#include "llcubemap.h"
  74#include "llviewerregion.h"
  75#include "lldrawpoolwater.h"
  76#include "lldrawpoolbump.h"
  77#include "llwlparammanager.h"
  78#include "llwaterparammanager.h"
  79#include "llpostprocess.h"
  80
  81extern LLPointer<LLViewerTexture> gStartTexture;
  82
  83LLPointer<LLViewerTexture> gDisconnectedImagep = NULL;
  84
  85// used to toggle renderer back on after teleport
  86const F32 TELEPORT_RENDER_DELAY = 20.f; // Max time a teleport is allowed to take before we raise the curtain
  87const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived.
  88const F32 TELEPORT_LOCAL_DELAY = 1.0f;  // Delay to prevent teleports after starting an in-sim teleport.
  89BOOL		 gTeleportDisplay = FALSE;
  90LLFrameTimer gTeleportDisplayTimer;
  91LLFrameTimer gTeleportArrivalTimer;
  92const F32		RESTORE_GL_TIME = 5.f;	// Wait this long while reloading textures before we raise the curtain
  93
  94BOOL gForceRenderLandFence = FALSE;
  95BOOL gDisplaySwapBuffers = FALSE;
  96BOOL gDepthDirty = FALSE;
  97BOOL gResizeScreenTexture = FALSE;
  98BOOL gWindowResized = FALSE;
  99BOOL gSnapshot = FALSE;
 100
 101U32 gRecentFrameCount = 0; // number of 'recent' frames
 102LLFrameTimer gRecentFPSTime;
 103LLFrameTimer gRecentMemoryTime;
 104
 105// Rendering stuff
 106void pre_show_depth_buffer();
 107void post_show_depth_buffer();
 108void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
 109void render_hud_attachments();
 110void render_ui_3d();
 111void render_ui_2d();
 112void render_disconnected_background();
 113
 114void display_startup()
 115{
 116	if (   !gViewerWindow->getActive()
 117		|| !gViewerWindow->getWindow()->getVisible() 
 118		|| gViewerWindow->getWindow()->getMinimized() )
 119	{
 120		return; 
 121	}
 122
 123	gPipeline.updateGL();
 124
 125	// Update images?
 126	//gImageList.updateImages(0.01f);
 127	LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
 128
 129	LLGLSDefault gls_default;
 130
 131	// Required for HTML update in login screen
 132	static S32 frame_count = 0;
 133
 134	LLGLState::checkStates();
 135	LLGLState::checkTextureChannels();
 136
 137	if (frame_count++ > 1) // make sure we have rendered a frame first
 138	{
 139		LLViewerDynamicTexture::updateAllInstances();
 140	}
 141
 142	LLGLState::checkStates();
 143	LLGLState::checkTextureChannels();
 144
 145	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 146	LLGLSUIDefault gls_ui;
 147	gPipeline.disableLights();
 148
 149	gViewerWindow->setup2DRender();
 150	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
 151
 152	gGL.color4f(1,1,1,1);
 153	gViewerWindow->draw();
 154	gGL.flush();
 155
 156	LLVertexBuffer::unbind();
 157
 158	LLGLState::checkStates();
 159	LLGLState::checkTextureChannels();
 160
 161	gViewerWindow->getWindow()->swapBuffers();
 162	glClear(GL_DEPTH_BUFFER_BIT);
 163}
 164
 165void display_update_camera()
 166{
 167	LLMemType mt_uc(LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA);
 168	// TODO: cut draw distance down if customizing avatar?
 169	// TODO: cut draw distance on per-parcel basis?
 170
 171	// Cut draw distance in half when customizing avatar,
 172	// but on the viewer only.
 173	F32 final_far = gAgentCamera.mDrawDistance;
 174	if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
 175	{
 176		final_far *= 0.5f;
 177	}
 178	LLViewerCamera::getInstance()->setFar(final_far);
 179	gViewerWindow->setup3DRender();
 180	
 181	// update all the sky/atmospheric/water settings
 182	LLWLParamManager::getInstance()->update(LLViewerCamera::getInstance());
 183	LLWaterParamManager::getInstance()->update(LLViewerCamera::getInstance());
 184
 185	// Update land visibility too
 186	LLWorld::getInstance()->setLandFarClip(final_far);
 187}
 188
 189// Write some stats to llinfos
 190void display_stats()
 191{
 192	F32 fps_log_freq = gSavedSettings.getF32("FPSLogFrequency");
 193	if (fps_log_freq > 0.f && gRecentFPSTime.getElapsedTimeF32() >= fps_log_freq)
 194	{
 195		F32 fps = gRecentFrameCount / fps_log_freq;
 196		llinfos << llformat("FPS: %.02f", fps) << llendl;
 197		gRecentFrameCount = 0;
 198		gRecentFPSTime.reset();
 199	}
 200	F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency");
 201	if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq)
 202	{
 203		gMemoryAllocated = LLMemory::getCurrentRSS();
 204		U32 memory = (U32)(gMemoryAllocated / (1024*1024));
 205		llinfos << llformat("MEMORY: %d MB", memory) << llendl;
 206		LLMemory::logMemoryInfo(TRUE) ;
 207		gRecentMemoryTime.reset();
 208	}
 209}
 210
 211static LLFastTimer::DeclareTimer FTM_PICK("Picking");
 212static LLFastTimer::DeclareTimer FTM_RENDER("Render", true);
 213static LLFastTimer::DeclareTimer FTM_UPDATE_SKY("Update Sky");
 214static LLFastTimer::DeclareTimer FTM_UPDATE_TEXTURES("Update Textures");
 215static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE("Update Images");
 216static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_CLASS("Class");
 217static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_BUMP("Bump");
 218static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_LIST("List");
 219static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_DELETE("Delete");
 220
 221// Paint the display!
 222void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 223{
 224	LLMemType mt_render(LLMemType::MTYPE_RENDER);
 225	LLFastTimer t(FTM_RENDER);
 226
 227	if (gWindowResized)
 228	{ //skip render on frames where window has been resized
 229		gGL.flush();
 230		glClear(GL_COLOR_BUFFER_BIT);
 231		gViewerWindow->getWindow()->swapBuffers();
 232		LLPipeline::refreshCachedSettings();
 233		gPipeline.resizeScreenTexture();
 234		gResizeScreenTexture = FALSE;
 235		gWindowResized = FALSE;
 236		return;
 237	}
 238
 239	if (LLPipeline::sRenderDeferred)
 240	{ //hack to make sky show up in deferred snapshots
 241		for_snapshot = FALSE;
 242	}
 243
 244	if (LLPipeline::sRenderFrameTest)
 245	{
 246		send_agent_pause();
 247	}
 248
 249	gSnapshot = for_snapshot;
 250
 251	LLGLSDefault gls_default;
 252	LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL);
 253	
 254	LLVertexBuffer::unbind();
 255
 256	LLGLState::checkStates();
 257	LLGLState::checkTextureChannels();
 258	
 259	stop_glerror();
 260
 261	gPipeline.disableLights();
 262	
 263	stop_glerror();
 264
 265	// Don't draw if the window is hidden or minimized.
 266	// In fact, must explicitly check the minimized state before drawing.
 267	// Attempting to draw into a minimized window causes a GL error. JC
 268	if (   !gViewerWindow->getActive()
 269		|| !gViewerWindow->getWindow()->getVisible() 
 270		|| gViewerWindow->getWindow()->getMinimized() )
 271	{
 272		// Clean up memory the pools may have allocated
 273		if (rebuild)
 274		{
 275			stop_glerror();
 276			gPipeline.rebuildPools();
 277			stop_glerror();
 278		}
 279
 280		stop_glerror();
 281		gViewerWindow->returnEmptyPicks();
 282		stop_glerror();
 283		return; 
 284	}
 285
 286	gViewerWindow->checkSettings();
 287	
 288	{
 289		LLFastTimer ftm(FTM_PICK);
 290		LLAppViewer::instance()->pingMainloopTimeout("Display:Pick");
 291		gViewerWindow->performPick();
 292	}
 293	
 294	LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates");
 295	LLGLState::checkStates();
 296	LLGLState::checkTextureChannels();
 297	
 298	//////////////////////////////////////////////////////////
 299	//
 300	// Logic for forcing window updates if we're in drone mode.
 301	//
 302
 303	// *TODO: Investigate running display() during gHeadlessClient.  See if this early exit is needed DK 2011-02-18
 304	if (gHeadlessClient) 
 305	{
 306#if LL_WINDOWS
 307		static F32 last_update_time = 0.f;
 308		if ((gFrameTimeSeconds - last_update_time) > 1.f)
 309		{
 310			InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE);
 311			last_update_time = gFrameTimeSeconds;
 312		}
 313#elif LL_DARWIN
 314		// MBW -- Do something clever here.
 315#endif
 316		// Not actually rendering, don't bother.
 317		return;
 318	}
 319
 320
 321	//
 322	// Bail out if we're in the startup state and don't want to try to
 323	// render the world.
 324	//
 325	if (LLStartUp::getStartupState() < STATE_STARTED)
 326	{
 327		LLAppViewer::instance()->pingMainloopTimeout("Display:Startup");
 328		display_startup();
 329		return;
 330	}
 331
 332	//LLGLState::verify(FALSE);
 333
 334	/////////////////////////////////////////////////
 335	//
 336	// Update GL Texture statistics (used for discard logic?)
 337	//
 338
 339	LLAppViewer::instance()->pingMainloopTimeout("Display:TextureStats");
 340	stop_glerror();
 341
 342	LLImageGL::updateStats(gFrameTimeSeconds);
 343	
 344	LLVOAvatar::sRenderName = gSavedSettings.getS32("AvatarNameTagMode");
 345	LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("NameTagShowGroupTitles") && gSavedSettings.getS32("AvatarNameTagMode"));
 346	
 347	gPipeline.mBackfaceCull = TRUE;
 348	gFrameCount++;
 349	gRecentFrameCount++;
 350	if (gFocusMgr.getAppHasFocus())
 351	{
 352		gForegroundFrameCount++;
 353	}
 354
 355	//////////////////////////////////////////////////////////
 356	//
 357	// Display start screen if we're teleporting, and skip render
 358	//
 359
 360	if (gTeleportDisplay)
 361	{
 362		LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport");
 363		const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived.
 364
 365		S32 attach_count = 0;
 366		if (isAgentAvatarValid())
 367		{
 368			attach_count = gAgentAvatarp->getAttachmentCount();
 369		}
 370		F32 teleport_save_time = TELEPORT_EXPIRY + TELEPORT_EXPIRY_PER_ATTACHMENT * attach_count;
 371		F32 teleport_elapsed = gTeleportDisplayTimer.getElapsedTimeF32();
 372		F32 teleport_percent = teleport_elapsed * (100.f / teleport_save_time);
 373		if( (gAgent.getTeleportState() != LLAgent::TELEPORT_START) && (teleport_percent > 100.f) )
 374		{
 375			// Give up.  Don't keep the UI locked forever.
 376			gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
 377			gAgent.setTeleportMessage(std::string());
 378		}
 379
 380		const std::string& message = gAgent.getTeleportMessage();
 381		switch( gAgent.getTeleportState() )
 382		{
 383		case LLAgent::TELEPORT_START:
 384			// Transition to REQUESTED.  Viewer has sent some kind
 385			// of TeleportRequest to the source simulator
 386			gTeleportDisplayTimer.reset();
 387			gViewerWindow->setShowProgress(TRUE);
 388			gViewerWindow->setProgressPercent(0);
 389			gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED );
 390			gAgent.setTeleportMessage(
 391				LLAgent::sTeleportProgressMessages["requesting"]);
 392			break;
 393
 394		case LLAgent::TELEPORT_REQUESTED:
 395			// Waiting for source simulator to respond
 396			gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) );
 397			gViewerWindow->setProgressString(message);
 398			break;
 399
 400		case LLAgent::TELEPORT_MOVING:
 401			// Viewer has received destination location from source simulator
 402			gViewerWindow->setProgressPercent( llmin(teleport_percent, 75.f) );
 403			gViewerWindow->setProgressString(message);
 404			break;
 405
 406		case LLAgent::TELEPORT_START_ARRIVAL:
 407			// Transition to ARRIVING.  Viewer has received avatar update, etc., from destination simulator
 408			gTeleportArrivalTimer.reset();
 409				gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
 410			gViewerWindow->setProgressPercent(75.f);
 411			gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING );
 412			gAgent.setTeleportMessage(
 413				LLAgent::sTeleportProgressMessages["arriving"]);
 414			gTextureList.mForceResetTextureStats = TRUE;
 415			gAgentCamera.resetView(TRUE, TRUE);
 416			break;
 417
 418		case LLAgent::TELEPORT_ARRIVING:
 419			// Make the user wait while content "pre-caches"
 420			{
 421				F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY);
 422				if( arrival_fraction > 1.f )
 423				{
 424					arrival_fraction = 1.f;
 425					//LLFirstUse::useTeleport();
 426					gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
 427				}
 428				gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
 429				gViewerWindow->setProgressPercent(  arrival_fraction * 25.f + 75.f);
 430				gViewerWindow->setProgressString(message);
 431			}
 432			break;
 433
 434		case LLAgent::TELEPORT_LOCAL:
 435			// Short delay when teleporting in the same sim (progress screen active but not shown - did not
 436			// fall-through from TELEPORT_START)
 437			{
 438				if( gTeleportDisplayTimer.getElapsedTimeF32() > TELEPORT_LOCAL_DELAY )
 439				{
 440					//LLFirstUse::useTeleport();
 441					gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
 442				}
 443			}
 444			break;
 445
 446		case LLAgent::TELEPORT_NONE:
 447			// No teleport in progress
 448			gViewerWindow->setShowProgress(FALSE);
 449			gTeleportDisplay = FALSE;
 450			break;
 451		}
 452	}
 453    else if(LLAppViewer::instance()->logoutRequestSent())
 454	{
 455		LLAppViewer::instance()->pingMainloopTimeout("Display:Logout");
 456		F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f / gLogoutMaxTime;
 457		if (percent_done > 100.f)
 458		{
 459			percent_done = 100.f;
 460		}
 461
 462		if( LLApp::isExiting() )
 463		{
 464			percent_done = 100.f;
 465		}
 466		
 467		gViewerWindow->setProgressPercent( percent_done );
 468	}
 469	else
 470	if (gRestoreGL)
 471	{
 472		LLAppViewer::instance()->pingMainloopTimeout("Display:RestoreGL");
 473		F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME;
 474		if( percent_done > 100.f )
 475		{
 476			gViewerWindow->setShowProgress(FALSE);
 477			gRestoreGL = FALSE;
 478		}
 479		else
 480		{
 481
 482			if( LLApp::isExiting() )
 483			{
 484				percent_done = 100.f;
 485			}
 486			
 487			gViewerWindow->setProgressPercent( percent_done );
 488		}
 489	}
 490
 491	//////////////////////////
 492	//
 493	// Prepare for the next frame
 494	//
 495
 496	/////////////////////////////
 497	//
 498	// Update the camera
 499	//
 500	//
 501
 502	LLAppViewer::instance()->pingMainloopTimeout("Display:Camera");
 503	LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield);
 504	LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE);
 505
 506	//////////////////////////
 507	//
 508	// clear the next buffer
 509	// (must follow dynamic texture writing since that uses the frame buffer)
 510	//
 511
 512	if (gDisconnected)
 513	{
 514		LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected");
 515		render_ui();
 516	}
 517	
 518	//////////////////////////
 519	//
 520	// Set rendering options
 521	//
 522	//
 523	LLAppViewer::instance()->pingMainloopTimeout("Display:RenderSetup");
 524	stop_glerror();
 525
 526	///////////////////////////////////////
 527	//
 528	// Slam lighting parameters back to our defaults.
 529	// Note that these are not the same as GL defaults...
 530
 531	stop_glerror();
 532	gGL.setAmbientLightColor(LLColor4::white);
 533	stop_glerror();
 534			
 535	/////////////////////////////////////
 536	//
 537	// Render
 538	//
 539	// Actually push all of our triangles to the screen.
 540	//
 541
 542	// do render-to-texture stuff here
 543	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES))
 544	{
 545		LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures");
 546		LLFastTimer t(FTM_UPDATE_TEXTURES);
 547		if (LLViewerDynamicTexture::updateAllInstances())
 548		{
 549			gGL.setColorMask(true, true);
 550			glClear(GL_DEPTH_BUFFER_BIT);
 551		}
 552	}
 553
 554	gViewerWindow->setup3DViewport();
 555
 556	gPipeline.resetFrameStats();	// Reset per-frame statistics.
 557	
 558	if (!gDisconnected)
 559	{
 560		LLMemType mt_du(LLMemType::MTYPE_DISPLAY_UPDATE);
 561		LLAppViewer::instance()->pingMainloopTimeout("Display:Update");
 562		if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
 563		{ //don't draw hud objects in this frame
 564			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
 565		}
 566
 567		if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES))
 568		{ //don't draw hud particles in this frame
 569			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
 570		}
 571
 572		//upkeep gl name pools
 573		LLGLNamePool::upkeepPools();
 574		
 575		stop_glerror();
 576		display_update_camera();
 577		stop_glerror();
 578				
 579		// *TODO: merge these two methods
 580		{
 581			LLMemType mt_uh(LLMemType::MTYPE_DISPLAY_UPDATE_HUD);
 582			LLHUDManager::getInstance()->updateEffects();
 583			LLHUDObject::updateAll();
 584			stop_glerror();
 585		}
 586
 587		{
 588			LLMemType mt_ug(LLMemType::MTYPE_DISPLAY_UPDATE_GEOM);
 589			const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time
 590			gPipeline.createObjects(max_geom_update_time);
 591			gPipeline.processPartitionQ();
 592			gPipeline.updateGeom(max_geom_update_time);
 593			stop_glerror();
 594		}
 595
 596		gPipeline.updateGL();
 597		stop_glerror();
 598
 599		S32 water_clip = 0;
 600		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
 601			 (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) || 
 602			  gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER)))
 603		{
 604			if (LLViewerCamera::getInstance()->cameraUnderWater())
 605			{
 606				water_clip = -1;
 607			}
 608			else
 609			{
 610				water_clip = 1;
 611			}
 612		}
 613		
 614		LLAppViewer::instance()->pingMainloopTimeout("Display:Cull");
 615		
 616		//Increment drawable frame counter
 617		LLDrawable::incrementVisible();
 618
 619		LLSpatialGroup::sNoDelete = TRUE;
 620		LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
 621
 622		/*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred)
 623		{ //force occlusion on for all render types if doing deferred render (tighter shadow frustum)
 624			LLPipeline::sUseOcclusion = 3;
 625		}*/
 626
 627		S32 occlusion = LLPipeline::sUseOcclusion;
 628		if (gDepthDirty)
 629		{ //depth buffer is invalid, don't overwrite occlusion state
 630			LLPipeline::sUseOcclusion = llmin(occlusion, 1);
 631		}
 632		gDepthDirty = FALSE;
 633
 634		LLGLState::checkStates();
 635		LLGLState::checkTextureChannels();
 636		LLGLState::checkClientArrays();
 637
 638		static LLCullResult result;
 639		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
 640		gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip);
 641		stop_glerror();
 642
 643		LLGLState::checkStates();
 644		LLGLState::checkTextureChannels();
 645		LLGLState::checkClientArrays();
 646
 647		BOOL to_texture = gPipeline.canUseVertexShaders() &&
 648						LLPipeline::sRenderGlow;
 649
 650		LLAppViewer::instance()->pingMainloopTimeout("Display:Swap");
 651		
 652		{ 
 653			LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SWAP);
 654
 655			if (gResizeScreenTexture)
 656			{
 657				gResizeScreenTexture = FALSE;
 658				gPipeline.resizeScreenTexture();
 659			}
 660
 661			gGL.setColorMask(true, true);
 662			glClearColor(0,0,0,0);
 663
 664			LLGLState::checkStates();
 665			LLGLState::checkTextureChannels();
 666			LLGLState::checkClientArrays();
 667
 668			if (!for_snapshot)
 669			{
 670				if (gFrameCount > 1)
 671				{ //for some reason, ATI 4800 series will error out if you 
 672				  //try to generate a shadow before the first frame is through
 673					gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
 674				}
 675
 676				LLVertexBuffer::unbind();
 677
 678				LLGLState::checkStates();
 679				LLGLState::checkTextureChannels();
 680				LLGLState::checkClientArrays();
 681
 682				glh::matrix4f proj = glh_get_current_projection();
 683				glh::matrix4f mod = glh_get_current_modelview();
 684				glViewport(0,0,512,512);
 685				LLVOAvatar::updateFreezeCounter() ;
 686
 687				if(!LLPipeline::sMemAllocationThrottled)
 688				{		
 689					LLVOAvatar::updateImpostors();
 690				}
 691
 692				glh_set_current_projection(proj);
 693				glh_set_current_modelview(mod);
 694				gGL.matrixMode(LLRender::MM_PROJECTION);
 695				gGL.loadMatrix(proj.m);
 696				gGL.matrixMode(LLRender::MM_MODELVIEW);
 697				gGL.loadMatrix(mod.m);
 698				gViewerWindow->setup3DViewport();
 699
 700				LLGLState::checkStates();
 701				LLGLState::checkTextureChannels();
 702				LLGLState::checkClientArrays();
 703
 704			}
 705			glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 706		}
 707
 708		LLGLState::checkStates();
 709		LLGLState::checkClientArrays();
 710
 711		//if (!for_snapshot)
 712		{
 713			LLMemType mt_gw(LLMemType::MTYPE_DISPLAY_GEN_REFLECTION);
 714			LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery");
 715			gPipeline.generateWaterReflection(*LLViewerCamera::getInstance());
 716			gPipeline.generateHighlight(*LLViewerCamera::getInstance());
 717			gPipeline.renderPhysicsDisplay();
 718		}
 719
 720		LLGLState::checkStates();
 721		LLGLState::checkClientArrays();
 722
 723		//////////////////////////////////////
 724		//
 725		// Update images, using the image stats generated during object update/culling
 726		//
 727		// Can put objects onto the retextured list.
 728		//
 729		// Doing this here gives hardware occlusion queries extra time to complete
 730		LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages");
 731		
 732		{
 733			LLMemType mt_iu(LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE);
 734			LLFastTimer t(FTM_IMAGE_UPDATE);
 735			
 736			{
 737				LLFastTimer t(FTM_IMAGE_UPDATE_CLASS);
 738				LLViewerTexture::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(),
 739											LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean());
 740			}
 741
 742			
 743			{
 744				LLFastTimer t(FTM_IMAGE_UPDATE_BUMP);
 745				gBumpImageList.updateImages();  // must be called before gTextureList version so that it's textures are thrown out first.
 746			}
 747
 748			{
 749				LLFastTimer t(FTM_IMAGE_UPDATE_LIST);
 750				F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time
 751				max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame)
 752				gTextureList.updateImages(max_image_decode_time);
 753			}
 754
 755			{
 756				LLFastTimer t(FTM_IMAGE_UPDATE_DELETE);
 757				//remove dead textures from GL
 758				LLImageGL::deleteDeadTextures();
 759				stop_glerror();
 760			}
 761		}
 762
 763		LLGLState::checkStates();
 764		LLGLState::checkClientArrays();
 765
 766		///////////////////////////////////
 767		//
 768		// StateSort
 769		//
 770		// Responsible for taking visible objects, and adding them to the appropriate draw orders.
 771		// In the case of alpha objects, z-sorts them first.
 772		// Also creates special lists for outlines and selected face rendering.
 773		//
 774		LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort");
 775		{
 776			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
 777			LLMemType mt_ss(LLMemType::MTYPE_DISPLAY_STATE_SORT);
 778			gPipeline.stateSort(*LLViewerCamera::getInstance(), result);
 779			stop_glerror();
 780				
 781			if (rebuild)
 782			{
 783				//////////////////////////////////////
 784				//
 785				// rebuildPools
 786				//
 787				//
 788				gPipeline.rebuildPools();
 789				stop_glerror();
 790			}
 791		}
 792
 793		LLGLState::checkStates();
 794		LLGLState::checkClientArrays();
 795
 796		LLPipeline::sUseOcclusion = occlusion;
 797
 798		{
 799			LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SKY);
 800			LLAppViewer::instance()->pingMainloopTimeout("Display:Sky");
 801			LLFastTimer t(FTM_UPDATE_SKY);	
 802			gSky.updateSky();
 803		}
 804
 805		if(gUseWireframe)
 806		{
 807			glClearColor(0.5f, 0.5f, 0.5f, 0.f);
 808			glClear(GL_COLOR_BUFFER_BIT);
 809			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
 810		}
 811
 812		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart");
 813		
 814		//// render frontmost floater opaque for occlusion culling purposes
 815		//LLFloater* frontmost_floaterp = gFloaterView->getFrontmost();
 816		//// assumes frontmost floater with focus is opaque
 817		//if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp))
 818		//{
 819		//	gGL.matrixMode(LLRender::MM_MODELVIEW);
 820		//	gGL.pushMatrix();
 821		//	{
 822		//		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 823
 824		//		glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
 825		//		gGL.loadIdentity();
 826
 827		//		LLRect floater_rect = frontmost_floaterp->calcScreenRect();
 828		//		// deflate by one pixel so rounding errors don't occlude outside of floater extents
 829		//		floater_rect.stretch(-1);
 830		//		LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidthScaled(), 
 831		//								(F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeightScaled(),
 832		//								(F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidthScaled(),
 833		//								(F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeightScaled());
 834		//		floater_3d_rect.translate(-0.5f, -0.5f);
 835		//		gGL.translatef(0.f, 0.f, -LLViewerCamera::getInstance()->getNear());
 836		//		gGL.scalef(LLViewerCamera::getInstance()->getNear() * LLViewerCamera::getInstance()->getAspect() / sinf(LLViewerCamera::getInstance()->getView()), LLViewerCamera::getInstance()->getNear() / sinf(LLViewerCamera::getInstance()->getView()), 1.f);
 837		//		gGL.color4fv(LLColor4::white.mV);
 838		//		gGL.begin(LLVertexBuffer::QUADS);
 839		//		{
 840		//			gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f);
 841		//			gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f);
 842		//			gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f);
 843		//			gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f);
 844		//		}
 845		//		gGL.end();
 846		//		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 847		//	}
 848		//	gGL.popMatrix();
 849		//}
 850
 851		LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE;
 852		
 853		LLGLState::checkStates();
 854		LLGLState::checkClientArrays();
 855
 856		stop_glerror();
 857
 858		if (to_texture)
 859		{
 860			gGL.setColorMask(true, true);
 861					
 862			if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
 863			{
 864				gPipeline.mDeferredScreen.bindTarget();
 865				glClearColor(1,0,1,1);
 866				gPipeline.mDeferredScreen.clear();
 867			}
 868			else
 869			{
 870				gPipeline.mScreen.bindTarget();
 871				if (LLPipeline::sUnderWaterRender && !gPipeline.canUseWindLightShaders())
 872				{
 873					const LLColor4 &col = LLDrawPoolWater::sWaterFogColor;
 874					glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
 875				}
 876				gPipeline.mScreen.clear();
 877			}
 878			
 879			gGL.setColorMask(true, false);
 880		}
 881		
 882		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderGeom");
 883		
 884		if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot())
 885				&& !gRestoreGL)
 886		{
 887			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
 888			LLMemType mt_rg(LLMemType::MTYPE_DISPLAY_RENDER_GEOM);
 889			gGL.setColorMask(true, false);
 890			if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
 891			{
 892				gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance());
 893			}
 894			else
 895			{
 896				gPipeline.renderGeom(*LLViewerCamera::getInstance(), TRUE);
 897			}
 898			
 899			gGL.setColorMask(true, true);
 900
 901			//store this frame's modelview matrix for use
 902			//when rendering next frame's occlusion queries
 903			for (U32 i = 0; i < 16; i++)
 904			{
 905				gGLLastModelView[i] = gGLModelView[i];
 906				gGLLastProjection[i] = gGLProjection[i];
 907			}
 908			stop_glerror();
 909		}
 910
 911		for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++)
 912		{ //dummy cleanup of any currently bound textures
 913			if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE)
 914			{
 915				gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType());
 916				gGL.getTexUnit(i)->disable();
 917			}
 918		}
 919		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");		
 920		
 921		if (to_texture)
 922		{
 923			LLMemType mt_rf(LLMemType::MTYPE_DISPLAY_RENDER_FLUSH);
 924			if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
 925			{
 926				gPipeline.mDeferredScreen.flush();
 927				if(LLRenderTarget::sUseFBO)
 928				{
 929					LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), 
 930															  gPipeline.mDeferredScreen.getHeight(), 0, 0, 
 931															  gPipeline.mDeferredScreen.getWidth(), 
 932															  gPipeline.mDeferredScreen.getHeight(), 
 933															  GL_DEPTH_BUFFER_BIT, GL_NEAREST);
 934				}
 935			}
 936			else
 937			{
 938				gPipeline.mScreen.flush();
 939				if(LLRenderTarget::sUseFBO)
 940				{				
 941					LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(), 
 942															  gPipeline.mScreen.getHeight(), 0, 0, 
 943															  gPipeline.mScreen.getWidth(), 
 944															  gPipeline.mScreen.getHeight(), 
 945															  GL_DEPTH_BUFFER_BIT, GL_NEAREST);
 946				}
 947			}
 948		}
 949
 950		if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
 951		{
 952			gPipeline.renderDeferredLighting();
 953		}
 954
 955		LLPipeline::sUnderWaterRender = FALSE;
 956
 957		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI");
 958		if (!for_snapshot)
 959		{
 960			LLFastTimer t(FTM_RENDER_UI);
 961			render_ui();
 962		}
 963
 964		
 965		LLSpatialGroup::sNoDelete = FALSE;
 966		gPipeline.clearReferences();
 967
 968		gPipeline.rebuildGroups();
 969	}
 970
 971	LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats");
 972	
 973	stop_glerror();
 974
 975	if (LLPipeline::sRenderFrameTest)
 976	{
 977		send_agent_resume();
 978		LLPipeline::sRenderFrameTest = FALSE;
 979	}
 980
 981	display_stats();
 982				
 983	LLAppViewer::instance()->pingMainloopTimeout("Display:Done");
 984}
 985
 986void render_hud_attachments()
 987{
 988	LLMemType mt_ra(LLMemType::MTYPE_DISPLAY_RENDER_ATTACHMENTS);
 989	gGL.matrixMode(LLRender::MM_PROJECTION);
 990	gGL.pushMatrix();
 991	gGL.matrixMode(LLRender::MM_MODELVIEW);
 992	gGL.pushMatrix();
 993		
 994	glh::matrix4f current_proj = glh_get_current_projection();
 995	glh::matrix4f current_mod = glh_get_current_modelview();
 996
 997	// clamp target zoom level to reasonable values
 998	gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f);
 999	// smoothly interpolate current zoom level
1000	gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f));
1001
1002	if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices())
1003	{
1004		LLCamera hud_cam = *LLViewerCamera::getInstance();
1005		LLVector3 origin = hud_cam.getOrigin();
1006		hud_cam.setOrigin(-1.f,0,0);
1007		hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1));
1008		LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE);
1009
1010		bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && gSavedSettings.getBOOL("RenderHUDParticles");
1011		
1012		//only render hud objects
1013		gPipeline.pushRenderTypeMask();
1014		
1015		// turn off everything
1016		gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES);
1017		// turn on HUD
1018		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
1019		// turn on HUD particles
1020		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
1021
1022		// if particles are off, turn off hud-particles as well
1023		if (!render_particles)
1024		{
1025			// turn back off HUD particles
1026			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
1027		}
1028
1029		bool has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
1030		if (has_ui)
1031		{
1032			gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
1033		}
1034
1035		S32 use_occlusion = LLPipeline::sUseOcclusion;
1036		LLPipeline::sUseOcclusion = 0;
1037				
1038		//cull, sort, and render hud objects
1039		static LLCullResult result;
1040		LLSpatialGroup::sNoDelete = TRUE;
1041
1042		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
1043		gPipeline.updateCull(hud_cam, result);
1044
1045		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP);
1046		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE);
1047		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME);
1048		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA);
1049		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT);
1050		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA);
1051		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK);
1052		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP);
1053		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT);
1054		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK);
1055		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY);
1056		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_SHINY);
1057		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISIBLE);
1058		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY);
1059		
1060		gPipeline.stateSort(hud_cam, result);
1061
1062		gPipeline.renderGeom(hud_cam);
1063
1064		LLSpatialGroup::sNoDelete = FALSE;
1065		//gPipeline.clearReferences();
1066
1067		render_hud_elements();
1068
1069		//restore type mask
1070		gPipeline.popRenderTypeMask();
1071
1072		if (has_ui)
1073		{
1074			gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
1075		}
1076		LLPipeline::sUseOcclusion = use_occlusion;
1077	}
1078	gGL.matrixMode(LLRender::MM_PROJECTION);
1079	gGL.popMatrix();
1080	gGL.matrixMode(LLRender::MM_MODELVIEW);
1081	gGL.popMatrix();
1082	
1083	glh_set_current_projection(current_proj);
1084	glh_set_current_modelview(current_mod);
1085}
1086
1087LLRect get_whole_screen_region()
1088{
1089	LLRect whole_screen = gViewerWindow->getWorldViewRectScaled();
1090	
1091	// apply camera zoom transform (for high res screenshots)
1092	F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
1093	S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
1094	if (zoom_factor > 1.f)
1095	{
1096		S32 num_horizontal_tiles = llceil(zoom_factor);
1097		S32 tile_width = llround((F32)gViewerWindow->getWorldViewWidthScaled() / zoom_factor);
1098		S32 tile_height = llround((F32)gViewerWindow->getWorldViewHeightScaled() / zoom_factor);
1099		int tile_y = sub_region / num_horizontal_tiles;
1100		int tile_x = sub_region - (tile_y * num_horizontal_tiles);
1101			
1102		whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWorldViewHeightScaled() - (tile_y * tile_height), tile_width, tile_height);
1103	}
1104	return whole_screen;
1105}
1106
1107bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::matrix4f &model)
1108{
1109	if (isAgentAvatarValid() && gAgentAvatarp->hasHUDAttachment())
1110	{
1111		F32 zoom_level = gAgentCamera.mHUDCurZoom;
1112		LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
1113		
1114		F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
1115		proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth);
1116		proj.element(2,2) = -0.01f;
1117		
1118		F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect();
1119		
1120		glh::matrix4f mat;
1121		F32 scale_x = (F32)gViewerWindow->getWorldViewWidthScaled() / (F32)screen_region.getWidth();
1122		F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight();
1123		mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f));
1124		mat.set_translate(
1125			glh::vec3f(clamp_rescale((F32)(screen_region.getCenterX() - screen_region.mLeft), 0.f, (F32)gViewerWindow->getWorldViewWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio),
1126					   clamp_rescale((F32)(screen_region.getCenterY() - screen_region.mBottom), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y),
1127					   0.f));
1128		proj *= mat;
1129		
1130		glh::matrix4f tmp_model((GLfloat*) OGL_TO_CFR_ROTATION);
1131		
1132		mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level));
1133		mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f));
1134		
1135		tmp_model *= mat;
1136		model = tmp_model;		
1137		return TRUE;
1138	}
1139	else
1140	{
1141		return FALSE;
1142	}
1143}
1144
1145bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model)
1146{
1147	LLRect whole_screen = get_whole_screen_region();
1148	return get_hud_matrices(whole_screen, proj, model);
1149}
1150
1151BOOL setup_hud_matrices()
1152{
1153	LLRect whole_screen = get_whole_screen_region();
1154	return setup_hud_matrices(whole_screen);
1155}
1156
1157BOOL setup_hud_matrices(const LLRect& screen_region)
1158{
1159	glh::matrix4f proj, model;
1160	bool result = get_hud_matrices(screen_region, proj, model);
1161	if (!result) return result;
1162	
1163	// set up transform to keep HUD objects in front of camera
1164	gGL.matrixMode(LLRender::MM_PROJECTION);
1165	gGL.loadMatrix(proj.m);
1166	glh_set_current_projection(proj);
1167	
1168	gGL.matrixMode(LLRender::MM_MODELVIEW);
1169	gGL.loadMatrix(model.m);
1170	glh_set_current_modelview(model);
1171	return TRUE;
1172}
1173
1174static LLFastTimer::DeclareTimer FTM_SWAP("Swap");
1175
1176void render_ui(F32 zoom_factor, int subfield)
1177{
1178	LLMemType mt_ru(LLMemType::MTYPE_DISPLAY_RENDER_UI);
1179	LLGLState::checkStates();
1180	
1181	glh::matrix4f saved_view = glh_get_current_modelview();
1182
1183	if (!gSnapshot)
1184	{
1185		gGL.pushMatrix();
1186		gGL.loadMatrix(gGLLastModelView);
1187		glh_set_current_modelview(glh_copy_matrix(gGLLastModelView));
1188	}
1189	
1190	{
1191		BOOL to_texture = gPipeline.canUseVertexShaders() &&
1192							LLPipeline::sRenderGlow;
1193
1194		if (to_texture)
1195		{
1196			gPipeline.renderBloom(gSnapshot, zoom_factor, subfield);
1197		}
1198		
1199		render_hud_elements();
1200		render_hud_attachments();
1201	}
1202
1203	LLGLSDefault gls_default;
1204	LLGLSUIDefault gls_ui;
1205	{
1206		gPipeline.disableLights();
1207	}
1208
1209	{
1210		gGL.color4f(1,1,1,1);
1211		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
1212		{
1213			LLFastTimer t(FTM_RENDER_UI);
1214
1215			if (!gDisconnected)
1216			{
1217				render_ui_3d();
1218				LLGLState::checkStates();
1219			}
1220			else
1221			{
1222				render_disconnected_background();
1223			}
1224
1225			render_ui_2d();
1226			LLGLState::checkStates();
1227		}
1228		gGL.flush();
1229
1230		{
1231			gViewerWindow->setup2DRender();
1232			gViewerWindow->updateDebugText();
1233			gViewerWindow->drawDebugText();
1234		}
1235
1236		LLVertexBuffer::unbind();
1237	}
1238
1239	if (!gSnapshot)
1240	{
1241		glh_set_current_modelview(saved_view);
1242		gGL.popMatrix();
1243	}
1244
1245	if (gDisplaySwapBuffers)
1246	{
1247		LLFastTimer t(FTM_SWAP);
1248		gViewerWindow->getWindow()->swapBuffers();
1249	}
1250	gDisplaySwapBuffers = TRUE;
1251}
1252
1253void renderCoordinateAxes()
1254{
1255	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
1256	gGL.begin(LLRender::LINES);
1257		gGL.color3f(1.0f, 0.0f, 0.0f);   // i direction = X-Axis = red
1258		gGL.vertex3f(0.0f, 0.0f, 0.0f);
1259		gGL.vertex3f(2.0f, 0.0f, 0.0f);
1260		gGL.vertex3f(3.0f, 0.0f, 0.0f);
1261		gGL.vertex3f(5.0f, 0.0f, 0.0f);
1262		gGL.vertex3f(6.0f, 0.0f, 0.0f);
1263		gGL.vertex3f(8.0f, 0.0f, 0.0f);
1264		// Make an X
1265		gGL.vertex3f(11.0f, 1.0f, 1.0f);
1266		gGL.vertex3f(11.0f, -1.0f, -1.0f);
1267		gGL.vertex3f(11.0f, 1.0f, -1.0f);
1268		gGL.vertex3f(11.0f, -1.0f, 1.0f);
1269
1270		gGL.color3f(0.0f, 1.0f, 0.0f);   // j direction = Y-Axis = green
1271		gGL.vertex3f(0.0f, 0.0f, 0.0f);
1272		gGL.vertex3f(0.0f, 2.0f, 0.0f);
1273		gGL.vertex3f(0.0f, 3.0f, 0.0f);
1274		gGL.vertex3f(0.0f, 5.0f, 0.0f);
1275		gGL.vertex3f(0.0f, 6.0f, 0.0f);
1276		gGL.vertex3f(0.0f, 8.0f, 0.0f);
1277		// Make a Y
1278		gGL.vertex3f(1.0f, 11.0f, 1.0f);
1279		gGL.vertex3f(0.0f, 11.0f, 0.0f);
1280		gGL.vertex3f(-1.0f, 11.0f, 1.0f);
1281		gGL.vertex3f(0.0f, 11.0f, 0.0f);
1282		gGL.vertex3f(0.0f, 11.0f, 0.0f);
1283		gGL.vertex3f(0.0f, 11.0f, -1.0f);
1284
1285		gGL.color3f(0.0f, 0.0f, 1.0f);   // Z-Axis = blue
1286		gGL.vertex3f(0.0f, 0.0f, 0.0f);
1287		gGL.vertex3f(0.0f, 0.0f, 2.0f);
1288		gGL.vertex3f(0.0f, 0.0f, 3.0f);
1289		gGL.vertex3f(0.0f, 0.0f, 5.0f);
1290		gGL.vertex3f(0.0f, 0.0f, 6.0f);
1291		gGL.vertex3f(0.0f, 0.0f, 8.0f);
1292		// Make a Z
1293		gGL.vertex3f(-1.0f, 1.0f, 11.0f);
1294		gGL.vertex3f(1.0f, 1.0f, 11.0f);
1295		gGL.vertex3f(1.0f, 1.0f, 11.0f);
1296		gGL.vertex3f(-1.0f, -1.0f, 11.0f);
1297		gGL.vertex3f(-1.0f, -1.0f, 11.0f);
1298		gGL.vertex3f(1.0f, -1.0f, 11.0f);
1299	gGL.end();
1300}
1301
1302
1303void draw_axes() 
1304{
1305	LLGLSUIDefault gls_ui;
1306	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
1307	// A vertical white line at origin
1308	LLVector3 v = gAgent.getPositionAgent();
1309	gGL.begin(LLRender::LINES);
1310		gGL.color3f(1.0f, 1.0f, 1.0f); 
1311		gGL.vertex3f(0.0f, 0.0f, 0.0f);
1312		gGL.vertex3f(0.0f, 0.0f, 40.0f);
1313	gGL.end();
1314	// Some coordinate axes
1315	gGL.pushMatrix();
1316		gGL.translatef( v.mV[VX], v.mV[VY], v.mV[VZ] );
1317		renderCoordinateAxes();
1318	gGL.popMatrix();
1319}
1320
1321void render_ui_3d()
1322{
1323	LLGLSPipeline gls_pipeline;
1324
1325	//////////////////////////////////////
1326	//
1327	// Render 3D UI elements
1328	// NOTE: zbuffer is cleared before we get here by LLDrawPoolHUD,
1329	//		 so 3d elements requiring Z buffer are moved to LLDrawPoolHUD
1330	//
1331
1332	/////////////////////////////////////////////////////////////
1333	//
1334	// Render 2.5D elements (2D elements in the world)
1335	// Stuff without z writes
1336	//
1337
1338	// Debugging stuff goes before the UI.
1339
1340	stop_glerror();
1341	
1342	if (LLGLSLShader::sNoFixedFunction)
1343	{
1344		gUIProgram.bind();
1345	}
1346
1347	// Coordinate axes
1348	if (gSavedSettings.getBOOL("ShowAxes"))
1349	{
1350		draw_axes();
1351	}
1352
1353	gViewerWindow->renderSelections(FALSE, FALSE, TRUE); // Non HUD call in render_hud_elements
1354	stop_glerror();
1355}
1356
1357void render_ui_2d()
1358{
1359	LLGLSUIDefault gls_ui;
1360
1361	/////////////////////////////////////////////////////////////
1362	//
1363	// Render 2D UI elements that overlay the world (no z compare)
1364
1365	//  Disable wireframe mode below here, as this is HUD/menus
1366	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1367
1368	//  Menu overlays, HUD, etc
1369	gViewerWindow->setup2DRender();
1370
1371	F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
1372	S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
1373
1374	if (zoom_factor > 1.f)
1375	{
1376		//decompose subregion number to x and y values
1377		int pos_y = sub_region / llceil(zoom_factor);
1378		int pos_x = sub_region - (pos_y*llceil(zoom_factor));
1379		// offset for this tile
1380		LLFontGL::sCurOrigin.mX -= llround((F32)gViewerWindow->getWindowWidthScaled() * (F32)pos_x / zoom_factor);
1381		LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeightScaled() * (F32)pos_y / zoom_factor);
1382	}
1383
1384	stop_glerror();
1385	//gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
1386
1387	// render outline for HUD
1388	if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f)
1389	{
1390		gGL.pushMatrix();
1391		S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2);
1392		S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2);
1393		gGL.scalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f);
1394		gGL.translatef((F32)half_width, (F32)half_height, 0.f);
1395		F32 zoom = gAgentCamera.mHUDCurZoom;
1396		gGL.scalef(zoom,zoom,1.f);
1397		gGL.color4fv(LLColor4::white.mV);
1398		gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE);
1399		gGL.popMatrix();
1400		stop_glerror();
1401	}
1402	
1403
1404	if (gSavedSettings.getBOOL("RenderUIBuffer"))
1405	{
1406		if (LLUI::sDirty)
1407		{
1408			LLUI::sDirty = FALSE;
1409			LLRect t_rect;
1410
1411			gPipeline.mUIScreen.bindTarget();
1412			gGL.setColorMask(true, true);
1413			{
1414				static const S32 pad = 8;
1415
1416				LLUI::sDirtyRect.mLeft -= pad;
1417				LLUI::sDirtyRect.mRight += pad;
1418				LLUI::sDirtyRect.mBottom -= pad;
1419				LLUI::sDirtyRect.mTop += pad;
1420
1421				LLGLEnable scissor(GL_SCISSOR_TEST);
1422				static LLRect last_rect = LLUI::sDirtyRect;
1423
1424				//union with last rect to avoid mouse poop
1425				last_rect.unionWith(LLUI::sDirtyRect);
1426								
1427				t_rect = LLUI::sDirtyRect;
1428				LLUI::sDirtyRect = last_rect;
1429				last_rect = t_rect;
1430			
1431				last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::sGLScaleFactor.mV[0]);
1432				last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::sGLScaleFactor.mV[0]);
1433				last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::sGLScaleFactor.mV[1]);
1434				last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::sGLScaleFactor.mV[1]);
1435
1436				LLRect clip_rect(last_rect);
1437				
1438				glClear(GL_COLOR_BUFFER_BIT);
1439
1440				gViewerWindow->draw();
1441			}
1442
1443			gPipeline.mUIScreen.flush();
1444			gGL.setColorMask(true, false);
1445
1446			LLUI::sDirtyRect = t_rect;
1447		}
1448
1449		LLGLDisable cull(GL_CULL_FACE);
1450		LLGLDisable blend(GL_BLEND);
1451		S32 width = gViewerWindow->getWindowWidthScaled();
1452		S32 height = gViewerWindow->getWindowHeightScaled();
1453		gGL.getTexUnit(0)->bind(&gPipeline.mUIScreen);
1454		gGL.begin(LLRender::TRIANGLE_STRIP);
1455		gGL.color4f(1,1,1,1);
1456		gGL.texCoord2f(0, 0);			gGL.vertex2i(0, 0);
1457		gGL.texCoord2f(width, 0);		gGL.vertex2i(width, 0);
1458		gGL.texCoord2f(0, height);		gGL.vertex2i(0, height);
1459		gGL.texCoord2f(width, height);	gGL.vertex2i(width, height);
1460		gGL.end();
1461	}
1462	else
1463	{
1464		gViewerWindow->draw();
1465	}
1466
1467
1468
1469	// reset current origin for font rendering, in case of tiling render
1470	LLFontGL::sCurOrigin.set(0, 0);
1471}
1472
1473void render_disconnected_background()
1474{
1475	if (LLGLSLShader::sNoFixedFunction)
1476	{
1477		gUIProgram.bind();
1478	}
1479
1480	gGL.color4f(1,1,1,1);
1481	if (!gDisconnectedImagep && gDisconnected)
1482	{
1483		llinfos << "Loading last bitmap..." << llendl;
1484
1485		std::string temp_str;
1486		temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_LAST_FILENAME;
1487
1488		LLPointer<LLImageBMP> image_bmp = new LLImageBMP;
1489		if( !image_bmp->load(temp_str) )
1490		{
1491			//llinfos << "Bitmap load failed" << llendl;
1492			return;
1493		}
1494		
1495		LLPointer<LLImageRaw> raw = new LLImageRaw;
1496		if (!image_bmp->decode(raw, 0.0f))
1497		{
1498			llinfos << "Bitmap decode failed" << llendl;
1499			gDisconnectedImagep = NULL;
1500			return;
1501		}
1502
1503		U8 *rawp = raw->getData();
1504		S32 npixels = (S32)image_bmp->getWidth()*(S32)image_bmp->getHeight();
1505		for (S32 i = 0; i < npixels; i++)
1506		{
1507			S32 sum = 0;
1508			sum = *rawp + *(rawp+1) + *(rawp+2);
1509			sum /= 3;
1510			*rawp = ((S32)sum*6 + *rawp)/7;
1511			rawp++;
1512			*rawp = ((S32)sum*6 + *rawp)/7;
1513			rawp++;
1514			*rawp = ((S32)sum*6 + *rawp)/7;
1515			rawp++;
1516		}
1517
1518		
1519		raw->expandToPowerOfTwo();
1520		gDisconnectedImagep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE );
1521		gStartTexture = gDisconnectedImagep;
1522		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
1523	}
1524
1525	// Make sure the progress view always fills the entire window.
1526	S32 width = gViewerWindow->getWindowWidthScaled();
1527	S32 height = gViewerWindow->getWindowHeightScaled();
1528
1529	if (gDisconnectedImagep)
1530	{
1531		LLGLSUIDefault gls_ui;
1532		gViewerWindow->setup2DRender();
1533		gGL.pushMatrix();
1534		{
1535			// scale ui to reflect UIScaleFactor
1536			// this can't be done in setup2DRender because it requires a
1537			// pushMatrix/popMatrix pair
1538			const LLVector2& display_scale = gViewerWindow->getDisplayScale();
1539			gGL.scalef(display_scale.mV[VX], display_scale.mV[VY], 1.f);
1540
1541			gGL.getTexUnit(0)->bind(gDisconnectedImagep);
1542			gGL.color4f(1.f, 1.f, 1.f, 1.f);
1543			gl_rect_2d_simple_tex(width, height);
1544			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
1545		}
1546		gGL.popMatrix();
1547	}
1548	gGL.flush();
1549
1550	if (LLGLSLShader::sNoFixedFunction)
1551	{
1552		gUIProgram.unbind();
1553	}
1554
1555}
1556
1557void display_cleanup()
1558{
1559	gDisconnectedImagep = NULL;
1560}