diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llviewerdisplay.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llviewerdisplay.cpp')
-rw-r--r-- | linden/indra/newview/llviewerdisplay.cpp | 851 |
1 files changed, 851 insertions, 0 deletions
diff --git a/linden/indra/newview/llviewerdisplay.cpp b/linden/indra/newview/llviewerdisplay.cpp new file mode 100644 index 0000000..f09e34c --- /dev/null +++ b/linden/indra/newview/llviewerdisplay.cpp | |||
@@ -0,0 +1,851 @@ | |||
1 | /** | ||
2 | * @file llviewerdisplay.cpp | ||
3 | * @brief LLViewerDisplay class implementation | ||
4 | * | ||
5 | * Copyright (c) 2004-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "llviewerprecompiledheaders.h" | ||
29 | |||
30 | #include "llagent.h" | ||
31 | #include "llviewercontrol.h" | ||
32 | #include "llcoord.h" | ||
33 | #include "llcriticaldamp.h" | ||
34 | #include "lldir.h" | ||
35 | #include "lldynamictexture.h" | ||
36 | #include "lldrawpoolalpha.h" | ||
37 | #include "llframestats.h" | ||
38 | #include "llgl.h" | ||
39 | #include "llglheaders.h" | ||
40 | #include "llhudmanager.h" | ||
41 | #include "llimagebmp.h" | ||
42 | #include "llimagegl.h" | ||
43 | #include "llselectmgr.h" | ||
44 | #include "llsky.h" | ||
45 | #include "llstartup.h" | ||
46 | #include "lltoolfocus.h" | ||
47 | #include "lltoolmgr.h" | ||
48 | #include "lltooldraganddrop.h" | ||
49 | #include "lltoolpie.h" | ||
50 | #include "lltracker.h" | ||
51 | #include "llui.h" | ||
52 | #include "llviewercamera.h" | ||
53 | #include "llviewerobjectlist.h" | ||
54 | #include "llviewerparcelmgr.h" | ||
55 | #include "llviewerwindow.h" | ||
56 | #include "llvoavatar.h" | ||
57 | #include "llvograss.h" | ||
58 | #include "llworld.h" | ||
59 | #include "pipeline.h" | ||
60 | #include "viewer.h" | ||
61 | #include "llstartup.h" | ||
62 | #include "llfasttimer.h" | ||
63 | #include "llfloatertools.h" | ||
64 | #include "llviewerimagelist.h" | ||
65 | #include "llfocusmgr.h" | ||
66 | |||
67 | extern U32 gFrameCount; | ||
68 | extern LLPointer<LLImageGL> gStartImageGL; | ||
69 | extern LLPointer<LLImageGL> gDisconnectedImagep; | ||
70 | extern BOOL gLogoutRequestSent; | ||
71 | extern LLTimer gLogoutTimer; | ||
72 | extern BOOL gHaveSavedSnapshot; | ||
73 | extern BOOL gDisplaySwapBuffers; | ||
74 | |||
75 | // used to toggle renderer back on after teleport | ||
76 | const F32 TELEPORT_RENDER_DELAY = 20.f; // Max time a teleport is allowed to take before we raise the curtain | ||
77 | const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived. | ||
78 | BOOL gTeleportDisplay = FALSE; | ||
79 | LLFrameTimer gTeleportDisplayTimer; | ||
80 | LLFrameTimer gTeleportArrivalTimer; | ||
81 | const F32 RESTORE_GL_TIME = 5.f; // Wait this long while reloading textures before we raise the curtain | ||
82 | |||
83 | BOOL gForceRenderLandFence = FALSE; | ||
84 | BOOL gDisplaySwapBuffers = FALSE; | ||
85 | |||
86 | // Rendering stuff | ||
87 | void pre_show_depth_buffer(); | ||
88 | void post_show_depth_buffer(); | ||
89 | void render_ui_and_swap(); | ||
90 | void render_ui_3d(); | ||
91 | void render_ui_2d(); | ||
92 | void render_disconnected_background(); | ||
93 | |||
94 | void process_keystrokes_async(); // in viewer.cpp | ||
95 | |||
96 | void display_startup() | ||
97 | { | ||
98 | if ( !gViewerWindow->getActive() | ||
99 | || !gViewerWindow->mWindow->getVisible() | ||
100 | || gViewerWindow->mWindow->getMinimized() | ||
101 | || gNoRender ) | ||
102 | { | ||
103 | return; | ||
104 | } | ||
105 | |||
106 | LLDynamicTexture::updateAllInstances(); | ||
107 | |||
108 | glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | ||
109 | LLGLSDefault gls_default; | ||
110 | LLGLSUIDefault gls_ui; | ||
111 | gPipeline.disableLights(); | ||
112 | |||
113 | gViewerWindow->setup2DRender(); | ||
114 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | ||
115 | |||
116 | gViewerWindow->draw(); | ||
117 | gViewerWindow->mWindow->swapBuffers(); | ||
118 | } | ||
119 | |||
120 | |||
121 | void display_update_camera() | ||
122 | { | ||
123 | // TODO: cut draw distance down if customizing avatar? | ||
124 | // TODO: cut draw distance on per-parcel basis? | ||
125 | |||
126 | // Cut draw distance in half when customizing avatar, | ||
127 | // but on the viewer only. | ||
128 | F32 final_far = gAgent.mDrawDistance; | ||
129 | if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgent.getCameraMode()) | ||
130 | { | ||
131 | final_far *= 0.5f; | ||
132 | } | ||
133 | gCamera->setFar(final_far); | ||
134 | gViewerWindow->setup3DRender(); | ||
135 | |||
136 | // Update land visibility too | ||
137 | if (gWorldp) | ||
138 | { | ||
139 | gWorldp->setLandFarClip(final_far); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | |||
144 | // Paint the display! | ||
145 | void display(BOOL rebuild, F32 zoom_factor, int subfield) | ||
146 | { | ||
147 | LLFastTimer t(LLFastTimer::FTM_RENDER); | ||
148 | |||
149 | LLGLSDefault gls_default; | ||
150 | LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL); | ||
151 | |||
152 | // No clue where this is getting unset, but safe enough to reset it here. | ||
153 | for (S32 j = 7; j >=0; j--) | ||
154 | { | ||
155 | glActiveTextureARB(GL_TEXTURE0_ARB+j); | ||
156 | glClientActiveTextureARB(GL_TEXTURE0_ARB+j); | ||
157 | j == 0 ? glEnable(GL_TEXTURE_2D) : glDisable(GL_TEXTURE_2D); | ||
158 | } | ||
159 | |||
160 | #ifndef LL_RELEASE_FOR_DOWNLOAD | ||
161 | LLGLState::checkStates(); | ||
162 | LLGLState::checkTextureChannels(); | ||
163 | #endif | ||
164 | |||
165 | gPipeline.disableLights(); | ||
166 | |||
167 | // Don't draw if the window is hidden or minimized. | ||
168 | // In fact, must explicitly check the minimized state before drawing. | ||
169 | // Attempting to draw into a minimized window causes a GL error. JC | ||
170 | if ( !gViewerWindow->getActive() | ||
171 | || !gViewerWindow->mWindow->getVisible() | ||
172 | || gViewerWindow->mWindow->getMinimized() ) | ||
173 | { | ||
174 | // Clean up memory the pools may have allocated | ||
175 | if (rebuild) | ||
176 | { | ||
177 | if (!gViewerWindow->renderingFastFrame()) | ||
178 | { | ||
179 | gFrameStats.start(LLFrameStats::REBUILD); | ||
180 | gPipeline.rebuildPools(); | ||
181 | } | ||
182 | } | ||
183 | return; | ||
184 | } | ||
185 | |||
186 | gViewerWindow->checkSettings(); | ||
187 | gViewerWindow->performPick(); | ||
188 | |||
189 | #ifndef LL_RELEASE_FOR_DOWNLOAD | ||
190 | LLGLState::checkStates(); | ||
191 | LLGLState::checkTextureChannels(); | ||
192 | #endif | ||
193 | |||
194 | ////////////////////////////////////////////////////////// | ||
195 | // | ||
196 | // Logic for forcing window updates if we're in drone mode. | ||
197 | // | ||
198 | |||
199 | if (gNoRender) | ||
200 | { | ||
201 | #if LL_WINDOWS | ||
202 | static F32 last_update_time = 0.f; | ||
203 | if ((gFrameTimeSeconds - last_update_time) > 1.f) | ||
204 | { | ||
205 | InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE); | ||
206 | last_update_time = gFrameTimeSeconds; | ||
207 | } | ||
208 | #elif LL_DARWIN | ||
209 | // MBW -- Do something clever here. | ||
210 | #endif | ||
211 | // Not actually rendering, don't bother. | ||
212 | return; | ||
213 | } | ||
214 | |||
215 | |||
216 | // | ||
217 | // Bail out if we're in the startup state and don't want to try to | ||
218 | // render the world. | ||
219 | // | ||
220 | if (gStartupState < STATE_STARTED) | ||
221 | { | ||
222 | display_startup(); | ||
223 | return; | ||
224 | } | ||
225 | |||
226 | //LLGLState::verify(FALSE); | ||
227 | |||
228 | ///////////////////////////////////////////////// | ||
229 | // | ||
230 | // Update GL Texture statistics (used for discard logic?) | ||
231 | // | ||
232 | |||
233 | gFrameStats.start(LLFrameStats::UPDATE_TEX_STATS); | ||
234 | stop_glerror(); | ||
235 | |||
236 | LLImageGL::updateStats(gFrameTimeSeconds); | ||
237 | |||
238 | LLVOAvatar::sRenderName = gSavedSettings.getS32("RenderName"); | ||
239 | gPipeline.mBackfaceCull = TRUE; | ||
240 | gFrameCount++; | ||
241 | |||
242 | ////////////////////////////////////////////////////////// | ||
243 | // | ||
244 | // Display start screen if we're teleporting, and skip render | ||
245 | // | ||
246 | |||
247 | if (gTeleportDisplay) | ||
248 | { | ||
249 | const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived. | ||
250 | |||
251 | S32 attach_count = 0; | ||
252 | if (gAgent.getAvatarObject()) | ||
253 | { | ||
254 | attach_count = gAgent.getAvatarObject()->getAttachmentCount(); | ||
255 | } | ||
256 | F32 teleport_save_time = TELEPORT_EXPIRY + TELEPORT_EXPIRY_PER_ATTACHMENT * attach_count; | ||
257 | F32 teleport_elapsed = gTeleportDisplayTimer.getElapsedTimeF32(); | ||
258 | F32 teleport_percent = teleport_elapsed * (100.f / teleport_save_time); | ||
259 | if( (gAgent.getTeleportState() != LLAgent::TELEPORT_START) && (teleport_percent > 100.f) ) | ||
260 | { | ||
261 | // Give up. Don't keep the UI locked forever. | ||
262 | gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); | ||
263 | gAgent.setTeleportMessage(""); | ||
264 | } | ||
265 | |||
266 | const LLString& message = gAgent.getTeleportMessage(); | ||
267 | switch( gAgent.getTeleportState() ) | ||
268 | { | ||
269 | case LLAgent::TELEPORT_START: | ||
270 | // Transition to REQUESTED. Viewer has sent some kind | ||
271 | // of TeleportRequest to the source simulator | ||
272 | gTeleportDisplayTimer.reset(); | ||
273 | gViewerWindow->setShowProgress(TRUE); | ||
274 | gViewerWindow->setProgressPercent(0); | ||
275 | gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); | ||
276 | gAgent.setTeleportMessage("Requesting Teleport..."); | ||
277 | break; | ||
278 | |||
279 | case LLAgent::TELEPORT_REQUESTED: | ||
280 | // Waiting for source simulator to respond | ||
281 | gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) ); | ||
282 | gViewerWindow->setProgressString(message); | ||
283 | break; | ||
284 | |||
285 | case LLAgent::TELEPORT_MOVING: | ||
286 | // Viewer has received destination location from source simulator | ||
287 | gViewerWindow->setProgressPercent( llmin(teleport_percent, 75.f) ); | ||
288 | gViewerWindow->setProgressString(message); | ||
289 | break; | ||
290 | |||
291 | case LLAgent::TELEPORT_START_ARRIVAL: | ||
292 | // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator | ||
293 | gTeleportArrivalTimer.reset(); | ||
294 | gViewerWindow->setProgressCancelButtonVisible(FALSE, "Cancel"); | ||
295 | gViewerWindow->setProgressPercent(75.f); | ||
296 | gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING ); | ||
297 | gAgent.setTeleportMessage("Arriving..."); | ||
298 | gImageList.mForceResetTextureStats = TRUE; | ||
299 | break; | ||
300 | |||
301 | case LLAgent::TELEPORT_ARRIVING: | ||
302 | // Make the user wait while content "pre-caches" | ||
303 | { | ||
304 | F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY); | ||
305 | if( arrival_fraction > 1.f ) | ||
306 | { | ||
307 | arrival_fraction = 1.f; | ||
308 | gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); | ||
309 | } | ||
310 | gViewerWindow->setProgressCancelButtonVisible(FALSE, "Cancel"); | ||
311 | gViewerWindow->setProgressPercent( arrival_fraction * 25.f + 75.f); | ||
312 | gViewerWindow->setProgressString(message); | ||
313 | } | ||
314 | break; | ||
315 | |||
316 | case LLAgent::TELEPORT_CANCELLING: | ||
317 | gViewerWindow->setProgressCancelButtonVisible(FALSE, "Cancel"); | ||
318 | gViewerWindow->setProgressPercent( 100.f ); | ||
319 | gViewerWindow->setProgressString("Canceling..."); | ||
320 | break; | ||
321 | |||
322 | case LLAgent::TELEPORT_NONE: | ||
323 | // No teleport in progress | ||
324 | gViewerWindow->setShowProgress(FALSE); | ||
325 | gTeleportDisplay = FALSE; | ||
326 | break; | ||
327 | } | ||
328 | } | ||
329 | else if(gLogoutRequestSent) | ||
330 | { | ||
331 | F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f / gLogoutMaxTime; | ||
332 | if (percent_done > 100.f) | ||
333 | { | ||
334 | percent_done = 100.f; | ||
335 | } | ||
336 | |||
337 | if( gQuit ) | ||
338 | { | ||
339 | percent_done = 100.f; | ||
340 | } | ||
341 | |||
342 | gViewerWindow->setProgressPercent( percent_done ); | ||
343 | } | ||
344 | else | ||
345 | if (gRestoreGL) | ||
346 | { | ||
347 | F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME; | ||
348 | if( percent_done > 100.f ) | ||
349 | { | ||
350 | gViewerWindow->setShowProgress(FALSE); | ||
351 | gRestoreGL = FALSE; | ||
352 | } | ||
353 | else | ||
354 | { | ||
355 | |||
356 | if( gQuit ) | ||
357 | { | ||
358 | percent_done = 100.f; | ||
359 | } | ||
360 | |||
361 | gViewerWindow->setProgressPercent( percent_done ); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | ////////////////////////// | ||
366 | // | ||
367 | // Prepare for the next frame | ||
368 | // | ||
369 | |||
370 | // Hmm... Should this be moved elsewhere? - djs 09/09/02 | ||
371 | // do render-to-texture stuff here | ||
372 | if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES)) | ||
373 | { | ||
374 | // LLFastTimer t(LLFastTimer::FTM_UPDATE_TEXTURES); | ||
375 | if (LLDynamicTexture::updateAllInstances()) | ||
376 | { | ||
377 | glClear(GL_COLOR_BUFFER_BIT); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | if (rebuild) | ||
382 | { | ||
383 | if (gViewerWindow->renderingFastFrame()) | ||
384 | { | ||
385 | gFrameStats.start(LLFrameStats::STATE_SORT); | ||
386 | gFrameStats.start(LLFrameStats::REBUILD); | ||
387 | } | ||
388 | } | ||
389 | |||
390 | ///////////////////////////// | ||
391 | // | ||
392 | // Update the camera | ||
393 | // | ||
394 | // | ||
395 | |||
396 | gCamera->setZoomParameters(zoom_factor, subfield); | ||
397 | |||
398 | ////////////////////////// | ||
399 | // | ||
400 | // clear the next buffer | ||
401 | // (must follow dynamic texture writing since that uses the frame buffer) | ||
402 | // | ||
403 | |||
404 | if (gDisconnected) | ||
405 | { | ||
406 | glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | ||
407 | render_disconnected_background(); | ||
408 | } | ||
409 | else if (!gViewerWindow->isPickPending()) | ||
410 | { | ||
411 | glClear( GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); | ||
412 | } | ||
413 | gViewerWindow->setupViewport(); | ||
414 | |||
415 | |||
416 | ////////////////////////// | ||
417 | // | ||
418 | // Set rendering options | ||
419 | // | ||
420 | // | ||
421 | stop_glerror(); | ||
422 | if (gSavedSettings.getBOOL("ShowDepthBuffer")) | ||
423 | { | ||
424 | pre_show_depth_buffer(); | ||
425 | } | ||
426 | |||
427 | if(gUseWireframe)//gSavedSettings.getBOOL("UseWireframe")) | ||
428 | { | ||
429 | glClearColor(0.5f, 0.5f, 0.5f, 0.f); | ||
430 | glClear(GL_COLOR_BUFFER_BIT); | ||
431 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | ||
432 | } | ||
433 | stop_glerror(); | ||
434 | |||
435 | /////////////////////////////////////// | ||
436 | // | ||
437 | // Slam lighting parameters back to our defaults. | ||
438 | // Note that these are not the same as GL defaults... | ||
439 | |||
440 | stop_glerror(); | ||
441 | F32 one[4] = {1.f, 1.f, 1.f, 1.f}; | ||
442 | glLightModelfv (GL_LIGHT_MODEL_AMBIENT,one); | ||
443 | stop_glerror(); | ||
444 | |||
445 | //LLGLState::verify(); | ||
446 | |||
447 | ///////////////////////////////////// | ||
448 | // | ||
449 | // Render | ||
450 | // | ||
451 | // Actually push all of our triangles to the screen. | ||
452 | // | ||
453 | if (!gDisconnected) | ||
454 | { | ||
455 | LLFastTimer t(LLFastTimer::FTM_WORLD_UPDATE); | ||
456 | stop_glerror(); | ||
457 | display_update_camera(); | ||
458 | stop_glerror(); | ||
459 | |||
460 | // *TODO: merge these two methods | ||
461 | gHUDManager->updateEffects(); | ||
462 | LLHUDObject::updateAll(); | ||
463 | stop_glerror(); | ||
464 | |||
465 | gFrameStats.start(LLFrameStats::UPDATE_GEOM); | ||
466 | const F32 max_geom_update_time = 0.005f; // 5 ms update time | ||
467 | gPipeline.updateGeom(max_geom_update_time); | ||
468 | stop_glerror(); | ||
469 | |||
470 | gFrameStats.start(LLFrameStats::UPDATE_CULL); | ||
471 | gPipeline.updateCull(); | ||
472 | stop_glerror(); | ||
473 | |||
474 | if (rebuild && !gViewerWindow->renderingFastFrame()) | ||
475 | { | ||
476 | LLFastTimer t(LLFastTimer::FTM_REBUILD); | ||
477 | |||
478 | /////////////////////////////////// | ||
479 | // | ||
480 | // StateSort | ||
481 | // | ||
482 | // Responsible for taking visible objects, and adding them to the appropriate draw orders. | ||
483 | // In the case of alpha objects, z-sorts them first. | ||
484 | // Also creates special lists for outlines and selected face rendering. | ||
485 | // | ||
486 | gFrameStats.start(LLFrameStats::STATE_SORT); | ||
487 | gPipeline.stateSort(); | ||
488 | stop_glerror(); | ||
489 | |||
490 | ////////////////////////////////////// | ||
491 | // | ||
492 | // rebuildPools | ||
493 | // | ||
494 | // | ||
495 | gFrameStats.start(LLFrameStats::REBUILD); | ||
496 | gPipeline.rebuildPools(); | ||
497 | stop_glerror(); | ||
498 | } | ||
499 | } | ||
500 | |||
501 | //// render frontmost floater opaque for occlusion culling purposes | ||
502 | //LLFloater* frontmost_floaterp = gFloaterView->getFrontmost(); | ||
503 | //// assumes frontmost floater with focus is opaque | ||
504 | //if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp)) | ||
505 | //{ | ||
506 | // glMatrixMode(GL_MODELVIEW); | ||
507 | // glPushMatrix(); | ||
508 | // { | ||
509 | // LLGLSNoTexture gls_no_texture; | ||
510 | |||
511 | // glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); | ||
512 | // glLoadIdentity(); | ||
513 | |||
514 | // LLRect floater_rect = frontmost_floaterp->getScreenRect(); | ||
515 | // // deflate by one pixel so rounding errors don't occlude outside of floater extents | ||
516 | // floater_rect.stretch(-1); | ||
517 | // LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidth(), | ||
518 | // (F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeight(), | ||
519 | // (F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidth(), | ||
520 | // (F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeight()); | ||
521 | // floater_3d_rect.translate(-0.5f, -0.5f); | ||
522 | // glTranslatef(0.f, 0.f, -gCamera->getNear()); | ||
523 | // glScalef(gCamera->getNear() * gCamera->getAspect() / sinf(gCamera->getView()), gCamera->getNear() / sinf(gCamera->getView()), 1.f); | ||
524 | // glColor4fv(LLColor4::white.mV); | ||
525 | // glBegin(GL_QUADS); | ||
526 | // { | ||
527 | // glVertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f); | ||
528 | // glVertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f); | ||
529 | // glVertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f); | ||
530 | // glVertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f); | ||
531 | // } | ||
532 | // glEnd(); | ||
533 | // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | ||
534 | // } | ||
535 | // glPopMatrix(); | ||
536 | //} | ||
537 | |||
538 | if (gViewerWindow->renderingFastFrame()) | ||
539 | { | ||
540 | gFrameStats.start(LLFrameStats::RENDER_SYNC); | ||
541 | gFrameStats.start(LLFrameStats::RENDER_GEOM); | ||
542 | } | ||
543 | else if (!(gLogoutRequestSent && gHaveSavedSnapshot) | ||
544 | && !gRestoreGL | ||
545 | && !gDisconnected) | ||
546 | { | ||
547 | gPipeline.renderGeom(); | ||
548 | stop_glerror(); | ||
549 | } | ||
550 | |||
551 | gFrameStats.start(LLFrameStats::RENDER_UI); | ||
552 | |||
553 | if (gHandleKeysAsync) | ||
554 | { | ||
555 | process_keystrokes_async(); | ||
556 | stop_glerror(); | ||
557 | } | ||
558 | |||
559 | |||
560 | #ifndef LL_RELEASE_FOR_DOWNLOAD | ||
561 | LLGLState::checkStates(); | ||
562 | #endif | ||
563 | render_ui_and_swap(); | ||
564 | #ifndef LL_RELEASE_FOR_DOWNLOAD | ||
565 | LLGLState::checkStates(); | ||
566 | #endif | ||
567 | |||
568 | gFrameStats.start(LLFrameStats::MISC_END); | ||
569 | stop_glerror(); | ||
570 | |||
571 | } | ||
572 | |||
573 | |||
574 | void render_ui_and_swap() | ||
575 | { | ||
576 | #ifndef LL_RELEASE_FOR_DOWNLOAD | ||
577 | LLGLState::checkStates(); | ||
578 | #endif | ||
579 | |||
580 | LLGLSDefault gls_default; | ||
581 | { | ||
582 | LLGLSUIDefault gls_ui; | ||
583 | gPipeline.disableLights(); | ||
584 | |||
585 | if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) | ||
586 | { | ||
587 | LLFastTimer t(LLFastTimer::FTM_RENDER_UI); | ||
588 | if (!gViewerWindow->renderingFastFrame() && !gDisconnected) | ||
589 | { | ||
590 | render_ui_3d(); | ||
591 | #ifndef LL_RELEASE_FOR_DOWNLOAD | ||
592 | LLGLState::checkStates(); | ||
593 | #endif | ||
594 | } | ||
595 | |||
596 | render_ui_2d(); | ||
597 | #ifndef LL_RELEASE_FOR_DOWNLOAD | ||
598 | LLGLState::checkStates(); | ||
599 | #endif | ||
600 | } | ||
601 | |||
602 | // now do the swap buffer | ||
603 | if (gDisplaySwapBuffers) | ||
604 | { | ||
605 | LLFastTimer t(LLFastTimer::FTM_SWAP); | ||
606 | gViewerWindow->mWindow->swapBuffers(); | ||
607 | } | ||
608 | } | ||
609 | |||
610 | gViewerWindow->finishFirstFastFrame(); | ||
611 | } | ||
612 | |||
613 | void render_ui_3d() | ||
614 | { | ||
615 | LLGLSPipeline gls_pipeline; | ||
616 | |||
617 | ////////////////////////////////////// | ||
618 | // | ||
619 | // Render 3D UI elements | ||
620 | // NOTE: zbuffer is cleared before we get here by LLDrawPoolHUD, | ||
621 | // so 3d elements requiring Z buffer are moved to LLDrawPoolHUD | ||
622 | // | ||
623 | |||
624 | // Render selections | ||
625 | |||
626 | glDisableClientState(GL_VERTEX_ARRAY); | ||
627 | glDisableClientState(GL_COLOR_ARRAY); | ||
628 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
629 | glDisableClientState(GL_NORMAL_ARRAY); | ||
630 | |||
631 | ///////////////////////////////////////////////////////////// | ||
632 | // | ||
633 | // Render 2.5D elements (2D elements in the world) | ||
634 | // Stuff without z writes | ||
635 | // | ||
636 | |||
637 | // Debugging stuff goes before the UI. | ||
638 | |||
639 | if (gSavedSettings.getBOOL("ShowDepthBuffer")) | ||
640 | { | ||
641 | post_show_depth_buffer(); | ||
642 | } | ||
643 | |||
644 | // Coordinate axes | ||
645 | if (gSavedSettings.getBOOL("ShowAxes")) | ||
646 | { | ||
647 | draw_axes(); | ||
648 | } | ||
649 | |||
650 | stop_glerror(); | ||
651 | |||
652 | gViewerWindow->renderSelections(FALSE, FALSE, TRUE); // Non HUD call in render_hud_elements | ||
653 | stop_glerror(); | ||
654 | } | ||
655 | |||
656 | void render_ui_2d() | ||
657 | { | ||
658 | LLGLSUIDefault gls_ui; | ||
659 | |||
660 | ///////////////////////////////////////////////////////////// | ||
661 | // | ||
662 | // Render 2D UI elements that overlay the world (no z compare) | ||
663 | |||
664 | // Disable wireframe mode below here, as this is HUD/menus | ||
665 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||
666 | |||
667 | // Menu overlays, HUD, etc | ||
668 | gViewerWindow->setup2DRender(); | ||
669 | |||
670 | F32 zoom_factor = gCamera->getZoomFactor(); | ||
671 | S16 sub_region = gCamera->getZoomSubRegion(); | ||
672 | |||
673 | if (zoom_factor > 1.f) | ||
674 | { | ||
675 | //decompose subregion number to x and y values | ||
676 | int pos_y = sub_region / llceil(zoom_factor); | ||
677 | int pos_x = sub_region - (pos_y*llceil(zoom_factor)); | ||
678 | // offset for this tile | ||
679 | LLFontGL::sCurOrigin.mX -= llround((F32)gViewerWindow->getWindowWidth() * (F32)pos_x / zoom_factor); | ||
680 | LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeight() * (F32)pos_y / zoom_factor); | ||
681 | } | ||
682 | |||
683 | |||
684 | stop_glerror(); | ||
685 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | ||
686 | |||
687 | // render outline for HUD | ||
688 | if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->mHUDCurZoom < 0.98f) | ||
689 | { | ||
690 | glPushMatrix(); | ||
691 | S32 half_width = (gViewerWindow->getWindowWidth() / 2); | ||
692 | S32 half_height = (gViewerWindow->getWindowHeight() / 2); | ||
693 | glTranslatef((F32)half_width, (F32)half_height, 0.f); | ||
694 | glScalef(gAgent.getAvatarObject()->mHUDCurZoom, gAgent.getAvatarObject()->mHUDCurZoom, gAgent.getAvatarObject()->mHUDCurZoom); | ||
695 | glColor4fv(LLColor4::white.mV); | ||
696 | gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE); | ||
697 | glPopMatrix(); | ||
698 | stop_glerror(); | ||
699 | } | ||
700 | gViewerWindow->draw(); | ||
701 | if (gDebugSelect) | ||
702 | { | ||
703 | gViewerWindow->drawPickBuffer(); | ||
704 | } | ||
705 | |||
706 | // reset current origin for font rendering, in case of tiling render | ||
707 | LLFontGL::sCurOrigin.set(0, 0); | ||
708 | } | ||
709 | |||
710 | void renderCoordinateAxes() | ||
711 | { | ||
712 | LLGLSNoTexture gls_no_texture; | ||
713 | glBegin(GL_LINES); | ||
714 | glColor3f(1.0f, 0.0f, 0.0f); // i direction = X-Axis = red | ||
715 | glVertex3f(0.0f, 0.0f, 0.0f); | ||
716 | glVertex3f(2.0f, 0.0f, 0.0f); | ||
717 | glVertex3f(3.0f, 0.0f, 0.0f); | ||
718 | glVertex3f(5.0f, 0.0f, 0.0f); | ||
719 | glVertex3f(6.0f, 0.0f, 0.0f); | ||
720 | glVertex3f(8.0f, 0.0f, 0.0f); | ||
721 | // Make an X | ||
722 | glVertex3f(11.0f, 1.0f, 1.0f); | ||
723 | glVertex3f(11.0f, -1.0f, -1.0f); | ||
724 | glVertex3f(11.0f, 1.0f, -1.0f); | ||
725 | glVertex3f(11.0f, -1.0f, 1.0f); | ||
726 | |||
727 | glColor3f(0.0f, 1.0f, 0.0f); // j direction = Y-Axis = green | ||
728 | glVertex3f(0.0f, 0.0f, 0.0f); | ||
729 | glVertex3f(0.0f, 2.0f, 0.0f); | ||
730 | glVertex3f(0.0f, 3.0f, 0.0f); | ||
731 | glVertex3f(0.0f, 5.0f, 0.0f); | ||
732 | glVertex3f(0.0f, 6.0f, 0.0f); | ||
733 | glVertex3f(0.0f, 8.0f, 0.0f); | ||
734 | // Make a Y | ||
735 | glVertex3f(1.0f, 11.0f, 1.0f); | ||
736 | glVertex3f(0.0f, 11.0f, 0.0f); | ||
737 | glVertex3f(-1.0f, 11.0f, 1.0f); | ||
738 | glVertex3f(0.0f, 11.0f, 0.0f); | ||
739 | glVertex3f(0.0f, 11.0f, 0.0f); | ||
740 | glVertex3f(0.0f, 11.0f, -1.0f); | ||
741 | |||
742 | glColor3f(0.0f, 0.0f, 1.0f); // Z-Axis = blue | ||
743 | glVertex3f(0.0f, 0.0f, 0.0f); | ||
744 | glVertex3f(0.0f, 0.0f, 2.0f); | ||
745 | glVertex3f(0.0f, 0.0f, 3.0f); | ||
746 | glVertex3f(0.0f, 0.0f, 5.0f); | ||
747 | glVertex3f(0.0f, 0.0f, 6.0f); | ||
748 | glVertex3f(0.0f, 0.0f, 8.0f); | ||
749 | // Make a Z | ||
750 | glVertex3f(-1.0f, 1.0f, 11.0f); | ||
751 | glVertex3f(1.0f, 1.0f, 11.0f); | ||
752 | glVertex3f(1.0f, 1.0f, 11.0f); | ||
753 | glVertex3f(-1.0f, -1.0f, 11.0f); | ||
754 | glVertex3f(-1.0f, -1.0f, 11.0f); | ||
755 | glVertex3f(1.0f, -1.0f, 11.0f); | ||
756 | glEnd(); | ||
757 | } | ||
758 | |||
759 | void draw_axes() | ||
760 | { | ||
761 | LLGLSUIDefault gls_ui; | ||
762 | LLGLSNoTexture gls_no_texture; | ||
763 | // A vertical white line at origin | ||
764 | LLVector3 v = gAgent.getPositionAgent(); | ||
765 | glBegin(GL_LINES); | ||
766 | glColor3f(1.0f, 1.0f, 1.0f); | ||
767 | glVertex3f(0.0f, 0.0f, 0.0f); | ||
768 | glVertex3f(0.0f, 0.0f, 40.0f); | ||
769 | glEnd(); | ||
770 | // Some coordinate axes | ||
771 | glPushMatrix(); | ||
772 | glTranslatef( v.mV[VX], v.mV[VY], v.mV[VZ] ); | ||
773 | renderCoordinateAxes(); | ||
774 | glPopMatrix(); | ||
775 | } | ||
776 | |||
777 | |||
778 | void render_disconnected_background() | ||
779 | { | ||
780 | if (!gDisconnectedImagep && gDisconnected) | ||
781 | { | ||
782 | llinfos << "Loading last bitmap..." << llendl; | ||
783 | |||
784 | char temp_str[MAX_PATH]; | ||
785 | strcpy(temp_str, gDirUtilp->getLindenUserDir().c_str()); | ||
786 | strcat(temp_str, gDirUtilp->getDirDelimiter().c_str()); | ||
787 | |||
788 | strcat(temp_str, SCREEN_LAST_FILENAME); | ||
789 | |||
790 | LLPointer<LLImageBMP> image_bmp = new LLImageBMP; | ||
791 | if( !image_bmp->load(temp_str) ) | ||
792 | { | ||
793 | //llinfos << "Bitmap load failed" << llendl; | ||
794 | return; | ||
795 | } | ||
796 | |||
797 | gDisconnectedImagep = new LLImageGL( FALSE ); | ||
798 | LLPointer<LLImageRaw> raw = new LLImageRaw; | ||
799 | if (!image_bmp->decode(raw)) | ||
800 | { | ||
801 | llinfos << "Bitmap decode failed" << llendl; | ||
802 | gDisconnectedImagep = NULL; | ||
803 | return; | ||
804 | } | ||
805 | |||
806 | U8 *rawp = raw->getData(); | ||
807 | S32 npixels = (S32)image_bmp->getWidth()*(S32)image_bmp->getHeight(); | ||
808 | for (S32 i = 0; i < npixels; i++) | ||
809 | { | ||
810 | S32 sum = 0; | ||
811 | sum = *rawp + *(rawp+1) + *(rawp+2); | ||
812 | sum /= 3; | ||
813 | *rawp = ((S32)sum*6 + *rawp)/7; | ||
814 | rawp++; | ||
815 | *rawp = ((S32)sum*6 + *rawp)/7; | ||
816 | rawp++; | ||
817 | *rawp = ((S32)sum*6 + *rawp)/7; | ||
818 | rawp++; | ||
819 | } | ||
820 | |||
821 | |||
822 | raw->expandToPowerOfTwo(); | ||
823 | gDisconnectedImagep->createGLTexture(0, raw); | ||
824 | gStartImageGL = gDisconnectedImagep; | ||
825 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
826 | } | ||
827 | |||
828 | // Make sure the progress view always fills the entire window. | ||
829 | S32 width = gViewerWindow->getWindowWidth(); | ||
830 | S32 height = gViewerWindow->getWindowHeight(); | ||
831 | |||
832 | if (gDisconnectedImagep) | ||
833 | { | ||
834 | LLGLSUIDefault gls_ui; | ||
835 | gViewerWindow->setup2DRender(); | ||
836 | glPushMatrix(); | ||
837 | { | ||
838 | // scale ui to reflect UIScaleFactor | ||
839 | // this can't be done in setup2DRender because it requires a | ||
840 | // pushMatrix/popMatrix pair | ||
841 | const LLVector2& display_scale = gViewerWindow->getDisplayScale(); | ||
842 | glScalef(display_scale.mV[VX], display_scale.mV[VY], 1.f); | ||
843 | |||
844 | LLViewerImage::bindTexture(gDisconnectedImagep); | ||
845 | glColor4f(1.f, 1.f, 1.f, 1.f); | ||
846 | gl_rect_2d_simple_tex(width, height); | ||
847 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
848 | } | ||
849 | glPopMatrix(); | ||
850 | } | ||
851 | } | ||