summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.hgtags2
-rw-r--r--doc/contributions.txt18
-rw-r--r--indra/llaudio/llaudiodecodemgr.cpp2
-rw-r--r--indra/llaudio/llaudioengine.h1
-rw-r--r--indra/llcharacter/llbvhloader.cpp2
-rw-r--r--indra/llcommon/linden_common.h23
-rw-r--r--indra/llcommon/llavatarname.cpp5
-rw-r--r--indra/llcommon/llevents.cpp4
-rw-r--r--indra/llcommon/llmd5.cpp2
-rw-r--r--indra/llcommon/llpreprocessor.h3
-rw-r--r--indra/llcommon/llsdserialize.cpp4494
-rw-r--r--indra/llcommon/llsdserialize_xml.cpp2
-rw-r--r--indra/llcommon/llsdutil.h2
-rw-r--r--indra/llcommon/llstat.cpp2
-rw-r--r--indra/llcommon/lltimer.cpp2
-rw-r--r--indra/llcrashlogger/llcrashlogger.cpp2
-rw-r--r--indra/llimage/llimagej2c.cpp8
-rw-r--r--indra/llinventory/llinventory.cpp4
-rw-r--r--indra/llmath/llcalcparser.h2
-rw-r--r--indra/llmath/llcoord.h108
-rw-r--r--indra/llmath/llvolume.cpp4
-rw-r--r--indra/llmath/m4math.cpp38
-rw-r--r--indra/llmessage/llcurl.cpp64
-rw-r--r--indra/llmessage/llhttpclient.cpp2
-rw-r--r--indra/llmessage/llmime.cpp4
-rw-r--r--indra/llmessage/llsdmessage.cpp2
-rw-r--r--indra/llmessage/llsdmessagebuilder.cpp2
-rw-r--r--indra/llmessage/llxfer.h1
-rw-r--r--indra/llmessage/message.cpp6
-rw-r--r--indra/llrender/llfontgl.cpp96
-rw-r--r--indra/llrender/llfontgl.h9
-rw-r--r--indra/llrender/llglslshader.cpp21
-rw-r--r--indra/llrender/llglslshader.h1
-rw-r--r--indra/llrender/llshadermgr.cpp5
-rw-r--r--indra/llrender/llvertexbuffer.cpp292
-rw-r--r--indra/llrender/llvertexbuffer.h58
-rw-r--r--indra/llui/llaccordionctrltab.cpp2
-rw-r--r--indra/llui/llbutton.cpp4
-rw-r--r--indra/llui/llcombobox.cpp2
-rw-r--r--indra/llui/lldraghandle.cpp2
-rw-r--r--indra/llui/llfloater.cpp122
-rw-r--r--indra/llui/llfloater.h34
-rw-r--r--indra/llui/lllayoutstack.cpp118
-rw-r--r--indra/llui/lllayoutstack.h7
-rw-r--r--indra/llui/lllineeditor.cpp2
-rw-r--r--indra/llui/llmenugl.cpp16
-rw-r--r--indra/llui/llnotifications.cpp3
-rw-r--r--indra/llui/llscrollcontainer.cpp18
-rw-r--r--indra/llui/llscrolllistcell.cpp6
-rw-r--r--indra/llui/llscrolllistitem.cpp2
-rw-r--r--indra/llui/llscrolllistitem.h2
-rw-r--r--indra/llui/lltextbase.cpp78
-rw-r--r--indra/llui/lltexteditor.cpp6
-rw-r--r--indra/llui/lltoolbar.cpp2
-rw-r--r--indra/llui/lltooltip.cpp10
-rw-r--r--indra/llui/llui.cpp73
-rw-r--r--indra/llui/lluistring.cpp12
-rw-r--r--indra/llui/llview.cpp80
-rw-r--r--indra/llui/llview.h4
-rw-r--r--indra/llvfs/lllfsthread.cpp2
-rw-r--r--indra/llvfs/llvfsthread.cpp2
-rw-r--r--indra/llwindow/lldragdropwin32.cpp10
-rw-r--r--indra/llwindow/llwindow.cpp39
-rw-r--r--indra/llwindow/llwindow.h2
-rw-r--r--indra/llwindow/llwindowcallbacks.cpp2
-rw-r--r--indra/llwindow/llwindowcallbacks.h2
-rw-r--r--indra/llwindow/llwindowwin32.cpp76
-rw-r--r--indra/llxml/llcontrol.h4
-rw-r--r--indra/llxml/llxmlnode.cpp31
-rw-r--r--indra/llxuixml/llinitparam.h13
-rw-r--r--indra/media_plugins/quicktime/media_plugin_quicktime.cpp6
-rw-r--r--indra/media_plugins/webkit/media_plugin_webkit.cpp24
-rw-r--r--indra/newview/CMakeLists.txt7
-rw-r--r--indra/newview/app_settings/commands.xml2
-rw-r--r--indra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl32
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/skyV.glsl30
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl30
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl30
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl34
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl32
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/skyV.glsl31
-rw-r--r--indra/newview/featuretable.txt1
-rw-r--r--indra/newview/featuretable_linux.txt1
-rw-r--r--indra/newview/featuretable_mac.txt1
-rw-r--r--indra/newview/featuretable_xp.txt1
-rwxr-xr-xindra/newview/llagent.cpp6
-rw-r--r--indra/newview/llagentwearables.cpp3
-rw-r--r--indra/newview/llappviewerwin32.cpp3
-rw-r--r--indra/newview/llcallfloater.cpp3
-rw-r--r--indra/newview/llexpandabletextbox.cpp2
-rw-r--r--indra/newview/llfasttimerview.cpp6
-rw-r--r--indra/newview/llfilepicker.cpp27
-rw-r--r--indra/newview/llfloateravatarpicker.cpp5
-rw-r--r--indra/newview/llfloaterbuildoptions.cpp49
-rw-r--r--indra/newview/llfloaterbuildoptions.h7
-rw-r--r--indra/newview/llfloaterbuy.cpp3
-rw-r--r--indra/newview/llfloaterbvhpreview.cpp (renamed from indra/newview/llfloateranimpreview.cpp)110
-rw-r--r--indra/newview/llfloaterbvhpreview.h (renamed from indra/newview/llfloateranimpreview.h)17
-rw-r--r--indra/newview/llfloatereditsky.cpp37
-rw-r--r--indra/newview/llfloatermediasettings.cpp6
-rw-r--r--indra/newview/llfloatermediasettings.h1
-rwxr-xr-xindra/newview/llfloatermodelpreview.cpp12
-rw-r--r--indra/newview/llfloaternamedesc.cpp19
-rw-r--r--indra/newview/llfloaternamedesc.h7
-rwxr-xr-xindra/newview/llfloaterpreference.cpp42
-rw-r--r--indra/newview/llfloaterpreference.h8
-rw-r--r--indra/newview/llfloaterregioninfo.h1
-rw-r--r--indra/newview/llfloaterreporter.h1
-rw-r--r--indra/newview/llfloaterscriptdebug.cpp6
-rw-r--r--indra/newview/llfloatersidepanelcontainer.cpp5
-rw-r--r--indra/newview/llfloatertools.cpp42
-rw-r--r--indra/newview/llfloatertools.h2
-rw-r--r--indra/newview/llfloatertranslationsettings.cpp2
-rw-r--r--indra/newview/llfolderview.cpp22
-rw-r--r--indra/newview/llfolderviewitem.cpp8
-rw-r--r--indra/newview/llfolderviewitem.h1
-rw-r--r--indra/newview/llgrouplist.cpp16
-rw-r--r--indra/newview/llgrouplist.h1
-rw-r--r--indra/newview/llhudrender.cpp2
-rw-r--r--indra/newview/llhudtext.cpp6
-rw-r--r--indra/newview/llimview.cpp16
-rw-r--r--indra/newview/llimview.h12
-rw-r--r--indra/newview/llinspecttoast.cpp2
-rw-r--r--indra/newview/llinventorybridge.cpp281
-rw-r--r--indra/newview/llinventorybridge.h6
-rw-r--r--indra/newview/llinventoryfilter.cpp124
-rw-r--r--indra/newview/llinventoryfilter.h9
-rw-r--r--indra/newview/llinventorymodelbackgroundfetch.cpp441
-rw-r--r--indra/newview/llinventorymodelbackgroundfetch.h20
-rw-r--r--indra/newview/llinventorypanel.cpp2
-rw-r--r--indra/newview/llinventorypanel.h2
-rw-r--r--indra/newview/llmemoryview.cpp2
-rwxr-xr-xindra/newview/llmeshrepository.cpp16
-rw-r--r--indra/newview/llmutelist.h1
-rw-r--r--indra/newview/llnearbychatbar.cpp6
-rw-r--r--indra/newview/llnearbychatbar.h2
-rw-r--r--indra/newview/llnetmap.cpp133
-rw-r--r--indra/newview/llnetmap.h2
-rw-r--r--indra/newview/llnotificationmanager.cpp28
-rw-r--r--indra/newview/llnotificationmanager.h5
-rw-r--r--indra/newview/llpanelface.cpp9
-rw-r--r--indra/newview/llpanelgrouproles.cpp5
-rw-r--r--indra/newview/llpanelimcontrolpanel.cpp2
-rw-r--r--indra/newview/llpanellogin.cpp16
-rw-r--r--indra/newview/llpanelmaininventory.cpp2
-rw-r--r--indra/newview/llpanelpeople.cpp7
-rw-r--r--indra/newview/llpanelprimmediacontrols.cpp2
-rw-r--r--indra/newview/llpanelprimmediacontrols.h2
-rw-r--r--indra/newview/llpanelvoiceeffect.cpp1
-rw-r--r--indra/newview/llparticipantlist.cpp12
-rw-r--r--indra/newview/llparticipantlist.h4
-rw-r--r--indra/newview/llplacesinventorybridge.cpp4
-rw-r--r--indra/newview/llpopupview.cpp2
-rw-r--r--indra/newview/llpreview.h1
-rw-r--r--indra/newview/llpreviewanim.cpp146
-rw-r--r--indra/newview/llpreviewanim.h20
-rw-r--r--indra/newview/llscreenchannel.cpp295
-rw-r--r--indra/newview/llscreenchannel.h30
-rw-r--r--indra/newview/llsechandler_basic.cpp12
-rw-r--r--indra/newview/llsidepanelinventory.cpp10
-rw-r--r--indra/newview/llspeakers.cpp14
-rw-r--r--indra/newview/llspeakers.h7
-rw-r--r--indra/newview/llstartup.cpp1
-rw-r--r--indra/newview/lltexturectrl.cpp9
-rw-r--r--indra/newview/lltextureview.cpp16
-rw-r--r--indra/newview/lltoast.cpp24
-rw-r--r--indra/newview/lltoast.h29
-rw-r--r--indra/newview/lltoastalertpanel.cpp25
-rw-r--r--indra/newview/lltoastalertpanel.h1
-rw-r--r--indra/newview/lltoastpanel.cpp2
-rw-r--r--indra/newview/lltooldraganddrop.cpp17
-rw-r--r--indra/newview/lltooldraganddrop.h9
-rw-r--r--indra/newview/lltoolmgr.cpp11
-rw-r--r--indra/newview/lltoolmgr.h2
-rwxr-xr-xindra/newview/lltranslate.cpp10
-rwxr-xr-xindra/newview/lltranslate.h1
-rw-r--r--indra/newview/lluploaddialog.cpp2
-rw-r--r--indra/newview/llviewercamera.h2
-rw-r--r--indra/newview/llviewerdisplay.cpp3079
-rw-r--r--indra/newview/llviewerfloaterreg.cpp5
-rw-r--r--indra/newview/llviewerinventory.cpp26
-rw-r--r--indra/newview/llviewerjointmesh.cpp1
-rw-r--r--indra/newview/llviewermedia.cpp45
-rw-r--r--indra/newview/llviewermedia.h3
-rw-r--r--indra/newview/llviewermenu.cpp6
-rw-r--r--indra/newview/llviewermenufile.cpp34
-rwxr-xr-xindra/newview/llviewermessage.cpp44
-rw-r--r--indra/newview/llviewermessage.h1
-rw-r--r--indra/newview/llviewershadermgr.cpp31
-rw-r--r--indra/newview/llviewertexteditor.cpp2
-rw-r--r--indra/newview/llviewerwindow.cpp41
-rw-r--r--indra/newview/llvoavatarself.cpp4
-rw-r--r--indra/newview/llvosky.cpp22
-rw-r--r--indra/newview/llvosky.h2
-rw-r--r--indra/newview/llvovolume.cpp15
-rw-r--r--indra/newview/llwaterparammanager.cpp2
-rw-r--r--indra/newview/llwlparammanager.cpp5
-rw-r--r--indra/newview/llwlparammanager.h9
-rw-r--r--indra/newview/llwlparamset.cpp94
-rw-r--r--indra/newview/llwlparamset.h2
-rw-r--r--indra/newview/llworld.cpp2494
-rw-r--r--indra/newview/llworldmapview.cpp31
-rw-r--r--indra/newview/llworldmapview.h4
-rw-r--r--indra/newview/pipeline.cpp19648
-rw-r--r--indra/newview/pipeline.h3
-rw-r--r--indra/newview/skins/default/colors.xml6
-rw-r--r--indra/newview/skins/default/textures/checker.pngbin0 -> 130 bytes
-rw-r--r--indra/newview/skins/default/textures/map_avatar_unknown_32.tgabin0 -> 4140 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_aaa.xml158
-rw-r--r--indra/newview/skins/default/xui/en/floater_about_land.xml22
-rw-r--r--indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml76
-rw-r--r--indra/newview/skins/default/xui/en/floater_animation_bvh_preview.xml (renamed from indra/newview/skins/default/xui/en/floater_animation_preview.xml)0
-rw-r--r--indra/newview/skins/default/xui/en/floater_build_options.xml61
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_contents.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_currency.xml8
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_object.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_choose_group.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_fast_timers.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_merchant_outbox.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_model_preview.xml86
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_animation.xml16
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml20
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_text_vertical_aligment.xml112
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_textbox.xml16
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml62
-rw-r--r--indra/newview/skins/default/xui/en/floater_toybox.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_voice_controls.xml2
-rw-r--r--indra/newview/skins/default/xui/en/inspect_object.xml3
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml10
-rw-r--r--indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_chat_header.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_chat_item.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_wearable.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_roles.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_inbox_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_instant_message.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_landmark_info.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_main_inventory.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_navigation_bar.xml15
-rw-r--r--indra/newview/skins/default/xui/en/panel_nearby_chat.xml84
-rw-r--r--indra/newview/skins/default/xui/en/panel_notification.xml18
-rw-r--r--indra/newview/skins/default/xui/en/panel_online_status_toast.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_general.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_sound.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_status_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_sys_well_item.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_teleport_history_item.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_toast.xml2
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_inventory.xml3
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml4
-rw-r--r--indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml8
-rw-r--r--indra/newview/skins/default/xui/en/widgets/bodyparts_list_item.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/button.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/check_box.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/clothing_list_item.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/dummy_clothing_list_item.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/tab_container.xml2
-rw-r--r--indra/newview/tests/llworldmipmap_test.cpp4
-rw-r--r--indra/newview/viewer_manifest.py4
-rw-r--r--indra/test/test.cpp212
-rw-r--r--indra/viewer_components/updater/llupdaterservice.cpp2
271 files changed, 18486 insertions, 17020 deletions
diff --git a/.hgtags b/.hgtags
index c93592fb52..b37a43092c 100644
--- a/.hgtags
+++ b/.hgtags
@@ -273,3 +273,5 @@ a01ef9bed28627f4ca543fbc1d70c79cc297a90f 3.2.9-beta2
987425b1acf4752379b2e1eb20944b4b35d67a85 3.2.8-beta2
d5f263687f43f278107363365938f0a214920a4b 3.3.0-start
dffd0457ee0745de65bf95f0642a5c9e46b8e2f0 viewer-beta-candidate
+d5f263687f43f278107363365938f0a214920a4b DRTVWR-119
+d5f263687f43f278107363365938f0a214920a4b 3.3.0-beta1
diff --git a/doc/contributions.txt b/doc/contributions.txt
index c5db396c97..3851e62cfb 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -103,6 +103,7 @@ Aleric Inglewood
STORM-163
STORM-955
STORM-960
+ STORM-1793
Ales Beaumont
VWR-9352
SNOW-240
@@ -466,6 +467,8 @@ Hiro Sommambulist
VWR-132
VWR-136
VWR-143
+Hitomi Tiponi
+ STORM-1741
Holger Gilruth
Horatio Freund
Hoze Menges
@@ -594,22 +597,34 @@ Jonathan Yap
STORM-1659
STORM-1674
STORM-1685
+ STORM-1718
STORM-1721
+ STORM-1718
STORM-1727
STORM-1725
STORM-1719
STORM-1712
STORM-1728
STORM-1736
+ STORM-1804
STORM-1734
STORM-1731
STORM-653
STORM-1737
STORM-1733
+ STORM-1741
STORM-1790
+ STORM-1795
STORM-1788
+ STORM-1803
+ STORM-1795
STORM-1799
STORM-1796
+ STORM-1807
+ STORM-1808
+ STORM-1809
+ STORM-1793
+ STORM-1810
Kadah Coba
STORM-1060
Jondan Lundquist
@@ -645,6 +660,7 @@ Kitty Barnett
STORM-1001
STORM-1175
VWR-24217
+ STORM-1804
Kolor Fall
Komiko Okamoto
Korvel Noh
@@ -1239,6 +1255,8 @@ WolfPup Lowenhar
VWR-20741
VWR-20933
Wundur Primbee
+Xellessanova Zenith
+ STORM-1793
Xiki Luik
xstorm Radek
YongYong Francois
diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp
index f0b44f97d2..7f747c2eca 100644
--- a/indra/llaudio/llaudiodecodemgr.cpp
+++ b/indra/llaudio/llaudiodecodemgr.cpp
@@ -215,7 +215,7 @@ BOOL LLVorbisDecodeState::initDecode()
return(FALSE);
}
- S32 sample_count = ov_pcm_total(&mVF, -1);
+ S32 sample_count = (S32)ov_pcm_total(&mVF, -1);
size_t size_guess = (size_t)sample_count;
vorbis_info* vi = ov_info(&mVF, -1);
size_guess *= (vi? vi->channels : 1);
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
index a47ee7ca7c..28b69e1973 100644
--- a/indra/llaudio/llaudioengine.h
+++ b/indra/llaudio/llaudioengine.h
@@ -37,6 +37,7 @@
#include "lluuid.h"
#include "llframetimer.h"
#include "llassettype.h"
+#include "llextendedstatus.h"
#include "lllistener.h"
diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp
index f3cf950afa..2a0df26384 100644
--- a/indra/llcharacter/llbvhloader.cpp
+++ b/indra/llcharacter/llbvhloader.cpp
@@ -1570,7 +1570,7 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp)
constraint_it++)
{
U8 byte = constraint_it->mChainLength;
- dp.packU8(byte, "chain_lenght");
+ dp.packU8(byte, "chain_length");
byte = constraint_it->mConstraintType;
dp.packU8(byte, "constraint_type");
diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h
index bdcc98e402..5cfcdab41c 100644
--- a/indra/llcommon/linden_common.h
+++ b/indra/llcommon/linden_common.h
@@ -52,34 +52,11 @@
#include <ctime>
#include <iosfwd>
-// Work around Microsoft compiler warnings in STL headers
-#ifdef LL_WINDOWS
-#pragma warning (disable : 4702) // unreachable code
-#pragma warning (disable : 4244) // conversion from time_t to S32
-#endif // LL_WINDOWS
-
-// *TODO: Eliminate these, most library .cpp files don't need them.
-// Add them to llviewerprecompiledheaders.h if necessary.
-#include <list>
-#include <map>
-#include <vector>
-#include <string>
-
-#ifdef LL_WINDOWS
-// Reenable warnings we disabled above
-#pragma warning (3 : 4702) // unreachable code, we like level 3, not 4
-// moved msvc warnings to llpreprocessor.h *TODO - delete this comment after merge conflicts are unlikely -brad
-#endif // LL_WINDOWS
-
// Linden only libs in alpha-order other than stdtypes.h
// *NOTE: Please keep includes here to a minimum, see above.
#include "stdtypes.h"
#include "lldefs.h"
#include "llerror.h"
-#include "llextendedstatus.h"
-// Don't do this, adds 15K lines of header code to every library file.
-//#include "llfasttimer.h"
#include "llfile.h"
-#include "llformat.h"
#endif
diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp
index ba3dd6d6b4..3206843bf4 100644
--- a/indra/llcommon/llavatarname.cpp
+++ b/indra/llcommon/llavatarname.cpp
@@ -106,6 +106,11 @@ std::string LLAvatarName::getCompleteName() const
std::string LLAvatarName::getLegacyName() const
{
+ if (mLegacyFirstName.empty() && mLegacyLastName.empty()) // display names disabled?
+ {
+ return mDisplayName;
+ }
+
std::string name;
name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() );
name = mLegacyFirstName;
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index db1ea4792b..0855180dcd 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -430,13 +430,13 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
{
// The new node isn't last. Place it between the previous node and
// the successor.
- newNode = (myprev + mydmi->second)/2.0;
+ newNode = (myprev + mydmi->second)/2.f;
}
else
{
// The new node is last. Bump myprev up to the next integer, add
// 1.0 and use that.
- newNode = std::ceil(myprev) + 1.0;
+ newNode = std::ceil(myprev) + 1.f;
}
// Now that newNode has a value that places it appropriately in mSignal,
// connect it.
diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp
index 75fde8e5ba..1409c55d1c 100644
--- a/indra/llcommon/llmd5.cpp
+++ b/indra/llcommon/llmd5.cpp
@@ -175,7 +175,7 @@ void LLMD5::update(std::istream& stream){
while (stream.good()){
stream.read( (char*)buffer, BLOCK_LEN); /* Flawfinder: ignore */ // note that return value of read is unusable.
- len=stream.gcount();
+ len=(int)stream.gcount();
update(buffer, len);
}
diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index 31d5f3d2c7..7fdb537ab5 100644
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -132,7 +132,7 @@
#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual"
#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden
#pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored
-#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file
+//#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file
#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.
#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
#pragma warning( disable : 4996 ) // warning: deprecated
@@ -152,6 +152,7 @@
#pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class
#pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class
#pragma warning (disable : 4018) // '<' : signed/unsigned mismatch
+
#endif // LL_MSVC
#if LL_WINDOWS
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 4722421fca..bc66832ad0 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -1,2249 +1,2249 @@
-/**
- * @file llsdserialize.cpp
- * @author Phoenix
- * @date 2006-03-05
- * @brief Implementation of LLSD parsers and formatters
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llsdserialize.h"
-#include "llpointer.h"
-#include "llstreamtools.h" // for fullread
-
-#include <iostream>
-#include "apr_base64.h"
-
-#ifdef LL_STANDALONE
-# include <zlib.h>
-#else
-# include "zlib/zlib.h" // for davep's dirty little zip functions
-#endif
-
-#if !LL_WINDOWS
-#include <netinet/in.h> // htonl & ntohl
-#endif
-
-#include "lldate.h"
-#include "llsd.h"
-#include "llstring.h"
-#include "lluri.h"
-
-// File constants
-static const int MAX_HDR_LEN = 20;
-static const char LEGACY_NON_HEADER[] = "<llsd>";
-const std::string LLSD_BINARY_HEADER("LLSD/Binary");
-const std::string LLSD_XML_HEADER("LLSD/XML");
-
-//used to deflate a gzipped asset (currently used for navmeshes)
+/**
+ * @file llsdserialize.cpp
+ * @author Phoenix
+ * @date 2006-03-05
+ * @brief Implementation of LLSD parsers and formatters
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llsdserialize.h"
+#include "llpointer.h"
+#include "llstreamtools.h" // for fullread
+
+#include <iostream>
+#include "apr_base64.h"
+
+#ifdef LL_STANDALONE
+# include <zlib.h>
+#else
+# include "zlib/zlib.h" // for davep's dirty little zip functions
+#endif
+
+#if !LL_WINDOWS
+#include <netinet/in.h> // htonl & ntohl
+#endif
+
+#include "lldate.h"
+#include "llsd.h"
+#include "llstring.h"
+#include "lluri.h"
+
+// File constants
+static const int MAX_HDR_LEN = 20;
+static const char LEGACY_NON_HEADER[] = "<llsd>";
+const std::string LLSD_BINARY_HEADER("LLSD/Binary");
+const std::string LLSD_XML_HEADER("LLSD/XML");
+
+//used to deflate a gzipped asset (currently used for navmeshes)
#define windowBits 15
#define ENABLE_ZLIB_GZIP 32
-
-/**
- * LLSDSerialize
- */
-
-// static
-void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options)
-{
- LLPointer<LLSDFormatter> f = NULL;
-
- switch (type)
- {
- case LLSD_BINARY:
- str << "<? " << LLSD_BINARY_HEADER << " ?>\n";
- f = new LLSDBinaryFormatter;
- break;
-
- case LLSD_XML:
- str << "<? " << LLSD_XML_HEADER << " ?>\n";
- f = new LLSDXMLFormatter;
- break;
-
- default:
- llwarns << "serialize request for unknown ELLSD_Serialize" << llendl;
- }
-
- if (f.notNull())
- {
- f->format(sd, str, options);
- }
-}
-
-// static
-bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
-{
- LLPointer<LLSDParser> p = NULL;
- char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */
- int i;
- int inbuf = 0;
- bool legacy_no_header = false;
- bool fail_if_not_legacy = false;
- std::string header;
-
- /*
- * Get the first line before anything.
- */
- str.get(hdr_buf, MAX_HDR_LEN, '\n');
- if (str.fail())
- {
- str.clear();
- fail_if_not_legacy = true;
- }
-
- if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */
- {
- legacy_no_header = true;
- inbuf = str.gcount();
- }
- else
- {
- if (fail_if_not_legacy)
- goto fail;
- /*
- * Remove the newline chars
- */
- for (i = 0; i < MAX_HDR_LEN; i++)
- {
- if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' ||
- hdr_buf[i] == '\n')
- {
- hdr_buf[i] = 0;
- break;
- }
- }
- header = hdr_buf;
-
- std::string::size_type start = std::string::npos;
- std::string::size_type end = std::string::npos;
- start = header.find_first_not_of("<? ");
- if (start != std::string::npos)
- {
- end = header.find_first_of(" ?", start);
- }
- if ((start == std::string::npos) || (end == std::string::npos))
- goto fail;
-
- header = header.substr(start, end - start);
- ws(str);
- }
- /*
- * Create the parser as appropriate
- */
- if (legacy_no_header)
- { // Create a LLSD XML parser, and parse the first chunk read above
- LLSDXMLParser* x = new LLSDXMLParser();
- x->parsePart(hdr_buf, inbuf); // Parse the first part that was already read
- x->parseLines(str, sd); // Parse the rest of it
- delete x;
- return true;
- }
-
- if (header == LLSD_BINARY_HEADER)
- {
- p = new LLSDBinaryParser;
- }
- else if (header == LLSD_XML_HEADER)
- {
- p = new LLSDXMLParser;
- }
- else
- {
- llwarns << "deserialize request for unknown ELLSD_Serialize" << llendl;
- }
-
- if (p.notNull())
- {
- p->parse(str, sd, max_bytes);
- return true;
- }
-
-fail:
- llwarns << "deserialize LLSD parse failure" << llendl;
- return false;
-}
-
-/**
- * Endian handlers
- */
-#if LL_BIG_ENDIAN
-U64 ll_htonll(U64 hostlonglong) { return hostlonglong; }
-U64 ll_ntohll(U64 netlonglong) { return netlonglong; }
-F64 ll_htond(F64 hostlonglong) { return hostlonglong; }
-F64 ll_ntohd(F64 netlonglong) { return netlonglong; }
-#else
-// I read some comments one a indicating that doing an integer add
-// here would be faster than a bitwise or. For now, the or has
-// programmer clarity, since the intended outcome matches the
-// operation.
-U64 ll_htonll(U64 hostlonglong)
-{
- return ((U64)(htonl((U32)((hostlonglong >> 32) & 0xFFFFFFFF))) |
- ((U64)(htonl((U32)(hostlonglong & 0xFFFFFFFF))) << 32));
-}
-U64 ll_ntohll(U64 netlonglong)
-{
- return ((U64)(ntohl((U32)((netlonglong >> 32) & 0xFFFFFFFF))) |
- ((U64)(ntohl((U32)(netlonglong & 0xFFFFFFFF))) << 32));
-}
-union LLEndianSwapper
-{
- F64 d;
- U64 i;
-};
-F64 ll_htond(F64 hostdouble)
-{
- LLEndianSwapper tmp;
- tmp.d = hostdouble;
- tmp.i = ll_htonll(tmp.i);
- return tmp.d;
-}
-F64 ll_ntohd(F64 netdouble)
-{
- LLEndianSwapper tmp;
- tmp.d = netdouble;
- tmp.i = ll_ntohll(tmp.i);
- return tmp.d;
-}
-#endif
-
-/**
- * Local functions.
- */
-/**
- * @brief Figure out what kind of string it is (raw or delimited) and handoff.
- *
- * @param istr The stream to read from.
- * @param value [out] The string which was found.
- * @param max_bytes The maximum possible length of the string. Passing in
- * a negative value will skip this check.
- * @return Returns number of bytes read off of the stream. Returns
- * PARSE_FAILURE (-1) on failure.
- */
-int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes);
-
-/**
- * @brief Parse a delimited string.
- *
- * @param istr The stream to read from, with the delimiter already popped.
- * @param value [out] The string which was found.
- * @param d The delimiter to use.
- * @return Returns number of bytes read off of the stream. Returns
- * PARSE_FAILURE (-1) on failure.
- */
-int deserialize_string_delim(std::istream& istr, std::string& value, char d);
-
-/**
- * @brief Read a raw string off the stream.
- *
- * @param istr The stream to read from, with the (len) parameter
- * leading the stream.
- * @param value [out] The string which was found.
- * @param d The delimiter to use.
- * @param max_bytes The maximum possible length of the string. Passing in
- * a negative value will skip this check.
- * @return Returns number of bytes read off of the stream. Returns
- * PARSE_FAILURE (-1) on failure.
- */
-int deserialize_string_raw(
- std::istream& istr,
- std::string& value,
- S32 max_bytes);
-
-/**
- * @brief helper method for dealing with the different notation boolean format.
- *
- * @param istr The stream to read from with the leading character stripped.
- * @param data [out] the result of the parse.
- * @param compare The string to compare the boolean against
- * @param vale The value to assign to data if the parse succeeds.
- * @return Returns number of bytes read off of the stream. Returns
- * PARSE_FAILURE (-1) on failure.
- */
-int deserialize_boolean(
- std::istream& istr,
- LLSD& data,
- const std::string& compare,
- bool value);
-
-/**
- * @brief Do notation escaping of a string to an ostream.
- *
- * @param value The string to escape and serialize
- * @param str The stream to serialize to.
- */
-void serialize_string(const std::string& value, std::ostream& str);
-
-
-/**
- * Local constants.
- */
-static const std::string NOTATION_TRUE_SERIAL("true");
-static const std::string NOTATION_FALSE_SERIAL("false");
-
-static const char BINARY_TRUE_SERIAL = '1';
-static const char BINARY_FALSE_SERIAL = '0';
-
-
-/**
- * LLSDParser
- */
-LLSDParser::LLSDParser()
- : mCheckLimits(true), mMaxBytesLeft(0), mParseLines(false)
-{
-}
-
-// virtual
-LLSDParser::~LLSDParser()
-{ }
-
-S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes)
-{
- mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true;
- mMaxBytesLeft = max_bytes;
- return doParse(istr, data);
-}
-
-
-// Parse using routine to get() lines, faster than parse()
-S32 LLSDParser::parseLines(std::istream& istr, LLSD& data)
-{
- mCheckLimits = false;
- mParseLines = true;
- return doParse(istr, data);
-}
-
-
-int LLSDParser::get(std::istream& istr) const
-{
- if(mCheckLimits) --mMaxBytesLeft;
- return istr.get();
-}
-
-std::istream& LLSDParser::get(
- std::istream& istr,
- char* s,
- std::streamsize n,
- char delim) const
-{
- istr.get(s, n, delim);
- if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
- return istr;
-}
-
-std::istream& LLSDParser::get(
- std::istream& istr,
- std::streambuf& sb,
- char delim) const
-{
- istr.get(sb, delim);
- if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
- return istr;
-}
-
-std::istream& LLSDParser::ignore(std::istream& istr) const
-{
- istr.ignore();
- if(mCheckLimits) --mMaxBytesLeft;
- return istr;
-}
-
-std::istream& LLSDParser::putback(std::istream& istr, char c) const
-{
- istr.putback(c);
- if(mCheckLimits) ++mMaxBytesLeft;
- return istr;
-}
-
-std::istream& LLSDParser::read(
- std::istream& istr,
- char* s,
- std::streamsize n) const
-{
- istr.read(s, n);
- if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
- return istr;
-}
-
-void LLSDParser::account(S32 bytes) const
-{
- if(mCheckLimits) mMaxBytesLeft -= bytes;
-}
-
-
-/**
- * LLSDNotationParser
- */
-LLSDNotationParser::LLSDNotationParser()
-{
-}
-
-// virtual
-LLSDNotationParser::~LLSDNotationParser()
-{ }
-
-// virtual
-S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
-{
- // map: { string:object, string:object }
- // array: [ object, object, object ]
- // undef: !
- // boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE
- // integer: i####
- // real: r####
- // uuid: u####
- // string: "g'day" | 'have a "nice" day' | s(size)"raw data"
- // uri: l"escaped"
- // date: d"YYYY-MM-DDTHH:MM:SS.FFZ"
- // binary: b##"ff3120ab1" | b(size)"raw data"
- char c;
- c = istr.peek();
- while(isspace(c))
- {
- // pop the whitespace.
- c = get(istr);
- c = istr.peek();
- continue;
- }
- if(!istr.good())
- {
- return 0;
- }
- S32 parse_count = 1;
- switch(c)
- {
- case '{':
- {
- S32 child_count = parseMap(istr, data);
- if((child_count == PARSE_FAILURE) || data.isUndefined())
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- parse_count += child_count;
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading map." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case '[':
- {
- S32 child_count = parseArray(istr, data);
- if((child_count == PARSE_FAILURE) || data.isUndefined())
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- parse_count += child_count;
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading array." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case '!':
- c = get(istr);
- data.clear();
- break;
-
- case '0':
- c = get(istr);
- data = false;
- break;
-
- case 'F':
- case 'f':
- ignore(istr);
- c = istr.peek();
- if(isalpha(c))
- {
- int cnt = deserialize_boolean(
- istr,
- data,
- NOTATION_FALSE_SERIAL,
- false);
- if(PARSE_FAILURE == cnt) parse_count = cnt;
- else account(cnt);
- }
- else
- {
- data = false;
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading boolean." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
-
- case '1':
- c = get(istr);
- data = true;
- break;
-
- case 'T':
- case 't':
- ignore(istr);
- c = istr.peek();
- if(isalpha(c))
- {
- int cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true);
- if(PARSE_FAILURE == cnt) parse_count = cnt;
- else account(cnt);
- }
- else
- {
- data = true;
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading boolean." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
-
- case 'i':
- {
- c = get(istr);
- S32 integer = 0;
- istr >> integer;
- data = integer;
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading integer." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'r':
- {
- c = get(istr);
- F64 real = 0.0;
- istr >> real;
- data = real;
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading real." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'u':
- {
- c = get(istr);
- LLUUID id;
- istr >> id;
- data = id;
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading uuid." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case '\"':
- case '\'':
- case 's':
- if(!parseString(istr, data))
- {
- parse_count = PARSE_FAILURE;
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading string." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
-
- case 'l':
- {
- c = get(istr); // pop the 'l'
- c = get(istr); // pop the delimiter
- std::string str;
- int cnt = deserialize_string_delim(istr, str, c);
- if(PARSE_FAILURE == cnt)
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- data = LLURI(str);
- account(cnt);
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading link." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'd':
- {
- c = get(istr); // pop the 'd'
- c = get(istr); // pop the delimiter
- std::string str;
- int cnt = deserialize_string_delim(istr, str, c);
- if(PARSE_FAILURE == cnt)
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- data = LLDate(str);
- account(cnt);
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading date." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'b':
- if(!parseBinary(istr, data))
- {
- parse_count = PARSE_FAILURE;
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading data." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
-
- default:
- parse_count = PARSE_FAILURE;
- llinfos << "Unrecognized character while parsing: int(" << (int)c
- << ")" << llendl;
- break;
- }
- if(PARSE_FAILURE == parse_count)
- {
- data.clear();
- }
- return parse_count;
-}
-
-S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const
-{
- // map: { string:object, string:object }
- map = LLSD::emptyMap();
- S32 parse_count = 0;
- char c = get(istr);
- if(c == '{')
- {
- // eat commas, white
- bool found_name = false;
- std::string name;
- c = get(istr);
- while(c != '}' && istr.good())
- {
- if(!found_name)
- {
- if((c == '\"') || (c == '\'') || (c == 's'))
- {
- putback(istr, c);
- found_name = true;
- int count = deserialize_string(istr, name, mMaxBytesLeft);
- if(PARSE_FAILURE == count) return PARSE_FAILURE;
- account(count);
- }
- c = get(istr);
- }
- else
- {
- if(isspace(c) || (c == ':'))
- {
- c = get(istr);
- continue;
- }
- putback(istr, c);
- LLSD child;
- S32 count = doParse(istr, child);
- if(count > 0)
- {
- // There must be a value for every key, thus
- // child_count must be greater than 0.
- parse_count += count;
- map.insert(name, child);
- }
- else
- {
- return PARSE_FAILURE;
- }
- found_name = false;
- c = get(istr);
- }
- }
- if(c != '}')
- {
- map.clear();
- return PARSE_FAILURE;
- }
- }
- return parse_count;
-}
-
-S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const
-{
- // array: [ object, object, object ]
- array = LLSD::emptyArray();
- S32 parse_count = 0;
- char c = get(istr);
- if(c == '[')
- {
- // eat commas, white
- c = get(istr);
- while((c != ']') && istr.good())
- {
- LLSD child;
- if(isspace(c) || (c == ','))
- {
- c = get(istr);
- continue;
- }
- putback(istr, c);
- S32 count = doParse(istr, child);
- if(PARSE_FAILURE == count)
- {
- return PARSE_FAILURE;
- }
- else
- {
- parse_count += count;
- array.append(child);
- }
- c = get(istr);
- }
- if(c != ']')
- {
- return PARSE_FAILURE;
- }
- }
- return parse_count;
-}
-
-bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
-{
- std::string value;
- int count = deserialize_string(istr, value, mMaxBytesLeft);
- if(PARSE_FAILURE == count) return false;
- account(count);
- data = value;
- return true;
-}
-
-bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
-{
- // binary: b##"ff3120ab1"
- // or: b(len)"..."
-
- // I want to manually control those values here to make sure the
- // parser doesn't break when someone changes a constant somewhere
- // else.
- const U32 BINARY_BUFFER_SIZE = 256;
- const U32 STREAM_GET_COUNT = 255;
-
- // need to read the base out.
- char buf[BINARY_BUFFER_SIZE]; /* Flawfinder: ignore */
- get(istr, buf, STREAM_GET_COUNT, '"');
- char c = get(istr);
- if(c != '"') return false;
- if(0 == strncmp("b(", buf, 2))
- {
- // We probably have a valid raw binary stream. determine
- // the size, and read it.
- S32 len = strtol(buf + 2, NULL, 0);
- if(mCheckLimits && (len > mMaxBytesLeft)) return false;
- std::vector<U8> value;
- if(len)
- {
- value.resize(len);
- account(fullread(istr, (char *)&value[0], len));
- }
- c = get(istr); // strip off the trailing double-quote
- data = value;
- }
- else if(0 == strncmp("b64", buf, 3))
- {
- // *FIX: A bit inefficient, but works for now. To make the
- // format better, I would need to add a hint into the
- // serialization format that indicated how long it was.
- std::stringstream coded_stream;
- get(istr, *(coded_stream.rdbuf()), '\"');
- c = get(istr);
- std::string encoded(coded_stream.str());
- S32 len = apr_base64_decode_len(encoded.c_str());
- std::vector<U8> value;
- if(len)
- {
- value.resize(len);
- len = apr_base64_decode_binary(&value[0], encoded.c_str());
- value.resize(len);
- }
- data = value;
- }
- else if(0 == strncmp("b16", buf, 3))
- {
- // yay, base 16. We pop the next character which is either a
- // double quote or base 16 data. If it's a double quote, we're
- // done parsing. If it's not, put the data back, and read the
- // stream until the next double quote.
- char* read; /*Flawfinder: ignore*/
- U8 byte;
- U8 byte_buffer[BINARY_BUFFER_SIZE];
- U8* write;
- std::vector<U8> value;
- c = get(istr);
- while(c != '"')
- {
- putback(istr, c);
- read = buf;
- write = byte_buffer;
- get(istr, buf, STREAM_GET_COUNT, '"');
- c = get(istr);
- while(*read != '\0') /*Flawfinder: ignore*/
- {
- byte = hex_as_nybble(*read++);
- byte = byte << 4;
- byte |= hex_as_nybble(*read++);
- *write++ = byte;
- }
- // copy the data out of the byte buffer
- value.insert(value.end(), byte_buffer, write);
- }
- data = value;
- }
- else
- {
- return false;
- }
- return true;
-}
-
-
-/**
- * LLSDBinaryParser
- */
-LLSDBinaryParser::LLSDBinaryParser()
-{
-}
-
-// virtual
-LLSDBinaryParser::~LLSDBinaryParser()
-{
-}
-
-// virtual
-S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
-{
-/**
- * Undefined: '!'<br>
- * Boolean: 't' for true 'f' for false<br>
- * Integer: 'i' + 4 bytes network byte order<br>
- * Real: 'r' + 8 bytes IEEE double<br>
- * UUID: 'u' + 16 byte unsigned integer<br>
- * String: 's' + 4 byte integer size + string<br>
- * strings also secretly support the notation format
- * Date: 'd' + 8 byte IEEE double for seconds since epoch<br>
- * URI: 'l' + 4 byte integer size + string uri<br>
- * Binary: 'b' + 4 byte integer size + binary data<br>
- * Array: '[' + 4 byte integer size + all values + ']'<br>
- * Map: '{' + 4 byte integer size every(key + value) + '}'<br>
- * map keys are serialized as s + 4 byte integer size + string or in the
- * notation format.
- */
- char c;
- c = get(istr);
- if(!istr.good())
- {
- return 0;
- }
- S32 parse_count = 1;
- switch(c)
- {
- case '{':
- {
- S32 child_count = parseMap(istr, data);
- if((child_count == PARSE_FAILURE) || data.isUndefined())
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- parse_count += child_count;
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading binary map." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case '[':
- {
- S32 child_count = parseArray(istr, data);
- if((child_count == PARSE_FAILURE) || data.isUndefined())
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- parse_count += child_count;
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading binary array." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case '!':
- data.clear();
- break;
-
- case '0':
- data = false;
- break;
-
- case '1':
- data = true;
- break;
-
- case 'i':
- {
- U32 value_nbo = 0;
- read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
- data = (S32)ntohl(value_nbo);
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading binary integer." << llendl;
- }
- break;
- }
-
- case 'r':
- {
- F64 real_nbo = 0.0;
- read(istr, (char*)&real_nbo, sizeof(F64)); /*Flawfinder: ignore*/
- data = ll_ntohd(real_nbo);
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading binary real." << llendl;
- }
- break;
- }
-
- case 'u':
- {
- LLUUID id;
- read(istr, (char*)(&id.mData), UUID_BYTES); /*Flawfinder: ignore*/
- data = id;
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading binary uuid." << llendl;
- }
- break;
- }
-
- case '\'':
- case '"':
- {
- std::string value;
- int cnt = deserialize_string_delim(istr, value, c);
- if(PARSE_FAILURE == cnt)
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- data = value;
- account(cnt);
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading binary (notation-style) string."
- << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 's':
- {
- std::string value;
- if(parseString(istr, value))
- {
- data = value;
- }
- else
- {
- parse_count = PARSE_FAILURE;
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading binary string." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'l':
- {
- std::string value;
- if(parseString(istr, value))
- {
- data = LLURI(value);
- }
- else
- {
- parse_count = PARSE_FAILURE;
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading binary link." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'd':
- {
- F64 real = 0.0;
- read(istr, (char*)&real, sizeof(F64)); /*Flawfinder: ignore*/
- data = LLDate(real);
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading binary date." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- case 'b':
- {
- // We probably have a valid raw binary stream. determine
- // the size, and read it.
- U32 size_nbo = 0;
- read(istr, (char*)&size_nbo, sizeof(U32)); /*Flawfinder: ignore*/
- S32 size = (S32)ntohl(size_nbo);
- if(mCheckLimits && (size > mMaxBytesLeft))
- {
- parse_count = PARSE_FAILURE;
- }
- else
- {
- std::vector<U8> value;
- if(size > 0)
- {
- value.resize(size);
- account(fullread(istr, (char*)&value[0], size));
- }
- data = value;
- }
- if(istr.fail())
- {
- llinfos << "STREAM FAILURE reading binary." << llendl;
- parse_count = PARSE_FAILURE;
- }
- break;
- }
-
- default:
- parse_count = PARSE_FAILURE;
- llinfos << "Unrecognized character while parsing: int(" << (int)c
- << ")" << llendl;
- break;
- }
- if(PARSE_FAILURE == parse_count)
- {
- data.clear();
- }
- return parse_count;
-}
-
-S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const
-{
- map = LLSD::emptyMap();
- U32 value_nbo = 0;
- read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
- S32 size = (S32)ntohl(value_nbo);
- S32 parse_count = 0;
- S32 count = 0;
- char c = get(istr);
- while(c != '}' && (count < size) && istr.good())
- {
- std::string name;
- switch(c)
- {
- case 'k':
- if(!parseString(istr, name))
- {
- return PARSE_FAILURE;
- }
- break;
- case '\'':
- case '"':
- {
- int cnt = deserialize_string_delim(istr, name, c);
- if(PARSE_FAILURE == cnt) return PARSE_FAILURE;
- account(cnt);
- break;
- }
- }
- LLSD child;
- S32 child_count = doParse(istr, child);
- if(child_count > 0)
- {
- // There must be a value for every key, thus child_count
- // must be greater than 0.
- parse_count += child_count;
- map.insert(name, child);
- }
- else
- {
- return PARSE_FAILURE;
- }
- ++count;
- c = get(istr);
- }
- if((c != '}') || (count < size))
- {
- // Make sure it is correctly terminated and we parsed as many
- // as were said to be there.
- return PARSE_FAILURE;
- }
- return parse_count;
-}
-
-S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
-{
- array = LLSD::emptyArray();
- U32 value_nbo = 0;
- read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
- S32 size = (S32)ntohl(value_nbo);
-
- // *FIX: This would be a good place to reserve some space in the
- // array...
-
- S32 parse_count = 0;
- S32 count = 0;
- char c = istr.peek();
- while((c != ']') && (count < size) && istr.good())
- {
- LLSD child;
- S32 child_count = doParse(istr, child);
- if(PARSE_FAILURE == child_count)
- {
- return PARSE_FAILURE;
- }
- if(child_count)
- {
- parse_count += child_count;
- array.append(child);
- }
- ++count;
- c = istr.peek();
- }
- c = get(istr);
- if((c != ']') || (count < size))
- {
- // Make sure it is correctly terminated and we parsed as many
- // as were said to be there.
- return PARSE_FAILURE;
- }
- return parse_count;
-}
-
-bool LLSDBinaryParser::parseString(
- std::istream& istr,
- std::string& value) const
-{
- // *FIX: This is memory inefficient.
- U32 value_nbo = 0;
- read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
- S32 size = (S32)ntohl(value_nbo);
- if(mCheckLimits && (size > mMaxBytesLeft)) return false;
- std::vector<char> buf;
- if(size)
- {
- buf.resize(size);
- account(fullread(istr, &buf[0], size));
- value.assign(buf.begin(), buf.end());
- }
- return true;
-}
-
-
-/**
- * LLSDFormatter
- */
-LLSDFormatter::LLSDFormatter() :
- mBoolAlpha(false)
-{
-}
-
-// virtual
-LLSDFormatter::~LLSDFormatter()
-{ }
-
-void LLSDFormatter::boolalpha(bool alpha)
-{
- mBoolAlpha = alpha;
-}
-
-void LLSDFormatter::realFormat(const std::string& format)
-{
- mRealFormat = format;
-}
-
-void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const
-{
- std::string buffer = llformat(mRealFormat.c_str(), real);
- ostr << buffer;
-}
-
-/**
- * LLSDNotationFormatter
- */
-LLSDNotationFormatter::LLSDNotationFormatter()
-{
-}
-
-// virtual
-LLSDNotationFormatter::~LLSDNotationFormatter()
-{ }
-
-// static
-std::string LLSDNotationFormatter::escapeString(const std::string& in)
-{
- std::ostringstream ostr;
- serialize_string(in, ostr);
- return ostr.str();
-}
-
-// virtual
-S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
-{
- S32 format_count = 1;
- switch(data.type())
- {
- case LLSD::TypeMap:
- {
- ostr << "{";
- bool need_comma = false;
- LLSD::map_const_iterator iter = data.beginMap();
- LLSD::map_const_iterator end = data.endMap();
- for(; iter != end; ++iter)
- {
- if(need_comma) ostr << ",";
- need_comma = true;
- ostr << '\'';
- serialize_string((*iter).first, ostr);
- ostr << "':";
- format_count += format((*iter).second, ostr);
- }
- ostr << "}";
- break;
- }
-
- case LLSD::TypeArray:
- {
- ostr << "[";
- bool need_comma = false;
- LLSD::array_const_iterator iter = data.beginArray();
- LLSD::array_const_iterator end = data.endArray();
- for(; iter != end; ++iter)
- {
- if(need_comma) ostr << ",";
- need_comma = true;
- format_count += format(*iter, ostr);
- }
- ostr << "]";
- break;
- }
-
- case LLSD::TypeUndefined:
- ostr << "!";
- break;
-
- case LLSD::TypeBoolean:
- if(mBoolAlpha ||
-#if( LL_WINDOWS || __GNUC__ > 2)
- (ostr.flags() & std::ios::boolalpha)
-#else
- (ostr.flags() & 0x0100)
-#endif
- )
- {
- ostr << (data.asBoolean()
- ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL);
- }
- else
- {
- ostr << (data.asBoolean() ? 1 : 0);
- }
- break;
-
- case LLSD::TypeInteger:
- ostr << "i" << data.asInteger();
- break;
-
- case LLSD::TypeReal:
- ostr << "r";
- if(mRealFormat.empty())
- {
- ostr << data.asReal();
- }
- else
- {
- formatReal(data.asReal(), ostr);
- }
- break;
-
- case LLSD::TypeUUID:
- ostr << "u" << data.asUUID();
- break;
-
- case LLSD::TypeString:
- ostr << '\'';
- serialize_string(data.asString(), ostr);
- ostr << '\'';
- break;
-
- case LLSD::TypeDate:
- ostr << "d\"" << data.asDate() << "\"";
- break;
-
- case LLSD::TypeURI:
- ostr << "l\"";
- serialize_string(data.asString(), ostr);
- ostr << "\"";
- break;
-
- case LLSD::TypeBinary:
- {
- // *FIX: memory inefficient.
- std::vector<U8> buffer = data.asBinary();
- ostr << "b(" << buffer.size() << ")\"";
- if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
- ostr << "\"";
- break;
- }
-
- default:
- // *NOTE: This should never happen.
- ostr << "!";
- break;
- }
- return format_count;
-}
-
-
-/**
- * LLSDBinaryFormatter
- */
-LLSDBinaryFormatter::LLSDBinaryFormatter()
-{
-}
-
-// virtual
-LLSDBinaryFormatter::~LLSDBinaryFormatter()
-{ }
-
-// virtual
-S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
-{
- S32 format_count = 1;
- switch(data.type())
- {
- case LLSD::TypeMap:
- {
- ostr.put('{');
- U32 size_nbo = htonl(data.size());
- ostr.write((const char*)(&size_nbo), sizeof(U32));
- LLSD::map_const_iterator iter = data.beginMap();
- LLSD::map_const_iterator end = data.endMap();
- for(; iter != end; ++iter)
- {
- ostr.put('k');
- formatString((*iter).first, ostr);
- format_count += format((*iter).second, ostr);
- }
- ostr.put('}');
- break;
- }
-
- case LLSD::TypeArray:
- {
- ostr.put('[');
- U32 size_nbo = htonl(data.size());
- ostr.write((const char*)(&size_nbo), sizeof(U32));
- LLSD::array_const_iterator iter = data.beginArray();
- LLSD::array_const_iterator end = data.endArray();
- for(; iter != end; ++iter)
- {
- format_count += format(*iter, ostr);
- }
- ostr.put(']');
- break;
- }
-
- case LLSD::TypeUndefined:
- ostr.put('!');
- break;
-
- case LLSD::TypeBoolean:
- if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL);
- else ostr.put(BINARY_FALSE_SERIAL);
- break;
-
- case LLSD::TypeInteger:
- {
- ostr.put('i');
- U32 value_nbo = htonl(data.asInteger());
- ostr.write((const char*)(&value_nbo), sizeof(U32));
- break;
- }
-
- case LLSD::TypeReal:
- {
- ostr.put('r');
- F64 value_nbo = ll_htond(data.asReal());
- ostr.write((const char*)(&value_nbo), sizeof(F64));
- break;
- }
-
- case LLSD::TypeUUID:
- ostr.put('u');
- ostr.write((const char*)(&(data.asUUID().mData)), UUID_BYTES);
- break;
-
- case LLSD::TypeString:
- ostr.put('s');
- formatString(data.asString(), ostr);
- break;
-
- case LLSD::TypeDate:
- {
- ostr.put('d');
- F64 value = data.asReal();
- ostr.write((const char*)(&value), sizeof(F64));
- break;
- }
-
- case LLSD::TypeURI:
- ostr.put('l');
- formatString(data.asString(), ostr);
- break;
-
- case LLSD::TypeBinary:
- {
- // *FIX: memory inefficient.
- ostr.put('b');
- std::vector<U8> buffer = data.asBinary();
- U32 size_nbo = htonl(buffer.size());
- ostr.write((const char*)(&size_nbo), sizeof(U32));
- if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
- break;
- }
-
- default:
- // *NOTE: This should never happen.
- ostr.put('!');
- break;
- }
- return format_count;
-}
-
-void LLSDBinaryFormatter::formatString(
- const std::string& string,
- std::ostream& ostr) const
-{
- U32 size_nbo = htonl(string.size());
- ostr.write((const char*)(&size_nbo), sizeof(U32));
- ostr.write(string.c_str(), string.size());
-}
-
-/**
- * local functions
- */
-int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes)
-{
- int c = istr.get();
- if(istr.fail())
- {
- // No data in stream, bail out but mention the character we
- // grabbed.
- return LLSDParser::PARSE_FAILURE;
- }
-
- int rv = LLSDParser::PARSE_FAILURE;
- switch(c)
- {
- case '\'':
- case '"':
- rv = deserialize_string_delim(istr, value, c);
- break;
- case 's':
- // technically, less than max_bytes, but this is just meant to
- // catch egregious protocol errors. parse errors will be
- // caught in the case of incorrect counts.
- rv = deserialize_string_raw(istr, value, max_bytes);
- break;
- default:
- break;
- }
- if(LLSDParser::PARSE_FAILURE == rv) return rv;
- return rv + 1; // account for the character grabbed at the top.
-}
-
-int deserialize_string_delim(
- std::istream& istr,
- std::string& value,
- char delim)
-{
- std::ostringstream write_buffer;
- bool found_escape = false;
- bool found_hex = false;
- bool found_digit = false;
- U8 byte = 0;
- int count = 0;
-
- while (true)
- {
- int next_byte = istr.get();
- ++count;
-
- if(istr.fail())
- {
- // If our stream is empty, break out
- value = write_buffer.str();
- return LLSDParser::PARSE_FAILURE;
- }
-
- char next_char = (char)next_byte; // Now that we know it's not EOF
-
- if(found_escape)
- {
- // next character(s) is a special sequence.
- if(found_hex)
- {
- if(found_digit)
- {
- found_digit = false;
- found_hex = false;
- found_escape = false;
- byte = byte << 4;
- byte |= hex_as_nybble(next_char);
- write_buffer << byte;
- byte = 0;
- }
- else
- {
- // next character is the first nybble of
- //
- found_digit = true;
- byte = hex_as_nybble(next_char);
- }
- }
- else if(next_char == 'x')
- {
- found_hex = true;
- }
- else
- {
- switch(next_char)
- {
- case 'a':
- write_buffer << '\a';
- break;
- case 'b':
- write_buffer << '\b';
- break;
- case 'f':
- write_buffer << '\f';
- break;
- case 'n':
- write_buffer << '\n';
- break;
- case 'r':
- write_buffer << '\r';
- break;
- case 't':
- write_buffer << '\t';
- break;
- case 'v':
- write_buffer << '\v';
- break;
- default:
- write_buffer << next_char;
- break;
- }
- found_escape = false;
- }
- }
- else if(next_char == '\\')
- {
- found_escape = true;
- }
- else if(next_char == delim)
- {
- break;
- }
- else
- {
- write_buffer << next_char;
- }
- }
-
- value = write_buffer.str();
- return count;
-}
-
-int deserialize_string_raw(
- std::istream& istr,
- std::string& value,
- S32 max_bytes)
-{
- int count = 0;
- const S32 BUF_LEN = 20;
- char buf[BUF_LEN]; /* Flawfinder: ignore */
- istr.get(buf, BUF_LEN - 1, ')');
- count += istr.gcount();
- int c = istr.get();
- c = istr.get();
- count += 2;
- if(((c == '"') || (c == '\'')) && (buf[0] == '('))
- {
- // We probably have a valid raw string. determine
- // the size, and read it.
- // *FIX: This is memory inefficient.
- S32 len = strtol(buf + 1, NULL, 0);
- if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE;
- std::vector<char> buf;
- if(len)
- {
- buf.resize(len);
- count += fullread(istr, (char *)&buf[0], len);
- value.assign(buf.begin(), buf.end());
- }
- c = istr.get();
- ++count;
- if(!((c == '"') || (c == '\'')))
- {
- return LLSDParser::PARSE_FAILURE;
- }
- }
- else
- {
- return LLSDParser::PARSE_FAILURE;
- }
- return count;
-}
-
-static const char* NOTATION_STRING_CHARACTERS[256] =
-{
- "\\x00", // 0
- "\\x01", // 1
- "\\x02", // 2
- "\\x03", // 3
- "\\x04", // 4
- "\\x05", // 5
- "\\x06", // 6
- "\\a", // 7
- "\\b", // 8
- "\\t", // 9
- "\\n", // 10
- "\\v", // 11
- "\\f", // 12
- "\\r", // 13
- "\\x0e", // 14
- "\\x0f", // 15
- "\\x10", // 16
- "\\x11", // 17
- "\\x12", // 18
- "\\x13", // 19
- "\\x14", // 20
- "\\x15", // 21
- "\\x16", // 22
- "\\x17", // 23
- "\\x18", // 24
- "\\x19", // 25
- "\\x1a", // 26
- "\\x1b", // 27
- "\\x1c", // 28
- "\\x1d", // 29
- "\\x1e", // 30
- "\\x1f", // 31
- " ", // 32
- "!", // 33
- "\"", // 34
- "#", // 35
- "$", // 36
- "%", // 37
- "&", // 38
- "\\'", // 39
- "(", // 40
- ")", // 41
- "*", // 42
- "+", // 43
- ",", // 44
- "-", // 45
- ".", // 46
- "/", // 47
- "0", // 48
- "1", // 49
- "2", // 50
- "3", // 51
- "4", // 52
- "5", // 53
- "6", // 54
- "7", // 55
- "8", // 56
- "9", // 57
- ":", // 58
- ";", // 59
- "<", // 60
- "=", // 61
- ">", // 62
- "?", // 63
- "@", // 64
- "A", // 65
- "B", // 66
- "C", // 67
- "D", // 68
- "E", // 69
- "F", // 70
- "G", // 71
- "H", // 72
- "I", // 73
- "J", // 74
- "K", // 75
- "L", // 76
- "M", // 77
- "N", // 78
- "O", // 79
- "P", // 80
- "Q", // 81
- "R", // 82
- "S", // 83
- "T", // 84
- "U", // 85
- "V", // 86
- "W", // 87
- "X", // 88
- "Y", // 89
- "Z", // 90
- "[", // 91
- "\\\\", // 92
- "]", // 93
- "^", // 94
- "_", // 95
- "`", // 96
- "a", // 97
- "b", // 98
- "c", // 99
- "d", // 100
- "e", // 101
- "f", // 102
- "g", // 103
- "h", // 104
- "i", // 105
- "j", // 106
- "k", // 107
- "l", // 108
- "m", // 109
- "n", // 110
- "o", // 111
- "p", // 112
- "q", // 113
- "r", // 114
- "s", // 115
- "t", // 116
- "u", // 117
- "v", // 118
- "w", // 119
- "x", // 120
- "y", // 121
- "z", // 122
- "{", // 123
- "|", // 124
- "}", // 125
- "~", // 126
- "\\x7f", // 127
- "\\x80", // 128
- "\\x81", // 129
- "\\x82", // 130
- "\\x83", // 131
- "\\x84", // 132
- "\\x85", // 133
- "\\x86", // 134
- "\\x87", // 135
- "\\x88", // 136
- "\\x89", // 137
- "\\x8a", // 138
- "\\x8b", // 139
- "\\x8c", // 140
- "\\x8d", // 141
- "\\x8e", // 142
- "\\x8f", // 143
- "\\x90", // 144
- "\\x91", // 145
- "\\x92", // 146
- "\\x93", // 147
- "\\x94", // 148
- "\\x95", // 149
- "\\x96", // 150
- "\\x97", // 151
- "\\x98", // 152
- "\\x99", // 153
- "\\x9a", // 154
- "\\x9b", // 155
- "\\x9c", // 156
- "\\x9d", // 157
- "\\x9e", // 158
- "\\x9f", // 159
- "\\xa0", // 160
- "\\xa1", // 161
- "\\xa2", // 162
- "\\xa3", // 163
- "\\xa4", // 164
- "\\xa5", // 165
- "\\xa6", // 166
- "\\xa7", // 167
- "\\xa8", // 168
- "\\xa9", // 169
- "\\xaa", // 170
- "\\xab", // 171
- "\\xac", // 172
- "\\xad", // 173
- "\\xae", // 174
- "\\xaf", // 175
- "\\xb0", // 176
- "\\xb1", // 177
- "\\xb2", // 178
- "\\xb3", // 179
- "\\xb4", // 180
- "\\xb5", // 181
- "\\xb6", // 182
- "\\xb7", // 183
- "\\xb8", // 184
- "\\xb9", // 185
- "\\xba", // 186
- "\\xbb", // 187
- "\\xbc", // 188
- "\\xbd", // 189
- "\\xbe", // 190
- "\\xbf", // 191
- "\\xc0", // 192
- "\\xc1", // 193
- "\\xc2", // 194
- "\\xc3", // 195
- "\\xc4", // 196
- "\\xc5", // 197
- "\\xc6", // 198
- "\\xc7", // 199
- "\\xc8", // 200
- "\\xc9", // 201
- "\\xca", // 202
- "\\xcb", // 203
- "\\xcc", // 204
- "\\xcd", // 205
- "\\xce", // 206
- "\\xcf", // 207
- "\\xd0", // 208
- "\\xd1", // 209
- "\\xd2", // 210
- "\\xd3", // 211
- "\\xd4", // 212
- "\\xd5", // 213
- "\\xd6", // 214
- "\\xd7", // 215
- "\\xd8", // 216
- "\\xd9", // 217
- "\\xda", // 218
- "\\xdb", // 219
- "\\xdc", // 220
- "\\xdd", // 221
- "\\xde", // 222
- "\\xdf", // 223
- "\\xe0", // 224
- "\\xe1", // 225
- "\\xe2", // 226
- "\\xe3", // 227
- "\\xe4", // 228
- "\\xe5", // 229
- "\\xe6", // 230
- "\\xe7", // 231
- "\\xe8", // 232
- "\\xe9", // 233
- "\\xea", // 234
- "\\xeb", // 235
- "\\xec", // 236
- "\\xed", // 237
- "\\xee", // 238
- "\\xef", // 239
- "\\xf0", // 240
- "\\xf1", // 241
- "\\xf2", // 242
- "\\xf3", // 243
- "\\xf4", // 244
- "\\xf5", // 245
- "\\xf6", // 246
- "\\xf7", // 247
- "\\xf8", // 248
- "\\xf9", // 249
- "\\xfa", // 250
- "\\xfb", // 251
- "\\xfc", // 252
- "\\xfd", // 253
- "\\xfe", // 254
- "\\xff" // 255
-};
-
-void serialize_string(const std::string& value, std::ostream& str)
-{
- std::string::const_iterator it = value.begin();
- std::string::const_iterator end = value.end();
- U8 c;
- for(; it != end; ++it)
- {
- c = (U8)(*it);
- str << NOTATION_STRING_CHARACTERS[c];
- }
-}
-
-int deserialize_boolean(
- std::istream& istr,
- LLSD& data,
- const std::string& compare,
- bool value)
-{
- //
- // this method is a little goofy, because it gets the stream at
- // the point where the t or f has already been
- // consumed. Basically, parse for a patch to the string passed in
- // starting at index 1. If it's a match:
- // * assign data to value
- // * return the number of bytes read
- // otherwise:
- // * set data to LLSD::null
- // * return LLSDParser::PARSE_FAILURE (-1)
- //
- int bytes_read = 0;
- std::string::size_type ii = 0;
- char c = istr.peek();
- while((++ii < compare.size())
- && (tolower(c) == (int)compare[ii])
- && istr.good())
- {
- istr.ignore();
- ++bytes_read;
- c = istr.peek();
- }
- if(compare.size() != ii)
- {
- data.clear();
- return LLSDParser::PARSE_FAILURE;
- }
- data = value;
- return bytes_read;
-}
-
-std::ostream& operator<<(std::ostream& s, const LLSD& llsd)
-{
- s << LLSDNotationStreamer(llsd);
- return s;
-}
-
-
-//dirty little zippers -- yell at davep if these are horrid
-
-//return a string containing gzipped bytes of binary serialized LLSD
-// VERY inefficient -- creates several copies of LLSD block in memory
-std::string zip_llsd(LLSD& data)
-{
- std::stringstream llsd_strm;
-
- LLSDSerialize::toBinary(data, llsd_strm);
-
- const U32 CHUNK = 65536;
-
- z_stream strm;
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
-
- S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION);
- if (ret != Z_OK)
- {
- llwarns << "Failed to compress LLSD block." << llendl;
- return std::string();
- }
-
- std::string source = llsd_strm.str();
-
- U8 out[CHUNK];
-
- strm.avail_in = source.size();
- strm.next_in = (U8*) source.data();
- U8* output = NULL;
-
- U32 cur_size = 0;
-
- U32 have = 0;
-
- do
- {
- strm.avail_out = CHUNK;
- strm.next_out = out;
-
- ret = deflate(&strm, Z_FINISH);
- if (ret == Z_OK || ret == Z_STREAM_END)
- { //copy result into output
- if (strm.avail_out >= CHUNK)
- {
- free(output);
- llwarns << "Failed to compress LLSD block." << llendl;
- return std::string();
- }
-
- have = CHUNK-strm.avail_out;
- output = (U8*) realloc(output, cur_size+have);
- memcpy(output+cur_size, out, have);
- cur_size += have;
- }
- else
- {
- free(output);
- llwarns << "Failed to compress LLSD block." << llendl;
- return std::string();
- }
- }
- while (ret == Z_OK);
-
- std::string::size_type size = cur_size;
-
- std::string result((char*) output, size);
- deflateEnd(&strm);
- free(output);
-
-#if 0 //verify results work with unzip_llsd
- std::istringstream test(result);
- LLSD test_sd;
- if (!unzip_llsd(test_sd, test, result.size()))
- {
- llerrs << "Invalid compression result!" << llendl;
- }
-#endif
-
- return result;
-}
-
-//decompress a block of LLSD from provided istream
-// not very efficient -- creats a copy of decompressed LLSD block in memory
-// and deserializes from that copy using LLSDSerialize
-bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
-{
- U8* result = NULL;
- U32 cur_size = 0;
- z_stream strm;
-
- const U32 CHUNK = 65536;
-
- U8 *in = new U8[size];
- is.read((char*) in, size);
-
- U8 out[CHUNK];
-
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = size;
- strm.next_in = in;
-
- S32 ret = inflateInit(&strm);
-
- do
- {
- strm.avail_out = CHUNK;
- strm.next_out = out;
- ret = inflate(&strm, Z_NO_FLUSH);
- if (ret == Z_STREAM_ERROR)
- {
- inflateEnd(&strm);
- free(result);
- delete [] in;
- return false;
- }
-
- switch (ret)
- {
- case Z_NEED_DICT:
- ret = Z_DATA_ERROR;
- case Z_DATA_ERROR:
- case Z_MEM_ERROR:
- inflateEnd(&strm);
- free(result);
- delete [] in;
- return false;
- break;
- }
-
- U32 have = CHUNK-strm.avail_out;
-
- result = (U8*) realloc(result, cur_size + have);
- memcpy(result+cur_size, out, have);
- cur_size += have;
-
- } while (ret == Z_OK);
-
- inflateEnd(&strm);
- delete [] in;
-
- if (ret != Z_STREAM_END)
- {
- free(result);
- return false;
- }
-
- //result now points to the decompressed LLSD block
- {
- std::string res_str((char*) result, cur_size);
-
- std::string deprecated_header("<? LLSD/Binary ?>");
-
- if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
- {
- res_str = res_str.substr(deprecated_header.size()+1, cur_size);
- }
- cur_size = res_str.size();
-
- std::istringstream istr(res_str);
-
- if (!LLSDSerialize::fromBinary(data, istr, cur_size))
- {
- llwarns << "Failed to unzip LLSD block" << llendl;
- free(result);
- return false;
- }
- }
-
- free(result);
- return true;
-}
-//This unzip function will only work with a gzip header and trailer - while the contents
-//of the actual compressed data is the same for either format (gzip vs zlib ), the headers
-//and trailers are different for the formats.
-U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size )
-{
- U8* result = NULL;
- U32 cur_size = 0;
- z_stream strm;
-
- const U32 CHUNK = 0x4000;
-
- U8 *in = new U8[size];
- is.read((char*) in, size);
-
- U8 out[CHUNK];
-
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = size;
- strm.next_in = in;
-
-
- S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP );
- do
- {
- strm.avail_out = CHUNK;
- strm.next_out = out;
- ret = inflate(&strm, Z_NO_FLUSH);
- if (ret == Z_STREAM_ERROR)
- {
- inflateEnd(&strm);
- free(result);
- delete [] in;
- valid = false;
- }
-
- switch (ret)
- {
- case Z_NEED_DICT:
- ret = Z_DATA_ERROR;
- case Z_DATA_ERROR:
- case Z_MEM_ERROR:
- inflateEnd(&strm);
- free(result);
- delete [] in;
- valid = false;
- break;
- }
-
- U32 have = CHUNK-strm.avail_out;
-
- result = (U8*) realloc(result, cur_size + have);
- memcpy(result+cur_size, out, have);
- cur_size += have;
-
- } while (ret == Z_OK);
-
- inflateEnd(&strm);
- delete [] in;
-
- if (ret != Z_STREAM_END)
- {
- free(result);
- valid = false;
- return NULL;
- }
-
- //result now points to the decompressed LLSD block
- {
- outsize= cur_size;
- valid = true;
- }
-
- return result;
-}
-
-
+
+/**
+ * LLSDSerialize
+ */
+
+// static
+void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options)
+{
+ LLPointer<LLSDFormatter> f = NULL;
+
+ switch (type)
+ {
+ case LLSD_BINARY:
+ str << "<? " << LLSD_BINARY_HEADER << " ?>\n";
+ f = new LLSDBinaryFormatter;
+ break;
+
+ case LLSD_XML:
+ str << "<? " << LLSD_XML_HEADER << " ?>\n";
+ f = new LLSDXMLFormatter;
+ break;
+
+ default:
+ llwarns << "serialize request for unknown ELLSD_Serialize" << llendl;
+ }
+
+ if (f.notNull())
+ {
+ f->format(sd, str, options);
+ }
+}
+
+// static
+bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
+{
+ LLPointer<LLSDParser> p = NULL;
+ char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */
+ int i;
+ int inbuf = 0;
+ bool legacy_no_header = false;
+ bool fail_if_not_legacy = false;
+ std::string header;
+
+ /*
+ * Get the first line before anything.
+ */
+ str.get(hdr_buf, MAX_HDR_LEN, '\n');
+ if (str.fail())
+ {
+ str.clear();
+ fail_if_not_legacy = true;
+ }
+
+ if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */
+ {
+ legacy_no_header = true;
+ inbuf = (int)str.gcount();
+ }
+ else
+ {
+ if (fail_if_not_legacy)
+ goto fail;
+ /*
+ * Remove the newline chars
+ */
+ for (i = 0; i < MAX_HDR_LEN; i++)
+ {
+ if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' ||
+ hdr_buf[i] == '\n')
+ {
+ hdr_buf[i] = 0;
+ break;
+ }
+ }
+ header = hdr_buf;
+
+ std::string::size_type start = std::string::npos;
+ std::string::size_type end = std::string::npos;
+ start = header.find_first_not_of("<? ");
+ if (start != std::string::npos)
+ {
+ end = header.find_first_of(" ?", start);
+ }
+ if ((start == std::string::npos) || (end == std::string::npos))
+ goto fail;
+
+ header = header.substr(start, end - start);
+ ws(str);
+ }
+ /*
+ * Create the parser as appropriate
+ */
+ if (legacy_no_header)
+ { // Create a LLSD XML parser, and parse the first chunk read above
+ LLSDXMLParser* x = new LLSDXMLParser();
+ x->parsePart(hdr_buf, inbuf); // Parse the first part that was already read
+ x->parseLines(str, sd); // Parse the rest of it
+ delete x;
+ return true;
+ }
+
+ if (header == LLSD_BINARY_HEADER)
+ {
+ p = new LLSDBinaryParser;
+ }
+ else if (header == LLSD_XML_HEADER)
+ {
+ p = new LLSDXMLParser;
+ }
+ else
+ {
+ llwarns << "deserialize request for unknown ELLSD_Serialize" << llendl;
+ }
+
+ if (p.notNull())
+ {
+ p->parse(str, sd, max_bytes);
+ return true;
+ }
+
+fail:
+ llwarns << "deserialize LLSD parse failure" << llendl;
+ return false;
+}
+
+/**
+ * Endian handlers
+ */
+#if LL_BIG_ENDIAN
+U64 ll_htonll(U64 hostlonglong) { return hostlonglong; }
+U64 ll_ntohll(U64 netlonglong) { return netlonglong; }
+F64 ll_htond(F64 hostlonglong) { return hostlonglong; }
+F64 ll_ntohd(F64 netlonglong) { return netlonglong; }
+#else
+// I read some comments one a indicating that doing an integer add
+// here would be faster than a bitwise or. For now, the or has
+// programmer clarity, since the intended outcome matches the
+// operation.
+U64 ll_htonll(U64 hostlonglong)
+{
+ return ((U64)(htonl((U32)((hostlonglong >> 32) & 0xFFFFFFFF))) |
+ ((U64)(htonl((U32)(hostlonglong & 0xFFFFFFFF))) << 32));
+}
+U64 ll_ntohll(U64 netlonglong)
+{
+ return ((U64)(ntohl((U32)((netlonglong >> 32) & 0xFFFFFFFF))) |
+ ((U64)(ntohl((U32)(netlonglong & 0xFFFFFFFF))) << 32));
+}
+union LLEndianSwapper
+{
+ F64 d;
+ U64 i;
+};
+F64 ll_htond(F64 hostdouble)
+{
+ LLEndianSwapper tmp;
+ tmp.d = hostdouble;
+ tmp.i = ll_htonll(tmp.i);
+ return tmp.d;
+}
+F64 ll_ntohd(F64 netdouble)
+{
+ LLEndianSwapper tmp;
+ tmp.d = netdouble;
+ tmp.i = ll_ntohll(tmp.i);
+ return tmp.d;
+}
+#endif
+
+/**
+ * Local functions.
+ */
+/**
+ * @brief Figure out what kind of string it is (raw or delimited) and handoff.
+ *
+ * @param istr The stream to read from.
+ * @param value [out] The string which was found.
+ * @param max_bytes The maximum possible length of the string. Passing in
+ * a negative value will skip this check.
+ * @return Returns number of bytes read off of the stream. Returns
+ * PARSE_FAILURE (-1) on failure.
+ */
+int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes);
+
+/**
+ * @brief Parse a delimited string.
+ *
+ * @param istr The stream to read from, with the delimiter already popped.
+ * @param value [out] The string which was found.
+ * @param d The delimiter to use.
+ * @return Returns number of bytes read off of the stream. Returns
+ * PARSE_FAILURE (-1) on failure.
+ */
+int deserialize_string_delim(std::istream& istr, std::string& value, char d);
+
+/**
+ * @brief Read a raw string off the stream.
+ *
+ * @param istr The stream to read from, with the (len) parameter
+ * leading the stream.
+ * @param value [out] The string which was found.
+ * @param d The delimiter to use.
+ * @param max_bytes The maximum possible length of the string. Passing in
+ * a negative value will skip this check.
+ * @return Returns number of bytes read off of the stream. Returns
+ * PARSE_FAILURE (-1) on failure.
+ */
+int deserialize_string_raw(
+ std::istream& istr,
+ std::string& value,
+ S32 max_bytes);
+
+/**
+ * @brief helper method for dealing with the different notation boolean format.
+ *
+ * @param istr The stream to read from with the leading character stripped.
+ * @param data [out] the result of the parse.
+ * @param compare The string to compare the boolean against
+ * @param vale The value to assign to data if the parse succeeds.
+ * @return Returns number of bytes read off of the stream. Returns
+ * PARSE_FAILURE (-1) on failure.
+ */
+int deserialize_boolean(
+ std::istream& istr,
+ LLSD& data,
+ const std::string& compare,
+ bool value);
+
+/**
+ * @brief Do notation escaping of a string to an ostream.
+ *
+ * @param value The string to escape and serialize
+ * @param str The stream to serialize to.
+ */
+void serialize_string(const std::string& value, std::ostream& str);
+
+
+/**
+ * Local constants.
+ */
+static const std::string NOTATION_TRUE_SERIAL("true");
+static const std::string NOTATION_FALSE_SERIAL("false");
+
+static const char BINARY_TRUE_SERIAL = '1';
+static const char BINARY_FALSE_SERIAL = '0';
+
+
+/**
+ * LLSDParser
+ */
+LLSDParser::LLSDParser()
+ : mCheckLimits(true), mMaxBytesLeft(0), mParseLines(false)
+{
+}
+
+// virtual
+LLSDParser::~LLSDParser()
+{ }
+
+S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes)
+{
+ mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true;
+ mMaxBytesLeft = max_bytes;
+ return doParse(istr, data);
+}
+
+
+// Parse using routine to get() lines, faster than parse()
+S32 LLSDParser::parseLines(std::istream& istr, LLSD& data)
+{
+ mCheckLimits = false;
+ mParseLines = true;
+ return doParse(istr, data);
+}
+
+
+int LLSDParser::get(std::istream& istr) const
+{
+ if(mCheckLimits) --mMaxBytesLeft;
+ return istr.get();
+}
+
+std::istream& LLSDParser::get(
+ std::istream& istr,
+ char* s,
+ std::streamsize n,
+ char delim) const
+{
+ istr.get(s, n, delim);
+ if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount();
+ return istr;
+}
+
+std::istream& LLSDParser::get(
+ std::istream& istr,
+ std::streambuf& sb,
+ char delim) const
+{
+ istr.get(sb, delim);
+ if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount();
+ return istr;
+}
+
+std::istream& LLSDParser::ignore(std::istream& istr) const
+{
+ istr.ignore();
+ if(mCheckLimits) --mMaxBytesLeft;
+ return istr;
+}
+
+std::istream& LLSDParser::putback(std::istream& istr, char c) const
+{
+ istr.putback(c);
+ if(mCheckLimits) ++mMaxBytesLeft;
+ return istr;
+}
+
+std::istream& LLSDParser::read(
+ std::istream& istr,
+ char* s,
+ std::streamsize n) const
+{
+ istr.read(s, n);
+ if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount();
+ return istr;
+}
+
+void LLSDParser::account(S32 bytes) const
+{
+ if(mCheckLimits) mMaxBytesLeft -= bytes;
+}
+
+
+/**
+ * LLSDNotationParser
+ */
+LLSDNotationParser::LLSDNotationParser()
+{
+}
+
+// virtual
+LLSDNotationParser::~LLSDNotationParser()
+{ }
+
+// virtual
+S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
+{
+ // map: { string:object, string:object }
+ // array: [ object, object, object ]
+ // undef: !
+ // boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE
+ // integer: i####
+ // real: r####
+ // uuid: u####
+ // string: "g'day" | 'have a "nice" day' | s(size)"raw data"
+ // uri: l"escaped"
+ // date: d"YYYY-MM-DDTHH:MM:SS.FFZ"
+ // binary: b##"ff3120ab1" | b(size)"raw data"
+ char c;
+ c = istr.peek();
+ while(isspace(c))
+ {
+ // pop the whitespace.
+ c = get(istr);
+ c = istr.peek();
+ continue;
+ }
+ if(!istr.good())
+ {
+ return 0;
+ }
+ S32 parse_count = 1;
+ switch(c)
+ {
+ case '{':
+ {
+ S32 child_count = parseMap(istr, data);
+ if((child_count == PARSE_FAILURE) || data.isUndefined())
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ parse_count += child_count;
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading map." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case '[':
+ {
+ S32 child_count = parseArray(istr, data);
+ if((child_count == PARSE_FAILURE) || data.isUndefined())
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ parse_count += child_count;
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading array." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case '!':
+ c = get(istr);
+ data.clear();
+ break;
+
+ case '0':
+ c = get(istr);
+ data = false;
+ break;
+
+ case 'F':
+ case 'f':
+ ignore(istr);
+ c = istr.peek();
+ if(isalpha(c))
+ {
+ int cnt = deserialize_boolean(
+ istr,
+ data,
+ NOTATION_FALSE_SERIAL,
+ false);
+ if(PARSE_FAILURE == cnt) parse_count = cnt;
+ else account(cnt);
+ }
+ else
+ {
+ data = false;
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading boolean." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+
+ case '1':
+ c = get(istr);
+ data = true;
+ break;
+
+ case 'T':
+ case 't':
+ ignore(istr);
+ c = istr.peek();
+ if(isalpha(c))
+ {
+ int cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true);
+ if(PARSE_FAILURE == cnt) parse_count = cnt;
+ else account(cnt);
+ }
+ else
+ {
+ data = true;
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading boolean." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+
+ case 'i':
+ {
+ c = get(istr);
+ S32 integer = 0;
+ istr >> integer;
+ data = integer;
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading integer." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'r':
+ {
+ c = get(istr);
+ F64 real = 0.0;
+ istr >> real;
+ data = real;
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading real." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'u':
+ {
+ c = get(istr);
+ LLUUID id;
+ istr >> id;
+ data = id;
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading uuid." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case '\"':
+ case '\'':
+ case 's':
+ if(!parseString(istr, data))
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading string." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+
+ case 'l':
+ {
+ c = get(istr); // pop the 'l'
+ c = get(istr); // pop the delimiter
+ std::string str;
+ int cnt = deserialize_string_delim(istr, str, c);
+ if(PARSE_FAILURE == cnt)
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ data = LLURI(str);
+ account(cnt);
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading link." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'd':
+ {
+ c = get(istr); // pop the 'd'
+ c = get(istr); // pop the delimiter
+ std::string str;
+ int cnt = deserialize_string_delim(istr, str, c);
+ if(PARSE_FAILURE == cnt)
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ data = LLDate(str);
+ account(cnt);
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading date." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'b':
+ if(!parseBinary(istr, data))
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading data." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+
+ default:
+ parse_count = PARSE_FAILURE;
+ llinfos << "Unrecognized character while parsing: int(" << (int)c
+ << ")" << llendl;
+ break;
+ }
+ if(PARSE_FAILURE == parse_count)
+ {
+ data.clear();
+ }
+ return parse_count;
+}
+
+S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const
+{
+ // map: { string:object, string:object }
+ map = LLSD::emptyMap();
+ S32 parse_count = 0;
+ char c = get(istr);
+ if(c == '{')
+ {
+ // eat commas, white
+ bool found_name = false;
+ std::string name;
+ c = get(istr);
+ while(c != '}' && istr.good())
+ {
+ if(!found_name)
+ {
+ if((c == '\"') || (c == '\'') || (c == 's'))
+ {
+ putback(istr, c);
+ found_name = true;
+ int count = deserialize_string(istr, name, mMaxBytesLeft);
+ if(PARSE_FAILURE == count) return PARSE_FAILURE;
+ account(count);
+ }
+ c = get(istr);
+ }
+ else
+ {
+ if(isspace(c) || (c == ':'))
+ {
+ c = get(istr);
+ continue;
+ }
+ putback(istr, c);
+ LLSD child;
+ S32 count = doParse(istr, child);
+ if(count > 0)
+ {
+ // There must be a value for every key, thus
+ // child_count must be greater than 0.
+ parse_count += count;
+ map.insert(name, child);
+ }
+ else
+ {
+ return PARSE_FAILURE;
+ }
+ found_name = false;
+ c = get(istr);
+ }
+ }
+ if(c != '}')
+ {
+ map.clear();
+ return PARSE_FAILURE;
+ }
+ }
+ return parse_count;
+}
+
+S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const
+{
+ // array: [ object, object, object ]
+ array = LLSD::emptyArray();
+ S32 parse_count = 0;
+ char c = get(istr);
+ if(c == '[')
+ {
+ // eat commas, white
+ c = get(istr);
+ while((c != ']') && istr.good())
+ {
+ LLSD child;
+ if(isspace(c) || (c == ','))
+ {
+ c = get(istr);
+ continue;
+ }
+ putback(istr, c);
+ S32 count = doParse(istr, child);
+ if(PARSE_FAILURE == count)
+ {
+ return PARSE_FAILURE;
+ }
+ else
+ {
+ parse_count += count;
+ array.append(child);
+ }
+ c = get(istr);
+ }
+ if(c != ']')
+ {
+ return PARSE_FAILURE;
+ }
+ }
+ return parse_count;
+}
+
+bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
+{
+ std::string value;
+ int count = deserialize_string(istr, value, mMaxBytesLeft);
+ if(PARSE_FAILURE == count) return false;
+ account(count);
+ data = value;
+ return true;
+}
+
+bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
+{
+ // binary: b##"ff3120ab1"
+ // or: b(len)"..."
+
+ // I want to manually control those values here to make sure the
+ // parser doesn't break when someone changes a constant somewhere
+ // else.
+ const U32 BINARY_BUFFER_SIZE = 256;
+ const U32 STREAM_GET_COUNT = 255;
+
+ // need to read the base out.
+ char buf[BINARY_BUFFER_SIZE]; /* Flawfinder: ignore */
+ get(istr, buf, STREAM_GET_COUNT, '"');
+ char c = get(istr);
+ if(c != '"') return false;
+ if(0 == strncmp("b(", buf, 2))
+ {
+ // We probably have a valid raw binary stream. determine
+ // the size, and read it.
+ S32 len = strtol(buf + 2, NULL, 0);
+ if(mCheckLimits && (len > mMaxBytesLeft)) return false;
+ std::vector<U8> value;
+ if(len)
+ {
+ value.resize(len);
+ account((int)fullread(istr, (char *)&value[0], len));
+ }
+ c = get(istr); // strip off the trailing double-quote
+ data = value;
+ }
+ else if(0 == strncmp("b64", buf, 3))
+ {
+ // *FIX: A bit inefficient, but works for now. To make the
+ // format better, I would need to add a hint into the
+ // serialization format that indicated how long it was.
+ std::stringstream coded_stream;
+ get(istr, *(coded_stream.rdbuf()), '\"');
+ c = get(istr);
+ std::string encoded(coded_stream.str());
+ S32 len = apr_base64_decode_len(encoded.c_str());
+ std::vector<U8> value;
+ if(len)
+ {
+ value.resize(len);
+ len = apr_base64_decode_binary(&value[0], encoded.c_str());
+ value.resize(len);
+ }
+ data = value;
+ }
+ else if(0 == strncmp("b16", buf, 3))
+ {
+ // yay, base 16. We pop the next character which is either a
+ // double quote or base 16 data. If it's a double quote, we're
+ // done parsing. If it's not, put the data back, and read the
+ // stream until the next double quote.
+ char* read; /*Flawfinder: ignore*/
+ U8 byte;
+ U8 byte_buffer[BINARY_BUFFER_SIZE];
+ U8* write;
+ std::vector<U8> value;
+ c = get(istr);
+ while(c != '"')
+ {
+ putback(istr, c);
+ read = buf;
+ write = byte_buffer;
+ get(istr, buf, STREAM_GET_COUNT, '"');
+ c = get(istr);
+ while(*read != '\0') /*Flawfinder: ignore*/
+ {
+ byte = hex_as_nybble(*read++);
+ byte = byte << 4;
+ byte |= hex_as_nybble(*read++);
+ *write++ = byte;
+ }
+ // copy the data out of the byte buffer
+ value.insert(value.end(), byte_buffer, write);
+ }
+ data = value;
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+}
+
+
+/**
+ * LLSDBinaryParser
+ */
+LLSDBinaryParser::LLSDBinaryParser()
+{
+}
+
+// virtual
+LLSDBinaryParser::~LLSDBinaryParser()
+{
+}
+
+// virtual
+S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
+{
+/**
+ * Undefined: '!'<br>
+ * Boolean: 't' for true 'f' for false<br>
+ * Integer: 'i' + 4 bytes network byte order<br>
+ * Real: 'r' + 8 bytes IEEE double<br>
+ * UUID: 'u' + 16 byte unsigned integer<br>
+ * String: 's' + 4 byte integer size + string<br>
+ * strings also secretly support the notation format
+ * Date: 'd' + 8 byte IEEE double for seconds since epoch<br>
+ * URI: 'l' + 4 byte integer size + string uri<br>
+ * Binary: 'b' + 4 byte integer size + binary data<br>
+ * Array: '[' + 4 byte integer size + all values + ']'<br>
+ * Map: '{' + 4 byte integer size every(key + value) + '}'<br>
+ * map keys are serialized as s + 4 byte integer size + string or in the
+ * notation format.
+ */
+ char c;
+ c = get(istr);
+ if(!istr.good())
+ {
+ return 0;
+ }
+ S32 parse_count = 1;
+ switch(c)
+ {
+ case '{':
+ {
+ S32 child_count = parseMap(istr, data);
+ if((child_count == PARSE_FAILURE) || data.isUndefined())
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ parse_count += child_count;
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading binary map." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case '[':
+ {
+ S32 child_count = parseArray(istr, data);
+ if((child_count == PARSE_FAILURE) || data.isUndefined())
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ parse_count += child_count;
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading binary array." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case '!':
+ data.clear();
+ break;
+
+ case '0':
+ data = false;
+ break;
+
+ case '1':
+ data = true;
+ break;
+
+ case 'i':
+ {
+ U32 value_nbo = 0;
+ read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
+ data = (S32)ntohl(value_nbo);
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading binary integer." << llendl;
+ }
+ break;
+ }
+
+ case 'r':
+ {
+ F64 real_nbo = 0.0;
+ read(istr, (char*)&real_nbo, sizeof(F64)); /*Flawfinder: ignore*/
+ data = ll_ntohd(real_nbo);
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading binary real." << llendl;
+ }
+ break;
+ }
+
+ case 'u':
+ {
+ LLUUID id;
+ read(istr, (char*)(&id.mData), UUID_BYTES); /*Flawfinder: ignore*/
+ data = id;
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading binary uuid." << llendl;
+ }
+ break;
+ }
+
+ case '\'':
+ case '"':
+ {
+ std::string value;
+ int cnt = deserialize_string_delim(istr, value, c);
+ if(PARSE_FAILURE == cnt)
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ data = value;
+ account(cnt);
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading binary (notation-style) string."
+ << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 's':
+ {
+ std::string value;
+ if(parseString(istr, value))
+ {
+ data = value;
+ }
+ else
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading binary string." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'l':
+ {
+ std::string value;
+ if(parseString(istr, value))
+ {
+ data = LLURI(value);
+ }
+ else
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading binary link." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'd':
+ {
+ F64 real = 0.0;
+ read(istr, (char*)&real, sizeof(F64)); /*Flawfinder: ignore*/
+ data = LLDate(real);
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading binary date." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ case 'b':
+ {
+ // We probably have a valid raw binary stream. determine
+ // the size, and read it.
+ U32 size_nbo = 0;
+ read(istr, (char*)&size_nbo, sizeof(U32)); /*Flawfinder: ignore*/
+ S32 size = (S32)ntohl(size_nbo);
+ if(mCheckLimits && (size > mMaxBytesLeft))
+ {
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ std::vector<U8> value;
+ if(size > 0)
+ {
+ value.resize(size);
+ account((int)fullread(istr, (char*)&value[0], size));
+ }
+ data = value;
+ }
+ if(istr.fail())
+ {
+ llinfos << "STREAM FAILURE reading binary." << llendl;
+ parse_count = PARSE_FAILURE;
+ }
+ break;
+ }
+
+ default:
+ parse_count = PARSE_FAILURE;
+ llinfos << "Unrecognized character while parsing: int(" << (int)c
+ << ")" << llendl;
+ break;
+ }
+ if(PARSE_FAILURE == parse_count)
+ {
+ data.clear();
+ }
+ return parse_count;
+}
+
+S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const
+{
+ map = LLSD::emptyMap();
+ U32 value_nbo = 0;
+ read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
+ S32 size = (S32)ntohl(value_nbo);
+ S32 parse_count = 0;
+ S32 count = 0;
+ char c = get(istr);
+ while(c != '}' && (count < size) && istr.good())
+ {
+ std::string name;
+ switch(c)
+ {
+ case 'k':
+ if(!parseString(istr, name))
+ {
+ return PARSE_FAILURE;
+ }
+ break;
+ case '\'':
+ case '"':
+ {
+ int cnt = deserialize_string_delim(istr, name, c);
+ if(PARSE_FAILURE == cnt) return PARSE_FAILURE;
+ account(cnt);
+ break;
+ }
+ }
+ LLSD child;
+ S32 child_count = doParse(istr, child);
+ if(child_count > 0)
+ {
+ // There must be a value for every key, thus child_count
+ // must be greater than 0.
+ parse_count += child_count;
+ map.insert(name, child);
+ }
+ else
+ {
+ return PARSE_FAILURE;
+ }
+ ++count;
+ c = get(istr);
+ }
+ if((c != '}') || (count < size))
+ {
+ // Make sure it is correctly terminated and we parsed as many
+ // as were said to be there.
+ return PARSE_FAILURE;
+ }
+ return parse_count;
+}
+
+S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
+{
+ array = LLSD::emptyArray();
+ U32 value_nbo = 0;
+ read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
+ S32 size = (S32)ntohl(value_nbo);
+
+ // *FIX: This would be a good place to reserve some space in the
+ // array...
+
+ S32 parse_count = 0;
+ S32 count = 0;
+ char c = istr.peek();
+ while((c != ']') && (count < size) && istr.good())
+ {
+ LLSD child;
+ S32 child_count = doParse(istr, child);
+ if(PARSE_FAILURE == child_count)
+ {
+ return PARSE_FAILURE;
+ }
+ if(child_count)
+ {
+ parse_count += child_count;
+ array.append(child);
+ }
+ ++count;
+ c = istr.peek();
+ }
+ c = get(istr);
+ if((c != ']') || (count < size))
+ {
+ // Make sure it is correctly terminated and we parsed as many
+ // as were said to be there.
+ return PARSE_FAILURE;
+ }
+ return parse_count;
+}
+
+bool LLSDBinaryParser::parseString(
+ std::istream& istr,
+ std::string& value) const
+{
+ // *FIX: This is memory inefficient.
+ U32 value_nbo = 0;
+ read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/
+ S32 size = (S32)ntohl(value_nbo);
+ if(mCheckLimits && (size > mMaxBytesLeft)) return false;
+ std::vector<char> buf;
+ if(size)
+ {
+ buf.resize(size);
+ account((int)fullread(istr, &buf[0], size));
+ value.assign(buf.begin(), buf.end());
+ }
+ return true;
+}
+
+
+/**
+ * LLSDFormatter
+ */
+LLSDFormatter::LLSDFormatter() :
+ mBoolAlpha(false)
+{
+}
+
+// virtual
+LLSDFormatter::~LLSDFormatter()
+{ }
+
+void LLSDFormatter::boolalpha(bool alpha)
+{
+ mBoolAlpha = alpha;
+}
+
+void LLSDFormatter::realFormat(const std::string& format)
+{
+ mRealFormat = format;
+}
+
+void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const
+{
+ std::string buffer = llformat(mRealFormat.c_str(), real);
+ ostr << buffer;
+}
+
+/**
+ * LLSDNotationFormatter
+ */
+LLSDNotationFormatter::LLSDNotationFormatter()
+{
+}
+
+// virtual
+LLSDNotationFormatter::~LLSDNotationFormatter()
+{ }
+
+// static
+std::string LLSDNotationFormatter::escapeString(const std::string& in)
+{
+ std::ostringstream ostr;
+ serialize_string(in, ostr);
+ return ostr.str();
+}
+
+// virtual
+S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
+{
+ S32 format_count = 1;
+ switch(data.type())
+ {
+ case LLSD::TypeMap:
+ {
+ ostr << "{";
+ bool need_comma = false;
+ LLSD::map_const_iterator iter = data.beginMap();
+ LLSD::map_const_iterator end = data.endMap();
+ for(; iter != end; ++iter)
+ {
+ if(need_comma) ostr << ",";
+ need_comma = true;
+ ostr << '\'';
+ serialize_string((*iter).first, ostr);
+ ostr << "':";
+ format_count += format((*iter).second, ostr);
+ }
+ ostr << "}";
+ break;
+ }
+
+ case LLSD::TypeArray:
+ {
+ ostr << "[";
+ bool need_comma = false;
+ LLSD::array_const_iterator iter = data.beginArray();
+ LLSD::array_const_iterator end = data.endArray();
+ for(; iter != end; ++iter)
+ {
+ if(need_comma) ostr << ",";
+ need_comma = true;
+ format_count += format(*iter, ostr);
+ }
+ ostr << "]";
+ break;
+ }
+
+ case LLSD::TypeUndefined:
+ ostr << "!";
+ break;
+
+ case LLSD::TypeBoolean:
+ if(mBoolAlpha ||
+#if( LL_WINDOWS || __GNUC__ > 2)
+ (ostr.flags() & std::ios::boolalpha)
+#else
+ (ostr.flags() & 0x0100)
+#endif
+ )
+ {
+ ostr << (data.asBoolean()
+ ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL);
+ }
+ else
+ {
+ ostr << (data.asBoolean() ? 1 : 0);
+ }
+ break;
+
+ case LLSD::TypeInteger:
+ ostr << "i" << data.asInteger();
+ break;
+
+ case LLSD::TypeReal:
+ ostr << "r";
+ if(mRealFormat.empty())
+ {
+ ostr << data.asReal();
+ }
+ else
+ {
+ formatReal(data.asReal(), ostr);
+ }
+ break;
+
+ case LLSD::TypeUUID:
+ ostr << "u" << data.asUUID();
+ break;
+
+ case LLSD::TypeString:
+ ostr << '\'';
+ serialize_string(data.asString(), ostr);
+ ostr << '\'';
+ break;
+
+ case LLSD::TypeDate:
+ ostr << "d\"" << data.asDate() << "\"";
+ break;
+
+ case LLSD::TypeURI:
+ ostr << "l\"";
+ serialize_string(data.asString(), ostr);
+ ostr << "\"";
+ break;
+
+ case LLSD::TypeBinary:
+ {
+ // *FIX: memory inefficient.
+ std::vector<U8> buffer = data.asBinary();
+ ostr << "b(" << buffer.size() << ")\"";
+ if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
+ ostr << "\"";
+ break;
+ }
+
+ default:
+ // *NOTE: This should never happen.
+ ostr << "!";
+ break;
+ }
+ return format_count;
+}
+
+
+/**
+ * LLSDBinaryFormatter
+ */
+LLSDBinaryFormatter::LLSDBinaryFormatter()
+{
+}
+
+// virtual
+LLSDBinaryFormatter::~LLSDBinaryFormatter()
+{ }
+
+// virtual
+S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
+{
+ S32 format_count = 1;
+ switch(data.type())
+ {
+ case LLSD::TypeMap:
+ {
+ ostr.put('{');
+ U32 size_nbo = htonl(data.size());
+ ostr.write((const char*)(&size_nbo), sizeof(U32));
+ LLSD::map_const_iterator iter = data.beginMap();
+ LLSD::map_const_iterator end = data.endMap();
+ for(; iter != end; ++iter)
+ {
+ ostr.put('k');
+ formatString((*iter).first, ostr);
+ format_count += format((*iter).second, ostr);
+ }
+ ostr.put('}');
+ break;
+ }
+
+ case LLSD::TypeArray:
+ {
+ ostr.put('[');
+ U32 size_nbo = htonl(data.size());
+ ostr.write((const char*)(&size_nbo), sizeof(U32));
+ LLSD::array_const_iterator iter = data.beginArray();
+ LLSD::array_const_iterator end = data.endArray();
+ for(; iter != end; ++iter)
+ {
+ format_count += format(*iter, ostr);
+ }
+ ostr.put(']');
+ break;
+ }
+
+ case LLSD::TypeUndefined:
+ ostr.put('!');
+ break;
+
+ case LLSD::TypeBoolean:
+ if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL);
+ else ostr.put(BINARY_FALSE_SERIAL);
+ break;
+
+ case LLSD::TypeInteger:
+ {
+ ostr.put('i');
+ U32 value_nbo = htonl(data.asInteger());
+ ostr.write((const char*)(&value_nbo), sizeof(U32));
+ break;
+ }
+
+ case LLSD::TypeReal:
+ {
+ ostr.put('r');
+ F64 value_nbo = ll_htond(data.asReal());
+ ostr.write((const char*)(&value_nbo), sizeof(F64));
+ break;
+ }
+
+ case LLSD::TypeUUID:
+ ostr.put('u');
+ ostr.write((const char*)(&(data.asUUID().mData)), UUID_BYTES);
+ break;
+
+ case LLSD::TypeString:
+ ostr.put('s');
+ formatString(data.asString(), ostr);
+ break;
+
+ case LLSD::TypeDate:
+ {
+ ostr.put('d');
+ F64 value = data.asReal();
+ ostr.write((const char*)(&value), sizeof(F64));
+ break;
+ }
+
+ case LLSD::TypeURI:
+ ostr.put('l');
+ formatString(data.asString(), ostr);
+ break;
+
+ case LLSD::TypeBinary:
+ {
+ // *FIX: memory inefficient.
+ ostr.put('b');
+ std::vector<U8> buffer = data.asBinary();
+ U32 size_nbo = htonl(buffer.size());
+ ostr.write((const char*)(&size_nbo), sizeof(U32));
+ if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
+ break;
+ }
+
+ default:
+ // *NOTE: This should never happen.
+ ostr.put('!');
+ break;
+ }
+ return format_count;
+}
+
+void LLSDBinaryFormatter::formatString(
+ const std::string& string,
+ std::ostream& ostr) const
+{
+ U32 size_nbo = htonl(string.size());
+ ostr.write((const char*)(&size_nbo), sizeof(U32));
+ ostr.write(string.c_str(), string.size());
+}
+
+/**
+ * local functions
+ */
+int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes)
+{
+ int c = istr.get();
+ if(istr.fail())
+ {
+ // No data in stream, bail out but mention the character we
+ // grabbed.
+ return LLSDParser::PARSE_FAILURE;
+ }
+
+ int rv = LLSDParser::PARSE_FAILURE;
+ switch(c)
+ {
+ case '\'':
+ case '"':
+ rv = deserialize_string_delim(istr, value, c);
+ break;
+ case 's':
+ // technically, less than max_bytes, but this is just meant to
+ // catch egregious protocol errors. parse errors will be
+ // caught in the case of incorrect counts.
+ rv = deserialize_string_raw(istr, value, max_bytes);
+ break;
+ default:
+ break;
+ }
+ if(LLSDParser::PARSE_FAILURE == rv) return rv;
+ return rv + 1; // account for the character grabbed at the top.
+}
+
+int deserialize_string_delim(
+ std::istream& istr,
+ std::string& value,
+ char delim)
+{
+ std::ostringstream write_buffer;
+ bool found_escape = false;
+ bool found_hex = false;
+ bool found_digit = false;
+ U8 byte = 0;
+ int count = 0;
+
+ while (true)
+ {
+ int next_byte = istr.get();
+ ++count;
+
+ if(istr.fail())
+ {
+ // If our stream is empty, break out
+ value = write_buffer.str();
+ return LLSDParser::PARSE_FAILURE;
+ }
+
+ char next_char = (char)next_byte; // Now that we know it's not EOF
+
+ if(found_escape)
+ {
+ // next character(s) is a special sequence.
+ if(found_hex)
+ {
+ if(found_digit)
+ {
+ found_digit = false;
+ found_hex = false;
+ found_escape = false;
+ byte = byte << 4;
+ byte |= hex_as_nybble(next_char);
+ write_buffer << byte;
+ byte = 0;
+ }
+ else
+ {
+ // next character is the first nybble of
+ //
+ found_digit = true;
+ byte = hex_as_nybble(next_char);
+ }
+ }
+ else if(next_char == 'x')
+ {
+ found_hex = true;
+ }
+ else
+ {
+ switch(next_char)
+ {
+ case 'a':
+ write_buffer << '\a';
+ break;
+ case 'b':
+ write_buffer << '\b';
+ break;
+ case 'f':
+ write_buffer << '\f';
+ break;
+ case 'n':
+ write_buffer << '\n';
+ break;
+ case 'r':
+ write_buffer << '\r';
+ break;
+ case 't':
+ write_buffer << '\t';
+ break;
+ case 'v':
+ write_buffer << '\v';
+ break;
+ default:
+ write_buffer << next_char;
+ break;
+ }
+ found_escape = false;
+ }
+ }
+ else if(next_char == '\\')
+ {
+ found_escape = true;
+ }
+ else if(next_char == delim)
+ {
+ break;
+ }
+ else
+ {
+ write_buffer << next_char;
+ }
+ }
+
+ value = write_buffer.str();
+ return count;
+}
+
+int deserialize_string_raw(
+ std::istream& istr,
+ std::string& value,
+ S32 max_bytes)
+{
+ int count = 0;
+ const S32 BUF_LEN = 20;
+ char buf[BUF_LEN]; /* Flawfinder: ignore */
+ istr.get(buf, BUF_LEN - 1, ')');
+ count += (int)istr.gcount();
+ int c = istr.get();
+ c = istr.get();
+ count += 2;
+ if(((c == '"') || (c == '\'')) && (buf[0] == '('))
+ {
+ // We probably have a valid raw string. determine
+ // the size, and read it.
+ // *FIX: This is memory inefficient.
+ S32 len = strtol(buf + 1, NULL, 0);
+ if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE;
+ std::vector<char> buf;
+ if(len)
+ {
+ buf.resize(len);
+ count += (int)fullread(istr, (char *)&buf[0], len);
+ value.assign(buf.begin(), buf.end());
+ }
+ c = istr.get();
+ ++count;
+ if(!((c == '"') || (c == '\'')))
+ {
+ return LLSDParser::PARSE_FAILURE;
+ }
+ }
+ else
+ {
+ return LLSDParser::PARSE_FAILURE;
+ }
+ return count;
+}
+
+static const char* NOTATION_STRING_CHARACTERS[256] =
+{
+ "\\x00", // 0
+ "\\x01", // 1
+ "\\x02", // 2
+ "\\x03", // 3
+ "\\x04", // 4
+ "\\x05", // 5
+ "\\x06", // 6
+ "\\a", // 7
+ "\\b", // 8
+ "\\t", // 9
+ "\\n", // 10
+ "\\v", // 11
+ "\\f", // 12
+ "\\r", // 13
+ "\\x0e", // 14
+ "\\x0f", // 15
+ "\\x10", // 16
+ "\\x11", // 17
+ "\\x12", // 18
+ "\\x13", // 19
+ "\\x14", // 20
+ "\\x15", // 21
+ "\\x16", // 22
+ "\\x17", // 23
+ "\\x18", // 24
+ "\\x19", // 25
+ "\\x1a", // 26
+ "\\x1b", // 27
+ "\\x1c", // 28
+ "\\x1d", // 29
+ "\\x1e", // 30
+ "\\x1f", // 31
+ " ", // 32
+ "!", // 33
+ "\"", // 34
+ "#", // 35
+ "$", // 36
+ "%", // 37
+ "&", // 38
+ "\\'", // 39
+ "(", // 40
+ ")", // 41
+ "*", // 42
+ "+", // 43
+ ",", // 44
+ "-", // 45
+ ".", // 46
+ "/", // 47
+ "0", // 48
+ "1", // 49
+ "2", // 50
+ "3", // 51
+ "4", // 52
+ "5", // 53
+ "6", // 54
+ "7", // 55
+ "8", // 56
+ "9", // 57
+ ":", // 58
+ ";", // 59
+ "<", // 60
+ "=", // 61
+ ">", // 62
+ "?", // 63
+ "@", // 64
+ "A", // 65
+ "B", // 66
+ "C", // 67
+ "D", // 68
+ "E", // 69
+ "F", // 70
+ "G", // 71
+ "H", // 72
+ "I", // 73
+ "J", // 74
+ "K", // 75
+ "L", // 76
+ "M", // 77
+ "N", // 78
+ "O", // 79
+ "P", // 80
+ "Q", // 81
+ "R", // 82
+ "S", // 83
+ "T", // 84
+ "U", // 85
+ "V", // 86
+ "W", // 87
+ "X", // 88
+ "Y", // 89
+ "Z", // 90
+ "[", // 91
+ "\\\\", // 92
+ "]", // 93
+ "^", // 94
+ "_", // 95
+ "`", // 96
+ "a", // 97
+ "b", // 98
+ "c", // 99
+ "d", // 100
+ "e", // 101
+ "f", // 102
+ "g", // 103
+ "h", // 104
+ "i", // 105
+ "j", // 106
+ "k", // 107
+ "l", // 108
+ "m", // 109
+ "n", // 110
+ "o", // 111
+ "p", // 112
+ "q", // 113
+ "r", // 114
+ "s", // 115
+ "t", // 116
+ "u", // 117
+ "v", // 118
+ "w", // 119
+ "x", // 120
+ "y", // 121
+ "z", // 122
+ "{", // 123
+ "|", // 124
+ "}", // 125
+ "~", // 126
+ "\\x7f", // 127
+ "\\x80", // 128
+ "\\x81", // 129
+ "\\x82", // 130
+ "\\x83", // 131
+ "\\x84", // 132
+ "\\x85", // 133
+ "\\x86", // 134
+ "\\x87", // 135
+ "\\x88", // 136
+ "\\x89", // 137
+ "\\x8a", // 138
+ "\\x8b", // 139
+ "\\x8c", // 140
+ "\\x8d", // 141
+ "\\x8e", // 142
+ "\\x8f", // 143
+ "\\x90", // 144
+ "\\x91", // 145
+ "\\x92", // 146
+ "\\x93", // 147
+ "\\x94", // 148
+ "\\x95", // 149
+ "\\x96", // 150
+ "\\x97", // 151
+ "\\x98", // 152
+ "\\x99", // 153
+ "\\x9a", // 154
+ "\\x9b", // 155
+ "\\x9c", // 156
+ "\\x9d", // 157
+ "\\x9e", // 158
+ "\\x9f", // 159
+ "\\xa0", // 160
+ "\\xa1", // 161
+ "\\xa2", // 162
+ "\\xa3", // 163
+ "\\xa4", // 164
+ "\\xa5", // 165
+ "\\xa6", // 166
+ "\\xa7", // 167
+ "\\xa8", // 168
+ "\\xa9", // 169
+ "\\xaa", // 170
+ "\\xab", // 171
+ "\\xac", // 172
+ "\\xad", // 173
+ "\\xae", // 174
+ "\\xaf", // 175
+ "\\xb0", // 176
+ "\\xb1", // 177
+ "\\xb2", // 178
+ "\\xb3", // 179
+ "\\xb4", // 180
+ "\\xb5", // 181
+ "\\xb6", // 182
+ "\\xb7", // 183
+ "\\xb8", // 184
+ "\\xb9", // 185
+ "\\xba", // 186
+ "\\xbb", // 187
+ "\\xbc", // 188
+ "\\xbd", // 189
+ "\\xbe", // 190
+ "\\xbf", // 191
+ "\\xc0", // 192
+ "\\xc1", // 193
+ "\\xc2", // 194
+ "\\xc3", // 195
+ "\\xc4", // 196
+ "\\xc5", // 197
+ "\\xc6", // 198
+ "\\xc7", // 199
+ "\\xc8", // 200
+ "\\xc9", // 201
+ "\\xca", // 202
+ "\\xcb", // 203
+ "\\xcc", // 204
+ "\\xcd", // 205
+ "\\xce", // 206
+ "\\xcf", // 207
+ "\\xd0", // 208
+ "\\xd1", // 209
+ "\\xd2", // 210
+ "\\xd3", // 211
+ "\\xd4", // 212
+ "\\xd5", // 213
+ "\\xd6", // 214
+ "\\xd7", // 215
+ "\\xd8", // 216
+ "\\xd9", // 217
+ "\\xda", // 218
+ "\\xdb", // 219
+ "\\xdc", // 220
+ "\\xdd", // 221
+ "\\xde", // 222
+ "\\xdf", // 223
+ "\\xe0", // 224
+ "\\xe1", // 225
+ "\\xe2", // 226
+ "\\xe3", // 227
+ "\\xe4", // 228
+ "\\xe5", // 229
+ "\\xe6", // 230
+ "\\xe7", // 231
+ "\\xe8", // 232
+ "\\xe9", // 233
+ "\\xea", // 234
+ "\\xeb", // 235
+ "\\xec", // 236
+ "\\xed", // 237
+ "\\xee", // 238
+ "\\xef", // 239
+ "\\xf0", // 240
+ "\\xf1", // 241
+ "\\xf2", // 242
+ "\\xf3", // 243
+ "\\xf4", // 244
+ "\\xf5", // 245
+ "\\xf6", // 246
+ "\\xf7", // 247
+ "\\xf8", // 248
+ "\\xf9", // 249
+ "\\xfa", // 250
+ "\\xfb", // 251
+ "\\xfc", // 252
+ "\\xfd", // 253
+ "\\xfe", // 254
+ "\\xff" // 255
+};
+
+void serialize_string(const std::string& value, std::ostream& str)
+{
+ std::string::const_iterator it = value.begin();
+ std::string::const_iterator end = value.end();
+ U8 c;
+ for(; it != end; ++it)
+ {
+ c = (U8)(*it);
+ str << NOTATION_STRING_CHARACTERS[c];
+ }
+}
+
+int deserialize_boolean(
+ std::istream& istr,
+ LLSD& data,
+ const std::string& compare,
+ bool value)
+{
+ //
+ // this method is a little goofy, because it gets the stream at
+ // the point where the t or f has already been
+ // consumed. Basically, parse for a patch to the string passed in
+ // starting at index 1. If it's a match:
+ // * assign data to value
+ // * return the number of bytes read
+ // otherwise:
+ // * set data to LLSD::null
+ // * return LLSDParser::PARSE_FAILURE (-1)
+ //
+ int bytes_read = 0;
+ std::string::size_type ii = 0;
+ char c = istr.peek();
+ while((++ii < compare.size())
+ && (tolower(c) == (int)compare[ii])
+ && istr.good())
+ {
+ istr.ignore();
+ ++bytes_read;
+ c = istr.peek();
+ }
+ if(compare.size() != ii)
+ {
+ data.clear();
+ return LLSDParser::PARSE_FAILURE;
+ }
+ data = value;
+ return bytes_read;
+}
+
+std::ostream& operator<<(std::ostream& s, const LLSD& llsd)
+{
+ s << LLSDNotationStreamer(llsd);
+ return s;
+}
+
+
+//dirty little zippers -- yell at davep if these are horrid
+
+//return a string containing gzipped bytes of binary serialized LLSD
+// VERY inefficient -- creates several copies of LLSD block in memory
+std::string zip_llsd(LLSD& data)
+{
+ std::stringstream llsd_strm;
+
+ LLSDSerialize::toBinary(data, llsd_strm);
+
+ const U32 CHUNK = 65536;
+
+ z_stream strm;
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+
+ S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION);
+ if (ret != Z_OK)
+ {
+ llwarns << "Failed to compress LLSD block." << llendl;
+ return std::string();
+ }
+
+ std::string source = llsd_strm.str();
+
+ U8 out[CHUNK];
+
+ strm.avail_in = source.size();
+ strm.next_in = (U8*) source.data();
+ U8* output = NULL;
+
+ U32 cur_size = 0;
+
+ U32 have = 0;
+
+ do
+ {
+ strm.avail_out = CHUNK;
+ strm.next_out = out;
+
+ ret = deflate(&strm, Z_FINISH);
+ if (ret == Z_OK || ret == Z_STREAM_END)
+ { //copy result into output
+ if (strm.avail_out >= CHUNK)
+ {
+ free(output);
+ llwarns << "Failed to compress LLSD block." << llendl;
+ return std::string();
+ }
+
+ have = CHUNK-strm.avail_out;
+ output = (U8*) realloc(output, cur_size+have);
+ memcpy(output+cur_size, out, have);
+ cur_size += have;
+ }
+ else
+ {
+ free(output);
+ llwarns << "Failed to compress LLSD block." << llendl;
+ return std::string();
+ }
+ }
+ while (ret == Z_OK);
+
+ std::string::size_type size = cur_size;
+
+ std::string result((char*) output, size);
+ deflateEnd(&strm);
+ free(output);
+
+#if 0 //verify results work with unzip_llsd
+ std::istringstream test(result);
+ LLSD test_sd;
+ if (!unzip_llsd(test_sd, test, result.size()))
+ {
+ llerrs << "Invalid compression result!" << llendl;
+ }
+#endif
+
+ return result;
+}
+
+//decompress a block of LLSD from provided istream
+// not very efficient -- creats a copy of decompressed LLSD block in memory
+// and deserializes from that copy using LLSDSerialize
+bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
+{
+ U8* result = NULL;
+ U32 cur_size = 0;
+ z_stream strm;
+
+ const U32 CHUNK = 65536;
+
+ U8 *in = new U8[size];
+ is.read((char*) in, size);
+
+ U8 out[CHUNK];
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = size;
+ strm.next_in = in;
+
+ S32 ret = inflateInit(&strm);
+
+ do
+ {
+ strm.avail_out = CHUNK;
+ strm.next_out = out;
+ ret = inflate(&strm, Z_NO_FLUSH);
+ if (ret == Z_STREAM_ERROR)
+ {
+ inflateEnd(&strm);
+ free(result);
+ delete [] in;
+ return false;
+ }
+
+ switch (ret)
+ {
+ case Z_NEED_DICT:
+ ret = Z_DATA_ERROR;
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ inflateEnd(&strm);
+ free(result);
+ delete [] in;
+ return false;
+ break;
+ }
+
+ U32 have = CHUNK-strm.avail_out;
+
+ result = (U8*) realloc(result, cur_size + have);
+ memcpy(result+cur_size, out, have);
+ cur_size += have;
+
+ } while (ret == Z_OK);
+
+ inflateEnd(&strm);
+ delete [] in;
+
+ if (ret != Z_STREAM_END)
+ {
+ free(result);
+ return false;
+ }
+
+ //result now points to the decompressed LLSD block
+ {
+ std::string res_str((char*) result, cur_size);
+
+ std::string deprecated_header("<? LLSD/Binary ?>");
+
+ if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
+ {
+ res_str = res_str.substr(deprecated_header.size()+1, cur_size);
+ }
+ cur_size = res_str.size();
+
+ std::istringstream istr(res_str);
+
+ if (!LLSDSerialize::fromBinary(data, istr, cur_size))
+ {
+ llwarns << "Failed to unzip LLSD block" << llendl;
+ free(result);
+ return false;
+ }
+ }
+
+ free(result);
+ return true;
+}
+//This unzip function will only work with a gzip header and trailer - while the contents
+//of the actual compressed data is the same for either format (gzip vs zlib ), the headers
+//and trailers are different for the formats.
+U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size )
+{
+ U8* result = NULL;
+ U32 cur_size = 0;
+ z_stream strm;
+
+ const U32 CHUNK = 0x4000;
+
+ U8 *in = new U8[size];
+ is.read((char*) in, size);
+
+ U8 out[CHUNK];
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = size;
+ strm.next_in = in;
+
+
+ S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP );
+ do
+ {
+ strm.avail_out = CHUNK;
+ strm.next_out = out;
+ ret = inflate(&strm, Z_NO_FLUSH);
+ if (ret == Z_STREAM_ERROR)
+ {
+ inflateEnd(&strm);
+ free(result);
+ delete [] in;
+ valid = false;
+ }
+
+ switch (ret)
+ {
+ case Z_NEED_DICT:
+ ret = Z_DATA_ERROR;
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ inflateEnd(&strm);
+ free(result);
+ delete [] in;
+ valid = false;
+ break;
+ }
+
+ U32 have = CHUNK-strm.avail_out;
+
+ result = (U8*) realloc(result, cur_size + have);
+ memcpy(result+cur_size, out, have);
+ cur_size += have;
+
+ } while (ret == Z_OK);
+
+ inflateEnd(&strm);
+ delete [] in;
+
+ if (ret != Z_STREAM_END)
+ {
+ free(result);
+ valid = false;
+ return NULL;
+ }
+
+ //result now points to the decompressed LLSD block
+ {
+ outsize= cur_size;
+ valid = true;
+ }
+
+ return result;
+}
+
+
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index be9db53906..34b3dbb99a 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -464,7 +464,7 @@ S32 LLSDXMLParser::Impl::parseLines(std::istream& input, LLSD& data)
}
}
- status = XML_ParseBuffer(mParser, num_read, false);
+ status = XML_ParseBuffer(mParser, (int)num_read, false);
if (status == XML_STATUS_ERROR)
{
break;
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index 65c7297cbf..532d3f9341 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -308,7 +308,7 @@ class LLSDParam<T> \
{ \
public: \
LLSDParam(const LLSD& value): \
- _value(value.AS()) \
+ _value((T)value.AS()) \
{} \
\
operator T() const { return _value; } \
diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp
index b2c495d093..057257057f 100644
--- a/indra/llcommon/llstat.cpp
+++ b/indra/llcommon/llstat.cpp
@@ -593,7 +593,7 @@ void LLStatTime::stop()
{
if ( LLStatAccum::SCALE_PER_FRAME == scale )
{
- return mTotalTimeInFrame;
+ return (F32)mTotalTimeInFrame;
}
else
{
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 38054b636e..9ebc6de7f4 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -83,7 +83,7 @@ U32 micro_sleep(U64 us, U32 max_yields)
{
// max_yields is unused; just fiddle with it to avoid warnings.
max_yields = 0;
- ms_sleep(us / 1000);
+ ms_sleep((U32)(us / 1000));
return 0;
}
#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index 3461aa3e6c..d6dcde4b9f 100644
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -250,7 +250,7 @@ void LLCrashLogger::gatherFiles()
if(minidump_stream.is_open())
{
minidump_stream.seekg(0, std::ios::end);
- size_t length = minidump_stream.tellg();
+ size_t length = (size_t)minidump_stream.tellg();
minidump_stream.seekg(0, std::ios::beg);
LLSD::Binary data;
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index cc8cb66d73..8241746a74 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -501,10 +501,10 @@ void LLImageCompressionTester::outputTestRecord(LLSD *sd)
F32 decompressionRate = 0.0f;
F32 compressionRate = 0.0f;
- F32 totalkBInDecompression = (F32)(mTotalBytesInDecompression) / 1000.0;
- F32 totalkBOutDecompression = (F32)(mTotalBytesOutDecompression) / 1000.0;
- F32 totalkBInCompression = (F32)(mTotalBytesInCompression) / 1000.0;
- F32 totalkBOutCompression = (F32)(mTotalBytesOutCompression) / 1000.0;
+ F32 totalkBInDecompression = (F32)(mTotalBytesInDecompression) / 1000.f;
+ F32 totalkBOutDecompression = (F32)(mTotalBytesOutDecompression) / 1000.f;
+ F32 totalkBInCompression = (F32)(mTotalBytesInCompression) / 1000.f;
+ F32 totalkBOutCompression = (F32)(mTotalBytesOutCompression) / 1000.f;
if (!is_approx_zero(mTotalTimeDecompression))
{
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 76760aa414..fbf23bc3f0 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -405,7 +405,7 @@ U32 LLInventoryItem::getCRC32() const
//lldebugs << "7 crc: " << std::hex << crc << std::dec << llendl;
crc += mSaleInfo.getCRC32();
//lldebugs << "8 crc: " << std::hex << crc << std::dec << llendl;
- crc += mCreationDate;
+ crc += (U32)mCreationDate;
//lldebugs << "9 crc: " << std::hex << crc << std::dec << llendl;
return crc;
}
@@ -521,7 +521,7 @@ void LLInventoryItem::packMessage(LLMessageSystem* msg) const
mSaleInfo.packMessage(msg);
msg->addStringFast(_PREHASH_Name, mName);
msg->addStringFast(_PREHASH_Description, mDescription);
- msg->addS32Fast(_PREHASH_CreationDate, mCreationDate);
+ msg->addS32Fast(_PREHASH_CreationDate, (S32)mCreationDate);
U32 crc = getCRC32();
msg->addU32Fast(_PREHASH_CRC, crc);
}
diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h
index bd9c8c2519..e0ad270266 100644
--- a/indra/llmath/llcalcparser.h
+++ b/indra/llmath/llcalcparser.h
@@ -174,7 +174,7 @@ private:
F32 _log(const F32& a) const { return log(a); }
F32 _exp(const F32& a) const { return exp(a); }
F32 _fabs(const F32& a) const { return fabs(a); }
- F32 _floor(const F32& a) const { return llfloor(a); }
+ F32 _floor(const F32& a) const { return (F32)llfloor(a); }
F32 _ceil(const F32& a) const { return llceil(a); }
F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); }
diff --git a/indra/llmath/llcoord.h b/indra/llmath/llcoord.h
index 706ad92787..1f617e649e 100644
--- a/indra/llmath/llcoord.h
+++ b/indra/llmath/llcoord.h
@@ -26,80 +26,80 @@
#ifndef LL_LLCOORD_H
#define LL_LLCOORD_H
+struct LLCoordCommon
+{
+ LLCoordCommon(S32 x, S32 y) : mX(x), mY(y) {}
+ LLCoordCommon() : mX(0), mY(0) {}
+ S32 mX;
+ S32 mY;
+};
+
// A two-dimensional pixel value
-class LLCoord
+template<typename COORD_FRAME>
+class LLCoord : protected COORD_FRAME
{
public:
- S32 mX;
- S32 mY;
+ typedef LLCoord<COORD_FRAME> self_t;
+ typename COORD_FRAME::value_t mX;
+ typename COORD_FRAME::value_t mY;
LLCoord(): mX(0), mY(0)
{}
LLCoord(S32 x, S32 y): mX(x), mY(y)
{}
- virtual ~LLCoord()
- {}
- virtual void set(S32 x, S32 y) { mX = x; mY = y; }
-};
+ LLCoord(const LLCoordCommon& other)
+ {
+ COORD_FRAME::convertFromCommon(other);
+ }
+ LLCoordCommon convert() const
+ {
+ return COORD_FRAME::convertToCommon();
+ }
-// GL coordinates start in the client region of a window,
-// with left, bottom = 0, 0
-class LLCoordGL : public LLCoord
-{
-public:
- LLCoordGL() : LLCoord()
- {}
- LLCoordGL(S32 x, S32 y) : LLCoord(x, y)
- {}
- bool operator==(const LLCoordGL& other) const { return mX == other.mX && mY == other.mY; }
- bool operator!=(const LLCoordGL& other) const { return !(*this == other); }
-};
+ void set(S32 x, S32 y) { mX = x; mY = y;}
+ bool operator==(const self_t& other) const { return mX == other.mX && mY == other.mY; }
+ bool operator!=(const self_t& other) const { return !(*this == other); }
-//bool operator ==(const LLCoordGL& a, const LLCoordGL& b);
+};
-// Window coords include things like window borders,
-// menu regions, etc.
-class LLCoordWindow : public LLCoord
+struct LL_COORD_TYPE_GL
{
-public:
- LLCoordWindow() : LLCoord()
- {}
- LLCoordWindow(S32 x, S32 y) : LLCoord(x, y)
- {}
- bool operator==(const LLCoordWindow& other) const { return mX == other.mX && mY == other.mY; }
- bool operator!=(const LLCoordWindow& other) const { return !(*this == other); }
-};
+ typedef S32 value_t;
+ LLCoordCommon convertToCommon() const
+ {
+ const LLCoord<LL_COORD_TYPE_GL>& self = static_cast<const LLCoord<LL_COORD_TYPE_GL>&>(*this);
+ return LLCoordCommon(self.mX, self.mY);
+ }
+
+ void convertFromCommon(const LLCoordCommon& from)
+ {
+ LLCoord<LL_COORD_TYPE_GL>& self = static_cast<LLCoord<LL_COORD_TYPE_GL>&>(*this);
+ self.mX = from.mX;
+ self.mY = from.mY;
+ }
+};
-// Screen coords start at left, top = 0, 0
-class LLCoordScreen : public LLCoord
+struct LL_COORD_TYPE_WINDOW
{
-public:
- LLCoordScreen() : LLCoord()
- {}
- LLCoordScreen(S32 x, S32 y) : LLCoord(x, y)
- {}
- bool operator==(const LLCoordScreen& other) const { return mX == other.mX && mY == other.mY; }
- bool operator!=(const LLCoordScreen& other) const { return !(*this == other); }
+ typedef S32 value_t;
+
+ LLCoordCommon convertToCommon() const;
+ void convertFromCommon(const LLCoordCommon& from);
};
-class LLCoordFont : public LLCoord
+struct LL_COORD_TYPE_SCREEN
{
-public:
- F32 mZ;
-
- LLCoordFont() : LLCoord(), mZ(0.f)
- {}
- LLCoordFont(S32 x, S32 y, F32 z = 0) : LLCoord(x,y), mZ(z)
- {}
-
- void set(S32 x, S32 y) { LLCoord::set(x,y); mZ = 0.f; }
- void set(S32 x, S32 y, F32 z) { mX = x; mY = y; mZ = z; }
- bool operator==(const LLCoordFont& other) const { return mX == other.mX && mY == other.mY; }
- bool operator!=(const LLCoordFont& other) const { return !(*this == other); }
+ typedef S32 value_t;
+
+ LLCoordCommon convertToCommon() const;
+ void convertFromCommon(const LLCoordCommon& from);
};
-
+
+typedef LLCoord<LL_COORD_TYPE_GL> LLCoordGL;
+typedef LLCoord<LL_COORD_TYPE_WINDOW> LLCoordWindow;
+typedef LLCoord<LL_COORD_TYPE_SCREEN> LLCoordScreen;
#endif
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 761fc171c4..cc9744756f 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2904,7 +2904,7 @@ F32 LLVolume::sculptGetSurfaceArea()
// compute the area of the quad by taking the length of the cross product of the two triangles
LLVector3 cross1 = (p1 - p2) % (p1 - p3);
LLVector3 cross2 = (p4 - p2) % (p4 - p3);
- area += (cross1.magVec() + cross2.magVec()) / 2.0;
+ area += (cross1.magVec() + cross2.magVec()) / 2.f;
}
}
@@ -5890,7 +5890,7 @@ F32 find_vertex_score(LLVCacheVertexData& data)
}
//bonus points for having low valence
- F32 valence_boost = powf(data.mActiveTriangles, -FindVertexScore_ValenceBoostPower);
+ F32 valence_boost = powf((F32)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower);
score += FindVertexScore_ValenceBoostScale * valence_boost;
return score;
diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp
index bad4deb4de..6a1b4143cf 100644
--- a/indra/llmath/m4math.cpp
+++ b/indra/llmath/m4math.cpp
@@ -858,25 +858,25 @@ LLSD LLMatrix4::getValue() const
void LLMatrix4::setValue(const LLSD& data)
{
- mMatrix[0][0] = data[0].asReal();
- mMatrix[0][1] = data[1].asReal();
- mMatrix[0][2] = data[2].asReal();
- mMatrix[0][3] = data[3].asReal();
-
- mMatrix[1][0] = data[4].asReal();
- mMatrix[1][1] = data[5].asReal();
- mMatrix[1][2] = data[6].asReal();
- mMatrix[1][3] = data[7].asReal();
-
- mMatrix[2][0] = data[8].asReal();
- mMatrix[2][1] = data[9].asReal();
- mMatrix[2][2] = data[10].asReal();
- mMatrix[2][3] = data[11].asReal();
-
- mMatrix[3][0] = data[12].asReal();
- mMatrix[3][1] = data[13].asReal();
- mMatrix[3][2] = data[14].asReal();
- mMatrix[3][3] = data[15].asReal();
+ mMatrix[0][0] = (F32)data[0].asReal();
+ mMatrix[0][1] = (F32)data[1].asReal();
+ mMatrix[0][2] = (F32)data[2].asReal();
+ mMatrix[0][3] = (F32)data[3].asReal();
+
+ mMatrix[1][0] = (F32)data[4].asReal();
+ mMatrix[1][1] = (F32)data[5].asReal();
+ mMatrix[1][2] = (F32)data[6].asReal();
+ mMatrix[1][3] = (F32)data[7].asReal();
+
+ mMatrix[2][0] = (F32)data[8].asReal();
+ mMatrix[2][1] = (F32)data[9].asReal();
+ mMatrix[2][2] = (F32)data[10].asReal();
+ mMatrix[2][3] = (F32)data[11].asReal();
+
+ mMatrix[3][0] = (F32)data[12].asReal();
+ mMatrix[3][1] = (F32)data[13].asReal();
+ mMatrix[3][2] = (F32)data[14].asReal();
+ mMatrix[3][3] = (F32)data[15].asReal();
}
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 3bcaffc275..b93d429feb 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -271,10 +271,10 @@ void LLCurl::Easy::releaseEasyHandle(CURL* handle)
if(sFreeHandles.size() < MAX_NUM_FREE_HANDLES)
{
- sFreeHandles.insert(handle);
- }
- else
- {
+ sFreeHandles.insert(handle);
+ }
+ else
+ {
LLCurl::deleteEasyHandle(handle) ;
}
}
@@ -453,9 +453,9 @@ size_t curlReadCallback(char* data, size_t size, size_t nmemb, void* user_data)
LLCurl::Easy* easy = (LLCurl::Easy*)user_data;
S32 n = size * nmemb;
- S32 startpos = easy->getInput().tellg();
+ S32 startpos = (S32)easy->getInput().tellg();
easy->getInput().seekg(0, std::ios::end);
- S32 endpos = easy->getInput().tellg();
+ S32 endpos = (S32)easy->getInput().tellg();
easy->getInput().seekg(startpos, std::ios::beg);
S32 maxn = endpos - startpos;
n = llmin(n, maxn);
@@ -560,16 +560,16 @@ LLCurl::Multi::Multi(F32 idle_time_out)
}
//llassert_always(mCurlMultiHandle);
-
+
if(mCurlMultiHandle)
{
- if(LLCurl::getCurlThread()->getThreaded())
- {
- mMutexp = new LLMutex(NULL) ;
- mDeletionMutexp = new LLMutex(NULL) ;
- mEasyMutexp = new LLMutex(NULL) ;
- }
- LLCurl::getCurlThread()->addMulti(this) ;
+ if(LLCurl::getCurlThread()->getThreaded())
+ {
+ mMutexp = new LLMutex(NULL) ;
+ mDeletionMutexp = new LLMutex(NULL) ;
+ mEasyMutexp = new LLMutex(NULL) ;
+ }
+ LLCurl::getCurlThread()->addMulti(this) ;
mIdleTimeOut = idle_time_out ;
if(mIdleTimeOut < LLCurl::sCurlRequestTimeOut)
@@ -577,8 +577,8 @@ LLCurl::Multi::Multi(F32 idle_time_out)
mIdleTimeOut = LLCurl::sCurlRequestTimeOut ;
}
- ++gCurlMultiCount;
- }
+ ++gCurlMultiCount;
+}
}
LLCurl::Multi::~Multi()
@@ -617,7 +617,7 @@ void LLCurl::Multi::cleanup()
mDeletionMutexp = NULL ;
delete mEasyMutexp ;
mEasyMutexp = NULL ;
-
+
mQueued = 0 ;
mState = STATE_COMPLETED;
@@ -738,7 +738,7 @@ bool LLCurl::Multi::doPerform()
}
mQueued = q;
- setState(STATE_COMPLETED) ;
+ setState(STATE_COMPLETED) ;
mIdleTimer.reset() ;
}
else if(mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it.
@@ -911,8 +911,8 @@ bool LLCurlThread::CurlRequest::processRequest()
if(!completed)
{
- setPriority(LLQueuedThread::PRIORITY_LOW) ;
- }
+ setPriority(LLQueuedThread::PRIORITY_LOW) ;
+ }
}
return completed ;
@@ -922,7 +922,7 @@ void LLCurlThread::CurlRequest::finishRequest(bool completed)
{
if(mMulti->isDead())
{
- mCurlThread->deleteMulti(mMulti) ;
+ mCurlThread->deleteMulti(mMulti) ;
}
else
{
@@ -968,8 +968,8 @@ void LLCurlThread::killMulti(LLCurl::Multi* multi)
if(multi->isValid())
{
- multi->markDead() ;
- }
+ multi->markDead() ;
+}
else
{
deleteMulti(multi) ;
@@ -1033,7 +1033,7 @@ void LLCurlRequest::addMulti()
mActiveRequestCount = 0 ;
return;
}
-
+
mMultiSet.insert(multi);
mActiveMulti = multi;
mActiveRequestCount = 0;
@@ -1229,15 +1229,15 @@ LLCurlEasyRequest::LLCurlEasyRequest()
if(mMulti->isValid())
{
- mEasy = mMulti->allocEasy();
- if (mEasy)
- {
- mEasy->setErrorBuffer();
- mEasy->setCA();
- // Set proxy settings if configured to do so.
- LLProxy::getInstance()->applyProxySettings(mEasy);
- }
+ mEasy = mMulti->allocEasy();
+ if (mEasy)
+ {
+ mEasy->setErrorBuffer();
+ mEasy->setCA();
+ // Set proxy settings if configured to do so.
+ LLProxy::getInstance()->applyProxySettings(mEasy);
}
+}
else
{
LLCurl::getCurlThread()->killMulti(mMulti) ;
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 231cb7ca8f..0c325a68aa 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -158,7 +158,7 @@ namespace
if(fstream.is_open())
{
fstream.seekg(0, std::ios::end);
- U32 fileSize = fstream.tellg();
+ U32 fileSize = (U32)fstream.tellg();
fstream.seekg(0, std::ios::beg);
std::vector<char> fileBuffer(fileSize);
fstream.read(&fileBuffer[0], fileSize);
diff --git a/indra/llmessage/llmime.cpp b/indra/llmessage/llmime.cpp
index 943a734927..9d9c4ebd68 100644
--- a/indra/llmessage/llmime.cpp
+++ b/indra/llmessage/llmime.cpp
@@ -388,7 +388,7 @@ bool LLMimeParser::Impl::parseHeaders(
// not to read past limit when we get() the newline.
S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1);
istr.getline(mBuffer, max_get, '\r');
- mScanCount += istr.gcount();
+ mScanCount += (S32)istr.gcount();
int c = istr.get();
if(EOF == c)
{
@@ -496,7 +496,7 @@ void LLMimeParser::Impl::scanPastSeparator(
// past limit when we get() the newline.
S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1);
istr.getline(mBuffer, max_get, '\r');
- mScanCount += istr.gcount();
+ mScanCount += (S32)istr.gcount();
if(istr.gcount() >= LINE_BUFFER_LENGTH - 1)
{
// that's way too long to be a separator, so ignore it.
diff --git a/indra/llmessage/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp
index 9148c9dd15..1c93c12d99 100644
--- a/indra/llmessage/llsdmessage.cpp
+++ b/indra/llmessage/llsdmessage.cpp
@@ -88,7 +88,7 @@ bool LLSDMessage::httpListener(const LLSD& request)
request,
url, "POST", reply, error),
LLSD(), // headers
- timeout);
+ (F32)timeout);
return false;
}
diff --git a/indra/llmessage/llsdmessagebuilder.cpp b/indra/llmessage/llsdmessagebuilder.cpp
index 2698a271ee..615221e0ad 100644
--- a/indra/llmessage/llsdmessagebuilder.cpp
+++ b/indra/llmessage/llsdmessagebuilder.cpp
@@ -317,7 +317,7 @@ void LLSDMessageBuilder::copyFromMessageData(const LLMsgData& data)
// S64 not supported in LLSD so we just truncate it
case MVT_S64:
- addS32(varname, *(S64*)mvci.getData());
+ addS32(varname, (S32)*(S64*)mvci.getData());
break;
case MVT_F32:
diff --git a/indra/llmessage/llxfer.h b/indra/llmessage/llxfer.h
index 989e8b2cab..f9348eb11f 100644
--- a/indra/llmessage/llxfer.h
+++ b/indra/llmessage/llxfer.h
@@ -29,6 +29,7 @@
#include "message.h"
#include "lltimer.h"
+#include "llextendedstatus.h"
const S32 LL_XFER_LARGE_PAYLOAD = 7680;
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index d0b0e178b8..6a425cfe98 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -3147,7 +3147,7 @@ bool LLMessageSystem::generateDigestForWindowAndUUIDs(char* digest, const S32 wi
LL_ERRS("Messaging") << "Trying to generate complex digest on a machine without a shared secret!" << llendl;
}
- U32 now = time(NULL);
+ U32 now = (U32)time(NULL);
now /= window;
@@ -3167,7 +3167,7 @@ bool LLMessageSystem::isMatchingDigestForWindowAndUUIDs(const char* digest, cons
}
char our_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
- U32 now = time(NULL);
+ U32 now = (U32)time(NULL);
now /= window;
@@ -3213,7 +3213,7 @@ bool LLMessageSystem::generateDigestForWindow(char* digest, const S32 window) co
LL_ERRS("Messaging") << "Trying to generate simple digest on a machine without a shared secret!" << llendl;
}
- U32 now = time(NULL);
+ U32 now = (U32)time(NULL);
now /= window;
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 82e8227ffe..fccbf37a8d 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -56,8 +56,9 @@ std::string LLFontGL::sAppDir;
LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f);
LLFontRegistry* LLFontGL::sFontRegistry = NULL;
-LLCoordFont LLFontGL::sCurOrigin;
-std::vector<LLCoordFont> LLFontGL::sOriginStack;
+LLCoordGL LLFontGL::sCurOrigin;
+F32 LLFontGL::sCurDepth;
+std::vector<std::pair<LLCoordGL, F32> > LLFontGL::sOriginStack;
const F32 EXT_X_BEARING = 1.f;
const F32 EXT_Y_BEARING = 0.f;
@@ -68,20 +69,6 @@ const F32 PIXEL_CORRECTION_DISTANCE = 0.01f;
const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture
const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f;
-static F32 llfont_round_x(F32 x)
-{
- //return llfloor((x-LLFontGL::sCurOrigin.mX)/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleX+LLFontGL::sCurOrigin.mX;
- //return llfloor(x/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleY;
- return x;
-}
-
-static F32 llfont_round_y(F32 y)
-{
- //return llfloor((y-LLFontGL::sCurOrigin.mY)/LLFontGL::sScaleY+0.5f)*LLFontGL::sScaleY+LLFontGL::sCurOrigin.mY;
- //return llfloor(y+0.5f);
- return y;
-}
-
LLFontGL::LLFontGL()
{
}
@@ -115,23 +102,23 @@ static LLFastTimer::DeclareTimer FTM_RENDER_FONTS("Fonts");
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses) const
{
- F32 x = rect.mLeft;
+ F32 x = (F32)rect.mLeft;
F32 y = 0.f;
switch(valign)
{
case TOP:
- y = rect.mTop;
+ y = (F32)rect.mTop;
break;
case VCENTER:
- y = rect.getCenterY();
+ y = (F32)rect.getCenterY();
break;
case BASELINE:
case BOTTOM:
- y = rect.mBottom;
+ y = (F32)rect.mBottom;
break;
default:
- y = rect.mBottom;
+ y = (F32)rect.mBottom;
break;
}
return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, rect.getWidth(), right_x, use_ellipses);
@@ -177,21 +164,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
gGL.loadUIIdentity();
- //gGL.translateUI(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ);
-
- // this code snaps the text origin to a pixel grid to start with
- //F32 pixel_offset_x = llround((F32)sCurOrigin.mX) - (sCurOrigin.mX);
- //F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY);
- //gGL.translateUI(-pixel_offset_x, -pixel_offset_y, 0.f);
-
LLVector2 origin(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY));
- // snap the text origin to a pixel grid to start with
- origin.mV[VX] -= llround((F32)sCurOrigin.mX) - (sCurOrigin.mX);
- origin.mV[VY] -= llround((F32)sCurOrigin.mY) - (sCurOrigin.mY);
- // Depth translation, so that floating text appears 'inworld'
- // and is correclty occluded.
- gGL.translatef(0.f,0.f,sCurOrigin.mZ);
+ // Depth translation, so that floating text appears 'in-world'
+ // and is correctly occluded.
+ gGL.translatef(0.f,0.f,sCurDepth);
S32 chars_drawn = 0;
S32 i;
@@ -215,16 +192,17 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
cur_y = ((F32)y * sScaleY) + origin.mV[VY];
// Offset y by vertical alignment.
+ // use unscaled font metrics here
switch (valign)
{
case TOP:
- cur_y -= mFontFreetype->getAscenderHeight();
+ cur_y -= llceil(mFontFreetype->getAscenderHeight());
break;
case BOTTOM:
- cur_y += mFontFreetype->getDescenderHeight();
+ cur_y += llceil(mFontFreetype->getDescenderHeight());
break;
case VCENTER:
- cur_y -= (mFontFreetype->getAscenderHeight() - mFontFreetype->getDescenderHeight()) / 2.f;
+ cur_y -= llceil((llceil(mFontFreetype->getAscenderHeight()) - llceil(mFontFreetype->getDescenderHeight())) / 2.f);
break;
case BASELINE:
// Baseline, do nothing.
@@ -250,7 +228,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
cur_render_y = cur_y;
cur_render_x = cur_x;
- F32 start_x = llround(cur_x);
+ F32 start_x = (F32)llround(cur_x);
const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache();
@@ -334,10 +312,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
(fgi->mXBitmapOffset + fgi->mWidth) * inv_width,
(fgi->mYBitmapOffset - PAD_UVY) * inv_height);
// snap glyph origin to whole screen pixel
- LLRectf screen_rect(llround(cur_render_x + (F32)fgi->mXBearing),
- llround(cur_render_y + (F32)fgi->mYBearing),
- llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,
- llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);
+ LLRectf screen_rect((F32)llround(cur_render_x + (F32)fgi->mXBearing),
+ (F32)llround(cur_render_y + (F32)fgi->mYBearing),
+ (F32)llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,
+ (F32)llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);
if (glyph_count >= GLYPH_BATCH_SIZE)
{
@@ -390,12 +368,12 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
//FIXME: add underline as glyph?
if (style_to_add & UNDERLINE)
{
- F32 descender = mFontFreetype->getDescenderHeight();
+ F32 descender = (F32)llfloor(mFontFreetype->getDescenderHeight());
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.begin(LLRender::LINES);
- gGL.vertex2f(start_x, cur_y - (descender));
- gGL.vertex2f(cur_x, cur_y - (descender));
+ gGL.vertex2f(start_x, cur_y - descender);
+ gGL.vertex2f(cur_x, cur_y - descender);
gGL.end();
}
@@ -444,19 +422,9 @@ S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y
}
// font metrics - override for LLFontFreetype that returns units of virtual pixels
-F32 LLFontGL::getLineHeight() const
+S32 LLFontGL::getLineHeight() const
{
- return (F32)llround(mFontFreetype->getLineHeight() / sScaleY);
-}
-
-F32 LLFontGL::getAscenderHeight() const
-{
- return (F32)llround(mFontFreetype->getAscenderHeight() / sScaleY);
-}
-
-F32 LLFontGL::getDescenderHeight() const
-{
- return (F32)llround(mFontFreetype->getDescenderHeight() / sScaleY);
+ return llceil(mFontFreetype->getAscenderHeight() / sScaleY) + llceil(mFontFreetype->getDescenderHeight() / sScaleY);
}
S32 LLFontGL::getWidth(const std::string& utf8text) const
@@ -645,7 +613,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
}
// Round after kerning.
- cur_x = llround(cur_x);
+ cur_x = (F32)llround(cur_x);
drawn_x = cur_x;
}
@@ -716,7 +684,7 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
}
// Round after kerning.
- total_width = llround(total_width);
+ total_width = (F32)llround(total_width);
}
if (drawable_chars == 0)
@@ -799,7 +767,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
// Round after kerning.
- cur_x = llround(cur_x);
+ cur_x = (F32)llround(cur_x);
}
return llmin(max_chars, pos - begin_offset);
@@ -1146,22 +1114,22 @@ void LLFontGL::renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* c
{
S32 index = 0;
- vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mRight), llfont_round_y(screen_rect.mTop), 0.f);
+ vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f);
uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
colors_out[index] = color;
index++;
- vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mLeft), llfont_round_y(screen_rect.mTop), 0.f);
+ vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 0.f);
uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
colors_out[index] = color;
index++;
- vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mLeft), llfont_round_y(screen_rect.mBottom), 0.f);
+ vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 0.f);
uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
colors_out[index] = color;
index++;
- vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mRight), llfont_round_y(screen_rect.mBottom), 0.f);
+ vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 0.f);
uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
colors_out[index] = color;
}
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index dc8d848ed2..74bdbb43e7 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -115,9 +115,7 @@ public:
S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const;
// font metrics - override for LLFontFreetype that returns units of virtual pixels
- F32 getLineHeight() const;
- F32 getAscenderHeight() const;
- F32 getDescenderHeight() const;
+ S32 getLineHeight() const;
S32 getWidth(const std::string& utf8text) const;
S32 getWidth(const llwchar* wchars) const;
@@ -188,8 +186,9 @@ public:
static std::string getFontPathLocal();
static std::string getFontPathSystem();
- static LLCoordFont sCurOrigin;
- static std::vector<LLCoordFont> sOriginStack;
+ static LLCoordGL sCurOrigin;
+ static F32 sCurDepth;
+ static std::vector<std::pair<LLCoordGL, F32> > sOriginStack;
static LLColor4 sShadowColor;
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 6b2852670a..3773568ad8 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -64,10 +64,23 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
}
LLShaderFeatures::LLShaderFeatures()
-: calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
-hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false),
-hasGamma(false), hasLighting(false), isAlphaLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false),
-hasAlphaMask(false)
+ : atmosphericHelpers(false)
+ , calculatesLighting(false)
+ , calculatesAtmospherics(false)
+ , hasLighting(false)
+ , isAlphaLighting(false)
+ , isShiny(false)
+ , isFullbright(false)
+ , isSpecular(false)
+ , hasWaterFog(false)
+ , hasTransport(false)
+ , hasSkinning(false)
+ , hasObjectSkinning(false)
+ , hasAtmospherics(false)
+ , hasGamma(false)
+ , mIndexedTextureChannels(0)
+ , disableTextureIndex(false)
+ , hasAlphaMask(false)
{
}
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 00b4b0dbd4..7873fe3c4e 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -33,6 +33,7 @@
class LLShaderFeatures
{
public:
+ bool atmosphericHelpers;
bool calculatesLighting;
bool calculatesAtmospherics;
bool hasLighting; // implies no transport (it's possible to have neither though)
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 1a03aeebb7..908443e8cf 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -94,13 +94,16 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
- if (features->calculatesLighting)
+ if (features->calculatesLighting || features->atmosphericHelpers)
{
if (!shader->attachObject("windlight/atmosphericsHelpersV.glsl"))
{
return FALSE;
}
+ }
+ if (features->calculatesLighting)
+ {
if (features->isSpecular)
{
if (!shader->attachObject("lighting/lightFuncSpecularV.glsl"))
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 79d1beb33a..b562c91e3e 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -53,31 +53,31 @@ U32 nhpo2(U32 v)
//============================================================================
//static
-LLVBOPool LLVertexBuffer::sStreamVBOPool;
-LLVBOPool LLVertexBuffer::sDynamicVBOPool;
-LLVBOPool LLVertexBuffer::sStreamIBOPool;
-LLVBOPool LLVertexBuffer::sDynamicIBOPool;
+LLVBOPool LLVertexBuffer::sStreamVBOPool(GL_STREAM_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
+LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
+LLVBOPool LLVertexBuffer::sStreamIBOPool(GL_STREAM_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
+LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
U32 LLVBOPool::sBytesPooled = 0;
-LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL ;
+LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL;
U32 LLVertexBuffer::sBindCount = 0;
U32 LLVertexBuffer::sSetCount = 0;
S32 LLVertexBuffer::sCount = 0;
S32 LLVertexBuffer::sGLCount = 0;
S32 LLVertexBuffer::sMappedCount = 0;
-BOOL LLVertexBuffer::sDisableVBOMapping = FALSE ;
-BOOL LLVertexBuffer::sEnableVBOs = TRUE;
+bool LLVertexBuffer::sDisableVBOMapping = false;
+bool LLVertexBuffer::sEnableVBOs = true;
U32 LLVertexBuffer::sGLRenderBuffer = 0;
U32 LLVertexBuffer::sGLRenderArray = 0;
U32 LLVertexBuffer::sGLRenderIndices = 0;
U32 LLVertexBuffer::sLastMask = 0;
-BOOL LLVertexBuffer::sVBOActive = FALSE;
-BOOL LLVertexBuffer::sIBOActive = FALSE;
+bool LLVertexBuffer::sVBOActive = false;
+bool LLVertexBuffer::sIBOActive = false;
U32 LLVertexBuffer::sAllocatedBytes = 0;
-BOOL LLVertexBuffer::sMapped = FALSE;
-BOOL LLVertexBuffer::sUseStreamDraw = TRUE;
-BOOL LLVertexBuffer::sUseVAO = FALSE;
-BOOL LLVertexBuffer::sPreferStreamDraw = FALSE;
+bool LLVertexBuffer::sMapped = false;
+bool LLVertexBuffer::sUseStreamDraw = true;
+bool LLVertexBuffer::sUseVAO = false;
+bool LLVertexBuffer::sPreferStreamDraw = false;
const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000; //1 ms
@@ -204,15 +204,15 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)
Record rec;
rec.mGLName = name;
rec.mClientData = buffer;
-
- sBytesPooled += size;
-
- if (!LLVertexBuffer::sDisableVBOMapping && mUsage == GL_DYNAMIC_DRAW_ARB)
+
+ if (buffer == NULL)
+
{
glDeleteBuffersARB(1, &rec.mGLName);
}
else
{
+ sBytesPooled += size;
mFreeList[i].push_back(rec);
}
}
@@ -283,7 +283,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
{
if (sLastMask != data_mask)
{
- BOOL error = FALSE;
+ bool error = false;
if (LLGLSLShader::sNoFixedFunction)
{
@@ -344,7 +344,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
{
if (gDebugSession)
{
- error = TRUE;
+ error = true;
gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl;
}
else
@@ -364,7 +364,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
{ //needs to be disabled, make sure it was (DEBUG TEMPORARY)
if (gDebugSession)
{
- error = TRUE;
+ error = true;
gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl;
}
else
@@ -430,7 +430,7 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, con
U32 count = pos.size();
llassert_always(norm.size() >= pos.size());
- llassert_always(count > 0) ;
+ llassert_always(count > 0);
unbind();
@@ -548,7 +548,7 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
{
validateRange(start, end, count, indices_offset);
- mMappable = FALSE;
+ mMappable = false;
gGL.syncMatrices();
llassert(mNumVerts >= 0);
@@ -603,7 +603,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
{
llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
- mMappable = FALSE;
+ mMappable = false;
gGL.syncMatrices();
llassert(mNumIndices >= 0);
@@ -649,7 +649,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
{
llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
- mMappable = FALSE;
+ mMappable = false;
gGL.syncMatrices();
llassert(mNumVerts >= 0);
@@ -668,7 +668,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
}
else
{
- BOOL uvb = useVBOs();
+ bool uvb = useVBOs();
if (mGLBuffer != sGLRenderBuffer || uvb != sVBOActive)
{
llerrs << "Wrong vertex buffer bound." << llendl;
@@ -690,23 +690,13 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
//static
void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
{
- sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject ;
- sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ;
+ sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject;
+ sDisableVBOMapping = sEnableVBOs && no_vbo_mapping;
- if(!sPrivatePoolp)
+ if (!sPrivatePoolp)
{
- sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC) ;
+ sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC);
}
-
- sStreamVBOPool.mType = GL_ARRAY_BUFFER_ARB;
- sStreamVBOPool.mUsage= GL_STREAM_DRAW_ARB;
- sStreamIBOPool.mType = GL_ELEMENT_ARRAY_BUFFER_ARB;
- sStreamIBOPool.mUsage= GL_STREAM_DRAW_ARB;
-
- sDynamicVBOPool.mType = GL_ARRAY_BUFFER_ARB;
- sDynamicVBOPool.mUsage= GL_DYNAMIC_DRAW_ARB;
- sDynamicIBOPool.mType = GL_ELEMENT_ARRAY_BUFFER_ARB;
- sDynamicIBOPool.mUsage= GL_DYNAMIC_DRAW_ARB;
}
//static
@@ -719,18 +709,18 @@ void LLVertexBuffer::unbind()
#endif
sGLRenderArray = 0;
sGLRenderIndices = 0;
- sIBOActive = FALSE;
+ sIBOActive = false;
}
if (sVBOActive)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- sVBOActive = FALSE;
+ sVBOActive = false;
}
if (sIBOActive)
{
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
- sIBOActive = FALSE;
+ sIBOActive = false;
}
sGLRenderBuffer = 0;
@@ -752,73 +742,81 @@ void LLVertexBuffer::cleanupClass()
if(sPrivatePoolp)
{
- LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp) ;
- sPrivatePoolp = NULL ;
+ LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp);
+ sPrivatePoolp = NULL;
}
}
//----------------------------------------------------------------------------
-LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
- LLRefCount(),
-
- mNumVerts(0),
- mNumIndices(0),
- mUsage(usage),
- mGLBuffer(0),
- mGLArray(0),
- mGLIndices(0),
- mMappedData(NULL),
- mMappedIndexData(NULL),
- mVertexLocked(FALSE),
- mIndexLocked(FALSE),
- mFinal(FALSE),
- mEmpty(TRUE),
- mFence(NULL)
+S32 LLVertexBuffer::determineUsage(S32 usage)
{
- LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
- mFence = NULL;
+ S32 ret_usage = usage;
+
if (!sEnableVBOs)
{
- mUsage = 0 ;
+ ret_usage = 0;
}
-
- if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
+
+ if (ret_usage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
{
- mUsage = 0;
+ ret_usage = 0;
}
- if (mUsage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw)
+ if (ret_usage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw)
{
- mUsage = GL_STREAM_DRAW_ARB;
+ ret_usage = GL_STREAM_DRAW_ARB;
}
-
- if (mUsage == 0 && LLRender::sGLCoreProfile)
+
+ if (ret_usage == 0 && LLRender::sGLCoreProfile)
{ //MUST use VBOs for all rendering
- mUsage = GL_STREAM_DRAW_ARB;
+ ret_usage = GL_STREAM_DRAW_ARB;
}
-
- if (mUsage && mUsage != GL_STREAM_DRAW_ARB)
+
+ if (ret_usage && ret_usage != GL_STREAM_DRAW_ARB)
{ //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default
if (sDisableVBOMapping)
{ //always use stream draw if VBO mapping is disabled
- mUsage = GL_STREAM_DRAW_ARB;
+ ret_usage = GL_STREAM_DRAW_ARB;
}
else
{
- mUsage = GL_DYNAMIC_DRAW_ARB;
+ret_usage = GL_DYNAMIC_DRAW_ARB;
+
}
}
+ return ret_usage;
+}
- if (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping)
- {
- mMappable = TRUE;
- }
- else
- {
- mMappable = FALSE;
- }
+LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
+ LLRefCount(),
+
+ mNumVerts(0),
+ mNumIndices(0),
+ mAlignedOffset(0),
+ mAlignedIndexOffset(0),
+ mSize(0),
+ mIndicesSize(0),
+ mTypeMask(typemask),
+ mUsage(LLVertexBuffer::determineUsage(usage)),
+ mGLBuffer(0),
+ mGLIndices(0),
+ mGLArray(0),
+ mMappedData(NULL),
+ mMappedIndexData(NULL),
+ mMappedDataUsingVBOs(false),
+ mMappedIndexDataUsingVBOs(false),
+ mVertexLocked(false),
+ mIndexLocked(false),
+ mFinal(false),
+ mEmpty(true),
+ mMappable(false),
+ mFence(NULL)
+{
+ LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
+
+ mMappable = (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping);
//zero out offsets
for (U32 i = 0; i < TYPE_MAX; i++)
@@ -826,12 +824,6 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
mOffsets[i] = 0;
}
- mTypeMask = typemask;
- mSize = 0;
- mIndicesSize = 0;
- mAlignedOffset = 0;
- mAlignedIndexOffset = 0;
-
sCount++;
}
@@ -903,7 +895,7 @@ LLVertexBuffer::~LLVertexBuffer()
mFence = NULL;
- llassert_always(!mMappedData && !mMappedIndexData) ;
+ llassert_always(!mMappedData && !mMappedIndexData);
};
void LLVertexBuffer::placeFence() const
@@ -1012,9 +1004,11 @@ void LLVertexBuffer::createGLBuffer(U32 size)
return;
}
- mEmpty = TRUE;
+ mEmpty = true;
- if (useVBOs())
+ mMappedDataUsingVBOs = useVBOs();
+
+ if (mMappedDataUsingVBOs)
{
genBuffer(size);
}
@@ -1041,12 +1035,14 @@ void LLVertexBuffer::createGLIndices(U32 size)
return;
}
- mEmpty = TRUE;
+ mEmpty = true;
//pad by 16 bytes for aligned copies
size += 16;
- if (useVBOs())
+ mMappedIndexDataUsingVBOs = useVBOs();
+
+ if (mMappedIndexDataUsingVBOs)
{
//pad by another 16 bytes for VBO pointer adjustment
size += 16;
@@ -1066,15 +1062,15 @@ void LLVertexBuffer::destroyGLBuffer()
LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_BUFFER);
if (mGLBuffer)
{
- if (useVBOs())
+ if (mMappedDataUsingVBOs)
{
releaseBuffer();
}
else
{
- FREE_MEM(sPrivatePoolp, (void*) mMappedData) ;
+ FREE_MEM(sPrivatePoolp, (void*) mMappedData);
mMappedData = NULL;
- mEmpty = TRUE;
+ mEmpty = true;
}
}
@@ -1087,15 +1083,15 @@ void LLVertexBuffer::destroyGLIndices()
LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_INDICES);
if (mGLIndices)
{
- if (useVBOs())
+ if (mMappedIndexDataUsingVBOs)
{
releaseIndices();
}
else
{
- FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData) ;
+ FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData);
mMappedIndexData = NULL;
- mEmpty = TRUE;
+ mEmpty = true;
}
}
@@ -1280,16 +1276,10 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
}
}
-BOOL LLVertexBuffer::useVBOs() const
+bool LLVertexBuffer::useVBOs() const
{
//it's generally ineffective to use VBO for things that are streaming on apple
-
- if (!mUsage)
- {
- return FALSE;
- }
-
- return TRUE;
+ return (mUsage != 0);
}
//----------------------------------------------------------------------------
@@ -1369,7 +1359,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
if (!mVertexLocked)
{
LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
- mVertexLocked = TRUE;
+ mVertexLocked = true;
sMappedCount++;
stop_glerror();
@@ -1448,17 +1438,17 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
{
log_glerror();
- //check the availability of memory
- LLMemory::logMemoryInfo(TRUE) ;
+ //check the availability of memory
+ LLMemory::logMemoryInfo(true);
if(mMappable)
{
//--------------------
//print out more debug info before crash
- llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
- GLint size ;
- glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ;
- llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ;
+ llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl;
+ GLint size;
+ glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
+ llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl;
//--------------------
GLint buff;
@@ -1473,7 +1463,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
}
else
{
- llerrs << "memory allocation for vertex data failed." << llendl ;
+ llerrs << "memory allocation for vertex data failed." << llendl;
}
}
}
@@ -1548,7 +1538,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
{
LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES);
- mIndexLocked = TRUE;
+ mIndexLocked = true;
sMappedCount++;
stop_glerror();
@@ -1627,7 +1617,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
if (!mMappedIndexData)
{
log_glerror();
- LLMemory::logMemoryInfo(TRUE) ;
+ LLMemory::logMemoryInfo(true);
if(mMappable)
{
@@ -1642,7 +1632,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
}
else
{
- llerrs << "memory allocation for Index data failed. " << llendl ;
+ llerrs << "memory allocation for Index data failed. " << llendl;
}
}
}
@@ -1673,10 +1663,10 @@ void LLVertexBuffer::unmapBuffer()
LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER);
if (!useVBOs())
{
- return ; //nothing to unmap
+ return; //nothing to unmap
}
- bool updated_all = false ;
+ bool updated_all = false;
if (mMappedData && mVertexLocked)
{
@@ -1743,7 +1733,7 @@ void LLVertexBuffer::unmapBuffer()
mMappedData = NULL;
}
- mVertexLocked = FALSE ;
+ mVertexLocked = false;
sMappedCount--;
}
@@ -1807,16 +1797,16 @@ void LLVertexBuffer::unmapBuffer()
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
stop_glerror();
- mMappedIndexData = NULL ;
+ mMappedIndexData = NULL;
}
- mIndexLocked = FALSE ;
+ mIndexLocked = false;
sMappedCount--;
}
if(updated_all)
{
- mEmpty = FALSE;
+ mEmpty = false;
}
}
@@ -1836,12 +1826,12 @@ template <class T,S32 type> struct VertexBufferStrider
if (ptr == NULL)
{
llwarns << "mapIndexBuffer failed!" << llendl;
- return FALSE;
+ return false;
}
strider = (T*)ptr;
strider.setStride(0);
- return TRUE;
+ return true;
}
else if (vbo.hasDataType(type))
{
@@ -1852,18 +1842,18 @@ template <class T,S32 type> struct VertexBufferStrider
if (ptr == NULL)
{
llwarns << "mapVertexBuffer failed!" << llendl;
- return FALSE;
+ return false;
}
strider = (T*)ptr;
strider.setStride(stride);
- return TRUE;
+ return true;
}
else
{
llerrs << "VertexBufferStrider could not find valid vertex data." << llendl;
}
- return FALSE;
+ return false;
}
};
@@ -1962,7 +1952,7 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind)
glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
sGLRenderBuffer = mGLBuffer;
sBindCount++;
- sVBOActive = TRUE;
+ sVBOActive = true;
if (mGLArray)
{
@@ -1994,7 +1984,7 @@ bool LLVertexBuffer::bindGLIndices(bool force_bind)
sGLRenderIndices = mGLIndices;
stop_glerror();
sBindCount++;
- sIBOActive = TRUE;
+ sIBOActive = true;
ret = true;
}
@@ -2016,7 +2006,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_BUFFER);
//set up pointers if the data mask is different ...
- BOOL setup = (sLastMask != data_mask);
+ bool setup = (sLastMask != data_mask);
if (gDebugGL && data_mask != 0)
{ //make sure data requirements are fulfilled
@@ -2050,21 +2040,17 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
if (mGLArray)
{
bindGLArray();
- setup = FALSE; //do NOT perform pointer setup if using VAO
+ setup = false; //do NOT perform pointer setup if using VAO
}
else
{
- if (bindGLBuffer())
- {
- setup = TRUE;
- }
- if (bindGLIndices())
- {
- setup = TRUE;
- }
+ const bool bindBuffer = bindGLBuffer();
+ const bool bindIndices = bindGLIndices();
+
+ setup = setup || bindBuffer || bindIndices;
}
- BOOL error = FALSE;
+ bool error = false;
if (gDebugGL && !mGLArray)
{
GLint buff;
@@ -2073,7 +2059,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
{
if (gDebugSession)
{
- error = TRUE;
+ error = true;
gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl;
}
else
@@ -2089,7 +2075,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
{
if (gDebugSession)
{
- error = TRUE;
+ error = true;
gFailLog << "Invalid GL index buffer bound: " << buff << std::endl;
}
else
@@ -2111,7 +2097,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
#endif
sGLRenderArray = 0;
sGLRenderIndices = 0;
- sIBOActive = FALSE;
+ sIBOActive = false;
}
if (mGLBuffer)
@@ -2120,13 +2106,13 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
sBindCount++;
- sVBOActive = FALSE;
- setup = TRUE; // ... or a VBO is deactivated
+ sVBOActive = false;
+ setup = true; // ... or a VBO is deactivated
}
if (sGLRenderBuffer != mGLBuffer)
{
sGLRenderBuffer = mGLBuffer;
- setup = TRUE; // ... or a client memory pointer changed
+ setup = true; // ... or a client memory pointer changed
}
}
if (mGLIndices)
@@ -2135,7 +2121,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
{
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
sBindCount++;
- sIBOActive = FALSE;
+ sIBOActive = false;
}
sGLRenderIndices = mGLIndices;
@@ -2223,19 +2209,19 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
{
S32 loc = TYPE_WEIGHT;
void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]);
- glVertexAttribPointerARB(loc, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
+ glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
}
if (data_mask & MAP_WEIGHT4)
{
S32 loc = TYPE_WEIGHT4;
void* ptr = (void*)(base+mOffsets[TYPE_WEIGHT4]);
- glVertexAttribPointerARB(loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
+ glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
}
if (data_mask & MAP_CLOTHWEIGHT)
{
S32 loc = TYPE_CLOTHWEIGHT;
void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
- glVertexAttribPointerARB(loc, 4, GL_FLOAT, TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
+ glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
}
if (data_mask & MAP_TEXTURE_INDEX)
{
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index e1cbfd3b61..d859199663 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -55,9 +55,14 @@ class LLVBOPool
{
public:
static U32 sBytesPooled;
+
+ LLVBOPool(U32 vboUsage, U32 vboType)
+ : mUsage(vboUsage)
+ , mType(vboType)
+ {}
- U32 mUsage;
- U32 mType;
+ const U32 mUsage;
+ const U32 mType;
//size MUST be a power of 2
volatile U8* allocate(U32& name, U32 size);
@@ -88,7 +93,7 @@ public:
//============================================================================
// base class
-class LLPrivateMemoryPool ;
+class LLPrivateMemoryPool;
class LLVertexBuffer : public LLRefCount
{
public:
@@ -103,6 +108,7 @@ public:
};
LLVertexBuffer(const LLVertexBuffer& rhs)
+ : mUsage(rhs.mUsage)
{
*this = rhs;
}
@@ -118,9 +124,9 @@ public:
static LLVBOPool sStreamIBOPool;
static LLVBOPool sDynamicIBOPool;
- static BOOL sUseStreamDraw;
- static BOOL sUseVAO;
- static BOOL sPreferStreamDraw;
+ static bool sUseStreamDraw;
+ static bool sUseVAO;
+ static bool sPreferStreamDraw;
static void initClass(bool use_vbo, bool no_vbo_mapping);
static void cleanupClass();
@@ -201,7 +207,7 @@ protected:
void destroyGLIndices();
void updateNumVerts(S32 nverts);
void updateNumIndices(S32 nindices);
- virtual BOOL useVBOs() const;
+ bool useVBOs() const;
void unmapBuffer();
public:
@@ -239,8 +245,8 @@ public:
bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
- BOOL isEmpty() const { return mEmpty; }
- BOOL isLocked() const { return mVertexLocked || mIndexLocked; }
+ bool isEmpty() const { return mEmpty; }
+ bool isLocked() const { return mVertexLocked || mIndexLocked; }
S32 getNumVerts() const { return mNumVerts; }
S32 getNumIndices() const { return mNumIndices; }
@@ -254,7 +260,7 @@ public:
volatile U8* getMappedIndices() const { return mMappedIndexData; }
S32 getOffset(S32 type) const { return mOffsets[type]; }
S32 getUsage() const { return mUsage; }
- BOOL isWriteable() const { return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? TRUE : FALSE; }
+ bool isWriteable() const { return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? true : false; }
void draw(U32 mode, U32 count, U32 indices_offset) const;
void drawArrays(U32 mode, U32 offset, U32 count) const;
@@ -274,18 +280,25 @@ protected:
S32 mSize;
S32 mIndicesSize;
U32 mTypeMask;
- S32 mUsage; // GL usage
+
+ const S32 mUsage; // GL usage
+
U32 mGLBuffer; // GL VBO handle
U32 mGLIndices; // GL IBO handle
U32 mGLArray; // GL VAO handle
volatile U8* mMappedData; // pointer to currently mapped data (NULL if unmapped)
volatile U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped)
- BOOL mVertexLocked; // if TRUE, vertex buffer is being or has been written to in client memory
- BOOL mIndexLocked; // if TRUE, index buffer is being or has been written to in client memory
- BOOL mFinal; // if TRUE, buffer can not be mapped again
- BOOL mEmpty; // if TRUE, client buffer is empty (or NULL). Old values have been discarded.
- mutable BOOL mMappable; // if TRUE, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData)
+
+ U32 mMappedDataUsingVBOs : 1;
+ U32 mMappedIndexDataUsingVBOs : 1;
+ U32 mVertexLocked : 1; // if true, vertex buffer is being or has been written to in client memory
+ U32 mIndexLocked : 1; // if true, index buffer is being or has been written to in client memory
+ U32 mFinal : 1; // if true, buffer can not be mapped again
+ U32 mEmpty : 1; // if true, client buffer is empty (or NULL). Old values have been discarded.
+
+ mutable bool mMappable; // if true, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData)
+
S32 mOffsets[TYPE_MAX];
std::vector<MappedRegion> mMappedVertexRegions;
@@ -296,26 +309,27 @@ protected:
void placeFence() const;
void waitFence() const;
+ static S32 determineUsage(S32 usage);
private:
- static LLPrivateMemoryPool* sPrivatePoolp ;
+ static LLPrivateMemoryPool* sPrivatePoolp;
public:
static S32 sCount;
static S32 sGLCount;
static S32 sMappedCount;
- static BOOL sMapped;
+ static bool sMapped;
typedef std::list<LLVertexBuffer*> buffer_list_t;
- static BOOL sDisableVBOMapping; //disable glMapBufferARB
- static BOOL sEnableVBOs;
+ static bool sDisableVBOMapping; //disable glMapBufferARB
+ static bool sEnableVBOs;
static S32 sTypeSize[TYPE_MAX];
static U32 sGLMode[LLRender::NUM_MODES];
static U32 sGLRenderBuffer;
static U32 sGLRenderArray;
static U32 sGLRenderIndices;
- static BOOL sVBOActive;
- static BOOL sIBOActive;
+ static bool sVBOActive;
+ static bool sIBOActive;
static U32 sLastMask;
static U32 sAllocatedBytes;
static U32 sBindCount;
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 7a5f9f9fd6..c025cd7939 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -976,7 +976,7 @@ void LLAccordionCtrlTab::drawChild(const LLRect& root_rect,LLView* child)
gGL.matrixMode(LLRender::MM_MODELVIEW);
LLUI::pushMatrix();
{
- LLUI::translate((F32)child->getRect().mLeft, (F32)child->getRect().mBottom, 0.f);
+ LLUI::translate((F32)child->getRect().mLeft, (F32)child->getRect().mBottom);
child->draw();
}
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index f0d92d597a..705fe16559 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -908,9 +908,9 @@ void LLButton::draw()
// Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars.
mLastDrawCharsCount = mGLFont->render(label, 0,
(F32)x,
- (F32)(mBottomVPad + y_offset),
+ (F32)(getRect().getHeight() / 2 + mBottomVPad),
label_color % alpha,
- mHAlign, LLFontGL::BOTTOM,
+ mHAlign, LLFontGL::VCENTER,
LLFontGL::NORMAL,
mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW,
S32_MAX, text_width,
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 89d8842393..806d2ef3f6 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -613,7 +613,7 @@ void LLComboBox::showList()
}
mList->setOrigin(rect.mLeft, rect.mBottom);
mList->reshape(rect.getWidth(), rect.getHeight());
- mList->translateIntoRect(root_view_local, FALSE);
+ mList->translateIntoRect(root_view_local);
// Make sure we didn't go off bottom of screen
S32 x, y;
diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp
index 42e6c3c786..5f69c6af31 100644
--- a/indra/llui/lldraghandle.cpp
+++ b/indra/llui/lldraghandle.cpp
@@ -244,7 +244,7 @@ void LLDragHandleTop::reshapeTitleBox()
const LLFontGL* font = LLFontGL::getFontSansSerif();
S32 title_width = getRect().getWidth();
title_width -= LEFT_PAD + 2 * BORDER_PAD + getButtonsRect().getWidth();
- S32 title_height = llround(font->getLineHeight());
+ S32 title_height = font->getLineHeight();
LLRect title_rect;
title_rect.setLeftTopAndSize(
LEFT_PAD,
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 33548151fd..22b20969fc 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -270,6 +270,7 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
mMinimizeSignal(NULL)
// mNotificationContext(NULL)
{
+ mPosition.setFloater(*this);
// mNotificationContext = new LLFloaterNotificationContext(getHandle());
// Clicks stop here.
@@ -925,7 +926,7 @@ void LLFloater::applyPositioning(LLFloater* other)
setOrigin(mSpecifiedLeft, mSpecifiedBottom);
const LLRect& snap_rect = gFloaterView->getSnapRect();
translate(snap_rect.mLeft, snap_rect.mBottom);
- translateIntoRect(snap_rect, FALSE);
+ translateIntoRect(snap_rect);
}
break;
@@ -949,7 +950,7 @@ void LLFloater::applyPositioning(LLFloater* other)
setOrigin(horizontal_offset, vertical_offset - rect_height);
translate(snap_rect.mLeft, snap_rect.mBottom);
- translateIntoRect(snap_rect, FALSE);
+ translateIntoRect(snap_rect);
}
break;
@@ -1681,6 +1682,8 @@ LLFloater* LLFloater::getClosableFloaterFromFocus()
{
if (it->hasFocus())
{
+ LLFloater& floater = *it;
+ focused_floater = &floater;
break;
}
}
@@ -1800,7 +1803,7 @@ void LLFloater::draw()
const LLFontGL* font = LLFontGL::getFontSansSerif();
LLRect r = getRect();
- gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1,
+ gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - font->getLineHeight() - 1,
titlebar_focus_color % alpha, 0, TRUE);
}
}
@@ -2641,6 +2644,8 @@ void LLFloaterView::refresh()
}
}
+const S32 FLOATER_MIN_VISIBLE_PIXELS = 16;
+
void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside)
{
if (floater->getParent() != this)
@@ -2694,7 +2699,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
}
// move window fully onscreen
- if (floater->translateIntoRect( getSnapRect(), allow_partial_outside ))
+ if (floater->translateIntoRect( getSnapRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX ))
{
floater->clearSnapTarget();
}
@@ -3269,3 +3274,112 @@ void LLFloater::stackWith(LLFloater& other)
setShape(next_rect);
}
+LLCoordFloater::LLCoordFloater(F32 x, F32 y, LLFloater& floater)
+: coord_t((S32)x, (S32)y)
+{
+ mFloater = floater.getHandle();
+}
+
+
+LLCoordFloater::LLCoordFloater(const LLCoordCommon& other, LLFloater& floater)
+{
+ mFloater = floater.getHandle();
+ convertFromCommon(other);
+}
+
+LLCoordFloater& LLCoordFloater::operator=(const LLCoordFloater& other)
+{
+ mFloater = other.mFloater;
+ coord_t::operator =(other);
+ return *this;
+}
+
+void LLCoordFloater::setFloater(LLFloater& floater)
+{
+ mFloater = floater.getHandle();
+}
+
+bool LLCoordFloater::operator==(const LLCoordFloater& other) const
+{
+ return mX == other.mX && mY == other.mY && mFloater == other.mFloater;
+}
+
+LLCoordCommon LL_COORD_FLOATER::convertToCommon() const
+{
+ const LLCoordFloater& self = static_cast<const LLCoordFloater&>(*this);
+
+ LLRect snap_rect = gFloaterView->getSnapRect();
+ LLFloater* floaterp = mFloater.get();
+ S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0;
+ S32 floater_height = floaterp ? floaterp->getRect().getHeight() : 0;
+ LLCoordCommon out;
+ if (self.mX < -0.5f)
+ {
+ out.mX = llround(rescale(self.mX, -1.f, -0.5f, snap_rect.mLeft - (floater_width - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mLeft));
+ }
+ else if (self.mX > 0.5f)
+ {
+ out.mX = llround(rescale(self.mX, 0.5f, 1.f, snap_rect.mRight - floater_width, snap_rect.mRight - FLOATER_MIN_VISIBLE_PIXELS));
+ }
+ else
+ {
+ out.mX = llround(rescale(self.mX, -0.5f, 0.5f, snap_rect.mLeft, snap_rect.mRight - floater_width));
+ }
+
+ if (self.mY < -0.5f)
+ {
+ out.mY = llround(rescale(self.mY, -1.f, -0.5f, snap_rect.mBottom - (floater_height - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mBottom));
+ }
+ else if (self.mY > 0.5f)
+ {
+ out.mY = llround(rescale(self.mY, 0.5f, 1.f, snap_rect.mTop - floater_height, snap_rect.mTop - FLOATER_MIN_VISIBLE_PIXELS));
+ }
+ else
+ {
+ out.mY = llround(rescale(self.mY, -0.5f, 0.5f, snap_rect.mBottom, snap_rect.mTop - floater_height));
+ }
+
+ // return center point instead of lower left
+ out.mX += floater_width / 2;
+ out.mY += floater_height / 2;
+
+ return out;
+}
+
+void LL_COORD_FLOATER::convertFromCommon(const LLCoordCommon& from)
+{
+ LLCoordFloater& self = static_cast<LLCoordFloater&>(*this);
+ LLRect snap_rect = gFloaterView->getSnapRect();
+ LLFloater* floaterp = mFloater.get();
+ S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0;
+ S32 floater_height = floaterp ? floaterp->getRect().getHeight() : 0;
+
+ S32 from_x = from.mX - floater_width / 2;
+ S32 from_y = from.mY - floater_height / 2;
+
+ if (from_x < snap_rect.mLeft)
+ {
+ self.mX = rescale(from_x, snap_rect.mLeft - (floater_width - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mLeft, -1.f, -0.5f);
+ }
+ else if (from_x + floater_width > snap_rect.mRight)
+ {
+ self.mX = rescale(from_x, snap_rect.mRight - floater_width, snap_rect.mRight - FLOATER_MIN_VISIBLE_PIXELS, 0.5f, 1.f);
+ }
+ else
+ {
+ self.mX = rescale(from_x, snap_rect.mLeft, snap_rect.mRight - floater_width, -0.5f, 0.5f);
+ }
+
+ if (from_y < snap_rect.mBottom)
+ {
+ self.mY = rescale(from_y, snap_rect.mBottom - (floater_height - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mBottom, -1.f, -0.5f);
+ }
+ else if (from_y + floater_height > snap_rect.mTop)
+ {
+ self.mY = rescale(from_y, snap_rect.mTop - floater_height, snap_rect.mTop - FLOATER_MIN_VISIBLE_PIXELS, 0.5f, 1.f);
+ }
+ else
+ {
+ self.mY = rescale(from_y, snap_rect.mBottom, snap_rect.mTop - floater_height, -0.5f, 0.5f);
+ }
+}
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 59b35d206f..a7cc9ae961 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -82,6 +82,37 @@ namespace LLInitParam
};
}
+struct LL_COORD_FLOATER
+{
+ typedef F32 value_t;
+
+ LLCoordCommon convertToCommon() const;
+ void convertFromCommon(const LLCoordCommon& from);
+protected:
+ LLHandle<LLFloater> mFloater;
+};
+
+struct LLCoordFloater : LLCoord<LL_COORD_FLOATER>
+{
+ typedef LLCoord<LL_COORD_FLOATER> coord_t;
+
+ LLCoordFloater() {}
+ LLCoordFloater(F32 x, F32 y, LLFloater& floater);
+ LLCoordFloater(const LLCoordCommon& other, LLFloater& floater);
+
+ LLCoordFloater& operator=(const LLCoordCommon& other)
+ {
+ convertFromCommon(other);
+ return *this;
+ }
+
+ LLCoordFloater& operator=(const LLCoordFloater& other);
+
+ bool operator==(const LLCoordFloater& other) const;
+ bool operator!=(const LLCoordFloater& other) const { return !(*this == other); }
+
+ void setFloater(LLFloater& floater);
+};
class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater>
{
@@ -184,7 +215,7 @@ public:
bool initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node = NULL);
/*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false);
- /*virtual*/ BOOL canSnapTo(const LLView* other_view);
+ /*virtual*/ BOOL canSnapTo(const LLView* other_view);
/*virtual*/ void setSnappedTo(const LLView* snap_view);
/*virtual*/ void setFocus( BOOL b );
/*virtual*/ void setIsChrome(BOOL is_chrome);
@@ -425,6 +456,7 @@ private:
LLFloaterEnums::EOpenPositioning mOpenPositioning;
S32 mSpecifiedLeft;
S32 mSpecifiedBottom;
+ LLCoordFloater mPosition;
S32 mMinWidth;
S32 mMinHeight;
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 2f1c2a47c9..ae262f794e 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -36,7 +36,7 @@
#include "llcriticaldamp.h"
#include "boost/foreach.hpp"
-static const F32 MIN_FRACTIONAL_SIZE = 0.0001f;
+static const F32 MIN_FRACTIONAL_SIZE = 0.0f;
static const F32 MAX_FRACTIONAL_SIZE = 1.f;
static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack");
@@ -129,6 +129,12 @@ void LLLayoutPanel::setOrientation( LLLayoutStack::ELayoutOrientation orientatio
? getRect().getWidth()
: getRect().getHeight()));
+ if (mAutoResize == FALSE
+ && mUserResize == TRUE
+ && mMinDim == -1 )
+ {
+ setMinDim(layout_dim);
+ }
mTargetDim = llmax(layout_dim, getMinDim());
}
@@ -306,7 +312,6 @@ void LLLayoutStack::updateLayout()
bool animation_in_progress = animatePanels();
F32 total_visible_fraction = 0.f;
- F32 total_open_fraction = 0.f;
S32 space_to_distribute = (mOrientation == HORIZONTAL)
? getRect().getWidth()
: getRect().getHeight();
@@ -318,20 +323,17 @@ void LLLayoutStack::updateLayout()
if (panelp->mAutoResize)
{
panelp->mTargetDim = panelp->getRelevantMinDim();
- if (!panelp->mCollapsed && panelp->getVisible())
- {
- total_open_fraction += panelp->mFractionalSize;
- }
}
space_to_distribute -= panelp->getVisibleDim() + llround((F32)mPanelSpacing * panelp->getVisibleAmount());
- total_visible_fraction += panelp->mFractionalSize;
+ total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor();
}
- llassert(total_visible_fraction < 1.01f);
+ llassert(total_visible_fraction < 1.05f);
// don't need spacing after last panel
space_to_distribute += panelp ? llround((F32)mPanelSpacing * panelp->getVisibleAmount()) : 0;
+ S32 remaining_space = space_to_distribute;
F32 fraction_distributed = 0.f;
if (space_to_distribute > 0 && total_visible_fraction > 0.f)
{ // give space proportionally to visible auto resize panels
@@ -343,26 +345,23 @@ void LLLayoutStack::updateLayout()
S32 delta = llround((F32)space_to_distribute * fraction_to_distribute);
fraction_distributed += fraction_to_distribute;
panelp->mTargetDim += delta;
+ remaining_space -= delta;
}
}
}
- if (fraction_distributed < total_visible_fraction)
- { // distribute any left over pixels to non-collapsed, visible panels
- F32 fraction_left = total_visible_fraction - fraction_distributed;
- S32 space_left = llround((F32)space_to_distribute * (fraction_left / total_visible_fraction));
+ // distribute any left over pixels to non-collapsed, visible panels
+ BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
+ {
+ if (remaining_space == 0) break;
- BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
+ if (panelp->mAutoResize
+ && !panelp->mCollapsed
+ && panelp->getVisible())
{
- if (panelp->mAutoResize
- && !panelp->mCollapsed
- && panelp->getVisible())
- {
- S32 space_for_panel = llmax(0, llround((F32)space_left * (panelp->mFractionalSize / total_open_fraction)));
- panelp->mTargetDim += space_for_panel;
- space_left -= space_for_panel;
- total_open_fraction -= panelp->mFractionalSize;
- }
+ S32 space_for_panel = remaining_space > 0 ? 1 : -1;
+ panelp->mTargetDim += space_for_panel;
+ remaining_space -= space_for_panel;
}
}
@@ -494,33 +493,46 @@ void LLLayoutStack::updateClass()
void LLLayoutStack::updateFractionalSizes()
{
- F32 total_resizable_dim = 0;
- S32 num_auto_resize_panels = 0;
+ F32 total_resizable_dim = 0.f;
BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
{
if (panelp->mAutoResize)
{
total_resizable_dim += llmax(0, panelp->getLayoutDim() - panelp->getRelevantMinDim());
- num_auto_resize_panels++;
}
}
- F32 total_fractional_size = 0.f;
-
BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
{
if (panelp->mAutoResize)
{
F32 panel_resizable_dim = llmax(MIN_FRACTIONAL_SIZE, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim()));
panelp->mFractionalSize = panel_resizable_dim > 0.f
- ? llclamp(panel_resizable_dim / total_resizable_dim, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE)
- : MIN_FRACTIONAL_SIZE;
- total_fractional_size += panelp->mFractionalSize;
+ ? llclamp(panel_resizable_dim / total_resizable_dim, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE)
+ : MIN_FRACTIONAL_SIZE;
llassert(!llisnan(panelp->mFractionalSize));
}
}
+ normalizeFractionalSizes();
+}
+
+
+void LLLayoutStack::normalizeFractionalSizes()
+{
+ S32 num_auto_resize_panels = 0;
+ F32 total_fractional_size = 0.f;
+
+ BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
+ {
+ if (panelp->mAutoResize)
+ {
+ total_fractional_size += panelp->mFractionalSize;
+ num_auto_resize_panels++;
+ }
+ }
+
if (total_fractional_size == 0.f)
{ // equal distribution
BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
@@ -632,7 +644,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
F32 total_visible_fraction = 0.f;
F32 delta_auto_resize_headroom = 0.f;
- F32 total_auto_resize_headroom = 0.f;
+ F32 original_auto_resize_headroom = 0.f;
LLLayoutPanel* other_resize_panel = NULL;
LLLayoutPanel* following_panel = NULL;
@@ -641,8 +653,11 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
{
if (panelp->mAutoResize)
{
- total_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim());
- total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor();
+ original_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim());
+ if (panelp->getVisible() && !panelp->mCollapsed)
+ {
+ total_visible_fraction += panelp->mFractionalSize;
+ }
}
if (panelp == resized_panel)
@@ -656,18 +671,25 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
}
}
- if (resized_panel->mAutoResize == FALSE)
+
+ if (resized_panel->mAutoResize)
{
- delta_auto_resize_headroom += -delta_dim;
+ if (!other_resize_panel || !other_resize_panel->mAutoResize)
+ {
+ delta_auto_resize_headroom += delta_dim;
+ }
}
- if (other_resize_panel && other_resize_panel->mAutoResize == FALSE)
+ else
{
- delta_auto_resize_headroom += delta_dim;
+ if (!other_resize_panel || other_resize_panel->mAutoResize)
+ {
+ delta_auto_resize_headroom -= delta_dim;
+ }
}
F32 fraction_given_up = 0.f;
F32 fraction_remaining = 1.f;
- F32 updated_auto_resize_headroom = total_auto_resize_headroom + delta_auto_resize_headroom;
+ F32 updated_auto_resize_headroom = original_auto_resize_headroom + delta_auto_resize_headroom;
enum
{
@@ -691,14 +713,15 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
case BEFORE_RESIZED_PANEL:
if (panelp->mAutoResize)
{ // freeze current size as fraction of overall auto_resize space
- F32 fractional_adjustment_factor = total_auto_resize_headroom / updated_auto_resize_headroom;
+ F32 fractional_adjustment_factor = updated_auto_resize_headroom == 0.f
+ ? 1.f
+ : original_auto_resize_headroom / updated_auto_resize_headroom;
F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor,
MIN_FRACTIONAL_SIZE,
MAX_FRACTIONAL_SIZE);
- F32 fraction_delta = (new_fractional_size - panelp->mFractionalSize);
- fraction_given_up -= fraction_delta;
+ fraction_given_up -= new_fractional_size - panelp->mFractionalSize;
fraction_remaining -= panelp->mFractionalSize;
- panelp->mFractionalSize += fraction_delta;
+ panelp->mFractionalSize = new_fractional_size;
llassert(!llisnan(panelp->mFractionalSize));
}
else
@@ -711,7 +734,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
{ // freeze new size as fraction
F32 new_fractional_size = (updated_auto_resize_headroom == 0.f)
? MAX_FRACTIONAL_SIZE
- : llclamp((F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE);
+ : llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE);
fraction_given_up -= new_fractional_size - panelp->mFractionalSize;
fraction_remaining -= panelp->mFractionalSize;
panelp->mFractionalSize = new_fractional_size;
@@ -720,7 +743,6 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
else
{ // freeze new size as original size
panelp->mTargetDim = new_dim;
- fraction_remaining -= fraction_given_up;
}
which_panel = NEXT_PANEL;
break;
@@ -728,14 +750,14 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
if (panelp->mAutoResize)
{
fraction_remaining -= panelp->mFractionalSize;
- if (fraction_given_up != 0.f)
+ if (resized_panel->mAutoResize)
{
panelp->mFractionalSize = llclamp(panelp->mFractionalSize + fraction_given_up, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE);
fraction_given_up = 0.f;
}
else
{
- F32 new_fractional_size = llclamp((F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom)
+ F32 new_fractional_size = llclamp(total_visible_fraction * (F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom)
/ updated_auto_resize_headroom,
MIN_FRACTIONAL_SIZE,
MAX_FRACTIONAL_SIZE);
@@ -750,7 +772,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
which_panel = AFTER_RESIZED_PANEL;
break;
case AFTER_RESIZED_PANEL:
- if (panelp->mAutoResize)
+ if (panelp->mAutoResize && fraction_given_up != 0.f)
{
panelp->mFractionalSize = llclamp(panelp->mFractionalSize + (panelp->mFractionalSize / fraction_remaining) * fraction_given_up,
MIN_FRACTIONAL_SIZE,
@@ -760,6 +782,8 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
break;
}
}
+ updateLayout();
+ normalizeFractionalSizes();
}
void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent)
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index efe93f6def..d32caec5f9 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -72,7 +72,7 @@ public:
/*virtual*/ void draw();
/*virtual*/ void removeChild(LLView*);
/*virtual*/ BOOL postBuild();
- /*virtual*/ bool addChild(LLView* child, S32 tab_group = 0);
+ /*virtual*/ bool addChild(LLView* child, S32 tab_groupdatefractuiona = 0);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
@@ -112,6 +112,7 @@ private:
LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const;
LLLayoutPanel* findEmbeddedPanelByName(const std::string& name) const;
void updateFractionalSizes();
+ void normalizeFractionalSizes();
void updatePanelRect( LLLayoutPanel* param1, const LLRect& new_rect );
S32 mPanelSpacing;
@@ -154,10 +155,10 @@ public:
void setVisible(BOOL visible);
S32 getLayoutDim() const;
- S32 getMinDim() const { return (mMinDim >= 0 || mAutoResize) ? llmax(0, mMinDim) : getLayoutDim(); }
+ S32 getMinDim() const { return llmax(0, mMinDim); }
void setMinDim(S32 value) { mMinDim = value; }
- S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : mMinDim; }
+ S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : getMinDim(); }
void setExpandedMinDim(S32 value) { mExpandedMinDim = value; }
S32 getRelevantMinDim() const
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 06dfc90d83..7e84814c51 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -1630,7 +1630,7 @@ void LLLineEditor::draw()
LLRect background( 0, getRect().getHeight(), getRect().getWidth(), 0 );
background.stretch( -mBorderThickness );
- S32 lineeditor_v_pad = llround((background.getHeight() - mGLFont->getLineHeight())/2);
+ S32 lineeditor_v_pad = (background.getHeight() - mGLFont->getLineHeight()) / 2;
drawBackground();
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 95ecbb1c94..ff6928ffda 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -317,7 +317,7 @@ void LLMenuItemGL::setJumpKey(KEY key)
// virtual
U32 LLMenuItemGL::getNominalHeight( void ) const
{
- return llround(mFont->getLineHeight()) + MENU_ITEM_PADDING;
+ return mFont->getLineHeight() + MENU_ITEM_PADDING;
}
//virtual
@@ -508,19 +508,19 @@ void LLMenuItemGL::draw( void )
{
if( !mDrawBoolLabel.empty() )
{
- mFont->render( mDrawBoolLabel.getWString(), 0, (F32)LEFT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color,
+ mFont->render( mDrawBoolLabel.getWString(), 0, (F32)LEFT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
}
- mFont->render( mLabel.getWString(), 0, (F32)LEFT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color,
+ mFont->render( mLabel.getWString(), 0, (F32)LEFT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
if( !mDrawAccelLabel.empty() )
{
- mFont->render( mDrawAccelLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color,
+ mFont->render( mDrawAccelLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color,
LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
}
if( !mDrawBranchLabel.empty() )
{
- mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color,
+ mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color,
LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
}
}
@@ -1966,7 +1966,7 @@ void LLMenuGL::arrange( void )
// *FIX: create the item first and then ask for its dimensions?
S32 spillover_item_width = PLAIN_PAD_PIXELS + LLFontGL::getFontSansSerif()->getWidth( std::string("More") ); // *TODO: Translate
- S32 spillover_item_height = llround(LLFontGL::getFontSansSerif()->getLineHeight()) + MENU_ITEM_PADDING;
+ S32 spillover_item_height = LLFontGL::getFontSansSerif()->getLineHeight() + MENU_ITEM_PADDING;
// Scrolling support
item_list_t::iterator first_visible_item_iter;
@@ -3082,7 +3082,7 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
mouse_y + MOUSE_CURSOR_PADDING,
CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2,
CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2);
- menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect, FALSE );
+ menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect );
menu->getParent()->sendChildToFront(menu);
}
@@ -3425,7 +3425,7 @@ void LLMenuHolderGL::draw()
LLUI::pushMatrix();
{
- LLUI::translate((F32)item_rect.mLeft, (F32)item_rect.mBottom, 0.f);
+ LLUI::translate((F32)item_rect.mLeft, (F32)item_rect.mBottom);
selecteditem->getMenu()->drawBackground(selecteditem, interpolant);
selecteditem->draw();
}
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index d232e27ef2..8aa548b974 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -1412,6 +1412,7 @@ void addPathIfExists(const std::string& new_path, std::vector<std::string>& path
bool LLNotifications::loadTemplates()
{
+ llinfos << "Reading notifications template" << llendl;
std::vector<std::string> search_paths;
std::string skin_relative_path = gDirUtilp->getDirDelimiter() + LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + "notifications.xml";
@@ -1484,6 +1485,8 @@ bool LLNotifications::loadTemplates()
mTemplates[notification.name] = LLNotificationTemplatePtr(new LLNotificationTemplate(notification));
}
+ llinfos << "...done" << llendl;
+
return true;
}
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index ad4cc20d9a..20bed050ad 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -378,23 +378,21 @@ void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height
if (!mHideScrollbar)
{
- if( *visible_height < doc_height )
+ // Note: 1 pixel change can happen on final animation and should not trigger
+ // the display of sliders.
+ if ((doc_height - *visible_height) > 1)
{
*show_v_scrollbar = TRUE;
*visible_width -= scrollbar_size;
}
-
- if( *visible_width < doc_width )
+ if ((doc_width - *visible_width) > 1)
{
*show_h_scrollbar = TRUE;
*visible_height -= scrollbar_size;
-
- // Must retest now that visible_height has changed
- if( !*show_v_scrollbar && (*visible_height < doc_height) )
- {
- *show_v_scrollbar = TRUE;
- *visible_width -= scrollbar_size;
- }
+ // Note: Do *not* recompute *show_v_scrollbar here because with
+ // the (- scrollbar_size) we just did we will always add a vertical scrollbar
+ // even if the height of the items is actually less than the visible size.
+ // Fear not though: there's enough calcVisibleSize() calls to add a vertical slider later.
}
}
}
diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp
index 9d25c7180d..8000efad0e 100644
--- a/indra/llui/llscrolllistcell.cpp
+++ b/indra/llui/llscrolllistcell.cpp
@@ -232,7 +232,7 @@ BOOL LLScrollListText::getVisible() const
//virtual
S32 LLScrollListText::getHeight() const
{
- return llround(mFont->getLineHeight());
+ return mFont->getLineHeight();
}
@@ -306,7 +306,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
break;
}
LLRect highlight_rect(left - 2,
- llround(mFont->getLineHeight()) + 1,
+ mFont->getLineHeight() + 1,
left + mFont->getWidth(mText.getString(), mHighlightOffset, mHighlightCount) + 1,
1);
mRoundedRectImage->draw(highlight_rect, highlight_color);
@@ -329,7 +329,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
break;
}
mFont->render(mText.getWString(), 0,
- start_x, 2.f,
+ start_x, 0.f,
display_color,
mFontAlignment,
LLFontGL::BOTTOM,
diff --git a/indra/llui/llscrolllistitem.cpp b/indra/llui/llscrolllistitem.cpp
index d95752e31c..5a1e96ab03 100644
--- a/indra/llui/llscrolllistitem.cpp
+++ b/indra/llui/llscrolllistitem.cpp
@@ -138,7 +138,7 @@ void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const
LLUI::pushMatrix();
{
- LLUI::translate((F32) cur_x, (F32) rect.mBottom, 0.0f);
+ LLUI::translate((F32) cur_x, (F32) rect.mBottom);
cell->draw( fg_color, highlight_color );
}
diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h
index 611df729b4..13655b5873 100644
--- a/indra/llui/llscrolllistitem.h
+++ b/indra/llui/llscrolllistitem.h
@@ -33,10 +33,10 @@
#include "v4color.h"
#include "llinitparam.h"
#include "llscrolllistcell.h"
+#include "llcoord.h"
#include <vector>
-class LLCoordGL;
class LLCheckBoxCtrl;
class LLResizeBar;
class LLScrollListCtrl;
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 0040be45c7..7aeeae298f 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1192,7 +1192,10 @@ void LLTextBase::reflow()
// shrink document to minimum size (visible portion of text widget)
// to force inlined widgets with follows set to shrink
- mDocumentView->reshape(mVisibleTextRect.getWidth(), mDocumentView->getRect().getHeight());
+ if (mWordWrap)
+ {
+ mDocumentView->reshape(mVisibleTextRect.getWidth(), mDocumentView->getRect().getHeight());
+ }
S32 cur_top = 0;
@@ -2157,7 +2160,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
{
// return default height rect in upper left
local_rect = content_window_rect;
- local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight());
+ local_rect.mBottom = local_rect.mTop - mDefaultFont->getLineHeight();
return local_rect;
}
@@ -2380,6 +2383,9 @@ S32 LLTextBase::getEditableIndex(S32 index, bool increasing_direction)
void LLTextBase::updateRects()
{
+ LLRect old_text_rect = mVisibleTextRect;
+ mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
+
if (mLineInfoList.empty())
{
mTextBoundingRect = LLRect(0, mVPad, mHPad, 0);
@@ -2395,10 +2401,24 @@ void LLTextBase::updateRects()
}
mTextBoundingRect.mTop += mVPad;
- // subtract a pixel off the bottom to deal with rounding errors in measuring font height
- mTextBoundingRect.mBottom -= 1;
- S32 delta_pos = -mTextBoundingRect.mBottom;
+ S32 delta_pos = 0;
+
+ switch(mVAlign)
+ {
+ case LLFontGL::TOP:
+ delta_pos = llmax(mVisibleTextRect.getHeight() - mTextBoundingRect.mTop, -mTextBoundingRect.mBottom);
+ break;
+ case LLFontGL::VCENTER:
+ delta_pos = (llmax(mVisibleTextRect.getHeight() - mTextBoundingRect.mTop, -mTextBoundingRect.mBottom) + (mVisibleTextRect.mBottom - mTextBoundingRect.mBottom)) / 2;
+ break;
+ case LLFontGL::BOTTOM:
+ delta_pos = mVisibleTextRect.mBottom - mTextBoundingRect.mBottom;
+ break;
+ case LLFontGL::BASELINE:
+ // do nothing
+ break;
+ }
// move line segments to fit new document rect
for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
{
@@ -2408,8 +2428,9 @@ void LLTextBase::updateRects()
}
// update document container dimensions according to text contents
- LLRect doc_rect = mTextBoundingRect;
+ LLRect doc_rect;
// use old mVisibleTextRect constraint document to width of viewable region
+ doc_rect.mBottom = llmin(mVisibleTextRect.mBottom, mTextBoundingRect.mBottom);
doc_rect.mLeft = 0;
// allow horizontal scrolling?
@@ -2419,11 +2440,22 @@ void LLTextBase::updateRects()
doc_rect.mRight = mScroller
? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)
: mVisibleTextRect.getWidth();
+ doc_rect.mTop = llmax(mVisibleTextRect.mTop, mTextBoundingRect.mTop);
if (!mScroller)
{
// push doc rect to top of text widget
- doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop);
+ switch(mVAlign)
+ {
+ case LLFontGL::TOP:
+ doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop);
+ break;
+ case LLFontGL::VCENTER:
+ doc_rect.translate(0, (mVisibleTextRect.getHeight() - doc_rect.mTop) / 2);
+ case LLFontGL::BOTTOM:
+ default:
+ break;
+ }
}
mDocumentView->setShape(doc_rect);
@@ -2431,7 +2463,6 @@ void LLTextBase::updateRects()
//update mVisibleTextRect *after* mDocumentView has been resized
// so that scrollbars are added if document needs to scroll
// since mVisibleTextRect does not include scrollbars
- LLRect old_text_rect = mVisibleTextRect;
mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
//FIXME: replace border with image?
if (mBorderVisible)
@@ -2444,9 +2475,27 @@ void LLTextBase::updateRects()
}
// update document container again, using new mVisibleTextRect (that has scrollbars enabled as needed)
+ doc_rect.mBottom = llmin(mVisibleTextRect.mBottom, mTextBoundingRect.mBottom);
+ doc_rect.mLeft = 0;
doc_rect.mRight = mScroller
? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)
: mVisibleTextRect.getWidth();
+ doc_rect.mTop = llmax(mVisibleTextRect.mTop, mTextBoundingRect.mTop);
+ if (!mScroller)
+ {
+ // push doc rect to top of text widget
+ switch(mVAlign)
+ {
+ case LLFontGL::TOP:
+ doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop);
+ break;
+ case LLFontGL::VCENTER:
+ doc_rect.translate(0, (mVisibleTextRect.getHeight() - doc_rect.mTop) / 2);
+ case LLFontGL::BOTTOM:
+ default:
+ break;
+ }
+ }
mDocumentView->setShape(doc_rect);
}
@@ -2560,8 +2609,7 @@ BOOL LLTextSegment::handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE;
BOOL LLTextSegment::handleToolTip(S32 x, S32 y, MASK mask) { return FALSE; }
const std::string& LLTextSegment::getName() const
{
- static std::string empty_string("");
- return empty_string;
+ return LLStringUtil::null;
}
void LLTextSegment::onMouseCaptureLost() {}
void LLTextSegment::screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {}
@@ -2578,7 +2626,7 @@ LLNormalTextSegment::LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 e
mToken(NULL),
mEditor(editor)
{
- mFontHeight = llceil(mStyle->getFont()->getLineHeight());
+ mFontHeight = mStyle->getFont()->getLineHeight();
LLUIImagePtr image = mStyle->getImage();
if (image.notNull())
@@ -2594,7 +2642,7 @@ LLNormalTextSegment::LLNormalTextSegment( const LLColor4& color, S32 start, S32
{
mStyle = new LLStyle(LLStyle::Params().visible(is_visible).color(color));
- mFontHeight = llceil(mStyle->getFont()->getLineHeight());
+ mFontHeight = mStyle->getFont()->getLineHeight();
}
LLNormalTextSegment::~LLNormalTextSegment()
@@ -2962,11 +3010,11 @@ LLLineBreakTextSegment::LLLineBreakTextSegment(S32 pos):LLTextSegment(pos,pos+1)
{
LLStyleSP s( new LLStyle(LLStyle::Params().visible(true)));
- mFontHeight = llceil(s->getFont()->getLineHeight());
+ mFontHeight = s->getFont()->getLineHeight();
}
LLLineBreakTextSegment::LLLineBreakTextSegment(LLStyleConstSP style,S32 pos):LLTextSegment(pos,pos+1)
{
- mFontHeight = llceil(style->getFont()->getLineHeight());
+ mFontHeight = style->getFont()->getLineHeight();
}
LLLineBreakTextSegment::~LLLineBreakTextSegment()
{
@@ -3003,7 +3051,7 @@ static const S32 IMAGE_HPAD = 3;
bool LLImageTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
{
width = 0;
- height = llceil(mStyle->getFont()->getLineHeight());;
+ height = mStyle->getFont()->getLineHeight();
LLUIImagePtr image = mStyle->getImage();
if( num_chars>0 && image.notNull())
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 3a23ce1cac..3409b6817d 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -1992,7 +1992,7 @@ void LLTextEditor::drawPreeditMarker()
return;
}
- const S32 line_height = llround( mDefaultFont->getLineHeight() );
+ const S32 line_height = mDefaultFont->getLineHeight();
S32 line_start = getLineStart(cur_line);
S32 line_y = mVisibleTextRect.mTop - line_height;
@@ -2715,7 +2715,7 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect
const LLWString textString(getWText());
const llwchar * const text = textString.c_str();
- const S32 line_height = llround(mDefaultFont->getLineHeight());
+ const S32 line_height = mDefaultFont->getLineHeight();
if (coord)
{
@@ -2818,7 +2818,7 @@ void LLTextEditor::markAsPreedit(S32 position, S32 length)
S32 LLTextEditor::getPreeditFontSize() const
{
- return llround(mDefaultFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);
+ return llround((F32)mDefaultFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);
}
BOOL LLTextEditor::isDirty() const
diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index 9b31a6449d..81ea0ebf0c 100644
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -827,7 +827,7 @@ void LLToolBar::draw()
// rect may have shifted during layout
LLUI::popMatrix();
LLUI::pushMatrix();
- LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom, 0.f);
+ LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom);
// Position the caret
LLIconCtrl* caret = getChild<LLIconCtrl>("caret");
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index 23cdd9ad9a..f737d48abf 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -180,6 +180,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)
params.font = p.font;
params.use_ellipses = true;
params.wrap = p.wrap;
+ params.font_valign = LLFontGL::VCENTER;
params.parse_urls = false; // disallow hyperlinks in tooltips, as they want to spawn their own explanatory tooltips
mTextBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild(mTextBox);
@@ -190,7 +191,6 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)
{
LLButton::Params icon_params;
icon_params.name = "tooltip_info";
- icon_params.label(""); // provid label but set to empty so name does not overwrite it -angela
LLRect icon_rect;
LLUIImage* imagep = p.image;
TOOLTIP_ICON_SIZE = (imagep ? imagep->getWidth() : 16);
@@ -291,6 +291,12 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p)
S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth());
S32 text_height = mTextBox->getTextPixelHeight();
mTextBox->reshape(text_width, text_height);
+ if (mInfoButton)
+ {
+ LLRect text_rect = mTextBox->getRect();
+ LLRect icon_rect = mInfoButton->getRect();
+ mTextBox->translate(0, icon_rect.getCenterY() - text_rect.getCenterY());
+ }
// reshape tooltip panel to fit text box
LLRect tooltip_rect = calcBoundingRect();
@@ -299,6 +305,8 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p)
tooltip_rect.mBottom = 0;
tooltip_rect.mLeft = 0;
+ mTextBox->reshape(mTextBox->getRect().getWidth(), llmax(mTextBox->getRect().getHeight(), tooltip_rect.getHeight() - 2 * mPadding));
+
setShape(tooltip_rect);
}
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 6b74c5a6be..b5e27616b7 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -972,43 +972,53 @@ void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor
// Draw gray and white checkerboard with black border
void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha)
{
- // Initialize the first time this is called.
- const S32 PIXELS = 32;
- static GLubyte checkerboard[PIXELS * PIXELS];
- static BOOL first = TRUE;
- if( first )
- {
- for( S32 i = 0; i < PIXELS; i++ )
+ if (!LLGLSLShader::sNoFixedFunction)
+ {
+ // Initialize the first time this is called.
+ const S32 PIXELS = 32;
+ static GLubyte checkerboard[PIXELS * PIXELS];
+ static BOOL first = TRUE;
+ if( first )
{
- for( S32 j = 0; j < PIXELS; j++ )
+ for( S32 i = 0; i < PIXELS; i++ )
{
- checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF;
+ for( S32 j = 0; j < PIXELS; j++ )
+ {
+ checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF;
+ }
}
+ first = FALSE;
}
- first = FALSE;
- }
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- // ...white squares
- gGL.color4f( 1.f, 1.f, 1.f, alpha );
- gl_rect_2d(rect);
+ // ...white squares
+ gGL.color4f( 1.f, 1.f, 1.f, alpha );
+ gl_rect_2d(rect);
- // ...gray squares
- gGL.color4f( .7f, .7f, .7f, alpha );
- gGL.flush();
+ // ...gray squares
+ gGL.color4f( .7f, .7f, .7f, alpha );
+ gGL.flush();
- if (!LLGLSLShader::sNoFixedFunction)
- { //polygon stipple is deprecated
glPolygonStipple( checkerboard );
LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE);
gl_rect_2d(rect);
}
else
- {
- gl_rect_2d(rect);
+ { //polygon stipple is deprecated, use "Checker" texture
+ LLPointer<LLUIImage> img = LLUI::getUIImage("Checker");
+ gGL.getTexUnit(0)->bind(img->getImage());
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+
+ LLColor4 color(1.f, 1.f, 1.f, alpha);
+ LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f);
+
+ gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(),
+ img->getImage(), color, uv_rect);
}
+
gGL.flush();
}
@@ -1688,21 +1698,22 @@ void LLUI::translate(F32 x, F32 y, F32 z)
gGL.translateUI(x,y,z);
LLFontGL::sCurOrigin.mX += (S32) x;
LLFontGL::sCurOrigin.mY += (S32) y;
- LLFontGL::sCurOrigin.mZ += z;
+ LLFontGL::sCurDepth += z;
}
//static
void LLUI::pushMatrix()
{
gGL.pushUIMatrix();
- LLFontGL::sOriginStack.push_back(LLFontGL::sCurOrigin);
+ LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth));
}
//static
void LLUI::popMatrix()
{
gGL.popUIMatrix();
- LLFontGL::sCurOrigin = *LLFontGL::sOriginStack.rbegin();
+ LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first;
+ LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second;
LLFontGL::sOriginStack.pop_back();
}
@@ -1712,7 +1723,7 @@ void LLUI::loadIdentity()
gGL.loadUIIdentity();
LLFontGL::sCurOrigin.mX = 0;
LLFontGL::sCurOrigin.mY = 0;
- LLFontGL::sCurOrigin.mZ = 0;
+ LLFontGL::sCurDepth = 0.f;
}
//static
@@ -1735,10 +1746,7 @@ void LLUI::setMousePositionScreen(S32 x, S32 y)
screen_x = llround((F32)x * sGLScaleFactor.mV[VX]);
screen_y = llround((F32)y * sGLScaleFactor.mV[VY]);
- LLCoordWindow window_point;
- LLView::getWindow()->convertCoords(LLCoordGL(screen_x, screen_y), &window_point);
-
- LLView::getWindow()->setCursorPosition(window_point);
+ LLView::getWindow()->setCursorPosition(LLCoordGL(screen_x, screen_y).convert());
}
//static
@@ -1746,8 +1754,7 @@ void LLUI::getMousePositionScreen(S32 *x, S32 *y)
{
LLCoordWindow cursor_pos_window;
getWindow()->getCursorPosition(&cursor_pos_window);
- LLCoordGL cursor_pos_gl;
- getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
+ LLCoordGL cursor_pos_gl(cursor_pos_window.convert());
*x = llround((F32)cursor_pos_gl.mX / sGLScaleFactor.mV[VX]);
*y = llround((F32)cursor_pos_gl.mY / sGLScaleFactor.mV[VX]);
}
@@ -2052,7 +2059,7 @@ void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y)
// Start at spawn position (using left/top)
view->setOrigin( local_x, local_y - view->getRect().getHeight());
// Make sure we're on-screen and not overlapping the mouse
- view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect, FALSE );
+ view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect );
}
LLView* LLUI::resolvePath(LLView* context, const std::string& path)
diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp
index ac69d3bf85..c4e073ccdb 100644
--- a/indra/llui/lluistring.cpp
+++ b/indra/llui/lluistring.cpp
@@ -128,17 +128,13 @@ void LLUIString::updateResult() const
}
mResult = mOrig;
- // get the defailt args + local args
- if (!mArgs || mArgs->empty())
+ // get the default args + local args
+ LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs();
+ if (mArgs && !mArgs->empty())
{
- LLStringUtil::format(mResult, LLTrans::getDefaultArgs());
- }
- else
- {
- LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs();
combined_args.insert(mArgs->begin(), mArgs->end());
- LLStringUtil::format(mResult, combined_args);
}
+ LLStringUtil::format(mResult, combined_args);
}
void LLUIString::updateWResult() const
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index e1ee0a5b14..421166dcd4 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -1106,7 +1106,7 @@ void LLView::drawChildren()
{
LLUI::pushMatrix();
{
- LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
+ LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom);
// flag the fact we are in draw here, in case overridden draw() method attempts to remove this widget
viewp->mInDraw = true;
viewp->draw();
@@ -1159,7 +1159,7 @@ void LLView::drawDebugRect()
if (getUseBoundingRect())
{
- LLUI::translate((F32)mBoundingRect.mLeft - (F32)mRect.mLeft, (F32)mBoundingRect.mBottom - (F32)mRect.mBottom, 0.f);
+ LLUI::translate((F32)mBoundingRect.mLeft - (F32)mRect.mLeft, (F32)mBoundingRect.mBottom - (F32)mRect.mBottom);
}
LLRect debug_rect = getUseBoundingRect() ? mBoundingRect : mRect;
@@ -1231,7 +1231,7 @@ void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_dr
gGL.matrixMode(LLRender::MM_MODELVIEW);
LLUI::pushMatrix();
{
- LLUI::translate((F32)childp->getRect().mLeft + x_offset, (F32)childp->getRect().mBottom + y_offset, 0.f);
+ LLUI::translate((F32)childp->getRect().mLeft + x_offset, (F32)childp->getRect().mBottom + y_offset);
childp->draw();
}
LLUI::popMatrix();
@@ -1300,7 +1300,10 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)
S32 delta_x = child_rect.mLeft - viewp->getRect().mLeft;
S32 delta_y = child_rect.mBottom - viewp->getRect().mBottom;
viewp->translate( delta_x, delta_y );
- viewp->reshape(child_rect.getWidth(), child_rect.getHeight());
+ if (child_rect.getWidth() != viewp->getRect().getWidth() || child_rect.getHeight() != viewp->getRect().getHeight())
+ {
+ viewp->reshape(child_rect.getWidth(), child_rect.getHeight());
+ }
}
}
@@ -1616,59 +1619,30 @@ LLView* LLView::findNextSibling(LLView* child)
}
-LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BOOL allow_partial_outside)
+LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, S32 min_overlap_pixels)
{
LLCoordGL delta;
- if (allow_partial_outside)
- {
- const S32 KEEP_ONSCREEN_PIXELS = 16;
+ const S32 KEEP_ONSCREEN_PIXELS_WIDTH = llmin(min_overlap_pixels, input.getWidth());
+ const S32 KEEP_ONSCREEN_PIXELS_HEIGHT = llmin(min_overlap_pixels, input.getHeight());
- if( input.mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft )
- {
- delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS);
- }
- else
- if( input.mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight )
- {
- delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS);
- }
+ if( input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH < constraint.mLeft )
+ {
+ delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH);
+ }
+ else if( input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH > constraint.mRight )
+ {
+ delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH);
+ }
- if( input.mTop > constraint.mTop )
- {
- delta.mY = constraint.mTop - input.mTop;
- }
- else
- if( input.mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom )
- {
- delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS);
- }
+ if( input.mTop > constraint.mTop )
+ {
+ delta.mY = constraint.mTop - input.mTop;
}
else
+ if( input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT < constraint.mBottom )
{
- if( input.mLeft < constraint.mLeft )
- {
- delta.mX = constraint.mLeft - input.mLeft;
- }
- else
- if( input.mRight > constraint.mRight )
- {
- delta.mX = constraint.mRight - input.mRight;
- // compensate for left edge possible going off screen
- delta.mX += llmax( 0, input.getWidth() - constraint.getWidth() );
- }
-
- if( input.mTop > constraint.mTop )
- {
- delta.mY = constraint.mTop - input.mTop;
- }
- else
- if( input.mBottom < constraint.mBottom )
- {
- delta.mY = constraint.mBottom - input.mBottom;
- // compensate for top edge possible going off screen
- delta.mY -= llmax( 0, input.getHeight() - constraint.getHeight() );
- }
+ delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT);
}
return delta;
@@ -1677,9 +1651,9 @@ LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BO
// Moves the view so that it is entirely inside of constraint.
// If the view will not fit because it's too big, aligns with the top and left.
// (Why top and left? That's where the drag bars are for floaters.)
-BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outside )
+BOOL LLView::translateIntoRect(const LLRect& constraint, S32 min_overlap_pixels)
{
- LLCoordGL translation = getNeededTranslation(getRect(), constraint, allow_partial_outside);
+ LLCoordGL translation = getNeededTranslation(getRect(), constraint, min_overlap_pixels);
if (translation.mX != 0 || translation.mY != 0)
{
@@ -1691,9 +1665,9 @@ BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outs
// move this view into "inside" but not onto "exclude"
// NOTE: if this view is already contained in "inside", we ignore the "exclude" rect
-BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside )
+BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, S32 min_overlap_pixels)
{
- LLCoordGL translation = getNeededTranslation(getRect(), inside, allow_partial_outside);
+ LLCoordGL translation = getNeededTranslation(getRect(), inside, min_overlap_pixels);
if (translation.mX != 0 || translation.mY != 0)
{
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index f1fac5f69c..fd19309a56 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -370,8 +370,8 @@ public:
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
virtual void translate( S32 x, S32 y );
void setOrigin( S32 x, S32 y ) { mRect.translate( x - mRect.mLeft, y - mRect.mBottom ); }
- BOOL translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside );
- BOOL translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside );
+ BOOL translateIntoRect( const LLRect& constraint, S32 min_overlap_pixels = S32_MAX);
+ BOOL translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, S32 min_overlap_pixels = S32_MAX);
void centerWithin(const LLRect& bounds);
void setShape(const LLRect& new_rect, bool by_user = false);
diff --git a/indra/llvfs/lllfsthread.cpp b/indra/llvfs/lllfsthread.cpp
index 3d3ed9f6d4..073b1af2a1 100644
--- a/indra/llvfs/lllfsthread.cpp
+++ b/indra/llvfs/lllfsthread.cpp
@@ -45,7 +45,7 @@ void LLLFSThread::initClass(bool local_is_threaded)
//static
S32 LLLFSThread::updateClass(U32 ms_elapsed)
{
- sLocal->update(ms_elapsed);
+ sLocal->update((F32)ms_elapsed);
return sLocal->getPending();
}
diff --git a/indra/llvfs/llvfsthread.cpp b/indra/llvfs/llvfsthread.cpp
index 254f8b55ba..a57e2b15ab 100644
--- a/indra/llvfs/llvfsthread.cpp
+++ b/indra/llvfs/llvfsthread.cpp
@@ -46,7 +46,7 @@ void LLVFSThread::initClass(bool local_is_threaded)
//static
S32 LLVFSThread::updateClass(U32 ms_elapsed)
{
- sLocal->update(ms_elapsed);
+ sLocal->update((F32)ms_elapsed);
return sLocal->getPending();
}
diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp
index d4d444eb28..15acddd987 100644
--- a/indra/llwindow/lldragdropwin32.cpp
+++ b/indra/llwindow/lldragdropwin32.cpp
@@ -124,10 +124,9 @@ class LLDragDropWin32Target:
ScreenToClient( mAppWindowHandle, &pt2 );
LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
- window_imp->convertCoords(cursor_coord_window, &gl_coord);
MASK mask = gKeyboard->currentMask(TRUE);
- LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
+ LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask,
LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl );
switch (result)
@@ -180,10 +179,9 @@ class LLDragDropWin32Target:
ScreenToClient( mAppWindowHandle, &pt2 );
LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
- window_imp->convertCoords(cursor_coord_window, &gl_coord);
MASK mask = gKeyboard->currentMask(TRUE);
- LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
+ LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask,
LLWindowCallbacks::DNDA_TRACK, mDropUrl );
switch (result)
@@ -237,15 +235,13 @@ class LLDragDropWin32Target:
LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA );
if ( NULL != window_imp )
{
- LLCoordGL gl_coord( 0, 0 );
-
POINT pt_client;
pt_client.x = pt.x;
pt_client.y = pt.y;
ScreenToClient( mAppWindowHandle, &pt_client );
LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y );
- window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ LLCoordGL gl_coord(cursor_coord_window.convert());
llinfos << "### (Drop) URL is: " << mDropUrl << llendl;
llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl;
llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl;
diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp
index 2e9e31bfea..6834b34387 100644
--- a/indra/llwindow/llwindow.cpp
+++ b/indra/llwindow/llwindow.cpp
@@ -436,3 +436,42 @@ BOOL LLWindowManager::isWindowValid(LLWindow *window)
{
return sWindowList.find(window) != sWindowList.end();
}
+
+//coordinate conversion utility funcs that forward to llwindow
+LLCoordCommon LL_COORD_TYPE_WINDOW::convertToCommon() const
+{
+ const LLCoordWindow& self = static_cast<const LLCoordWindow&>(*this);
+
+ LLWindow* windowp = &(*LLWindow::beginInstances());
+ LLCoordGL out;
+ windowp->convertCoords(self, &out);
+ return out.convert();
+}
+
+void LL_COORD_TYPE_WINDOW::convertFromCommon(const LLCoordCommon& from)
+{
+ LLCoordWindow& self = static_cast<LLCoordWindow&>(*this);
+
+ LLWindow* windowp = &(*LLWindow::beginInstances());
+ LLCoordGL from_gl(from);
+ windowp->convertCoords(from_gl, &self);
+}
+
+LLCoordCommon LL_COORD_TYPE_SCREEN::convertToCommon() const
+{
+ const LLCoordScreen& self = static_cast<const LLCoordScreen&>(*this);
+
+ LLWindow* windowp = &(*LLWindow::beginInstances());
+ LLCoordGL out;
+ windowp->convertCoords(self, &out);
+ return out.convert();
+}
+
+void LL_COORD_TYPE_SCREEN::convertFromCommon(const LLCoordCommon& from)
+{
+ LLCoordScreen& self = static_cast<LLCoordScreen&>(*this);
+
+ LLWindow* windowp = &(*LLWindow::beginInstances());
+ LLCoordGL from_gl(from);
+ windowp->convertCoords(from_gl, &self);
+}
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index cab2d0a8fb..d2971581d2 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -39,7 +39,7 @@ class LLWindowCallbacks;
// Refer to llwindow_test in test/common/llwindow for usage example
-class LLWindow
+class LLWindow : public LLInstanceTracker<LLWindow>
{
public:
struct LLWindowResolution
diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp
index c2705bbf74..9712ae1d91 100644
--- a/indra/llwindow/llwindowcallbacks.cpp
+++ b/indra/llwindow/llwindowcallbacks.cpp
@@ -28,8 +28,6 @@
#include "llwindowcallbacks.h"
-#include "llcoord.h"
-
//
// LLWindowCallbacks
//
diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h
index 8572b442f1..7da5959700 100644
--- a/indra/llwindow/llwindowcallbacks.h
+++ b/indra/llwindow/llwindowcallbacks.h
@@ -26,7 +26,7 @@
#ifndef LLWINDOWCALLBACKS_H
#define LLWINDOWCALLBACKS_H
-class LLCoordGL;
+#include "llcoord.h"
class LLWindow;
class LLWindowCallbacks
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 228fbefd19..ebc3203f14 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -1065,6 +1065,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
return FALSE;
}
+ LL_INFOS("Window") << "Device context retrieved." << llendl ;
+
if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd)))
{
close();
@@ -1073,6 +1075,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
return FALSE;
}
+ LL_INFOS("Window") << "Pixel format chosen." << llendl ;
+
// Verify what pixel format we actually received.
if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),
&pfd))
@@ -1541,24 +1545,16 @@ void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScre
BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)
{
- LLCoordScreen screen_pos;
-
mMousePositionModified = TRUE;
if (!mWindowHandle)
{
return FALSE;
}
- if (!convertCoords(position, &screen_pos))
- {
- return FALSE;
- }
// Inform the application of the new mouse position (needed for per-frame
// hover/picking to function).
- LLCoordGL gl_pos;
- convertCoords(position, &gl_pos);
- mCallbacks->handleMouseMove(this, gl_pos, (MASK)0);
+ mCallbacks->handleMouseMove(this, position.convert(), (MASK)0);
// DEV-18951 VWR-8524 Camera moves wildly when alt-clicking.
// Because we have preemptively notified the application of the new
@@ -1568,24 +1564,23 @@ BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)
while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))
{ }
- return SetCursorPos(screen_pos.mX, screen_pos.mY);
+ LLCoordScreen screen_pos(position.convert());
+ return ::SetCursorPos(screen_pos.mX, screen_pos.mY);
}
BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position)
{
POINT cursor_point;
- LLCoordScreen screen_pos;
- if (!mWindowHandle ||
- !GetCursorPos(&cursor_point))
+ if (!mWindowHandle
+ || !GetCursorPos(&cursor_point)
+ || !position)
{
return FALSE;
}
- screen_pos.mX = cursor_point.x;
- screen_pos.mY = cursor_point.y;
-
- return convertCoords(screen_pos, position);
+ *position = LLCoordScreen(cursor_point.x, cursor_point.y).convert();
+ return TRUE;
}
void LLWindowWin32::hideCursor()
@@ -2163,15 +2158,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
- LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
+ LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
- window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ gl_coord = cursor_coord_window.convert();
}
else
{
- window_imp->convertCoords(window_coord, &gl_coord);
+ gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2193,15 +2188,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
- LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
+ LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
- window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ gl_coord = cursor_coord_window.convert();
}
else
{
- window_imp->convertCoords(window_coord, &gl_coord);
+ gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2226,15 +2221,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
- LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
+ LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
- window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ gl_coord = cursor_coord_window.convert();
}
else
{
- window_imp->convertCoords(window_coord, &gl_coord);
+ gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2261,15 +2256,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
- LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
+ LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
- window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ gl_coord = cursor_coord_window.convert();
}
else
{
- window_imp->convertCoords(window_coord, &gl_coord);
+ gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2290,15 +2285,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
- LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
+ LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
- window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ gl_coord = cursor_coord_window.convert();
}
else
{
- window_imp->convertCoords(window_coord, &gl_coord);
+ gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2325,15 +2320,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
- LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
+ LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
- window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ gl_coord = cursor_coord_window.convert();
}
else
{
- window_imp->convertCoords(window_coord, &gl_coord);
+ gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2354,15 +2349,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// If we don't do this, many clicks could get buffered up, and if the
// first click changes the cursor position, all subsequent clicks
// will occur at the wrong location. JC
- LLCoordWindow cursor_coord_window;
if (window_imp->mMousePositionModified)
{
+ LLCoordWindow cursor_coord_window;
window_imp->getCursorPosition(&cursor_coord_window);
- window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ gl_coord = cursor_coord_window.convert();
}
else
{
- window_imp->convertCoords(window_coord, &gl_coord);
+ gl_coord = window_coord.convert();
}
MASK mask = gKeyboard->currentMask(TRUE);
// generate move event to update mouse coordinates
@@ -2434,9 +2429,8 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_MOUSEMOVE:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEMOVE");
- window_imp->convertCoords(window_coord, &gl_coord);
MASK mask = gKeyboard->currentMask(TRUE);
- window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
+ window_imp->mCallbacks->handleMouseMove(window_imp, window_coord.convert(), mask);
return 0;
}
@@ -3324,7 +3318,7 @@ void LLWindowWin32::setLanguageTextInput( const LLCoordGL & position )
LLWinImm::setCompositionWindow( himc, &ime_form );
- sWinIMEWindowPosition.set( win_pos.mX, win_pos.mY );
+ sWinIMEWindowPosition = win_pos;
}
LLWinImm::releaseContext(mWindowHandle, himc);
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index bf38a8b062..597031ec70 100644
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -92,6 +92,8 @@ typedef enum e_control_type
class LLControlVariable : public LLRefCount
{
+ LOG_CLASS(LLControlVariable);
+
friend class LLControlGroup;
public:
@@ -180,6 +182,8 @@ T convert_from_llsd(const LLSD& sd, eControlType type, const std::string& contro
//const U32 STRING_CACHE_SIZE = 10000;
class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>
{
+ LOG_CLASS(LLControlGroup);
+
protected:
typedef std::map<std::string, LLControlVariablePtr > ctrl_name_table_t;
ctrl_name_table_t mNameTable;
diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp
index 2b4a0fc2a1..2ffb0d8503 100644
--- a/indra/llxml/llxmlnode.cpp
+++ b/indra/llxml/llxmlnode.cpp
@@ -631,13 +631,14 @@ bool LLXMLNode::updateNode(
}
//update all of node's children with updateNodes children that match name
- LLXMLNodePtr child;
+ LLXMLNodePtr child = node->getFirstChild();
+ LLXMLNodePtr last_child = child;
LLXMLNodePtr updateChild;
for (updateChild = update_node->getFirstChild(); updateChild.notNull();
updateChild = updateChild->getNextSibling())
{
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
+ while(child.notNull())
{
std::string nodeName;
std::string updateName;
@@ -656,6 +657,22 @@ bool LLXMLNode::updateNode(
if ((nodeName != "") && (updateName == nodeName))
{
updateNode(child, updateChild);
+ last_child = child;
+ child = child->getNextSibling();
+ if (child.isNull())
+ {
+ child = node->getFirstChild();
+ }
+ break;
+ }
+
+ child = child->getNextSibling();
+ if (child.isNull())
+ {
+ child = node->getFirstChild();
+ }
+ if (child == last_child)
+ {
break;
}
}
@@ -784,7 +801,7 @@ bool LLXMLNode::parseStream(
while(str.good())
{
str.read((char*)buffer, BUFSIZE);
- int count = str.gcount();
+ int count = (int)str.gcount();
if (XML_Parse(my_parser, (const char *)buffer, count, !str.good()) != XML_STATUS_OK)
{
@@ -882,11 +899,8 @@ bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root,
for (itor = paths.begin(), ++itor; itor != paths.end(); ++itor)
{
- std::string nodeName;
- std::string updateName;
-
std::string layer_filename = *itor;
- if(layer_filename.empty())
+ if(layer_filename.empty() || layer_filename == filename)
{
// no localized version of this file, that's ok, keep looking
continue;
@@ -898,6 +912,9 @@ bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root,
return false;
}
+ std::string nodeName;
+ std::string updateName;
+
updateRoot->getAttributeString("name", updateName);
root->getAttributeString("name", nodeName);
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index ab20957760..4ab1d891a3 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -1253,15 +1253,16 @@ namespace LLInitParam
return mValues.back();
}
- void add(const value_t& item)
+ self_t& add(const value_t& item)
{
param_value_t param_value;
param_value.setValue(item);
mValues.push_back(param_value);
setProvided();
+ return *this;
}
- void add(const typename name_value_lookup_t::name_t& name)
+ self_t& add(const typename name_value_lookup_t::name_t& name)
{
value_t value;
@@ -1271,6 +1272,8 @@ namespace LLInitParam
add(value);
mValues.back().setValueName(name);
}
+
+ return *this;
}
// implicit conversion
@@ -1441,13 +1444,14 @@ namespace LLInitParam
return mValues.back();
}
- void add(const value_t& item)
+ self_t& add(const value_t& item)
{
mValues.push_back(item);
setProvided();
+ return *this;
}
- void add(const typename name_value_lookup_t::name_t& name)
+ self_t& add(const typename name_value_lookup_t::name_t& name)
{
value_t value;
@@ -1457,6 +1461,7 @@ namespace LLInitParam
add(value);
mValues.back().setValueName(name);
}
+ return *this;
}
// implicit conversion
diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
index 999f754dcf..24328202cb 100644
--- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
+++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
@@ -705,7 +705,7 @@ private:
// look up "Display Name" in meta data
OSType meta_data_key = kQTMetaDataCommonKeyDisplayName;
QTMetaDataItem item = kQTMetaDataItemUninitialized;
- result = QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard,
+ result = (OSErr)QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard,
0, kQTMetaDataKeyFormatCommon,
(const UInt8 *)&meta_data_key,
sizeof( meta_data_key ), &item );
@@ -714,14 +714,14 @@ private:
// find the size of the title
ByteCount size;
- result = QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size );
+ result = (OSErr)QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size );
if ( noErr != result || size <= 0 /*|| size > 1024 FIXME: arbitrary limit */ )
return false;
// allocate some space and grab it
UInt8* item_data = new UInt8[ size + 1 ];
memset( item_data, 0, ( size + 1 ) * sizeof( UInt8 ) );
- result = QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL );
+ result = (OSErr)QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL );
if ( noErr != result )
{
delete [] item_data;
diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp
index 47f8dcd545..1812abd7d5 100644
--- a/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -991,7 +991,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
{
if(message_name == "set_volume")
{
- F32 volume = message_in.getValueReal("volume");
+ F32 volume = (F32)message_in.getValueReal("volume");
setVolume(volume);
}
}
@@ -1057,9 +1057,9 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
S32 height = message_in.getValueS32("height");
S32 texture_width = message_in.getValueS32("texture_width");
S32 texture_height = message_in.getValueS32("texture_height");
- mBackgroundR = message_in.getValueReal("background_r");
- mBackgroundG = message_in.getValueReal("background_g");
- mBackgroundB = message_in.getValueReal("background_b");
+ mBackgroundR = (F32)message_in.getValueReal("background_r");
+ mBackgroundG = (F32)message_in.getValueReal("background_g");
+ mBackgroundB = (F32)message_in.getValueReal("background_b");
// mBackgroundA = message_in.setValueReal("background_a"); // Ignore any alpha
if(!name.empty())
@@ -1245,9 +1245,9 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
if(message_name == "js_agent_location")
{
#if LLQTWEBKIT_API_VERSION >= 9
- F32 x = message_in.getValueReal("x");
- F32 y = message_in.getValueReal("y");
- F32 z = message_in.getValueReal("z");
+ F32 x = (F32)message_in.getValueReal("x");
+ F32 y = (F32)message_in.getValueReal("y");
+ F32 z = (F32)message_in.getValueReal("z");
LLQtWebKit::getInstance()->setAgentLocation( x, y, z );
LLQtWebKit::getInstance()->emitLocation();
#endif
@@ -1256,9 +1256,9 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
if(message_name == "js_agent_global_location")
{
#if LLQTWEBKIT_API_VERSION >= 9
- F32 x = message_in.getValueReal("x");
- F32 y = message_in.getValueReal("y");
- F32 z = message_in.getValueReal("z");
+ F32 x = (F32)message_in.getValueReal("x");
+ F32 y = (F32)message_in.getValueReal("y");
+ F32 z = (F32)message_in.getValueReal("z");
LLQtWebKit::getInstance()->setAgentGlobalLocation( x, y, z );
LLQtWebKit::getInstance()->emitLocation();
#endif
@@ -1267,7 +1267,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
if(message_name == "js_agent_orientation")
{
#if LLQTWEBKIT_API_VERSION >= 9
- F32 angle = message_in.getValueReal("angle");
+ F32 angle = (F32)message_in.getValueReal("angle");
LLQtWebKit::getInstance()->setAgentOrientation( angle );
LLQtWebKit::getInstance()->emitLocation();
#endif
@@ -1323,7 +1323,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
else if(message_name == "set_page_zoom_factor")
{
#if LLQTWEBKIT_API_VERSION >= 15
- F32 factor = message_in.getValueReal("factor");
+ F32 factor = (F32)message_in.getValueReal("factor");
LLQtWebKit::getInstance()->setPageZoomFactor(factor);
#else
llwarns << "Ignoring setPageZoomFactor message (llqtwebkit version is too old)." << llendl;
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 44cb23b648..b586c6e31f 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -166,7 +166,7 @@ set(viewer_SOURCE_FILES
llfirstuse.cpp
llflexibleobject.cpp
llfloaterabout.cpp
- llfloateranimpreview.cpp
+ llfloaterbvhpreview.cpp
llfloaterauction.cpp
llfloateravatar.cpp
llfloateravatarpicker.cpp
@@ -732,7 +732,7 @@ set(viewer_HEADER_FILES
llfirstuse.h
llflexibleobject.h
llfloaterabout.h
- llfloateranimpreview.h
+ llfloaterbvhpreview.h
llfloaterauction.h
llfloateravatar.h
llfloateravatarpicker.h
@@ -1365,7 +1365,9 @@ if (WINDOWS)
DXGUID_LIBRARY
)
+# see EXP-1765 - theory is opengl32.lib needs to be included before gdi32.lib (windows libs)
set(viewer_LIBRARIES
+ opengl32
${WINDOWS_LIBRARIES}
comdlg32
${DINPUT_LIBRARY}
@@ -1375,7 +1377,6 @@ if (WINDOWS)
odbccp32
ole32
oleaut32
- opengl32
shell32
Vfw32
winspool
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index d3253bc381..ff4d9ceb93 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -37,6 +37,8 @@
tooltip_ref="Command_Build_Tooltip"
execute_function="Build.Toggle"
execute_parameters="build"
+ is_enabled_function="Build.Enabled"
+ is_enabled_parameters="build"
is_running_function="Floater.IsOpen"
is_running_parameters="build"
/>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 77a76e6bf7..eb2b0834e9 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4282,6 +4282,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>InventoryInboxToggleState</key>
+ <map>
+ <key>Comment</key>
+ <string>Stores the open/closed state of inventory Received items panel</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>InventoryLinking</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
index 40b0cf47ac..eada38eaaa 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl
@@ -55,6 +55,12 @@ uniform vec3 light_direction[8];
uniform vec3 light_attenuation[8];
uniform vec3 light_diffuse[8];
+float calcDirectionalLight(vec3 n, vec3 l)
+{
+ float a = max(dot(n,l),0.0);
+ return a;
+}
+
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
{
//get light vector
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
index 8c96d55342..5c36118a50 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
@@ -64,6 +64,12 @@ uniform vec3 light_direction[8];
uniform vec3 light_attenuation[8];
uniform vec3 light_diffuse[8];
+float calcDirectionalLight(vec3 n, vec3 l)
+{
+ float a = max(dot(n,l),0.0);
+ return a;
+}
+
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
{
//get light vector
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
index c0edddc40a..d6149fcc32 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
@@ -59,6 +59,12 @@ uniform vec3 light_direction[8];
uniform vec3 light_attenuation[8];
uniform vec3 light_diffuse[8];
+float calcDirectionalLight(vec3 n, vec3 l)
+{
+ float a = max(dot(n,l),0.0);
+ return a;
+}
+
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
{
//get light vector
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
index 64e094e3c5..17f425475c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
@@ -50,18 +50,18 @@ uniform vec4 sunlight_color;
uniform vec4 ambient;
uniform vec4 blue_horizon;
uniform vec4 blue_density;
-uniform vec4 haze_horizon;
-uniform vec4 haze_density;
+uniform float haze_horizon;
+uniform float haze_density;
-uniform vec4 cloud_shadow;
-uniform vec4 density_multiplier;
-uniform vec4 max_y;
+uniform float cloud_shadow;
+uniform float density_multiplier;
+uniform float max_y;
uniform vec4 glow;
uniform vec4 cloud_color;
-uniform vec4 cloud_scale;
+uniform float cloud_scale;
void main()
{
@@ -77,7 +77,7 @@ void main()
// Set altitude
if (P.y > 0.)
{
- P *= (max_y.x / P.y);
+ P *= (max_y / P.y);
}
else
{
@@ -99,12 +99,12 @@ void main()
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x);
+ light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
// Calculate relative weights
- temp1 = blue_density + haze_density.x;
+ temp1 = blue_density + haze_density;
blue_weight = blue_density / temp1;
- haze_weight = haze_density.x / temp1;
+ haze_weight = haze_density / temp1;
// Compute sunlight from P & lightnorm (for long rays like sky)
temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
@@ -112,7 +112,7 @@ void main()
sunlight *= exp( - light_atten * temp2.y);
// Distance
- temp2.z = Plen * density_multiplier.x;
+ temp2.z = Plen * density_multiplier;
// Transparency (-> temp1)
// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
@@ -136,14 +136,14 @@ void main()
// Increase ambient when there are more clouds
vec4 tmpAmbient = ambient;
- tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5;
+ tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
// Dim sunlight by cloud shadow percentage
- sunlight *= (1. - cloud_shadow.x);
+ sunlight *= (1. - cloud_shadow);
// Haze color below cloud
vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient)
- + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient)
+ + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
);
// CLOUDS
@@ -164,13 +164,13 @@ void main()
vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1);
// Make a nice cloud density based on the cloud_shadow value that was passed in.
- vary_CloudDensity = 2. * (cloud_shadow.x - 0.25);
+ vary_CloudDensity = 2. * (cloud_shadow - 0.25);
// Texture coords
vary_texcoord0 = texcoord0;
vary_texcoord0.xy -= 0.5;
- vary_texcoord0.xy /= cloud_scale.x;
+ vary_texcoord0.xy /= cloud_scale;
vary_texcoord0.xy += 0.5;
vary_texcoord1 = vary_texcoord0;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
index 721de18e0b..cb7603f4fd 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
@@ -44,19 +44,17 @@ uniform vec4 sunlight_color;
uniform vec4 ambient;
uniform vec4 blue_horizon;
uniform vec4 blue_density;
-uniform vec4 haze_horizon;
-uniform vec4 haze_density;
+uniform float haze_horizon;
+uniform float haze_density;
-uniform vec4 cloud_shadow;
-uniform vec4 density_multiplier;
-uniform vec4 max_y;
+uniform float cloud_shadow;
+uniform float density_multiplier;
+uniform float max_y;
uniform vec4 glow;
uniform vec4 cloud_color;
-uniform vec4 cloud_scale;
-
void main()
{
@@ -71,7 +69,7 @@ void main()
// Set altitude
if (P.y > 0.)
{
- P *= (max_y.x / P.y);
+ P *= (max_y / P.y);
}
else
{
@@ -93,12 +91,12 @@ void main()
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x);
+ light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
// Calculate relative weights
- temp1 = blue_density + haze_density.x;
+ temp1 = blue_density + haze_density;
blue_weight = blue_density / temp1;
- haze_weight = haze_density.x / temp1;
+ haze_weight = haze_density / temp1;
// Compute sunlight from P & lightnorm (for long rays like sky)
temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
@@ -106,7 +104,7 @@ void main()
sunlight *= exp( - light_atten * temp2.y);
// Distance
- temp2.z = Plen * density_multiplier.x;
+ temp2.z = Plen * density_multiplier;
// Transparency (-> temp1)
// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
@@ -131,20 +129,20 @@ void main()
// Haze color above cloud
vary_HazeColor = ( blue_horizon * blue_weight * (sunlight + ambient)
- + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + ambient)
+ + (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient)
);
// Increase ambient when there are more clouds
vec4 tmpAmbient = ambient;
- tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5;
+ tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
// Dim sunlight by cloud shadow percentage
- sunlight *= (1. - cloud_shadow.x);
+ sunlight *= (1. - cloud_shadow);
// Haze color below cloud
vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient)
- + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient)
+ + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
);
// Final atmosphere additive
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 51110ae4df..0c53a4ffa5 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -51,12 +51,12 @@ uniform vec4 sunlight_color;
uniform vec4 ambient;
uniform vec4 blue_horizon;
uniform vec4 blue_density;
-uniform vec4 haze_horizon;
-uniform vec4 haze_density;
-uniform vec4 cloud_shadow;
-uniform vec4 density_multiplier;
-uniform vec4 distance_multiplier;
-uniform vec4 max_y;
+uniform float haze_horizon;
+uniform float haze_density;
+uniform float cloud_shadow;
+uniform float density_multiplier;
+uniform float distance_multiplier;
+uniform float max_y;
uniform vec4 glow;
uniform float scene_light_strength;
uniform mat3 env_mat;
@@ -159,13 +159,13 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
//sunlight attenuation effect (hue and brightness) due to atmosphere
//this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
+ light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
//I had thought blue_density and haze_density should have equal weighting,
//but attenuation due to haze_density tends to seem too strong
- temp1 = blue_density + vec4(haze_density.r);
+ temp1 = blue_density + vec4(haze_density);
blue_weight = blue_density / temp1;
- haze_weight = vec4(haze_density.r) / temp1;
+ haze_weight = vec4(haze_density) / temp1;
//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
temp2.y = max(0.0, tmpLightnorm.y);
@@ -173,12 +173,12 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
sunlight *= exp( - light_atten * temp2.y);
// main atmospheric scattering line integral
- temp2.z = Plen * density_multiplier.x;
+ temp2.z = Plen * density_multiplier;
// Transparency (-> temp1)
- // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
+ // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati
// compiler gets confused.
- temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
+ temp1 = exp(-temp1 * temp2.z * distance_multiplier);
//final atmosphere attenuation factor
setAtmosAttenuation(temp1.rgb);
@@ -199,7 +199,7 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
temp2.x += .25;
//increase ambient when there are more clouds
- vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
+ vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5;
/* decrease value and saturation (that in HSV, not HSL) for occluded areas
* // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
@@ -213,8 +213,8 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
//haze color
setAdditiveColor(
- vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
- + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
+ vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
+ + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
+ tmpAmbient)));
//brightness of surface both sunlight and ambient
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
index 83815b1786..9629cfe824 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl
@@ -61,6 +61,12 @@ uniform vec3 light_direction[8];
uniform vec3 light_attenuation[8];
uniform vec3 light_diffuse[8];
+float calcDirectionalLight(vec3 n, vec3 l)
+{
+ float a = max(dot(n,l),0.0);
+ return a;
+}
+
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
{
//get light vector
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
index 1660f9687e..1586aab0f2 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl
@@ -63,6 +63,12 @@ uniform vec3 light_direction[8];
uniform vec3 light_attenuation[8];
uniform vec3 light_diffuse[8];
+float calcDirectionalLight(vec3 n, vec3 l)
+{
+ float a = max(dot(n,l),0.0);
+ return a;
+}
+
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
{
//get light vector
diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
index 84c27edb26..44aaa98b97 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
@@ -60,6 +60,12 @@ uniform vec3 light_direction[8];
uniform vec3 light_attenuation[8];
uniform vec3 light_diffuse[8];
+float calcDirectionalLight(vec3 n, vec3 l)
+{
+ float a = max(dot(n,l),0.0);
+ return a;
+}
+
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
{
//get light vector
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 97f3063a9e..27ea77b5a2 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -51,12 +51,12 @@ uniform vec4 sunlight_color;
uniform vec4 ambient;
uniform vec4 blue_horizon;
uniform vec4 blue_density;
-uniform vec4 haze_horizon;
-uniform vec4 haze_density;
-uniform vec4 cloud_shadow;
-uniform vec4 density_multiplier;
-uniform vec4 distance_multiplier;
-uniform vec4 max_y;
+uniform float haze_horizon;
+uniform float haze_density;
+uniform float cloud_shadow;
+uniform float density_multiplier;
+uniform float distance_multiplier;
+uniform float max_y;
uniform vec4 glow;
uniform float scene_light_strength;
uniform mat3 env_mat;
@@ -161,13 +161,13 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
//sunlight attenuation effect (hue and brightness) due to atmosphere
//this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
+ light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
//I had thought blue_density and haze_density should have equal weighting,
//but attenuation due to haze_density tends to seem too strong
- temp1 = blue_density + vec4(haze_density.r);
+ temp1 = blue_density + vec4(haze_density);
blue_weight = blue_density / temp1;
- haze_weight = vec4(haze_density.r) / temp1;
+ haze_weight = vec4(haze_density) / temp1;
//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
temp2.y = max(0.0, tmpLightnorm.y);
@@ -175,12 +175,12 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
sunlight *= exp( - light_atten * temp2.y);
// main atmospheric scattering line integral
- temp2.z = Plen * density_multiplier.x;
+ temp2.z = Plen * density_multiplier;
// Transparency (-> temp1)
- // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
+ // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati
// compiler gets confused.
- temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
+ temp1 = exp(-temp1 * temp2.z * distance_multiplier);
//final atmosphere attenuation factor
setAtmosAttenuation(temp1.rgb);
@@ -201,7 +201,7 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
temp2.x += .25;
//increase ambient when there are more clouds
- vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
+ vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5;
/* decrease value and saturation (that in HSV, not HSL) for occluded areas
* // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
@@ -215,8 +215,8 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
//haze color
setAdditiveColor(
- vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
- + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
+ vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
+ + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
+ tmpAmbient)));
//brightness of surface both sunlight and ambient
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
index 6a83be1426..da3d922017 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
@@ -47,12 +47,12 @@ uniform vec4 sunlight_color;
uniform vec4 ambient;
uniform vec4 blue_horizon;
uniform vec4 blue_density;
-uniform vec4 haze_horizon;
-uniform vec4 haze_density;
-uniform vec4 cloud_shadow;
-uniform vec4 density_multiplier;
-uniform vec4 distance_multiplier;
-uniform vec4 max_y;
+uniform float haze_horizon;
+uniform float haze_density;
+uniform float cloud_shadow;
+uniform float density_multiplier;
+uniform float distance_multiplier;
+uniform float max_y;
uniform vec4 glow;
void calcAtmospherics(vec3 inPositionEye) {
@@ -61,8 +61,8 @@ void calcAtmospherics(vec3 inPositionEye) {
setPositionEye(P);
//(TERRAIN) limit altitude
- if (P.y > max_y.x) P *= (max_y.x / P.y);
- if (P.y < -max_y.x) P *= (-max_y.x / P.y);
+ if (P.y > max_y) P *= (max_y / P.y);
+ if (P.y < -max_y) P *= (-max_y / P.y);
vec3 tmpLightnorm = lightnorm.xyz;
@@ -78,13 +78,13 @@ void calcAtmospherics(vec3 inPositionEye) {
//sunlight attenuation effect (hue and brightness) due to atmosphere
//this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
+ light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
//I had thought blue_density and haze_density should have equal weighting,
//but attenuation due to haze_density tends to seem too strong
- temp1 = blue_density + vec4(haze_density.r);
+ temp1 = blue_density + vec4(haze_density);
blue_weight = blue_density / temp1;
- haze_weight = vec4(haze_density.r) / temp1;
+ haze_weight = vec4(haze_density) / temp1;
//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
temp2.y = max(0.0, tmpLightnorm.y);
@@ -92,12 +92,12 @@ void calcAtmospherics(vec3 inPositionEye) {
sunlight *= exp( - light_atten * temp2.y);
// main atmospheric scattering line integral
- temp2.z = Plen * density_multiplier.x;
+ temp2.z = Plen * density_multiplier;
// Transparency (-> temp1)
- // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
+ // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati
// compiler gets confused.
- temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
+ temp1 = exp(-temp1 * temp2.z * distance_multiplier);
//final atmosphere attenuation factor
setAtmosAttenuation(temp1.rgb);
@@ -122,12 +122,12 @@ void calcAtmospherics(vec3 inPositionEye) {
//increase ambient when there are more clouds
- vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
+ vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5;
//haze color
setAdditiveColor(
- vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
- + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
+ vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
+ + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
+ tmpAmbient)));
//brightness of surface both sunlight and ambient
diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
index c5bb52169c..c1dd45cd67 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
@@ -49,18 +49,18 @@ uniform vec4 sunlight_color;
uniform vec4 ambient;
uniform vec4 blue_horizon;
uniform vec4 blue_density;
-uniform vec4 haze_horizon;
-uniform vec4 haze_density;
+uniform float haze_horizon;
+uniform float haze_density;
-uniform vec4 cloud_shadow;
-uniform vec4 density_multiplier;
-uniform vec4 max_y;
+uniform float cloud_shadow;
+uniform float density_multiplier;
+uniform float max_y;
uniform vec4 glow;
uniform vec4 cloud_color;
-uniform vec4 cloud_scale;
+uniform float cloud_scale;
void main()
{
@@ -76,7 +76,7 @@ void main()
// Set altitude
if (P.y > 0.)
{
- P *= (max_y.x / P.y);
+ P *= (max_y / P.y);
}
else
{
@@ -98,12 +98,12 @@ void main()
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x);
+ light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
// Calculate relative weights
- temp1 = blue_density + haze_density.x;
+ temp1 = blue_density + haze_density;
blue_weight = blue_density / temp1;
- haze_weight = haze_density.x / temp1;
+ haze_weight = haze_density / temp1;
// Compute sunlight from P & lightnorm (for long rays like sky)
temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
@@ -111,7 +111,7 @@ void main()
sunlight *= exp( - light_atten * temp2.y);
// Distance
- temp2.z = Plen * density_multiplier.x;
+ temp2.z = Plen * density_multiplier;
// Transparency (-> temp1)
// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
@@ -135,14 +135,14 @@ void main()
// Increase ambient when there are more clouds
vec4 tmpAmbient = ambient;
- tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5;
+ tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
// Dim sunlight by cloud shadow percentage
- sunlight *= (1. - cloud_shadow.x);
+ sunlight *= (1. - cloud_shadow);
// Haze color below cloud
vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient)
- + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient)
+ + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
);
// CLOUDS
@@ -163,13 +163,13 @@ void main()
vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1);
// Make a nice cloud density based on the cloud_shadow value that was passed in.
- vary_CloudDensity = 2. * (cloud_shadow.x - 0.25);
+ vary_CloudDensity = 2. * (cloud_shadow - 0.25);
// Texture coords
vary_texcoord0 = texcoord0;
vary_texcoord0.xy -= 0.5;
- vary_texcoord0.xy /= cloud_scale.x;
+ vary_texcoord0.xy /= cloud_scale;
vary_texcoord0.xy += 0.5;
vary_texcoord1 = vary_texcoord0;
diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
index 46773cf89f..3788ddaf2d 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
@@ -42,19 +42,17 @@ uniform vec4 sunlight_color;
uniform vec4 ambient;
uniform vec4 blue_horizon;
uniform vec4 blue_density;
-uniform vec4 haze_horizon;
-uniform vec4 haze_density;
+uniform float haze_horizon;
+uniform float haze_density;
-uniform vec4 cloud_shadow;
-uniform vec4 density_multiplier;
-uniform vec4 max_y;
+uniform float cloud_shadow;
+uniform float density_multiplier;
+uniform float max_y;
uniform vec4 glow;
uniform vec4 cloud_color;
-uniform vec4 cloud_scale;
-
void main()
{
@@ -68,7 +66,7 @@ void main()
// Set altitude
if (P.y > 0.)
{
- P *= (max_y.x / P.y);
+ P *= (max_y / P.y);
}
else
{
@@ -87,15 +85,14 @@ void main()
vec4 sunlight = sunlight_color;
vec4 light_atten;
-
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x);
+ light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
// Calculate relative weights
- temp1 = blue_density + haze_density.x;
+ temp1 = blue_density + haze_density;
blue_weight = blue_density / temp1;
- haze_weight = haze_density.x / temp1;
+ haze_weight = haze_density / temp1;
// Compute sunlight from P & lightnorm (for long rays like sky)
temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
@@ -103,7 +100,7 @@ void main()
sunlight *= exp( - light_atten * temp2.y);
// Distance
- temp2.z = Plen * density_multiplier.x;
+ temp2.z = Plen * density_multiplier;
// Transparency (-> temp1)
// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
@@ -128,20 +125,20 @@ void main()
// Haze color above cloud
vary_HazeColor = ( blue_horizon * blue_weight * (sunlight + ambient)
- + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + ambient)
+ + (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient)
);
// Increase ambient when there are more clouds
vec4 tmpAmbient = ambient;
- tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5;
+ tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
// Dim sunlight by cloud shadow percentage
- sunlight *= (1. - cloud_shadow.x);
+ sunlight *= (1. - cloud_shadow);
// Haze color below cloud
vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient)
- + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient)
+ + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
);
// Final atmosphere additive
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 0f33d40ac3..76bb2b0976 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -42,7 +42,6 @@ RenderGamma 1 0
RenderGlowResolutionPow 1 9
RenderGround 1 1
RenderMaxPartCount 1 8192
-RenderNightBrightness 1 1.0
RenderObjectBump 1 1
RenderLocalLights 1 1
RenderReflectionDetail 1 4
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index 8142311a55..5e217e000a 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -43,7 +43,6 @@ RenderGlowResolutionPow 1 9
RenderGround 1 1
RenderLocalLights 1 1
RenderMaxPartCount 1 8192
-RenderNightBrightness 1 1.0
RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index 942c043081..915a012a39 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -43,7 +43,6 @@ RenderGlowResolutionPow 1 9
RenderGround 1 1
RenderLocalLights 1 1
RenderMaxPartCount 1 8192
-RenderNightBrightness 1 1.0
RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt
index 278d601860..ae2cf910f2 100644
--- a/indra/newview/featuretable_xp.txt
+++ b/indra/newview/featuretable_xp.txt
@@ -43,7 +43,6 @@ RenderGlowResolutionPow 1 9
RenderGround 1 1
RenderLocalLights 1 1
RenderMaxPartCount 1 8192
-RenderNightBrightness 1 1.0
RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 9d23d439fa..cbd08ad1c3 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -170,11 +170,7 @@ bool LLAgent::isActionAllowed(const LLSD& sdname)
const std::string& param = sdname.asString();
- if (param == "build")
- {
- retval = gAgent.canEditParcel();
- }
- else if (param == "speak")
+ if (param == "speak")
{
if ( gAgent.isVoiceConnected() &&
LLViewerParcelMgr::getInstance()->allowAgentVoice() &&
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 09305a5b4d..dd02a74a38 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -817,7 +817,10 @@ void LLAgentWearables::popWearable(const LLWearableType::EType type, U32 index)
if (wearable)
{
mWearableDatas[type].erase(mWearableDatas[type].begin() + index);
+ if (isAgentAvatarValid())
+ {
gAgentAvatarp->wearableUpdated(wearable->getType(), TRUE);
+ }
wearable->setLabelUpdated();
}
}
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 647ace7ee3..6931b55c4c 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -30,7 +30,8 @@
#include "llmemtype.h"
-#include "llwindowwin32.cpp" // *FIX: for setting gIconResource.
+#include "llwindowwin32.h" // *FIX: for setting gIconResource.
+#include "llgl.h"
#include "res/resource.h" // *FIX: for setting gIconResource.
#include <fcntl.h> //_O_APPEND
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index e3217668c5..f2375bfa4f 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -188,7 +188,7 @@ void LLCallFloater::draw()
// Need to resort the participant list if it's in sort by recent speaker order.
if (mParticipants)
- mParticipants->updateRecentSpeakersOrder();
+ mParticipants->update();
LLFloater::draw();
}
@@ -333,6 +333,7 @@ void LLCallFloater::refreshParticipantList()
if (!non_avatar_caller)
{
+ llassert(mParticipants == NULL); // check for possible memory leak
mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT, false);
mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1));
const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder");
diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp
index 2abfbf37ca..935dcb74b0 100644
--- a/indra/newview/llexpandabletextbox.cpp
+++ b/indra/newview/llexpandabletextbox.cpp
@@ -55,7 +55,7 @@ public:
else
{
width = mEditor.getDocumentView()->getRect().getWidth() - mEditor.getHPad();
- height = llceil(mStyle->getFont()->getLineHeight());
+ height = mStyle->getFont()->getLineHeight();
}
return true;
}
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 233038daba..9664aa7dbe 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -149,7 +149,7 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask)
LLFastTimer::NamedTimer* LLFastTimerView::getLegendID(S32 y)
{
- S32 idx = (getRect().getHeight() - y) / ((S32) LLFontGL::getFontMonospace()->getLineHeight()+2) - 5;
+ S32 idx = (getRect().getHeight() - y) / (LLFontGL::getFontMonospace()->getLineHeight()+2) - 5;
if (idx >= 0 && idx < (S32)ft_display_idx.size())
{
@@ -552,7 +552,7 @@ void LLFastTimerView::draw()
// update rectangle that includes timer bars
mBarRect.mLeft = xleft;
mBarRect.mRight = getRect().getWidth();
- mBarRect.mTop = ytop - ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 4);
+ mBarRect.mTop = ytop - (LLFontGL::getFontMonospace()->getLineHeight() + 4);
mBarRect.mBottom = margin + LINE_GRAPH_HEIGHT;
y = ytop;
@@ -846,7 +846,7 @@ void LLFastTimerView::draw()
tdesc = llformat("%4.2f ms", ms);
x = mGraphRect.mRight - LLFontGL::getFontMonospace()->getWidth(tdesc)-5;
- y = mGraphRect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight());
+ y = mGraphRect.mTop - LLFontGL::getFontMonospace()->getLineHeight();
LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white,
LLFontGL::LEFT, LLFontGL::TOP);
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 8024755e86..8986a694f9 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -49,7 +49,7 @@ LLFilePicker LLFilePicker::sInstance;
#if LL_WINDOWS
#define SOUND_FILTER L"Sounds (*.wav)\0*.wav\0"
#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0"
-#define ANIM_FILTER L"Animations (*.bvh)\0*.bvh\0"
+#define ANIM_FILTER L"Animations (*.bvh; *.anim)\0*.bvh;*.anim\0"
#define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0"
#ifdef _CORY_TESTING
#define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0"
@@ -593,8 +593,10 @@ Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callB
}
else if (filter == FFLOAD_ANIM)
{
- if (fileInfo.filetype != 'BVH ' &&
- (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("bvh"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
+ if (fileInfo.filetype != 'BVH ' &&
+ fileInfo.filetype != 'ANIM' &&
+ (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("bvh"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) &&
+ fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("anim"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
)
{
result = false;
@@ -1073,8 +1075,11 @@ void LLFilePicker::chooser_responder(GtkWidget *widget, gint response, gpointer
}
// set the default path for this usage context.
- picker->mContextToPathMap[picker->mCurContextName] =
- gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget));
+ const char* cur_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget));
+ if (cur_folder != NULL)
+ {
+ picker->mContextToPathMap[picker->mCurContextName] = cur_folder;
+ }
gtk_widget_destroy(widget);
gtk_main_quit();
@@ -1196,10 +1201,14 @@ static std::string add_wav_filter_to_gtkchooser(GtkWindow *picker)
LLTrans::getString("sound_files") + " (*.wav)");
}
-static std::string add_bvh_filter_to_gtkchooser(GtkWindow *picker)
+static std::string add_anim_filter_to_gtkchooser(GtkWindow *picker)
{
- return add_simple_pattern_filter_to_gtkchooser(picker, "*.bvh",
- LLTrans::getString("animation_files") + " (*.bvh)");
+ GtkFileFilter *gfilter = gtk_file_filter_new();
+ gtk_file_filter_add_pattern(gfilter, "*.bvh");
+ gtk_file_filter_add_pattern(gfilter, "*.anim");
+ std::string filtername = LLTrans::getString("animation_files") + " (*.bvh; *.anim)";
+ add_common_filters_to_gtkchooser(gfilter, picker, filtername);
+ return filtername;
}
static std::string add_collada_filter_to_gtkchooser(GtkWindow *picker)
@@ -1351,7 +1360,7 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
filtername = add_wav_filter_to_gtkchooser(picker);
break;
case FFLOAD_ANIM:
- filtername = add_bvh_filter_to_gtkchooser(picker);
+ filtername = add_anim_filter_to_gtkchooser(picker);
break;
case FFLOAD_COLLADA:
filtername = add_collada_filter_to_gtkchooser(picker);
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index aa66fcf9b8..0290e7cdf0 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -63,6 +63,11 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,
// *TODO: Use a key to allow this not to be an effective singleton
LLFloaterAvatarPicker* floater =
LLFloaterReg::showTypedInstance<LLFloaterAvatarPicker>("avatar_picker");
+ if (!floater)
+ {
+ llwarns << "Cannot instantiate avatar picker" << llendl;
+ return NULL;
+ }
floater->mSelectionCallback = callback;
floater->setAllowMultiple(allow_multiple);
diff --git a/indra/newview/llfloaterbuildoptions.cpp b/indra/newview/llfloaterbuildoptions.cpp
index 86c1bf0534..1b65d8d683 100644
--- a/indra/newview/llfloaterbuildoptions.cpp
+++ b/indra/newview/llfloaterbuildoptions.cpp
@@ -41,13 +41,9 @@
// Methods
//
-void commit_grid_mode(LLUICtrl *);
-
LLFloaterBuildOptions::LLFloaterBuildOptions(const LLSD& key)
- : LLFloater(key),
- mComboGridMode(NULL)
+ : LLFloater(key)
{
- mCommitCallbackRegistrar.add("GridOptions.gridMode", boost::bind(&commit_grid_mode,_1));
}
LLFloaterBuildOptions::~LLFloaterBuildOptions()
@@ -55,45 +51,9 @@ LLFloaterBuildOptions::~LLFloaterBuildOptions()
BOOL LLFloaterBuildOptions::postBuild()
{
- mComboGridMode = getChild<LLComboBox>("combobox grid mode");
-
return TRUE;
}
-void LLFloaterBuildOptions::setGridMode(EGridMode mode)
-{
- mComboGridMode->setCurrentByIndex((S32)mode);
-}
-
-void LLFloaterBuildOptions::updateGridMode()
-{
- if (mComboGridMode)
- {
- S32 index = mComboGridMode->getCurrentIndex();
- mComboGridMode->removeall();
-
- switch (mObjectSelection->getSelectType())
- {
- case SELECT_TYPE_HUD:
- mComboGridMode->add(getString("grid_screen_text"));
- mComboGridMode->add(getString("grid_local_text"));
- break;
- case SELECT_TYPE_WORLD:
- mComboGridMode->add(getString("grid_world_text"));
- mComboGridMode->add(getString("grid_local_text"));
- mComboGridMode->add(getString("grid_reference_text"));
- break;
- case SELECT_TYPE_ATTACHMENT:
- mComboGridMode->add(getString("grid_attachment_text"));
- mComboGridMode->add(getString("grid_local_text"));
- mComboGridMode->add(getString("grid_reference_text"));
- break;
- }
-
- mComboGridMode->setCurrentByIndex(index);
- }
-}
-
// virtual
void LLFloaterBuildOptions::onOpen(const LLSD& key)
{
@@ -105,10 +65,3 @@ void LLFloaterBuildOptions::onClose(bool app_quitting)
{
mObjectSelection = NULL;
}
-
-void commit_grid_mode(LLUICtrl *ctrl)
-{
- LLComboBox* combo = (LLComboBox*)ctrl;
-
- LLSelectMgr::getInstance()->setGridMode((EGridMode)combo->getCurrentIndex());
-}
diff --git a/indra/newview/llfloaterbuildoptions.h b/indra/newview/llfloaterbuildoptions.h
index 7f3811bf1c..02c56cb6a9 100644
--- a/indra/newview/llfloaterbuildoptions.h
+++ b/indra/newview/llfloaterbuildoptions.h
@@ -35,7 +35,6 @@
#include "llfloater.h"
#include "llselectmgr.h"
-class LLComboBox;
class LLObjectSelection;
typedef LLSafeHandle<LLObjectSelection> LLObjectSelectionHandle;
@@ -44,23 +43,17 @@ class LLFloaterBuildOptions
: public LLFloater
{
public:
-
virtual BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void onClose(bool app_quitting);
- void setGridMode(EGridMode mode);
- void updateGridMode();
-
private:
-
friend class LLFloaterReg;
LLFloaterBuildOptions(const LLSD& key);
~LLFloaterBuildOptions();
- LLComboBox* mComboGridMode;
LLObjectSelectionHandle mObjectSelection;
};
#endif
diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp
index ee8487b160..087b0007e1 100644
--- a/indra/newview/llfloaterbuy.cpp
+++ b/indra/newview/llfloaterbuy.cpp
@@ -239,8 +239,9 @@ void LLFloaterBuy::inventoryChanged(LLViewerObject* obj,
// Compute icon for this item
BOOL item_is_multi = FALSE;
- if ( inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED
+ if (( inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED
|| inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS)
+ && !(inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK))
{
item_is_multi = TRUE;
}
diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp
index 2a3512e21a..b050a638dc 100644
--- a/indra/newview/llfloateranimpreview.cpp
+++ b/indra/newview/llfloaterbvhpreview.cpp
@@ -1,6 +1,6 @@
/**
- * @file llfloateranimpreview.cpp
- * @brief LLFloaterAnimPreview class implementation
+ * @file llfloaterbvhpreview.cpp
+ * @brief LLFloaterBvhPreview class implementation
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -26,7 +26,7 @@
#include "llviewerprecompiledheaders.h"
-#include "llfloateranimpreview.h"
+#include "llfloaterbvhpreview.h"
#include "llbvhloader.h"
#include "lldatapacker.h"
@@ -115,9 +115,9 @@ std::string STATUS[] =
};
//-----------------------------------------------------------------------------
-// LLFloaterAnimPreview()
+// LLFloaterBvhPreview()
//-----------------------------------------------------------------------------
-LLFloaterAnimPreview::LLFloaterAnimPreview(const std::string& filename) :
+LLFloaterBvhPreview::LLFloaterBvhPreview(const std::string& filename) :
LLFloaterNameDesc(filename)
{
mLastMouseX = 0;
@@ -153,35 +153,35 @@ LLFloaterAnimPreview::LLFloaterAnimPreview(const std::string& filename) :
//-----------------------------------------------------------------------------
// setAnimCallbacks()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::setAnimCallbacks()
+void LLFloaterBvhPreview::setAnimCallbacks()
{
- getChild<LLUICtrl>("playback_slider")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onSliderMove, this));
+ getChild<LLUICtrl>("playback_slider")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onSliderMove, this));
- getChild<LLUICtrl>("preview_base_anim")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitBaseAnim, this));
+ getChild<LLUICtrl>("preview_base_anim")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitBaseAnim, this));
getChild<LLUICtrl>("preview_base_anim")->setValue("Standing");
- getChild<LLUICtrl>("priority")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitPriority, this));
- getChild<LLUICtrl>("loop_check")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitLoop, this));
- getChild<LLUICtrl>("loop_in_point")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitLoopIn, this));
- getChild<LLUICtrl>("loop_in_point")->setValidateBeforeCommit( boost::bind(&LLFloaterAnimPreview::validateLoopIn, this, _1));
- getChild<LLUICtrl>("loop_out_point")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitLoopOut, this));
- getChild<LLUICtrl>("loop_out_point")->setValidateBeforeCommit( boost::bind(&LLFloaterAnimPreview::validateLoopOut, this, _1));
+ getChild<LLUICtrl>("priority")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitPriority, this));
+ getChild<LLUICtrl>("loop_check")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitLoop, this));
+ getChild<LLUICtrl>("loop_in_point")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitLoopIn, this));
+ getChild<LLUICtrl>("loop_in_point")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateLoopIn, this, _1));
+ getChild<LLUICtrl>("loop_out_point")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitLoopOut, this));
+ getChild<LLUICtrl>("loop_out_point")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateLoopOut, this, _1));
- getChild<LLUICtrl>("hand_pose_combo")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitHandPose, this));
+ getChild<LLUICtrl>("hand_pose_combo")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitHandPose, this));
- getChild<LLUICtrl>("emote_combo")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitEmote, this));
+ getChild<LLUICtrl>("emote_combo")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitEmote, this));
getChild<LLUICtrl>("emote_combo")->setValue("[None]");
- getChild<LLUICtrl>("ease_in_time")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitEaseIn, this));
- getChild<LLUICtrl>("ease_in_time")->setValidateBeforeCommit( boost::bind(&LLFloaterAnimPreview::validateEaseIn, this, _1));
- getChild<LLUICtrl>("ease_out_time")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitEaseOut, this));
- getChild<LLUICtrl>("ease_out_time")->setValidateBeforeCommit( boost::bind(&LLFloaterAnimPreview::validateEaseOut, this, _1));
+ getChild<LLUICtrl>("ease_in_time")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitEaseIn, this));
+ getChild<LLUICtrl>("ease_in_time")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateEaseIn, this, _1));
+ getChild<LLUICtrl>("ease_out_time")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitEaseOut, this));
+ getChild<LLUICtrl>("ease_out_time")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateEaseOut, this, _1));
}
//-----------------------------------------------------------------------------
// postBuild()
//-----------------------------------------------------------------------------
-BOOL LLFloaterAnimPreview::postBuild()
+BOOL LLFloaterBvhPreview::postBuild()
{
LLKeyframeMotion* motionp = NULL;
LLBVHLoader* loaderp = NULL;
@@ -191,7 +191,7 @@ BOOL LLFloaterAnimPreview::postBuild()
return FALSE;
}
- getChild<LLUICtrl>("name_form")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitName, this));
+ getChild<LLUICtrl>("name_form")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitName, this));
childSetAction("ok_btn", onBtnOK, this);
setDefaultBtn();
@@ -203,15 +203,15 @@ BOOL LLFloaterAnimPreview::postBuild()
mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f);
mPlayButton = getChild<LLButton>( "play_btn");
- mPlayButton->setClickedCallback(boost::bind(&LLFloaterAnimPreview::onBtnPlay, this));
+ mPlayButton->setClickedCallback(boost::bind(&LLFloaterBvhPreview::onBtnPlay, this));
mPlayButton->setVisible(true);
mPauseButton = getChild<LLButton>( "pause_btn");
- mPauseButton->setClickedCallback(boost::bind(&LLFloaterAnimPreview::onBtnPause, this));
+ mPauseButton->setClickedCallback(boost::bind(&LLFloaterBvhPreview::onBtnPause, this));
mPauseButton->setVisible(false);
mStopButton = getChild<LLButton>( "stop_btn");
- mStopButton->setClickedCallback(boost::bind(&LLFloaterAnimPreview::onBtnStop, this));
+ mStopButton->setClickedCallback(boost::bind(&LLFloaterBvhPreview::onBtnStop, this));
getChildView("bad_animation_text")->setVisible(FALSE);
@@ -363,9 +363,9 @@ BOOL LLFloaterAnimPreview::postBuild()
}
//-----------------------------------------------------------------------------
-// LLFloaterAnimPreview()
+// LLFloaterBvhPreview()
//-----------------------------------------------------------------------------
-LLFloaterAnimPreview::~LLFloaterAnimPreview()
+LLFloaterBvhPreview::~LLFloaterBvhPreview()
{
mAnimPreview = NULL;
@@ -375,7 +375,7 @@ LLFloaterAnimPreview::~LLFloaterAnimPreview()
//-----------------------------------------------------------------------------
// draw()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::draw()
+void LLFloaterBvhPreview::draw()
{
LLFloater::draw();
LLRect r = getRect();
@@ -414,7 +414,7 @@ void LLFloaterAnimPreview::draw()
//-----------------------------------------------------------------------------
// resetMotion()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::resetMotion()
+void LLFloaterBvhPreview::resetMotion()
{
LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();
BOOL paused = avatarp->areAnimationsPaused();
@@ -450,7 +450,7 @@ void LLFloaterAnimPreview::resetMotion()
//-----------------------------------------------------------------------------
// handleMouseDown()
//-----------------------------------------------------------------------------
-BOOL LLFloaterAnimPreview::handleMouseDown(S32 x, S32 y, MASK mask)
+BOOL LLFloaterBvhPreview::handleMouseDown(S32 x, S32 y, MASK mask)
{
if (mPreviewRect.pointInRect(x, y))
{
@@ -468,7 +468,7 @@ BOOL LLFloaterAnimPreview::handleMouseDown(S32 x, S32 y, MASK mask)
//-----------------------------------------------------------------------------
// handleMouseUp()
//-----------------------------------------------------------------------------
-BOOL LLFloaterAnimPreview::handleMouseUp(S32 x, S32 y, MASK mask)
+BOOL LLFloaterBvhPreview::handleMouseUp(S32 x, S32 y, MASK mask)
{
gFocusMgr.setMouseCapture(FALSE);
gViewerWindow->showCursor();
@@ -478,7 +478,7 @@ BOOL LLFloaterAnimPreview::handleMouseUp(S32 x, S32 y, MASK mask)
//-----------------------------------------------------------------------------
// handleHover()
//-----------------------------------------------------------------------------
-BOOL LLFloaterAnimPreview::handleHover(S32 x, S32 y, MASK mask)
+BOOL LLFloaterBvhPreview::handleHover(S32 x, S32 y, MASK mask)
{
MASK local_mask = mask & ~MASK_ALT;
@@ -533,7 +533,7 @@ BOOL LLFloaterAnimPreview::handleHover(S32 x, S32 y, MASK mask)
//-----------------------------------------------------------------------------
// handleScrollWheel()
//-----------------------------------------------------------------------------
-BOOL LLFloaterAnimPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)
+BOOL LLFloaterBvhPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
mAnimPreview->zoom((F32)clicks * -0.2f);
mAnimPreview->requestUpdate();
@@ -544,7 +544,7 @@ BOOL LLFloaterAnimPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)
//-----------------------------------------------------------------------------
// onMouseCaptureLost()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onMouseCaptureLost()
+void LLFloaterBvhPreview::onMouseCaptureLost()
{
gViewerWindow->showCursor();
}
@@ -552,7 +552,7 @@ void LLFloaterAnimPreview::onMouseCaptureLost()
//-----------------------------------------------------------------------------
// onBtnPlay()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onBtnPlay()
+void LLFloaterBvhPreview::onBtnPlay()
{
if (!getEnabled())
return;
@@ -576,7 +576,7 @@ void LLFloaterAnimPreview::onBtnPlay()
//-----------------------------------------------------------------------------
// onBtnPause()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onBtnPause()
+void LLFloaterBvhPreview::onBtnPause()
{
if (!getEnabled())
return;
@@ -598,7 +598,7 @@ void LLFloaterAnimPreview::onBtnPause()
//-----------------------------------------------------------------------------
// onBtnStop()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onBtnStop()
+void LLFloaterBvhPreview::onBtnStop()
{
if (!getEnabled())
return;
@@ -614,7 +614,7 @@ void LLFloaterAnimPreview::onBtnStop()
//-----------------------------------------------------------------------------
// onSliderMove()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onSliderMove()
+void LLFloaterBvhPreview::onSliderMove()
{
if (!getEnabled())
return;
@@ -639,7 +639,7 @@ void LLFloaterAnimPreview::onSliderMove()
//-----------------------------------------------------------------------------
// onCommitBaseAnim()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onCommitBaseAnim()
+void LLFloaterBvhPreview::onCommitBaseAnim()
{
if (!getEnabled())
return;
@@ -668,7 +668,7 @@ void LLFloaterAnimPreview::onCommitBaseAnim()
//-----------------------------------------------------------------------------
// onCommitLoop()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onCommitLoop()
+void LLFloaterBvhPreview::onCommitLoop()
{
if (!getEnabled())
return;
@@ -687,7 +687,7 @@ void LLFloaterAnimPreview::onCommitLoop()
//-----------------------------------------------------------------------------
// onCommitLoopIn()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onCommitLoopIn()
+void LLFloaterBvhPreview::onCommitLoopIn()
{
if (!getEnabled())
return;
@@ -707,7 +707,7 @@ void LLFloaterAnimPreview::onCommitLoopIn()
//-----------------------------------------------------------------------------
// onCommitLoopOut()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onCommitLoopOut()
+void LLFloaterBvhPreview::onCommitLoopOut()
{
if (!getEnabled())
return;
@@ -727,7 +727,7 @@ void LLFloaterAnimPreview::onCommitLoopOut()
//-----------------------------------------------------------------------------
// onCommitName()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onCommitName()
+void LLFloaterBvhPreview::onCommitName()
{
if (!getEnabled())
return;
@@ -746,7 +746,7 @@ void LLFloaterAnimPreview::onCommitName()
//-----------------------------------------------------------------------------
// onCommitHandPose()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onCommitHandPose()
+void LLFloaterBvhPreview::onCommitHandPose()
{
if (!getEnabled())
return;
@@ -757,7 +757,7 @@ void LLFloaterAnimPreview::onCommitHandPose()
//-----------------------------------------------------------------------------
// onCommitEmote()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onCommitEmote()
+void LLFloaterBvhPreview::onCommitEmote()
{
if (!getEnabled())
return;
@@ -768,7 +768,7 @@ void LLFloaterAnimPreview::onCommitEmote()
//-----------------------------------------------------------------------------
// onCommitPriority()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onCommitPriority()
+void LLFloaterBvhPreview::onCommitPriority()
{
if (!getEnabled())
return;
@@ -782,7 +782,7 @@ void LLFloaterAnimPreview::onCommitPriority()
//-----------------------------------------------------------------------------
// onCommitEaseIn()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onCommitEaseIn()
+void LLFloaterBvhPreview::onCommitEaseIn()
{
if (!getEnabled())
return;
@@ -797,7 +797,7 @@ void LLFloaterAnimPreview::onCommitEaseIn()
//-----------------------------------------------------------------------------
// onCommitEaseOut()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onCommitEaseOut()
+void LLFloaterBvhPreview::onCommitEaseOut()
{
if (!getEnabled())
return;
@@ -812,7 +812,7 @@ void LLFloaterAnimPreview::onCommitEaseOut()
//-----------------------------------------------------------------------------
// validateEaseIn()
//-----------------------------------------------------------------------------
-bool LLFloaterAnimPreview::validateEaseIn(const LLSD& data)
+bool LLFloaterBvhPreview::validateEaseIn(const LLSD& data)
{
if (!getEnabled())
return false;
@@ -832,7 +832,7 @@ bool LLFloaterAnimPreview::validateEaseIn(const LLSD& data)
//-----------------------------------------------------------------------------
// validateEaseOut()
//-----------------------------------------------------------------------------
-bool LLFloaterAnimPreview::validateEaseOut(const LLSD& data)
+bool LLFloaterBvhPreview::validateEaseOut(const LLSD& data)
{
if (!getEnabled())
return false;
@@ -852,7 +852,7 @@ bool LLFloaterAnimPreview::validateEaseOut(const LLSD& data)
//-----------------------------------------------------------------------------
// validateLoopIn()
//-----------------------------------------------------------------------------
-bool LLFloaterAnimPreview::validateLoopIn(const LLSD& data)
+bool LLFloaterBvhPreview::validateLoopIn(const LLSD& data)
{
if (!getEnabled())
return false;
@@ -880,7 +880,7 @@ bool LLFloaterAnimPreview::validateLoopIn(const LLSD& data)
//-----------------------------------------------------------------------------
// validateLoopOut()
//-----------------------------------------------------------------------------
-bool LLFloaterAnimPreview::validateLoopOut(const LLSD& data)
+bool LLFloaterBvhPreview::validateLoopOut(const LLSD& data)
{
if (!getEnabled())
return false;
@@ -909,7 +909,7 @@ bool LLFloaterAnimPreview::validateLoopOut(const LLSD& data)
//-----------------------------------------------------------------------------
// refresh()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::refresh()
+void LLFloaterBvhPreview::refresh()
{
// Are we showing the play button (default) or the pause button?
bool show_play = true;
@@ -958,9 +958,9 @@ void LLFloaterAnimPreview::refresh()
//-----------------------------------------------------------------------------
// onBtnOK()
//-----------------------------------------------------------------------------
-void LLFloaterAnimPreview::onBtnOK(void* userdata)
+void LLFloaterBvhPreview::onBtnOK(void* userdata)
{
- LLFloaterAnimPreview* floaterp = (LLFloaterAnimPreview*)userdata;
+ LLFloaterBvhPreview* floaterp = (LLFloaterBvhPreview*)userdata;
if (!floaterp->getEnabled()) return;
if (floaterp->mAnimPreview)
diff --git a/indra/newview/llfloateranimpreview.h b/indra/newview/llfloaterbvhpreview.h
index f1ffb6547f..b81cc6e3a5 100644
--- a/indra/newview/llfloateranimpreview.h
+++ b/indra/newview/llfloaterbvhpreview.h
@@ -1,6 +1,6 @@
/**
- * @file llfloateranimpreview.h
- * @brief LLFloaterAnimPreview class definition
+ * @file llfloaterbvhpreview.h
+ * @brief LLFloaterBvhPreview class definition
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -24,14 +24,15 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLFLOATERANIMPREVIEW_H
-#define LL_LLFLOATERANIMPREVIEW_H
+#ifndef LL_LLFLOATERBVHPREVIEW_H
+#define LL_LLFLOATERBVHPREVIEW_H
#include "llassettype.h"
#include "llfloaternamedesc.h"
#include "lldynamictexture.h"
#include "llcharacter.h"
#include "llquaternion.h"
+#include "llextendedstatus.h"
class LLVOAvatar;
class LLViewerJointMesh;
@@ -67,11 +68,11 @@ protected:
LLPointer<LLVOAvatar> mDummyAvatar;
};
-class LLFloaterAnimPreview : public LLFloaterNameDesc
+class LLFloaterBvhPreview : public LLFloaterNameDesc
{
public:
- LLFloaterAnimPreview(const std::string& filename);
- virtual ~LLFloaterAnimPreview();
+ LLFloaterBvhPreview(const std::string& filename);
+ virtual ~LLFloaterBvhPreview();
BOOL postBuild();
@@ -128,4 +129,4 @@ protected:
std::map<std::string, LLUUID> mIDList;
};
-#endif // LL_LLFLOATERANIMPREVIEW_H
+#endif // LL_LLFLOATERBVHPREVIEW_H
diff --git a/indra/newview/llfloatereditsky.cpp b/indra/newview/llfloatereditsky.cpp
index abee7b5dc9..352361ce9e 100644
--- a/indra/newview/llfloatereditsky.cpp
+++ b/indra/newview/llfloatereditsky.cpp
@@ -151,8 +151,8 @@ void LLFloaterEditSky::initCallbacks(void)
getChild<LLUICtrl>("WLBlueHorizon")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, &param_mgr.mBlueHorizon));
// haze density, horizon, mult, and altitude
- getChild<LLUICtrl>("WLHazeDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, &param_mgr.mHazeDensity));
- getChild<LLUICtrl>("WLHazeHorizon")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, &param_mgr.mHazeHorizon));
+ getChild<LLUICtrl>("WLHazeDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mHazeDensity));
+ getChild<LLUICtrl>("WLHazeHorizon")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mHazeHorizon));
getChild<LLUICtrl>("WLDensityMult")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mDensityMult));
getChild<LLUICtrl>("WLMaxAltitude")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mMaxAlt));
@@ -220,15 +220,14 @@ void LLFloaterEditSky::syncControls()
setColorSwatch("WLBlueHorizon", param_mgr->mBlueHorizon, WL_BLUE_HORIZON_DENSITY_SCALE);
// haze density, horizon, mult, and altitude
- param_mgr->mHazeDensity = cur_params.getVector(param_mgr->mHazeDensity.mName, err);
- childSetValue("WLHazeDensity", param_mgr->mHazeDensity.r);
- param_mgr->mHazeHorizon = cur_params.getVector(param_mgr->mHazeHorizon.mName, err);
- childSetValue("WLHazeHorizon", param_mgr->mHazeHorizon.r);
- param_mgr->mDensityMult = cur_params.getVector(param_mgr->mDensityMult.mName, err);
- childSetValue("WLDensityMult", param_mgr->mDensityMult.x *
- param_mgr->mDensityMult.mult);
- param_mgr->mMaxAlt = cur_params.getVector(param_mgr->mMaxAlt.mName, err);
- childSetValue("WLMaxAltitude", param_mgr->mMaxAlt.x);
+ param_mgr->mHazeDensity = cur_params.getFloat(param_mgr->mHazeDensity.mName, err);
+ childSetValue("WLHazeDensity", (F32) param_mgr->mHazeDensity);
+ param_mgr->mHazeHorizon = cur_params.getFloat(param_mgr->mHazeHorizon.mName, err);
+ childSetValue("WLHazeHorizon", (F32) param_mgr->mHazeHorizon);
+ param_mgr->mDensityMult = cur_params.getFloat(param_mgr->mDensityMult.mName, err);
+ childSetValue("WLDensityMult", ((F32) param_mgr->mDensityMult) * param_mgr->mDensityMult.mult);
+ param_mgr->mMaxAlt = cur_params.getFloat(param_mgr->mMaxAlt.mName, err);
+ childSetValue("WLMaxAltitude", (F32) param_mgr->mMaxAlt);
// blue density
param_mgr->mBlueDensity = cur_params.getVector(param_mgr->mBlueDensity.mName, err);
@@ -273,10 +272,10 @@ void LLFloaterEditSky::syncControls()
childSetValue("WLCloudDetailDensity", param_mgr->mCloudDetail.b);
// Cloud extras
- param_mgr->mCloudCoverage = cur_params.getVector(param_mgr->mCloudCoverage.mName, err);
- param_mgr->mCloudScale = cur_params.getVector(param_mgr->mCloudScale.mName, err);
- childSetValue("WLCloudCoverage", param_mgr->mCloudCoverage.x);
- childSetValue("WLCloudScale", param_mgr->mCloudScale.x);
+ param_mgr->mCloudCoverage = cur_params.getFloat(param_mgr->mCloudCoverage.mName, err);
+ param_mgr->mCloudScale = cur_params.getFloat(param_mgr->mCloudScale.mName, err);
+ childSetValue("WLCloudCoverage", (F32) param_mgr->mCloudCoverage);
+ childSetValue("WLCloudScale", (F32) param_mgr->mCloudScale);
// cloud scrolling
bool lockX = !param_mgr->mCurParams.getEnableCloudScrollX();
@@ -306,13 +305,13 @@ void LLFloaterEditSky::syncControls()
childSetValue("WLCloudScrollX", param_mgr->mCurParams.getCloudScrollX() - 10.0f);
childSetValue("WLCloudScrollY", param_mgr->mCurParams.getCloudScrollY() - 10.0f);
- param_mgr->mDistanceMult = cur_params.getVector(param_mgr->mDistanceMult.mName, err);
- childSetValue("WLDistanceMult", param_mgr->mDistanceMult.x);
+ param_mgr->mDistanceMult = cur_params.getFloat(param_mgr->mDistanceMult.mName, err);
+ childSetValue("WLDistanceMult", (F32) param_mgr->mDistanceMult);
// Tweak extras
- param_mgr->mWLGamma = cur_params.getVector(param_mgr->mWLGamma.mName, err);
- childSetValue("WLGamma", param_mgr->mWLGamma.x);
+ param_mgr->mWLGamma = cur_params.getFloat(param_mgr->mWLGamma.mName, err);
+ childSetValue("WLGamma", (F32) param_mgr->mWLGamma);
childSetValue("WLStarAlpha", param_mgr->mCurParams.getStarBrightness());
}
diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp
index 895e16adef..4f2a6ec1b7 100644
--- a/indra/newview/llfloatermediasettings.cpp
+++ b/indra/newview/llfloatermediasettings.cpp
@@ -312,3 +312,9 @@ bool LLFloaterMediaSettings::haveValuesChanged() const
return values_changed;
}
+bool LLFloaterMediaSettings::instanceExists()
+{
+ return LLFloaterReg::findTypedInstance<LLFloaterMediaSettings>("media_settings");
+}
+
+
diff --git a/indra/newview/llfloatermediasettings.h b/indra/newview/llfloatermediasettings.h
index ecc55d2cbc..1d25530986 100644
--- a/indra/newview/llfloatermediasettings.h
+++ b/indra/newview/llfloatermediasettings.h
@@ -45,6 +45,7 @@ public:
/*virtual*/ void onClose(bool app_quitting);
static LLFloaterMediaSettings* getInstance();
+ static bool instanceExists();
static void apply();
static void initValues( const LLSD& media_settings , bool editable);
static void clearValues( bool editable);
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 9122e5a8f5..7448f2bb2a 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -4525,7 +4525,17 @@ void LLModelPreview::updateStatusMessages()
}
}
- if (mFMP->childGetValue("physics_lod_combo").asString() == "From file")
+
+ LLCtrlSelectionInterface* iface = fmp->childGetSelectionInterface("physics_lod_combo");
+ S32 which_mode = 0;
+ S32 file_mode = 1;
+ if (iface)
+ {
+ which_mode = iface->getFirstSelectedIndex();
+ file_mode = iface->getItemCount() - 1;
+ }
+
+ if (which_mode == file_mode)
{
mFMP->childEnable("physics_file");
mFMP->childEnable("physics_browse");
diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp
index 66f0fc3cd7..27b1c3b9cd 100644
--- a/indra/newview/llfloaternamedesc.cpp
+++ b/indra/newview/llfloaternamedesc.cpp
@@ -207,6 +207,25 @@ BOOL LLFloaterSoundPreview::postBuild()
//-----------------------------------------------------------------------------
+// LLFloaterAnimPreview()
+//-----------------------------------------------------------------------------
+
+LLFloaterAnimPreview::LLFloaterAnimPreview(const LLSD& filename )
+ : LLFloaterNameDesc(filename)
+{
+}
+
+BOOL LLFloaterAnimPreview::postBuild()
+{
+ if (!LLFloaterNameDesc::postBuild())
+ {
+ return FALSE;
+ }
+ getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnOK, this));
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
// LLFloaterScriptPreview()
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llfloaternamedesc.h b/indra/newview/llfloaternamedesc.h
index 69bbccaf80..41643681ac 100644
--- a/indra/newview/llfloaternamedesc.h
+++ b/indra/newview/llfloaternamedesc.h
@@ -64,6 +64,13 @@ public:
virtual BOOL postBuild();
};
+class LLFloaterAnimPreview : public LLFloaterNameDesc
+{
+public:
+ LLFloaterAnimPreview(const LLSD& filename );
+ virtual BOOL postBuild();
+};
+
class LLFloaterScriptPreview : public LLFloaterNameDesc
{
public:
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index a333989e7e..173b0e538c 100755
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -741,7 +741,8 @@ void LLFloaterPreference::onClose(bool app_quitting)
void LLFloaterPreference::onOpenHardwareSettings()
{
- LLFloaterReg::showInstance("prefs_hardware_settings");
+ LLFloater* floater = LLFloaterReg::showInstance("prefs_hardware_settings");
+ addDependentFloater(floater, FALSE);
}
// static
void LLFloaterPreference::onBtnOK()
@@ -1800,7 +1801,46 @@ void LLPanelPreference::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl)
}
}
+class LLPanelPreferencePrivacy : public LLPanelPreference
+{
+public:
+ LLPanelPreferencePrivacy()
+ {
+ mAccountIndependentSettings.push_back("VoiceCallsFriendsOnly");
+ mAccountIndependentSettings.push_back("AutoDisengageMic");
+ }
+
+ /*virtual*/ void saveSettings()
+ {
+ LLPanelPreference::saveSettings();
+
+ // Don't save (=erase from the saved values map) per-account privacy settings
+ // if we're not logged in, otherwise they will be reset to defaults on log off.
+ if (LLStartUp::getStartupState() != STATE_STARTED)
+ {
+ // Erase only common settings, assuming there are no color settings on Privacy page.
+ for (control_values_map_t::iterator it = mSavedValues.begin(); it != mSavedValues.end(); )
+ {
+ const std::string setting = it->first->getName();
+ if (std::find(mAccountIndependentSettings.begin(),
+ mAccountIndependentSettings.end(), setting) == mAccountIndependentSettings.end())
+ {
+ mSavedValues.erase(it++);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+ }
+ }
+
+private:
+ std::list<std::string> mAccountIndependentSettings;
+};
+
static LLRegisterPanelClassWrapper<LLPanelPreferenceGraphics> t_pref_graph("panel_preference_graphics");
+static LLRegisterPanelClassWrapper<LLPanelPreferencePrivacy> t_pref_privacy("panel_preference_privacy");
BOOL LLPanelPreferenceGraphics::postBuild()
{
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 7ee3294478..ec5994e917 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -198,15 +198,17 @@ public:
virtual void saveSettings();
class Updater;
+
+protected:
+ typedef std::map<LLControlVariable*, LLSD> control_values_map_t;
+ control_values_map_t mSavedValues;
+
private:
//for "Only friends and groups can call or IM me"
static void showFriendsOnlyWarning(LLUICtrl*, const LLSD&);
//for "Show my Favorite Landmarks at Login"
static void showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value);
- typedef std::map<LLControlVariable*, LLSD> control_values_map_t;
- control_values_map_t mSavedValues;
-
typedef std::map<std::string, LLColor4> string_color_map_t;
string_color_map_t mSavedColors;
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index c402de66e8..ae45949b4a 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -33,6 +33,7 @@
#include "llfloater.h"
#include "llhost.h"
#include "llpanel.h"
+#include "llextendedstatus.h"
#include "llenvmanager.h" // for LLEnvironmentSettings
diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h
index cd98f7be57..7d68431710 100644
--- a/indra/newview/llfloaterreporter.h
+++ b/indra/newview/llfloaterreporter.h
@@ -31,6 +31,7 @@
#include "llfloater.h"
#include "lluuid.h"
#include "v3math.h"
+#include "llextendedstatus.h"
class LLAvatarName;
class LLMessageSystem;
diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp
index a0d1a32e12..b691db1049 100644
--- a/indra/newview/llfloaterscriptdebug.cpp
+++ b/indra/newview/llfloaterscriptdebug.cpp
@@ -106,7 +106,11 @@ void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std:
if (objectp)
{
objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", TRUE, LLViewerTexture::BOOST_UI));
- floater_label = llformat("%s(%.2f, %.2f)", user_name.c_str(), objectp->getPositionRegion().mV[VX], objectp->getPositionRegion().mV[VY]);
+ floater_label = llformat("%s(%.0f, %.0f, %.0f)",
+ user_name.c_str(),
+ objectp->getPositionRegion().mV[VX],
+ objectp->getPositionRegion().mV[VY],
+ objectp->getPositionRegion().mV[VZ]);
}
else
{
diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp
index be7a53491d..5385977d95 100644
--- a/indra/newview/llfloatersidepanelcontainer.cpp
+++ b/indra/newview/llfloatersidepanelcontainer.cpp
@@ -59,7 +59,10 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na
LLView* view = findChildView(panel_name, true);
if (!view) return NULL;
- openFloater();
+ if (!getVisible())
+ {
+ openFloater();
+ }
LLPanel* panel = NULL;
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index bd5b5f4eb0..6978e6a430 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -36,6 +36,7 @@
#include "llagentcamera.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
+#include "llcombobox.h"
#include "lldraghandle.h"
#include "llerror.h"
#include "llfloaterbuildoptions.h"
@@ -103,6 +104,7 @@ const std::string PANEL_NAMES[LLFloaterTools::PANEL_COUNT] =
// Local prototypes
+void commit_grid_mode(LLUICtrl *ctrl);
void commit_select_component(void *data);
void click_show_more(void*);
void click_popup_info(void*);
@@ -252,6 +254,7 @@ BOOL LLFloaterTools::postBuild()
getChild<LLUICtrl>("checkbox uniform")->setValue((BOOL)gSavedSettings.getBOOL("ScaleUniform"));
mCheckStretchTexture = getChild<LLCheckBoxCtrl>("checkbox stretch textures");
getChild<LLUICtrl>("checkbox stretch textures")->setValue((BOOL)gSavedSettings.getBOOL("ScaleStretchTextures"));
+ mComboGridMode = getChild<LLComboBox>("combobox grid mode");
mCheckStretchUniformLabel = getChild<LLTextBox>("checkbox uniform label");
//
@@ -330,6 +333,7 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)
mCheckSnapToGrid(NULL),
mBtnGridOptions(NULL),
mTitleMedia(NULL),
+ mComboGridMode(NULL),
mCheckStretchUniform(NULL),
mCheckStretchTexture(NULL),
mCheckStretchUniformLabel(NULL),
@@ -386,6 +390,7 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)
mCommitCallbackRegistrar.add("BuildTool.commitRadioMove", boost::bind(&commit_radio_group_move,_1));
mCommitCallbackRegistrar.add("BuildTool.commitRadioEdit", boost::bind(&commit_radio_group_edit,_1));
+ mCommitCallbackRegistrar.add("BuildTool.gridMode", boost::bind(&commit_grid_mode,_1));
mCommitCallbackRegistrar.add("BuildTool.selectComponent", boost::bind(&commit_select_component, this));
mCommitCallbackRegistrar.add("BuildTool.gridOptions", boost::bind(&LLFloaterTools::onClickGridOptions,this));
mCommitCallbackRegistrar.add("BuildTool.applyToSelection", boost::bind(&click_apply_to_selection, this));
@@ -687,6 +692,33 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
mRadioGroupEdit->setValue("radio select face");
}
+ if (mComboGridMode)
+ {
+ mComboGridMode->setVisible( edit_visible );
+ S32 index = mComboGridMode->getCurrentIndex();
+ mComboGridMode->removeall();
+
+ switch (mObjectSelection->getSelectType())
+ {
+ case SELECT_TYPE_HUD:
+ mComboGridMode->add(getString("grid_screen_text"));
+ mComboGridMode->add(getString("grid_local_text"));
+ break;
+ case SELECT_TYPE_WORLD:
+ mComboGridMode->add(getString("grid_world_text"));
+ mComboGridMode->add(getString("grid_local_text"));
+ mComboGridMode->add(getString("grid_reference_text"));
+ break;
+ case SELECT_TYPE_ATTACHMENT:
+ mComboGridMode->add(getString("grid_attachment_text"));
+ mComboGridMode->add(getString("grid_local_text"));
+ mComboGridMode->add(getString("grid_reference_text"));
+ break;
+ }
+
+ mComboGridMode->setCurrentByIndex(index);
+ }
+
// Snap to grid disabled for grab tool - very confusing
if (mCheckSnapToGrid) mCheckSnapToGrid->setVisible( edit_visible /* || tool == LLToolGrab::getInstance() */ );
if (mBtnGridOptions) mBtnGridOptions->setVisible( edit_visible /* || tool == LLToolGrab::getInstance() */ );
@@ -1037,6 +1069,13 @@ void LLFloaterTools::setObjectType( LLPCode pcode )
gFocusMgr.setMouseCapture(NULL);
}
+void commit_grid_mode(LLUICtrl *ctrl)
+{
+ LLComboBox* combo = (LLComboBox*)ctrl;
+
+ LLSelectMgr::getInstance()->setGridMode((EGridMode)combo->getCurrentIndex());
+}
+
void LLFloaterTools::onClickGridOptions()
{
@@ -1144,7 +1183,7 @@ void LLFloaterTools::updateLandImpacts()
childSetTextArg("remaining_capacity", "[CAPACITY_STRING]", remaining_capacity_str);
// Update land impacts info in the weights floater
- LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::getTypedInstance<LLFloaterObjectWeights>("object_weights");
+ LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::findTypedInstance<LLFloaterObjectWeights>("object_weights");
if(object_weights_floater)
{
object_weights_floater->updateLandImpacts(parcel);
@@ -1234,6 +1273,7 @@ void LLFloaterTools::getMediaState()
}
} func;
+
// check if all faces have media(or, all dont have media)
LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo = selected_objects->getSelectedTEValue( &func, bool_has_media );
diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h
index 63ed9dc82b..7a19d093a4 100644
--- a/indra/newview/llfloatertools.h
+++ b/indra/newview/llfloatertools.h
@@ -33,6 +33,7 @@
class LLButton;
class LLCheckBoxCtrl;
+class LLComboBox;
class LLPanelPermissions;
class LLPanelObject;
class LLPanelVolume;
@@ -140,6 +141,7 @@ public:
LLCheckBoxCtrl* mCheckSnapToGrid;
LLButton* mBtnGridOptions;
+ LLComboBox* mComboGridMode;
LLCheckBoxCtrl* mCheckStretchUniform;
LLCheckBoxCtrl* mCheckStretchTexture;
diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp
index 428a02e9f0..1a17183efd 100644
--- a/indra/newview/llfloatertranslationsettings.cpp
+++ b/indra/newview/llfloatertranslationsettings.cpp
@@ -293,6 +293,6 @@ void LLFloaterTranslationSettings::onBtnOK()
gSavedSettings.setString("TranslationService", getSelectedService());
gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey());
gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey());
- LLNearbyChatBar::getInstance()->enableTranslationCheckbox(LLTranslate::isTranslationConfigured());
+ LLNearbyChatBar::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured());
closeFloater(false);
}
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index e0d7d67f7d..86001e4146 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -255,7 +255,7 @@ LLFolderView::LLFolderView(const Params& p)
LLRect new_r = LLRect(rect.mLeft + ICON_PAD,
rect.mTop - TEXT_PAD,
rect.mRight,
- rect.mTop - TEXT_PAD - llfloor(font->getLineHeight()));
+ rect.mTop - TEXT_PAD - font->getLineHeight());
text_p.rect(new_r);
text_p.name(std::string(p.name));
text_p.font(font);
@@ -388,7 +388,7 @@ void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse
static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange");
-// This view grows and shinks to enclose all of its children items and folders.
+// This view grows and shrinks to enclose all of its children items and folders.
S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation )
{
if (getListener()->getUUID().notNull())
@@ -414,7 +414,7 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen
getRoot()->getFilter()->getShowFolderState();
S32 total_width = LEFT_PAD;
- S32 running_height = mDebugFilters ? llceil(LLFontGL::getFontMonospace()->getLineHeight()) : 0;
+ S32 running_height = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0;
S32 target_height = running_height;
S32 parent_item_height = getRect().getHeight();
@@ -527,15 +527,15 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent)
LLView::reshape(width, height, called_from_parent);
scroll_rect = mScrollContainer->getContentWindowRect();
}
- width = llmax(mMinWidth, scroll_rect.getWidth());
+ width = llmax(mMinWidth, scroll_rect.getWidth());
height = llmax(mRunningHeight, scroll_rect.getHeight());
- // restrict width with scroll container's width
- if (mUseEllipses)
+ // Restrict width within scroll container's width
+ if (mUseEllipses && mScrollContainer)
+ {
width = scroll_rect.getWidth();
-
+ }
LLView::reshape(width, height, called_from_parent);
-
mReshapeSignal(mSelectedItems, FALSE);
}
@@ -912,7 +912,7 @@ void LLFolderView::draw()
}
else if (mShowEmptyMessage)
{
- if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration())
+ if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration())
{
mStatusText = LLTrans::getString("Searching");
}
@@ -1966,7 +1966,7 @@ void LLFolderView::scrollToShowSelection()
// However we allow scrolling for folder views with mAutoSelectOverride
// (used in Places SP) as an exception because the selection in them
// is not reset during items filtering. See STORM-133.
- if ( (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mAutoSelectOverride)
+ if ( (!LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mAutoSelectOverride)
&& mSelectedItems.size() )
{
mNeedsScroll = TRUE;
@@ -1994,7 +1994,7 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr
LLRect visible_doc_rect = mScrollContainer->getVisibleContentRect();
S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight();
- S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight());
+ S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight();
// when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder
S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight();
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index 8d6114c887..afad27b4e0 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -410,8 +410,8 @@ BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* roo
}
-// Finds width and height of this object and it's children. Also
-// makes sure that this view and it's children are the right size.
+// Finds width and height of this object and its children. Also
+// makes sure that this view and its children are the right size.
S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)
{
const Params& p = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>();
@@ -423,7 +423,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)
: 0;
if (mLabelWidthDirty)
{
- mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mSearchableLabel);
+ mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + TEXT_PAD_RIGHT;
mLabelWidthDirty = false;
}
@@ -1045,7 +1045,7 @@ void LLFolderViewItem::draw()
}
if ((mIsLoading
&& mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime"))
- || (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()
+ || (LLInventoryModelBackgroundFetch::instance().folderFetchActive()
&& root_is_loading
&& mShowLoadStatus))
{
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 2fc79f5765..4e8dc2da16 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -114,6 +114,7 @@ public:
static const S32 ICON_PAD = 2;
static const S32 ICON_WIDTH = 16;
static const S32 TEXT_PAD = 1;
+ static const S32 TEXT_PAD_RIGHT = 4;
static const S32 ARROW_SIZE = 12;
static const S32 MAX_FOLDER_ITEM_OVERLAP = 2;
// animation parameters
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp
index bbf66ca750..129cddda45 100644
--- a/indra/newview/llgrouplist.cpp
+++ b/indra/newview/llgrouplist.cpp
@@ -123,6 +123,22 @@ BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)
return handled;
}
+// virtual
+BOOL LLGroupList::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = LLView::handleDoubleClick(x, y, mask);
+ // Handle double click only for the selected item in the list, skip clicks on empty space.
+ if (handled)
+ {
+ if (mDoubleClickSignal)
+ {
+ (*mDoubleClickSignal)(this, x, y, mask);
+ }
+ }
+
+ return handled;
+}
+
void LLGroupList::setNameFilter(const std::string& filter)
{
std::string filter_upper = filter;
diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h
index d7051db891..8abf14b3d0 100644
--- a/indra/newview/llgrouplist.h
+++ b/indra/newview/llgrouplist.h
@@ -51,6 +51,7 @@ public:
virtual void draw(); // from LLView
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); // from LLView
+ /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); // from LLView
void setNameFilter(const std::string& filter);
void toggleIcons();
diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp
index 122711a86d..dff310ecf9 100644
--- a/indra/newview/llhudrender.cpp
+++ b/indra/newview/llhudrender.cpp
@@ -138,7 +138,7 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
LLUI::translate((F32) winX*1.0f/LLFontGL::sScaleX, (F32) winY*1.0f/(LLFontGL::sScaleY), -(((F32) winZ*2.f)-1.f));
F32 right_x;
- font.render(wstr, 0, 0, 0, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x);
+ font.render(wstr, 0, 0, 1, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x);
LLUI::popMatrix();
gGL.popMatrix();
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 24a876c59a..579b6008ae 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -227,7 +227,7 @@ void LLHUDText::renderText()
segment_iter != mTextSegments.end(); ++segment_iter )
{
const LLFontGL* fontp = segment_iter->mFont;
- y_offset -= fontp->getLineHeight();
+ y_offset -= fontp->getLineHeight() - 1; // correction factor to match legacy font metrics
U8 style = segment_iter->mStyle;
LLFontGL::ShadowType shadow = LLFontGL::DROP_SHADOW;
@@ -480,8 +480,6 @@ void LLHUDText::updateSize()
F32 width = 0.f;
S32 max_lines = getMaxLines();
- //S32 lines = (max_lines < 0) ? (S32)mTextSegments.size() : llmin((S32)mTextSegments.size(), max_lines);
- //F32 height = (F32)mFontp->getLineHeight() * (lines + mLabelSegments.size());
S32 start_segment;
if (max_lines < 0) start_segment = 0;
@@ -491,7 +489,7 @@ void LLHUDText::updateSize()
while (iter != mTextSegments.end())
{
const LLFontGL* fontp = iter->mFont;
- height += fontp->getLineHeight();
+ height += fontp->getLineHeight() - 1; // correction factor to match legacy font metrics
width = llmax(width, llmin(iter->getWidth(fontp), HUD_TEXT_MAX_WIDTH));
++iter;
}
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index a856bd0bdc..c4ea8c0d31 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -2458,7 +2458,10 @@ void LLIMMgr::addMessage(
make_ui_sound("UISndNewIncomingIMSession");
}
- if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat))
+ bool skip_message = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") &&
+ LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL);
+
+ if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !skip_message)
{
LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg);
}
@@ -2977,6 +2980,17 @@ bool LLIMMgr::isVoiceCall(const LLUUID& session_id)
return im_session->mStartedAsIMCall;
}
+void LLIMMgr::addNotifiedNonFriendSessionID(const LLUUID& session_id)
+{
+ mNotifiedNonFriendSessions.insert(session_id);
+}
+
+bool LLIMMgr::isNonFriendSessionNotified(const LLUUID& session_id)
+{
+ return mNotifiedNonFriendSessions.end() != mNotifiedNonFriendSessions.find(session_id);
+
+}
+
void LLIMMgr::noteOfflineUsers(
const LLUUID& session_id,
const LLDynamicArray<LLUUID>& ids)
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index b1be26a169..f07a78e2f7 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -438,6 +438,10 @@ public:
bool isVoiceCall(const LLUUID& session_id);
+ void addNotifiedNonFriendSessionID(const LLUUID& session_id);
+
+ bool isNonFriendSessionNotified(const LLUUID& session_id);
+
private:
/**
@@ -465,6 +469,14 @@ private:
typedef std::list <LLIMSessionObserver *> session_observers_list_t;
session_observers_list_t mSessionObservers;
+ // EXP-901
+ // If "Only friends and groups can IM me" option is ON but the user got message from non-friend,
+ // the user should be notified that to be able to see this message the option should be OFF.
+ // This set stores session IDs in which user was notified. Need to store this IDs so that the user
+ // be notified only one time per session with non-friend.
+ typedef std::set<LLUUID> notified_non_friend_sessions_t;
+ notified_non_friend_sessions_t mNotifiedNonFriendSessions;
+
LLSD mPendingInvitations;
LLSD mPendingAgentListUpdates;
};
diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp
index d7b82667d1..f4fe5dec01 100644
--- a/indra/newview/llinspecttoast.cpp
+++ b/indra/newview/llinspecttoast.cpp
@@ -72,6 +72,8 @@ LLInspectToast::LLInspectToast(const LLSD& notification_id) :
LLInspectToast::~LLInspectToast()
{
LLTransientFloaterMgr::getInstance()->removeControlView(this);
+
+ mConnection.disconnect();
}
// virtual
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index c0065a94e6..2de2b17373 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -113,6 +113,13 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
bool confirm_attachment_rez(const LLSD& notification, const LLSD& response);
void teleport_via_landmark(const LLUUID& asset_id);
static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit);
+static bool check_category(LLInventoryModel* model,
+ const LLUUID& cat_id,
+ LLFolderView* active_folder_view,
+ LLInventoryFilter* filter);
+static bool check_item(const LLUUID& item_id,
+ LLFolderView* active_folder_view,
+ LLInventoryFilter* filter);
// Helper functions
@@ -148,7 +155,7 @@ LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory,
mInvType(LLInventoryType::IT_NONE),
mIsLink(FALSE)
{
- mInventoryPanel = inventory->getHandle();
+ mInventoryPanel = inventory->getInventoryPanelHandle();
const LLInventoryObject* obj = getInventoryObject();
mIsLink = obj && obj->getIsLinkType();
}
@@ -798,7 +805,7 @@ LLInventoryObject* LLInvFVBridge::getInventoryObject() const
LLInventoryModel* LLInvFVBridge::getInventoryModel() const
{
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLInventoryPanel* panel = mInventoryPanel.get();
return panel ? panel->getModel() : NULL;
}
@@ -1324,8 +1331,8 @@ void LLItemBridge::selectItem()
LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem());
if(item && !item->isFinished())
{
- item->fetchFromServer();
- //LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false);
+ //item->fetchFromServer();
+ LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false);
}
}
@@ -1738,7 +1745,7 @@ BOOL LLFolderBridge::isItemRemovable() const
return FALSE;
}
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLInventoryPanel* panel = mInventoryPanel.get();
LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL);
if (folderp)
{
@@ -1959,6 +1966,12 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
if (!isAgentAvatarValid()) return FALSE;
if (!isAgentInventory()) return FALSE; // cannot drag categories into library
+ LLInventoryPanel* destination_panel = mInventoryPanel.get();
+ if (!destination_panel) return false;
+
+ LLInventoryFilter* filter = destination_panel->getFilter();
+ if (!filter) return false;
+
const LLUUID &cat_id = inv_cat->getUUID();
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
@@ -2096,7 +2109,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
// NOTE: The cargo id's count is a total of categories AND items but we err on the side of
// prevention rather than letting too many folders into the hierarchy of the outbox,
// when we're dragging the item to a new parent
- dragged_folder_count += LLToolDragAndDrop::instance().getCargoIDsCount();
+ dragged_folder_count += LLToolDragAndDrop::instance().getCargoCount();
}
}
@@ -2146,6 +2159,39 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
+ if (is_movable)
+ {
+ LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
+ is_movable = active_panel != NULL;
+
+ // For a folder to pass the filter all its descendants are required to pass.
+ // We make this exception to allow reordering folders within an inventory panel,
+ // which has a filter applied, like Recent tab for example.
+ // There may be folders which are displayed because some of their descendants pass
+ // the filter, but other don't, and thus remain hidden. Without this check,
+ // such folders would not be allowed to be moved within a panel.
+ if (destination_panel == active_panel)
+ {
+ is_movable = true;
+ }
+ else
+ {
+ LLFolderView* active_folder_view = NULL;
+
+ if (is_movable)
+ {
+ active_folder_view = active_panel->getRootFolder();
+ is_movable = active_folder_view != NULL;
+ }
+
+ if (is_movable)
+ {
+ // Check whether the folder being dragged from active inventory panel
+ // passes the filter of the destination panel.
+ is_movable = check_category(model, cat_id, active_folder_view, filter);
+ }
+ }
+ }
//
//--------------------------------------------------------------------------------
@@ -2240,7 +2286,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
else
{
- accept = move_inv_category_world_to_agent(cat_id, mUUID, drop);
+ accept = move_inv_category_world_to_agent(cat_id, mUUID, drop, NULL, NULL, filter);
}
}
else if (LLToolDragAndDrop::SOURCE_LIBRARY == source)
@@ -2285,7 +2331,8 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
const LLUUID& category_id,
BOOL drop,
void (*callback)(S32, void*),
- void* user_data)
+ void* user_data,
+ LLInventoryFilter* filter)
{
// Make sure the object exists. If we allowed dragging from
// anonymous objects, it would be possible to bypass
@@ -2309,7 +2356,7 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
return FALSE;
}
- BOOL accept = TRUE;
+ BOOL accept = FALSE;
BOOL is_move = FALSE;
// coming from a task. Need to figure out if the person can
@@ -2318,9 +2365,16 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
LLInventoryObject::object_list_t::iterator end = inventory_objects.end();
for ( ; it != end; ++it)
{
+ LLInventoryItem* item = dynamic_cast<LLInventoryItem*>(it->get());
+ if (!item)
+ {
+ llwarns << "Invalid inventory item for drop" << llendl;
+ continue;
+ }
+
// coming from a task. Need to figure out if the person can
// move/copy this item.
- LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions());
+ LLPermissions perm(item->getPermissions());
if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
&& perm.allowTransferTo(gAgent.getID())))
// || gAgent.isGodlike())
@@ -2335,9 +2389,14 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
is_move = TRUE;
accept = TRUE;
}
- else
+
+ if (filter && accept)
+ {
+ accept = filter->check(item);
+ }
+
+ if (!accept)
{
- accept = FALSE;
break;
}
}
@@ -2820,18 +2879,62 @@ void LLFolderBridge::pasteFromClipboard()
if(model && isClipboardPasteable())
{
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
+ const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
-
- const LLUUID parent_id(mUUID);
+ const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
LLDynamicArray<LLUUID> objects;
LLInventoryClipboard::instance().retrieve(objects);
+
+ if (move_is_into_outbox)
+ {
+ LLFolderViewItem * outbox_itemp = mRoot->getItemByID(mUUID);
+
+ if (outbox_itemp)
+ {
+ LLToolDragAndDrop::instance().setCargoCount(objects.size());
+
+ BOOL can_list = TRUE;
+
+ for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin();
+ (iter != objects.end()) && (can_list == TRUE);
+ ++iter)
+ {
+ const LLUUID& item_id = (*iter);
+ LLInventoryItem *item = model->getItem(item_id);
+
+ if (item)
+ {
+ MASK mask = 0x0;
+ BOOL drop = FALSE;
+ EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(item->getActualType());
+ void * cargo_data = (void *) item;
+ std::string tooltip_msg;
+
+ can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg);
+ }
+ }
+
+ LLToolDragAndDrop::instance().resetCargoCount();
+
+ if (can_list == FALSE)
+ {
+ // Notify user of failure somehow -- play error sound? modal dialog?
+ return;
+ }
+ }
+ }
+
+ const LLUUID parent_id(mUUID);
+
for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin();
iter != objects.end();
++iter)
{
const LLUUID& item_id = (*iter);
+
LLInventoryItem *item = model->getItem(item_id);
if (item)
{
@@ -2874,8 +2977,17 @@ void LLFolderBridge::pasteLinkFromClipboard()
if(model)
{
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
+ const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
+
const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
+
+ if (move_is_into_outbox)
+ {
+ // Notify user of failure somehow -- play error sound? modal dialog?
+ return;
+ }
const LLUUID parent_id(mUUID);
@@ -3290,7 +3402,7 @@ void LLFolderBridge::createNewCategory(void* user_data)
{
LLFolderBridge* bridge = (LLFolderBridge*)user_data;
if(!bridge) return;
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get());
+ LLInventoryPanel* panel = bridge->mInventoryPanel.get();
if (!panel) return;
LLInventoryModel* model = panel->getModel();
if(!model) return;
@@ -3470,7 +3582,7 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item)
// use callback to rearrange favorite landmarks after adding
// to have new one placed before target (on which it was dropped). See EXT-4312.
LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback();
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLInventoryPanel* panel = mInventoryPanel.get();
LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
if (drag_over_item && drag_over_item->getListener())
{
@@ -3520,6 +3632,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
if (!isAgentInventory()) return FALSE; // cannot drag into library
if (!isAgentAvatarValid()) return FALSE;
+ LLInventoryPanel* destination_panel = mInventoryPanel.get();
+ if (!destination_panel) return false;
+
+ LLInventoryFilter* filter = destination_panel->getFilter();
+ if (!filter) return false;
+
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false);
const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false);
@@ -3529,7 +3647,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
const BOOL move_is_into_favorites = (mUUID == favorites_id);
const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id);
- const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); //(mUUID == outbox_id);
+ const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_item->getUUID(), outbox_id);
LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
@@ -3608,7 +3726,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID);
- int existing_item_count = LLToolDragAndDrop::instance().getCargoIDsCount();
+ int existing_item_count = LLToolDragAndDrop::instance().getCargoCount();
if (master_folder != NULL)
{
@@ -3628,6 +3746,21 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
}
+ LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
+
+ // Check whether the item being dragged from active inventory panel
+ // passes the filter of the destination panel.
+ if (accept && active_panel)
+ {
+ LLFolderView* active_folder_view = active_panel->getRootFolder();
+ if (!active_folder_view) return false;
+
+ LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID());
+ if (!fv_item) return false;
+
+ accept = filter->check(fv_item);
+ }
+
if (accept && drop)
{
if (inv_item->getType() == LLAssetType::AT_GESTURE
@@ -3637,15 +3770,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
// If an item is being dragged between windows, unselect everything in the active window
// so that we don't follow the selection to its new location (which is very annoying).
- LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
- if (active_panel)
- {
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- if (active_panel && (panel != active_panel))
+ if (active_panel && (destination_panel != active_panel))
{
active_panel->unSelectAll();
}
- }
//--------------------------------------------------------------------------------
// Destination folder logic
@@ -3655,8 +3783,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
// (only reorder the item in Favorites folder)
if ((mUUID == inv_item->getParentUUID()) && move_is_into_favorites)
{
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
+ LLFolderViewItem* itemp = destination_panel->getRootFolder()->getDraggingOverItem();
if (itemp)
{
LLUUID srcItemId = inv_item->getUUID();
@@ -3760,6 +3887,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
accept = FALSE;
}
+ // Check whether the item being dragged from in world
+ // passes the filter of the destination panel.
+ if (accept)
+ {
+ accept = filter->check(inv_item);
+ }
+
if (accept && drop)
{
LLMoveInv* move_inv = new LLMoveInv;
@@ -3797,6 +3931,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
accept = !(move_is_into_current_outfit || move_is_into_outfit);
}
+ // Check whether the item being dragged from notecard
+ // passes the filter of the destination panel.
+ if (accept)
+ {
+ accept = filter->check(inv_item);
+ }
+
if (accept && drop)
{
copy_inventory_from_notecard(mUUID, // Drop to the chosen destination folder
@@ -3828,6 +3969,21 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
accept = can_move_to_landmarks(inv_item);
}
+ LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
+
+ // Check whether the item being dragged from the library
+ // passes the filter of the destination panel.
+ if (accept && active_panel)
+ {
+ LLFolderView* active_folder_view = active_panel->getRootFolder();
+ if (!active_folder_view) return false;
+
+ LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID());
+ if (!fv_item) return false;
+
+ accept = filter->check(fv_item);
+ }
+
if (accept && drop)
{
// FAVORITES folder
@@ -3862,6 +4018,69 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
return accept;
}
+// static
+bool check_category(LLInventoryModel* model,
+ const LLUUID& cat_id,
+ LLFolderView* active_folder_view,
+ LLInventoryFilter* filter)
+{
+ if (!model || !active_folder_view || !filter)
+ return false;
+
+ if (!filter->checkFolder(cat_id))
+ {
+ return false;
+ }
+
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ model->collectDescendents(cat_id, descendent_categories, descendent_items, TRUE);
+
+ S32 num_descendent_categories = descendent_categories.count();
+ S32 num_descendent_items = descendent_items.count();
+
+ if (num_descendent_categories + num_descendent_items == 0)
+ {
+ // Empty folder should be checked as any other folder view item.
+ // If we are filtering by date the folder should not pass because
+ // it doesn't have its own creation date. See LLInvFVBridge::getCreationDate().
+ return check_item(cat_id, active_folder_view, filter);
+ }
+
+ for (S32 i = 0; i < num_descendent_categories; ++i)
+ {
+ LLInventoryCategory* category = descendent_categories[i];
+ if(!check_category(model, category->getUUID(), active_folder_view, filter))
+ {
+ return false;
+ }
+ }
+
+ for (S32 i = 0; i < num_descendent_items; ++i)
+ {
+ LLViewerInventoryItem* item = descendent_items[i];
+ if(!check_item(item->getUUID(), active_folder_view, filter))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// static
+bool check_item(const LLUUID& item_id,
+ LLFolderView* active_folder_view,
+ LLInventoryFilter* filter)
+{
+ if (!active_folder_view || !filter) return false;
+
+ LLFolderViewItem* fv_item = active_folder_view->getItemByID(item_id);
+ if (!fv_item) return false;
+
+ return filter->check(fv_item);
+}
+
// +=================================================+
// | LLTextureBridge |
// +=================================================+
@@ -4184,7 +4403,7 @@ LLCallingCardBridge::~LLCallingCardBridge()
void LLCallingCardBridge::refreshFolderViewItem()
{
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLInventoryPanel* panel = mInventoryPanel.get();
LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL;
if (itemp)
{
@@ -4633,14 +4852,14 @@ void LLAnimationBridge::performAction(LLInventoryModel* model, std::string actio
{
if (getItem())
{
- LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE;
- if ("playworld" == action) activate = LLPreviewAnim::PLAY;
- if ("playlocal" == action) activate = LLPreviewAnim::AUDITION;
+ LLSD::String activate = "NONE";
+ if ("playworld" == action) activate = "Inworld";
+ if ("playlocal" == action) activate = "Locally";
LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID));
if (preview)
{
- preview->activate(activate);
+ preview->play(activate);
}
}
}
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 871657a58a..3b4f845f54 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -35,6 +35,7 @@
#include "llviewercontrol.h"
#include "llwearable.h"
+class LLInventoryFilter;
class LLInventoryPanel;
class LLInventoryModel;
class LLMenuGL;
@@ -161,7 +162,7 @@ protected:
BOOL restamp);
void removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch);
protected:
- LLHandle<LLPanel> mInventoryPanel;
+ LLHandle<LLInventoryPanel> mInventoryPanel;
LLFolderView* mRoot;
const LLUUID mUUID; // item id
LLInventoryType::EType mInvType;
@@ -645,7 +646,8 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
const LLUUID& category_id,
BOOL drop,
void (*callback)(S32, void*) = NULL,
- void* user_data = NULL);
+ void* user_data = NULL,
+ LLInventoryFilter* filter = NULL);
// Utility function to hide all entries except those in the list
// Can be called multiple times on the same menu (e.g. if multiple items
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index d54bce4619..5496c273f2 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -108,16 +108,48 @@ BOOL LLInventoryFilter::check(const LLFolderViewItem* item)
return passed;
}
-bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder)
+bool LLInventoryFilter::check(const LLInventoryItem* item)
{
- // we're showing all folders, overriding filter
- if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)
+ mSubStringMatchOffset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos;
+
+ const bool passed_filtertype = checkAgainstFilterType(item);
+ const bool passed_permissions = checkAgainstPermissions(item);
+ const bool passed = (passed_filtertype &&
+ passed_permissions &&
+ (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos));
+
+ return passed;
+}
+
+bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const
+{
+ if (!folder)
{
- return true;
+ llwarns << "The filter can not be checked on an invalid folder." << llendl;
+ llassert(false); // crash in development builds
+ return false;
}
const LLFolderViewEventListener* listener = folder->getListener();
+ if (!listener)
+ {
+ llwarns << "Folder view event listener not found." << llendl;
+ llassert(false); // crash in development builds
+ return false;
+ }
+
const LLUUID folder_id = listener->getUUID();
+
+ return checkFolder(folder_id);
+}
+
+bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const
+{
+ // we're showing all folders, overriding filter
+ if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)
+ {
+ return true;
+ }
if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY)
{
@@ -227,6 +259,56 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con
return TRUE;
}
+bool LLInventoryFilter::checkAgainstFilterType(const LLInventoryItem* item) const
+{
+ LLInventoryType::EType object_type = item->getInventoryType();
+ const LLUUID object_id = item->getUUID();
+
+ const U32 filterTypes = mFilterOps.mFilterTypes;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_OBJECT
+ // Pass if this item's type is of the correct filter type
+ if (filterTypes & FILTERTYPE_OBJECT)
+ {
+ // If it has no type, pass it, unless it's a link.
+ if (object_type == LLInventoryType::IT_NONE)
+ {
+ if (item && item->getIsLinkType())
+ {
+ return false;
+ }
+ }
+ else if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0))
+ {
+ return false;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_UUID
+ // Pass if this item is the target UUID or if it links to the target UUID
+ if (filterTypes & FILTERTYPE_UUID)
+ {
+ if (!item) return false;
+
+ if (item->getLinkedUUID() != mFilterOps.mFilterUUID)
+ return false;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // FILTERTYPE_DATE
+ // Pass if this item is within the date range.
+ if (filterTypes & FILTERTYPE_DATE)
+ {
+ // We don't get the updated item creation date for the task inventory or
+ // a notecard embedded item. See LLTaskInvFVBridge::getCreationDate().
+ return false;
+ }
+
+ return true;
+}
+
BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const
{
const LLFolderViewEventListener* listener = item->getListener();
@@ -244,6 +326,17 @@ BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) co
return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions;
}
+bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) const
+{
+ if (!item) return false;
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ PermissionMask perm = new_item->getPermissionMask();
+ new_item = NULL;
+
+ return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions;
+}
+
BOOL LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const
{
const LLFolderViewEventListener* listener = item->getListener();
@@ -464,7 +557,9 @@ void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date)
mFilterOps.mMaxDate = llmax(mFilterOps.mMinDate, max_date);
setModified();
}
- mFilterOps.mFilterTypes |= FILTERTYPE_DATE;
+
+ areDateLimitsSet() ? mFilterOps.mFilterTypes |= FILTERTYPE_DATE
+ : mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE;
}
void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)
@@ -476,10 +571,12 @@ void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)
}
if (!sl && isSinceLogoff())
{
- setDateRange(0, time_max());
+ setDateRange(time_min(), time_max());
setModified();
}
- mFilterOps.mFilterTypes |= FILTERTYPE_DATE;
+
+ areDateLimitsSet() ? mFilterOps.mFilterTypes |= FILTERTYPE_DATE
+ : mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE;
}
BOOL LLInventoryFilter::isSinceLogoff() const
@@ -524,7 +621,9 @@ void LLInventoryFilter::setHoursAgo(U32 hours)
setModified(FILTER_RESTART);
}
}
- mFilterOps.mFilterTypes |= FILTERTYPE_DATE;
+
+ areDateLimitsSet() ? mFilterOps.mFilterTypes |= FILTERTYPE_DATE
+ : mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE;
}
void LLInventoryFilter::setFilterLinks(U64 filter_links)
@@ -804,7 +903,7 @@ const std::string& LLInventoryFilter::getFilterText()
filtered_by_all_types = FALSE;
}
- if (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()
+ if (!LLInventoryModelBackgroundFetch::instance().folderFetchActive()
&& filtered_by_type
&& !filtered_by_all_types)
{
@@ -974,3 +1073,10 @@ const std::string& LLInventoryFilter::getEmptyLookupMessage() const
return mEmptyLookupMessage;
}
+
+bool LLInventoryFilter::areDateLimitsSet()
+{
+ return mFilterOps.mMinDate != time_min()
+ || mFilterOps.mMaxDate != time_max()
+ || mFilterOps.mHoursAgo != 0;
+}
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index bba24ac652..6be2acfaa3 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -32,6 +32,7 @@
class LLFolderViewItem;
class LLFolderViewFolder;
+class LLInventoryItem;
class LLInventoryFilter
{
@@ -115,9 +116,13 @@ public:
// + Execution And Results
// +-------------------------------------------------------------------+
BOOL check(const LLFolderViewItem* item);
- bool checkFolder(const LLFolderViewFolder* folder);
+ bool check(const LLInventoryItem* item);
+ bool checkFolder(const LLFolderViewFolder* folder) const;
+ bool checkFolder(const LLUUID& folder_id) const;
BOOL checkAgainstFilterType(const LLFolderViewItem* item) const;
+ bool checkAgainstFilterType(const LLInventoryItem* item) const;
BOOL checkAgainstPermissions(const LLFolderViewItem* item) const;
+ bool checkAgainstPermissions(const LLInventoryItem* item) const;
BOOL checkAgainstFilterLinks(const LLFolderViewItem* item) const;
std::string::size_type getStringMatchOffset() const;
@@ -175,6 +180,8 @@ public:
void fromLLSD(LLSD& data);
private:
+ bool areDateLimitsSet();
+
struct FilterOps
{
FilterOps();
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index 91fdd67806..f4d0110b0f 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -43,6 +43,7 @@ const S32 MAX_FETCH_RETRIES = 10;
LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch() :
mBackgroundFetchActive(FALSE),
+ mFolderFetchActive(false),
mAllFoldersFetched(FALSE),
mRecursiveInventoryFetchStarted(FALSE),
mRecursiveLibraryFetchStarted(FALSE),
@@ -50,7 +51,7 @@ LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch() :
mMinTimeBetweenFetches(0.3f),
mMaxTimeBetweenFetches(10.f),
mTimelyFetchPending(FALSE),
- mBulkFetchCount(0)
+ mFetchCount(0)
{
}
@@ -60,7 +61,7 @@ LLInventoryModelBackgroundFetch::~LLInventoryModelBackgroundFetch()
bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete() const
{
- return mFetchQueue.empty() && mBulkFetchCount<=0;
+ return mFetchQueue.empty() && mFetchCount<=0;
}
bool LLInventoryModelBackgroundFetch::libraryFetchStarted() const
@@ -98,19 +99,21 @@ bool LLInventoryModelBackgroundFetch::isEverythingFetched() const
return mAllFoldersFetched;
}
-BOOL LLInventoryModelBackgroundFetch::backgroundFetchActive() const
+BOOL LLInventoryModelBackgroundFetch::folderFetchActive() const
{
- return mBackgroundFetchActive;
+ return mFolderFetchActive;
}
-void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive)
+void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive)
{
- if (!mAllFoldersFetched || cat_id.notNull())
- {
- LL_DEBUGS("InventoryFetch") << "Start fetching category: " << cat_id << ", recursive: " << recursive << LL_ENDL;
+ LLViewerInventoryCategory* cat = gInventory.getCategory(id);
+ if (cat || (id.isNull() && !isEverythingFetched()))
+ { // it's a folder, do a bulk fetch
+ LL_DEBUGS("InventoryFetch") << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL;
mBackgroundFetchActive = TRUE;
- if (cat_id.isNull())
+ mFolderFetchActive = true;
+ if (id.isNull())
{
if (!mRecursiveInventoryFetchStarted)
{
@@ -128,41 +131,41 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive
else
{
// Specific folder requests go to front of queue.
- if (mFetchQueue.empty() || mFetchQueue.front().mCatUUID != cat_id)
+ if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id)
{
- mFetchQueue.push_front(FetchQueueInfo(cat_id, recursive));
+ mFetchQueue.push_front(FetchQueueInfo(id, recursive));
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
}
- if (cat_id == gInventory.getLibraryRootFolderID())
+ if (id == gInventory.getLibraryRootFolderID())
{
mRecursiveLibraryFetchStarted |= recursive;
}
- if (cat_id == gInventory.getRootFolderID())
+ if (id == gInventory.getRootFolderID())
{
mRecursiveInventoryFetchStarted |= recursive;
}
}
}
+ else if (LLViewerInventoryItem* itemp = gInventory.getItem(id))
+ {
+ if (!itemp->mIsComplete && (mFetchQueue.empty() || mFetchQueue.front().mUUID != id))
+ {
+ mBackgroundFetchActive = TRUE;
+
+ mFetchQueue.push_front(FetchQueueInfo(id, false, false));
+ gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
+ }
+ }
}
void LLInventoryModelBackgroundFetch::findLostItems()
{
mBackgroundFetchActive = TRUE;
+ mFolderFetchActive = true;
mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, TRUE));
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
}
-void LLInventoryModelBackgroundFetch::stopBackgroundFetch()
-{
- if (mBackgroundFetchActive)
- {
- mBackgroundFetchActive = FALSE;
- gIdleCallbacks.deleteFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
- mBulkFetchCount=0;
- mMinTimeBetweenFetches=0.0f;
- }
-}
-
void LLInventoryModelBackgroundFetch::setAllFoldersFetched()
{
if (mRecursiveInventoryFetchStarted &&
@@ -170,7 +173,7 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched()
{
mAllFoldersFetched = TRUE;
}
- stopBackgroundFetch();
+ mFolderFetchActive = false;
}
void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *)
@@ -183,10 +186,9 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
if (mBackgroundFetchActive && gAgent.getRegion())
{
// If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
- std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");
- if (gSavedSettings.getBOOL("UseHTTPInventory") && !url.empty())
+ if (gSavedSettings.getBOOL("UseHTTPInventory"))
{
- bulkFetch(url);
+ bulkFetch();
return;
}
@@ -201,6 +203,9 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
llinfos << "Inventory fetch completed" << llendl;
setAllFoldersFetched();
+ mBackgroundFetchActive = false;
+ mFolderFetchActive = false;
+
return;
}
@@ -230,80 +235,114 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
}
const FetchQueueInfo info = mFetchQueue.front();
- LLViewerInventoryCategory* cat = gInventory.getCategory(info.mCatUUID);
- // Category has been deleted, remove from queue.
- if (!cat)
+ if (info.mIsCategory)
{
- mFetchQueue.pop_front();
- continue;
- }
+
+ LLViewerInventoryCategory* cat = gInventory.getCategory(info.mUUID);
+
+ // Category has been deleted, remove from queue.
+ if (!cat)
+ {
+ mFetchQueue.pop_front();
+ continue;
+ }
- if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches &&
- LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
- {
- // Category exists but has no children yet, fetch the descendants
- // for now, just request every time and rely on retry timer to throttle.
- if (cat->fetch())
+ if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches &&
+ LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
{
- mFetchTimer.reset();
- mTimelyFetchPending = TRUE;
+ // Category exists but has no children yet, fetch the descendants
+ // for now, just request every time and rely on retry timer to throttle.
+ if (cat->fetch())
+ {
+ mFetchTimer.reset();
+ mTimelyFetchPending = TRUE;
+ }
+ else
+ {
+ // The catagory also tracks if it has expired and here it says it hasn't
+ // yet. Get out of here because nothing is going to happen until we
+ // update the timers.
+ break;
+ }
}
- else
+ // Do I have all my children?
+ else if (gInventory.isCategoryComplete(info.mUUID))
{
- // The catagory also tracks if it has expired and here it says it hasn't
- // yet. Get out of here because nothing is going to happen until we
- // update the timers.
+ // Finished with this category, remove from queue.
+ mFetchQueue.pop_front();
+
+ // Add all children to queue.
+ LLInventoryModel::cat_array_t* categories;
+ LLInventoryModel::item_array_t* items;
+ gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
+ for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
+ it != categories->end();
+ ++it)
+ {
+ mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(),info.mRecursive));
+ }
+
+ // We received a response in less than the fast time.
+ if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() < fast_fetch_time)
+ {
+ // Shrink timeouts based on success.
+ mMinTimeBetweenFetches = llmax(mMinTimeBetweenFetches * 0.8f, 0.3f);
+ mMaxTimeBetweenFetches = llmax(mMaxTimeBetweenFetches * 0.8f, 10.f);
+ lldebugs << "Inventory fetch times shrunk to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << llendl;
+ }
+
+ mTimelyFetchPending = FALSE;
+ continue;
+ }
+ else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches)
+ {
+ // Received first packet, but our num descendants does not match db's num descendants
+ // so try again later.
+ mFetchQueue.pop_front();
+
+ if (mNumFetchRetries++ < MAX_FETCH_RETRIES)
+ {
+ // push on back of queue
+ mFetchQueue.push_back(info);
+ }
+ mTimelyFetchPending = FALSE;
+ mFetchTimer.reset();
break;
}
+
+ // Not enough time has elapsed to do a new fetch
+ break;
}
- // Do I have all my children?
- else if (gInventory.isCategoryComplete(info.mCatUUID))
+ else
{
- // Finished with this category, remove from queue.
- mFetchQueue.pop_front();
+ LLViewerInventoryItem* itemp = gInventory.getItem(info.mUUID);
- // Add all children to queue.
- LLInventoryModel::cat_array_t* categories;
- LLInventoryModel::item_array_t* items;
- gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
- for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
- it != categories->end();
- ++it)
+ mFetchQueue.pop_front();
+ if (!itemp)
{
- mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(),info.mRecursive));
+ continue;
}
- // We received a response in less than the fast time.
- if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() < fast_fetch_time)
+ if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches)
{
- // Shrink timeouts based on success.
- mMinTimeBetweenFetches = llmax(mMinTimeBetweenFetches * 0.8f, 0.3f);
- mMaxTimeBetweenFetches = llmax(mMaxTimeBetweenFetches * 0.8f, 10.f);
- lldebugs << "Inventory fetch times shrunk to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << llendl;
+ itemp->fetchFromServer();
+ mFetchTimer.reset();
+ mTimelyFetchPending = TRUE;
}
-
- mTimelyFetchPending = FALSE;
- continue;
- }
- else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches)
- {
- // Received first packet, but our num descendants does not match db's num descendants
- // so try again later.
- mFetchQueue.pop_front();
-
- if (mNumFetchRetries++ < MAX_FETCH_RETRIES)
+ else if (itemp->mIsComplete)
+ {
+ mTimelyFetchPending = FALSE;
+ }
+ else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches)
{
- // push on back of queue
mFetchQueue.push_back(info);
+ mFetchTimer.reset();
+ mTimelyFetchPending = FALSE;
}
- mTimelyFetchPending = FALSE;
- mFetchTimer.reset();
+ // Not enough time has elapsed to do a new fetch
break;
}
-
- // Not enough time has elapsed to do a new fetch
- break;
}
//
@@ -313,15 +352,35 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
}
}
-void LLInventoryModelBackgroundFetch::incrBulkFetch(S16 fetching)
+void LLInventoryModelBackgroundFetch::incrFetchCount(S16 fetching)
{
- mBulkFetchCount += fetching;
- if (mBulkFetchCount < 0)
+ mFetchCount += fetching;
+ if (mFetchCount < 0)
{
- mBulkFetchCount = 0;
+ mFetchCount = 0;
}
}
+class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInventoryResponder
+{
+public:
+ LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {};
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+};
+
+void LLInventoryModelFetchItemResponder::result( const LLSD& content )
+{
+ LLInventoryModel::fetchInventoryResponder::result(content);
+ LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
+}
+
+void LLInventoryModelFetchItemResponder::error( U32 status, const std::string& reason )
+{
+ LLInventoryModel::fetchInventoryResponder::error(status, reason);
+ LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
+}
+
class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
{
@@ -458,7 +517,7 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)
}
}
- fetcher->incrBulkFetch(-1);
+ fetcher->incrFetchCount(-1);
if (fetcher->isBulkFetchProcessingComplete())
{
@@ -477,7 +536,7 @@ void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::str
llinfos << "LLInventoryModelFetchDescendentsResponder::error "
<< status << ": " << reason << llendl;
- fetcher->incrBulkFetch(-1);
+ fetcher->incrFetchCount(-1);
if (status==499) // timed out
{
@@ -508,12 +567,13 @@ BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat
// Bundle up a bunch of requests to send all at once.
// static
-void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)
+void LLInventoryModelBackgroundFetch::bulkFetch()
{
//Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped.
//If there are items in mFetchQueue, we want to check the time since the last bulkFetch was
//sent. If it exceeds our retry time, go ahead and fire off another batch.
- //Stopbackgroundfetch will be run from the Responder instead of here.
+ LLViewerRegion* region = gAgent.getRegion();
+ if (!region) return;
S16 max_concurrent_fetches=8;
F32 new_min_time = 0.5f; //HACK! Clean this up when old code goes away entirely.
@@ -523,12 +583,13 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)
}
if (gDisconnected ||
- (mBulkFetchCount > max_concurrent_fetches) ||
+ (mFetchCount > max_concurrent_fetches) ||
(mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches))
{
return; // just bail if we are disconnected
}
+ U32 item_count=0;
U32 folder_count=0;
U32 max_batch_size=5;
@@ -536,83 +597,159 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)
uuid_vec_t recursive_cats;
- LLSD body;
- LLSD body_lib;
+ LLSD folder_request_body;
+ LLSD folder_request_body_lib;
+ LLSD item_request_body;
+ LLSD item_request_body_lib;
- while (!(mFetchQueue.empty()) && (folder_count < max_batch_size))
+ while (!mFetchQueue.empty()
+ && (item_count + folder_count) < max_batch_size)
{
const FetchQueueInfo& fetch_info = mFetchQueue.front();
- const LLUUID &cat_id = fetch_info.mCatUUID;
- if (cat_id.isNull()) //DEV-17797
- {
- LLSD folder_sd;
- folder_sd["folder_id"] = LLUUID::null.asString();
- folder_sd["owner_id"] = gAgent.getID();
- folder_sd["sort_order"] = (LLSD::Integer)sort_order;
- folder_sd["fetch_folders"] = (LLSD::Boolean)FALSE;
- folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
- body["folders"].append(folder_sd);
- folder_count++;
- }
- else
- {
- const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
+ if (fetch_info.mIsCategory)
+ {
+ const LLUUID &cat_id = fetch_info.mUUID;
+ if (cat_id.isNull()) //DEV-17797
+ {
+ LLSD folder_sd;
+ folder_sd["folder_id"] = LLUUID::null.asString();
+ folder_sd["owner_id"] = gAgent.getID();
+ folder_sd["sort_order"] = (LLSD::Integer)sort_order;
+ folder_sd["fetch_folders"] = (LLSD::Boolean)FALSE;
+ folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
+ folder_request_body["folders"].append(folder_sd);
+ folder_count++;
+ }
+ else
+ {
+ const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
- if (cat)
- {
- if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
- {
- LLSD folder_sd;
- folder_sd["folder_id"] = cat->getUUID();
- folder_sd["owner_id"] = cat->getOwnerID();
- folder_sd["sort_order"] = (LLSD::Integer)sort_order;
- folder_sd["fetch_folders"] = TRUE; //(LLSD::Boolean)sFullFetchStarted;
- folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
-
- if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
- body_lib["folders"].append(folder_sd);
- else
- body["folders"].append(folder_sd);
- folder_count++;
- }
- // May already have this folder, but append child folders to list.
- if (fetch_info.mRecursive)
- {
- LLInventoryModel::cat_array_t* categories;
- LLInventoryModel::item_array_t* items;
- gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
- for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
- it != categories->end();
- ++it)
+ if (cat)
+ {
+ if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
{
- mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive));
- }
- }
- }
- }
- if (fetch_info.mRecursive)
- recursive_cats.push_back(cat_id);
+ LLSD folder_sd;
+ folder_sd["folder_id"] = cat->getUUID();
+ folder_sd["owner_id"] = cat->getOwnerID();
+ folder_sd["sort_order"] = (LLSD::Integer)sort_order;
+ folder_sd["fetch_folders"] = TRUE; //(LLSD::Boolean)sFullFetchStarted;
+ folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
+
+ if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
+ folder_request_body_lib["folders"].append(folder_sd);
+ else
+ folder_request_body["folders"].append(folder_sd);
+ folder_count++;
+ }
+ // May already have this folder, but append child folders to list.
+ if (fetch_info.mRecursive)
+ {
+ LLInventoryModel::cat_array_t* categories;
+ LLInventoryModel::item_array_t* items;
+ gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
+ for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
+ it != categories->end();
+ ++it)
+ {
+ mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive));
+ }
+ }
+ }
+ }
+ if (fetch_info.mRecursive)
+ recursive_cats.push_back(cat_id);
+ }
+ else
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(fetch_info.mUUID);
+ if (itemp)
+ {
+ LLSD item_sd;
+ item_sd["owner_id"] = itemp->getPermissions().getOwner();
+ item_sd["item_id"] = itemp->getUUID();
+ if (itemp->getPermissions().getOwner() == gAgent.getID())
+ {
+ item_request_body.append(item_sd);
+ }
+ else
+ {
+ item_request_body_lib.append(item_sd);
+ }
+ //itemp->fetchFromServer();
+ item_count++;
+ }
+ }
mFetchQueue.pop_front();
}
- if (folder_count > 0)
+ if (item_count + folder_count > 0)
{
- mBulkFetchCount++;
- if (body["folders"].size())
+ if (folder_count)
{
- LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body, recursive_cats);
- LLHTTPClient::post(url, body, fetcher, 300.0);
+ std::string url = region->getCapability("FetchInventoryDescendents2");
+ mFetchCount++;
+ if (folder_request_body["folders"].size())
+ {
+ LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats);
+ LLHTTPClient::post(url, folder_request_body, fetcher, 300.0);
+ }
+ if (folder_request_body_lib["folders"].size())
+ {
+ std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
+
+ LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats);
+ LLHTTPClient::post(url_lib, folder_request_body_lib, fetcher, 300.0);
+ }
}
- if (body_lib["folders"].size())
+ if (item_count)
{
- std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
-
- LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body_lib, recursive_cats);
- LLHTTPClient::post(url_lib, body_lib, fetcher, 300.0);
+ std::string url;
+
+ if (item_request_body.size())
+ {
+ mFetchCount++;
+ url = region->getCapability("FetchInventory2");
+ if (!url.empty())
+ {
+ LLSD body;
+ body["agent_id"] = gAgent.getID();
+ body["items"] = item_request_body;
+
+ LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body));
+ }
+ //else
+ //{
+ // LLMessageSystem* msg = gMessageSystem;
+ // msg->newMessage("FetchInventory");
+ // msg->nextBlock("AgentData");
+ // msg->addUUID("AgentID", gAgent.getID());
+ // msg->addUUID("SessionID", gAgent.getSessionID());
+ // msg->nextBlock("InventoryData");
+ // msg->addUUID("OwnerID", mPermissions.getOwner());
+ // msg->addUUID("ItemID", mUUID);
+ // gAgent.sendReliableMessage();
+ //}
+ }
+
+ if (item_request_body_lib.size())
+ {
+ mFetchCount++;
+
+ url = region->getCapability("FetchLib2");
+ if (!url.empty())
+ {
+ LLSD body;
+ body["agent_id"] = gAgent.getID();
+ body["items"] = item_request_body_lib;
+
+ LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body));
+ }
+ }
}
mFetchTimer.reset();
}
+
else if (isBulkFetchProcessingComplete())
{
setAllFoldersFetched();
@@ -624,7 +761,7 @@ bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LL
for (fetch_queue_t::const_iterator it = mFetchQueue.begin();
it != mFetchQueue.end(); ++it)
{
- const LLUUID& fetch_id = (*it).mCatUUID;
+ const LLUUID& fetch_id = (*it).mUUID;
if (gInventory.isObjectDescendentOf(fetch_id, cat_id))
return false;
}
diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h
index c35c785ceb..9dfedddd6d 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.h
+++ b/indra/newview/llinventorymodelbackgroundfetch.h
@@ -48,7 +48,7 @@ public:
// This gets triggered when performing a filter-search.
void start(const LLUUID& cat_id = LLUUID::null, BOOL recursive = TRUE);
- BOOL backgroundFetchActive() const;
+ BOOL folderFetchActive() const;
bool isEverythingFetched() const; // completing the fetch once per session should be sufficient
bool libraryFetchStarted() const;
@@ -60,14 +60,13 @@ public:
bool inventoryFetchInProgress() const;
void findLostItems();
+ void incrFetchCount(S16 fetching);
protected:
- void incrBulkFetch(S16 fetching);
bool isBulkFetchProcessingComplete() const;
- void bulkFetch(std::string url);
+ void bulkFetch();
void backgroundFetch();
static void backgroundFetchCB(void*); // background fetch idle function
- void stopBackgroundFetch(); // stop fetch process
void setAllFoldersFetched();
bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const;
@@ -77,7 +76,8 @@ private:
BOOL mAllFoldersFetched;
BOOL mBackgroundFetchActive;
- S16 mBulkFetchCount;
+ bool mFolderFetchActive;
+ S16 mFetchCount;
BOOL mTimelyFetchPending;
S32 mNumFetchRetries;
@@ -87,11 +87,11 @@ private:
struct FetchQueueInfo
{
- FetchQueueInfo(const LLUUID& id, BOOL recursive) :
- mCatUUID(id), mRecursive(recursive)
- {
- }
- LLUUID mCatUUID;
+ FetchQueueInfo(const LLUUID& id, BOOL recursive, bool is_category = true) :
+ mUUID(id), mRecursive(recursive), mIsCategory(is_category)
+ {}
+ LLUUID mUUID;
+ bool mIsCategory;
BOOL mRecursive;
};
typedef std::deque<FetchQueueInfo> fetch_queue_t;
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 382569fa3a..01a8ecfb5d 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -817,7 +817,7 @@ BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask)
if(handled)
{
ECursorType cursor = getWindow()->getCursor();
- if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() && cursor == UI_CURSOR_ARROW)
+ if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() && cursor == UI_CURSOR_ARROW)
{
// replace arrow cursor with arrow and hourglass cursor
getWindow()->setCursor(UI_CURSOR_WORKING);
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 8279163762..7d805f6862 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -160,6 +160,8 @@ public:
void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ LLHandle<LLInventoryPanel> getInventoryPanelHandle() const { return getDerivedHandle<LLInventoryPanel>(); }
+
// Callbacks
void doToSelected(const LLSD& userdata);
void doCreate(const LLSD& userdata);
diff --git a/indra/newview/llmemoryview.cpp b/indra/newview/llmemoryview.cpp
index 7e9c3c84a7..c0a323d6cb 100644
--- a/indra/newview/llmemoryview.cpp
+++ b/indra/newview/llmemoryview.cpp
@@ -220,7 +220,7 @@ void LLMemoryView::draw()
S32 x, y;
S32 margin = 10;
- S32 texth = (S32)LLFontGL::getFontMonospace()->getLineHeight();
+ S32 texth = LLFontGL::getFontMonospace()->getLineHeight();
S32 xleft = margin;
S32 ytop = height - margin;
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index b02bf79a28..bd20210190 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -728,7 +728,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
if (!http_url.empty())
{
ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
- new LLMeshSkinInfoResponder(mesh_id, offset, size));
+ new LLMeshSkinInfoResponder(mesh_id, offset, size));
if(ret)
{
LLMeshRepository::sHTTPRequestCount++;
@@ -805,7 +805,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
if (!http_url.empty())
{
ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
- new LLMeshDecompositionResponder(mesh_id, offset, size));
+ new LLMeshDecompositionResponder(mesh_id, offset, size));
if(ret)
{
LLMeshRepository::sHTTPRequestCount++;
@@ -881,7 +881,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
if (!http_url.empty())
{
ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
- new LLMeshPhysicsShapeResponder(mesh_id, offset, size));
+ new LLMeshPhysicsShapeResponder(mesh_id, offset, size));
if(ret)
{
@@ -1093,17 +1093,19 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
bool LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size)
{
- LLVolume* volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod));
+ LLPointer<LLVolume> volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod));
std::string mesh_string((char*) data, data_size);
std::istringstream stream(mesh_string);
if (volume->unpackVolumeFaces(stream, data_size))
{
- LoadedMesh mesh(volume, mesh_params, lod);
if (volume->getNumFaces() > 0)
{
- LLMutexLock lock(mMutex);
- mLoadedQ.push(mesh);
+ LoadedMesh mesh(volume, mesh_params, lod);
+ {
+ LLMutexLock lock(mMutex);
+ mLoadedQ.push(mesh);
+ }
return true;
}
}
diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h
index 04e1570081..7a70370fe3 100644
--- a/indra/newview/llmutelist.h
+++ b/indra/newview/llmutelist.h
@@ -29,6 +29,7 @@
#include "llstring.h"
#include "lluuid.h"
+#include "llextendedstatus.h"
class LLViewerObject;
class LLMessageSystem;
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index 4512c14b7a..b4224e30e6 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -124,7 +124,7 @@ BOOL LLNearbyChatBar::postBuild()
// virtual
void LLNearbyChatBar::onOpen(const LLSD& key)
{
- enableTranslationCheckbox(LLTranslate::isTranslationConfigured());
+ showTranslationCheckbox(LLTranslate::isTranslationConfigured());
}
bool LLNearbyChatBar::applyRectControl()
@@ -170,9 +170,9 @@ void LLNearbyChatBar::showHistory()
}
}
-void LLNearbyChatBar::enableTranslationCheckbox(BOOL enable)
+void LLNearbyChatBar::showTranslationCheckbox(BOOL show)
{
- getChild<LLUICtrl>("translate_chat_checkbox")->setEnabled(enable);
+ getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(show);
}
void LLNearbyChatBar::draw()
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
index baf12a06ea..8547cf0bce 100644
--- a/indra/newview/llnearbychatbar.h
+++ b/indra/newview/llnearbychatbar.h
@@ -61,7 +61,7 @@ public:
static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate);
void showHistory();
- void enableTranslationCheckbox(BOOL enable);
+ void showTranslationCheckbox(BOOL show);
/*virtual*/void setMinimized(BOOL b);
protected:
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index 15d5d7c162..1bda7640bd 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -74,6 +74,8 @@ const F32 DOT_SCALE = 0.75f;
const F32 MIN_PICK_SCALE = 2.f;
const S32 MOUSE_DRAG_SLOP = 2; // How far the mouse needs to move before we think it's a drag
+const F64 COARSEUPDATE_MAX_Z = 1020.0f;
+
LLNetMap::LLNetMap (const Params & p)
: LLUICtrl (p),
mBackgroundColor (p.bg_color()),
@@ -300,7 +302,8 @@ void LLNetMap::draw()
}
LLVector3 map_center_agent = gAgent.getPosAgentFromGlobal(mObjectImageCenterGlobal);
- map_center_agent -= gAgentCamera.getCameraPositionAgent();
+ LLVector3 camera_position = gAgentCamera.getCameraPositionAgent();
+ map_center_agent -= camera_position;
map_center_agent.mV[VX] *= mScale/region_width;
map_center_agent.mV[VY] *= mScale/region_width;
@@ -321,9 +324,6 @@ void LLNetMap::draw()
gGL.popMatrix();
- LLVector3d pos_global;
- LLVector3 pos_map;
-
// Mouse pointer in local coordinates
S32 local_mouse_x;
S32 local_mouse_y;
@@ -333,90 +333,67 @@ void LLNetMap::draw()
F32 closest_dist_squared = F32_MAX; // value will be overridden in the loop
F32 min_pick_dist_squared = (mDotRadius * MIN_PICK_SCALE) * (mDotRadius * MIN_PICK_SCALE);
+ LLVector3 pos_map;
+ uuid_vec_t avatar_ids;
+ std::vector<LLVector3d> positions;
+ bool unknown_relative_z;
+
+ LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgentCamera.getCameraPositionGlobal());
+
// Draw avatars
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ for (U32 i = 0; i < avatar_ids.size(); i++)
{
- LLViewerRegion* regionp = *iter;
- const LLVector3d& origin_global = regionp->getOriginGlobal();
-
- S32 count = regionp->mMapAvatars.count();
- S32 i;
- LLVector3 pos_local;
- U32 compact_local;
- U8 bits;
- // TODO: it'd be very cool to draw these in sorted order from lowest Z to highest.
- // just be careful to sort the avatar IDs along with the positions. -MG
- for (i = 0; i < count; i++)
- {
- compact_local = regionp->mMapAvatars.get(i);
+ pos_map = globalPosToView(positions[i]);
+ LLUUID uuid = avatar_ids[i];
- bits = compact_local & 0xFF;
- pos_local.mV[VZ] = F32(bits) * 4.f;
- compact_local >>= 8;
+ bool show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL);
- bits = compact_local & 0xFF;
- pos_local.mV[VY] = (F32)bits;
- compact_local >>= 8;
+ LLColor4 color = show_as_friend ? map_avatar_friend_color : map_avatar_color;
- bits = compact_local & 0xFF;
- pos_local.mV[VX] = (F32)bits;
+ unknown_relative_z = positions[i].mdV[VZ] == COARSEUPDATE_MAX_Z &&
+ camera_position.mV[VZ] >= COARSEUPDATE_MAX_Z;
- pos_global.setVec( pos_local );
- pos_global += origin_global;
+ LLWorldMapView::drawAvatar(
+ pos_map.mV[VX], pos_map.mV[VY],
+ color,
+ pos_map.mV[VZ], mDotRadius,
+ unknown_relative_z);
- pos_map = globalPosToView(pos_global);
-
- LLUUID uuid(NULL);
- BOOL show_as_friend = FALSE;
- if( i < regionp->mMapAvatarIDs.count())
+ if(uuid.notNull())
+ {
+ bool selected = false;
+ uuid_vec_t::iterator sel_iter = gmSelected.begin();
+ for (; sel_iter != gmSelected.end(); sel_iter++)
{
- uuid = regionp->mMapAvatarIDs.get(i);
- show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL);
+ if(*sel_iter == uuid)
+ {
+ selected = true;
+ break;
+ }
}
-
- LLColor4 color = show_as_friend ? map_avatar_friend_color : map_avatar_color;
- LLWorldMapView::drawAvatar(
- pos_map.mV[VX], pos_map.mV[VY],
- color,
- pos_map.mV[VZ], mDotRadius);
-
- if(uuid.notNull())
+ if(selected)
{
- bool selected = false;
- uuid_vec_t::iterator sel_iter = gmSelected.begin();
- for (; sel_iter != gmSelected.end(); sel_iter++)
+ if( (pos_map.mV[VX] < 0) ||
+ (pos_map.mV[VY] < 0) ||
+ (pos_map.mV[VX] >= getRect().getWidth()) ||
+ (pos_map.mV[VY] >= getRect().getHeight()) )
{
- if(*sel_iter == uuid)
- {
- selected = true;
- break;
- }
- }
- if(selected)
+ S32 x = llround( pos_map.mV[VX] );
+ S32 y = llround( pos_map.mV[VY] );
+ LLWorldMapView::drawTrackingCircle( getRect(), x, y, color, 1, 10);
+ } else
{
- if( (pos_map.mV[VX] < 0) ||
- (pos_map.mV[VY] < 0) ||
- (pos_map.mV[VX] >= getRect().getWidth()) ||
- (pos_map.mV[VY] >= getRect().getHeight()) )
- {
- S32 x = llround( pos_map.mV[VX] );
- S32 y = llround( pos_map.mV[VY] );
- LLWorldMapView::drawTrackingCircle( getRect(), x, y, color, 1, 10);
- } else
- {
- LLWorldMapView::drawTrackingDot(pos_map.mV[VX],pos_map.mV[VY],color,0.f);
- }
+ LLWorldMapView::drawTrackingDot(pos_map.mV[VX],pos_map.mV[VY],color,0.f);
}
}
+ }
- F32 dist_to_cursor_squared = dist_vec_squared(LLVector2(pos_map.mV[VX], pos_map.mV[VY]),
- LLVector2(local_mouse_x,local_mouse_y));
- if(dist_to_cursor_squared < min_pick_dist_squared && dist_to_cursor_squared < closest_dist_squared)
- {
- closest_dist_squared = dist_to_cursor_squared;
- mClosestAgentToCursor = regionp->mMapAvatarIDs.get(i);
- }
+ F32 dist_to_cursor_squared = dist_vec_squared(LLVector2(pos_map.mV[VX], pos_map.mV[VY]),
+ LLVector2(local_mouse_x,local_mouse_y));
+ if(dist_to_cursor_squared < min_pick_dist_squared && dist_to_cursor_squared < closest_dist_squared)
+ {
+ closest_dist_squared = dist_to_cursor_squared;
+ mClosestAgentToCursor = uuid;
}
}
@@ -440,7 +417,7 @@ void LLNetMap::draw()
}
// Draw dot for self avatar position
- pos_global = gAgent.getPositionGlobal();
+ LLVector3d pos_global = gAgent.getPositionGlobal();
pos_map = globalPosToView(pos_global);
S32 dot_width = llround(mDotRadius * 2.f);
LLUIImagePtr you = LLWorldMapView::sAvatarYouLargeImage;
@@ -514,9 +491,11 @@ void LLNetMap::reshape(S32 width, S32 height, BOOL called_from_parent)
createObjectImage();
}
-LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos )
+LLVector3 LLNetMap::globalPosToView(const LLVector3d& global_pos)
{
- LLVector3d relative_pos_global = global_pos - gAgentCamera.getCameraPositionGlobal();
+ LLVector3d camera_position = gAgentCamera.getCameraPositionGlobal();
+
+ LLVector3d relative_pos_global = global_pos - camera_position;
LLVector3 pos_local;
pos_local.setVec(relative_pos_global); // convert to floats from doubles
@@ -541,7 +520,7 @@ LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos )
void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color,
BOOL draw_arrow )
{
- LLVector3 pos_local = globalPosToView( pos_global );
+ LLVector3 pos_local = globalPosToView(pos_global);
if( (pos_local.mV[VX] < 0) ||
(pos_local.mV[VY] < 0) ||
(pos_local.mV[VX] >= getRect().getWidth()) ||
diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h
index 20fcee0814..1f7e7d68c6 100644
--- a/indra/newview/llnetmap.h
+++ b/indra/newview/llnetmap.h
@@ -33,9 +33,9 @@
#include "v3dmath.h"
#include "v4color.h"
#include "llpointer.h"
+#include "llcoord.h"
class LLColor4U;
-class LLCoordGL;
class LLImageRaw;
class LLViewerTexture;
class LLFloaterMap;
diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp
index 6105eff8ea..f792f53ac5 100644
--- a/indra/newview/llnotificationmanager.cpp
+++ b/indra/newview/llnotificationmanager.cpp
@@ -35,6 +35,7 @@
#include "llnotifications.h"
#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
using namespace LLNotificationsUI;
@@ -48,6 +49,10 @@ LLNotificationManager::LLNotificationManager()
//--------------------------------------------------------------------------
LLNotificationManager::~LLNotificationManager()
{
+ BOOST_FOREACH(listener_pair_t& pair, mChannelListeners)
+ {
+ pair.second.disconnect();
+ }
}
//--------------------------------------------------------------------------
@@ -64,16 +69,16 @@ void LLNotificationManager::init()
LLNotificationChannel::buildChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser"));
LLNotificationChannel::buildChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox"));
- LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
- LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
- LLNotifications::instance().getChannel("Group Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
- LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
- LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
- LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
- LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
- LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1));
- LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1));
- LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1));
+ mChannelListeners["Notifications"] = LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+ mChannelListeners["NotificationTips"] = LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+ mChannelListeners["Group Notifications"] = LLNotifications::instance().getChannel("Group Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+ mChannelListeners["Alerts"] = LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+ mChannelListeners["AlertModal"] = LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+ mChannelListeners["IM Notifications"] = LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+ mChannelListeners["Offer"] = LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1));
+ mChannelListeners["Hints"] = LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1));
+ mChannelListeners["Browser"] = LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1));
+ mChannelListeners["Outbox"] = LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1));
mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD()));
mNotifyHandlers["notifytip"] = boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD()));
@@ -92,6 +97,9 @@ bool LLNotificationManager::onNotification(const LLSD& notify)
{
LLSysHandler* handle = NULL;
+ if (LLNotifications::destroyed())
+ return false;
+
LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
if (!notification)
diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h
index 16e82e4cce..27b6ba1c71 100644
--- a/indra/newview/llnotificationmanager.h
+++ b/indra/newview/llnotificationmanager.h
@@ -28,6 +28,8 @@
#ifndef LL_LLNOTIFICATIONMANAGER_H
#define LL_LLNOTIFICATIONMANAGER_H
+#include "llevents.h"
+
#include "lluictrl.h"
#include "llnotificationhandler.h"
@@ -47,6 +49,7 @@ class LLToast;
class LLNotificationManager : public LLSingleton<LLNotificationManager>
{
typedef std::pair<std::string, LLEventHandler*> eventhandlers;
+ typedef std::pair<const std::string, LLBoundListener> listener_pair_t;
public:
LLNotificationManager();
virtual ~LLNotificationManager();
@@ -70,6 +73,8 @@ private:
//TODO (*)
std::map<std::string, boost::shared_ptr<LLEventHandler> > mNotifyHandlers;
// cruft std::map<std::string, LLChatHandler*> mChatHandlers;
+
+ std::map<std::string, LLBoundListener> mChannelListeners;
};
}
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index a4f6921f98..7301b305b2 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -875,8 +875,15 @@ void LLPanelFace::getState()
{
getChild<LLUICtrl>("TexScaleU")->setValue(2.0f * getChild<LLUICtrl>("TexScaleU")->getValue().asReal() );
getChild<LLUICtrl>("TexScaleV")->setValue(2.0f * getChild<LLUICtrl>("TexScaleV")->getValue().asReal() );
- }
+ // EXP-1507 (change label based on the mapping mode)
+ getChild<LLUICtrl>("rpt")->setValue(getString("string repeats per meter"));
+ }
+ else
+ if (selected_texgen == 0) // FIXME: should not be magic numbers
+ {
+ getChild<LLUICtrl>("rpt")->setValue(getString("string repeats per face"));
+ }
}
{
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index fbe331c7ab..f825ee3215 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -749,7 +749,10 @@ LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab()
LLPanelGroupMembersSubTab::~LLPanelGroupMembersSubTab()
{
- gSavedSettings.setString("GroupMembersSortOrder", mMembersList->getSortColumnName());
+ if (mMembersList)
+ {
+ gSavedSettings.setString("GroupMembersSortOrder", mMembersList->getSortColumnName());
+ }
}
BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index 0295ad151f..eda0749cdb 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -374,7 +374,7 @@ void LLPanelGroupControlPanel::draw()
{
// Need to resort the participant list if it's in sort by recent speaker order.
if (mParticipantList)
- mParticipantList->updateRecentSpeakersOrder();
+ mParticipantList->update();
LLPanelChatControlPanel::draw();
}
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 058d1ad6bc..76aadcd913 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -216,6 +216,7 @@ void LLPanelLogin::addUsersWithFavoritesToUsername()
void LLPanelLogin::addFavoritesToStartLocation()
{
+ // Clear the combo.
LLComboBox* combo = getChild<LLComboBox>("start_location_combo");
if (!combo) return;
int num_items = combo->getItemCount();
@@ -223,6 +224,10 @@ void LLPanelLogin::addFavoritesToStartLocation()
{
combo->remove(i);
}
+
+ // Load favorites into the combo.
+ std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple();
+ std::string canonical_user_name = canonicalize_username(user_defined_name);
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
LLSD fav_llsd;
llifstream file;
@@ -232,15 +237,18 @@ void LLPanelLogin::addFavoritesToStartLocation()
for (LLSD::map_const_iterator iter = fav_llsd.beginMap();
iter != fav_llsd.endMap(); ++iter)
{
- std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple();
-
// The account name in stored_favorites.xml has Resident last name even if user has
// a single word account name, so it can be compared case-insensitive with the
// user defined "firstname lastname".
- S32 res = LLStringUtil::compareInsensitive(canonicalize_username(user_defined_name), iter->first);
- if (res != 0) continue;
+ S32 res = LLStringUtil::compareInsensitive(canonical_user_name, iter->first);
+ if (res != 0)
+ {
+ lldebugs << "Skipping favorites for " << iter->first << llendl;
+ continue;
+ }
combo->addSeparator();
+ lldebugs << "Loading favorites for " << iter->first << llendl;
LLSD user_llsd = iter->second;
for (LLSD::array_const_iterator iter1 = user_llsd.beginArray();
iter1 != user_llsd.endArray(); ++iter1)
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 374afb90be..c3c62920d3 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -567,7 +567,7 @@ void LLPanelMainInventory::updateItemcountText()
std::string text = "";
- if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive())
+ if (LLInventoryModelBackgroundFetch::instance().folderFetchActive())
{
text = getString("ItemcountFetching", string_args);
}
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 9c46f04abf..f1380e7a36 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -1162,8 +1162,13 @@ void LLPanelPeople::onAddFriendWizButtonClicked()
{
// Show add friend wizard.
LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelPeople::onAvatarPicked, _1, _2), FALSE, TRUE);
+ if (!picker)
+ {
+ return;
+ }
+
// Need to disable 'ok' button when friend occurs in selection
- if (picker) picker->setOkBtnEnableCb(boost::bind(&LLPanelPeople::isItemsFreeOfFriends, this, _1));
+ picker->setOkBtnEnableCb(boost::bind(&LLPanelPeople::isItemsFreeOfFriends, this, _1));
LLFloater* root_floater = gFloaterView->getParentFloater(this);
if (root_floater)
{
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 39c0628cbe..76d38f067d 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -818,7 +818,7 @@ bool LLPanelPrimMediaControls::isMouseOver()
LLCoordGL cursor_pos_gl;
S32 x, y;
getWindow()->getCursorPosition(&cursor_pos_window);
- getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
+ cursor_pos_gl = cursor_pos_window.convert();
if(mMediaControlsStack->getVisible())
{
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
index 66956181f2..eeb433e306 100644
--- a/indra/newview/llpanelprimmediacontrols.h
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -30,9 +30,9 @@
#include "llpanel.h"
#include "llviewermedia.h"
#include "llnotificationptr.h"
+#include "llcoord.h"
class LLButton;
-class LLCoordWindow;
class LLIconCtrl;
class LLLayoutStack;
class LLProgressBar;
diff --git a/indra/newview/llpanelvoiceeffect.cpp b/indra/newview/llpanelvoiceeffect.cpp
index 4bbfec8ab7..5fec6d967d 100644
--- a/indra/newview/llpanelvoiceeffect.cpp
+++ b/indra/newview/llpanelvoiceeffect.cpp
@@ -123,7 +123,6 @@ void LLPanelVoiceEffect::update(bool list_updated)
if (mVoiceEffectCombo)
{
LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface();
- llassert(effect_interface);
if (!effect_interface) return;
if (list_updated)
{
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 5c95e805ce..975a6c67d8 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -390,7 +390,10 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)
{
const LLPointer<LLSpeaker>& speakerp = *it;
- update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice);
+ if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
+ {
+ update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice);
+ }
}
}
}
@@ -466,12 +469,12 @@ void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t c
mValidateSpeakerCallback = cb;
}
-void LLParticipantList::updateRecentSpeakersOrder()
+void LLParticipantList::update()
{
+ mSpeakerMgr->update(true);
+
if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder() && !isHovered())
{
- // Need to update speakers to sort list correctly
- mSpeakerMgr->update(true);
// Resort avatar list
sort();
}
@@ -760,6 +763,7 @@ void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata,
LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(speaker_id);
if (speakerp.isNull())
{
+ LL_WARNS("Speakers") << "Speaker " << speaker_id << " not found" << llendl;
return;
}
LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(mParent.mAvatarList->getItemByValue(speaker_id));
diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h
index a001d29b67..53966c15fe 100644
--- a/indra/newview/llparticipantlist.h
+++ b/indra/newview/llparticipantlist.h
@@ -72,9 +72,9 @@ public:
const EParticipantSortOrder getSortOrder() const;
/**
- * Refreshes the participant list if it's in sort by recent speaker order.
+ * Refreshes the participant list.
*/
- void updateRecentSpeakersOrder();
+ void update();
/**
* Set a callback to be called before adding a speaker. Invalid speakers will not be added.
diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp
index 225ac6e224..fe4cc0f55f 100644
--- a/indra/newview/llplacesinventorybridge.cpp
+++ b/indra/newview/llplacesinventorybridge.cpp
@@ -89,7 +89,7 @@ void LLPlacesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
std::vector<std::string> items;
std::vector<std::string> disabled_items;
- LLInventoryPanel* inv_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLInventoryPanel* inv_panel = mInventoryPanel.get();
bool is_open = false;
if (inv_panel)
{
@@ -137,7 +137,7 @@ void LLPlacesFolderBridge::performAction(LLInventoryModel* model, std::string ac
LLFolderViewFolder* LLPlacesFolderBridge::getFolder()
{
LLFolderViewFolder* folder = NULL;
- LLInventoryPanel* inv_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLInventoryPanel* inv_panel = mInventoryPanel.get();
if (inv_panel)
{
folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID));
diff --git a/indra/newview/llpopupview.cpp b/indra/newview/llpopupview.cpp
index 9fbb67a63a..08829c1184 100644
--- a/indra/newview/llpopupview.cpp
+++ b/indra/newview/llpopupview.cpp
@@ -83,7 +83,7 @@ void LLPopupView::draw()
LLUI::pushMatrix();
{
- LLUI::translate( (F32) screen_x, (F32) screen_y, 0.f);
+ LLUI::translate( (F32) screen_x, (F32) screen_y);
popup->draw();
}
LLUI::popMatrix();
diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h
index 896e17c3c3..759430c3a5 100644
--- a/indra/newview/llpreview.h
+++ b/indra/newview/llpreview.h
@@ -32,6 +32,7 @@
#include "llpointer.h"
#include "lluuid.h"
#include "llinventoryobserver.h"
+#include "llextendedstatus.h"
#include <map>
class LLInventoryItem;
diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp
index 8e8b530e13..35ac0537a3 100644
--- a/indra/newview/llpreviewanim.cpp
+++ b/indra/newview/llpreviewanim.cpp
@@ -43,19 +43,7 @@ extern LLAgent gAgent;
LLPreviewAnim::LLPreviewAnim(const LLSD& key)
: LLPreview( key )
{
-}
-
-// static
-void LLPreviewAnim::endAnimCallback( void *userdata )
-{
- LLHandle<LLFloater>* handlep = ((LLHandle<LLFloater>*)userdata);
- LLFloater* self = handlep->get();
- delete handlep; // done with the handle
- if (self)
- {
- self->getChild<LLUICtrl>("Anim play btn")->setValue(FALSE);
- self->getChild<LLUICtrl>("Anim audition btn")->setValue(FALSE);
- }
+ mCommitCallbackRegistrar.add("PreviewAnim.Play", boost::bind(&LLPreviewAnim::play, this, _2));
}
// virtual
@@ -68,106 +56,115 @@ BOOL LLPreviewAnim::postBuild()
getChild<LLUICtrl>("desc")->setValue(item->getDescription());
}
- childSetAction("Anim play btn",playAnim, this);
- childSetAction("Anim audition btn",auditionAnim, this);
-
childSetCommitCallback("desc", LLPreview::onText, this);
getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
-
+
return LLPreview::postBuild();
}
-void LLPreviewAnim::activate(e_activation_type type)
+// static
+// llinventorybridge also calls into here
+void LLPreviewAnim::play(const LLSD& param)
{
- switch ( type )
+ const LLInventoryItem *item = getItem();
+
+ if(item)
{
- case PLAY:
+ LLUUID itemID=item->getAssetUUID();
+
+ std::string btn_name = param.asString();
+ LLButton* btn_inuse;
+ LLButton* btn_other;
+
+ if ("Inworld" == btn_name)
{
- playAnim( (void *) this );
- break;
+ btn_inuse = getChild<LLButton>("Inworld");
+ btn_other = getChild<LLButton>("Locally");
}
- case AUDITION:
+ else if ("Locally" == btn_name)
{
- auditionAnim( (void *) this );
- break;
+ btn_inuse = getChild<LLButton>("Locally");
+ btn_other = getChild<LLButton>("Inworld");
}
- default:
+ else
{
- //do nothing
+ return;
}
- }
-}
-
-// static
-void LLPreviewAnim::playAnim( void *userdata )
-{
- LLPreviewAnim* self = (LLPreviewAnim*) userdata;
- const LLInventoryItem *item = self->getItem();
- if(item)
- {
- LLUUID itemID=item->getAssetUUID();
+ if (btn_inuse)
+ {
+ btn_inuse->toggleState();
+ }
- LLButton* btn = self->getChild<LLButton>("Anim play btn");
- if (btn)
+ if (btn_other)
{
- btn->toggleState();
+ btn_other->setEnabled(false);
}
- if (self->getChild<LLUICtrl>("Anim play btn")->getValue().asBoolean() )
+ if (getChild<LLUICtrl>(btn_name)->getValue().asBoolean() )
{
- self->mPauseRequest = NULL;
- gAgent.sendAnimationRequest(itemID, ANIM_REQUEST_START);
+ if("Inworld" == btn_name)
+ {
+ gAgent.sendAnimationRequest(itemID, ANIM_REQUEST_START);
+ }
+ else
+ {
+ gAgentAvatarp->startMotion(item->getAssetUUID());
+ }
+
LLMotion* motion = gAgentAvatarp->findMotion(itemID);
if (motion)
{
- motion->setDeactivateCallback(&endAnimCallback, (void *)(new LLHandle<LLFloater>(self->getHandle())));
+ mItemID = itemID;
+ mDidStart = false;
}
}
else
{
gAgentAvatarp->stopMotion(itemID);
gAgent.sendAnimationRequest(itemID, ANIM_REQUEST_STOP);
+
+ if (btn_other)
+ {
+ btn_other->setEnabled(true);
+ }
}
}
}
-// static
-void LLPreviewAnim::auditionAnim( void *userdata )
+// virtual
+void LLPreviewAnim::draw()
{
- LLPreviewAnim* self = (LLPreviewAnim*) userdata;
- const LLInventoryItem *item = self->getItem();
-
- if(item)
+ LLPreview::draw();
+ if (!this->mItemID.isNull())
{
- LLUUID itemID=item->getAssetUUID();
-
- LLButton* btn = self->getChild<LLButton>("Anim audition btn");
- if (btn)
- {
- btn->toggleState();
- }
-
- if (self->getChild<LLUICtrl>("Anim audition btn")->getValue().asBoolean() )
+ LLMotion* motion = gAgentAvatarp->findMotion(this->mItemID);
+ if (motion)
{
- self->mPauseRequest = NULL;
- gAgentAvatarp->startMotion(item->getAssetUUID());
- LLMotion* motion = gAgentAvatarp->findMotion(itemID);
-
- if (motion)
+ if (motion->isStopped() && this->mDidStart)
{
- motion->setDeactivateCallback(&endAnimCallback, (void *)(new LLHandle<LLFloater>(self->getHandle())));
+ cleanup();
+ }
+ if(gAgentAvatarp->isMotionActive(this->mItemID) && !this->mDidStart)
+ {
+ this->mDidStart = true;
}
- }
- else
- {
- gAgentAvatarp->stopMotion(itemID);
- gAgent.sendAnimationRequest(itemID, ANIM_REQUEST_STOP);
}
}
}
// virtual
+void LLPreviewAnim::cleanup()
+{
+ this->mItemID = LLUUID::null;
+ this->mDidStart = false;
+ getChild<LLUICtrl>("Inworld")->setValue(FALSE);
+ getChild<LLUICtrl>("Locally")->setValue(FALSE);
+ getChild<LLUICtrl>("Inworld")->setEnabled(true);
+ getChild<LLUICtrl>("Locally")->setEnabled(true);
+}
+
+// virtual
void LLPreviewAnim::onClose(bool app_quitting)
{
const LLInventoryItem *item = getItem();
@@ -176,12 +173,5 @@ void LLPreviewAnim::onClose(bool app_quitting)
{
gAgentAvatarp->stopMotion(item->getAssetUUID());
gAgent.sendAnimationRequest(item->getAssetUUID(), ANIM_REQUEST_STOP);
- LLMotion* motion = gAgentAvatarp->findMotion(item->getAssetUUID());
-
- if (motion)
- {
- // *TODO: minor memory leak here, user data is never deleted (Use real callbacks)
- motion->setDeactivateCallback(NULL, (void *)NULL);
- }
}
}
diff --git a/indra/newview/llpreviewanim.h b/indra/newview/llpreviewanim.h
index 32e07ee33a..8eaed6ca1f 100644
--- a/indra/newview/llpreviewanim.h
+++ b/indra/newview/llpreviewanim.h
@@ -33,24 +33,18 @@
class LLPreviewAnim : public LLPreview
{
public:
- enum e_activation_type { NONE = 0, PLAY = 1, AUDITION = 2 };
- LLPreviewAnim(const LLSD& key);
- static void playAnim( void* userdata );
- static void auditionAnim( void* userdata );
- static void endAnimCallback( void *userdata );
+ LLPreviewAnim(const LLSD& key);
/*virtual*/ BOOL postBuild();
/*virtual*/ void onClose(bool app_quitting);
- void activate(e_activation_type type);
+ void draw();
+ void cleanup();
+ void play(const LLSD& param);
protected:
- LLAnimPauseRequest mPauseRequest;
- LLUUID mItemID;
- std::string mTitle;
- LLUUID mObjectID;
- LLButton* mPlayBtn;
- LLButton* mAuditionBtn;
+ LLUUID mItemID;
+ bool mDidStart;
};
-#endif // LL_LLPREVIEWSOUND_H
+#endif // LL_LLPREVIEWANIM_H
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 5301955964..d340b304ca 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -195,17 +195,18 @@ LLScreenChannel::~LLScreenChannel()
}
-std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher)
+std::list<const LLToast*> LLScreenChannel::findToasts(const Matcher& matcher)
{
- std::list<LLToast*> res;
+ std::list<const LLToast*> res;
// collect stored toasts
for (std::vector<ToastElem>::iterator it = mStoredToastList.begin(); it
!= mStoredToastList.end(); it++)
{
- if (matcher.matches(it->toast->getNotification()))
+ const LLToast* toast = it->getToast();
+ if (toast && matcher.matches(toast->getNotification()))
{
- res.push_back(it->toast);
+ res.push_back(toast);
}
}
@@ -213,9 +214,10 @@ std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher)
for (std::vector<ToastElem>::iterator it = mToastList.begin(); it
!= mToastList.end(); it++)
{
- if (matcher.matches(it->toast->getNotification()))
+ const LLToast* toast = it->getToast();
+ if (toast && matcher.matches(toast->getNotification()))
{
- res.push_back(it->toast);
+ res.push_back(toast);
}
}
@@ -260,15 +262,16 @@ void LLScreenChannel::addToast(const LLToast::Params& p)
return;
}
- ToastElem new_toast_elem(p);
+ LLToast* toast = new LLToast(p);
+ ToastElem new_toast_elem(toast->getHandle());
- new_toast_elem.toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1));
- new_toast_elem.toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1));
+ toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1));
+ toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1));
if(mControlHovering)
{
- new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2));
- new_toast_elem.toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopToastTimer, this, new_toast_elem.toast));
- new_toast_elem.toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startToastTimer, this, new_toast_elem.toast));
+ toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2));
+ toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopToastTimer, this, toast));
+ toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startToastTimer, this, toast));
}
if(show_toast)
@@ -340,13 +343,13 @@ void LLScreenChannel::onToastFade(LLToast* toast)
//--------------------------------------------------------------------------
void LLScreenChannel::deleteToast(LLToast* toast)
{
- if (toast->isDead())
+ if (!toast || toast->isDead())
{
return;
}
// send signal to observers about destroying of a toast
- toast->mOnDeleteToastSignal(toast);
+ toast->closeToast();
// update channel's Hovering state
// turning hovering off manually because onMouseLeave won't happen if a toast was closed using a keyboard
@@ -354,9 +357,6 @@ void LLScreenChannel::deleteToast(LLToast* toast)
{
mHoveredToast = NULL;
}
-
- // close the toast
- toast->closeFloater();
}
//--------------------------------------------------------------------------
@@ -364,12 +364,16 @@ void LLScreenChannel::deleteToast(LLToast* toast)
void LLScreenChannel::storeToast(ToastElem& toast_elem)
{
// do not store clones
- std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), toast_elem.id);
+ std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), toast_elem.getID());
if( it != mStoredToastList.end() )
return;
- mStoredToastList.push_back(toast_elem);
- mOnStoreToast(toast_elem.toast->getPanel(), toast_elem.id);
+ const LLToast* toast = toast_elem.getToast();
+ if (toast)
+ {
+ mStoredToastList.push_back(toast_elem);
+ mOnStoreToast(toast->getPanel(), toast->getNotificationID());
+ }
}
//--------------------------------------------------------------------------
@@ -382,9 +386,13 @@ void LLScreenChannel::loadStoredToastsToChannel()
for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it)
{
- (*it).toast->setIsHidden(false);
- (*it).toast->startTimer();
- mToastList.push_back((*it));
+ LLToast* toast = it->getToast();
+ if (toast)
+ {
+ toast->setIsHidden(false);
+ toast->startTimer();
+ mToastList.push_back(*it);
+ }
}
mStoredToastList.clear();
@@ -399,17 +407,19 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)
if( it == mStoredToastList.end() )
return;
- LLToast* toast = (*it).toast;
-
- if(toast->getVisible())
+ LLToast* toast = it->getToast();
+ if (toast)
{
- // toast is already in channel
- return;
- }
+ if(toast->getVisible())
+ {
+ // toast is already in channel
+ return;
+ }
- toast->setIsHidden(false);
- toast->startTimer();
- mToastList.push_back((*it));
+ toast->setIsHidden(false);
+ toast->startTimer();
+ mToastList.push_back(*it);
+ }
redrawToasts();
}
@@ -423,9 +433,19 @@ void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id)
if( it == mStoredToastList.end() )
return;
- LLToast* toast = (*it).toast;
- mStoredToastList.erase(it);
- mRejectToastSignal(toast->getNotificationID());
+ const LLToast* toast = it->getToast();
+ if (toast)
+ {
+ mRejectToastSignal(toast->getNotificationID());
+ }
+
+ // Call find() once more, because the mStoredToastList could have been changed
+ // in mRejectToastSignal callback and the iterator could have become invalid.
+ it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
+ if (it != mStoredToastList.end())
+ {
+ mStoredToastList.erase(it);
+ }
}
//--------------------------------------------------------------------------
@@ -436,21 +456,22 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id)
if( it != mToastList.end())
{
- LLToast* toast = (*it).toast;
+ LLToast* toast = it->getToast();
// if it is a notification toast and notification is UnResponded - then respond on it
// else - simply destroy a toast
//
// NOTE: if a notification is unresponded this function will be called twice for the same toast.
// At first, the notification will be discarded, at second (it will be caused by discarding),
// the toast will be destroyed.
- if(toast->isNotificationValid())
+ if(toast && toast->isNotificationValid())
{
mRejectToastSignal(toast->getNotificationID());
}
else
{
- mToastList.erase(it);
+
deleteToast(toast);
+ mToastList.erase(it);
redrawToasts();
}
return;
@@ -459,20 +480,31 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id)
// searching among stored toasts
it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
- if( it != mStoredToastList.end() )
+ if (it != mStoredToastList.end())
+ {
+ LLToast* toast = it->getToast();
+ if (toast)
+ {
+ // send signal to a listener to let him perform some action on toast rejecting
+ mRejectToastSignal(toast->getNotificationID());
+ deleteToast(toast);
+ }
+ }
+
+ // Call find() once more, because the mStoredToastList could have been changed
+ // in mRejectToastSignal callback and the iterator could have become invalid.
+ it = find(mStoredToastList.begin(), mStoredToastList.end(), id);
+ if (it != mStoredToastList.end())
{
- LLToast* toast = (*it).toast;
mStoredToastList.erase(it);
- // send signal to a listener to let him perform some action on toast rejecting
- mRejectToastSignal(toast->getNotificationID());
- deleteToast(toast);
}
+
}
void LLScreenChannel::killMatchedToasts(const Matcher& matcher)
{
- std::list<LLToast*> to_delete = findToasts(matcher);
- for (std::list<LLToast*>::iterator it = to_delete.begin(); it
+ std::list<const LLToast*> to_delete = findToasts(matcher);
+ for (std::list<const LLToast*>::iterator it = to_delete.begin(); it
!= to_delete.end(); it++)
{
killToastByNotificationID((*it)-> getNotificationID());
@@ -486,12 +518,15 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)
if( it != mToastList.end() && panel)
{
- LLToast* toast = (*it).toast;
- LLPanel* old_panel = toast->getPanel();
- toast->removeChild(old_panel);
- delete old_panel;
- toast->insertPanel(panel);
- toast->startTimer();
+ LLToast* toast = it->getToast();
+ if (toast)
+ {
+ LLPanel* old_panel = toast->getPanel();
+ toast->removeChild(old_panel);
+ delete old_panel;
+ toast->insertPanel(panel);
+ toast->startTimer();
+ }
redrawToasts();
}
}
@@ -540,16 +575,29 @@ void LLScreenChannel::showToastsBottom()
{
if(it != mToastList.rbegin())
{
- LLToast* toast = (*(it-1)).toast;
+ LLToast* toast = (it-1)->getToast();
+ if (!toast)
+ {
+ llwarns << "Attempt to display a deleted toast." << llendl;
+ return;
+ }
+
bottom = toast->getRect().mTop - toast->getTopPad();
toast_margin = gSavedSettings.getS32("ToastGap");
}
- toast_rect = (*it).toast->getRect();
+ LLToast* toast = it->getToast();
+ if(!toast)
+ {
+ llwarns << "Attempt to display a deleted toast." << llendl;
+ return;
+ }
+
+ toast_rect = toast->getRect();
toast_rect.setOriginAndSize(getRect().mRight - toast_rect.getWidth(),
bottom + toast_margin, toast_rect.getWidth(),
toast_rect.getHeight());
- (*it).toast->setRect(toast_rect);
+ toast->setRect(toast_rect);
if(floater && floater->overlapsScreenChannel())
{
@@ -561,7 +609,7 @@ void LLScreenChannel::showToastsBottom()
{
shift += floater->getDockControl()->getTongueHeight();
}
- (*it).toast->translate(0, shift);
+ toast->translate(0, shift);
}
LLRect channel_rect = getChannelRect();
@@ -572,13 +620,13 @@ void LLScreenChannel::showToastsBottom()
}
}
- bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().mTop;
+ bool stop_showing_toasts = toast->getRect().mTop > getRect().mTop;
if(!stop_showing_toasts)
{
if( it != mToastList.rend()-1)
{
- S32 toast_top = (*it).toast->getRect().mTop + gSavedSettings.getS32("ToastGap");
+ S32 toast_top = toast->getRect().mTop + gSavedSettings.getS32("ToastGap");
stop_showing_toasts = toast_top > getRect().mTop;
}
}
@@ -592,17 +640,17 @@ void LLScreenChannel::showToastsBottom()
if(stop_showing_toasts)
break;
- if( !(*it).toast->getVisible() )
+ if( !toast->getVisible() )
{
// HACK
// EXT-2653: it is necessary to prevent overlapping for secondary showed toasts
- (*it).toast->setVisible(TRUE);
+ toast->setVisible(TRUE);
}
- if(!(*it).toast->hasFocus())
+ if(!toast->hasFocus())
{
// Fixing Z-order of toasts (EXT-4862)
// Next toast will be positioned under this one.
- gFloaterView->sendChildToBack((*it).toast);
+ gFloaterView->sendChildToBack(toast);
}
}
@@ -612,7 +660,11 @@ void LLScreenChannel::showToastsBottom()
mHiddenToastsNum = 0;
for(; it != mToastList.rend(); it++)
{
- (*it).toast->hide();
+ LLToast* toast = it->getToast();
+ if (toast)
+ {
+ toast->hide();
+ }
}
}
}
@@ -620,17 +672,31 @@ void LLScreenChannel::showToastsBottom()
//--------------------------------------------------------------------------
void LLScreenChannel::showToastsCentre()
{
- LLRect toast_rect;
- S32 bottom = (getRect().mTop - getRect().mBottom)/2 + mToastList[0].toast->getRect().getHeight()/2;
+ LLToast* toast = mToastList[0].getToast();
+ if (!toast)
+ {
+ llwarns << "Attempt to display a deleted toast." << llendl;
+ return;
+ }
+
+ LLRect toast_rect;
+ S32 bottom = (getRect().mTop - getRect().mBottom)/2 + toast->getRect().getHeight()/2;
std::vector<ToastElem>::reverse_iterator it;
for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)
{
- toast_rect = (*it).toast->getRect();
+ LLToast* toast = it->getToast();
+ if (!toast)
+ {
+ llwarns << "Attempt to display a deleted toast." << llendl;
+ return;
+ }
+
+ toast_rect = toast->getRect();
toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + gSavedSettings.getS32("ToastGap"), toast_rect.getWidth() ,toast_rect.getHeight());
- (*it).toast->setRect(toast_rect);
+ toast->setRect(toast_rect);
- (*it).toast->setVisible(TRUE);
+ toast->setVisible(TRUE);
}
}
@@ -652,16 +718,29 @@ void LLScreenChannel::showToastsTop()
{
if(it != mToastList.rbegin())
{
- LLToast* toast = (*(it-1)).toast;
+ LLToast* toast = (it-1)->getToast();
+ if (!toast)
+ {
+ llwarns << "Attempt to display a deleted toast." << llendl;
+ return;
+ }
+
top = toast->getRect().mBottom - toast->getTopPad();
toast_margin = gSavedSettings.getS32("ToastGap");
}
- toast_rect = (*it).toast->getRect();
+ LLToast* toast = it->getToast();
+ if (!toast)
+ {
+ llwarns << "Attempt to display a deleted toast." << llendl;
+ return;
+ }
+
+ toast_rect = toast->getRect();
toast_rect.setLeftTopAndSize(channel_rect.mRight - toast_rect.getWidth(),
top, toast_rect.getWidth(),
toast_rect.getHeight());
- (*it).toast->setRect(toast_rect);
+ toast->setRect(toast_rect);
if(floater && floater->overlapsScreenChannel())
{
@@ -673,7 +752,7 @@ void LLScreenChannel::showToastsTop()
{
shift -= floater->getDockControl()->getTongueHeight();
}
- (*it).toast->translate(0, shift);
+ toast->translate(0, shift);
}
LLRect channel_rect = getChannelRect();
@@ -684,13 +763,13 @@ void LLScreenChannel::showToastsTop()
}
}
- bool stop_showing_toasts = (*it).toast->getRect().mBottom < channel_rect.mBottom;
+ bool stop_showing_toasts = toast->getRect().mBottom < channel_rect.mBottom;
if(!stop_showing_toasts)
{
if( it != mToastList.rend()-1)
{
- S32 toast_bottom = (*it).toast->getRect().mBottom - gSavedSettings.getS32("ToastGap");
+ S32 toast_bottom = toast->getRect().mBottom - gSavedSettings.getS32("ToastGap");
stop_showing_toasts = toast_bottom < channel_rect.mBottom;
}
}
@@ -704,29 +783,41 @@ void LLScreenChannel::showToastsTop()
if(stop_showing_toasts)
break;
- if( !(*it).toast->getVisible() )
+ if (!toast->getVisible())
{
// HACK
// EXT-2653: it is necessary to prevent overlapping for secondary showed toasts
- (*it).toast->setVisible(TRUE);
+ toast->setVisible(TRUE);
}
- if(!(*it).toast->hasFocus())
+ if (!toast->hasFocus())
{
// Fixing Z-order of toasts (EXT-4862)
// Next toast will be positioned under this one.
- gFloaterView->sendChildToBack((*it).toast);
+ gFloaterView->sendChildToBack(toast);
}
}
// Dismiss toasts we don't have space for (STORM-391).
+ std::vector<LLToast*> toasts_to_hide;
if(it != mToastList.rend())
{
mHiddenToastsNum = 0;
for(; it != mToastList.rend(); it++)
{
- (*it).toast->hide();
+ LLToast* toast = it->getToast();
+ if (toast)
+ {
+ toasts_to_hide.push_back(toast);
+ }
}
}
+
+ for (std::vector<LLToast*>::iterator it = toasts_to_hide.begin(), end_it = toasts_to_hide.end();
+ it != end_it;
+ ++it)
+ {
+ (*it)->hide();
+ }
}
//--------------------------------------------------------------------------
@@ -827,7 +918,17 @@ void LLNotificationsUI::LLScreenChannel::startToastTimer(LLToast* toast)
void LLScreenChannel::hideToastsFromScreen()
{
for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++)
- (*it).toast->setVisible(FALSE);
+ {
+ LLToast* toast = it->getToast();
+ if (toast)
+ {
+ toast->setVisible(FALSE);
+ }
+ else
+ {
+ llwarns << "Attempt to hide a deleted toast." << llendl;
+ }
+ }
}
//--------------------------------------------------------------------------
@@ -836,8 +937,15 @@ void LLScreenChannel::hideToast(const LLUUID& notification_id)
std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), notification_id);
if(mToastList.end() != it)
{
- ToastElem te = *it;
- te.toast->hide();
+ LLToast* toast = it->getToast();
+ if (toast)
+ {
+ toast->hide();
+ }
+ else
+ {
+ llwarns << "Attempt to hide a deleted toast." << llendl;
+ }
}
}
@@ -845,24 +953,25 @@ void LLScreenChannel::closeHiddenToasts(const Matcher& matcher)
{
// since we can't guarantee that close toast operation doesn't change mToastList
// we collect matched toasts that should be closed into separate list
- std::list<ToastElem> toasts;
+ std::list<LLToast*> toasts;
for (std::vector<ToastElem>::iterator it = mToastList.begin(); it
!= mToastList.end(); it++)
{
- LLToast * toast = it->toast;
+ LLToast* toast = it->getToast();
// add to list valid toast that match to provided matcher criteria
if (toast != NULL && !toast->isDead() && toast->getNotification() != NULL
&& !toast->getVisible() && matcher.matches(toast->getNotification()))
{
- toasts.push_back(*it);
+ toasts.push_back(toast);
}
}
// close collected toasts
- for (std::list<ToastElem>::iterator it = toasts.begin(); it
+ for (std::list<LLToast*>::iterator it = toasts.begin(); it
!= toasts.end(); it++)
{
- it->toast->closeFloater();
+ LLToast* toast = *it;
+ toast->closeFloater();
}
}
@@ -872,7 +981,7 @@ void LLScreenChannel::removeToastsFromChannel()
hideToastsFromScreen();
for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++)
{
- deleteToast((*it).toast);
+ deleteToast(it->getToast());
}
mToastList.clear();
}
@@ -886,9 +995,10 @@ void LLScreenChannel::removeAndStoreAllStorableToasts()
hideToastsFromScreen();
for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();)
{
- if((*it).toast->getCanBeStored())
+ LLToast* toast = it->getToast();
+ if(toast && toast->getCanBeStored())
{
- storeToast(*(it));
+ storeToast(*it);
it = mToastList.erase(it);
}
else
@@ -908,9 +1018,10 @@ void LLScreenChannel::removeToastsBySessionID(LLUUID id)
hideToastsFromScreen();
for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();)
{
- if((*it).toast->getSessionID() == id)
+ LLToast* toast = it->getToast();
+ if(toast && toast->getSessionID() == id)
{
- deleteToast((*it).toast);
+ deleteToast(toast);
it = mToastList.erase(it);
}
else
@@ -968,5 +1079,5 @@ LLToast* LLScreenChannel::getToastByNotificationID(LLUUID id)
if (it == mStoredToastList.end())
return NULL;
- return it->toast;
+ return it->getToast();
}
diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h
index c9f8855fe6..695b6cd44d 100644
--- a/indra/newview/llscreenchannel.h
+++ b/indra/newview/llscreenchannel.h
@@ -163,7 +163,7 @@ public:
virtual bool matches(const LLNotificationPtr) const = 0;
};
- std::list<LLToast*> findToasts(const Matcher& matcher);
+ std::list<const LLToast*> findToasts(const Matcher& matcher);
// Channel's outfit-functions
// update channel's size and position in the World View
@@ -238,31 +238,39 @@ public:
reject_tost_signal_t mRejectToastSignal; boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mRejectToastSignal.connect(cb); }
private:
- struct ToastElem
+ class ToastElem
{
- LLUUID id;
- LLToast* toast;
+ public:
+ ToastElem(const LLHandle<LLToast>& toast) : mToast(toast)
+ {
+ }
- ToastElem(LLToast::Params p) : id(p.notif_id)
+ ToastElem(const ToastElem& toast_elem) : mToast(toast_elem.mToast)
{
- toast = new LLToast(p);
}
- ToastElem(const ToastElem& toast_elem)
+ LLToast* getToast() const
{
- id = toast_elem.id;
- toast = toast_elem.toast;
+ return mToast.get();
+ }
+
+ LLUUID getID() const
+ {
+ return mToast.isDead() ? LLUUID() : mToast.get()->getNotificationID();
}
bool operator == (const LLUUID &id_op) const
{
- return (id == id_op);
+ return (getID() == id_op);
}
bool operator == (LLPanel* panel_op) const
{
- return (toast == panel_op);
+ return (mToast.get() == panel_op);
}
+
+ private:
+ LLHandle<LLToast> mToast;
};
// Channel's handlers
diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
index 8d64c8c04f..30400a4c6a 100644
--- a/indra/newview/llsechandler_basic.cpp
+++ b/indra/newview/llsechandler_basic.cpp
@@ -1360,7 +1360,11 @@ void LLSecAPIBasicHandler::_writeProtectedData()
// (even though this file isn't really secure. Perhaps in the future
// it may be, however.
LLFile::remove(tmp_filename);
- throw LLProtectedDataException("Error writing Protected Data Store");
+
+ // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()
+ // Decided throwing an exception here was overkill until we figure out why this happens
+ //throw LLProtectedDataException("Error writing Protected Data Store");
+ llinfos << "LLProtectedDataException(Error writing Protected Data Store)" << llendl;
}
// move the temporary file to the specified file location.
@@ -1369,7 +1373,11 @@ void LLSecAPIBasicHandler::_writeProtectedData()
(LLFile::rename(tmp_filename, mProtectedDataFilename)))
{
LLFile::remove(tmp_filename);
- throw LLProtectedDataException("Could not overwrite protected data store");
+
+ // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()
+ // Decided throwing an exception here was overkill until we figure out why this happens
+ //throw LLProtectedDataException("Could not overwrite protected data store");
+ llinfos << "LLProtectedDataException(Could not overwrite protected data store)" << llendl;
}
}
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 038b18afbd..c8b67cc9ec 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -217,15 +217,17 @@ BOOL LLSidepanelInventory::postBuild()
{
LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
- // Collapse inbox panel
- inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true);
-
// Set up button states and callbacks
LLButton * inbox_button = getChild<LLButton>(INBOX_BUTTON_NAME);
- inbox_button->setToggleState(false);
inbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleInboxBtn, this));
+ // Get the previous inbox state from "InventoryInboxToggleState" setting.
+ bool is_inbox_collapsed = !inbox_button->getToggleState();
+
+ // Restore the collapsed inbox panel state
+ inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), is_inbox_collapsed);
+
// Set the inbox visible based on debug settings (final setting comes from http request below)
enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox"));
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index c588bd8fb4..07d2f1ad6f 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -272,6 +272,7 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
speakerp->mStatus = status;
mSpeakers.insert(std::make_pair(speakerp->mID, speakerp));
mSpeakersSorted.push_back(speakerp);
+ LL_DEBUGS("Speakers") << "Added speaker " << id << llendl;
fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add");
}
else
@@ -290,6 +291,10 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
speakerp->lookupName();
}
}
+ else
+ {
+ LL_WARNS("Speakers") << "Speaker " << id << " not found" << llendl;
+ }
}
mSpeakerDelayRemover->unsetActionTimer(speakerp->mID);
@@ -354,6 +359,7 @@ void LLSpeakerMgr::update(BOOL resort_ok)
if (moderator_muted_voice != speakerp->mModeratorMutedVoice)
{
speakerp->mModeratorMutedVoice = moderator_muted_voice;
+ LL_DEBUGS("Speakers") << (speakerp->mModeratorMutedVoice? "Muted" : "Umuted") << " speaker " << speaker_id<< llendl;
speakerp->fireEvent(new LLSpeakerVoiceModerationEvent(speakerp));
}
@@ -484,6 +490,7 @@ bool LLSpeakerMgr::removeSpeaker(const LLUUID& speaker_id)
}
}
+ LL_DEBUGS("Speakers") << "Removed speaker " << speaker_id << llendl;
fireEvent(new LLSpeakerListChangeEvent(this, speaker_id), "remove");
update(TRUE);
@@ -595,7 +602,10 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
speaker_it->second["mutes"]["text"];
// Fire event only if moderator changed
if ( is_moderator != speakerp->mIsModerator )
+ {
+ LL_DEBUGS("Speakers") << "Speaker " << agent_id << (is_moderator ? "is now" : "no longer is") << " a moderator" << llendl;
fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator");
+ }
}
}
}
@@ -665,7 +675,10 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
speakerp->mIsModerator = agent_info["is_moderator"];
// Fire event only if moderator changed
if ( is_moderator != speakerp->mIsModerator )
+ {
+ LL_DEBUGS("Speakers") << "Speaker " << agent_id << (is_moderator ? "is now" : "no longer is") << " a moderator" << llendl;
fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator");
+ }
}
if (agent_info.has("mutes"))
@@ -857,6 +870,7 @@ void LLActiveSpeakerMgr::updateSpeakerList()
// always populate from active voice channel
if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel) //MA: seems this is always false
{
+ LL_DEBUGS("Speakers") << "Removed all speakers" << llendl;
fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear");
mSpeakers.clear();
mSpeakersSorted.clear();
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index 35f2ee7056..b9358cf37c 100644
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -208,6 +208,8 @@ private:
class LLSpeakerMgr : public LLOldEvents::LLObservable
{
+ LOG_CLASS(LLSpeakerMgr);
+
public:
LLSpeakerMgr(LLVoiceChannel* channelp);
virtual ~LLSpeakerMgr();
@@ -271,6 +273,8 @@ protected:
class LLIMSpeakerMgr : public LLSpeakerMgr
{
+ LOG_CLASS(LLIMSpeakerMgr);
+
public:
LLIMSpeakerMgr(LLVoiceChannel* channel);
@@ -320,6 +324,8 @@ protected:
class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLActiveSpeakerMgr>
{
+ LOG_CLASS(LLActiveSpeakerMgr);
+
public:
LLActiveSpeakerMgr();
protected:
@@ -328,6 +334,7 @@ protected:
class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeakerMgr>
{
+ LOG_CLASS(LLLocalSpeakerMgr);
public:
LLLocalSpeakerMgr();
~LLLocalSpeakerMgr ();
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 3923b4510a..0ac8c1fe39 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -880,7 +880,6 @@ bool idle_startup()
LLFile::mkdir(gDirUtilp->getLindenUserDir());
// Set PerAccountSettingsFile to the default value.
- std::string per_account_settings_file = LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount");
gSavedSettings.setString("PerAccountSettingsFile",
gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT,
LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount")));
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index de22f2ae6b..19a944e88e 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -922,13 +922,20 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
S32 image_top = getRect().getHeight();
S32 image_bottom = BTN_HEIGHT_SMALL;
S32 image_middle = (image_top + image_bottom) / 2;
- S32 line_height = llround(LLFontGL::getFontSansSerifSmall()->getLineHeight());
+ S32 line_height = LLFontGL::getFontSansSerifSmall()->getLineHeight();
LLTextBox::Params tentative_label_p(p.multiselect_text);
tentative_label_p.name("Multiple");
tentative_label_p.rect(LLRect (0, image_middle + line_height / 2, getRect().getWidth(), image_middle - line_height / 2 ));
tentative_label_p.follows.flags(FOLLOWS_ALL);
mTentativeLabel = LLUICtrlFactory::create<LLTextBox> (tentative_label_p);
+
+ // It is no longer possible to associate a style with a textbox, so it has to be done in this fashion
+ LLStyle::Params style_params;
+ style_params.color = LLColor4::white;
+
+ mTentativeLabel->setText(LLTrans::getString("multiple_textures"), style_params);
+ mTentativeLabel->setHAlign(LLFontGL::HCENTER);
addChild( mTentativeLabel );
LLRect border_rect = getLocalRect();
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 1c89766b26..5b41a05f2a 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -386,7 +386,7 @@ public:
Params()
: texture_view("texture_view")
{
- S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
changeDefault(rect, LLRect(0,0,100,line_height * 4));
}
};
@@ -411,7 +411,7 @@ void LLAvatarTexBar::draw()
LLVOAvatarSelf* avatarp = gAgentAvatarp;
if (!avatarp) return;
- const S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ const S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
const S32 v_offset = 0;
const S32 l_offset = 3;
@@ -485,7 +485,7 @@ public:
Params()
: texture_view("texture_view")
{
- S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
changeDefault(rect, LLRect(0,0,100,line_height * 4));
}
};
@@ -512,7 +512,7 @@ void LLGLTexMemBar::draw()
F32 discard_bias = LLViewerTexture::sDesiredDiscardBias;
F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ;
F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ;
- S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
S32 v_offset = (S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f);
F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024);
F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024);
@@ -1097,7 +1097,7 @@ void LLTextureSizeView::drawTextureSizeGraph()
{
if(mTextureSizeBar.size() == 0)
{
- S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
mTextureSizeBar.resize(LLImageGL::sTextureLoadedCounter.size()) ;
mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ;
@@ -1140,7 +1140,7 @@ F32 LLTextureSizeView::drawTextureSizeDistributionGraph()
}
}
- S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
S32 left = mTextureSizeBarRect.mLeft ;
S32 bottom = mTextureSizeBarRect.mBottom ;
S32 right = mTextureSizeBarRect.mRight ;
@@ -1222,7 +1222,7 @@ void LLTextureSizeView::drawTextureCategoryGraph()
{
if(mTextureSizeBar.size() == 0)
{
- S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
mTextureSizeBar.resize(LLViewerTexture::getTotalNumOfCategories()) ;
mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ;
@@ -1267,7 +1267,7 @@ F32 LLTextureSizeView::drawTextureCategoryDistributionGraph()
}
}
- S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
+ S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
S32 left = mTextureSizeBarRect.mLeft ;
S32 bottom = mTextureSizeBarRect.mBottom ;
S32 right = mTextureSizeBarRect.mRight ;
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
index da691a2d0c..0eec7f0afd 100644
--- a/indra/newview/lltoast.cpp
+++ b/indra/newview/lltoast.cpp
@@ -180,11 +180,14 @@ LLToast::~LLToast()
//--------------------------------------------------------------------------
void LLToast::hide()
{
- setVisible(FALSE);
- setFading(false);
- mTimer->stop();
- mIsHidden = true;
- mOnFadeSignal(this);
+ if (!mIsHidden)
+ {
+ setVisible(FALSE);
+ setFading(false);
+ mTimer->stop();
+ mIsHidden = true;
+ mOnFadeSignal(this);
+ }
}
void LLToast::onFocusLost()
@@ -215,6 +218,13 @@ void LLToast::setFadingTime(S32 seconds)
mToastFadingTime = seconds;
}
+void LLToast::closeToast()
+{
+ mOnDeleteToastSignal(this);
+
+ closeFloater();
+}
+
S32 LLToast::getTopPad()
{
if(mWrapperPanel)
@@ -296,9 +306,7 @@ void LLToast::reshapeToPanel()
if(!panel)
return;
- LLRect panel_rect = panel->getRect();
-
- panel_rect.setLeftTopAndSize(0, panel_rect.getHeight(), panel_rect.getWidth(), panel_rect.getHeight());
+ LLRect panel_rect = panel->getLocalRect();
panel->setShape(panel_rect);
LLRect toast_rect = getRect();
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index 0b06728935..e1d99b1bcb 100644
--- a/indra/newview/lltoast.h
+++ b/indra/newview/lltoast.h
@@ -75,6 +75,7 @@ class LLToast : public LLModalDialog, public LLInstanceTracker<LLToast>
public:
typedef boost::function<void (LLToast* toast)> toast_callback_t;
typedef boost::signals2::signal<void (LLToast* toast)> toast_signal_t;
+ typedef boost::signals2::signal<void (LLToast* toast, bool mouse_enter)> toast_hover_check_signal_t;
struct Params : public LLInitParam::Block<Params>
{
@@ -131,7 +132,7 @@ public:
void reshapeToPanel();
// get toast's panel
- LLPanel* getPanel() { return mPanel; }
+ LLPanel* getPanel() const { return mPanel; }
// enable/disable Toast's Hide button
void setHideButtonEnabled(bool enabled);
//
@@ -155,6 +156,8 @@ public:
void setFadingTime(S32 seconds);
+ void closeToast();
+
/**
* Returns padding between floater top and wrapper_panel top.
* This padding should be taken into account when positioning or reshaping toasts
@@ -167,9 +170,9 @@ public:
// get information whether the notification corresponding to the toast is valid or not
bool isNotificationValid();
// get toast's Notification ID
- const LLUUID getNotificationID() { return mNotificationID;}
+ const LLUUID getNotificationID() const { return mNotificationID;}
// get toast's Session ID
- const LLUUID getSessionID() { return mSessionID;}
+ const LLUUID getSessionID() const { return mSessionID;}
//
void setCanFade(bool can_fade);
//
@@ -179,19 +182,12 @@ public:
// set whether this toast considered as hidden or not
void setIsHidden( bool is_toast_hidden ) { mIsHidden = is_toast_hidden; }
- const LLNotificationPtr& getNotification() { return mNotification;}
+ const LLNotificationPtr& getNotification() const { return mNotification;}
// Registers signals/callbacks for events
- toast_signal_t mOnFadeSignal;
- toast_signal_t mOnDeleteToastSignal;
- toast_signal_t mOnToastDestroyedSignal;
- boost::signals2::connection setOnFadeCallback(toast_callback_t cb) { return mOnFadeSignal.connect(cb); }
- boost::signals2::connection setOnToastDestroyedCallback(toast_callback_t cb) { return mOnToastDestroyedSignal.connect(cb); }
-
- typedef boost::function<void (LLToast* toast, bool mouse_enter)> toast_hover_check_callback_t;
- typedef boost::signals2::signal<void (LLToast* toast, bool mouse_enter)> toast_hover_check_signal_t;
- toast_hover_check_signal_t mOnToastHoverSignal;
- boost::signals2::connection setOnToastHoverCallback(toast_hover_check_callback_t cb) { return mOnToastHoverSignal.connect(cb); }
+ boost::signals2::connection setOnFadeCallback(const toast_signal_t::slot_type& cb) { return mOnFadeSignal.connect(cb); }
+ boost::signals2::connection setOnToastDestroyedCallback(const toast_signal_t::slot_type& cb) { return mOnToastDestroyedSignal.connect(cb); }
+ boost::signals2::connection setOnToastHoverCallback(const toast_hover_check_signal_t::slot_type& cb) { return mOnToastHoverSignal.connect(cb); }
boost::signals2::connection setMouseEnterCallback( const commit_signal_t::slot_type& cb ) { return mToastMouseEnterSignal.connect(cb); };
boost::signals2::connection setMouseLeaveCallback( const commit_signal_t::slot_type& cb ) { return mToastMouseLeaveSignal.connect(cb); };
@@ -237,6 +233,11 @@ private:
bool mIsFading;
bool mIsHovered;
+ toast_signal_t mOnFadeSignal;
+ toast_signal_t mOnDeleteToastSignal;
+ toast_signal_t mOnToastDestroyedSignal;
+ toast_hover_check_signal_t mOnToastHoverSignal;
+
commit_signal_t mToastMouseEnterSignal;
commit_signal_t mToastMouseLeaveSignal;
};
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index 0f337825e9..9ba8431fde 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -69,8 +69,22 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
mLabel(notification->getName()),
mLineEditor(NULL)
{
+ // EXP-1822
+ // save currently focused view, so that return focus to it
+ // on destroying this toast.
+ LLView* current_selection = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus());
+ while(current_selection)
+ {
+ if (current_selection->isFocusRoot())
+ {
+ mPreviouslyFocusedView = current_selection->getHandle();
+ break;
+ }
+ current_selection = current_selection->getParent();
+ }
+
const LLFontGL* font = LLFontGL::getFontSansSerif();
- const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);
+ const S32 LINE_HEIGHT = font->getLineHeight();
const S32 EDITOR_HEIGHT = 20;
LLNotificationFormPtr form = mNotification->getForm();
@@ -365,7 +379,7 @@ bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std::
}
const LLFontGL* font = mCheck->getFont();
- const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f);
+ const S32 LINE_HEIGHT = font->getLineHeight();
// Extend dialog for "check next time"
S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * HPAD;
@@ -408,6 +422,13 @@ LLToastAlertPanel::~LLToastAlertPanel()
{
LLTransientFloaterMgr::instance().removeControlView(
LLTransientFloaterMgr::GLOBAL, this);
+
+ // EXP-1822
+ // return focus to the previously focused view
+ if (mPreviouslyFocusedView.get())
+ {
+ mPreviouslyFocusedView.get()->setFocus(TRUE);
+ }
}
BOOL LLToastAlertPanel::hasTitleBar() const
diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h
index 7b157f19bb..d1be5e018e 100644
--- a/indra/newview/lltoastalertpanel.h
+++ b/indra/newview/lltoastalertpanel.h
@@ -113,6 +113,7 @@ private:
LLFrameTimer mDefaultBtnTimer;
// For Dialogs that take a line as text as input:
LLLineEditor* mLineEditor;
+ LLHandle<LLView> mPreviouslyFocusedView;
};
diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp
index fc69157a40..d2a4ce8745 100644
--- a/indra/newview/lltoastpanel.cpp
+++ b/indra/newview/lltoastpanel.cpp
@@ -68,7 +68,7 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount)
if (message->getVisible())
{
S32 heightDelta = 0;
- S32 maxTextHeight = (S32)(message->getDefaultFont()->getLineHeight() * maxLineCount);
+ S32 maxTextHeight = message->getDefaultFont()->getLineHeight() * maxLineCount;
LLRect messageRect = message->getRect();
S32 oldTextHeight = messageRect.getHeight();
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 8c32dfcb4d..c7ab934f9e 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -333,14 +333,15 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()
};
LLToolDragAndDrop::LLToolDragAndDrop()
-: LLTool(std::string("draganddrop"), NULL),
- mDragStartX(0),
- mDragStartY(0),
- mSource(SOURCE_AGENT),
- mCursor(UI_CURSOR_NO),
- mLastAccept(ACCEPT_NO),
- mDrop(FALSE),
- mCurItemIndex(0)
+: LLTool(std::string("draganddrop"), NULL),
+ mCargoCount(0),
+ mDragStartX(0),
+ mDragStartY(0),
+ mSource(SOURCE_AGENT),
+ mCursor(UI_CURSOR_NO),
+ mLastAccept(ACCEPT_NO),
+ mDrop(FALSE),
+ mCurItemIndex(0)
{
}
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index 188d36cd1b..245c2a23e6 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -86,8 +86,11 @@ public:
EAcceptance getLastAccept() { return mLastAccept; }
boost::signals2::connection setEndDragCallback( const enddrag_signal_t::slot_type& cb ) { return mEndDragSignal.connect(cb); }
-
- uuid_vec_t::size_type getCargoIDsCount() const { return mCargoIDs.size(); }
+
+ void setCargoCount(U32 count) { mCargoCount = count; }
+ void resetCargoCount() { mCargoCount = 0; }
+ U32 getCargoCount() const { return (mCargoCount > 0) ? mCargoCount : mCargoIDs.size(); }
+
static S32 getOperationId() { return sOperationId; }
protected:
@@ -118,6 +121,8 @@ protected:
protected:
+ U32 mCargoCount;
+
S32 mDragStartX;
S32 mDragStartY;
diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp
index 6bc7c6de11..ac01316462 100644
--- a/indra/newview/lltoolmgr.cpp
+++ b/indra/newview/lltoolmgr.cpp
@@ -81,7 +81,7 @@ LLToolMgr::LLToolMgr()
// Not a panel, register these callbacks globally.
LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Active", boost::bind(&LLToolMgr::inEdit, this));
LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Enabled", boost::bind(&LLToolMgr::canEdit, this));
- LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this));
+ LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this, _2));
gToolNull = new LLTool(LLStringUtil::null); // Does nothing
setCurrentTool(gToolNull);
@@ -245,8 +245,15 @@ bool LLToolMgr::canEdit()
return LLViewerParcelMgr::getInstance()->allowAgentBuild();
}
-void LLToolMgr::toggleBuildMode()
+void LLToolMgr::toggleBuildMode(const LLSD& sdname)
{
+ const std::string& param = sdname.asString();
+
+ if (param == "build" && !canEdit())
+ {
+ return;
+ }
+
LLFloaterReg::toggleInstanceOrBringToFront("build");
bool build_visible = LLFloaterReg::instanceVisible("build");
diff --git a/indra/newview/lltoolmgr.h b/indra/newview/lltoolmgr.h
index d489c4c829..12649cfba2 100644
--- a/indra/newview/lltoolmgr.h
+++ b/indra/newview/lltoolmgr.h
@@ -54,7 +54,7 @@ public:
bool inEdit();
bool canEdit();
- void toggleBuildMode();
+ void toggleBuildMode(const LLSD& sdname);
/* Determines if we are in Build mode or not. */
bool inBuildMode();
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index c1cc9c7bc4..f3d8de1904 100755
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -162,10 +162,10 @@ void LLBingTranslationHandler::getTranslateURL(
const std::string &text) const
{
url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=")
- + getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + to_lang;
+ + getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + getAPILanguageCode(to_lang);
if (!from_lang.empty())
{
- url += "&from=" + from_lang;
+ url += "&from=" + getAPILanguageCode(from_lang);
}
}
@@ -236,6 +236,12 @@ std::string LLBingTranslationHandler::getAPIKey()
return gSavedSettings.getString("BingTranslateAPIKey");
}
+// static
+std::string LLBingTranslationHandler::getAPILanguageCode(const std::string& lang)
+{
+ return lang == "zh" ? "zh-CHT" : lang; // treat Chinese as Traditional Chinese
+}
+
LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_lang, const std::string& to_lang)
: mFromLang(from_lang)
, mToLang(to_lang)
diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h
index 424bc14587..c58e1adb8c 100755
--- a/indra/newview/lltranslate.h
+++ b/indra/newview/lltranslate.h
@@ -157,6 +157,7 @@ public:
/*virtual*/ bool isConfigured() const;
private:
static std::string getAPIKey();
+ static std::string getAPILanguageCode(const std::string& lang);
};
/**
diff --git a/indra/newview/lluploaddialog.cpp b/indra/newview/lluploaddialog.cpp
index df7c5be0d6..e59064c074 100644
--- a/indra/newview/lluploaddialog.cpp
+++ b/indra/newview/lluploaddialog.cpp
@@ -115,7 +115,7 @@ void LLUploadDialog::setMessage( const std::string& msg)
token = strtok( NULL, "\n" );
}
- S32 line_height = S32( font->getLineHeight() + 0.99f );
+ S32 line_height = font->getLineHeight();
S32 dialog_width = max_msg_width + 2 * HPAD;
S32 dialog_height = line_height * msg_lines.size() + 2 * VPAD;
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index cc3395115b..184033de42 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -32,8 +32,8 @@
#include "llstat.h"
#include "lltimer.h"
#include "m4math.h"
+#include "llcoord.h"
-class LLCoordGL;
class LLViewerObject;
// This rotation matrix moves the default OpenGL reference frame
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index d7ef038e4e..42309349b0 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1,889 +1,892 @@
-/**
- * @file llviewerdisplay.cpp
- * @brief LLViewerDisplay class implementation
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llviewerdisplay.h"
-
-#include "llgl.h"
-#include "llrender.h"
-#include "llglheaders.h"
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "llviewercontrol.h"
-#include "llcoord.h"
-#include "llcriticaldamp.h"
-#include "lldir.h"
-#include "lldynamictexture.h"
-#include "lldrawpoolalpha.h"
-#include "llfeaturemanager.h"
-//#include "llfirstuse.h"
-#include "llhudmanager.h"
-#include "llimagebmp.h"
-#include "llmemory.h"
-#include "llselectmgr.h"
-#include "llsky.h"
-#include "llstartup.h"
-#include "lltoolfocus.h"
-#include "lltoolmgr.h"
-#include "lltooldraganddrop.h"
-#include "lltoolpie.h"
-#include "lltracker.h"
-#include "lltrans.h"
-#include "llui.h"
-#include "llviewercamera.h"
-#include "llviewerobjectlist.h"
-#include "llviewerparcelmgr.h"
-#include "llviewerwindow.h"
-#include "llvoavatarself.h"
-#include "llvograss.h"
-#include "llworld.h"
-#include "pipeline.h"
-#include "llspatialpartition.h"
-#include "llappviewer.h"
-#include "llstartup.h"
-#include "llviewershadermgr.h"
-#include "llfasttimer.h"
-#include "llfloatertools.h"
-#include "llviewertexturelist.h"
-#include "llfocusmgr.h"
-#include "llcubemap.h"
-#include "llviewerregion.h"
-#include "lldrawpoolwater.h"
-#include "lldrawpoolbump.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
-#include "llpostprocess.h"
-#include "LLPathingLib.h"
-#include "llfloaterpathfindingconsole.h"
-#include "llfloaterreg.h"
-
-extern LLPointer<LLViewerTexture> gStartTexture;
-
-LLPointer<LLViewerTexture> gDisconnectedImagep = NULL;
-
-// used to toggle renderer back on after teleport
-const F32 TELEPORT_RENDER_DELAY = 20.f; // Max time a teleport is allowed to take before we raise the curtain
-const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived.
-const F32 TELEPORT_LOCAL_DELAY = 1.0f; // Delay to prevent teleports after starting an in-sim teleport.
-BOOL gTeleportDisplay = FALSE;
-LLFrameTimer gTeleportDisplayTimer;
-LLFrameTimer gTeleportArrivalTimer;
-const F32 RESTORE_GL_TIME = 5.f; // Wait this long while reloading textures before we raise the curtain
-
-BOOL gForceRenderLandFence = FALSE;
-BOOL gDisplaySwapBuffers = FALSE;
-BOOL gDepthDirty = FALSE;
-BOOL gResizeScreenTexture = FALSE;
-BOOL gWindowResized = FALSE;
-BOOL gSnapshot = FALSE;
-
-U32 gRecentFrameCount = 0; // number of 'recent' frames
-LLFrameTimer gRecentFPSTime;
-LLFrameTimer gRecentMemoryTime;
-
-// Rendering stuff
-void pre_show_depth_buffer();
-void post_show_depth_buffer();
-void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
-void render_hud_attachments();
-void render_ui_3d();
-void render_ui_2d();
-void render_disconnected_background();
-
-void display_startup()
-{
- if ( !gViewerWindow->getActive()
- || !gViewerWindow->getWindow()->getVisible()
- || gViewerWindow->getWindow()->getMinimized() )
- {
- return;
- }
-
- gPipeline.updateGL();
-
- // Update images?
- //gImageList.updateImages(0.01f);
- LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
-
- LLGLSDefault gls_default;
-
- // Required for HTML update in login screen
- static S32 frame_count = 0;
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
-
- if (frame_count++ > 1) // make sure we have rendered a frame first
- {
- LLViewerDynamicTexture::updateAllInstances();
- }
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
-
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- LLGLSUIDefault gls_ui;
- gPipeline.disableLights();
-
- gViewerWindow->setup2DRender();
- gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-
- gGL.color4f(1,1,1,1);
- gViewerWindow->draw();
- gGL.flush();
-
- LLVertexBuffer::unbind();
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
-
- gViewerWindow->getWindow()->swapBuffers();
- glClear(GL_DEPTH_BUFFER_BIT);
-}
-
-void display_update_camera()
-{
- LLMemType mt_uc(LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA);
- // TODO: cut draw distance down if customizing avatar?
- // TODO: cut draw distance on per-parcel basis?
-
- // Cut draw distance in half when customizing avatar,
- // but on the viewer only.
- F32 final_far = gAgentCamera.mDrawDistance;
- if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
- {
- final_far *= 0.5f;
- }
- LLViewerCamera::getInstance()->setFar(final_far);
- gViewerWindow->setup3DRender();
-
- // update all the sky/atmospheric/water settings
- LLWLParamManager::getInstance()->update(LLViewerCamera::getInstance());
- LLWaterParamManager::getInstance()->update(LLViewerCamera::getInstance());
-
- // Update land visibility too
- LLWorld::getInstance()->setLandFarClip(final_far);
-}
-
-// Write some stats to llinfos
-void display_stats()
-{
- F32 fps_log_freq = gSavedSettings.getF32("FPSLogFrequency");
- if (fps_log_freq > 0.f && gRecentFPSTime.getElapsedTimeF32() >= fps_log_freq)
- {
- F32 fps = gRecentFrameCount / fps_log_freq;
- llinfos << llformat("FPS: %.02f", fps) << llendl;
- gRecentFrameCount = 0;
- gRecentFPSTime.reset();
- }
- F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency");
- if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq)
- {
- gMemoryAllocated = LLMemory::getCurrentRSS();
- U32 memory = (U32)(gMemoryAllocated / (1024*1024));
- llinfos << llformat("MEMORY: %d MB", memory) << llendl;
- LLMemory::logMemoryInfo(TRUE) ;
- gRecentMemoryTime.reset();
- }
-}
-
-static LLFastTimer::DeclareTimer FTM_PICK("Picking");
-static LLFastTimer::DeclareTimer FTM_RENDER("Render", true);
-static LLFastTimer::DeclareTimer FTM_UPDATE_SKY("Update Sky");
-static LLFastTimer::DeclareTimer FTM_UPDATE_TEXTURES("Update Textures");
-static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE("Update Images");
-static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_CLASS("Class");
-static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_BUMP("Bump");
-static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_LIST("List");
-static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_DELETE("Delete");
-
-// Paint the display!
-void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
-{
- LLMemType mt_render(LLMemType::MTYPE_RENDER);
- LLFastTimer t(FTM_RENDER);
-
- if (gWindowResized)
- { //skip render on frames where window has been resized
- gGL.flush();
- glClear(GL_COLOR_BUFFER_BIT);
- gViewerWindow->getWindow()->swapBuffers();
- LLPipeline::refreshCachedSettings();
- gPipeline.resizeScreenTexture();
- gResizeScreenTexture = FALSE;
- gWindowResized = FALSE;
- return;
- }
-
- if (LLPipeline::sRenderDeferred)
- { //hack to make sky show up in deferred snapshots
- for_snapshot = FALSE;
- }
-
- if (LLPipeline::sRenderFrameTest)
- {
- send_agent_pause();
- }
-
- gSnapshot = for_snapshot;
-
- LLGLSDefault gls_default;
- LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL);
-
- LLVertexBuffer::unbind();
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
-
- stop_glerror();
-
- gPipeline.disableLights();
-
- stop_glerror();
-
- // Don't draw if the window is hidden or minimized.
- // In fact, must explicitly check the minimized state before drawing.
- // Attempting to draw into a minimized window causes a GL error. JC
- if ( !gViewerWindow->getActive()
- || !gViewerWindow->getWindow()->getVisible()
- || gViewerWindow->getWindow()->getMinimized() )
- {
- // Clean up memory the pools may have allocated
- if (rebuild)
- {
- stop_glerror();
- gPipeline.rebuildPools();
- stop_glerror();
- }
-
- stop_glerror();
- gViewerWindow->returnEmptyPicks();
- stop_glerror();
- return;
- }
-
- gViewerWindow->checkSettings();
-
- {
- LLFastTimer ftm(FTM_PICK);
- LLAppViewer::instance()->pingMainloopTimeout("Display:Pick");
- gViewerWindow->performPick();
- }
-
- LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates");
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
-
- //////////////////////////////////////////////////////////
- //
- // Logic for forcing window updates if we're in drone mode.
- //
-
- // *TODO: Investigate running display() during gHeadlessClient. See if this early exit is needed DK 2011-02-18
- if (gHeadlessClient)
- {
-#if LL_WINDOWS
- static F32 last_update_time = 0.f;
- if ((gFrameTimeSeconds - last_update_time) > 1.f)
- {
- InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE);
- last_update_time = gFrameTimeSeconds;
- }
-#elif LL_DARWIN
- // MBW -- Do something clever here.
-#endif
- // Not actually rendering, don't bother.
- return;
- }
-
-
- //
- // Bail out if we're in the startup state and don't want to try to
- // render the world.
- //
- if (LLStartUp::getStartupState() < STATE_STARTED)
- {
- LLAppViewer::instance()->pingMainloopTimeout("Display:Startup");
- display_startup();
- return;
- }
-
- //LLGLState::verify(FALSE);
-
- /////////////////////////////////////////////////
- //
- // Update GL Texture statistics (used for discard logic?)
- //
-
- LLAppViewer::instance()->pingMainloopTimeout("Display:TextureStats");
- stop_glerror();
-
- LLImageGL::updateStats(gFrameTimeSeconds);
-
- LLVOAvatar::sRenderName = gSavedSettings.getS32("AvatarNameTagMode");
- LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("NameTagShowGroupTitles") && gSavedSettings.getS32("AvatarNameTagMode"));
-
- gPipeline.mBackfaceCull = TRUE;
- gFrameCount++;
- gRecentFrameCount++;
- if (gFocusMgr.getAppHasFocus())
- {
- gForegroundFrameCount++;
- }
-
- //////////////////////////////////////////////////////////
- //
- // Display start screen if we're teleporting, and skip render
- //
-
- if (gTeleportDisplay)
- {
- LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport");
- const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived.
-
- S32 attach_count = 0;
- if (isAgentAvatarValid())
- {
- attach_count = gAgentAvatarp->getAttachmentCount();
- }
- F32 teleport_save_time = TELEPORT_EXPIRY + TELEPORT_EXPIRY_PER_ATTACHMENT * attach_count;
- F32 teleport_elapsed = gTeleportDisplayTimer.getElapsedTimeF32();
- F32 teleport_percent = teleport_elapsed * (100.f / teleport_save_time);
- if( (gAgent.getTeleportState() != LLAgent::TELEPORT_START) && (teleport_percent > 100.f) )
- {
- // Give up. Don't keep the UI locked forever.
- gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
- gAgent.setTeleportMessage(std::string());
- }
-
- const std::string& message = gAgent.getTeleportMessage();
- switch( gAgent.getTeleportState() )
- {
- case LLAgent::TELEPORT_START:
- // Transition to REQUESTED. Viewer has sent some kind
- // of TeleportRequest to the source simulator
- gTeleportDisplayTimer.reset();
- gViewerWindow->setShowProgress(TRUE);
- gViewerWindow->setProgressPercent(0);
- gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED );
- gAgent.setTeleportMessage(
- LLAgent::sTeleportProgressMessages["requesting"]);
- break;
-
- case LLAgent::TELEPORT_REQUESTED:
- // Waiting for source simulator to respond
- gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) );
- gViewerWindow->setProgressString(message);
- break;
-
- case LLAgent::TELEPORT_MOVING:
- // Viewer has received destination location from source simulator
- gViewerWindow->setProgressPercent( llmin(teleport_percent, 75.f) );
- gViewerWindow->setProgressString(message);
- break;
-
- case LLAgent::TELEPORT_START_ARRIVAL:
- // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator
- gTeleportArrivalTimer.reset();
- gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
- gViewerWindow->setProgressPercent(75.f);
- gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING );
- gAgent.setTeleportMessage(
- LLAgent::sTeleportProgressMessages["arriving"]);
- gTextureList.mForceResetTextureStats = TRUE;
- gAgentCamera.resetView(TRUE, TRUE);
- break;
-
- case LLAgent::TELEPORT_ARRIVING:
- // Make the user wait while content "pre-caches"
- {
- F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY);
- if( arrival_fraction > 1.f )
- {
- arrival_fraction = 1.f;
- //LLFirstUse::useTeleport();
- gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
- }
- gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
- gViewerWindow->setProgressPercent( arrival_fraction * 25.f + 75.f);
- gViewerWindow->setProgressString(message);
- }
- break;
-
- case LLAgent::TELEPORT_LOCAL:
- // Short delay when teleporting in the same sim (progress screen active but not shown - did not
- // fall-through from TELEPORT_START)
- {
- if( gTeleportDisplayTimer.getElapsedTimeF32() > TELEPORT_LOCAL_DELAY )
- {
- //LLFirstUse::useTeleport();
- gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
- }
- }
- break;
-
- case LLAgent::TELEPORT_NONE:
- // No teleport in progress
- gViewerWindow->setShowProgress(FALSE);
- gTeleportDisplay = FALSE;
- break;
- }
- }
- else if(LLAppViewer::instance()->logoutRequestSent())
- {
- LLAppViewer::instance()->pingMainloopTimeout("Display:Logout");
- F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f / gLogoutMaxTime;
- if (percent_done > 100.f)
- {
- percent_done = 100.f;
- }
-
- if( LLApp::isExiting() )
- {
- percent_done = 100.f;
- }
-
- gViewerWindow->setProgressPercent( percent_done );
- }
- else
- if (gRestoreGL)
- {
- LLAppViewer::instance()->pingMainloopTimeout("Display:RestoreGL");
- F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME;
- if( percent_done > 100.f )
- {
- gViewerWindow->setShowProgress(FALSE);
- gRestoreGL = FALSE;
- }
- else
- {
-
- if( LLApp::isExiting() )
- {
- percent_done = 100.f;
- }
-
- gViewerWindow->setProgressPercent( percent_done );
- }
- }
-
- //////////////////////////
- //
- // Prepare for the next frame
- //
-
- /////////////////////////////
- //
- // Update the camera
- //
- //
-
- LLAppViewer::instance()->pingMainloopTimeout("Display:Camera");
- LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield);
- LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE);
-
- //////////////////////////
- //
- // clear the next buffer
- // (must follow dynamic texture writing since that uses the frame buffer)
- //
-
- if (gDisconnected)
- {
- LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected");
- render_ui();
- }
-
- //////////////////////////
- //
- // Set rendering options
- //
- //
- LLAppViewer::instance()->pingMainloopTimeout("Display:RenderSetup");
- stop_glerror();
-
- ///////////////////////////////////////
- //
- // Slam lighting parameters back to our defaults.
- // Note that these are not the same as GL defaults...
-
- stop_glerror();
- gGL.setAmbientLightColor(LLColor4::white);
- stop_glerror();
-
- /////////////////////////////////////
- //
- // Render
- //
- // Actually push all of our triangles to the screen.
- //
-
- // do render-to-texture stuff here
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES))
- {
- LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures");
- LLFastTimer t(FTM_UPDATE_TEXTURES);
- if (LLViewerDynamicTexture::updateAllInstances())
- {
- gGL.setColorMask(true, true);
- glClear(GL_DEPTH_BUFFER_BIT);
- }
- }
-
- gViewerWindow->setup3DViewport();
-
- gPipeline.resetFrameStats(); // Reset per-frame statistics.
-
- if (!gDisconnected)
- {
- LLMemType mt_du(LLMemType::MTYPE_DISPLAY_UPDATE);
- LLAppViewer::instance()->pingMainloopTimeout("Display:Update");
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- { //don't draw hud objects in this frame
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
- }
-
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES))
- { //don't draw hud particles in this frame
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
- }
-
- //upkeep gl name pools
- LLGLNamePool::upkeepPools();
-
- stop_glerror();
- display_update_camera();
- stop_glerror();
-
- // *TODO: merge these two methods
- {
- LLMemType mt_uh(LLMemType::MTYPE_DISPLAY_UPDATE_HUD);
- LLHUDManager::getInstance()->updateEffects();
- LLHUDObject::updateAll();
- stop_glerror();
- }
-
- {
- LLMemType mt_ug(LLMemType::MTYPE_DISPLAY_UPDATE_GEOM);
- const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time
- gPipeline.createObjects(max_geom_update_time);
- gPipeline.processPartitionQ();
- gPipeline.updateGeom(max_geom_update_time);
- stop_glerror();
- }
-
- gPipeline.updateGL();
- stop_glerror();
-
- S32 water_clip = 0;
- if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
- (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) ||
- gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER)))
- {
- if (LLViewerCamera::getInstance()->cameraUnderWater())
- {
- water_clip = -1;
- }
- else
- {
- water_clip = 1;
- }
- }
-
- LLAppViewer::instance()->pingMainloopTimeout("Display:Cull");
-
- //Increment drawable frame counter
- LLDrawable::incrementVisible();
-
- LLSpatialGroup::sNoDelete = TRUE;
- LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
-
- /*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred)
- { //force occlusion on for all render types if doing deferred render (tighter shadow frustum)
- LLPipeline::sUseOcclusion = 3;
- }*/
-
- S32 occlusion = LLPipeline::sUseOcclusion;
- if (gDepthDirty)
- { //depth buffer is invalid, don't overwrite occlusion state
- LLPipeline::sUseOcclusion = llmin(occlusion, 1);
- }
- gDepthDirty = FALSE;
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
-
- static LLCullResult result;
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip);
- stop_glerror();
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
-
- BOOL to_texture = gPipeline.canUseVertexShaders() &&
- LLPipeline::sRenderGlow;
-
- LLAppViewer::instance()->pingMainloopTimeout("Display:Swap");
-
- {
- LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SWAP);
-
- if (gResizeScreenTexture)
- {
- gResizeScreenTexture = FALSE;
- gPipeline.resizeScreenTexture();
- }
-
- gGL.setColorMask(true, true);
- glClearColor(0,0,0,0);
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
-
- if (!for_snapshot)
- {
- if (gFrameCount > 1)
- {
- //for some reason, ATI 4800 series will error out if you
- //try to generate a shadow before the first frame is through
- gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
- }
-
- LLVertexBuffer::unbind();
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
-
- glh::matrix4f proj = glh_get_current_projection();
- glh::matrix4f mod = glh_get_current_modelview();
- glViewport(0,0,512,512);
- LLVOAvatar::updateFreezeCounter() ;
-
- if(!LLPipeline::sMemAllocationThrottled)
- {
- LLVOAvatar::updateImpostors();
- }
-
- glh_set_current_projection(proj);
- glh_set_current_modelview(mod);
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.loadMatrix(proj.m);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.loadMatrix(mod.m);
- gViewerWindow->setup3DViewport();
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
-
- }
- glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- }
-
- LLGLState::checkStates();
- LLGLState::checkClientArrays();
-
- //if (!for_snapshot)
- {
- LLMemType mt_gw(LLMemType::MTYPE_DISPLAY_GEN_REFLECTION);
- LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery");
- gPipeline.generateWaterReflection(*LLViewerCamera::getInstance());
- gPipeline.generateHighlight(*LLViewerCamera::getInstance());
- gPipeline.renderPhysicsDisplay();
- }
-
- LLGLState::checkStates();
- LLGLState::checkClientArrays();
-
- //////////////////////////////////////
- //
- // Update images, using the image stats generated during object update/culling
- //
- // Can put objects onto the retextured list.
- //
- // Doing this here gives hardware occlusion queries extra time to complete
- LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages");
-
- {
- LLMemType mt_iu(LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE);
- LLFastTimer t(FTM_IMAGE_UPDATE);
-
- {
- LLFastTimer t(FTM_IMAGE_UPDATE_CLASS);
- LLViewerTexture::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(),
- LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean());
- }
-
-
- {
- LLFastTimer t(FTM_IMAGE_UPDATE_BUMP);
- gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first.
- }
-
- {
- LLFastTimer t(FTM_IMAGE_UPDATE_LIST);
- F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time
- max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame)
- gTextureList.updateImages(max_image_decode_time);
- }
-
- {
- LLFastTimer t(FTM_IMAGE_UPDATE_DELETE);
- //remove dead textures from GL
- LLImageGL::deleteDeadTextures();
- stop_glerror();
- }
- }
-
- LLGLState::checkStates();
- LLGLState::checkClientArrays();
-
- ///////////////////////////////////
- //
- // StateSort
- //
- // Responsible for taking visible objects, and adding them to the appropriate draw orders.
- // In the case of alpha objects, z-sorts them first.
- // Also creates special lists for outlines and selected face rendering.
- //
- LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort");
- {
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- LLMemType mt_ss(LLMemType::MTYPE_DISPLAY_STATE_SORT);
- gPipeline.stateSort(*LLViewerCamera::getInstance(), result);
- stop_glerror();
-
- if (rebuild)
- {
- //////////////////////////////////////
- //
- // rebuildPools
- //
- //
- gPipeline.rebuildPools();
- stop_glerror();
- }
- }
-
- LLGLState::checkStates();
- LLGLState::checkClientArrays();
-
- LLPipeline::sUseOcclusion = occlusion;
-
- {
- LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SKY);
- LLAppViewer::instance()->pingMainloopTimeout("Display:Sky");
- LLFastTimer t(FTM_UPDATE_SKY);
- gSky.updateSky();
- }
-
- if(gUseWireframe)
- {
- glClearColor(0.5f, 0.5f, 0.5f, 0.f);
- glClear(GL_COLOR_BUFFER_BIT);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- }
-
- LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart");
-
- //// render frontmost floater opaque for occlusion culling purposes
- //LLFloater* frontmost_floaterp = gFloaterView->getFrontmost();
- //// assumes frontmost floater with focus is opaque
- //if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp))
- //{
- // gGL.matrixMode(LLRender::MM_MODELVIEW);
- // gGL.pushMatrix();
- // {
- // gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- // glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
- // gGL.loadIdentity();
-
- // LLRect floater_rect = frontmost_floaterp->calcScreenRect();
- // // deflate by one pixel so rounding errors don't occlude outside of floater extents
- // floater_rect.stretch(-1);
- // LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidthScaled(),
- // (F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeightScaled(),
- // (F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidthScaled(),
- // (F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeightScaled());
- // floater_3d_rect.translate(-0.5f, -0.5f);
- // gGL.translatef(0.f, 0.f, -LLViewerCamera::getInstance()->getNear());
- // gGL.scalef(LLViewerCamera::getInstance()->getNear() * LLViewerCamera::getInstance()->getAspect() / sinf(LLViewerCamera::getInstance()->getView()), LLViewerCamera::getInstance()->getNear() / sinf(LLViewerCamera::getInstance()->getView()), 1.f);
- // gGL.color4fv(LLColor4::white.mV);
- // gGL.begin(LLVertexBuffer::QUADS);
- // {
- // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f);
- // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f);
- // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f);
- // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f);
- // }
- // gGL.end();
- // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- // }
- // gGL.popMatrix();
- //}
-
- LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE;
-
- LLGLState::checkStates();
- LLGLState::checkClientArrays();
-
- stop_glerror();
-
-
- if (to_texture)
- {
- gGL.setColorMask(true, true);
-
- if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
- {
- gPipeline.mDeferredScreen.bindTarget();
- glClearColor(1,0,1,1);
- gPipeline.mDeferredScreen.clear();
- }
- else
- {
- gPipeline.mScreen.bindTarget();
- if (LLPipeline::sUnderWaterRender && !gPipeline.canUseWindLightShaders())
- {
- const LLColor4 &col = LLDrawPoolWater::sWaterFogColor;
- glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
- }
- gPipeline.mScreen.clear();
- }
-
- gGL.setColorMask(true, false);
- }
-
+/**
+ * @file llviewerdisplay.cpp
+ * @brief LLViewerDisplay class implementation
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewerdisplay.h"
+
+#include "llgl.h"
+#include "llrender.h"
+#include "llglheaders.h"
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "llviewercontrol.h"
+#include "llcoord.h"
+#include "llcriticaldamp.h"
+#include "lldir.h"
+#include "lldynamictexture.h"
+#include "lldrawpoolalpha.h"
+#include "llfeaturemanager.h"
+//#include "llfirstuse.h"
+#include "llhudmanager.h"
+#include "llimagebmp.h"
+#include "llmemory.h"
+#include "llselectmgr.h"
+#include "llsky.h"
+#include "llstartup.h"
+#include "lltoolfocus.h"
+#include "lltoolmgr.h"
+#include "lltooldraganddrop.h"
+#include "lltoolpie.h"
+#include "lltracker.h"
+#include "lltrans.h"
+#include "llui.h"
+#include "llviewercamera.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerwindow.h"
+#include "llvoavatarself.h"
+#include "llvograss.h"
+#include "llworld.h"
+#include "pipeline.h"
+#include "llspatialpartition.h"
+#include "llappviewer.h"
+#include "llstartup.h"
+#include "llviewershadermgr.h"
+#include "llfasttimer.h"
+#include "llfloatertools.h"
+#include "llviewertexturelist.h"
+#include "llfocusmgr.h"
+#include "llcubemap.h"
+#include "llviewerregion.h"
+#include "lldrawpoolwater.h"
+#include "lldrawpoolbump.h"
+#include "llwlparammanager.h"
+#include "llwaterparammanager.h"
+#include "llpostprocess.h"
+#include "LLPathingLib.h"
+#include "llfloaterpathfindingconsole.h"
+#include "llfloaterreg.h"
+
+extern LLPointer<LLViewerTexture> gStartTexture;
+
+LLPointer<LLViewerTexture> gDisconnectedImagep = NULL;
+
+// used to toggle renderer back on after teleport
+const F32 TELEPORT_RENDER_DELAY = 20.f; // Max time a teleport is allowed to take before we raise the curtain
+const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived.
+const F32 TELEPORT_LOCAL_DELAY = 1.0f; // Delay to prevent teleports after starting an in-sim teleport.
+BOOL gTeleportDisplay = FALSE;
+LLFrameTimer gTeleportDisplayTimer;
+LLFrameTimer gTeleportArrivalTimer;
+const F32 RESTORE_GL_TIME = 5.f; // Wait this long while reloading textures before we raise the curtain
+
+BOOL gForceRenderLandFence = FALSE;
+BOOL gDisplaySwapBuffers = FALSE;
+BOOL gDepthDirty = FALSE;
+BOOL gResizeScreenTexture = FALSE;
+BOOL gWindowResized = FALSE;
+BOOL gSnapshot = FALSE;
+
+U32 gRecentFrameCount = 0; // number of 'recent' frames
+LLFrameTimer gRecentFPSTime;
+LLFrameTimer gRecentMemoryTime;
+
+// Rendering stuff
+void pre_show_depth_buffer();
+void post_show_depth_buffer();
+void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
+void render_hud_attachments();
+void render_ui_3d();
+void render_ui_2d();
+void render_disconnected_background();
+
+void display_startup()
+{
+ if ( !gViewerWindow->getActive()
+ || !gViewerWindow->getWindow()->getVisible()
+ || gViewerWindow->getWindow()->getMinimized() )
+ {
+ return;
+ }
+
+ gPipeline.updateGL();
+
+ // Update images?
+ //gImageList.updateImages(0.01f);
+ LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
+
+ LLGLSDefault gls_default;
+
+ // Required for HTML update in login screen
+ static S32 frame_count = 0;
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+
+ if (frame_count++ > 1) // make sure we have rendered a frame first
+ {
+ LLViewerDynamicTexture::updateAllInstances();
+ }
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ LLGLSUIDefault gls_ui;
+ gPipeline.disableLights();
+
+ gViewerWindow->setup2DRender();
+ gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+ gGL.color4f(1,1,1,1);
+ gViewerWindow->draw();
+ gGL.flush();
+
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+
+ gViewerWindow->getWindow()->swapBuffers();
+ glClear(GL_DEPTH_BUFFER_BIT);
+}
+
+void display_update_camera()
+{
+ LLMemType mt_uc(LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA);
+ // TODO: cut draw distance down if customizing avatar?
+ // TODO: cut draw distance on per-parcel basis?
+
+ // Cut draw distance in half when customizing avatar,
+ // but on the viewer only.
+ F32 final_far = gAgentCamera.mDrawDistance;
+ if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
+ {
+ final_far *= 0.5f;
+ }
+ LLViewerCamera::getInstance()->setFar(final_far);
+ gViewerWindow->setup3DRender();
+
+ // update all the sky/atmospheric/water settings
+ LLWLParamManager::getInstance()->update(LLViewerCamera::getInstance());
+ LLWaterParamManager::getInstance()->update(LLViewerCamera::getInstance());
+
+ // Update land visibility too
+ LLWorld::getInstance()->setLandFarClip(final_far);
+}
+
+// Write some stats to llinfos
+void display_stats()
+{
+ F32 fps_log_freq = gSavedSettings.getF32("FPSLogFrequency");
+ if (fps_log_freq > 0.f && gRecentFPSTime.getElapsedTimeF32() >= fps_log_freq)
+ {
+ F32 fps = gRecentFrameCount / fps_log_freq;
+ llinfos << llformat("FPS: %.02f", fps) << llendl;
+ gRecentFrameCount = 0;
+ gRecentFPSTime.reset();
+ }
+ F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency");
+ if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq)
+ {
+ gMemoryAllocated = LLMemory::getCurrentRSS();
+ U32 memory = (U32)(gMemoryAllocated / (1024*1024));
+ llinfos << llformat("MEMORY: %d MB", memory) << llendl;
+ LLMemory::logMemoryInfo(TRUE) ;
+ gRecentMemoryTime.reset();
+ }
+}
+
+static LLFastTimer::DeclareTimer FTM_PICK("Picking");
+static LLFastTimer::DeclareTimer FTM_RENDER("Render", true);
+static LLFastTimer::DeclareTimer FTM_UPDATE_SKY("Update Sky");
+static LLFastTimer::DeclareTimer FTM_UPDATE_TEXTURES("Update Textures");
+static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE("Update Images");
+static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_CLASS("Class");
+static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_BUMP("Bump");
+static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_LIST("List");
+static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_DELETE("Delete");
+
+// Paint the display!
+void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
+{
+ LLMemType mt_render(LLMemType::MTYPE_RENDER);
+ LLFastTimer t(FTM_RENDER);
+
+ if (gWindowResized)
+ { //skip render on frames where window has been resized
+ gGL.flush();
+ glClear(GL_COLOR_BUFFER_BIT);
+ gViewerWindow->getWindow()->swapBuffers();
+ LLPipeline::refreshCachedSettings();
+ gPipeline.resizeScreenTexture();
+ gResizeScreenTexture = FALSE;
+ gWindowResized = FALSE;
+ return;
+ }
+
+ if (LLPipeline::sRenderDeferred)
+ { //hack to make sky show up in deferred snapshots
+ for_snapshot = FALSE;
+ }
+
+ if (LLPipeline::sRenderFrameTest)
+ {
+ send_agent_pause();
+ }
+
+ gSnapshot = for_snapshot;
+
+ LLGLSDefault gls_default;
+ LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL);
+
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+
+ stop_glerror();
+
+ gPipeline.disableLights();
+
+ //reset vertex buffers if needed
+ gPipeline.doResetVertexBuffers();
+
+ stop_glerror();
+
+ // Don't draw if the window is hidden or minimized.
+ // In fact, must explicitly check the minimized state before drawing.
+ // Attempting to draw into a minimized window causes a GL error. JC
+ if ( !gViewerWindow->getActive()
+ || !gViewerWindow->getWindow()->getVisible()
+ || gViewerWindow->getWindow()->getMinimized() )
+ {
+ // Clean up memory the pools may have allocated
+ if (rebuild)
+ {
+ stop_glerror();
+ gPipeline.rebuildPools();
+ stop_glerror();
+ }
+
+ stop_glerror();
+ gViewerWindow->returnEmptyPicks();
+ stop_glerror();
+ return;
+ }
+
+ gViewerWindow->checkSettings();
+
+ {
+ LLFastTimer ftm(FTM_PICK);
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Pick");
+ gViewerWindow->performPick();
+ }
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates");
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+
+ //////////////////////////////////////////////////////////
+ //
+ // Logic for forcing window updates if we're in drone mode.
+ //
+
+ // *TODO: Investigate running display() during gHeadlessClient. See if this early exit is needed DK 2011-02-18
+ if (gHeadlessClient)
+ {
+#if LL_WINDOWS
+ static F32 last_update_time = 0.f;
+ if ((gFrameTimeSeconds - last_update_time) > 1.f)
+ {
+ InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE);
+ last_update_time = gFrameTimeSeconds;
+ }
+#elif LL_DARWIN
+ // MBW -- Do something clever here.
+#endif
+ // Not actually rendering, don't bother.
+ return;
+ }
+
+
+ //
+ // Bail out if we're in the startup state and don't want to try to
+ // render the world.
+ //
+ if (LLStartUp::getStartupState() < STATE_STARTED)
+ {
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Startup");
+ display_startup();
+ return;
+ }
+
+ //LLGLState::verify(FALSE);
+
+ /////////////////////////////////////////////////
+ //
+ // Update GL Texture statistics (used for discard logic?)
+ //
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:TextureStats");
+ stop_glerror();
+
+ LLImageGL::updateStats(gFrameTimeSeconds);
+
+ LLVOAvatar::sRenderName = gSavedSettings.getS32("AvatarNameTagMode");
+ LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("NameTagShowGroupTitles") && gSavedSettings.getS32("AvatarNameTagMode"));
+
+ gPipeline.mBackfaceCull = TRUE;
+ gFrameCount++;
+ gRecentFrameCount++;
+ if (gFocusMgr.getAppHasFocus())
+ {
+ gForegroundFrameCount++;
+ }
+
+ //////////////////////////////////////////////////////////
+ //
+ // Display start screen if we're teleporting, and skip render
+ //
+
+ if (gTeleportDisplay)
+ {
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport");
+ const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived.
+
+ S32 attach_count = 0;
+ if (isAgentAvatarValid())
+ {
+ attach_count = gAgentAvatarp->getAttachmentCount();
+ }
+ F32 teleport_save_time = TELEPORT_EXPIRY + TELEPORT_EXPIRY_PER_ATTACHMENT * attach_count;
+ F32 teleport_elapsed = gTeleportDisplayTimer.getElapsedTimeF32();
+ F32 teleport_percent = teleport_elapsed * (100.f / teleport_save_time);
+ if( (gAgent.getTeleportState() != LLAgent::TELEPORT_START) && (teleport_percent > 100.f) )
+ {
+ // Give up. Don't keep the UI locked forever.
+ gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
+ gAgent.setTeleportMessage(std::string());
+ }
+
+ const std::string& message = gAgent.getTeleportMessage();
+ switch( gAgent.getTeleportState() )
+ {
+ case LLAgent::TELEPORT_START:
+ // Transition to REQUESTED. Viewer has sent some kind
+ // of TeleportRequest to the source simulator
+ gTeleportDisplayTimer.reset();
+ gViewerWindow->setShowProgress(TRUE);
+ gViewerWindow->setProgressPercent(0);
+ gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED );
+ gAgent.setTeleportMessage(
+ LLAgent::sTeleportProgressMessages["requesting"]);
+ break;
+
+ case LLAgent::TELEPORT_REQUESTED:
+ // Waiting for source simulator to respond
+ gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) );
+ gViewerWindow->setProgressString(message);
+ break;
+
+ case LLAgent::TELEPORT_MOVING:
+ // Viewer has received destination location from source simulator
+ gViewerWindow->setProgressPercent( llmin(teleport_percent, 75.f) );
+ gViewerWindow->setProgressString(message);
+ break;
+
+ case LLAgent::TELEPORT_START_ARRIVAL:
+ // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator
+ gTeleportArrivalTimer.reset();
+ gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
+ gViewerWindow->setProgressPercent(75.f);
+ gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING );
+ gAgent.setTeleportMessage(
+ LLAgent::sTeleportProgressMessages["arriving"]);
+ gTextureList.mForceResetTextureStats = TRUE;
+ gAgentCamera.resetView(TRUE, TRUE);
+ break;
+
+ case LLAgent::TELEPORT_ARRIVING:
+ // Make the user wait while content "pre-caches"
+ {
+ F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY);
+ if( arrival_fraction > 1.f )
+ {
+ arrival_fraction = 1.f;
+ //LLFirstUse::useTeleport();
+ gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
+ }
+ gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
+ gViewerWindow->setProgressPercent( arrival_fraction * 25.f + 75.f);
+ gViewerWindow->setProgressString(message);
+ }
+ break;
+
+ case LLAgent::TELEPORT_LOCAL:
+ // Short delay when teleporting in the same sim (progress screen active but not shown - did not
+ // fall-through from TELEPORT_START)
+ {
+ if( gTeleportDisplayTimer.getElapsedTimeF32() > TELEPORT_LOCAL_DELAY )
+ {
+ //LLFirstUse::useTeleport();
+ gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
+ }
+ }
+ break;
+
+ case LLAgent::TELEPORT_NONE:
+ // No teleport in progress
+ gViewerWindow->setShowProgress(FALSE);
+ gTeleportDisplay = FALSE;
+ break;
+ }
+ }
+ else if(LLAppViewer::instance()->logoutRequestSent())
+ {
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Logout");
+ F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f / gLogoutMaxTime;
+ if (percent_done > 100.f)
+ {
+ percent_done = 100.f;
+ }
+
+ if( LLApp::isExiting() )
+ {
+ percent_done = 100.f;
+ }
+
+ gViewerWindow->setProgressPercent( percent_done );
+ }
+ else
+ if (gRestoreGL)
+ {
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RestoreGL");
+ F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME;
+ if( percent_done > 100.f )
+ {
+ gViewerWindow->setShowProgress(FALSE);
+ gRestoreGL = FALSE;
+ }
+ else
+ {
+
+ if( LLApp::isExiting() )
+ {
+ percent_done = 100.f;
+ }
+
+ gViewerWindow->setProgressPercent( percent_done );
+ }
+ }
+
+ //////////////////////////
+ //
+ // Prepare for the next frame
+ //
+
+ /////////////////////////////
+ //
+ // Update the camera
+ //
+ //
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Camera");
+ LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield);
+ LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE);
+
+ //////////////////////////
+ //
+ // clear the next buffer
+ // (must follow dynamic texture writing since that uses the frame buffer)
+ //
+
+ if (gDisconnected)
+ {
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected");
+ render_ui();
+ }
+
+ //////////////////////////
+ //
+ // Set rendering options
+ //
+ //
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderSetup");
+ stop_glerror();
+
+ ///////////////////////////////////////
+ //
+ // Slam lighting parameters back to our defaults.
+ // Note that these are not the same as GL defaults...
+
+ stop_glerror();
+ gGL.setAmbientLightColor(LLColor4::white);
+ stop_glerror();
+
+ /////////////////////////////////////
+ //
+ // Render
+ //
+ // Actually push all of our triangles to the screen.
+ //
+
+ // do render-to-texture stuff here
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES))
+ {
+ LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures");
+ LLFastTimer t(FTM_UPDATE_TEXTURES);
+ if (LLViewerDynamicTexture::updateAllInstances())
+ {
+ gGL.setColorMask(true, true);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+ }
+
+ gViewerWindow->setup3DViewport();
+
+ gPipeline.resetFrameStats(); // Reset per-frame statistics.
+
+ if (!gDisconnected)
+ {
+ LLMemType mt_du(LLMemType::MTYPE_DISPLAY_UPDATE);
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Update");
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ { //don't draw hud objects in this frame
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ }
+
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES))
+ { //don't draw hud particles in this frame
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
+ }
+
+ //upkeep gl name pools
+ LLGLNamePool::upkeepPools();
+
+ stop_glerror();
+ display_update_camera();
+ stop_glerror();
+
+ // *TODO: merge these two methods
+ {
+ LLMemType mt_uh(LLMemType::MTYPE_DISPLAY_UPDATE_HUD);
+ LLHUDManager::getInstance()->updateEffects();
+ LLHUDObject::updateAll();
+ stop_glerror();
+ }
+
+ {
+ LLMemType mt_ug(LLMemType::MTYPE_DISPLAY_UPDATE_GEOM);
+ const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time
+ gPipeline.createObjects(max_geom_update_time);
+ gPipeline.processPartitionQ();
+ gPipeline.updateGeom(max_geom_update_time);
+ stop_glerror();
+ }
+
+ gPipeline.updateGL();
+ stop_glerror();
+
+ S32 water_clip = 0;
+ if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
+ (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) ||
+ gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER)))
+ {
+ if (LLViewerCamera::getInstance()->cameraUnderWater())
+ {
+ water_clip = -1;
+ }
+ else
+ {
+ water_clip = 1;
+ }
+ }
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Cull");
+
+ //Increment drawable frame counter
+ LLDrawable::incrementVisible();
+
+ LLSpatialGroup::sNoDelete = TRUE;
+ LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName();
+
+ /*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred)
+ { //force occlusion on for all render types if doing deferred render (tighter shadow frustum)
+ LLPipeline::sUseOcclusion = 3;
+ }*/
+
+ S32 occlusion = LLPipeline::sUseOcclusion;
+ if (gDepthDirty)
+ { //depth buffer is invalid, don't overwrite occlusion state
+ LLPipeline::sUseOcclusion = llmin(occlusion, 1);
+ }
+ gDepthDirty = FALSE;
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ static LLCullResult result;
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip);
+ stop_glerror();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ BOOL to_texture = gPipeline.canUseVertexShaders() &&
+ LLPipeline::sRenderGlow;
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Swap");
+
+ {
+ LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SWAP);
+
+ if (gResizeScreenTexture)
+ {
+ gResizeScreenTexture = FALSE;
+ gPipeline.resizeScreenTexture();
+ }
+
+ gGL.setColorMask(true, true);
+ glClearColor(0,0,0,0);
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ if (!for_snapshot)
+ {
+ if (gFrameCount > 1)
+ {
+ //for some reason, ATI 4800 series will error out if you
+ //try to generate a shadow before the first frame is through
+ gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
+ }
+
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ glh::matrix4f proj = glh_get_current_projection();
+ glh::matrix4f mod = glh_get_current_modelview();
+ glViewport(0,0,512,512);
+ LLVOAvatar::updateFreezeCounter() ;
+
+ if(!LLPipeline::sMemAllocationThrottled)
+ {
+ LLVOAvatar::updateImpostors();
+ }
+
+ glh_set_current_projection(proj);
+ glh_set_current_modelview(mod);
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.loadMatrix(proj.m);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.loadMatrix(mod.m);
+ gViewerWindow->setup3DViewport();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ }
+ glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ }
+
+ LLGLState::checkStates();
+ LLGLState::checkClientArrays();
+
+ //if (!for_snapshot)
+ {
+ LLMemType mt_gw(LLMemType::MTYPE_DISPLAY_GEN_REFLECTION);
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery");
+ gPipeline.generateWaterReflection(*LLViewerCamera::getInstance());
+ gPipeline.generateHighlight(*LLViewerCamera::getInstance());
+ gPipeline.renderPhysicsDisplay();
+ }
+
+ LLGLState::checkStates();
+ LLGLState::checkClientArrays();
+
+ //////////////////////////////////////
+ //
+ // Update images, using the image stats generated during object update/culling
+ //
+ // Can put objects onto the retextured list.
+ //
+ // Doing this here gives hardware occlusion queries extra time to complete
+ LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages");
+
+ {
+ LLMemType mt_iu(LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE);
+ LLFastTimer t(FTM_IMAGE_UPDATE);
+
+ {
+ LLFastTimer t(FTM_IMAGE_UPDATE_CLASS);
+ LLViewerTexture::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(),
+ LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean());
+ }
+
+
+ {
+ LLFastTimer t(FTM_IMAGE_UPDATE_BUMP);
+ gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first.
+ }
+
+ {
+ LLFastTimer t(FTM_IMAGE_UPDATE_LIST);
+ F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time
+ max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame)
+ gTextureList.updateImages(max_image_decode_time);
+ }
+
+ {
+ LLFastTimer t(FTM_IMAGE_UPDATE_DELETE);
+ //remove dead textures from GL
+ LLImageGL::deleteDeadTextures();
+ stop_glerror();
+ }
+ }
+
+ LLGLState::checkStates();
+ LLGLState::checkClientArrays();
+
+ ///////////////////////////////////
+ //
+ // StateSort
+ //
+ // Responsible for taking visible objects, and adding them to the appropriate draw orders.
+ // In the case of alpha objects, z-sorts them first.
+ // Also creates special lists for outlines and selected face rendering.
+ //
+ LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort");
+ {
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ LLMemType mt_ss(LLMemType::MTYPE_DISPLAY_STATE_SORT);
+ gPipeline.stateSort(*LLViewerCamera::getInstance(), result);
+ stop_glerror();
+
+ if (rebuild)
+ {
+ //////////////////////////////////////
+ //
+ // rebuildPools
+ //
+ //
+ gPipeline.rebuildPools();
+ stop_glerror();
+ }
+ }
+
+ LLGLState::checkStates();
+ LLGLState::checkClientArrays();
+
+ LLPipeline::sUseOcclusion = occlusion;
+
+ {
+ LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SKY);
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Sky");
+ LLFastTimer t(FTM_UPDATE_SKY);
+ gSky.updateSky();
+ }
+
+ if(gUseWireframe)
+ {
+ glClearColor(0.5f, 0.5f, 0.5f, 0.f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ }
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart");
+
+ //// render frontmost floater opaque for occlusion culling purposes
+ //LLFloater* frontmost_floaterp = gFloaterView->getFrontmost();
+ //// assumes frontmost floater with focus is opaque
+ //if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp))
+ //{
+ // gGL.matrixMode(LLRender::MM_MODELVIEW);
+ // gGL.pushMatrix();
+ // {
+ // gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ // glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
+ // gGL.loadIdentity();
+
+ // LLRect floater_rect = frontmost_floaterp->calcScreenRect();
+ // // deflate by one pixel so rounding errors don't occlude outside of floater extents
+ // floater_rect.stretch(-1);
+ // LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidthScaled(),
+ // (F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeightScaled(),
+ // (F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidthScaled(),
+ // (F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeightScaled());
+ // floater_3d_rect.translate(-0.5f, -0.5f);
+ // gGL.translatef(0.f, 0.f, -LLViewerCamera::getInstance()->getNear());
+ // gGL.scalef(LLViewerCamera::getInstance()->getNear() * LLViewerCamera::getInstance()->getAspect() / sinf(LLViewerCamera::getInstance()->getView()), LLViewerCamera::getInstance()->getNear() / sinf(LLViewerCamera::getInstance()->getView()), 1.f);
+ // gGL.color4fv(LLColor4::white.mV);
+ // gGL.begin(LLVertexBuffer::QUADS);
+ // {
+ // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f);
+ // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f);
+ // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f);
+ // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f);
+ // }
+ // gGL.end();
+ // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ // }
+ // gGL.popMatrix();
+ //}
+
+ LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE;
+
+ LLGLState::checkStates();
+ LLGLState::checkClientArrays();
+
+ stop_glerror();
+
+
+ if (to_texture)
+ {
+ gGL.setColorMask(true, true);
+
+ if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
+ {
+ gPipeline.mDeferredScreen.bindTarget();
+ glClearColor(1,0,1,1);
+ gPipeline.mDeferredScreen.clear();
+ }
+ else
+ {
+ gPipeline.mScreen.bindTarget();
+ if (LLPipeline::sUnderWaterRender && !gPipeline.canUseWindLightShaders())
+ {
+ const LLColor4 &col = LLDrawPoolWater::sWaterFogColor;
+ glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
+ }
+ gPipeline.mScreen.clear();
+ }
+
+ gGL.setColorMask(true, false);
+ }
+
if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot())
&& !gRestoreGL)
{
@@ -911,655 +914,655 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
gGLLastProjection[i] = gGLProjection[i];
}
stop_glerror();
- }
-
- for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++)
- { //dummy cleanup of any currently bound textures
- if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE)
- {
- gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType());
- gGL.getTexUnit(i)->disable();
- }
- }
- LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");
-
- if (to_texture)
- {
- LLMemType mt_rf(LLMemType::MTYPE_DISPLAY_RENDER_FLUSH);
- if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
- {
- gPipeline.mDeferredScreen.flush();
- if(LLRenderTarget::sUseFBO)
- {
- LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(),
- gPipeline.mDeferredScreen.getHeight(), 0, 0,
- gPipeline.mDeferredScreen.getWidth(),
- gPipeline.mDeferredScreen.getHeight(),
- GL_DEPTH_BUFFER_BIT, GL_NEAREST);
- }
- }
- else
- {
- gPipeline.mScreen.flush();
- if(LLRenderTarget::sUseFBO)
- {
- LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(),
- gPipeline.mScreen.getHeight(), 0, 0,
- gPipeline.mScreen.getWidth(),
- gPipeline.mScreen.getHeight(),
- GL_DEPTH_BUFFER_BIT, GL_NEAREST);
- }
- }
- }
-
-
- if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender )
- {
- gPipeline.renderDeferredLighting();
- }
-
- LLPipeline::sUnderWaterRender = FALSE;
-
- LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI");
- if (!for_snapshot)
- {
- LLFastTimer t(FTM_RENDER_UI);
- render_ui();
- }
-
-
- LLSpatialGroup::sNoDelete = FALSE;
- gPipeline.clearReferences();
-
- gPipeline.rebuildGroups();
- }
-
- LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats");
-
- stop_glerror();
-
- if (LLPipeline::sRenderFrameTest)
- {
- send_agent_resume();
- LLPipeline::sRenderFrameTest = FALSE;
- }
-
- display_stats();
-
- LLAppViewer::instance()->pingMainloopTimeout("Display:Done");
-}
-
-void render_hud_attachments()
-{
- LLMemType mt_ra(LLMemType::MTYPE_DISPLAY_RENDER_ATTACHMENTS);
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
-
- glh::matrix4f current_proj = glh_get_current_projection();
- glh::matrix4f current_mod = glh_get_current_modelview();
-
- // clamp target zoom level to reasonable values
- gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f);
- // smoothly interpolate current zoom level
- gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f));
-
- if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices())
- {
- LLCamera hud_cam = *LLViewerCamera::getInstance();
- LLVector3 origin = hud_cam.getOrigin();
- hud_cam.setOrigin(-1.f,0,0);
- hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1));
- LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE);
-
- bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && gSavedSettings.getBOOL("RenderHUDParticles");
-
- //only render hud objects
- gPipeline.pushRenderTypeMask();
-
- // turn off everything
- gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES);
- // turn on HUD
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
- // turn on HUD particles
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
-
- // if particles are off, turn off hud-particles as well
- if (!render_particles)
- {
- // turn back off HUD particles
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
- }
-
- bool has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
- if (has_ui)
- {
- gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
-
- S32 use_occlusion = LLPipeline::sUseOcclusion;
- LLPipeline::sUseOcclusion = 0;
-
- //cull, sort, and render hud objects
- static LLCullResult result;
- LLSpatialGroup::sNoDelete = TRUE;
-
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- gPipeline.updateCull(hud_cam, result);
-
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_SHINY);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISIBLE);
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY);
-
- gPipeline.stateSort(hud_cam, result);
-
- gPipeline.renderGeom(hud_cam);
-
- LLSpatialGroup::sNoDelete = FALSE;
- //gPipeline.clearReferences();
-
- render_hud_elements();
-
- //restore type mask
- gPipeline.popRenderTypeMask();
-
- if (has_ui)
- {
- gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
- LLPipeline::sUseOcclusion = use_occlusion;
- }
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
-
- glh_set_current_projection(current_proj);
- glh_set_current_modelview(current_mod);
-}
-
-LLRect get_whole_screen_region()
-{
- LLRect whole_screen = gViewerWindow->getWorldViewRectScaled();
-
- // apply camera zoom transform (for high res screenshots)
- F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
- S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
- if (zoom_factor > 1.f)
- {
- S32 num_horizontal_tiles = llceil(zoom_factor);
- S32 tile_width = llround((F32)gViewerWindow->getWorldViewWidthScaled() / zoom_factor);
- S32 tile_height = llround((F32)gViewerWindow->getWorldViewHeightScaled() / zoom_factor);
- int tile_y = sub_region / num_horizontal_tiles;
- int tile_x = sub_region - (tile_y * num_horizontal_tiles);
-
- whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWorldViewHeightScaled() - (tile_y * tile_height), tile_width, tile_height);
- }
- return whole_screen;
-}
-
-bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::matrix4f &model)
-{
- if (isAgentAvatarValid() && gAgentAvatarp->hasHUDAttachment())
- {
- F32 zoom_level = gAgentCamera.mHUDCurZoom;
- LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
-
- F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
- proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth);
- proj.element(2,2) = -0.01f;
-
- F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect();
-
- glh::matrix4f mat;
- F32 scale_x = (F32)gViewerWindow->getWorldViewWidthScaled() / (F32)screen_region.getWidth();
- F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight();
- mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f));
- mat.set_translate(
- 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),
- clamp_rescale((F32)(screen_region.getCenterY() - screen_region.mBottom), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y),
- 0.f));
- proj *= mat;
-
- glh::matrix4f tmp_model((GLfloat*) OGL_TO_CFR_ROTATION);
-
- mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level));
- mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f));
-
- tmp_model *= mat;
- model = tmp_model;
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model)
-{
- LLRect whole_screen = get_whole_screen_region();
- return get_hud_matrices(whole_screen, proj, model);
-}
-
-BOOL setup_hud_matrices()
-{
- LLRect whole_screen = get_whole_screen_region();
- return setup_hud_matrices(whole_screen);
-}
-
-BOOL setup_hud_matrices(const LLRect& screen_region)
-{
- glh::matrix4f proj, model;
- bool result = get_hud_matrices(screen_region, proj, model);
- if (!result) return result;
-
- // set up transform to keep HUD objects in front of camera
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.loadMatrix(proj.m);
- glh_set_current_projection(proj);
-
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.loadMatrix(model.m);
- glh_set_current_modelview(model);
- return TRUE;
-}
-
-static LLFastTimer::DeclareTimer FTM_SWAP("Swap");
-
-void render_ui(F32 zoom_factor, int subfield)
-{
- LLMemType mt_ru(LLMemType::MTYPE_DISPLAY_RENDER_UI);
- LLGLState::checkStates();
-
- glh::matrix4f saved_view = glh_get_current_modelview();
-
- if (!gSnapshot)
- {
- gGL.pushMatrix();
- gGL.loadMatrix(gGLLastModelView);
- glh_set_current_modelview(glh_copy_matrix(gGLLastModelView));
- }
-
- {
- BOOL to_texture = gPipeline.canUseVertexShaders() &&
- LLPipeline::sRenderGlow;
-
- if (to_texture)
- {
- gPipeline.renderBloom(gSnapshot, zoom_factor, subfield);
- }
-
- render_hud_elements();
- render_hud_attachments();
- }
-
- LLGLSDefault gls_default;
- LLGLSUIDefault gls_ui;
- {
- gPipeline.disableLights();
- }
-
- {
- gGL.color4f(1,1,1,1);
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- LLFastTimer t(FTM_RENDER_UI);
-
- if (!gDisconnected)
- {
- render_ui_3d();
- LLGLState::checkStates();
- }
- else
- {
- render_disconnected_background();
- }
- render_ui_2d();
- LLGLState::checkStates();
- }
- gGL.flush();
-
- {
- gViewerWindow->setup2DRender();
- gViewerWindow->updateDebugText();
- gViewerWindow->drawDebugText();
- }
-
- LLVertexBuffer::unbind();
- }
-
- if (!gSnapshot)
- {
- glh_set_current_modelview(saved_view);
- gGL.popMatrix();
- }
-
- if (gDisplaySwapBuffers)
- {
- LLFastTimer t(FTM_SWAP);
- gViewerWindow->getWindow()->swapBuffers();
- }
- gDisplaySwapBuffers = TRUE;
-}
-
-void renderCoordinateAxes()
-{
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.begin(LLRender::LINES);
- gGL.color3f(1.0f, 0.0f, 0.0f); // i direction = X-Axis = red
- gGL.vertex3f(0.0f, 0.0f, 0.0f);
- gGL.vertex3f(2.0f, 0.0f, 0.0f);
- gGL.vertex3f(3.0f, 0.0f, 0.0f);
- gGL.vertex3f(5.0f, 0.0f, 0.0f);
- gGL.vertex3f(6.0f, 0.0f, 0.0f);
- gGL.vertex3f(8.0f, 0.0f, 0.0f);
- // Make an X
- gGL.vertex3f(11.0f, 1.0f, 1.0f);
- gGL.vertex3f(11.0f, -1.0f, -1.0f);
- gGL.vertex3f(11.0f, 1.0f, -1.0f);
- gGL.vertex3f(11.0f, -1.0f, 1.0f);
-
- gGL.color3f(0.0f, 1.0f, 0.0f); // j direction = Y-Axis = green
- gGL.vertex3f(0.0f, 0.0f, 0.0f);
- gGL.vertex3f(0.0f, 2.0f, 0.0f);
- gGL.vertex3f(0.0f, 3.0f, 0.0f);
- gGL.vertex3f(0.0f, 5.0f, 0.0f);
- gGL.vertex3f(0.0f, 6.0f, 0.0f);
- gGL.vertex3f(0.0f, 8.0f, 0.0f);
- // Make a Y
- gGL.vertex3f(1.0f, 11.0f, 1.0f);
- gGL.vertex3f(0.0f, 11.0f, 0.0f);
- gGL.vertex3f(-1.0f, 11.0f, 1.0f);
- gGL.vertex3f(0.0f, 11.0f, 0.0f);
- gGL.vertex3f(0.0f, 11.0f, 0.0f);
- gGL.vertex3f(0.0f, 11.0f, -1.0f);
-
- gGL.color3f(0.0f, 0.0f, 1.0f); // Z-Axis = blue
- gGL.vertex3f(0.0f, 0.0f, 0.0f);
- gGL.vertex3f(0.0f, 0.0f, 2.0f);
- gGL.vertex3f(0.0f, 0.0f, 3.0f);
- gGL.vertex3f(0.0f, 0.0f, 5.0f);
- gGL.vertex3f(0.0f, 0.0f, 6.0f);
- gGL.vertex3f(0.0f, 0.0f, 8.0f);
- // Make a Z
- gGL.vertex3f(-1.0f, 1.0f, 11.0f);
- gGL.vertex3f(1.0f, 1.0f, 11.0f);
- gGL.vertex3f(1.0f, 1.0f, 11.0f);
- gGL.vertex3f(-1.0f, -1.0f, 11.0f);
- gGL.vertex3f(-1.0f, -1.0f, 11.0f);
- gGL.vertex3f(1.0f, -1.0f, 11.0f);
- gGL.end();
-}
-
-
-void draw_axes()
-{
- LLGLSUIDefault gls_ui;
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- // A vertical white line at origin
- LLVector3 v = gAgent.getPositionAgent();
- gGL.begin(LLRender::LINES);
- gGL.color3f(1.0f, 1.0f, 1.0f);
- gGL.vertex3f(0.0f, 0.0f, 0.0f);
- gGL.vertex3f(0.0f, 0.0f, 40.0f);
- gGL.end();
- // Some coordinate axes
- gGL.pushMatrix();
- gGL.translatef( v.mV[VX], v.mV[VY], v.mV[VZ] );
- renderCoordinateAxes();
- gGL.popMatrix();
-}
-
-void render_ui_3d()
-{
- LLGLSPipeline gls_pipeline;
-
- //////////////////////////////////////
- //
- // Render 3D UI elements
- // NOTE: zbuffer is cleared before we get here by LLDrawPoolHUD,
- // so 3d elements requiring Z buffer are moved to LLDrawPoolHUD
- //
-
- /////////////////////////////////////////////////////////////
- //
- // Render 2.5D elements (2D elements in the world)
- // Stuff without z writes
- //
-
- // Debugging stuff goes before the UI.
-
- stop_glerror();
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gUIProgram.bind();
- }
-
- // Coordinate axes
- if (gSavedSettings.getBOOL("ShowAxes"))
- {
- draw_axes();
- }
-
- gViewerWindow->renderSelections(FALSE, FALSE, TRUE); // Non HUD call in render_hud_elements
- stop_glerror();
-}
-
-void render_ui_2d()
-{
- LLGLSUIDefault gls_ui;
-
- /////////////////////////////////////////////////////////////
- //
- // Render 2D UI elements that overlay the world (no z compare)
-
- // Disable wireframe mode below here, as this is HUD/menus
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-
- // Menu overlays, HUD, etc
- gViewerWindow->setup2DRender();
-
- F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
- S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
-
- if (zoom_factor > 1.f)
- {
- //decompose subregion number to x and y values
- int pos_y = sub_region / llceil(zoom_factor);
- int pos_x = sub_region - (pos_y*llceil(zoom_factor));
- // offset for this tile
- LLFontGL::sCurOrigin.mX -= llround((F32)gViewerWindow->getWindowWidthScaled() * (F32)pos_x / zoom_factor);
- LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeightScaled() * (F32)pos_y / zoom_factor);
- }
-
- stop_glerror();
- //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-
- // render outline for HUD
- if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f)
- {
- gGL.pushMatrix();
- S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2);
- S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2);
- gGL.scalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f);
- gGL.translatef((F32)half_width, (F32)half_height, 0.f);
- F32 zoom = gAgentCamera.mHUDCurZoom;
- gGL.scalef(zoom,zoom,1.f);
- gGL.color4fv(LLColor4::white.mV);
- gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE);
- gGL.popMatrix();
- stop_glerror();
- }
-
-
- if (gSavedSettings.getBOOL("RenderUIBuffer"))
- {
- if (LLUI::sDirty)
- {
- LLUI::sDirty = FALSE;
- LLRect t_rect;
-
- gPipeline.mUIScreen.bindTarget();
- gGL.setColorMask(true, true);
- {
- static const S32 pad = 8;
-
- LLUI::sDirtyRect.mLeft -= pad;
- LLUI::sDirtyRect.mRight += pad;
- LLUI::sDirtyRect.mBottom -= pad;
- LLUI::sDirtyRect.mTop += pad;
-
- LLGLEnable scissor(GL_SCISSOR_TEST);
- static LLRect last_rect = LLUI::sDirtyRect;
-
- //union with last rect to avoid mouse poop
- last_rect.unionWith(LLUI::sDirtyRect);
-
- t_rect = LLUI::sDirtyRect;
- LLUI::sDirtyRect = last_rect;
- last_rect = t_rect;
-
- last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::sGLScaleFactor.mV[0]);
- last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::sGLScaleFactor.mV[0]);
- last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::sGLScaleFactor.mV[1]);
- last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::sGLScaleFactor.mV[1]);
-
- LLRect clip_rect(last_rect);
-
- glClear(GL_COLOR_BUFFER_BIT);
-
- gViewerWindow->draw();
- }
-
- gPipeline.mUIScreen.flush();
- gGL.setColorMask(true, false);
-
- LLUI::sDirtyRect = t_rect;
- }
-
- LLGLDisable cull(GL_CULL_FACE);
- LLGLDisable blend(GL_BLEND);
- S32 width = gViewerWindow->getWindowWidthScaled();
- S32 height = gViewerWindow->getWindowHeightScaled();
- gGL.getTexUnit(0)->bind(&gPipeline.mUIScreen);
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.color4f(1,1,1,1);
- gGL.texCoord2f(0, 0); gGL.vertex2i(0, 0);
- gGL.texCoord2f(width, 0); gGL.vertex2i(width, 0);
- gGL.texCoord2f(0, height); gGL.vertex2i(0, height);
- gGL.texCoord2f(width, height); gGL.vertex2i(width, height);
- gGL.end();
- }
- else
- {
- gViewerWindow->draw();
- }
-
-
-
- // reset current origin for font rendering, in case of tiling render
- LLFontGL::sCurOrigin.set(0, 0);
-}
-
-void render_disconnected_background()
-{
- if (LLGLSLShader::sNoFixedFunction)
- {
- gUIProgram.bind();
- }
-
- gGL.color4f(1,1,1,1);
- if (!gDisconnectedImagep && gDisconnected)
- {
- llinfos << "Loading last bitmap..." << llendl;
-
- std::string temp_str;
- temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_LAST_FILENAME;
-
- LLPointer<LLImageBMP> image_bmp = new LLImageBMP;
- if( !image_bmp->load(temp_str) )
- {
- //llinfos << "Bitmap load failed" << llendl;
- return;
- }
-
- LLPointer<LLImageRaw> raw = new LLImageRaw;
- if (!image_bmp->decode(raw, 0.0f))
- {
- llinfos << "Bitmap decode failed" << llendl;
- gDisconnectedImagep = NULL;
- return;
- }
-
- U8 *rawp = raw->getData();
- S32 npixels = (S32)image_bmp->getWidth()*(S32)image_bmp->getHeight();
- for (S32 i = 0; i < npixels; i++)
- {
- S32 sum = 0;
- sum = *rawp + *(rawp+1) + *(rawp+2);
- sum /= 3;
- *rawp = ((S32)sum*6 + *rawp)/7;
- rawp++;
- *rawp = ((S32)sum*6 + *rawp)/7;
- rawp++;
- *rawp = ((S32)sum*6 + *rawp)/7;
- rawp++;
- }
-
-
- raw->expandToPowerOfTwo();
- gDisconnectedImagep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE );
- gStartTexture = gDisconnectedImagep;
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
-
- // Make sure the progress view always fills the entire window.
- S32 width = gViewerWindow->getWindowWidthScaled();
- S32 height = gViewerWindow->getWindowHeightScaled();
-
- if (gDisconnectedImagep)
- {
- LLGLSUIDefault gls_ui;
- gViewerWindow->setup2DRender();
- gGL.pushMatrix();
- {
- // scale ui to reflect UIScaleFactor
- // this can't be done in setup2DRender because it requires a
- // pushMatrix/popMatrix pair
- const LLVector2& display_scale = gViewerWindow->getDisplayScale();
- gGL.scalef(display_scale.mV[VX], display_scale.mV[VY], 1.f);
-
- gGL.getTexUnit(0)->bind(gDisconnectedImagep);
- gGL.color4f(1.f, 1.f, 1.f, 1.f);
- gl_rect_2d_simple_tex(width, height);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
- gGL.popMatrix();
- }
- gGL.flush();
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gUIProgram.unbind();
- }
-
-}
-
-void display_cleanup()
-{
- gDisconnectedImagep = NULL;
-}
+ }
+
+ for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++)
+ { //dummy cleanup of any currently bound textures
+ if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE)
+ {
+ gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType());
+ gGL.getTexUnit(i)->disable();
+ }
+ }
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");
+
+ if (to_texture)
+ {
+ LLMemType mt_rf(LLMemType::MTYPE_DISPLAY_RENDER_FLUSH);
+ if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
+ {
+ gPipeline.mDeferredScreen.flush();
+ if(LLRenderTarget::sUseFBO)
+ {
+ LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(),
+ gPipeline.mDeferredScreen.getHeight(), 0, 0,
+ gPipeline.mDeferredScreen.getWidth(),
+ gPipeline.mDeferredScreen.getHeight(),
+ GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ }
+ }
+ else
+ {
+ gPipeline.mScreen.flush();
+ if(LLRenderTarget::sUseFBO)
+ {
+ LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(),
+ gPipeline.mScreen.getHeight(), 0, 0,
+ gPipeline.mScreen.getWidth(),
+ gPipeline.mScreen.getHeight(),
+ GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ }
+ }
+ }
+
+
+ if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender )
+ {
+ gPipeline.renderDeferredLighting();
+ }
+
+ LLPipeline::sUnderWaterRender = FALSE;
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI");
+ if (!for_snapshot)
+ {
+ LLFastTimer t(FTM_RENDER_UI);
+ render_ui();
+ }
+
+
+ LLSpatialGroup::sNoDelete = FALSE;
+ gPipeline.clearReferences();
+
+ gPipeline.rebuildGroups();
+ }
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats");
+
+ stop_glerror();
+
+ if (LLPipeline::sRenderFrameTest)
+ {
+ send_agent_resume();
+ LLPipeline::sRenderFrameTest = FALSE;
+ }
+
+ display_stats();
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Done");
+}
+
+void render_hud_attachments()
+{
+ LLMemType mt_ra(LLMemType::MTYPE_DISPLAY_RENDER_ATTACHMENTS);
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.pushMatrix();
+
+ glh::matrix4f current_proj = glh_get_current_projection();
+ glh::matrix4f current_mod = glh_get_current_modelview();
+
+ // clamp target zoom level to reasonable values
+ gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f);
+ // smoothly interpolate current zoom level
+ gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f));
+
+ if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices())
+ {
+ LLCamera hud_cam = *LLViewerCamera::getInstance();
+ LLVector3 origin = hud_cam.getOrigin();
+ hud_cam.setOrigin(-1.f,0,0);
+ hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1));
+ LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE);
+
+ bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && gSavedSettings.getBOOL("RenderHUDParticles");
+
+ //only render hud objects
+ gPipeline.pushRenderTypeMask();
+
+ // turn off everything
+ gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES);
+ // turn on HUD
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ // turn on HUD particles
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
+
+ // if particles are off, turn off hud-particles as well
+ if (!render_particles)
+ {
+ // turn back off HUD particles
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
+ }
+
+ bool has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ if (has_ui)
+ {
+ gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+
+ S32 use_occlusion = LLPipeline::sUseOcclusion;
+ LLPipeline::sUseOcclusion = 0;
+
+ //cull, sort, and render hud objects
+ static LLCullResult result;
+ LLSpatialGroup::sNoDelete = TRUE;
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ gPipeline.updateCull(hud_cam, result);
+
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_SHINY);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISIBLE);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY);
+
+ gPipeline.stateSort(hud_cam, result);
+
+ gPipeline.renderGeom(hud_cam);
+
+ LLSpatialGroup::sNoDelete = FALSE;
+ //gPipeline.clearReferences();
+
+ render_hud_elements();
+
+ //restore type mask
+ gPipeline.popRenderTypeMask();
+
+ if (has_ui)
+ {
+ gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+ LLPipeline::sUseOcclusion = use_occlusion;
+ }
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+
+ glh_set_current_projection(current_proj);
+ glh_set_current_modelview(current_mod);
+}
+
+LLRect get_whole_screen_region()
+{
+ LLRect whole_screen = gViewerWindow->getWorldViewRectScaled();
+
+ // apply camera zoom transform (for high res screenshots)
+ F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
+ S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
+ if (zoom_factor > 1.f)
+ {
+ S32 num_horizontal_tiles = llceil(zoom_factor);
+ S32 tile_width = llround((F32)gViewerWindow->getWorldViewWidthScaled() / zoom_factor);
+ S32 tile_height = llround((F32)gViewerWindow->getWorldViewHeightScaled() / zoom_factor);
+ int tile_y = sub_region / num_horizontal_tiles;
+ int tile_x = sub_region - (tile_y * num_horizontal_tiles);
+
+ whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWorldViewHeightScaled() - (tile_y * tile_height), tile_width, tile_height);
+ }
+ return whole_screen;
+}
+
+bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::matrix4f &model)
+{
+ if (isAgentAvatarValid() && gAgentAvatarp->hasHUDAttachment())
+ {
+ F32 zoom_level = gAgentCamera.mHUDCurZoom;
+ LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
+
+ F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
+ proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth);
+ proj.element(2,2) = -0.01f;
+
+ F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect();
+
+ glh::matrix4f mat;
+ F32 scale_x = (F32)gViewerWindow->getWorldViewWidthScaled() / (F32)screen_region.getWidth();
+ F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight();
+ mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f));
+ mat.set_translate(
+ 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),
+ clamp_rescale((F32)(screen_region.getCenterY() - screen_region.mBottom), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y),
+ 0.f));
+ proj *= mat;
+
+ glh::matrix4f tmp_model((GLfloat*) OGL_TO_CFR_ROTATION);
+
+ mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level));
+ mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f));
+
+ tmp_model *= mat;
+ model = tmp_model;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model)
+{
+ LLRect whole_screen = get_whole_screen_region();
+ return get_hud_matrices(whole_screen, proj, model);
+}
+
+BOOL setup_hud_matrices()
+{
+ LLRect whole_screen = get_whole_screen_region();
+ return setup_hud_matrices(whole_screen);
+}
+
+BOOL setup_hud_matrices(const LLRect& screen_region)
+{
+ glh::matrix4f proj, model;
+ bool result = get_hud_matrices(screen_region, proj, model);
+ if (!result) return result;
+
+ // set up transform to keep HUD objects in front of camera
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.loadMatrix(proj.m);
+ glh_set_current_projection(proj);
+
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.loadMatrix(model.m);
+ glh_set_current_modelview(model);
+ return TRUE;
+}
+
+static LLFastTimer::DeclareTimer FTM_SWAP("Swap");
+
+void render_ui(F32 zoom_factor, int subfield)
+{
+ LLMemType mt_ru(LLMemType::MTYPE_DISPLAY_RENDER_UI);
+ LLGLState::checkStates();
+
+ glh::matrix4f saved_view = glh_get_current_modelview();
+
+ if (!gSnapshot)
+ {
+ gGL.pushMatrix();
+ gGL.loadMatrix(gGLLastModelView);
+ glh_set_current_modelview(glh_copy_matrix(gGLLastModelView));
+ }
+
+ {
+ BOOL to_texture = gPipeline.canUseVertexShaders() &&
+ LLPipeline::sRenderGlow;
+
+ if (to_texture)
+ {
+ gPipeline.renderBloom(gSnapshot, zoom_factor, subfield);
+ }
+
+ render_hud_elements();
+ render_hud_attachments();
+ }
+
+ LLGLSDefault gls_default;
+ LLGLSUIDefault gls_ui;
+ {
+ gPipeline.disableLights();
+ }
+
+ {
+ gGL.color4f(1,1,1,1);
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ LLFastTimer t(FTM_RENDER_UI);
+
+ if (!gDisconnected)
+ {
+ render_ui_3d();
+ LLGLState::checkStates();
+ }
+ else
+ {
+ render_disconnected_background();
+ }
+ render_ui_2d();
+ LLGLState::checkStates();
+ }
+ gGL.flush();
+
+ {
+ gViewerWindow->setup2DRender();
+ gViewerWindow->updateDebugText();
+ gViewerWindow->drawDebugText();
+ }
+
+ LLVertexBuffer::unbind();
+ }
+
+ if (!gSnapshot)
+ {
+ glh_set_current_modelview(saved_view);
+ gGL.popMatrix();
+ }
+
+ if (gDisplaySwapBuffers)
+ {
+ LLFastTimer t(FTM_SWAP);
+ gViewerWindow->getWindow()->swapBuffers();
+ }
+ gDisplaySwapBuffers = TRUE;
+}
+
+void renderCoordinateAxes()
+{
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.begin(LLRender::LINES);
+ gGL.color3f(1.0f, 0.0f, 0.0f); // i direction = X-Axis = red
+ gGL.vertex3f(0.0f, 0.0f, 0.0f);
+ gGL.vertex3f(2.0f, 0.0f, 0.0f);
+ gGL.vertex3f(3.0f, 0.0f, 0.0f);
+ gGL.vertex3f(5.0f, 0.0f, 0.0f);
+ gGL.vertex3f(6.0f, 0.0f, 0.0f);
+ gGL.vertex3f(8.0f, 0.0f, 0.0f);
+ // Make an X
+ gGL.vertex3f(11.0f, 1.0f, 1.0f);
+ gGL.vertex3f(11.0f, -1.0f, -1.0f);
+ gGL.vertex3f(11.0f, 1.0f, -1.0f);
+ gGL.vertex3f(11.0f, -1.0f, 1.0f);
+
+ gGL.color3f(0.0f, 1.0f, 0.0f); // j direction = Y-Axis = green
+ gGL.vertex3f(0.0f, 0.0f, 0.0f);
+ gGL.vertex3f(0.0f, 2.0f, 0.0f);
+ gGL.vertex3f(0.0f, 3.0f, 0.0f);
+ gGL.vertex3f(0.0f, 5.0f, 0.0f);
+ gGL.vertex3f(0.0f, 6.0f, 0.0f);
+ gGL.vertex3f(0.0f, 8.0f, 0.0f);
+ // Make a Y
+ gGL.vertex3f(1.0f, 11.0f, 1.0f);
+ gGL.vertex3f(0.0f, 11.0f, 0.0f);
+ gGL.vertex3f(-1.0f, 11.0f, 1.0f);
+ gGL.vertex3f(0.0f, 11.0f, 0.0f);
+ gGL.vertex3f(0.0f, 11.0f, 0.0f);
+ gGL.vertex3f(0.0f, 11.0f, -1.0f);
+
+ gGL.color3f(0.0f, 0.0f, 1.0f); // Z-Axis = blue
+ gGL.vertex3f(0.0f, 0.0f, 0.0f);
+ gGL.vertex3f(0.0f, 0.0f, 2.0f);
+ gGL.vertex3f(0.0f, 0.0f, 3.0f);
+ gGL.vertex3f(0.0f, 0.0f, 5.0f);
+ gGL.vertex3f(0.0f, 0.0f, 6.0f);
+ gGL.vertex3f(0.0f, 0.0f, 8.0f);
+ // Make a Z
+ gGL.vertex3f(-1.0f, 1.0f, 11.0f);
+ gGL.vertex3f(1.0f, 1.0f, 11.0f);
+ gGL.vertex3f(1.0f, 1.0f, 11.0f);
+ gGL.vertex3f(-1.0f, -1.0f, 11.0f);
+ gGL.vertex3f(-1.0f, -1.0f, 11.0f);
+ gGL.vertex3f(1.0f, -1.0f, 11.0f);
+ gGL.end();
+}
+
+
+void draw_axes()
+{
+ LLGLSUIDefault gls_ui;
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ // A vertical white line at origin
+ LLVector3 v = gAgent.getPositionAgent();
+ gGL.begin(LLRender::LINES);
+ gGL.color3f(1.0f, 1.0f, 1.0f);
+ gGL.vertex3f(0.0f, 0.0f, 0.0f);
+ gGL.vertex3f(0.0f, 0.0f, 40.0f);
+ gGL.end();
+ // Some coordinate axes
+ gGL.pushMatrix();
+ gGL.translatef( v.mV[VX], v.mV[VY], v.mV[VZ] );
+ renderCoordinateAxes();
+ gGL.popMatrix();
+}
+
+void render_ui_3d()
+{
+ LLGLSPipeline gls_pipeline;
+
+ //////////////////////////////////////
+ //
+ // Render 3D UI elements
+ // NOTE: zbuffer is cleared before we get here by LLDrawPoolHUD,
+ // so 3d elements requiring Z buffer are moved to LLDrawPoolHUD
+ //
+
+ /////////////////////////////////////////////////////////////
+ //
+ // Render 2.5D elements (2D elements in the world)
+ // Stuff without z writes
+ //
+
+ // Debugging stuff goes before the UI.
+
+ stop_glerror();
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gUIProgram.bind();
+ }
+
+ // Coordinate axes
+ if (gSavedSettings.getBOOL("ShowAxes"))
+ {
+ draw_axes();
+ }
+
+ gViewerWindow->renderSelections(FALSE, FALSE, TRUE); // Non HUD call in render_hud_elements
+ stop_glerror();
+}
+
+void render_ui_2d()
+{
+ LLGLSUIDefault gls_ui;
+
+ /////////////////////////////////////////////////////////////
+ //
+ // Render 2D UI elements that overlay the world (no z compare)
+
+ // Disable wireframe mode below here, as this is HUD/menus
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ // Menu overlays, HUD, etc
+ gViewerWindow->setup2DRender();
+
+ F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
+ S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
+
+ if (zoom_factor > 1.f)
+ {
+ //decompose subregion number to x and y values
+ int pos_y = sub_region / llceil(zoom_factor);
+ int pos_x = sub_region - (pos_y*llceil(zoom_factor));
+ // offset for this tile
+ LLFontGL::sCurOrigin.mX -= llround((F32)gViewerWindow->getWindowWidthScaled() * (F32)pos_x / zoom_factor);
+ LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeightScaled() * (F32)pos_y / zoom_factor);
+ }
+
+ stop_glerror();
+ //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+ // render outline for HUD
+ if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f)
+ {
+ gGL.pushMatrix();
+ S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2);
+ S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2);
+ gGL.scalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f);
+ gGL.translatef((F32)half_width, (F32)half_height, 0.f);
+ F32 zoom = gAgentCamera.mHUDCurZoom;
+ gGL.scalef(zoom,zoom,1.f);
+ gGL.color4fv(LLColor4::white.mV);
+ gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE);
+ gGL.popMatrix();
+ stop_glerror();
+ }
+
+
+ if (gSavedSettings.getBOOL("RenderUIBuffer"))
+ {
+ if (LLUI::sDirty)
+ {
+ LLUI::sDirty = FALSE;
+ LLRect t_rect;
+
+ gPipeline.mUIScreen.bindTarget();
+ gGL.setColorMask(true, true);
+ {
+ static const S32 pad = 8;
+
+ LLUI::sDirtyRect.mLeft -= pad;
+ LLUI::sDirtyRect.mRight += pad;
+ LLUI::sDirtyRect.mBottom -= pad;
+ LLUI::sDirtyRect.mTop += pad;
+
+ LLGLEnable scissor(GL_SCISSOR_TEST);
+ static LLRect last_rect = LLUI::sDirtyRect;
+
+ //union with last rect to avoid mouse poop
+ last_rect.unionWith(LLUI::sDirtyRect);
+
+ t_rect = LLUI::sDirtyRect;
+ LLUI::sDirtyRect = last_rect;
+ last_rect = t_rect;
+
+ last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::sGLScaleFactor.mV[0]);
+ last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::sGLScaleFactor.mV[0]);
+ last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::sGLScaleFactor.mV[1]);
+ last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::sGLScaleFactor.mV[1]);
+
+ LLRect clip_rect(last_rect);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ gViewerWindow->draw();
+ }
+
+ gPipeline.mUIScreen.flush();
+ gGL.setColorMask(true, false);
+
+ LLUI::sDirtyRect = t_rect;
+ }
+
+ LLGLDisable cull(GL_CULL_FACE);
+ LLGLDisable blend(GL_BLEND);
+ S32 width = gViewerWindow->getWindowWidthScaled();
+ S32 height = gViewerWindow->getWindowHeightScaled();
+ gGL.getTexUnit(0)->bind(&gPipeline.mUIScreen);
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.color4f(1,1,1,1);
+ gGL.texCoord2f(0, 0); gGL.vertex2i(0, 0);
+ gGL.texCoord2f(width, 0); gGL.vertex2i(width, 0);
+ gGL.texCoord2f(0, height); gGL.vertex2i(0, height);
+ gGL.texCoord2f(width, height); gGL.vertex2i(width, height);
+ gGL.end();
+ }
+ else
+ {
+ gViewerWindow->draw();
+ }
+
+
+
+ // reset current origin for font rendering, in case of tiling render
+ LLFontGL::sCurOrigin.set(0, 0);
+}
+
+void render_disconnected_background()
+{
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gUIProgram.bind();
+ }
+
+ gGL.color4f(1,1,1,1);
+ if (!gDisconnectedImagep && gDisconnected)
+ {
+ llinfos << "Loading last bitmap..." << llendl;
+
+ std::string temp_str;
+ temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_LAST_FILENAME;
+
+ LLPointer<LLImageBMP> image_bmp = new LLImageBMP;
+ if( !image_bmp->load(temp_str) )
+ {
+ //llinfos << "Bitmap load failed" << llendl;
+ return;
+ }
+
+ LLPointer<LLImageRaw> raw = new LLImageRaw;
+ if (!image_bmp->decode(raw, 0.0f))
+ {
+ llinfos << "Bitmap decode failed" << llendl;
+ gDisconnectedImagep = NULL;
+ return;
+ }
+
+ U8 *rawp = raw->getData();
+ S32 npixels = (S32)image_bmp->getWidth()*(S32)image_bmp->getHeight();
+ for (S32 i = 0; i < npixels; i++)
+ {
+ S32 sum = 0;
+ sum = *rawp + *(rawp+1) + *(rawp+2);
+ sum /= 3;
+ *rawp = ((S32)sum*6 + *rawp)/7;
+ rawp++;
+ *rawp = ((S32)sum*6 + *rawp)/7;
+ rawp++;
+ *rawp = ((S32)sum*6 + *rawp)/7;
+ rawp++;
+ }
+
+
+ raw->expandToPowerOfTwo();
+ gDisconnectedImagep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE );
+ gStartTexture = gDisconnectedImagep;
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ }
+
+ // Make sure the progress view always fills the entire window.
+ S32 width = gViewerWindow->getWindowWidthScaled();
+ S32 height = gViewerWindow->getWindowHeightScaled();
+
+ if (gDisconnectedImagep)
+ {
+ LLGLSUIDefault gls_ui;
+ gViewerWindow->setup2DRender();
+ gGL.pushMatrix();
+ {
+ // scale ui to reflect UIScaleFactor
+ // this can't be done in setup2DRender because it requires a
+ // pushMatrix/popMatrix pair
+ const LLVector2& display_scale = gViewerWindow->getDisplayScale();
+ gGL.scalef(display_scale.mV[VX], display_scale.mV[VY], 1.f);
+
+ gGL.getTexUnit(0)->bind(gDisconnectedImagep);
+ gGL.color4f(1.f, 1.f, 1.f, 1.f);
+ gl_rect_2d_simple_tex(width, height);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ }
+ gGL.popMatrix();
+ }
+ gGL.flush();
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gUIProgram.unbind();
+ }
+
+}
+
+void display_cleanup()
+{
+ gDisconnectedImagep = NULL;
+}
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index d396219bf8..12f802b29a 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -35,7 +35,6 @@
#include "llcallfloater.h"
#include "llfasttimerview.h"
#include "llfloaterabout.h"
-#include "llfloateranimpreview.h"
#include "llfloaterauction.h"
#include "llfloateravatar.h"
#include "llfloateravatarpicker.h"
@@ -49,6 +48,7 @@
#include "llfloaterbuyland.h"
#include "llfloaterbulkpermission.h"
#include "llfloaterbump.h"
+#include "llfloaterbvhpreview.h"
#include "llfloatercamera.h"
#include "llfloaterdeleteenvpreset.h"
#include "llfloaterdisplayname.h"
@@ -302,7 +302,8 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterUIPreviewUtil::registerFloater();
- LLFloaterReg::add("upload_anim", "floater_animation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload");
+ LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBvhPreview>, "upload");
+ LLFloaterReg::add("upload_anim_anim", "floater_animation_anim_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload");
LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImagePreview>, "upload");
LLFloaterReg::add("upload_model", "floater_model_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelPreview>, "upload");
LLFloaterReg::add("upload_model_wizard", "floater_model_wizard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelWizard>);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 163581ea7f..45ca23cdfe 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -436,11 +436,6 @@ void LLViewerInventoryItem::fetchFromServer(void) const
gAgent.sendReliableMessage();
}
}
- else
- {
- // *FIX: this can be removed after a bit.
- llwarns << "request to fetch complete item" << llendl;
- }
}
// virtual
@@ -1462,6 +1457,7 @@ const std::string& LLViewerInventoryItem::getName() const
class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage>
, public LLDestroyClass<LLFavoritesOrderStorage>
{
+ LOG_CLASS(LLFavoritesOrderStorage);
public:
/**
* Sets sort index for specified with LLUUID favorite landmark
@@ -1620,10 +1616,18 @@ void LLFavoritesOrderStorage::load()
void LLFavoritesOrderStorage::saveFavoritesSLURLs()
{
// Do not change the file if we are not logged in yet.
- if (!LLLoginInstance::getInstance()->authSuccess()) return;
+ if (!LLLoginInstance::getInstance()->authSuccess())
+ {
+ llwarns << "Cannot save favorites: not logged in" << llendl;
+ return;
+ }
std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
- if (user_dir.empty()) return;
+ if (user_dir.empty())
+ {
+ llwarns << "Cannot save favorites: empty user dir name" << llendl;
+ return;
+ }
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
llifstream in_file;
@@ -1649,13 +1653,19 @@ void LLFavoritesOrderStorage::saveFavoritesSLURLs()
slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]);
if (slurl_iter != mSLURLs.end())
{
+ lldebugs << "Saving favorite: idx=" << (*it)->getSortField() << ", SLURL=" << slurl_iter->second << ", value=" << value << llendl;
value["slurl"] = slurl_iter->second;
user_llsd[(*it)->getSortField()] = value;
}
+ else
+ {
+ llwarns << "Not saving favorite " << value["name"] << ": no matching SLURL" << llendl;
+ }
}
LLAvatarName av_name;
LLAvatarNameCache::get( gAgentID, &av_name );
+ lldebugs << "Saved favorites for " << av_name.getLegacyName() << llendl;
fav_llsd[av_name.getLegacyName()] = user_llsd;
llofstream file;
@@ -1674,6 +1684,7 @@ void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()
LLAvatarName av_name;
LLAvatarNameCache::get( gAgentID, &av_name );
+ lldebugs << "Removed favorites for " << av_name.getLegacyName() << llendl;
if (fav_llsd.has(av_name.getLegacyName()))
{
fav_llsd.erase(av_name.getLegacyName());
@@ -1706,6 +1717,7 @@ void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmar
void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl)
{
+ lldebugs << "Saving landmark SLURL: " << slurl << llendl;
mSLURLs[asset_id] = slurl;
}
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index 76f4e18c27..e052e37393 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -63,7 +63,6 @@ extern PFNGLWEIGHTFVARBPROC glWeightfvARB;
extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB;
#endif
-static LLPointer<LLVertexBuffer> sRenderBuffer = NULL;
static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX |
LLVertexBuffer::MAP_NORMAL |
LLVertexBuffer::MAP_TEXCOORD0;
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 046360e9e9..1eb4bedfaf 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -387,7 +387,6 @@ class LLViewerMediaMuteListObserver : public LLMuteListObserver
static LLViewerMediaMuteListObserver sViewerMediaMuteListObserver;
static bool sViewerMediaMuteListObserverInitialized = false;
-static bool sInWorldMediaDisabled = false;
//////////////////////////////////////////////////////////////////////////////////////////
@@ -654,20 +653,6 @@ void LLViewerMedia::muteListChanged()
//////////////////////////////////////////////////////////////////////////////////////////
// static
-void LLViewerMedia::setInWorldMediaDisabled(bool disabled)
-{
- sInWorldMediaDisabled = disabled;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
-bool LLViewerMedia::getInWorldMediaDisabled()
-{
- return sInWorldMediaDisabled;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// static
bool LLViewerMedia::isInterestingEnough(const LLVOVolume *object, const F64 &object_interest)
{
bool result = false;
@@ -1568,7 +1553,6 @@ LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource()
bool LLViewerMedia::hasInWorldMedia()
{
- if (sInWorldMediaDisabled) return false;
impl_list::iterator iter = sViewerMediaImplList.begin();
impl_list::iterator end = sViewerMediaImplList.end();
// This should be quick, because there should be very few non-in-world-media impls
@@ -1901,7 +1885,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
}
}
- LL_WARNS_ONCE("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL;
+ LL_WARNS_ONCE("Plugin") << "plugin initialization failed for mime type: " << media_type << LL_ENDL;
LLSD args;
args["MIME_TYPE"] = media_type;
LLNotificationsUtil::add("NoPlugin", args);
@@ -3107,15 +3091,6 @@ bool LLViewerMediaImpl::isForcedUnloaded() const
return true;
}
- if(sInWorldMediaDisabled)
- {
- // When inworld media is disabled, all instances that aren't marked as "used in UI" will not be loaded.
- if(!mUsedInUI)
- {
- return true;
- }
- }
-
// If this media's class is not supposed to be shown, unload
if (!shouldShowBasedOnClass())
{
@@ -3783,12 +3758,22 @@ bool LLViewerMediaImpl::shouldShowBasedOnClass() const
// If it is attached to an avatar and the pref is off, we shouldn't show it
if (attached_to_another_avatar)
- return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING);
-
+ {
+ static LLCachedControl<bool> show_media_on_others(gSavedSettings, LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING);
+ return show_media_on_others;
+ }
if (inside_parcel)
- return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING);
+ {
+ static LLCachedControl<bool> show_media_within_parcel(gSavedSettings, LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING);
+
+ return show_media_within_parcel;
+ }
else
- return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING);
+ {
+ static LLCachedControl<bool> show_media_outside_parcel(gSavedSettings, LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING);
+
+ return show_media_outside_parcel;
+ }
}
//////////////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 15dcda59cf..fff5b3fc08 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -112,9 +112,6 @@ public:
static F32 getVolume();
static void muteListChanged();
- static void setInWorldMediaDisabled(bool disabled);
- static bool getInWorldMediaDisabled();
-
static bool isInterestingEnough(const LLVOVolume* object, const F64 &object_interest);
// Returns the priority-sorted list of all media impls.
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 06f9d931f8..e91a1d6afa 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -7338,12 +7338,6 @@ class LLToolsUseSelectionForGrid : public view_listener_t
} func;
LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func);
LLSelectMgr::getInstance()->setGridMode(GRID_MODE_REF_OBJECT);
-
- LLFloaterBuildOptions* build_options_floater = LLFloaterReg::getTypedInstance<LLFloaterBuildOptions>("build_options");
- if (build_options_floater && build_options_floater->getVisible())
- {
- build_options_floater->setGridMode(GRID_MODE_REF_OBJECT);
- }
return true;
}
};
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 99d08087d4..e2f9b1f1a0 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -183,7 +183,7 @@ void LLFilePickerThread::clearDead()
#if LL_WINDOWS
static std::string SOUND_EXTENSIONS = "wav";
static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg png";
-static std::string ANIM_EXTENSIONS = "bvh";
+static std::string ANIM_EXTENSIONS = "bvh anim";
#ifdef _CORY_TESTING
static std::string GEOMETRY_EXTENSIONS = "slg";
#endif
@@ -385,7 +385,14 @@ class LLFileUploadAnim : public view_listener_t
const std::string filename = upload_pick((void*)LLFilePicker::FFLOAD_ANIM);
if (!filename.empty())
{
- LLFloaterReg::showInstance("upload_anim", LLSD(filename));
+ if (filename.rfind(".anim") != std::string::npos)
+ {
+ LLFloaterReg::showInstance("upload_anim_anim", LLSD(filename));
+ }
+ else
+ {
+ LLFloaterReg::showInstance("upload_anim_bvh", LLSD(filename));
+ }
}
return true;
}
@@ -527,8 +534,22 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
FALSE))
{
gViewerWindow->playSnapshotAnimAndSound();
-
- LLPointer<LLImageFormatted> formatted = new LLImagePNG;
+ LLPointer<LLImageFormatted> formatted;
+ LLFloaterSnapshot::ESnapshotFormat fmt = (LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");
+ switch (fmt)
+ {
+ case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
+ formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality"));
+ break;
+ default:
+ llwarns << "Unknown local snapshot format: " << fmt << llendl;
+ case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
+ formatted = new LLImagePNG;
+ break;
+ case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
+ formatted = new LLImageBMP;
+ break;
+ }
formatted->enableOverSize() ;
formatted->encode(raw, 0);
formatted->disableOverSize() ;
@@ -785,6 +806,11 @@ LLUUID upload_new_resource(
upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args);
return LLUUID();
}
+ else if (exten == "anim")
+ {
+ asset_type = LLAssetType::AT_ANIMATION;
+ filename = src_filename;
+ }
else
{
// Unknown extension
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 8905efed75..05f1be5de5 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -135,6 +135,7 @@ extern BOOL gDebugClicks;
// function prototypes
bool check_offer_throttle(const std::string& from_name, bool check_only);
+bool check_asset_previewable(const LLAssetType::EType asset_type);
static void process_money_balance_reply_extended(LLMessageSystem* msg);
//inventory offer throttle globals
@@ -1147,7 +1148,18 @@ bool check_offer_throttle(const std::string& from_name, bool check_only)
}
}
}
-
+
+// Return "true" if we have a preview method for that asset type, "false" otherwise
+bool check_asset_previewable(const LLAssetType::EType asset_type)
+{
+ return (asset_type == LLAssetType::AT_NOTECARD) ||
+ (asset_type == LLAssetType::AT_LANDMARK) ||
+ (asset_type == LLAssetType::AT_TEXTURE) ||
+ (asset_type == LLAssetType::AT_ANIMATION) ||
+ (asset_type == LLAssetType::AT_SCRIPT) ||
+ (asset_type == LLAssetType::AT_SOUND);
+}
+
void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_name)
{
for (uuid_vec_t::const_iterator obj_iter = objects.begin();
@@ -1171,7 +1183,7 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam
// Either an inventory item or a category.
const LLInventoryItem* item = dynamic_cast<const LLInventoryItem*>(obj);
- if (item)
+ if (item && check_asset_previewable(asset_type))
{
////////////////////////////////////////////////////////////////////////////////
// Special handling for various types.
@@ -1246,6 +1258,7 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam
LLFloaterReg::showInstance("preview_sound", LLSD(obj_id), take_focus);
break;
default:
+ LL_DEBUGS("Messaging") << "No preview method for previewable asset type : " << LLAssetType::lookupHumanReadable(asset_type) << LL_ENDL;
break;
}
}
@@ -2360,8 +2373,15 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;
bool mute_im = is_muted;
- if(accept_im_from_only_friend&&!is_friend)
+ if (accept_im_from_only_friend && !is_friend)
{
+ if (!gIMMgr->isNonFriendSessionNotified(session_id))
+ {
+ std::string message = LLTrans::getString("IM_unblock_only_groups_friends");
+ gIMMgr->addMessage(session_id, from_id, name, message);
+ gIMMgr->addNotifiedNonFriendSessionID(session_id);
+ }
+
mute_im = true;
}
if (!mute_im || is_linden)
@@ -5816,6 +5836,16 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)
S32 orig = notification["payload"]["questions"].asInteger();
S32 new_questions = orig;
+ if (response["Details"])
+ {
+ // respawn notification...
+ LLNotificationsUtil::add(notification["name"], notification["substitutions"], notification["payload"]);
+
+ // ...with description on top
+ LLNotificationsUtil::add("DebitPermissionDetails");
+ return false;
+ }
+
// check whether permissions were granted or denied
BOOL allowed = TRUE;
// the "yes/accept" button is the first button in the template, making it button 0
@@ -5873,14 +5903,6 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)
gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(item_id));
}
- if (response["Details"])
- {
- // respawn notification...
- LLNotificationsUtil::add(notification["name"], notification["substitutions"], notification["payload"]);
-
- // ...with description on top
- LLNotificationsUtil::add("DebitPermissionDetails");
- }
return false;
}
static LLNotificationFunctorRegistration script_question_cb_reg_1("ScriptQuestion", script_question_cb);
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index d8acd99953..46bfb2dad0 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -35,6 +35,7 @@
#include "message.h"
#include "stdenums.h"
#include "llnotifications.h"
+#include "llextendedstatus.h"
//
// Forward declarations
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 5de363e03c..6db2138688 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -730,7 +730,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
vector< pair<string, S32> > shaders;
shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
- shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+ shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
shaders.push_back( make_pair( "windlight/atmosphericsHelpersV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
shaders.push_back( make_pair( "lighting/lightFuncV.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
shaders.push_back( make_pair( "lighting/sumLightsV.glsl", sum_lights_class ) );
@@ -1102,19 +1102,25 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader";
+ gDeferredSkinnedAlphaProgram.mFeatures.atmosphericHelpers = true;
gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true;
gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true;
gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true;
gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true;
- gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true;
- gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true;
+ gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = false;
+ gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = false;
gDeferredSkinnedAlphaProgram.mFeatures.isAlphaLighting = true;
gDeferredSkinnedAlphaProgram.mFeatures.disableTextureIndex = true;
gDeferredSkinnedAlphaProgram.mShaderFiles.clear();
gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+
success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL);
+
+ // Hack to include uniforms for lighting without linking in lighting file
+ gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true;
+ gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true;
}
if (success)
@@ -1231,11 +1237,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
gDeferredAlphaProgram.mName = "Deferred Alpha Shader";
- gDeferredAlphaProgram.mFeatures.calculatesLighting = true;
+ gDeferredAlphaProgram.mFeatures.atmosphericHelpers = true;
+ gDeferredAlphaProgram.mFeatures.calculatesLighting = false;
gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true;
gDeferredAlphaProgram.mFeatures.hasGamma = true;
gDeferredAlphaProgram.mFeatures.hasAtmospherics = true;
- gDeferredAlphaProgram.mFeatures.hasLighting = true;
+ gDeferredAlphaProgram.mFeatures.hasLighting = false;
gDeferredAlphaProgram.mFeatures.isAlphaLighting = true;
gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
@@ -1251,7 +1258,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+
success = gDeferredAlphaProgram.createShader(NULL, NULL);
+
+ // Hack
+ gDeferredAlphaProgram.mFeatures.calculatesLighting = true;
+ gDeferredAlphaProgram.mFeatures.hasLighting = true;
}
if (success)
@@ -1394,19 +1406,24 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
gDeferredAvatarAlphaProgram.mName = "Avatar Alpha Shader";
+ gDeferredAvatarAlphaProgram.mFeatures.atmosphericHelpers = true;
gDeferredAvatarAlphaProgram.mFeatures.hasSkinning = true;
- gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true;
+ gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = false;
gDeferredAvatarAlphaProgram.mFeatures.calculatesAtmospherics = true;
gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true;
gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true;
- gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true;
+ gDeferredAvatarAlphaProgram.mFeatures.hasLighting = false;
gDeferredAvatarAlphaProgram.mFeatures.isAlphaLighting = true;
gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true;
gDeferredAvatarAlphaProgram.mShaderFiles.clear();
gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedNoColorF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+
success = gDeferredAvatarAlphaProgram.createShader(NULL, &mAvatarUniforms);
+
+ gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true;
+ gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true;
}
if (success)
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index b41ed00f17..99102309a1 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -187,7 +187,7 @@ public:
else
{
width = EMBEDDED_ITEM_LABEL_PADDING + mImage->getWidth() + mStyle->getFont()->getWidth(mLabel.c_str());
- height = llmax(mImage->getHeight(), llceil(mStyle->getFont()->getLineHeight()));
+ height = llmax(mImage->getHeight(), mStyle->getFont()->getLineHeight());
}
return false;
}
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 2d837b3df8..8750b3b1f2 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -27,9 +27,6 @@
#include "llviewerprecompiledheaders.h"
#include "llviewerwindow.h"
-#if LL_WINDOWS
-#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
-#endif
// system library includes
#include <stdio.h>
@@ -49,7 +46,6 @@
#include "llviewquery.h"
#include "llxmltree.h"
#include "llslurl.h"
-//#include "llviewercamera.h"
#include "llrender.h"
#include "llvoiceclient.h" // for push-to-talk button handling
@@ -616,7 +612,7 @@ public:
addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount,
LLMeshRepository::sHTTPRetryCount));
ypos += y_inc;
-
+
addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, LLMeshRepository::sLODProcessing));
ypos += y_inc;
@@ -1556,14 +1552,14 @@ LLViewerWindow::LLViewerWindow(const Params& p)
mResDirty(false),
mStatesDirty(false),
mCurrResolutionIndex(0),
+ mProgressView(NULL)
+{
// gKeyboard is still NULL, so it doesn't do LLWindowListener any good to
// pass its value right now. Instead, pass it a nullary function that
// will, when we later need it, return the value of gKeyboard.
// boost::lambda::var() constructs such a functor on the fly.
- mWindowListener(new LLWindowListener(this, boost::lambda::var(gKeyboard))),
- mViewerWindowListener(new LLViewerWindowListener(this)),
- mProgressView(NULL)
-{
+ mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard)));
+ mViewerWindowListener.reset(new LLViewerWindowListener(this));
LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));
LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"));
@@ -1989,12 +1985,12 @@ void LLViewerWindow::shutdownViews()
gMorphView->setVisible(FALSE);
}
llinfos << "Global views cleaned." << llendl ;
-
+
// DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open
// will crump with LL_ERRS.
LLModalDialog::shutdownModals();
llinfos << "LLModalDialog shut down." << llendl;
-
+
// destroy the nav bar, not currently part of gViewerWindow
// *TODO: Make LLNavigationBar part of gViewerWindow
if (LLNavigationBar::instanceExists())
@@ -2002,17 +1998,17 @@ void LLViewerWindow::shutdownViews()
delete LLNavigationBar::getInstance();
}
llinfos << "LLNavigationBar destroyed." << llendl ;
-
+
// destroy menus after instantiating navbar above, as it needs
// access to gMenuHolder
cleanup_menus();
llinfos << "menus destroyed." << llendl ;
-
+
// Delete all child views.
delete mRootView;
mRootView = NULL;
llinfos << "RootView deleted." << llendl ;
-
+
// Automatically deleted as children of mRootView. Fix the globals.
gStatusBar = NULL;
gIMMgr = NULL;
@@ -2391,7 +2387,7 @@ void LLViewerWindow::draw()
gGL.matrixMode(LLRender::MM_MODELVIEW);
LLUI::pushMatrix();
- LLUI::translate( (F32) screen_x, (F32) screen_y, 0.f);
+ LLUI::translate( (F32) screen_x, (F32) screen_y);
top_ctrl->draw();
LLUI::popMatrix();
}
@@ -3199,12 +3195,6 @@ void LLViewerWindow::updateLayout()
//gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible());
}
- LLFloaterBuildOptions* build_options_floater = LLFloaterReg::findTypedInstance<LLFloaterBuildOptions>("build_options");
- if (build_options_floater && build_options_floater->getVisible())
- {
- build_options_floater->updateGridMode();
- }
-
// Always update console
if(gConsole)
{
@@ -4122,14 +4112,11 @@ void LLViewerWindow::resetSnapshotLoc()
void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
{
LLCoordWindow size;
+ LLCoordWindow new_size(new_width, new_height);
gViewerWindow->getWindow()->getSize(&size);
- if ( size.mX != new_width
- || size.mY != new_height)
+ if ( size != new_size )
{
- LLCoordWindow new_size(new_width, new_height);
- LLCoordScreen screen_size;
- gViewerWindow->getWindow()->convertCoords(new_size, &screen_size);
- gViewerWindow->getWindow()->setSize(screen_size);
+ gViewerWindow->getWindow()->setSize(new_size.convert());
}
}
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 15786b5dd0..c505936097 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -366,9 +366,9 @@ BOOL LLVOAvatarSelf::buildMenus()
item_params.label = sub_piemenu_name;
}
item_params.name =(item_params.label );
- item_params.on_click.function_name = "Attachment.Detach";
+ item_params.on_click.function_name = "Attachment.DetachFromPoint";
item_params.on_click.parameter = iter->first;
- item_params.on_enable.function_name = "Attachment.EnableDetach";
+ item_params.on_enable.function_name = "Attachment.PointFilled";
item_params.on_enable.parameter = iter->first;
LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index e9db37821b..312034022e 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -342,7 +342,7 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
blue_density = LLColor3();
blue_horizon = LLColor3();
haze_density = 0.f;
- haze_horizon = LLColor3();
+ haze_horizon = 1.f;
density_multiplier = 0.f;
max_y = 0.f;
glow = LLColor3();
@@ -651,17 +651,17 @@ void LLVOSky::initAtmospherics(void)
sunlight_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("sunlight_color", error));
ambient = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("ambient", error));
//lightnorm = LLWLParamManager::getInstance()->mCurParams.getVector("lightnorm", error);
- gamma = LLWLParamManager::getInstance()->mCurParams.getVector("gamma", error)[0];
+ gamma = LLWLParamManager::getInstance()->mCurParams.getFloat("gamma", error);
blue_density = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_density", error));
blue_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_horizon", error));
- haze_density = LLWLParamManager::getInstance()->mCurParams.getVector("haze_density", error)[0];
- haze_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("haze_horizon", error));
- density_multiplier = LLWLParamManager::getInstance()->mCurParams.getVector("density_multiplier", error)[0];
- max_y = LLWLParamManager::getInstance()->mCurParams.getVector("max_y", error)[0];
+ haze_density = LLWLParamManager::getInstance()->mCurParams.getFloat("haze_density", error);
+ haze_horizon = LLWLParamManager::getInstance()->mCurParams.getFloat("haze_horizon", error);
+ density_multiplier = LLWLParamManager::getInstance()->mCurParams.getFloat("density_multiplier", error);
+ max_y = LLWLParamManager::getInstance()->mCurParams.getFloat("max_y", error);
glow = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("glow", error));
- cloud_shadow = LLWLParamManager::getInstance()->mCurParams.getVector("cloud_shadow", error)[0];
+ cloud_shadow = LLWLParamManager::getInstance()->mCurParams.getFloat("cloud_shadow", error);
cloud_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_color", error));
- cloud_scale = LLWLParamManager::getInstance()->mCurParams.getVector("cloud_scale", error)[0];
+ cloud_scale = LLWLParamManager::getInstance()->mCurParams.getFloat("cloud_scale", error);
cloud_pos_density1 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density1", error));
cloud_pos_density2 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density2", error));
@@ -825,7 +825,7 @@ void LLVOSky::calcSkyColorWLVert(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLCo
// Haze color above cloud
vary_HazeColor = (blue_horizon * blue_weight * (sunlight + ambient)
- + componentMult(haze_horizon.mV[0] * haze_weight, sunlight * temp2.mV[0] + ambient)
+ + componentMult(haze_horizon * haze_weight, sunlight * temp2.mV[0] + ambient)
);
// Increase ambient when there are more clouds
@@ -836,7 +836,7 @@ void LLVOSky::calcSkyColorWLVert(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLCo
// Haze color below cloud
LLColor3 additiveColorBelowCloud = (blue_horizon * blue_weight * (sunlight + tmpAmbient)
- + componentMult(haze_horizon.mV[0] * haze_weight, sunlight * temp2.mV[0] + tmpAmbient)
+ + componentMult(haze_horizon * haze_weight, sunlight * temp2.mV[0] + tmpAmbient)
);
// Final atmosphere additive
@@ -1002,7 +1002,7 @@ void LLVOSky::calcAtmospherics(void)
//haze color
vary_HazeColor =
(blue_horizon * blue_weight * (sunlight*(1.f - cloud_shadow) + tmpAmbient)
- + componentMult(haze_horizon.mV[0] * haze_weight, sunlight*(1.f - cloud_shadow) * temp2.mV[0] + tmpAmbient)
+ + componentMult(haze_horizon * haze_weight, sunlight*(1.f - cloud_shadow) * temp2.mV[0] + tmpAmbient)
);
//brightness of surface both sunlight and ambient
diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h
index d3a42583ea..6e6898d80a 100644
--- a/indra/newview/llvosky.h
+++ b/indra/newview/llvosky.h
@@ -410,7 +410,7 @@ public:
LLColor3 blue_density;
LLColor3 blue_horizon;
F32 haze_density;
- LLColor3 haze_horizon;
+ F32 haze_horizon;
F32 density_multiplier;
F32 max_y;
LLColor3 glow;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 03d4c51aff..438d578ac5 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4939,6 +4939,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
fullbright = TRUE;
}
+ if (hud_group)
+ { //all hud attachments are fullbright
+ fullbright = TRUE;
+ }
+
const LLTextureEntry* te = facep->getTextureEntry();
tex = facep->getTexture();
@@ -4968,7 +4973,6 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
}
}
else if (gPipeline.canUseVertexShaders()
- && group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD
&& LLPipeline::sRenderBump
&& te->getShiny())
{ //shiny
@@ -5033,9 +5037,12 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
}
}
- //not sure why this is here -- shiny HUD attachments maybe? -- davep 5/11/2010
- if (!is_alpha && te->getShiny() && LLPipeline::sRenderBump)
- {
+
+ if (!gPipeline.canUseVertexShaders() &&
+ !is_alpha &&
+ te->getShiny() &&
+ LLPipeline::sRenderBump)
+ { //shiny as an extra pass when shaders are disabled
registerFace(group, facep, LLRenderPass::PASS_SHINY);
}
}
diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp
index 20b34637b8..e386112334 100644
--- a/indra/newview/llwaterparammanager.cpp
+++ b/indra/newview/llwaterparammanager.cpp
@@ -194,7 +194,7 @@ void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader)
shader->uniform4fv("waterPlane", 1, mWaterPlane.mV);
shader->uniform1f("waterFogDensity", getFogDensity());
shader->uniform1f("waterFogKS", mWaterFogKS);
- shader->uniform4f("distance_multiplier", 0, 0, 0, 0);
+ shader->uniform1f("distance_multiplier", 0);
}
}
diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp
index 55608a059f..49d9d44d74 100644
--- a/indra/newview/llwlparammanager.cpp
+++ b/indra/newview/llwlparammanager.cpp
@@ -64,7 +64,6 @@
LLWLParamManager::LLWLParamManager() :
//set the defaults for the controls
- // index is from sWLUniforms in pipeline.cpp line 979
/// Sun Delta Terrain tweak variables.
mSunDeltaYaw(180.0f),
@@ -72,10 +71,10 @@ LLWLParamManager::LLWLParamManager() :
mWLGamma(1.0f, "gamma"),
mBlueHorizon(0.25f, 0.25f, 1.0f, 1.0f, "blue_horizon", "WLBlueHorizon"),
- mHazeDensity(1.0f, 1.0f, 1.0f, 0.5f, "haze_density"),
+ mHazeDensity(1.0f, "haze_density"),
mBlueDensity(0.25f, 0.25f, 0.25f, 1.0f, "blue_density", "WLBlueDensity"),
mDensityMult(1.0f, "density_multiplier", 1000),
- mHazeHorizon(1.0f, 1.0f, 1.0f, 0.5f, "haze_horizon"),
+ mHazeHorizon(1.0f, "haze_horizon"),
mMaxAlt(4000.0f, "max_y"),
// Lighting
diff --git a/indra/newview/llwlparammanager.h b/indra/newview/llwlparammanager.h
index bc984b9126..72422500fc 100644
--- a/indra/newview/llwlparammanager.h
+++ b/indra/newview/llwlparammanager.h
@@ -102,9 +102,8 @@ struct WLFloatControl {
{
}
- inline WLFloatControl & operator = (LLVector4 const & val) {
- x = val.mV[0];
-
+ inline WLFloatControl & operator = (F32 val) {
+ x = val;
return *this;
}
@@ -340,10 +339,10 @@ public:
/// Atmospherics
WLColorControl mBlueHorizon;
- WLColorControl mHazeDensity;
+ WLFloatControl mHazeDensity;
WLColorControl mBlueDensity;
WLFloatControl mDensityMult;
- WLColorControl mHazeHorizon;
+ WLFloatControl mHazeHorizon;
WLFloatControl mMaxAlt;
/// Lighting
diff --git a/indra/newview/llwlparamset.cpp b/indra/newview/llwlparamset.cpp
index 5bb7025031..b04d30db55 100644
--- a/indra/newview/llwlparamset.cpp
+++ b/indra/newview/llwlparamset.cpp
@@ -41,33 +41,7 @@
LLWLParamSet::LLWLParamSet(void) :
mName("Unnamed Preset"),
mCloudScrollXOffset(0.f), mCloudScrollYOffset(0.f)
-{
-/* REMOVE or init the LLSD
- const std::map<std::string, LLVector4>::value_type hardcodedPreset[] = {
- std::make_pair("lightnorm", LLVector4(0.f, 0.707f, -0.707f, 0.f)),
- std::make_pair("sunlight_color", LLVector4(0.6f, 0.6f, 2.83f, 2.27f)),
- std::make_pair("ambient", LLVector4(0.27f, 0.33f, 0.44f, 1.19f)),
- std::make_pair("blue_horizon", LLVector4(0.3f, 0.4f, 0.9f, 1.f)),
- std::make_pair("blue_density", LLVector4(0.3f, 0.4f, 0.8f, 1.f)),
- std::make_pair("haze_horizon", LLVector4(0.6f, 0.6f, 0.6f, 1.f)),
- std::make_pair("haze_density", LLVector4(0.3f, 0.3f, 0.3f, 1.f)),
- std::make_pair("cloud_shadow", LLVector4(0.f, 0.f, 0.f, 0.f)),
- std::make_pair("density_multiplier", LLVector4(0.001f, 0.001f, 0.001f, 0.001f)),
- std::make_pair("distance_multiplier", LLVector4(1.f, 1.f, 1.f, 1.f)),
- std::make_pair("max_y", LLVector4(600.f, 600.f, 600.f, 0.f)),
- std::make_pair("glow", LLVector4(15.f, 0.001f, -0.03125f, 0.f)),
- std::make_pair("cloud_color", LLVector4(0.0f, 0.0f, 0.0f, 0.0f)),
- std::make_pair("cloud_pos_density1", LLVector4(0.f, 0.f, 0.f, 1.f)),
- std::make_pair("cloud_pos_density2", LLVector4(0.f, 0.f, 0.f, 1.f)),
- std::make_pair("cloud_scale", LLVector4(0.42f, 0.f, 0.f, 1.f)),
- std::make_pair("gamma", LLVector4(2.0f, 2.0f, 2.0f, 0.0f)),
- };
- std::map<std::string, LLVector4>::value_type const * endHardcodedPreset =
- hardcodedPreset + LL_ARRAY_SIZE(hardcodedPreset);
-
- mParamValues.insert(hardcodedPreset, endHardcodedPreset);
-*/
-}
+{}
static LLFastTimer::DeclareTimer FTM_WL_PARAM_UPDATE("WL Param Update");
@@ -79,55 +53,78 @@ void LLWLParamSet::update(LLGLSLShader * shader) const
i != mParamValues.endMap();
++i)
{
-
-
const std::string& param = i->first;
- if( param == "star_brightness" || param == "preset_num" || param == "sun_angle" ||
+ if (param == "star_brightness" || param == "preset_num" || param == "sun_angle" ||
param == "east_angle" || param == "enable_cloud_scroll" ||
param == "cloud_scroll_rate" || param == "lightnorm" )
{
continue;
}
- if(param == "cloud_pos_density1")
+ if (param == "cloud_pos_density1")
{
LLVector4 val;
val.mV[0] = F32(i->second[0].asReal()) + mCloudScrollXOffset;
val.mV[1] = F32(i->second[1].asReal()) + mCloudScrollYOffset;
val.mV[2] = (F32) i->second[2].asReal();
val.mV[3] = (F32) i->second[3].asReal();
+
stop_glerror();
shader->uniform4fv(param, 1, val.mV);
stop_glerror();
- }
+ }
+ else if (param == "cloud_scale" || param == "cloud_shadow" ||
+ param == "density_multiplier" || param == "distance_multiplier" ||
+ param == "haze_density" || param == "haze_horizon" ||
+ param == "max_y" )
+ {
+ F32 val = (F32) i->second[0].asReal();
+
+ stop_glerror();
+ shader->uniform1f(param, val);
+ stop_glerror();
+ }
else // param is the uniform name
{
- LLVector4 val;
-
// handle all the different cases
- if(i->second.isArray() && i->second.size() == 4)
+ if (i->second.isArray() && i->second.size() == 4)
{
+ LLVector4 val;
+
val.mV[0] = (F32) i->second[0].asReal();
val.mV[1] = (F32) i->second[1].asReal();
val.mV[2] = (F32) i->second[2].asReal();
val.mV[3] = (F32) i->second[3].asReal();
+
+ stop_glerror();
+ shader->uniform4fv(param, 1, val.mV);
+ stop_glerror();
}
- else if(i->second.isReal())
+ else if (i->second.isReal())
{
- val.mV[0] = (F32) i->second.asReal();
+ F32 val = (F32) i->second.asReal();
+
+ stop_glerror();
+ shader->uniform1f(param, val);
+ stop_glerror();
}
- else if(i->second.isInteger())
+ else if (i->second.isInteger())
{
- val.mV[0] = (F32) i->second.asReal();
+ S32 val = (S32) i->second.asInteger();
+
+ stop_glerror();
+ shader->uniform1i(param, val);
+ stop_glerror();
}
- else if(i->second.isBoolean())
+ else if (i->second.isBoolean())
{
- val.mV[0] = i->second.asBoolean();
+ S32 val = (i->second.asBoolean() ? 1 : 0);
+
+ stop_glerror();
+ shader->uniform1i(param, val);
+ stop_glerror();
}
- stop_glerror();
- shader->uniform4fv(param, 1, val.mV);
- stop_glerror();
}
}
}
@@ -148,7 +145,8 @@ void LLWLParamSet::set(const std::string& paramName, float x)
}
}
-void LLWLParamSet::set(const std::string& paramName, float x, float y) {
+void LLWLParamSet::set(const std::string& paramName, float x, float y)
+{
mParamValues[paramName][0] = x;
mParamValues[paramName][1] = y;
}
@@ -194,7 +192,6 @@ void LLWLParamSet::set(const std::string& paramName, const LLColor4 & val)
LLVector4 LLWLParamSet::getVector(const std::string& paramName, bool& error)
{
-
// test to see if right type
LLSD cur_val = mParamValues.get(paramName);
if (!cur_val.isArray())
@@ -215,7 +212,6 @@ LLVector4 LLWLParamSet::getVector(const std::string& paramName, bool& error)
F32 LLWLParamSet::getFloat(const std::string& paramName, bool& error)
{
-
// test to see if right type
LLSD cur_val = mParamValues.get(paramName);
if (cur_val.isArray() && cur_val.size() != 0)
@@ -234,8 +230,6 @@ F32 LLWLParamSet::getFloat(const std::string& paramName, bool& error)
return 0;
}
-
-
void LLWLParamSet::setSunAngle(float val)
{
// keep range 0 - 2pi
@@ -263,7 +257,6 @@ void LLWLParamSet::setEastAngle(float val)
mParamValues["east_angle"] = val;
}
-
void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight)
{
// set up the iterators
@@ -282,7 +275,6 @@ void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight)
// Iterate through values
for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter)
{
-
// If param exists in both src and dest, set the holder variables, otherwise skip
if(src.mParamValues.has(iter->first) && dest.mParamValues.has(iter->first))
{
diff --git a/indra/newview/llwlparamset.h b/indra/newview/llwlparamset.h
index 3c44ed3bb8..b087119dd5 100644
--- a/indra/newview/llwlparamset.h
+++ b/indra/newview/llwlparamset.h
@@ -110,7 +110,7 @@ public:
/// \param error A flag to set if it's not the proper return type
LLVector4 getVector(const std::string& paramName, bool& error);
- /// Get an integer parameter
+ /// Get a float parameter
/// \param paramName The name of the parameter to set.
/// \param error A flag to set if it's not the proper return type
F32 getFloat(const std::string& paramName, bool& error);
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 9fd77546eb..e508f768b4 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -1,1097 +1,1097 @@
-/**
- * @file llworld.cpp
- * @brief Initial test structure to organize viewer regions
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llworld.h"
-#include "llrender.h"
-
-#include "indra_constants.h"
-#include "llstl.h"
-
-#include "llagent.h"
-#include "llviewercontrol.h"
-#include "lldrawpool.h"
-#include "llglheaders.h"
-#include "llhttpnode.h"
-#include "llregionhandle.h"
-#include "llsurface.h"
-#include "lltrans.h"
-#include "llviewercamera.h"
-#include "llviewertexture.h"
-#include "llviewertexturelist.h"
-#include "llviewernetwork.h"
-#include "llviewerobjectlist.h"
-#include "llviewerparceloverlay.h"
-#include "llviewerregion.h"
-#include "llviewerstats.h"
-#include "llvlcomposition.h"
-#include "llvoavatar.h"
-#include "llvocache.h"
-#include "llvowater.h"
-#include "message.h"
-#include "pipeline.h"
-#include "llappviewer.h" // for do_disconnect()
-#include "llfloaterpathfindingconsole.h"
-
-#include <deque>
-#include <queue>
-#include <map>
-#include <cstring>
-
-
-//
-// Globals
-//
-U32 gAgentPauseSerialNum = 0;
-
-//
-// Constants
-//
-const S32 MAX_NUMBER_OF_CLOUDS = 750;
-const S32 WORLD_PATCH_SIZE = 16;
-
-extern LLColor4U MAX_WATER_COLOR;
-
-const U32 LLWorld::mWidth = 256;
-
-// meters/point, therefore mWidth * mScale = meters per edge
-const F32 LLWorld::mScale = 1.f;
-
-const F32 LLWorld::mWidthInMeters = mWidth * mScale;
-
-//
-// Functions
-//
-
-// allocate the stack
-LLWorld::LLWorld() :
- mLandFarClip(DEFAULT_FAR_PLANE),
- mLastPacketsIn(0),
- mLastPacketsOut(0),
- mLastPacketsLost(0),
- mSpaceTimeUSec(0)
-{
- for (S32 i = 0; i < 8; i++)
- {
- mEdgeWaterObjects[i] = NULL;
- }
-
- LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,4);
- U8 *default_texture = raw->getData();
- *(default_texture++) = MAX_WATER_COLOR.mV[0];
- *(default_texture++) = MAX_WATER_COLOR.mV[1];
- *(default_texture++) = MAX_WATER_COLOR.mV[2];
- *(default_texture++) = MAX_WATER_COLOR.mV[3];
-
- mDefaultWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
- gGL.getTexUnit(0)->bind(mDefaultWaterTexturep);
- mDefaultWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
-
-}
-
-
-void LLWorld::destroyClass()
-{
- mHoleWaterObjects.clear();
- gObjectList.destroy();
- for(region_list_t::iterator region_it = mRegionList.begin(); region_it != mRegionList.end(); )
- {
- LLViewerRegion* region_to_delete = *region_it++;
- removeRegion(region_to_delete->getHost());
- }
- if(LLVOCache::hasInstance())
- {
- LLVOCache::getInstance()->destroyClass() ;
- }
- LLViewerPartSim::getInstance()->destroyClass();
-
- mDefaultWaterTexturep = NULL ;
- for (S32 i = 0; i < 8; i++)
- {
- mEdgeWaterObjects[i] = NULL;
- }
-}
-
-
-LLViewerRegion* LLWorld::addRegion(const U64 &region_handle, const LLHost &host)
-{
- LLMemType mt(LLMemType::MTYPE_REGIONS);
- llinfos << "Add region with handle: " << region_handle << " on host " << host << llendl;
- LLViewerRegion *regionp = getRegionFromHandle(region_handle);
- if (regionp)
- {
- llinfos << "Region exists, removing it " << llendl;
- LLHost old_host = regionp->getHost();
- // region already exists!
- if (host == old_host && regionp->isAlive())
- {
- // This is a duplicate for the same host and it's alive, don't bother.
- return regionp;
- }
-
- if (host != old_host)
- {
- llwarns << "LLWorld::addRegion exists, but old host " << old_host
- << " does not match new host " << host << llendl;
- }
- if (!regionp->isAlive())
- {
- llwarns << "LLWorld::addRegion exists, but isn't alive" << llendl;
- }
-
- // Kill the old host, and then we can continue on and add the new host. We have to kill even if the host
- // matches, because all the agent state for the new camera is completely different.
- removeRegion(old_host);
- }
-
- U32 iindex = 0;
- U32 jindex = 0;
- from_region_handle(region_handle, &iindex, &jindex);
- S32 x = (S32)(iindex/mWidth);
- S32 y = (S32)(jindex/mWidth);
- llinfos << "Adding new region (" << x << ":" << y << ")" << llendl;
- llinfos << "Host: " << host << llendl;
-
- LLVector3d origin_global;
-
- origin_global = from_region_handle(region_handle);
-
- regionp = new LLViewerRegion(region_handle,
- host,
- mWidth,
- WORLD_PATCH_SIZE,
- getRegionWidthInMeters() );
- if (!regionp)
- {
- llerrs << "Unable to create new region!" << llendl;
- }
-
- mRegionList.push_back(regionp);
- mActiveRegionList.push_back(regionp);
- mCulledRegionList.push_back(regionp);
-
-
- // Find all the adjacent regions, and attach them.
- // Generate handles for all of the adjacent regions, and attach them in the correct way.
- // connect the edges
- F32 adj_x = 0.f;
- F32 adj_y = 0.f;
- F32 region_x = 0.f;
- F32 region_y = 0.f;
- U64 adj_handle = 0;
-
- F32 width = getRegionWidthInMeters();
-
- LLViewerRegion *neighborp;
- from_region_handle(region_handle, &region_x, &region_y);
-
- // Iterate through all directions, and connect neighbors if there.
- S32 dir;
- for (dir = 0; dir < 8; dir++)
- {
- adj_x = region_x + width * gDirAxes[dir][0];
- adj_y = region_y + width * gDirAxes[dir][1];
- to_region_handle(adj_x, adj_y, &adj_handle);
-
- neighborp = getRegionFromHandle(adj_handle);
- if (neighborp)
- {
- //llinfos << "Connecting " << region_x << ":" << region_y << " -> " << adj_x << ":" << adj_y << llendl;
- regionp->connectNeighbor(neighborp, dir);
- }
- }
-
- updateWaterObjects();
-
- return regionp;
-}
-
-
-void LLWorld::removeRegion(const LLHost &host)
-{
- F32 x, y;
-
- LLViewerRegion *regionp = getRegion(host);
- if (!regionp)
- {
- llwarns << "Trying to remove region that doesn't exist!" << llendl;
- return;
- }
-
- if (regionp == gAgent.getRegion())
- {
- for (region_list_t::iterator iter = mRegionList.begin();
- iter != mRegionList.end(); ++iter)
- {
- LLViewerRegion* reg = *iter;
- llwarns << "RegionDump: " << reg->getName()
- << " " << reg->getHost()
- << " " << reg->getOriginGlobal()
- << llendl;
- }
-
- llwarns << "Agent position global " << gAgent.getPositionGlobal()
- << " agent " << gAgent.getPositionAgent()
- << llendl;
-
- llwarns << "Regions visited " << gAgent.getRegionsVisited() << llendl;
-
- llwarns << "gFrameTimeSeconds " << gFrameTimeSeconds << llendl;
-
- llwarns << "Disabling region " << regionp->getName() << " that agent is in!" << llendl;
- LLAppViewer::instance()->forceDisconnect(LLTrans::getString("YouHaveBeenDisconnected"));
-
- regionp->saveObjectCache() ; //force to save objects here in case that the object cache is about to be destroyed.
- return;
- }
-
- from_region_handle(regionp->getHandle(), &x, &y);
- llinfos << "Removing region " << x << ":" << y << llendl;
-
- mRegionList.remove(regionp);
- mActiveRegionList.remove(regionp);
- mCulledRegionList.remove(regionp);
- mVisibleRegionList.remove(regionp);
-
- delete regionp;
-
- updateWaterObjects();
-
- //double check all objects of this region are removed.
- gObjectList.clearAllMapObjectsInRegion(regionp) ;
- //llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ;
-}
-
-
-LLViewerRegion* LLWorld::getRegion(const LLHost &host)
-{
- for (region_list_t::iterator iter = mRegionList.begin();
- iter != mRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- if (regionp->getHost() == host)
- {
- return regionp;
- }
- }
- return NULL;
-}
-
-LLViewerRegion* LLWorld::getRegionFromPosAgent(const LLVector3 &pos)
-{
- return getRegionFromPosGlobal(gAgent.getPosGlobalFromAgent(pos));
-}
-
-LLViewerRegion* LLWorld::getRegionFromPosGlobal(const LLVector3d &pos)
-{
- for (region_list_t::iterator iter = mRegionList.begin();
- iter != mRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- if (regionp->pointInRegionGlobal(pos))
- {
- return regionp;
- }
- }
- return NULL;
-}
-
-
-LLVector3d LLWorld::clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos)
-{
- if (positionRegionValidGlobal(end_pos))
- {
- return end_pos;
- }
-
- LLViewerRegion* regionp = getRegionFromPosGlobal(start_pos);
- if (!regionp)
- {
- return start_pos;
- }
-
- LLVector3d delta_pos = end_pos - start_pos;
- LLVector3d delta_pos_abs;
- delta_pos_abs.setVec(delta_pos);
- delta_pos_abs.abs();
-
- LLVector3 region_coord = regionp->getPosRegionFromGlobal(end_pos);
- F64 clip_factor = 1.0;
- F32 region_width = regionp->getWidth();
- if (region_coord.mV[VX] < 0.f)
- {
- if (region_coord.mV[VY] < region_coord.mV[VX])
- {
- // clip along y -
- clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]);
- }
- else
- {
- // clip along x -
- clip_factor = -(region_coord.mV[VX] / delta_pos_abs.mdV[VX]);
- }
- }
- else if (region_coord.mV[VX] > region_width)
- {
- if (region_coord.mV[VY] > region_coord.mV[VX])
- {
- // clip along y +
- clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY];
- }
- else
- {
- //clip along x +
- clip_factor = (region_coord.mV[VX] - region_width) / delta_pos_abs.mdV[VX];
- }
- }
- else if (region_coord.mV[VY] < 0.f)
- {
- // clip along y -
- clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]);
- }
- else if (region_coord.mV[VY] > region_width)
- {
- // clip along y +
- clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY];
- }
-
- // clamp to within region dimensions
- LLVector3d final_region_pos = LLVector3d(region_coord) - (delta_pos * clip_factor);
- final_region_pos.mdV[VX] = llclamp(final_region_pos.mdV[VX], 0.0,
- (F64)(region_width - F_ALMOST_ZERO));
- final_region_pos.mdV[VY] = llclamp(final_region_pos.mdV[VY], 0.0,
- (F64)(region_width - F_ALMOST_ZERO));
- final_region_pos.mdV[VZ] = llclamp(final_region_pos.mdV[VZ], 0.0,
- (F64)(LLWorld::getInstance()->getRegionMaxHeight() - F_ALMOST_ZERO));
- return regionp->getPosGlobalFromRegion(LLVector3(final_region_pos));
-}
-
-LLViewerRegion* LLWorld::getRegionFromHandle(const U64 &handle)
-{
- for (region_list_t::iterator iter = mRegionList.begin();
- iter != mRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- if (regionp->getHandle() == handle)
- {
- return regionp;
- }
- }
- return NULL;
-}
-
-
-void LLWorld::updateAgentOffset(const LLVector3d &offset_global)
-{
-#if 0
- for (region_list_t::iterator iter = mRegionList.begin();
- iter != mRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- regionp->setAgentOffset(offset_global);
- }
-#endif
-}
-
-
-BOOL LLWorld::positionRegionValidGlobal(const LLVector3d &pos_global)
-{
- for (region_list_t::iterator iter = mRegionList.begin();
- iter != mRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- if (regionp->pointInRegionGlobal(pos_global))
- {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-
-// Allow objects to go up to their radius underground.
-F32 LLWorld::getMinAllowedZ(LLViewerObject* object, const LLVector3d &global_pos)
-{
- F32 land_height = resolveLandHeightGlobal(global_pos);
- F32 radius = 0.5f * object->getScale().length();
- return land_height - radius;
-}
-
-
-
-LLViewerRegion* LLWorld::resolveRegionGlobal(LLVector3 &pos_region, const LLVector3d &pos_global)
-{
- LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
-
- if (regionp)
- {
- pos_region = regionp->getPosRegionFromGlobal(pos_global);
- return regionp;
- }
-
- return NULL;
-}
-
-
-LLViewerRegion* LLWorld::resolveRegionAgent(LLVector3 &pos_region, const LLVector3 &pos_agent)
-{
- LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
- LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
-
- if (regionp)
- {
- pos_region = regionp->getPosRegionFromGlobal(pos_global);
- return regionp;
- }
-
- return NULL;
-}
-
-
-F32 LLWorld::resolveLandHeightAgent(const LLVector3 &pos_agent)
-{
- LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
- return resolveLandHeightGlobal(pos_global);
-}
-
-
-F32 LLWorld::resolveLandHeightGlobal(const LLVector3d &pos_global)
-{
- LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
- if (regionp)
- {
- return regionp->getLand().resolveHeightGlobal(pos_global);
- }
- return 0.0f;
-}
-
-
-// Takes a line defined by "point_a" and "point_b" and determines the closest (to point_a)
-// point where the the line intersects an object or the land surface. Stores the results
-// in "intersection" and "intersection_normal" and returns a scalar value that represents
-// the normalized distance along the line from "point_a" to "intersection".
-//
-// Currently assumes point_a and point_b only differ in z-direction,
-// but it may eventually become more general.
-F32 LLWorld::resolveStepHeightGlobal(const LLVOAvatar* avatarp, const LLVector3d &point_a, const LLVector3d &point_b,
- LLVector3d &intersection, LLVector3 &intersection_normal,
- LLViewerObject **viewerObjectPtr)
-{
- // initialize return value to null
- if (viewerObjectPtr)
- {
- *viewerObjectPtr = NULL;
- }
-
- LLViewerRegion *regionp = getRegionFromPosGlobal(point_a);
- if (!regionp)
- {
- // We're outside the world
- intersection = 0.5f * (point_a + point_b);
- intersection_normal.setVec(0.0f, 0.0f, 1.0f);
- return 0.5f;
- }
-
- // calculate the length of the segment
- F32 segment_length = (F32)((point_a - point_b).length());
- if (0.0f == segment_length)
- {
- intersection = point_a;
- intersection_normal.setVec(0.0f, 0.0f, 1.0f);
- return segment_length;
- }
-
- // get land height
- // Note: we assume that the line is parallel to z-axis here
- LLVector3d land_intersection = point_a;
- F32 normalized_land_distance;
-
- land_intersection.mdV[VZ] = regionp->getLand().resolveHeightGlobal(point_a);
- normalized_land_distance = (F32)(point_a.mdV[VZ] - land_intersection.mdV[VZ]) / segment_length;
- intersection = land_intersection;
- intersection_normal = resolveLandNormalGlobal(land_intersection);
-
- if (avatarp && !avatarp->mFootPlane.isExactlyClear())
- {
- LLVector3 foot_plane_normal(avatarp->mFootPlane.mV);
- LLVector3 start_pt = avatarp->getRegion()->getPosRegionFromGlobal(point_a);
- // added 0.05 meters to compensate for error in foot plane reported by Havok
- F32 norm_dist_from_plane = ((start_pt * foot_plane_normal) - avatarp->mFootPlane.mV[VW]) + 0.05f;
- norm_dist_from_plane = llclamp(norm_dist_from_plane / segment_length, 0.f, 1.f);
- if (norm_dist_from_plane < normalized_land_distance)
- {
- // collided with object before land
- normalized_land_distance = norm_dist_from_plane;
- intersection = point_a;
- intersection.mdV[VZ] -= norm_dist_from_plane * segment_length;
- intersection_normal = foot_plane_normal;
- }
- else
- {
- intersection = land_intersection;
- intersection_normal = resolveLandNormalGlobal(land_intersection);
- }
- }
-
- return normalized_land_distance;
-}
-
-
-LLSurfacePatch * LLWorld::resolveLandPatchGlobal(const LLVector3d &pos_global)
-{
- // returns a pointer to the patch at this location
- LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
- if (!regionp)
- {
- return NULL;
- }
-
- return regionp->getLand().resolvePatchGlobal(pos_global);
-}
-
-
-LLVector3 LLWorld::resolveLandNormalGlobal(const LLVector3d &pos_global)
-{
- LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
- if (!regionp)
- {
- return LLVector3::z_axis;
- }
-
- return regionp->getLand().resolveNormalGlobal(pos_global);
-}
-
-
-void LLWorld::updateVisibilities()
-{
- F32 cur_far_clip = LLViewerCamera::getInstance()->getFar();
-
- // Go through the culled list and check for visible regions (region is visible if land is visible)
- for (region_list_t::iterator iter = mCulledRegionList.begin();
- iter != mCulledRegionList.end(); )
- {
- region_list_t::iterator curiter = iter++;
- LLViewerRegion* regionp = *curiter;
-
- LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN);
- if (part)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0);
- if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1]))
- {
- mCulledRegionList.erase(curiter);
- mVisibleRegionList.push_back(regionp);
- }
- }
- }
-
- // Update all of the visible regions
- for (region_list_t::iterator iter = mVisibleRegionList.begin();
- iter != mVisibleRegionList.end(); )
- {
- region_list_t::iterator curiter = iter++;
- LLViewerRegion* regionp = *curiter;
- if (!regionp->getLand().hasZData())
- {
- continue;
- }
-
- LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN);
- if (part)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0);
- if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1]))
- {
- regionp->calculateCameraDistance();
- regionp->getLand().updatePatchVisibilities(gAgent);
- }
- else
- {
- mVisibleRegionList.erase(curiter);
- mCulledRegionList.push_back(regionp);
- }
- }
- }
-
- // Sort visible regions
- mVisibleRegionList.sort(LLViewerRegion::CompareDistance());
-
- LLViewerCamera::getInstance()->setFar(cur_far_clip);
-}
-
-void LLWorld::updateRegions(F32 max_update_time)
-{
- LLMemType mt_ur(LLMemType::MTYPE_IDLE_UPDATE_REGIONS);
- LLTimer update_timer;
- BOOL did_one = FALSE;
-
- // Perform idle time updates for the regions (and associated surfaces)
- for (region_list_t::iterator iter = mRegionList.begin();
- iter != mRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- F32 max_time = max_update_time - update_timer.getElapsedTimeF32();
- if (did_one && max_time <= 0.f)
- break;
- max_time = llmin(max_time, max_update_time*.1f);
- did_one |= regionp->idleUpdate(max_update_time);
- }
-}
-
-void LLWorld::updateParticles()
-{
- LLViewerPartSim::getInstance()->updateSimulation();
-}
-
-void LLWorld::renderPropertyLines()
-{
- S32 region_count = 0;
- S32 vertex_count = 0;
-
- for (region_list_t::iterator iter = mVisibleRegionList.begin();
- iter != mVisibleRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- region_count++;
- vertex_count += regionp->renderPropertyLines();
- }
-}
-
-
-void LLWorld::updateNetStats()
-{
- F32 bits = 0.f;
- U32 packets = 0;
-
- for (region_list_t::iterator iter = mActiveRegionList.begin();
- iter != mActiveRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- regionp->updateNetStats();
- bits += regionp->mBitStat.getCurrent();
- packets += llfloor( regionp->mPacketsStat.getCurrent() );
- }
-
- S32 packets_in = gMessageSystem->mPacketsIn - mLastPacketsIn;
- S32 packets_out = gMessageSystem->mPacketsOut - mLastPacketsOut;
- S32 packets_lost = gMessageSystem->mDroppedPackets - mLastPacketsLost;
-
- S32 actual_in_bits = gMessageSystem->mPacketRing.getAndResetActualInBits();
- S32 actual_out_bits = gMessageSystem->mPacketRing.getAndResetActualOutBits();
- LLViewerStats::getInstance()->mActualInKBitStat.addValue(actual_in_bits/1024.f);
- LLViewerStats::getInstance()->mActualOutKBitStat.addValue(actual_out_bits/1024.f);
- LLViewerStats::getInstance()->mKBitStat.addValue(bits/1024.f);
- LLViewerStats::getInstance()->mPacketsInStat.addValue(packets_in);
- LLViewerStats::getInstance()->mPacketsOutStat.addValue(packets_out);
- LLViewerStats::getInstance()->mPacketsLostStat.addValue(gMessageSystem->mDroppedPackets);
- if (packets_in)
- {
- LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(100.f*((F32)packets_lost/(F32)packets_in));
- }
- else
- {
- LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(0.f);
- }
-
- mLastPacketsIn = gMessageSystem->mPacketsIn;
- mLastPacketsOut = gMessageSystem->mPacketsOut;
- mLastPacketsLost = gMessageSystem->mDroppedPackets;
-}
-
-
-void LLWorld::printPacketsLost()
-{
- llinfos << "Simulators:" << llendl;
- llinfos << "----------" << llendl;
-
- LLCircuitData *cdp = NULL;
- for (region_list_t::iterator iter = mActiveRegionList.begin();
- iter != mActiveRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- cdp = gMessageSystem->mCircuitInfo.findCircuit(regionp->getHost());
- if (cdp)
- {
- LLVector3d range = regionp->getCenterGlobal() - gAgent.getPositionGlobal();
-
- llinfos << regionp->getHost() << ", range: " << range.length()
- << " packets lost: " << cdp->getPacketsLost() << llendl;
- }
- }
-}
-
-void LLWorld::processCoarseUpdate(LLMessageSystem* msg, void** user_data)
-{
- LLViewerRegion* region = LLWorld::getInstance()->getRegion(msg->getSender());
- if( region )
- {
- region->updateCoarseLocations(msg);
- }
-}
-
-F32 LLWorld::getLandFarClip() const
-{
- return mLandFarClip;
-}
-
-void LLWorld::setLandFarClip(const F32 far_clip)
-{
- static S32 const rwidth = (S32)REGION_WIDTH_U32;
- S32 const n1 = (llceil(mLandFarClip) - 1) / rwidth;
- S32 const n2 = (llceil(far_clip) - 1) / rwidth;
- bool need_water_objects_update = n1 != n2;
-
- mLandFarClip = far_clip;
-
- if (need_water_objects_update)
- {
- updateWaterObjects();
- }
-}
-
-// Some region that we're connected to, but not the one we're in, gave us
-// a (possibly) new water height. Update it in our local copy.
-void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_height)
-{
- for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter)
- {
- if ((*iter)->getName() == sim_name)
- {
- (*iter)->setWaterHeight(water_height);
- break;
- }
- }
-}
-
-void LLWorld::updateWaterObjects()
-{
- if (!gAgent.getRegion())
- {
- return;
- }
- if (mRegionList.empty())
- {
- llwarns << "No regions!" << llendl;
- return;
- }
-
- // First, determine the min and max "box" of water objects
- S32 min_x = 0;
- S32 min_y = 0;
- S32 max_x = 0;
- S32 max_y = 0;
- U32 region_x, region_y;
-
- S32 rwidth = 256;
-
- // We only want to fill in water for stuff that's near us, say, within 256 or 512m
- S32 range = LLViewerCamera::getInstance()->getFar() > 256.f ? 512 : 256;
-
- LLViewerRegion* regionp = gAgent.getRegion();
- from_region_handle(regionp->getHandle(), &region_x, &region_y);
-
- min_x = (S32)region_x - range;
- min_y = (S32)region_y - range;
- max_x = (S32)region_x + range;
- max_y = (S32)region_y + range;
-
- for (region_list_t::iterator iter = mRegionList.begin();
- iter != mRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- LLVOWater* waterp = regionp->getLand().getWaterObj();
- if (waterp)
- {
- gObjectList.updateActive(waterp);
- }
- }
-
- for (std::list<LLVOWater*>::iterator iter = mHoleWaterObjects.begin();
- iter != mHoleWaterObjects.end(); ++ iter)
- {
- LLVOWater* waterp = *iter;
- gObjectList.killObject(waterp);
- }
- mHoleWaterObjects.clear();
-
- // Now, get a list of the holes
- S32 x, y;
- F32 water_height = gAgent.getRegion()->getWaterHeight() + 256.f;
- for (x = min_x; x <= max_x; x += rwidth)
- {
- for (y = min_y; y <= max_y; y += rwidth)
- {
- U64 region_handle = to_region_handle(x, y);
- if (!getRegionFromHandle(region_handle))
- {
- LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion());
- waterp->setUseTexture(FALSE);
- waterp->setPositionGlobal(LLVector3d(x + rwidth/2,
- y + rwidth/2,
- water_height));
- waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f));
- gPipeline.createObject(waterp);
- mHoleWaterObjects.push_back(waterp);
- }
- }
- }
-
- // Update edge water objects
- S32 wx, wy;
- S32 center_x, center_y;
- wx = (max_x - min_x) + rwidth;
- wy = (max_y - min_y) + rwidth;
- center_x = min_x + (wx >> 1);
- center_y = min_y + (wy >> 1);
-
- S32 add_boundary[4] = {
- 512 - (max_x - region_x),
- 512 - (max_y - region_y),
- 512 - (region_x - min_x),
- 512 - (region_y - min_y) };
-
- S32 dir;
- for (dir = 0; dir < 8; dir++)
- {
- S32 dim[2] = { 0 };
- switch (gDirAxes[dir][0])
- {
- case -1: dim[0] = add_boundary[2]; break;
- case 0: dim[0] = wx; break;
- default: dim[0] = add_boundary[0]; break;
- }
- switch (gDirAxes[dir][1])
- {
- case -1: dim[1] = add_boundary[3]; break;
- case 0: dim[1] = wy; break;
- default: dim[1] = add_boundary[1]; break;
- }
-
- // Resize and reshape the water objects
- const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]);
- const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]);
-
- LLVOWater* waterp = mEdgeWaterObjects[dir];
- if (!waterp || waterp->isDead())
- {
- // The edge water objects can be dead because they're attached to the region that the
- // agent was in when they were originally created.
- mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER,
- gAgent.getRegion());
- waterp = mEdgeWaterObjects[dir];
- waterp->setUseTexture(FALSE);
- waterp->setIsEdgePatch(TRUE);
- gPipeline.createObject(waterp);
- }
-
- waterp->setRegion(gAgent.getRegion());
- LLVector3d water_pos(water_center_x, water_center_y, water_height) ;
- LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f);
-
- //stretch out to horizon
- water_scale.mV[0] += fabsf(2048.f * gDirAxes[dir][0]);
- water_scale.mV[1] += fabsf(2048.f * gDirAxes[dir][1]);
-
- water_pos.mdV[0] += 1024.f * gDirAxes[dir][0];
- water_pos.mdV[1] += 1024.f * gDirAxes[dir][1];
-
- waterp->setPositionGlobal(water_pos);
- waterp->setScale(water_scale);
-
- gObjectList.updateActive(waterp);
- }
-}
-
-
-void LLWorld::shiftRegions(const LLVector3& offset)
-{
- for (region_list_t::const_iterator i = getRegionList().begin(); i != getRegionList().end(); ++i)
- {
- LLViewerRegion* region = *i;
- region->updateRenderMatrix();
- }
-
- LLViewerPartSim::getInstance()->shift(offset);
-}
-
-LLViewerTexture* LLWorld::getDefaultWaterTexture()
-{
- return mDefaultWaterTexturep;
-}
-
-void LLWorld::setSpaceTimeUSec(const U64 space_time_usec)
-{
- mSpaceTimeUSec = space_time_usec;
-}
-
-U64 LLWorld::getSpaceTimeUSec() const
-{
- return mSpaceTimeUSec;
-}
-
-void LLWorld::requestCacheMisses()
-{
- for (region_list_t::iterator iter = mRegionList.begin();
- iter != mRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- regionp->requestCacheMisses();
- }
-}
-
-void LLWorld::getInfo(LLSD& info)
-{
- LLSD region_info;
- for (region_list_t::iterator iter = mRegionList.begin();
- iter != mRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- regionp->getInfo(region_info);
- info["World"].append(region_info);
- }
-}
-
-void LLWorld::disconnectRegions()
-{
- LLMessageSystem* msg = gMessageSystem;
- for (region_list_t::iterator iter = mRegionList.begin();
- iter != mRegionList.end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- if (regionp == gAgent.getRegion())
- {
- // Skip the main agent
- continue;
- }
-
- llinfos << "Sending AgentQuitCopy to: " << regionp->getHost() << llendl;
- msg->newMessageFast(_PREHASH_AgentQuitCopy);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_FuseBlock);
- msg->addU32Fast(_PREHASH_ViewerCircuitCode, gMessageSystem->mOurCircuitCode);
- msg->sendMessage(regionp->getHost());
- }
-}
-
-static LLFastTimer::DeclareTimer FTM_ENABLE_SIMULATOR("Enable Sim");
-
-void process_enable_simulator(LLMessageSystem *msg, void **user_data)
-{
- LLFastTimer t(FTM_ENABLE_SIMULATOR);
- // enable the appropriate circuit for this simulator and
- // add its values into the gSimulator structure
- U64 handle;
- U32 ip_u32;
- U16 port;
-
- msg->getU64Fast(_PREHASH_SimulatorInfo, _PREHASH_Handle, handle);
- msg->getIPAddrFast(_PREHASH_SimulatorInfo, _PREHASH_IP, ip_u32);
- msg->getIPPortFast(_PREHASH_SimulatorInfo, _PREHASH_Port, port);
-
- // which simulator should we modify?
- LLHost sim(ip_u32, port);
-
- // Viewer trusts the simulator.
- msg->enableCircuit(sim, TRUE);
- LLWorld::getInstance()->addRegion(handle, sim);
-
- // give the simulator a message it can use to get ip and port
- llinfos << "simulator_enable() Enabling " << sim << " with code " << msg->getOurCircuitCode() << llendl;
- msg->newMessageFast(_PREHASH_UseCircuitCode);
- msg->nextBlockFast(_PREHASH_CircuitCode);
- msg->addU32Fast(_PREHASH_Code, msg->getOurCircuitCode());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addUUIDFast(_PREHASH_ID, gAgent.getID());
- msg->sendReliable(sim);
-}
-
-class LLEstablishAgentCommunication : public LLHTTPNode
-{
- LOG_CLASS(LLEstablishAgentCommunication);
-public:
- virtual void describe(Description& desc) const
- {
- desc.shortInfo("seed capability info for a region");
- desc.postAPI();
- desc.input(
- "{ seed-capability: ..., sim-ip: ..., sim-port }");
- desc.source(__FILE__, __LINE__);
- }
-
- virtual void post(ResponsePtr response, const LLSD& context, const LLSD& input) const
- {
- if (!input["body"].has("agent-id") ||
- !input["body"].has("sim-ip-and-port") ||
- !input["body"].has("seed-capability"))
- {
- llwarns << "invalid parameters" << llendl;
- return;
- }
-
- LLHost sim(input["body"]["sim-ip-and-port"].asString());
-
- LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(sim);
- if (!regionp)
- {
- llwarns << "Got EstablishAgentCommunication for unknown region "
- << sim << llendl;
- return;
- }
- regionp->setSeedCapability(input["body"]["seed-capability"]);
- }
-};
-
-// disable the circuit to this simulator
-// Called in response to "DisableSimulator" message.
-void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data)
-{
- LLHost host = mesgsys->getSender();
-
- //llinfos << "Disabling simulator with message from " << host << llendl;
- LLWorld::getInstance()->removeRegion(host);
-
- mesgsys->disableCircuit(host);
-}
-
-
-void process_region_handshake(LLMessageSystem* msg, void** user_data)
-{
- LLHost host = msg->getSender();
- LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(host);
- if (!regionp)
- {
- llwarns << "Got region handshake for unknown region "
- << host << llendl;
- return;
- }
-
- regionp->unpackRegionHandshake();
+/**
+ * @file llworld.cpp
+ * @brief Initial test structure to organize viewer regions
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llworld.h"
+#include "llrender.h"
+
+#include "indra_constants.h"
+#include "llstl.h"
+
+#include "llagent.h"
+#include "llviewercontrol.h"
+#include "lldrawpool.h"
+#include "llglheaders.h"
+#include "llhttpnode.h"
+#include "llregionhandle.h"
+#include "llsurface.h"
+#include "lltrans.h"
+#include "llviewercamera.h"
+#include "llviewertexture.h"
+#include "llviewertexturelist.h"
+#include "llviewernetwork.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparceloverlay.h"
+#include "llviewerregion.h"
+#include "llviewerstats.h"
+#include "llvlcomposition.h"
+#include "llvoavatar.h"
+#include "llvocache.h"
+#include "llvowater.h"
+#include "message.h"
+#include "pipeline.h"
+#include "llappviewer.h" // for do_disconnect()
+#include "llfloaterpathfindingconsole.h"
+
+#include <deque>
+#include <queue>
+#include <map>
+#include <cstring>
+
+
+//
+// Globals
+//
+U32 gAgentPauseSerialNum = 0;
+
+//
+// Constants
+//
+const S32 MAX_NUMBER_OF_CLOUDS = 750;
+const S32 WORLD_PATCH_SIZE = 16;
+
+extern LLColor4U MAX_WATER_COLOR;
+
+const U32 LLWorld::mWidth = 256;
+
+// meters/point, therefore mWidth * mScale = meters per edge
+const F32 LLWorld::mScale = 1.f;
+
+const F32 LLWorld::mWidthInMeters = mWidth * mScale;
+
+//
+// Functions
+//
+
+// allocate the stack
+LLWorld::LLWorld() :
+ mLandFarClip(DEFAULT_FAR_PLANE),
+ mLastPacketsIn(0),
+ mLastPacketsOut(0),
+ mLastPacketsLost(0),
+ mSpaceTimeUSec(0)
+{
+ for (S32 i = 0; i < 8; i++)
+ {
+ mEdgeWaterObjects[i] = NULL;
+ }
+
+ LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,4);
+ U8 *default_texture = raw->getData();
+ *(default_texture++) = MAX_WATER_COLOR.mV[0];
+ *(default_texture++) = MAX_WATER_COLOR.mV[1];
+ *(default_texture++) = MAX_WATER_COLOR.mV[2];
+ *(default_texture++) = MAX_WATER_COLOR.mV[3];
+
+ mDefaultWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
+ gGL.getTexUnit(0)->bind(mDefaultWaterTexturep);
+ mDefaultWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
+
+}
+
+
+void LLWorld::destroyClass()
+{
+ mHoleWaterObjects.clear();
+ gObjectList.destroy();
+ for(region_list_t::iterator region_it = mRegionList.begin(); region_it != mRegionList.end(); )
+ {
+ LLViewerRegion* region_to_delete = *region_it++;
+ removeRegion(region_to_delete->getHost());
+ }
+ if(LLVOCache::hasInstance())
+ {
+ LLVOCache::getInstance()->destroyClass() ;
+ }
+ LLViewerPartSim::getInstance()->destroyClass();
+
+ mDefaultWaterTexturep = NULL ;
+ for (S32 i = 0; i < 8; i++)
+ {
+ mEdgeWaterObjects[i] = NULL;
+ }
+}
+
+
+LLViewerRegion* LLWorld::addRegion(const U64 &region_handle, const LLHost &host)
+{
+ LLMemType mt(LLMemType::MTYPE_REGIONS);
+ llinfos << "Add region with handle: " << region_handle << " on host " << host << llendl;
+ LLViewerRegion *regionp = getRegionFromHandle(region_handle);
+ if (regionp)
+ {
+ llinfos << "Region exists, removing it " << llendl;
+ LLHost old_host = regionp->getHost();
+ // region already exists!
+ if (host == old_host && regionp->isAlive())
+ {
+ // This is a duplicate for the same host and it's alive, don't bother.
+ return regionp;
+ }
+
+ if (host != old_host)
+ {
+ llwarns << "LLWorld::addRegion exists, but old host " << old_host
+ << " does not match new host " << host << llendl;
+ }
+ if (!regionp->isAlive())
+ {
+ llwarns << "LLWorld::addRegion exists, but isn't alive" << llendl;
+ }
+
+ // Kill the old host, and then we can continue on and add the new host. We have to kill even if the host
+ // matches, because all the agent state for the new camera is completely different.
+ removeRegion(old_host);
+ }
+
+ U32 iindex = 0;
+ U32 jindex = 0;
+ from_region_handle(region_handle, &iindex, &jindex);
+ S32 x = (S32)(iindex/mWidth);
+ S32 y = (S32)(jindex/mWidth);
+ llinfos << "Adding new region (" << x << ":" << y << ")" << llendl;
+ llinfos << "Host: " << host << llendl;
+
+ LLVector3d origin_global;
+
+ origin_global = from_region_handle(region_handle);
+
+ regionp = new LLViewerRegion(region_handle,
+ host,
+ mWidth,
+ WORLD_PATCH_SIZE,
+ getRegionWidthInMeters() );
+ if (!regionp)
+ {
+ llerrs << "Unable to create new region!" << llendl;
+ }
+
+ mRegionList.push_back(regionp);
+ mActiveRegionList.push_back(regionp);
+ mCulledRegionList.push_back(regionp);
+
+
+ // Find all the adjacent regions, and attach them.
+ // Generate handles for all of the adjacent regions, and attach them in the correct way.
+ // connect the edges
+ F32 adj_x = 0.f;
+ F32 adj_y = 0.f;
+ F32 region_x = 0.f;
+ F32 region_y = 0.f;
+ U64 adj_handle = 0;
+
+ F32 width = getRegionWidthInMeters();
+
+ LLViewerRegion *neighborp;
+ from_region_handle(region_handle, &region_x, &region_y);
+
+ // Iterate through all directions, and connect neighbors if there.
+ S32 dir;
+ for (dir = 0; dir < 8; dir++)
+ {
+ adj_x = region_x + width * gDirAxes[dir][0];
+ adj_y = region_y + width * gDirAxes[dir][1];
+ to_region_handle(adj_x, adj_y, &adj_handle);
+
+ neighborp = getRegionFromHandle(adj_handle);
+ if (neighborp)
+ {
+ //llinfos << "Connecting " << region_x << ":" << region_y << " -> " << adj_x << ":" << adj_y << llendl;
+ regionp->connectNeighbor(neighborp, dir);
+ }
+ }
+
+ updateWaterObjects();
+
+ return regionp;
+}
+
+
+void LLWorld::removeRegion(const LLHost &host)
+{
+ F32 x, y;
+
+ LLViewerRegion *regionp = getRegion(host);
+ if (!regionp)
+ {
+ llwarns << "Trying to remove region that doesn't exist!" << llendl;
+ return;
+ }
+
+ if (regionp == gAgent.getRegion())
+ {
+ for (region_list_t::iterator iter = mRegionList.begin();
+ iter != mRegionList.end(); ++iter)
+ {
+ LLViewerRegion* reg = *iter;
+ llwarns << "RegionDump: " << reg->getName()
+ << " " << reg->getHost()
+ << " " << reg->getOriginGlobal()
+ << llendl;
+ }
+
+ llwarns << "Agent position global " << gAgent.getPositionGlobal()
+ << " agent " << gAgent.getPositionAgent()
+ << llendl;
+
+ llwarns << "Regions visited " << gAgent.getRegionsVisited() << llendl;
+
+ llwarns << "gFrameTimeSeconds " << gFrameTimeSeconds << llendl;
+
+ llwarns << "Disabling region " << regionp->getName() << " that agent is in!" << llendl;
+ LLAppViewer::instance()->forceDisconnect(LLTrans::getString("YouHaveBeenDisconnected"));
+
+ regionp->saveObjectCache() ; //force to save objects here in case that the object cache is about to be destroyed.
+ return;
+ }
+
+ from_region_handle(regionp->getHandle(), &x, &y);
+ llinfos << "Removing region " << x << ":" << y << llendl;
+
+ mRegionList.remove(regionp);
+ mActiveRegionList.remove(regionp);
+ mCulledRegionList.remove(regionp);
+ mVisibleRegionList.remove(regionp);
+
+ delete regionp;
+
+ updateWaterObjects();
+
+ //double check all objects of this region are removed.
+ gObjectList.clearAllMapObjectsInRegion(regionp) ;
+ //llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ;
+}
+
+
+LLViewerRegion* LLWorld::getRegion(const LLHost &host)
+{
+ for (region_list_t::iterator iter = mRegionList.begin();
+ iter != mRegionList.end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ if (regionp->getHost() == host)
+ {
+ return regionp;
+ }
+ }
+ return NULL;
+}
+
+LLViewerRegion* LLWorld::getRegionFromPosAgent(const LLVector3 &pos)
+{
+ return getRegionFromPosGlobal(gAgent.getPosGlobalFromAgent(pos));
+}
+
+LLViewerRegion* LLWorld::getRegionFromPosGlobal(const LLVector3d &pos)
+{
+ for (region_list_t::iterator iter = mRegionList.begin();
+ iter != mRegionList.end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ if (regionp->pointInRegionGlobal(pos))
+ {
+ return regionp;
+ }
+ }
+ return NULL;
+}
+
+
+LLVector3d LLWorld::clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos)
+{
+ if (positionRegionValidGlobal(end_pos))
+ {
+ return end_pos;
+ }
+
+ LLViewerRegion* regionp = getRegionFromPosGlobal(start_pos);
+ if (!regionp)
+ {
+ return start_pos;
+ }
+
+ LLVector3d delta_pos = end_pos - start_pos;
+ LLVector3d delta_pos_abs;
+ delta_pos_abs.setVec(delta_pos);
+ delta_pos_abs.abs();
+
+ LLVector3 region_coord = regionp->getPosRegionFromGlobal(end_pos);
+ F64 clip_factor = 1.0;
+ F32 region_width = regionp->getWidth();
+ if (region_coord.mV[VX] < 0.f)
+ {
+ if (region_coord.mV[VY] < region_coord.mV[VX])
+ {
+ // clip along y -
+ clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]);
+ }
+ else
+ {
+ // clip along x -
+ clip_factor = -(region_coord.mV[VX] / delta_pos_abs.mdV[VX]);
+ }
+ }
+ else if (region_coord.mV[VX] > region_width)
+ {
+ if (region_coord.mV[VY] > region_coord.mV[VX])
+ {
+ // clip along y +
+ clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY];
+ }
+ else
+ {
+ //clip along x +
+ clip_factor = (region_coord.mV[VX] - region_width) / delta_pos_abs.mdV[VX];
+ }
+ }
+ else if (region_coord.mV[VY] < 0.f)
+ {
+ // clip along y -
+ clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]);
+ }
+ else if (region_coord.mV[VY] > region_width)
+ {
+ // clip along y +
+ clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY];
+ }
+
+ // clamp to within region dimensions
+ LLVector3d final_region_pos = LLVector3d(region_coord) - (delta_pos * clip_factor);
+ final_region_pos.mdV[VX] = llclamp(final_region_pos.mdV[VX], 0.0,
+ (F64)(region_width - F_ALMOST_ZERO));
+ final_region_pos.mdV[VY] = llclamp(final_region_pos.mdV[VY], 0.0,
+ (F64)(region_width - F_ALMOST_ZERO));
+ final_region_pos.mdV[VZ] = llclamp(final_region_pos.mdV[VZ], 0.0,
+ (F64)(LLWorld::getInstance()->getRegionMaxHeight() - F_ALMOST_ZERO));
+ return regionp->getPosGlobalFromRegion(LLVector3(final_region_pos));
+}
+
+LLViewerRegion* LLWorld::getRegionFromHandle(const U64 &handle)
+{
+ for (region_list_t::iterator iter = mRegionList.begin();
+ iter != mRegionList.end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ if (regionp->getHandle() == handle)
+ {
+ return regionp;
+ }
+ }
+ return NULL;
+}
+
+
+void LLWorld::updateAgentOffset(const LLVector3d &offset_global)
+{
+#if 0
+ for (region_list_t::iterator iter = mRegionList.begin();
+ iter != mRegionList.end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ regionp->setAgentOffset(offset_global);
+ }
+#endif
+}
+
+
+BOOL LLWorld::positionRegionValidGlobal(const LLVector3d &pos_global)
+{
+ for (region_list_t::iterator iter = mRegionList.begin();
+ iter != mRegionList.end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ if (regionp->pointInRegionGlobal(pos_global))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+// Allow objects to go up to their radius underground.
+F32 LLWorld::getMinAllowedZ(LLViewerObject* object, const LLVector3d &global_pos)
+{
+ F32 land_height = resolveLandHeightGlobal(global_pos);
+ F32 radius = 0.5f * object->getScale().length();
+ return land_height - radius;
+}
+
+
+
+LLViewerRegion* LLWorld::resolveRegionGlobal(LLVector3 &pos_region, const LLVector3d &pos_global)
+{
+ LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
+
+ if (regionp)
+ {
+ pos_region = regionp->getPosRegionFromGlobal(pos_global);
+ return regionp;
+ }
+
+ return NULL;
+}
+
+
+LLViewerRegion* LLWorld::resolveRegionAgent(LLVector3 &pos_region, const LLVector3 &pos_agent)
+{
+ LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
+ LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
+
+ if (regionp)
+ {
+ pos_region = regionp->getPosRegionFromGlobal(pos_global);
+ return regionp;
+ }
+
+ return NULL;
+}
+
+
+F32 LLWorld::resolveLandHeightAgent(const LLVector3 &pos_agent)
+{
+ LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
+ return resolveLandHeightGlobal(pos_global);
+}
+
+
+F32 LLWorld::resolveLandHeightGlobal(const LLVector3d &pos_global)
+{
+ LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
+ if (regionp)
+ {
+ return regionp->getLand().resolveHeightGlobal(pos_global);
+ }
+ return 0.0f;
+}
+
+
+// Takes a line defined by "point_a" and "point_b" and determines the closest (to point_a)
+// point where the the line intersects an object or the land surface. Stores the results
+// in "intersection" and "intersection_normal" and returns a scalar value that represents
+// the normalized distance along the line from "point_a" to "intersection".
+//
+// Currently assumes point_a and point_b only differ in z-direction,
+// but it may eventually become more general.
+F32 LLWorld::resolveStepHeightGlobal(const LLVOAvatar* avatarp, const LLVector3d &point_a, const LLVector3d &point_b,
+ LLVector3d &intersection, LLVector3 &intersection_normal,
+ LLViewerObject **viewerObjectPtr)
+{
+ // initialize return value to null
+ if (viewerObjectPtr)
+ {
+ *viewerObjectPtr = NULL;
+ }
+
+ LLViewerRegion *regionp = getRegionFromPosGlobal(point_a);
+ if (!regionp)
+ {
+ // We're outside the world
+ intersection = 0.5f * (point_a + point_b);
+ intersection_normal.setVec(0.0f, 0.0f, 1.0f);
+ return 0.5f;
+ }
+
+ // calculate the length of the segment
+ F32 segment_length = (F32)((point_a - point_b).length());
+ if (0.0f == segment_length)
+ {
+ intersection = point_a;
+ intersection_normal.setVec(0.0f, 0.0f, 1.0f);
+ return segment_length;
+ }
+
+ // get land height
+ // Note: we assume that the line is parallel to z-axis here
+ LLVector3d land_intersection = point_a;
+ F32 normalized_land_distance;
+
+ land_intersection.mdV[VZ] = regionp->getLand().resolveHeightGlobal(point_a);
+ normalized_land_distance = (F32)(point_a.mdV[VZ] - land_intersection.mdV[VZ]) / segment_length;
+ intersection = land_intersection;
+ intersection_normal = resolveLandNormalGlobal(land_intersection);
+
+ if (avatarp && !avatarp->mFootPlane.isExactlyClear())
+ {
+ LLVector3 foot_plane_normal(avatarp->mFootPlane.mV);
+ LLVector3 start_pt = avatarp->getRegion()->getPosRegionFromGlobal(point_a);
+ // added 0.05 meters to compensate for error in foot plane reported by Havok
+ F32 norm_dist_from_plane = ((start_pt * foot_plane_normal) - avatarp->mFootPlane.mV[VW]) + 0.05f;
+ norm_dist_from_plane = llclamp(norm_dist_from_plane / segment_length, 0.f, 1.f);
+ if (norm_dist_from_plane < normalized_land_distance)
+ {
+ // collided with object before land
+ normalized_land_distance = norm_dist_from_plane;
+ intersection = point_a;
+ intersection.mdV[VZ] -= norm_dist_from_plane * segment_length;
+ intersection_normal = foot_plane_normal;
+ }
+ else
+ {
+ intersection = land_intersection;
+ intersection_normal = resolveLandNormalGlobal(land_intersection);
+ }
+ }
+
+ return normalized_land_distance;
+}
+
+
+LLSurfacePatch * LLWorld::resolveLandPatchGlobal(const LLVector3d &pos_global)
+{
+ // returns a pointer to the patch at this location
+ LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
+ if (!regionp)
+ {
+ return NULL;
+ }
+
+ return regionp->getLand().resolvePatchGlobal(pos_global);
+}
+
+
+LLVector3 LLWorld::resolveLandNormalGlobal(const LLVector3d &pos_global)
+{
+ LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
+ if (!regionp)
+ {
+ return LLVector3::z_axis;
+ }
+
+ return regionp->getLand().resolveNormalGlobal(pos_global);
+}
+
+
+void LLWorld::updateVisibilities()
+{
+ F32 cur_far_clip = LLViewerCamera::getInstance()->getFar();
+
+ // Go through the culled list and check for visible regions (region is visible if land is visible)
+ for (region_list_t::iterator iter = mCulledRegionList.begin();
+ iter != mCulledRegionList.end(); )
+ {
+ region_list_t::iterator curiter = iter++;
+ LLViewerRegion* regionp = *curiter;
+
+ LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN);
+ if (part)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0);
+ if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1]))
+ {
+ mCulledRegionList.erase(curiter);
+ mVisibleRegionList.push_back(regionp);
+ }
+ }
+ }
+
+ // Update all of the visible regions
+ for (region_list_t::iterator iter = mVisibleRegionList.begin();
+ iter != mVisibleRegionList.end(); )
+ {
+ region_list_t::iterator curiter = iter++;
+ LLViewerRegion* regionp = *curiter;
+ if (!regionp->getLand().hasZData())
+ {
+ continue;
+ }
+
+ LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN);
+ if (part)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0);
+ if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1]))
+ {
+ regionp->calculateCameraDistance();
+ regionp->getLand().updatePatchVisibilities(gAgent);
+ }
+ else
+ {
+ mVisibleRegionList.erase(curiter);
+ mCulledRegionList.push_back(regionp);
+ }
+ }
+ }
+
+ // Sort visible regions
+ mVisibleRegionList.sort(LLViewerRegion::CompareDistance());
+
+ LLViewerCamera::getInstance()->setFar(cur_far_clip);
+}
+
+void LLWorld::updateRegions(F32 max_update_time)
+{
+ LLMemType mt_ur(LLMemType::MTYPE_IDLE_UPDATE_REGIONS);
+ LLTimer update_timer;
+ BOOL did_one = FALSE;
+
+ // Perform idle time updates for the regions (and associated surfaces)
+ for (region_list_t::iterator iter = mRegionList.begin();
+ iter != mRegionList.end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ F32 max_time = max_update_time - update_timer.getElapsedTimeF32();
+ if (did_one && max_time <= 0.f)
+ break;
+ max_time = llmin(max_time, max_update_time*.1f);
+ did_one |= regionp->idleUpdate(max_update_time);
+ }
+}
+
+void LLWorld::updateParticles()
+{
+ LLViewerPartSim::getInstance()->updateSimulation();
+}
+
+void LLWorld::renderPropertyLines()
+{
+ S32 region_count = 0;
+ S32 vertex_count = 0;
+
+ for (region_list_t::iterator iter = mVisibleRegionList.begin();
+ iter != mVisibleRegionList.end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ region_count++;
+ vertex_count += regionp->renderPropertyLines();
+ }
+}
+
+
+void LLWorld::updateNetStats()
+{
+ F32 bits = 0.f;
+ U32 packets = 0;
+
+ for (region_list_t::iterator iter = mActiveRegionList.begin();
+ iter != mActiveRegionList.end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ regionp->updateNetStats();
+ bits += regionp->mBitStat.getCurrent();
+ packets += llfloor( regionp->mPacketsStat.getCurrent() );
+ }
+
+ S32 packets_in = gMessageSystem->mPacketsIn - mLastPacketsIn;
+ S32 packets_out = gMessageSystem->mPacketsOut - mLastPacketsOut;
+ S32 packets_lost = gMessageSystem->mDroppedPackets - mLastPacketsLost;
+
+ S32 actual_in_bits = gMessageSystem->mPacketRing.getAndResetActualInBits();
+ S32 actual_out_bits = gMessageSystem->mPacketRing.getAndResetActualOutBits();
+ LLViewerStats::getInstance()->mActualInKBitStat.addValue(actual_in_bits/1024.f);
+ LLViewerStats::getInstance()->mActualOutKBitStat.addValue(actual_out_bits/1024.f);
+ LLViewerStats::getInstance()->mKBitStat.addValue(bits/1024.f);
+ LLViewerStats::getInstance()->mPacketsInStat.addValue(packets_in);
+ LLViewerStats::getInstance()->mPacketsOutStat.addValue(packets_out);
+ LLViewerStats::getInstance()->mPacketsLostStat.addValue(gMessageSystem->mDroppedPackets);
+ if (packets_in)
+ {
+ LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(100.f*((F32)packets_lost/(F32)packets_in));
+ }
+ else
+ {
+ LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(0.f);
+ }
+
+ mLastPacketsIn = gMessageSystem->mPacketsIn;
+ mLastPacketsOut = gMessageSystem->mPacketsOut;
+ mLastPacketsLost = gMessageSystem->mDroppedPackets;
+}
+
+
+void LLWorld::printPacketsLost()
+{
+ llinfos << "Simulators:" << llendl;
+ llinfos << "----------" << llendl;
+
+ LLCircuitData *cdp = NULL;
+ for (region_list_t::iterator iter = mActiveRegionList.begin();
+ iter != mActiveRegionList.end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ cdp = gMessageSystem->mCircuitInfo.findCircuit(regionp->getHost());
+ if (cdp)
+ {
+ LLVector3d range = regionp->getCenterGlobal() - gAgent.getPositionGlobal();
+
+ llinfos << regionp->getHost() << ", range: " << range.length()
+ << " packets lost: " << cdp->getPacketsLost() << llendl;
+ }
+ }
+}
+
+void LLWorld::processCoarseUpdate(LLMessageSystem* msg, void** user_data)
+{
+ LLViewerRegion* region = LLWorld::getInstance()->getRegion(msg->getSender());
+ if( region )
+ {
+ region->updateCoarseLocations(msg);
+ }
+}
+
+F32 LLWorld::getLandFarClip() const
+{
+ return mLandFarClip;
+}
+
+void LLWorld::setLandFarClip(const F32 far_clip)
+{
+ static S32 const rwidth = (S32)REGION_WIDTH_U32;
+ S32 const n1 = (llceil(mLandFarClip) - 1) / rwidth;
+ S32 const n2 = (llceil(far_clip) - 1) / rwidth;
+ bool need_water_objects_update = n1 != n2;
+
+ mLandFarClip = far_clip;
+
+ if (need_water_objects_update)
+ {
+ updateWaterObjects();
+ }
+}
+
+// Some region that we're connected to, but not the one we're in, gave us
+// a (possibly) new water height. Update it in our local copy.
+void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_height)
+{
+ for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter)
+ {
+ if ((*iter)->getName() == sim_name)
+ {
+ (*iter)->setWaterHeight(water_height);
+ break;
+ }
+ }
+}
+
+void LLWorld::updateWaterObjects()
+{
+ if (!gAgent.getRegion())
+ {
+ return;
+ }
+ if (mRegionList.empty())
+ {
+ llwarns << "No regions!" << llendl;
+ return;
+ }
+
+ // First, determine the min and max "box" of water objects
+ S32 min_x = 0;
+ S32 min_y = 0;
+ S32 max_x = 0;
+ S32 max_y = 0;
+ U32 region_x, region_y;
+
+ S32 rwidth = 256;
+
+ // We only want to fill in water for stuff that's near us, say, within 256 or 512m
+ S32 range = LLViewerCamera::getInstance()->getFar() > 256.f ? 512 : 256;
+
+ LLViewerRegion* regionp = gAgent.getRegion();
+ from_region_handle(regionp->getHandle(), &region_x, &region_y);
+
+ min_x = (S32)region_x - range;
+ min_y = (S32)region_y - range;
+ max_x = (S32)region_x + range;
+ max_y = (S32)region_y + range;
+
+ for (region_list_t::iterator iter = mRegionList.begin();
+ iter != mRegionList.end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ LLVOWater* waterp = regionp->getLand().getWaterObj();
+ if (waterp)
+ {
+ gObjectList.updateActive(waterp);
+ }
+ }
+
+ for (std::list<LLVOWater*>::iterator iter = mHoleWaterObjects.begin();
+ iter != mHoleWaterObjects.end(); ++ iter)
+ {
+ LLVOWater* waterp = *iter;
+ gObjectList.killObject(waterp);
+ }
+ mHoleWaterObjects.clear();
+
+ // Now, get a list of the holes
+ S32 x, y;
+ F32 water_height = gAgent.getRegion()->getWaterHeight() + 256.f;
+ for (x = min_x; x <= max_x; x += rwidth)
+ {
+ for (y = min_y; y <= max_y; y += rwidth)
+ {
+ U64 region_handle = to_region_handle(x, y);
+ if (!getRegionFromHandle(region_handle))
+ {
+ LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion());
+ waterp->setUseTexture(FALSE);
+ waterp->setPositionGlobal(LLVector3d(x + rwidth/2,
+ y + rwidth/2,
+ water_height));
+ waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f));
+ gPipeline.createObject(waterp);
+ mHoleWaterObjects.push_back(waterp);
+ }
+ }
+ }
+
+ // Update edge water objects
+ S32 wx, wy;
+ S32 center_x, center_y;
+ wx = (max_x - min_x) + rwidth;
+ wy = (max_y - min_y) + rwidth;
+ center_x = min_x + (wx >> 1);
+ center_y = min_y + (wy >> 1);
+
+ S32 add_boundary[4] = {
+ 512 - (max_x - region_x),
+ 512 - (max_y - region_y),
+ 512 - (region_x - min_x),
+ 512 - (region_y - min_y) };
+
+ S32 dir;
+ for (dir = 0; dir < 8; dir++)
+ {
+ S32 dim[2] = { 0 };
+ switch (gDirAxes[dir][0])
+ {
+ case -1: dim[0] = add_boundary[2]; break;
+ case 0: dim[0] = wx; break;
+ default: dim[0] = add_boundary[0]; break;
+ }
+ switch (gDirAxes[dir][1])
+ {
+ case -1: dim[1] = add_boundary[3]; break;
+ case 0: dim[1] = wy; break;
+ default: dim[1] = add_boundary[1]; break;
+ }
+
+ // Resize and reshape the water objects
+ const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]);
+ const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]);
+
+ LLVOWater* waterp = mEdgeWaterObjects[dir];
+ if (!waterp || waterp->isDead())
+ {
+ // The edge water objects can be dead because they're attached to the region that the
+ // agent was in when they were originally created.
+ mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER,
+ gAgent.getRegion());
+ waterp = mEdgeWaterObjects[dir];
+ waterp->setUseTexture(FALSE);
+ waterp->setIsEdgePatch(TRUE);
+ gPipeline.createObject(waterp);
+ }
+
+ waterp->setRegion(gAgent.getRegion());
+ LLVector3d water_pos(water_center_x, water_center_y, water_height) ;
+ LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f);
+
+ //stretch out to horizon
+ water_scale.mV[0] += fabsf(2048.f * gDirAxes[dir][0]);
+ water_scale.mV[1] += fabsf(2048.f * gDirAxes[dir][1]);
+
+ water_pos.mdV[0] += 1024.f * gDirAxes[dir][0];
+ water_pos.mdV[1] += 1024.f * gDirAxes[dir][1];
+
+ waterp->setPositionGlobal(water_pos);
+ waterp->setScale(water_scale);
+
+ gObjectList.updateActive(waterp);
+ }
+}
+
+
+void LLWorld::shiftRegions(const LLVector3& offset)
+{
+ for (region_list_t::const_iterator i = getRegionList().begin(); i != getRegionList().end(); ++i)
+ {
+ LLViewerRegion* region = *i;
+ region->updateRenderMatrix();
+ }
+
+ LLViewerPartSim::getInstance()->shift(offset);
+}
+
+LLViewerTexture* LLWorld::getDefaultWaterTexture()
+{
+ return mDefaultWaterTexturep;
+}
+
+void LLWorld::setSpaceTimeUSec(const U64 space_time_usec)
+{
+ mSpaceTimeUSec = space_time_usec;
+}
+
+U64 LLWorld::getSpaceTimeUSec() const
+{
+ return mSpaceTimeUSec;
+}
+
+void LLWorld::requestCacheMisses()
+{
+ for (region_list_t::iterator iter = mRegionList.begin();
+ iter != mRegionList.end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ regionp->requestCacheMisses();
+ }
+}
+
+void LLWorld::getInfo(LLSD& info)
+{
+ LLSD region_info;
+ for (region_list_t::iterator iter = mRegionList.begin();
+ iter != mRegionList.end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ regionp->getInfo(region_info);
+ info["World"].append(region_info);
+ }
+}
+
+void LLWorld::disconnectRegions()
+{
+ LLMessageSystem* msg = gMessageSystem;
+ for (region_list_t::iterator iter = mRegionList.begin();
+ iter != mRegionList.end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ if (regionp == gAgent.getRegion())
+ {
+ // Skip the main agent
+ continue;
+ }
+
+ llinfos << "Sending AgentQuitCopy to: " << regionp->getHost() << llendl;
+ msg->newMessageFast(_PREHASH_AgentQuitCopy);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_FuseBlock);
+ msg->addU32Fast(_PREHASH_ViewerCircuitCode, gMessageSystem->mOurCircuitCode);
+ msg->sendMessage(regionp->getHost());
+ }
+}
+
+static LLFastTimer::DeclareTimer FTM_ENABLE_SIMULATOR("Enable Sim");
+
+void process_enable_simulator(LLMessageSystem *msg, void **user_data)
+{
+ LLFastTimer t(FTM_ENABLE_SIMULATOR);
+ // enable the appropriate circuit for this simulator and
+ // add its values into the gSimulator structure
+ U64 handle;
+ U32 ip_u32;
+ U16 port;
+
+ msg->getU64Fast(_PREHASH_SimulatorInfo, _PREHASH_Handle, handle);
+ msg->getIPAddrFast(_PREHASH_SimulatorInfo, _PREHASH_IP, ip_u32);
+ msg->getIPPortFast(_PREHASH_SimulatorInfo, _PREHASH_Port, port);
+
+ // which simulator should we modify?
+ LLHost sim(ip_u32, port);
+
+ // Viewer trusts the simulator.
+ msg->enableCircuit(sim, TRUE);
+ LLWorld::getInstance()->addRegion(handle, sim);
+
+ // give the simulator a message it can use to get ip and port
+ llinfos << "simulator_enable() Enabling " << sim << " with code " << msg->getOurCircuitCode() << llendl;
+ msg->newMessageFast(_PREHASH_UseCircuitCode);
+ msg->nextBlockFast(_PREHASH_CircuitCode);
+ msg->addU32Fast(_PREHASH_Code, msg->getOurCircuitCode());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addUUIDFast(_PREHASH_ID, gAgent.getID());
+ msg->sendReliable(sim);
+}
+
+class LLEstablishAgentCommunication : public LLHTTPNode
+{
+ LOG_CLASS(LLEstablishAgentCommunication);
+public:
+ virtual void describe(Description& desc) const
+ {
+ desc.shortInfo("seed capability info for a region");
+ desc.postAPI();
+ desc.input(
+ "{ seed-capability: ..., sim-ip: ..., sim-port }");
+ desc.source(__FILE__, __LINE__);
+ }
+
+ virtual void post(ResponsePtr response, const LLSD& context, const LLSD& input) const
+ {
+ if (!input["body"].has("agent-id") ||
+ !input["body"].has("sim-ip-and-port") ||
+ !input["body"].has("seed-capability"))
+ {
+ llwarns << "invalid parameters" << llendl;
+ return;
+ }
+
+ LLHost sim(input["body"]["sim-ip-and-port"].asString());
+
+ LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(sim);
+ if (!regionp)
+ {
+ llwarns << "Got EstablishAgentCommunication for unknown region "
+ << sim << llendl;
+ return;
+ }
+ regionp->setSeedCapability(input["body"]["seed-capability"]);
+ }
+};
+
+// disable the circuit to this simulator
+// Called in response to "DisableSimulator" message.
+void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data)
+{
+ LLHost host = mesgsys->getSender();
+
+ //llinfos << "Disabling simulator with message from " << host << llendl;
+ LLWorld::getInstance()->removeRegion(host);
+
+ mesgsys->disableCircuit(host);
+}
+
+
+void process_region_handshake(LLMessageSystem* msg, void** user_data)
+{
+ LLHost host = msg->getSender();
+ LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(host);
+ if (!regionp)
+ {
+ llwarns << "Got region handshake for unknown region "
+ << host << llendl;
+ return;
+ }
+
+ regionp->unpackRegionHandshake();
LLFloaterPathfindingConsole* pWindow = LLFloaterPathfindingConsole::getInstanceHandle().get();
if ( pWindow && pWindow->getHeartBeat() )
@@ -1099,163 +1099,149 @@ void process_region_handshake(LLMessageSystem* msg, void** user_data)
pWindow->regionCrossingOccured();
return;
}
-
-}
-
-
-void send_agent_pause()
-{
- // *NOTE:Mani Pausing the mainloop timeout. Otherwise a long modal event may cause
- // the thread monitor to timeout.
- LLAppViewer::instance()->pauseMainloopTimeout();
-
- // Note: used to check for LLWorld initialization before it became a singleton.
- // Rather than just remove this check I'm changing it to assure that the message
- // system has been initialized. -MG
- if (!gMessageSystem)
- {
- return;
- }
-
- gMessageSystem->newMessageFast(_PREHASH_AgentPause);
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
-
- gAgentPauseSerialNum++;
- gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum);
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- gMessageSystem->sendReliable(regionp->getHost());
- }
-
- gObjectList.mWasPaused = TRUE;
-}
-
-
-void send_agent_resume()
-{
- // Note: used to check for LLWorld initialization before it became a singleton.
- // Rather than just remove this check I'm changing it to assure that the message
- // system has been initialized. -MG
- if (!gMessageSystem)
- {
- return;
- }
-
- gMessageSystem->newMessageFast(_PREHASH_AgentResume);
- gMessageSystem->nextBlockFast(_PREHASH_AgentData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
- gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
-
- gAgentPauseSerialNum++;
- gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum);
-
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- gMessageSystem->sendReliable(regionp->getHost());
- }
-
- // Reset the FPS counter to avoid an invalid fps
- LLViewerStats::getInstance()->mFPSStat.start();
-
- LLAppViewer::instance()->resumeMainloopTimeout();
-}
-
-static LLVector3d unpackLocalToGlobalPosition(U32 compact_local, const LLVector3d& region_origin)
-{
- LLVector3d pos_global;
- LLVector3 pos_local;
- U8 bits;
-
- bits = compact_local & 0xFF;
- pos_local.mV[VZ] = F32(bits) * 4.f;
- compact_local >>= 8;
-
- bits = compact_local & 0xFF;
- pos_local.mV[VY] = (F32)bits;
- compact_local >>= 8;
-
- bits = compact_local & 0xFF;
- pos_local.mV[VX] = (F32)bits;
-
- pos_global.setVec( pos_local );
- pos_global += region_origin;
- return pos_global;
-}
-
-void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positions, const LLVector3d& relative_to, F32 radius) const
-{
- F32 radius_squared = radius * radius;
-
- if(avatar_ids != NULL)
- {
- avatar_ids->clear();
- }
- if(positions != NULL)
- {
- positions->clear();
- }
- // get the list of avatars from the character list first, so distances are correct
- // when agent is above 1020m and other avatars are nearby
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter;
- if(!pVOAvatar->isDead() && !pVOAvatar->isSelf())
- {
- LLUUID uuid = pVOAvatar->getID();
- if(!uuid.isNull())
- {
- LLVector3d pos_global = pVOAvatar->getPositionGlobal();
- if(dist_vec_squared(pos_global, relative_to) <= radius_squared)
- {
- if(positions != NULL)
- {
- positions->push_back(pos_global);
- }
- if(avatar_ids !=NULL)
- {
- avatar_ids->push_back(uuid);
- }
- }
- }
- }
- }
- // region avatars added for situations where radius is greater than RenderFarClip
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* regionp = *iter;
- const LLVector3d& origin_global = regionp->getOriginGlobal();
- S32 count = regionp->mMapAvatars.count();
- for (S32 i = 0; i < count; i++)
- {
- LLVector3d pos_global = unpackLocalToGlobalPosition(regionp->mMapAvatars.get(i), origin_global);
- if(dist_vec_squared(pos_global, relative_to) <= radius_squared)
- {
- LLUUID uuid = regionp->mMapAvatarIDs.get(i);
- // if this avatar doesn't already exist in the list, add it
- if(uuid.notNull() && avatar_ids!=NULL && std::find(avatar_ids->begin(), avatar_ids->end(), uuid) == avatar_ids->end())
- {
- if(positions != NULL)
- {
- positions->push_back(pos_global);
- }
- avatar_ids->push_back(uuid);
- }
- }
- }
- }
-}
-
-
-LLHTTPRegistration<LLEstablishAgentCommunication>
- gHTTPRegistrationEstablishAgentCommunication(
- "/message/EstablishAgentCommunication");
+
+}
+
+
+void send_agent_pause()
+{
+ // *NOTE:Mani Pausing the mainloop timeout. Otherwise a long modal event may cause
+ // the thread monitor to timeout.
+ LLAppViewer::instance()->pauseMainloopTimeout();
+
+ // Note: used to check for LLWorld initialization before it became a singleton.
+ // Rather than just remove this check I'm changing it to assure that the message
+ // system has been initialized. -MG
+ if (!gMessageSystem)
+ {
+ return;
+ }
+
+ gMessageSystem->newMessageFast(_PREHASH_AgentPause);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
+
+ gAgentPauseSerialNum++;
+ gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum);
+
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ gMessageSystem->sendReliable(regionp->getHost());
+ }
+
+ gObjectList.mWasPaused = TRUE;
+}
+
+
+void send_agent_resume()
+{
+ // Note: used to check for LLWorld initialization before it became a singleton.
+ // Rather than just remove this check I'm changing it to assure that the message
+ // system has been initialized. -MG
+ if (!gMessageSystem)
+ {
+ return;
+ }
+
+ gMessageSystem->newMessageFast(_PREHASH_AgentResume);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
+
+ gAgentPauseSerialNum++;
+ gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum);
+
+
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ gMessageSystem->sendReliable(regionp->getHost());
+ }
+
+ // Reset the FPS counter to avoid an invalid fps
+ LLViewerStats::getInstance()->mFPSStat.start();
+
+ LLAppViewer::instance()->resumeMainloopTimeout();
+}
+
+static LLVector3d unpackLocalToGlobalPosition(U32 compact_local, const LLVector3d& region_origin)
+{
+ LLVector3d pos_local;
+
+ pos_local.mdV[VZ] = (compact_local & 0xFFU) * 4;
+ pos_local.mdV[VY] = (compact_local >> 8) & 0xFFU;
+ pos_local.mdV[VX] = (compact_local >> 16) & 0xFFU;
+
+ return region_origin + pos_local;
+}
+
+void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positions, const LLVector3d& relative_to, F32 radius) const
+{
+ F32 radius_squared = radius * radius;
+
+ if(avatar_ids != NULL)
+ {
+ avatar_ids->clear();
+ }
+ if(positions != NULL)
+ {
+ positions->clear();
+ }
+ // get the list of avatars from the character list first, so distances are correct
+ // when agent is above 1020m and other avatars are nearby
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
+ {
+ LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter;
+ LLVector3d pos_global = pVOAvatar->getPositionGlobal();
+ LLUUID uuid = pVOAvatar->getID();
+ if( !pVOAvatar->isDead()
+ && !pVOAvatar->isSelf()
+ && !uuid.isNull() &&
+ dist_vec_squared(pos_global, relative_to) <= radius_squared)
+ {
+ if(positions != NULL)
+ {
+ positions->push_back(pos_global);
+ }
+ if(avatar_ids !=NULL)
+ {
+ avatar_ids->push_back(uuid);
+ }
+ }
+ }
+ // region avatars added for situations where radius is greater than RenderFarClip
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* regionp = *iter;
+ const LLVector3d& origin_global = regionp->getOriginGlobal();
+ S32 count = regionp->mMapAvatars.count();
+ for (S32 i = 0; i < count; i++)
+ {
+ LLVector3d pos_global = unpackLocalToGlobalPosition(regionp->mMapAvatars.get(i), origin_global);
+ if(dist_vec_squared(pos_global, relative_to) <= radius_squared)
+ {
+ LLUUID uuid = regionp->mMapAvatarIDs.get(i);
+ // if this avatar doesn't already exist in the list, add it
+ if(uuid.notNull() && avatar_ids != NULL && std::find(avatar_ids->begin(), avatar_ids->end(), uuid) == avatar_ids->end())
+ {
+ if (positions != NULL)
+ {
+ positions->push_back(pos_global);
+ }
+ avatar_ids->push_back(uuid);
+ }
+ }
+ }
+ }
+}
+
+
+LLHTTPRegistration<LLEstablishAgentCommunication>
+ gHTTPRegistrationEstablishAgentCommunication(
+ "/message/EstablishAgentCommunication");
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index e50851b8e7..a3ccf87cfc 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -77,6 +77,7 @@ LLUIImagePtr LLWorldMapView::sAvatarYouLargeImage = NULL;
LLUIImagePtr LLWorldMapView::sAvatarLevelImage = NULL;
LLUIImagePtr LLWorldMapView::sAvatarAboveImage = NULL;
LLUIImagePtr LLWorldMapView::sAvatarBelowImage = NULL;
+LLUIImagePtr LLWorldMapView::sAvatarUnknownImage = NULL;
LLUIImagePtr LLWorldMapView::sTelehubImage = NULL;
LLUIImagePtr LLWorldMapView::sInfohubImage = NULL;
@@ -120,6 +121,7 @@ void LLWorldMapView::initClass()
sAvatarLevelImage = LLUI::getUIImage("map_avatar_32.tga");
sAvatarAboveImage = LLUI::getUIImage("map_avatar_above_32.tga");
sAvatarBelowImage = LLUI::getUIImage("map_avatar_below_32.tga");
+ sAvatarUnknownImage = LLUI::getUIImage("map_avatar_unknown_32.tga");
sHomeImage = LLUI::getUIImage("map_home.tga");
sTelehubImage = LLUI::getUIImage("map_telehub.tga");
@@ -149,6 +151,7 @@ void LLWorldMapView::cleanupClass()
sAvatarLevelImage = NULL;
sAvatarAboveImage = NULL;
sAvatarBelowImage = NULL;
+ sAvatarUnknownImage = NULL;
sTelehubImage = NULL;
sInfohubImage = NULL;
@@ -513,7 +516,7 @@ void LLWorldMapView::draw()
TRUE,
"You are here",
"",
- llround(LLFontGL::getFontSansSerifSmall()->getLineHeight())); // offset vertically by one line, to avoid overlap with target tracking
+ LLFontGL::getFontSansSerifSmall()->getLineHeight()); // offset vertically by one line, to avoid overlap with target tracking
}
// Draw the current agent viewing angle
@@ -992,7 +995,7 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&
const S32 TEXT_PADDING = DEFAULT_TRACKING_ARROW_SIZE + 2;
S32 half_text_width = llfloor(font->getWidthF32(label) * 0.5f);
text_x = llclamp(text_x, half_text_width + TEXT_PADDING, getRect().getWidth() - half_text_width - TEXT_PADDING);
- text_y = llclamp(text_y + vert_offset, TEXT_PADDING + vert_offset, getRect().getHeight() - llround(font->getLineHeight()) - TEXT_PADDING - vert_offset);
+ text_y = llclamp(text_y + vert_offset, TEXT_PADDING + vert_offset, getRect().getHeight() - font->getLineHeight() - TEXT_PADDING - vert_offset);
if (label != "")
{
@@ -1005,7 +1008,7 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&
if (tooltip != "")
{
- text_y -= (S32)font->getLineHeight();
+ text_y -= font->getLineHeight();
font->renderUTF8(
tooltip, 0,
@@ -1147,17 +1150,25 @@ void LLWorldMapView::drawAvatar(F32 x_pixels,
F32 y_pixels,
const LLColor4& color,
F32 relative_z,
- F32 dot_radius)
+ F32 dot_radius,
+ bool unknown_relative_z)
{
const F32 HEIGHT_THRESHOLD = 7.f;
LLUIImagePtr dot_image = sAvatarLevelImage;
- if(relative_z < -HEIGHT_THRESHOLD)
+ if (unknown_relative_z)
{
- dot_image = sAvatarBelowImage;
+ dot_image = sAvatarUnknownImage;
}
- else if(relative_z > HEIGHT_THRESHOLD)
- {
- dot_image = sAvatarAboveImage;
+ else
+ {
+ if(relative_z < -HEIGHT_THRESHOLD)
+ {
+ dot_image = sAvatarBelowImage;
+ }
+ else if(relative_z > HEIGHT_THRESHOLD)
+ {
+ dot_image = sAvatarAboveImage;
+ }
}
S32 dot_width = llround(dot_radius * 2.f);
dot_image->draw(llround(x_pixels - dot_radius),
@@ -1203,7 +1214,7 @@ void LLWorldMapView::drawIconName(F32 x_pixels,
LLFontGL::NORMAL,
LLFontGL::DROP_SHADOW);
- text_y -= llround(LLFontGL::getFontSansSerif()->getLineHeight());
+ text_y -= LLFontGL::getFontSansSerif()->getLineHeight();
// render text
LLFontGL::getFontSansSerif()->renderUTF8(second_line, 0,
diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h
index 9ab53b1ba3..a2a6dc53fb 100644
--- a/indra/newview/llworldmapview.h
+++ b/indra/newview/llworldmapview.h
@@ -112,7 +112,8 @@ public:
F32 y_pixels,
const LLColor4& color,
F32 relative_z = 0.f,
- F32 dot_radius = 3.f);
+ F32 dot_radius = 3.f,
+ bool reached_max_z = false);
static void drawIconName(F32 x_pixels,
F32 y_pixels,
const LLColor4& color,
@@ -138,6 +139,7 @@ public:
static LLUIImagePtr sAvatarLevelImage;
static LLUIImagePtr sAvatarAboveImage;
static LLUIImagePtr sAvatarBelowImage;
+ static LLUIImagePtr sAvatarUnknownImage;
static LLUIImagePtr sTelehubImage;
static LLUIImagePtr sInfohubImage;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 9548263843..28d59785d3 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -1,4342 +1,4328 @@
-/**
- * @file pipeline.cpp
- * @brief Rendering pipeline.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "pipeline.h"
-
-// library includes
-#include "llaudioengine.h" // For debugging.
-#include "imageids.h"
-#include "llerror.h"
-#include "llviewercontrol.h"
-#include "llfasttimer.h"
-#include "llfontgl.h"
-#include "llmemtype.h"
-#include "llnamevalue.h"
-#include "llpointer.h"
-#include "llprimitive.h"
-#include "llvolume.h"
-#include "material_codes.h"
-#include "timing.h"
-#include "v3color.h"
-#include "llui.h"
-#include "llglheaders.h"
-#include "llrender.h"
-#include "llwindow.h" // swapBuffers()
-
-// newview includes
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "lldrawable.h"
-#include "lldrawpoolalpha.h"
-#include "lldrawpoolavatar.h"
-#include "lldrawpoolground.h"
-#include "lldrawpoolbump.h"
-#include "lldrawpooltree.h"
-#include "lldrawpoolwater.h"
-#include "llface.h"
-#include "llfeaturemanager.h"
-#include "llfloatertelehub.h"
-#include "llfloaterreg.h"
-#include "llgldbg.h"
-#include "llhudmanager.h"
-#include "llhudnametag.h"
-#include "llhudtext.h"
-#include "lllightconstants.h"
-#include "llmeshrepository.h"
-#include "llresmgr.h"
-#include "llselectmgr.h"
-#include "llsky.h"
-#include "lltracker.h"
-#include "lltool.h"
-#include "lltoolmgr.h"
-#include "llviewercamera.h"
-#include "llviewermediafocus.h"
-#include "llviewertexturelist.h"
-#include "llviewerobject.h"
-#include "llviewerobjectlist.h"
-#include "llviewerparcelmgr.h"
-#include "llviewerregion.h" // for audio debugging.
-#include "llviewerwindow.h" // For getSpinAxis
-#include "llvoavatarself.h"
-#include "llvoground.h"
-#include "llvosky.h"
-#include "llvotree.h"
-#include "llvovolume.h"
-#include "llvosurfacepatch.h"
-#include "llvowater.h"
-#include "llvotree.h"
-#include "llvopartgroup.h"
-#include "llworld.h"
-#include "llcubemap.h"
-#include "llviewershadermgr.h"
-#include "llviewerstats.h"
-#include "llviewerjoystick.h"
-#include "llviewerdisplay.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
-#include "llspatialpartition.h"
-#include "llmutelist.h"
-#include "lltoolpie.h"
-#include "llcurl.h"
-#include "llnotifications.h"
-#include "LLPathingLib.h"
-#include "llfloaterpathfindingconsole.h"
-
-#ifdef _DEBUG
-// Debug indices is disabled for now for debug performance - djs 4/24/02
-//#define DEBUG_INDICES
-#else
-//#define DEBUG_INDICES
-#endif
-
-//cached settings
-BOOL LLPipeline::RenderAvatarVP;
-BOOL LLPipeline::VertexShaderEnable;
-BOOL LLPipeline::WindLightUseAtmosShaders;
-BOOL LLPipeline::RenderDeferred;
-F32 LLPipeline::RenderDeferredSunWash;
-U32 LLPipeline::RenderFSAASamples;
-U32 LLPipeline::RenderResolutionDivisor;
-BOOL LLPipeline::RenderUIBuffer;
-S32 LLPipeline::RenderShadowDetail;
-BOOL LLPipeline::RenderDeferredSSAO;
-F32 LLPipeline::RenderShadowResolutionScale;
-BOOL LLPipeline::RenderLocalLights;
-BOOL LLPipeline::RenderDelayCreation;
-BOOL LLPipeline::RenderAnimateRes;
-BOOL LLPipeline::FreezeTime;
-S32 LLPipeline::DebugBeaconLineWidth;
-F32 LLPipeline::RenderHighlightBrightness;
-LLColor4 LLPipeline::RenderHighlightColor;
-F32 LLPipeline::RenderHighlightThickness;
-BOOL LLPipeline::RenderSpotLightsInNondeferred;
-LLColor4 LLPipeline::PreviewAmbientColor;
-LLColor4 LLPipeline::PreviewDiffuse0;
-LLColor4 LLPipeline::PreviewSpecular0;
-LLColor4 LLPipeline::PreviewDiffuse1;
-LLColor4 LLPipeline::PreviewSpecular1;
-LLColor4 LLPipeline::PreviewDiffuse2;
-LLColor4 LLPipeline::PreviewSpecular2;
-LLVector3 LLPipeline::PreviewDirection0;
-LLVector3 LLPipeline::PreviewDirection1;
-LLVector3 LLPipeline::PreviewDirection2;
-F32 LLPipeline::RenderGlowMinLuminance;
-F32 LLPipeline::RenderGlowMaxExtractAlpha;
-F32 LLPipeline::RenderGlowWarmthAmount;
-LLVector3 LLPipeline::RenderGlowLumWeights;
-LLVector3 LLPipeline::RenderGlowWarmthWeights;
-S32 LLPipeline::RenderGlowResolutionPow;
-S32 LLPipeline::RenderGlowIterations;
-F32 LLPipeline::RenderGlowWidth;
-F32 LLPipeline::RenderGlowStrength;
-BOOL LLPipeline::RenderDepthOfField;
-F32 LLPipeline::CameraFocusTransitionTime;
-F32 LLPipeline::CameraFNumber;
-F32 LLPipeline::CameraFocalLength;
-F32 LLPipeline::CameraFieldOfView;
-F32 LLPipeline::RenderShadowNoise;
-F32 LLPipeline::RenderShadowBlurSize;
-F32 LLPipeline::RenderSSAOScale;
-U32 LLPipeline::RenderSSAOMaxScale;
-F32 LLPipeline::RenderSSAOFactor;
-LLVector3 LLPipeline::RenderSSAOEffect;
-F32 LLPipeline::RenderShadowOffsetError;
-F32 LLPipeline::RenderShadowBiasError;
-F32 LLPipeline::RenderShadowOffset;
-F32 LLPipeline::RenderShadowBias;
-F32 LLPipeline::RenderSpotShadowOffset;
-F32 LLPipeline::RenderSpotShadowBias;
-F32 LLPipeline::RenderEdgeDepthCutoff;
-F32 LLPipeline::RenderEdgeNormCutoff;
-LLVector3 LLPipeline::RenderShadowGaussian;
-F32 LLPipeline::RenderShadowBlurDistFactor;
-BOOL LLPipeline::RenderDeferredAtmospheric;
-S32 LLPipeline::RenderReflectionDetail;
-F32 LLPipeline::RenderHighlightFadeTime;
-LLVector3 LLPipeline::RenderShadowClipPlanes;
-LLVector3 LLPipeline::RenderShadowOrthoClipPlanes;
-LLVector3 LLPipeline::RenderShadowNearDist;
-F32 LLPipeline::RenderFarClip;
-LLVector3 LLPipeline::RenderShadowSplitExponent;
-F32 LLPipeline::RenderShadowErrorCutoff;
-F32 LLPipeline::RenderShadowFOVCutoff;
-BOOL LLPipeline::CameraOffset;
-F32 LLPipeline::CameraMaxCoF;
-F32 LLPipeline::CameraDoFResScale;
-
-const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f;
-const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f;
-const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
-const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
-const S32 MAX_OFFSCREEN_GEOMETRY_CHANGES_PER_FRAME = 10;
-const U32 REFLECTION_MAP_RES = 128;
-const U32 DEFERRED_VB_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
-// Max number of occluders to search for. JC
-const S32 MAX_OCCLUDER_COUNT = 2;
-
-extern S32 gBoxFrame;
-//extern BOOL gHideSelectedObjects;
-extern BOOL gDisplaySwapBuffers;
-extern BOOL gDebugGL;
-
-// hack counter for rendering a fixed number of frames after toggling
-// fullscreen to work around DEV-5361
-static S32 sDelayedVBOEnable = 0;
-
-BOOL gAvatarBacklight = FALSE;
-
-BOOL gDebugPipeline = FALSE;
-LLPipeline gPipeline;
-const LLMatrix4* gGLLastMatrix = NULL;
-
-LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Geometry");
-LLFastTimer::DeclareTimer FTM_RENDER_GRASS("Grass");
-LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE("Invisible");
-LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION("Occlusion");
-LLFastTimer::DeclareTimer FTM_RENDER_SHINY("Shiny");
-LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE("Simple");
-LLFastTimer::DeclareTimer FTM_RENDER_TERRAIN("Terrain");
-LLFastTimer::DeclareTimer FTM_RENDER_TREES("Trees");
-LLFastTimer::DeclareTimer FTM_RENDER_UI("UI");
-LLFastTimer::DeclareTimer FTM_RENDER_WATER("Water");
-LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY("Windlight Sky");
-LLFastTimer::DeclareTimer FTM_RENDER_ALPHA("Alpha Objects");
-LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS("Avatars");
-LLFastTimer::DeclareTimer FTM_RENDER_BUMP("Bump");
-LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT("Fullbright");
-LLFastTimer::DeclareTimer FTM_RENDER_GLOW("Glow");
-LLFastTimer::DeclareTimer FTM_GEO_UPDATE("Geo Update");
-LLFastTimer::DeclareTimer FTM_POOLRENDER("RenderPool");
-LLFastTimer::DeclareTimer FTM_POOLS("Pools");
-LLFastTimer::DeclareTimer FTM_RENDER_BLOOM_FBO("First FBO");
-LLFastTimer::DeclareTimer FTM_STATESORT("Sort Draw State");
-LLFastTimer::DeclareTimer FTM_PIPELINE("Pipeline");
-LLFastTimer::DeclareTimer FTM_CLIENT_COPY("Client Copy");
-LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading");
-
-
-static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");
-static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort");
-
-//----------------------------------------
-std::string gPoolNames[] =
-{
- // Correspond to LLDrawpool enum render type
- "NONE",
- "POOL_SIMPLE",
- "POOL_GROUND",
- "POOL_FULLBRIGHT",
- "POOL_BUMP",
- "POOL_TERRAIN,"
- "POOL_SKY",
- "POOL_WL_SKY",
- "POOL_TREE",
- "POOL_GRASS",
- "POOL_INVISIBLE",
- "POOL_AVATAR",
- "POOL_VOIDWATER",
- "POOL_WATER",
- "POOL_GLOW",
- "POOL_ALPHA"
-};
-
-void drawBox(const LLVector3& c, const LLVector3& r);
-void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
-U32 nhpo2(U32 v);
-
-glh::matrix4f glh_copy_matrix(F32* src)
-{
- glh::matrix4f ret;
- ret.set_value(src);
- return ret;
-}
-
-glh::matrix4f glh_get_current_modelview()
-{
- return glh_copy_matrix(gGLModelView);
-}
-
-glh::matrix4f glh_get_current_projection()
-{
- return glh_copy_matrix(gGLProjection);
-}
-
-glh::matrix4f glh_get_last_modelview()
-{
- return glh_copy_matrix(gGLLastModelView);
-}
-
-glh::matrix4f glh_get_last_projection()
-{
- return glh_copy_matrix(gGLLastProjection);
-}
-
-void glh_copy_matrix(const glh::matrix4f& src, F32* dst)
-{
- for (U32 i = 0; i < 16; i++)
- {
- dst[i] = src.m[i];
- }
-}
-
-void glh_set_current_modelview(const glh::matrix4f& mat)
-{
- glh_copy_matrix(mat, gGLModelView);
-}
-
-void glh_set_current_projection(glh::matrix4f& mat)
-{
- glh_copy_matrix(mat, gGLProjection);
-}
-
-glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar)
-{
- glh::matrix4f ret(
- 2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left),
- 0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom),
- 0.f, 0.f, -2.f/(zfar-znear), -(zfar+znear)/(zfar-znear),
- 0.f, 0.f, 0.f, 1.f);
-
- return ret;
-}
-
-void display_update_camera();
-//----------------------------------------
-
-S32 LLPipeline::sCompiles = 0;
-
-BOOL LLPipeline::sPickAvatar = TRUE;
-BOOL LLPipeline::sDynamicLOD = TRUE;
-BOOL LLPipeline::sShowHUDAttachments = TRUE;
-BOOL LLPipeline::sRenderMOAPBeacons = FALSE;
-BOOL LLPipeline::sRenderPhysicalBeacons = TRUE;
-BOOL LLPipeline::sRenderScriptedBeacons = FALSE;
-BOOL LLPipeline::sRenderScriptedTouchBeacons = TRUE;
-BOOL LLPipeline::sRenderParticleBeacons = FALSE;
-BOOL LLPipeline::sRenderSoundBeacons = FALSE;
-BOOL LLPipeline::sRenderBeacons = FALSE;
-BOOL LLPipeline::sRenderHighlight = TRUE;
-BOOL LLPipeline::sForceOldBakedUpload = FALSE;
-S32 LLPipeline::sUseOcclusion = 0;
-BOOL LLPipeline::sDelayVBUpdate = TRUE;
-BOOL LLPipeline::sAutoMaskAlphaDeferred = TRUE;
-BOOL LLPipeline::sAutoMaskAlphaNonDeferred = FALSE;
-BOOL LLPipeline::sDisableShaders = FALSE;
-BOOL LLPipeline::sRenderBump = TRUE;
-BOOL LLPipeline::sBakeSunlight = FALSE;
-BOOL LLPipeline::sNoAlpha = FALSE;
-BOOL LLPipeline::sUseTriStrips = TRUE;
-BOOL LLPipeline::sUseFarClip = TRUE;
-BOOL LLPipeline::sShadowRender = FALSE;
-BOOL LLPipeline::sWaterReflections = FALSE;
-BOOL LLPipeline::sRenderGlow = FALSE;
-BOOL LLPipeline::sReflectionRender = FALSE;
-BOOL LLPipeline::sImpostorRender = FALSE;
-BOOL LLPipeline::sUnderWaterRender = FALSE;
-BOOL LLPipeline::sTextureBindTest = FALSE;
-BOOL LLPipeline::sRenderFrameTest = FALSE;
-BOOL LLPipeline::sRenderAttachedLights = TRUE;
-BOOL LLPipeline::sRenderAttachedParticles = TRUE;
-BOOL LLPipeline::sRenderDeferred = FALSE;
-BOOL LLPipeline::sMemAllocationThrottled = FALSE;
-S32 LLPipeline::sVisibleLightCount = 0;
-F32 LLPipeline::sMinRenderSize = 0.f;
-
-
-static LLCullResult* sCull = NULL;
-
-static const U32 gl_cube_face[] =
-{
- GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
- GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
- GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
-};
-
-void validate_framebuffer_object();
-
-
-bool addDeferredAttachments(LLRenderTarget& target)
-{
- return target.addColorAttachment(GL_RGBA) && //specular
- target.addColorAttachment(GL_RGBA); //normal+z
-}
-
-LLPipeline::LLPipeline() :
- mBackfaceCull(FALSE),
- mBatchCount(0),
- mMatrixOpCount(0),
- mTextureMatrixOps(0),
- mMaxBatchSize(0),
- mMinBatchSize(0),
- mMeanBatchSize(0),
- mTrianglesDrawn(0),
- mNumVisibleNodes(0),
- mVerticesRelit(0),
- mLightingChanges(0),
- mGeometryChanges(0),
- mNumVisibleFaces(0),
-
- mInitialized(FALSE),
- mVertexShadersEnabled(FALSE),
- mVertexShadersLoaded(0),
- mRenderDebugFeatureMask(0),
- mRenderDebugMask(0),
- mOldRenderDebugMask(0),
- mGroupQ1Locked(false),
- mGroupQ2Locked(false),
- mLastRebuildPool(NULL),
- mAlphaPool(NULL),
- mSkyPool(NULL),
- mTerrainPool(NULL),
- mWaterPool(NULL),
- mGroundPool(NULL),
- mSimplePool(NULL),
- mFullbrightPool(NULL),
- mInvisiblePool(NULL),
- mGlowPool(NULL),
- mBumpPool(NULL),
- mWLSkyPool(NULL),
- mLightMask(0),
- mLightMovingMask(0),
- mLightingDetail(0),
- mScreenWidth(0),
- mScreenHeight(0)
-{
- mNoiseMap = 0;
- mTrueNoiseMap = 0;
- mLightFunc = 0;
-}
-
-void LLPipeline::init()
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_INIT);
-
- refreshCachedSettings();
-
- gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
- sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
- sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
- sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
- LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
- LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
- LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
- sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
- sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
-
- mInitialized = TRUE;
-
- stop_glerror();
-
- //create render pass pools
- getPool(LLDrawPool::POOL_ALPHA);
- getPool(LLDrawPool::POOL_SIMPLE);
- getPool(LLDrawPool::POOL_GRASS);
- getPool(LLDrawPool::POOL_FULLBRIGHT);
- getPool(LLDrawPool::POOL_INVISIBLE);
- getPool(LLDrawPool::POOL_BUMP);
- getPool(LLDrawPool::POOL_GLOW);
-
- LLViewerStats::getInstance()->mTrianglesDrawnStat.reset();
- resetFrameStats();
-
- for (U32 i = 0; i < NUM_RENDER_TYPES; ++i)
- {
- mRenderTypeEnabled[i] = TRUE; //all rendering types start enabled
- }
-
- mRenderDebugFeatureMask = 0xffffffff; // All debugging features on
- mRenderDebugMask = 0; // All debug starts off
-
- // Don't turn on ground when this is set
- // Mac Books with intel 950s need this
- if(!gSavedSettings.getBOOL("RenderGround"))
- {
- toggleRenderType(RENDER_TYPE_GROUND);
- }
-
- // make sure RenderPerformanceTest persists (hackity hack hack)
- // disables non-object rendering (UI, sky, water, etc)
- if (gSavedSettings.getBOOL("RenderPerformanceTest"))
- {
- gSavedSettings.setBOOL("RenderPerformanceTest", FALSE);
- gSavedSettings.setBOOL("RenderPerformanceTest", TRUE);
- }
-
- mOldRenderDebugMask = mRenderDebugMask;
-
- mBackfaceCull = TRUE;
-
- stop_glerror();
-
- // Enable features
-
- LLViewerShaderMgr::instance()->setShaders();
-
- stop_glerror();
-
- for (U32 i = 0; i < 2; ++i)
- {
- mSpotLightFade[i] = 1.f;
- }
-
- mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0);
- mDeferredVB->allocateBuffer(8, 0, true);
- setLightingDetail(-1);
-
- //
- // Update all settings to trigger a cached settings refresh
- //
-
- gSavedSettings.getControl("RenderAutoMaskAlphaDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderUseFarClip")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderAvatarMaxVisible")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderDelayVBUpdate")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-
- gSavedSettings.getControl("UseOcclusion")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-
- gSavedSettings.getControl("VertexShaderEnable")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderAvatarVP")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("WindLightUseAtmosShaders")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderDeferredSunWash")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderFSAASamples")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderResolutionDivisor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderUIBuffer")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowDetail")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderDeferredSSAO")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowResolutionScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderLocalLights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderDelayCreation")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderAnimateRes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("FreezeTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("DebugBeaconLineWidth")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderHighlightBrightness")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderHighlightColor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderHighlightThickness")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderSpotLightsInNondeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("PreviewAmbientColor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("PreviewDiffuse0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("PreviewSpecular0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("PreviewDiffuse1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("PreviewSpecular1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("PreviewDiffuse2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("PreviewSpecular2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("PreviewDirection0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("PreviewDirection1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("PreviewDirection2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderGlowMinLuminance")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderGlowMaxExtractAlpha")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderGlowWarmthAmount")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderGlowLumWeights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderGlowWarmthWeights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderGlowResolutionPow")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderGlowIterations")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderGlowWidth")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderGlowStrength")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderDepthOfField")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("CameraFocusTransitionTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("CameraFNumber")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("CameraFocalLength")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("CameraFieldOfView")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowNoise")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowBlurSize")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderSSAOScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderSSAOMaxScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderSSAOFactor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderSSAOEffect")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowOffsetError")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowBiasError")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowBias")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderSpotShadowOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderSpotShadowBias")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderEdgeDepthCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderEdgeNormCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowGaussian")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowBlurDistFactor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderDeferredAtmospheric")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderReflectionDetail")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderHighlightFadeTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowClipPlanes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowOrthoClipPlanes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowNearDist")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderFarClip")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowSplitExponent")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowErrorCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("RenderShadowFOVCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("CameraOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("CameraMaxCoF")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
- gSavedSettings.getControl("CameraDoFResScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
-}
-
-LLPipeline::~LLPipeline()
-{
-
-}
-
-void LLPipeline::cleanup()
-{
- assertInitialized();
-
- mGroupQ1.clear() ;
- mGroupQ2.clear() ;
-
- for(pool_set_t::iterator iter = mPools.begin();
- iter != mPools.end(); )
- {
- pool_set_t::iterator curiter = iter++;
- LLDrawPool* poolp = *curiter;
- if (poolp->isFacePool())
- {
- LLFacePool* face_pool = (LLFacePool*) poolp;
- if (face_pool->mReferences.empty())
- {
- mPools.erase(curiter);
- removeFromQuickLookup( poolp );
- delete poolp;
- }
- }
- else
- {
- mPools.erase(curiter);
- removeFromQuickLookup( poolp );
- delete poolp;
- }
- }
-
- if (!mTerrainPools.empty())
- {
- llwarns << "Terrain Pools not cleaned up" << llendl;
- }
- if (!mTreePools.empty())
- {
- llwarns << "Tree Pools not cleaned up" << llendl;
- }
-
- delete mAlphaPool;
- mAlphaPool = NULL;
- delete mSkyPool;
- mSkyPool = NULL;
- delete mTerrainPool;
- mTerrainPool = NULL;
- delete mWaterPool;
- mWaterPool = NULL;
- delete mGroundPool;
- mGroundPool = NULL;
- delete mSimplePool;
- mSimplePool = NULL;
- delete mFullbrightPool;
- mFullbrightPool = NULL;
- delete mInvisiblePool;
- mInvisiblePool = NULL;
- delete mGlowPool;
- mGlowPool = NULL;
- delete mBumpPool;
- mBumpPool = NULL;
- // don't delete wl sky pool it was handled above in the for loop
- //delete mWLSkyPool;
- mWLSkyPool = NULL;
-
- releaseGLBuffers();
-
- mFaceSelectImagep = NULL;
-
- mMovedBridge.clear();
-
- mInitialized = FALSE;
-
- mDeferredVB = NULL;
-}
-
-//============================================================================
-
-void LLPipeline::destroyGL()
-{
- stop_glerror();
- unloadShaders();
- mHighlightFaces.clear();
-
- resetDrawOrders();
-
- resetVertexBuffers();
-
- releaseGLBuffers();
-
- if (LLVertexBuffer::sEnableVBOs)
- {
- // render 30 frames after switching to work around DEV-5361
- sDelayedVBOEnable = 30;
- LLVertexBuffer::sEnableVBOs = FALSE;
- }
-}
-
-static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture");
-
-//static
-void LLPipeline::throttleNewMemoryAllocation(BOOL disable)
-{
- if(sMemAllocationThrottled != disable)
- {
- sMemAllocationThrottled = disable ;
-
- if(sMemAllocationThrottled)
- {
- //send out notification
- LLNotification::Params params("LowMemory");
- LLNotifications::instance().add(params);
-
- //release some memory.
- }
- }
-}
-
-void LLPipeline::resizeScreenTexture()
-{
- LLFastTimer ft(FTM_RESIZE_SCREEN_TEXTURE);
- if (gPipeline.canUseVertexShaders() && assertInitialized())
- {
- GLuint resX = gViewerWindow->getWorldViewWidthRaw();
- GLuint resY = gViewerWindow->getWorldViewHeightRaw();
-
- allocateScreenBuffer(resX,resY);
- }
-}
-
-void LLPipeline::allocatePhysicsBuffer()
-{
- GLuint resX = gViewerWindow->getWorldViewWidthRaw();
- GLuint resY = gViewerWindow->getWorldViewHeightRaw();
-
- if (mPhysicsDisplay.getWidth() != resX || mPhysicsDisplay.getHeight() != resY)
- {
- mPhysicsDisplay.allocate(resX, resY, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
- }
-}
-
-void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
-{
- refreshCachedSettings();
- U32 samples = RenderFSAASamples;
-
- //try to allocate screen buffers at requested resolution and samples
- // - on failure, shrink number of samples and try again
- // - if not multisampled, shrink resolution and try again (favor X resolution over Y)
- // Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state
-
- if (!allocateScreenBuffer(resX, resY, samples))
- {
- releaseScreenBuffers();
- //reduce number of samples
- while (samples > 0)
- {
- samples /= 2;
- if (allocateScreenBuffer(resX, resY, samples))
- { //success
- return;
- }
- releaseScreenBuffers();
- }
-
- samples = 0;
-
- //reduce resolution
- while (resY > 0 && resX > 0)
- {
- resY /= 2;
- if (allocateScreenBuffer(resX, resY, samples))
- {
- return;
- }
- releaseScreenBuffers();
-
- resX /= 2;
- if (allocateScreenBuffer(resX, resY, samples))
- {
- return;
- }
- releaseScreenBuffers();
- }
-
- llwarns << "Unable to allocate screen buffer at any resolution!" << llendl;
- }
-}
-
-
-bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
-{
- refreshCachedSettings();
-
- // remember these dimensions
- mScreenWidth = resX;
- mScreenHeight = resY;
-
- U32 res_mod = RenderResolutionDivisor;
-
- if (res_mod > 1 && res_mod < resX && res_mod < resY)
- {
- resX /= res_mod;
- resY /= res_mod;
- }
-
- if (RenderUIBuffer)
- {
- if (!mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE))
- {
- return false;
- }
- }
-
- if (LLPipeline::sRenderDeferred)
- {
- S32 shadow_detail = RenderShadowDetail;
- BOOL ssao = RenderDeferredSSAO;
-
- //allocate deferred rendering color buffers
- if (!mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (!addDeferredAttachments(mDeferredScreen)) return false;
-
- if (!mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (samples > 0)
- {
- if (!mFXAABuffer.allocate(nhpo2(resX), nhpo2(resY), GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
- }
- else
- {
- mFXAABuffer.release();
- }
-
- if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0)
- { //only need mDeferredLight for shadows OR ssao OR dof OR fxaa
- if (!mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
- }
- else
- {
- mDeferredLight.release();
- }
-
- F32 scale = RenderShadowResolutionScale;
-
- if (shadow_detail > 0)
- { //allocate 4 sun shadow maps
- for (U32 i = 0; i < 4; i++)
- {
- if (!mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false;
- }
- }
- else
- {
- for (U32 i = 0; i < 4; i++)
- {
- mShadow[i].release();
- }
- }
-
- U32 width = nhpo2(U32(resX*scale))/2;
- U32 height = width;
-
- if (shadow_detail > 1)
- { //allocate two spot shadow maps
- for (U32 i = 4; i < 6; i++)
- {
- if (!mShadow[i].allocate(width, height, 0, TRUE, FALSE)) return false;
- }
- }
- else
- {
- for (U32 i = 4; i < 6; i++)
- {
- mShadow[i].release();
- }
- }
- }
- else
- {
- mDeferredLight.release();
-
- for (U32 i = 0; i < 6; i++)
- {
- mShadow[i].release();
- }
- mFXAABuffer.release();
- mScreen.release();
- mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
- mDeferredDepth.release();
-
- if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
- }
-
- if (LLPipeline::sRenderDeferred)
- { //share depth buffer between deferred targets
- mDeferredScreen.shareDepthBuffer(mScreen);
- }
-
- gGL.getTexUnit(0)->disable();
-
- stop_glerror();
-
- return true;
-}
-
-//static
-void LLPipeline::updateRenderDeferred()
-{
- BOOL deferred = ((RenderDeferred &&
- LLRenderTarget::sUseFBO &&
- LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
- VertexShaderEnable &&
- RenderAvatarVP &&
- WindLightUseAtmosShaders) ? TRUE : FALSE) &&
- !gUseWireframe;
-
- sRenderDeferred = deferred;
- if (deferred)
- { //must render glow when rendering deferred since post effect pass is needed to present any lighting at all
- sRenderGlow = TRUE;
- }
-}
-
-//static
-void LLPipeline::refreshCachedSettings()
-{
- LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred");
- LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred");
- LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip");
- LLVOAvatar::sMaxVisible = (U32)gSavedSettings.getS32("RenderAvatarMaxVisible");
- LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate");
-
- LLPipeline::sUseOcclusion =
- (!gUseWireframe
- && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion")
- && gSavedSettings.getBOOL("UseOcclusion")
- && gGLManager.mHasOcclusionQuery) ? 2 : 0;
-
- VertexShaderEnable = gSavedSettings.getBOOL("VertexShaderEnable");
- RenderAvatarVP = gSavedSettings.getBOOL("RenderAvatarVP");
- WindLightUseAtmosShaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders");
- RenderDeferred = gSavedSettings.getBOOL("RenderDeferred");
- RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash");
- RenderFSAASamples = gSavedSettings.getU32("RenderFSAASamples");
- RenderResolutionDivisor = gSavedSettings.getU32("RenderResolutionDivisor");
- RenderUIBuffer = gSavedSettings.getBOOL("RenderUIBuffer");
- RenderShadowDetail = gSavedSettings.getS32("RenderShadowDetail");
- RenderDeferredSSAO = gSavedSettings.getBOOL("RenderDeferredSSAO");
- RenderShadowResolutionScale = gSavedSettings.getF32("RenderShadowResolutionScale");
- RenderLocalLights = gSavedSettings.getBOOL("RenderLocalLights");
- RenderDelayCreation = gSavedSettings.getBOOL("RenderDelayCreation");
- RenderAnimateRes = gSavedSettings.getBOOL("RenderAnimateRes");
- FreezeTime = gSavedSettings.getBOOL("FreezeTime");
- DebugBeaconLineWidth = gSavedSettings.getS32("DebugBeaconLineWidth");
- RenderHighlightBrightness = gSavedSettings.getF32("RenderHighlightBrightness");
- RenderHighlightColor = gSavedSettings.getColor4("RenderHighlightColor");
- RenderHighlightThickness = gSavedSettings.getF32("RenderHighlightThickness");
- RenderSpotLightsInNondeferred = gSavedSettings.getBOOL("RenderSpotLightsInNondeferred");
- PreviewAmbientColor = gSavedSettings.getColor4("PreviewAmbientColor");
- PreviewDiffuse0 = gSavedSettings.getColor4("PreviewDiffuse0");
- PreviewSpecular0 = gSavedSettings.getColor4("PreviewSpecular0");
- PreviewDiffuse1 = gSavedSettings.getColor4("PreviewDiffuse1");
- PreviewSpecular1 = gSavedSettings.getColor4("PreviewSpecular1");
- PreviewDiffuse2 = gSavedSettings.getColor4("PreviewDiffuse2");
- PreviewSpecular2 = gSavedSettings.getColor4("PreviewSpecular2");
- PreviewDirection0 = gSavedSettings.getVector3("PreviewDirection0");
- PreviewDirection1 = gSavedSettings.getVector3("PreviewDirection1");
- PreviewDirection2 = gSavedSettings.getVector3("PreviewDirection2");
- RenderGlowMinLuminance = gSavedSettings.getF32("RenderGlowMinLuminance");
- RenderGlowMaxExtractAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha");
- RenderGlowWarmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount");
- RenderGlowLumWeights = gSavedSettings.getVector3("RenderGlowLumWeights");
- RenderGlowWarmthWeights = gSavedSettings.getVector3("RenderGlowWarmthWeights");
- RenderGlowResolutionPow = gSavedSettings.getS32("RenderGlowResolutionPow");
- RenderGlowIterations = gSavedSettings.getS32("RenderGlowIterations");
- RenderGlowWidth = gSavedSettings.getF32("RenderGlowWidth");
- RenderGlowStrength = gSavedSettings.getF32("RenderGlowStrength");
- RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField");
- CameraFocusTransitionTime = gSavedSettings.getF32("CameraFocusTransitionTime");
- CameraFNumber = gSavedSettings.getF32("CameraFNumber");
- CameraFocalLength = gSavedSettings.getF32("CameraFocalLength");
- CameraFieldOfView = gSavedSettings.getF32("CameraFieldOfView");
- RenderShadowNoise = gSavedSettings.getF32("RenderShadowNoise");
- RenderShadowBlurSize = gSavedSettings.getF32("RenderShadowBlurSize");
- RenderSSAOScale = gSavedSettings.getF32("RenderSSAOScale");
- RenderSSAOMaxScale = gSavedSettings.getU32("RenderSSAOMaxScale");
- RenderSSAOFactor = gSavedSettings.getF32("RenderSSAOFactor");
- RenderSSAOEffect = gSavedSettings.getVector3("RenderSSAOEffect");
- RenderShadowOffsetError = gSavedSettings.getF32("RenderShadowOffsetError");
- RenderShadowBiasError = gSavedSettings.getF32("RenderShadowBiasError");
- RenderShadowOffset = gSavedSettings.getF32("RenderShadowOffset");
- RenderShadowBias = gSavedSettings.getF32("RenderShadowBias");
- RenderSpotShadowOffset = gSavedSettings.getF32("RenderSpotShadowOffset");
- RenderSpotShadowBias = gSavedSettings.getF32("RenderSpotShadowBias");
- RenderEdgeDepthCutoff = gSavedSettings.getF32("RenderEdgeDepthCutoff");
- RenderEdgeNormCutoff = gSavedSettings.getF32("RenderEdgeNormCutoff");
- RenderShadowGaussian = gSavedSettings.getVector3("RenderShadowGaussian");
- RenderShadowBlurDistFactor = gSavedSettings.getF32("RenderShadowBlurDistFactor");
- RenderDeferredAtmospheric = gSavedSettings.getBOOL("RenderDeferredAtmospheric");
- RenderReflectionDetail = gSavedSettings.getS32("RenderReflectionDetail");
- RenderHighlightFadeTime = gSavedSettings.getF32("RenderHighlightFadeTime");
- RenderShadowClipPlanes = gSavedSettings.getVector3("RenderShadowClipPlanes");
- RenderShadowOrthoClipPlanes = gSavedSettings.getVector3("RenderShadowOrthoClipPlanes");
- RenderShadowNearDist = gSavedSettings.getVector3("RenderShadowNearDist");
- RenderFarClip = gSavedSettings.getF32("RenderFarClip");
- RenderShadowSplitExponent = gSavedSettings.getVector3("RenderShadowSplitExponent");
- RenderShadowErrorCutoff = gSavedSettings.getF32("RenderShadowErrorCutoff");
- RenderShadowFOVCutoff = gSavedSettings.getF32("RenderShadowFOVCutoff");
- CameraOffset = gSavedSettings.getBOOL("CameraOffset");
- CameraMaxCoF = gSavedSettings.getF32("CameraMaxCoF");
- CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale");
-
- updateRenderDeferred();
-}
-
-void LLPipeline::releaseGLBuffers()
-{
- assertInitialized();
-
- if (mNoiseMap)
- {
- LLImageGL::deleteTextures(1, &mNoiseMap);
- mNoiseMap = 0;
- }
-
- if (mTrueNoiseMap)
- {
- LLImageGL::deleteTextures(1, &mTrueNoiseMap);
- mTrueNoiseMap = 0;
- }
-
- if (mLightFunc)
- {
- LLImageGL::deleteTextures(1, &mLightFunc);
- mLightFunc = 0;
- }
-
- mWaterRef.release();
- mWaterDis.release();
-
- for (U32 i = 0; i < 3; i++)
- {
- mGlow[i].release();
- }
-
- releaseScreenBuffers();
-
- gBumpImageList.destroyGL();
- LLVOAvatar::resetImpostors();
-}
-
-void LLPipeline::releaseScreenBuffers()
-{
- mUIScreen.release();
- mScreen.release();
- mFXAABuffer.release();
- mPhysicsDisplay.release();
- mDeferredScreen.release();
- mDeferredDepth.release();
- mDeferredLight.release();
-
- mHighlight.release();
-
- for (U32 i = 0; i < 6; i++)
- {
- mShadow[i].release();
- }
-}
-
-
-void LLPipeline::createGLBuffers()
-{
- stop_glerror();
- LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS);
- assertInitialized();
-
- updateRenderDeferred();
-
- if (LLPipeline::sWaterReflections)
- { //water reflection texture
- U32 res = (U32) gSavedSettings.getS32("RenderWaterRefResolution");
-
- mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE);
- mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE);
- }
-
- mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE);
-
- stop_glerror();
-
- GLuint resX = gViewerWindow->getWorldViewWidthRaw();
- GLuint resY = gViewerWindow->getWorldViewHeightRaw();
-
- if (LLPipeline::sRenderGlow)
- { //screen space glow buffers
- const U32 glow_res = llmax(1,
- llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow")));
-
- for (U32 i = 0; i < 3; i++)
- {
- mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE);
- }
-
- allocateScreenBuffer(resX,resY);
- mScreenWidth = 0;
- mScreenHeight = 0;
- }
-
- if (sRenderDeferred)
- {
- if (!mNoiseMap)
- {
- const U32 noiseRes = 128;
- LLVector3 noise[noiseRes*noiseRes];
-
- F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f;
- for (U32 i = 0; i < noiseRes*noiseRes; ++i)
- {
- noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f);
- noise[i].normVec();
- noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f;
- }
-
- LLImageGL::generateTextures(1, &mNoiseMap);
-
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);
- LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- }
-
- if (!mTrueNoiseMap)
- {
- const U32 noiseRes = 128;
- F32 noise[noiseRes*noiseRes*3];
- for (U32 i = 0; i < noiseRes*noiseRes*3; i++)
- {
- noise[i] = ll_frand()*2.0-1.0;
- }
-
- LLImageGL::generateTextures(1, &mTrueNoiseMap);
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap);
- LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- }
-
- if (!mLightFunc)
- {
- U32 lightResX = gSavedSettings.getU32("RenderSpecularResX");
- U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
- U8* lg = new U8[lightResX*lightResY];
-
- for (U32 y = 0; y < lightResY; ++y)
- {
- for (U32 x = 0; x < lightResX; ++x)
- {
- //spec func
- F32 sa = (F32) x/(lightResX-1);
- F32 spec = (F32) y/(lightResY-1);
- //lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255);
-
- //F32 sp = acosf(sa)/(1.f-spec);
-
- sa = powf(sa, gSavedSettings.getF32("RenderSpecularExponent"));
- F32 a = acosf(sa*0.25f+0.75f);
- F32 m = llmax(0.5f-spec*0.5f, 0.001f);
- F32 t2 = tanf(a)/m;
- t2 *= t2;
-
- F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f;
- F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2);
-
- lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255);
- }
- }
-
- LLImageGL::generateTextures(1, &mLightFunc);
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
- LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, lg);
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
-
- delete [] lg;
- }
- }
-
- gBumpImageList.restoreGL();
-}
-
-void LLPipeline::restoreGL()
-{
- LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_RESTORE_GL);
- assertInitialized();
-
- if (mVertexShadersEnabled)
- {
- LLViewerShaderMgr::instance()->setShaders();
- }
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- part->restoreGL();
- }
- }
- }
-}
-
-
-BOOL LLPipeline::canUseVertexShaders()
-{
- static const std::string vertex_shader_enable_feature_string = "VertexShaderEnable";
-
- if (sDisableShaders ||
- !gGLManager.mHasVertexShader ||
- !gGLManager.mHasFragmentShader ||
- !LLFeatureManager::getInstance()->isFeatureAvailable(vertex_shader_enable_feature_string) ||
- (assertInitialized() && mVertexShadersLoaded != 1) )
- {
- return FALSE;
- }
- else
- {
- return TRUE;
- }
-}
-
-BOOL LLPipeline::canUseWindLightShaders() const
-{
- return (!LLPipeline::sDisableShaders &&
- gWLSkyProgram.mProgramObject != 0 &&
- LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1);
-}
-
-BOOL LLPipeline::canUseWindLightShadersOnObjects() const
-{
- return (canUseWindLightShaders()
- && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0);
-}
-
-BOOL LLPipeline::canUseAntiAliasing() const
-{
- return TRUE;
-}
-
-void LLPipeline::unloadShaders()
-{
- LLMemType mt_us(LLMemType::MTYPE_PIPELINE_UNLOAD_SHADERS);
- LLViewerShaderMgr::instance()->unloadShaders();
-
- mVertexShadersLoaded = 0;
-}
-
-void LLPipeline::assertInitializedDoError()
-{
- llerrs << "LLPipeline used when uninitialized." << llendl;
-}
-
-//============================================================================
-
-void LLPipeline::enableShadows(const BOOL enable_shadows)
-{
- //should probably do something here to wrangle shadows....
-}
-
-S32 LLPipeline::getMaxLightingDetail() const
-{
- /*if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)
- {
- return 3;
- }
- else*/
- {
- return 1;
- }
-}
-
-S32 LLPipeline::setLightingDetail(S32 level)
-{
- LLMemType mt_ld(LLMemType::MTYPE_PIPELINE_LIGHTING_DETAIL);
- refreshCachedSettings();
-
- if (level < 0)
- {
- if (RenderLocalLights)
- {
- level = 1;
- }
- else
- {
- level = 0;
- }
- }
- level = llclamp(level, 0, getMaxLightingDetail());
- mLightingDetail = level;
-
- return mLightingDetail;
-}
-
-class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable>
-{
-public:
- const std::set<LLViewerFetchedTexture*>& mTextures;
-
- LLOctreeDirtyTexture(const std::set<LLViewerFetchedTexture*>& textures) : mTextures(textures) { }
-
- virtual void visit(const LLOctreeNode<LLDrawable>* node)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
-
- if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty())
- {
- for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
- {
- for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
- {
- LLDrawInfo* params = *j;
- LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params->mTexture);
- if (tex && mTextures.find(tex) != mTextures.end())
- {
- group->setState(LLSpatialGroup::GEOM_DIRTY);
- }
- }
- }
- }
-
- for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
- {
- LLSpatialBridge* bridge = *i;
- traverse(bridge->mOctree);
- }
- }
-};
-
-// Called when a texture changes # of channels (causes faces to move to alpha pool)
-void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerFetchedTexture*>& textures)
-{
- assertInitialized();
-
- // *TODO: This is inefficient and causes frame spikes; need a better way to do this
- // Most of the time is spent in dirty.traverse.
-
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- if (poolp->isFacePool())
- {
- ((LLFacePool*) poolp)->dirtyTextures(textures);
- }
- }
-
- LLOctreeDirtyTexture dirty(textures);
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- dirty.traverse(part->mOctree);
- }
- }
- }
-}
-
-LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
-{
- assertInitialized();
-
- LLDrawPool *poolp = NULL;
- switch( type )
- {
- case LLDrawPool::POOL_SIMPLE:
- poolp = mSimplePool;
- break;
-
- case LLDrawPool::POOL_GRASS:
- poolp = mGrassPool;
- break;
-
- case LLDrawPool::POOL_FULLBRIGHT:
- poolp = mFullbrightPool;
- break;
-
- case LLDrawPool::POOL_INVISIBLE:
- poolp = mInvisiblePool;
- break;
-
- case LLDrawPool::POOL_GLOW:
- poolp = mGlowPool;
- break;
-
- case LLDrawPool::POOL_TREE:
- poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 );
- break;
-
- case LLDrawPool::POOL_TERRAIN:
- poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 );
- break;
-
- case LLDrawPool::POOL_BUMP:
- poolp = mBumpPool;
- break;
-
- case LLDrawPool::POOL_ALPHA:
- poolp = mAlphaPool;
- break;
-
- case LLDrawPool::POOL_AVATAR:
- break; // Do nothing
-
- case LLDrawPool::POOL_SKY:
- poolp = mSkyPool;
- break;
-
- case LLDrawPool::POOL_WATER:
- poolp = mWaterPool;
- break;
-
- case LLDrawPool::POOL_GROUND:
- poolp = mGroundPool;
- break;
-
- case LLDrawPool::POOL_WL_SKY:
- poolp = mWLSkyPool;
- break;
-
- default:
- llassert(0);
- llerrs << "Invalid Pool Type in LLPipeline::findPool() type=" << type << llendl;
- break;
- }
-
- return poolp;
-}
-
-
-LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerTexture *tex0)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
- LLDrawPool *poolp = findPool(type, tex0);
- if (poolp)
- {
- return poolp;
- }
-
- LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0);
- addPool( new_poolp );
-
- return new_poolp;
-}
-
-
-// static
-LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
- U32 type = getPoolTypeFromTE(te, imagep);
- return gPipeline.getPool(type, imagep);
-}
-
-//static
-U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
-{
- LLMemType mt_gpt(LLMemType::MTYPE_PIPELINE_GET_POOL_TYPE);
-
- if (!te || !imagep)
- {
- return 0;
- }
-
- bool alpha = te->getColor().mV[3] < 0.999f;
- if (imagep)
- {
- alpha = alpha || (imagep->getComponents() == 4 && imagep->getType() != LLViewerTexture::MEDIA_TEXTURE) || (imagep->getComponents() == 2);
- }
-
- if (alpha)
- {
- return LLDrawPool::POOL_ALPHA;
- }
- else if ((te->getBumpmap() || te->getShiny()))
- {
- return LLDrawPool::POOL_BUMP;
- }
- else
- {
- return LLDrawPool::POOL_SIMPLE;
- }
-}
-
-
-void LLPipeline::addPool(LLDrawPool *new_poolp)
-{
- LLMemType mt_a(LLMemType::MTYPE_PIPELINE_ADD_POOL);
- assertInitialized();
- mPools.insert(new_poolp);
- addToQuickLookup( new_poolp );
-}
-
-void LLPipeline::allocDrawable(LLViewerObject *vobj)
-{
- LLMemType mt_ad(LLMemType::MTYPE_PIPELINE_ALLOCATE_DRAWABLE);
- LLDrawable *drawable = new LLDrawable();
- vobj->mDrawable = drawable;
-
- drawable->mVObjp = vobj;
-
- //encompass completely sheared objects by taking
- //the most extreme point possible (<1,1,0.5>)
- drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length());
- if (vobj->isOrphaned())
- {
- drawable->setState(LLDrawable::FORCE_INVISIBLE);
- }
- drawable->updateXform(TRUE);
-}
-
-
-static LLFastTimer::DeclareTimer FTM_UNLINK("Unlink");
-static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_MOVE_LIST("Movelist");
-static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_SPATIAL_PARTITION("Spatial Partition");
-static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_LIGHT_SET("Light Set");
-static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_HIGHLIGHT_SET("Highlight Set");
-
-void LLPipeline::unlinkDrawable(LLDrawable *drawable)
-{
- LLFastTimer t(FTM_UNLINK);
-
- assertInitialized();
-
- LLPointer<LLDrawable> drawablep = drawable; // make sure this doesn't get deleted before we are done
-
- // Based on flags, remove the drawable from the queues that it's on.
- if (drawablep->isState(LLDrawable::ON_MOVE_LIST))
- {
- LLFastTimer t(FTM_REMOVE_FROM_MOVE_LIST);
- LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep);
- if (iter != mMovedList.end())
- {
- mMovedList.erase(iter);
- }
- }
-
- if (drawablep->getSpatialGroup())
- {
- LLFastTimer t(FTM_REMOVE_FROM_SPATIAL_PARTITION);
- if (!drawablep->getSpatialGroup()->mSpatialPartition->remove(drawablep, drawablep->getSpatialGroup()))
- {
-#ifdef LL_RELEASE_FOR_DOWNLOAD
- llwarns << "Couldn't remove object from spatial group!" << llendl;
-#else
- llerrs << "Couldn't remove object from spatial group!" << llendl;
-#endif
- }
- }
-
- {
- LLFastTimer t(FTM_REMOVE_FROM_LIGHT_SET);
- mLights.erase(drawablep);
-
- for (light_set_t::iterator iter = mNearbyLights.begin();
- iter != mNearbyLights.end(); iter++)
- {
- if (iter->drawable == drawablep)
- {
- mNearbyLights.erase(iter);
- break;
- }
- }
- }
-
- {
- LLFastTimer t(FTM_REMOVE_FROM_HIGHLIGHT_SET);
- HighlightItem item(drawablep);
- mHighlightSet.erase(item);
-
- if (mHighlightObject == drawablep)
- {
- mHighlightObject = NULL;
- }
- }
-
- for (U32 i = 0; i < 2; ++i)
- {
- if (mShadowSpotLight[i] == drawablep)
- {
- mShadowSpotLight[i] = NULL;
- }
-
- if (mTargetShadowSpotLight[i] == drawablep)
- {
- mTargetShadowSpotLight[i] = NULL;
- }
- }
-
-
-}
-
-U32 LLPipeline::addObject(LLViewerObject *vobj)
-{
- LLMemType mt_ao(LLMemType::MTYPE_PIPELINE_ADD_OBJECT);
-
- if (RenderDelayCreation)
- {
- mCreateQ.push_back(vobj);
- }
- else
- {
- createObject(vobj);
- }
-
- return 1;
-}
-
-void LLPipeline::createObjects(F32 max_dtime)
-{
- LLFastTimer ftm(FTM_GEO_UPDATE);
- LLMemType mt(LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS);
-
- LLTimer update_timer;
-
- while (!mCreateQ.empty() && update_timer.getElapsedTimeF32() < max_dtime)
- {
- LLViewerObject* vobj = mCreateQ.front();
- if (!vobj->isDead())
- {
- createObject(vobj);
- }
- mCreateQ.pop_front();
- }
-
- //for (LLViewerObject::vobj_list_t::iterator iter = mCreateQ.begin(); iter != mCreateQ.end(); ++iter)
- //{
- // createObject(*iter);
- //}
-
- //mCreateQ.clear();
-}
-
-void LLPipeline::createObject(LLViewerObject* vobj)
-{
- LLDrawable* drawablep = vobj->mDrawable;
-
- if (!drawablep)
- {
- drawablep = vobj->createDrawable(this);
- }
- else
- {
- llerrs << "Redundant drawable creation!" << llendl;
- }
-
- llassert(drawablep);
-
- if (vobj->getParent())
- {
- vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1
- }
- else
- {
- vobj->setDrawableParent(NULL); // LLPipeline::addObject 2
- }
-
- markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE);
-
- if (drawablep->getVOVolume() && RenderAnimateRes)
- {
- // fun animated res
- drawablep->updateXform(TRUE);
- drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
- drawablep->setScale(LLVector3(0,0,0));
- drawablep->makeActive();
- }
-}
-
-
-void LLPipeline::resetFrameStats()
-{
- assertInitialized();
-
- LLViewerStats::getInstance()->mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f);
-
- if (mBatchCount > 0)
- {
- mMeanBatchSize = gPipeline.mTrianglesDrawn/gPipeline.mBatchCount;
- }
- mTrianglesDrawn = 0;
- sCompiles = 0;
- mVerticesRelit = 0;
- mLightingChanges = 0;
- mGeometryChanges = 0;
- mNumVisibleFaces = 0;
-
- if (mOldRenderDebugMask != mRenderDebugMask)
- {
- gObjectList.clearDebugText();
- mOldRenderDebugMask = mRenderDebugMask;
- }
-
-}
-
-//external functions for asynchronous updating
-void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep)
-{
- if (FreezeTime)
- {
- return;
- }
- if (!drawablep)
- {
- llerrs << "updateMove called with NULL drawablep" << llendl;
- return;
- }
- if (drawablep->isState(LLDrawable::EARLY_MOVE))
- {
- return;
- }
-
- assertInitialized();
-
- // update drawable now
- drawablep->clearState(LLDrawable::MOVE_UNDAMPED); // force to DAMPED
- drawablep->updateMove(); // returns done
- drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
- // Put on move list so that EARLY_MOVE gets cleared
- if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
- {
- mMovedList.push_back(drawablep);
- drawablep->setState(LLDrawable::ON_MOVE_LIST);
- }
-}
-
-void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep)
-{
- if (FreezeTime)
- {
- return;
- }
- if (!drawablep)
- {
- llerrs << "updateMove called with NULL drawablep" << llendl;
- return;
- }
- if (drawablep->isState(LLDrawable::EARLY_MOVE))
- {
- return;
- }
-
- assertInitialized();
-
- // update drawable now
- drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED
- drawablep->updateMove();
- drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
- // Put on move list so that EARLY_MOVE gets cleared
- if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
- {
- mMovedList.push_back(drawablep);
- drawablep->setState(LLDrawable::ON_MOVE_LIST);
- }
-}
-
-void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)
-{
- for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin();
- iter != moved_list.end(); )
- {
- LLDrawable::drawable_vector_t::iterator curiter = iter++;
- LLDrawable *drawablep = *curiter;
- BOOL done = TRUE;
- if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE)))
- {
- done = drawablep->updateMove();
- }
- drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);
- if (done)
- {
- drawablep->clearState(LLDrawable::ON_MOVE_LIST);
- iter = moved_list.erase(curiter);
- }
- }
-}
-
-static LLFastTimer::DeclareTimer FTM_OCTREE_BALANCE("Balance Octree");
-static LLFastTimer::DeclareTimer FTM_UPDATE_MOVE("Update Move");
-
-void LLPipeline::updateMove()
-{
- LLFastTimer t(FTM_UPDATE_MOVE);
- LLMemType mt_um(LLMemType::MTYPE_PIPELINE_UPDATE_MOVE);
-
- if (FreezeTime)
- {
- return;
- }
-
- assertInitialized();
-
- {
- static LLFastTimer::DeclareTimer ftm("Retexture");
- LLFastTimer t(ftm);
-
- for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin();
- iter != mRetexturedList.end(); ++iter)
- {
- LLDrawable* drawablep = *iter;
- if (drawablep && !drawablep->isDead())
- {
- drawablep->updateTexture();
- }
- }
- mRetexturedList.clear();
- }
-
- {
- static LLFastTimer::DeclareTimer ftm("Moved List");
- LLFastTimer t(ftm);
- updateMovedList(mMovedList);
- }
-
- //balance octrees
- {
- LLFastTimer ot(FTM_OCTREE_BALANCE);
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- part->mOctree->balance();
- }
- }
- }
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Culling and occlusion testing
-/////////////////////////////////////////////////////////////////////////////
-
-//static
-F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
-{
- LLVector3 lookAt = center - camera.getOrigin();
- F32 dist = lookAt.length();
-
- //ramp down distance for nearby objects
- //shrink dist by dist/16.
- if (dist < 16.f)
- {
- dist /= 16.f;
- dist *= dist;
- dist *= 16.f;
- }
-
- //get area of circle around node
- F32 app_angle = atanf(size.length()/dist);
- F32 radius = app_angle*LLDrawable::sCurPixelAngle;
- return radius*radius * F_PI;
-}
-
-//static
-F32 LLPipeline::calcPixelArea(const LLVector4a& center, const LLVector4a& size, LLCamera &camera)
-{
- LLVector4a origin;
- origin.load3(camera.getOrigin().mV);
-
- LLVector4a lookAt;
- lookAt.setSub(center, origin);
- F32 dist = lookAt.getLength3().getF32();
-
- //ramp down distance for nearby objects
- //shrink dist by dist/16.
- if (dist < 16.f)
- {
- dist /= 16.f;
- dist *= dist;
- dist *= 16.f;
- }
-
- //get area of circle around node
- F32 app_angle = atanf(size.getLength3().getF32()/dist);
- F32 radius = app_angle*LLDrawable::sCurPixelAngle;
- return radius*radius * F_PI;
-}
-
-void LLPipeline::grabReferences(LLCullResult& result)
-{
- sCull = &result;
-}
-
-void LLPipeline::clearReferences()
-{
- sCull = NULL;
-}
-
-void check_references(LLSpatialGroup* group, LLDrawable* drawable)
-{
- for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
- {
- if (drawable == *i)
- {
- llerrs << "LLDrawable deleted while actively reference by LLPipeline." << llendl;
- }
- }
-}
-
-void check_references(LLDrawable* drawable, LLFace* face)
-{
- for (S32 i = 0; i < drawable->getNumFaces(); ++i)
- {
- if (drawable->getFace(i) == face)
- {
- llerrs << "LLFace deleted while actively referenced by LLPipeline." << llendl;
- }
- }
-}
-
-void check_references(LLSpatialGroup* group, LLFace* face)
-{
- for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
- {
- LLDrawable* drawable = *i;
- check_references(drawable, face);
- }
-}
-
-void LLPipeline::checkReferences(LLFace* face)
-{
-#if 0
- if (sCull)
- {
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- check_references(group, face);
- }
-
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- check_references(group, face);
- }
-
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- check_references(group, face);
- }
-
- for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter)
- {
- LLDrawable* drawable = *iter;
- check_references(drawable, face);
- }
- }
-#endif
-}
-
-void LLPipeline::checkReferences(LLDrawable* drawable)
-{
-#if 0
- if (sCull)
- {
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- check_references(group, drawable);
- }
-
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- check_references(group, drawable);
- }
-
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- check_references(group, drawable);
- }
-
- for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter)
- {
- if (drawable == *iter)
- {
- llerrs << "LLDrawable deleted while actively referenced by LLPipeline." << llendl;
- }
- }
- }
-#endif
-}
-
-void check_references(LLSpatialGroup* group, LLDrawInfo* draw_info)
-{
- for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
- {
- LLSpatialGroup::drawmap_elem_t& draw_vec = i->second;
- for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j)
- {
- LLDrawInfo* params = *j;
- if (params == draw_info)
- {
- llerrs << "LLDrawInfo deleted while actively referenced by LLPipeline." << llendl;
- }
- }
- }
-}
-
-
-void LLPipeline::checkReferences(LLDrawInfo* draw_info)
-{
-#if 0
- if (sCull)
- {
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- check_references(group, draw_info);
- }
-
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- check_references(group, draw_info);
- }
-
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- check_references(group, draw_info);
- }
- }
-#endif
-}
-
-void LLPipeline::checkReferences(LLSpatialGroup* group)
-{
-#if 0
- if (sCull)
- {
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
- {
- if (group == *iter)
- {
- llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
- }
- }
-
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
- {
- if (group == *iter)
- {
- llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
- }
- }
-
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
- {
- if (group == *iter)
- {
- llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
- }
- }
- }
-#endif
-}
-
-
-BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera)
-{
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
-
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- if (hasRenderType(part->mDrawableType))
- {
- if (part->visibleObjectsInFrustum(camera))
- {
- return TRUE;
- }
- }
- }
- }
- }
-
- return FALSE;
-}
-
-BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& max)
-{
- const F32 X = 65536.f;
-
- min = LLVector3(X,X,X);
- max = LLVector3(-X,-X,-X);
-
- U32 saved_camera_id = LLViewerCamera::sCurCameraID;
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
-
- BOOL res = TRUE;
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
-
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- if (hasRenderType(part->mDrawableType))
- {
- if (!part->getVisibleExtents(camera, min, max))
- {
- res = FALSE;
- }
- }
- }
- }
- }
-
- LLViewerCamera::sCurCameraID = saved_camera_id;
-
- return res;
-}
-
-static LLFastTimer::DeclareTimer FTM_CULL("Object Culling");
-
-void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip, LLPlane* planep)
-{
- LLFastTimer t(FTM_CULL);
- LLMemType mt_uc(LLMemType::MTYPE_PIPELINE_UPDATE_CULL);
-
- grabReferences(result);
-
- sCull->clear();
-
- BOOL to_texture = LLPipeline::sUseOcclusion > 1 &&
- !hasRenderType(LLPipeline::RENDER_TYPE_HUD) &&
- LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
- gPipeline.canUseVertexShaders() &&
- sRenderGlow;
-
- if (to_texture)
- {
- mScreen.bindTarget();
- }
-
- if (sUseOcclusion > 1)
- {
- gGL.setColorMask(false, false);
- }
-
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadMatrix(gGLLastProjection);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLLastModelView);
-
-
- LLVertexBuffer::unbind();
- LLGLDisable blend(GL_BLEND);
- LLGLDisable test(GL_ALPHA_TEST);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-
- //setup a clip plane in projection matrix for reflection renders (prevents flickering from occlusion culling)
- LLViewerRegion* region = gAgent.getRegion();
- LLPlane plane;
-
- if (planep)
- {
- plane = *planep;
- }
- else
- {
- if (region)
- {
- LLVector3 pnorm;
- F32 height = region->getWaterHeight();
- if (water_clip < 0)
- { //camera is above water, clip plane points up
- pnorm.setVec(0,0,1);
- plane.setVec(pnorm, -height);
- }
- else if (water_clip > 0)
- { //camera is below water, clip plane points down
- pnorm = LLVector3(0,0,-1);
- plane.setVec(pnorm, height);
- }
- }
- }
-
- glh::matrix4f modelview = glh_get_last_modelview();
- glh::matrix4f proj = glh_get_last_projection();
- LLGLUserClipPlane clip(plane, modelview, proj, water_clip != 0 && LLPipeline::sReflectionRender);
-
- LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-
- bool bound_shader = false;
- if (gPipeline.canUseVertexShaders() && LLGLSLShader::sCurBoundShader == 0)
- { //if no shader is currently bound, use the occlusion shader instead of fixed function if we can
- // (shadow render uses a special shader that clamps to clip planes)
- bound_shader = true;
- gOcclusionProgram.bind();
- }
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
- if (water_clip != 0)
- {
- LLPlane plane(LLVector3(0,0, (F32) -water_clip), (F32) water_clip*region->getWaterHeight());
- camera.setUserClipPlane(plane);
- }
- else
- {
- camera.disableUserClipPlane();
- }
-
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- if (hasRenderType(part->mDrawableType))
- {
- part->cull(camera);
- }
- }
- }
- }
-
- if (bound_shader)
- {
- gOcclusionProgram.unbind();
- }
-
- camera.disableUserClipPlane();
-
- if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) &&
- gSky.mVOSkyp.notNull() &&
- gSky.mVOSkyp->mDrawable.notNull())
- {
- gSky.mVOSkyp->mDrawable->setVisible(camera);
- sCull->pushDrawable(gSky.mVOSkyp->mDrawable);
- gSky.updateCull();
- stop_glerror();
- }
-
- if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) &&
- !gPipeline.canUseWindLightShaders() &&
- gSky.mVOGroundp.notNull() &&
- gSky.mVOGroundp->mDrawable.notNull() &&
- !LLPipeline::sWaterReflections)
- {
- gSky.mVOGroundp->mDrawable->setVisible(camera);
- sCull->pushDrawable(gSky.mVOGroundp->mDrawable);
- }
-
-
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
-
- if (sUseOcclusion > 1)
- {
- gGL.setColorMask(true, false);
- }
-
- if (to_texture)
- {
- mScreen.flush();
- }
-}
-
-void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
-{
- if (group->getData().empty())
- {
- return;
- }
-
- group->setVisible();
-
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
- {
- group->updateDistance(camera);
- }
-
- const F32 MINIMUM_PIXEL_AREA = 16.f;
-
- if (group->mPixelArea < MINIMUM_PIXEL_AREA)
- {
- return;
- }
-
- if (sMinRenderSize > 0.f &&
- llmax(llmax(group->mBounds[1][0], group->mBounds[1][1]), group->mBounds[1][2]) < sMinRenderSize)
- {
- return;
- }
-
- assertInitialized();
-
- if (!group->mSpatialPartition->mRenderByGroup)
- { //render by drawable
- sCull->pushDrawableGroup(group);
- }
- else
- { //render by group
- sCull->pushVisibleGroup(group);
- }
-
- mNumVisibleNodes++;
-}
-
-void LLPipeline::markOccluder(LLSpatialGroup* group)
-{
- if (sUseOcclusion > 1 && group && !group->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION))
- {
- LLSpatialGroup* parent = group->getParent();
-
- if (!parent || !parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
- { //only mark top most occluders as active occlusion
- sCull->pushOcclusionGroup(group);
- group->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
-
- if (parent &&
- !parent->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION) &&
- parent->getElementCount() == 0 &&
- parent->needsUpdate())
- {
- sCull->pushOcclusionGroup(group);
- parent->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
- }
- }
- }
-}
-
-void LLPipeline::doOcclusion(LLCamera& camera)
-{
- if (LLPipeline::sUseOcclusion > 1 && sCull->hasOcclusionGroups())
- {
- LLVertexBuffer::unbind();
-
- if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
- {
- gGL.setColorMask(true, false, false, false);
- }
- else
- {
- gGL.setColorMask(false, false);
- }
- LLGLDisable blend(GL_BLEND);
- LLGLDisable test(GL_ALPHA_TEST);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-
- LLGLDisable cull(GL_CULL_FACE);
-
-
- bool bind_shader = LLGLSLShader::sNoFixedFunction && LLGLSLShader::sCurBoundShader == 0;
- if (bind_shader)
- {
- if (LLPipeline::sShadowRender)
- {
- gDeferredShadowProgram.bind();
- }
- else
- {
- gOcclusionProgram.bind();
- }
- }
-
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- group->doOcclusion(&camera);
- group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
- }
-
- if (bind_shader)
- {
- if (LLPipeline::sShadowRender)
- {
- gDeferredShadowProgram.unbind();
- }
- else
- {
- gOcclusionProgram.unbind();
- }
- }
-
- gGL.setColorMask(true, false);
- }
-}
-
-BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
-{
- BOOL update_complete = drawablep->updateGeometry(priority);
- if (update_complete && assertInitialized())
- {
- drawablep->setState(LLDrawable::BUILT);
- mGeometryChanges++;
- }
- return update_complete;
-}
-
-void LLPipeline::updateGL()
-{
- while (!LLGLUpdate::sGLQ.empty())
- {
- LLGLUpdate* glu = LLGLUpdate::sGLQ.front();
- glu->updateGL();
- glu->mInQ = FALSE;
- LLGLUpdate::sGLQ.pop_front();
- }
-}
-
-void LLPipeline::rebuildPriorityGroups()
-{
- LLTimer update_timer;
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
-
- assertInitialized();
-
- gMeshRepo.notifyLoadedMeshes();
-
- mGroupQ1Locked = true;
- // Iterate through all drawables on the priority build queue,
- for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin();
- iter != mGroupQ1.end(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- group->rebuildGeom();
- group->clearState(LLSpatialGroup::IN_BUILD_Q1);
- }
-
- mGroupQ1.clear();
- mGroupQ1Locked = false;
-
-}
-
-void LLPipeline::rebuildGroups()
-{
- if (mGroupQ2.empty())
- {
- return;
- }
-
- mGroupQ2Locked = true;
- // Iterate through some drawables on the non-priority build queue
- S32 size = (S32) mGroupQ2.size();
- S32 min_count = llclamp((S32) ((F32) (size * size)/4096*0.25f), 1, size);
-
- S32 count = 0;
-
- std::sort(mGroupQ2.begin(), mGroupQ2.end(), LLSpatialGroup::CompareUpdateUrgency());
-
- LLSpatialGroup::sg_vector_t::iterator iter;
- LLSpatialGroup::sg_vector_t::iterator last_iter = mGroupQ2.begin();
-
- for (iter = mGroupQ2.begin();
- iter != mGroupQ2.end() && count <= min_count; ++iter)
- {
- LLSpatialGroup* group = *iter;
- last_iter = iter;
-
- if (!group->isDead())
- {
- group->rebuildGeom();
-
- if (group->mSpatialPartition->mRenderByGroup)
- {
- count++;
- }
- }
-
- group->clearState(LLSpatialGroup::IN_BUILD_Q2);
- }
-
- mGroupQ2.erase(mGroupQ2.begin(), ++last_iter);
-
- mGroupQ2Locked = false;
-
- updateMovedList(mMovedBridge);
-}
-
-void LLPipeline::updateGeom(F32 max_dtime)
-{
- LLTimer update_timer;
- LLMemType mt(LLMemType::MTYPE_PIPELINE_UPDATE_GEOM);
- LLPointer<LLDrawable> drawablep;
-
- LLFastTimer t(FTM_GEO_UPDATE);
-
- assertInitialized();
-
- if (sDelayedVBOEnable > 0)
- {
- if (--sDelayedVBOEnable <= 0)
- {
- resetVertexBuffers();
- LLVertexBuffer::sEnableVBOs = TRUE;
- }
- }
-
- // notify various object types to reset internal cost metrics, etc.
- // for now, only LLVOVolume does this to throttle LOD changes
- LLVOVolume::preUpdateGeom();
-
- // Iterate through all drawables on the priority build queue,
- for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin();
- iter != mBuildQ1.end();)
- {
- LLDrawable::drawable_list_t::iterator curiter = iter++;
- LLDrawable* drawablep = *curiter;
- if (drawablep && !drawablep->isDead())
- {
- if (drawablep->isState(LLDrawable::IN_REBUILD_Q2))
- {
- drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
- LLDrawable::drawable_list_t::iterator find = std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep);
- if (find != mBuildQ2.end())
- {
- mBuildQ2.erase(find);
- }
- }
-
- if (updateDrawableGeom(drawablep, TRUE))
- {
- drawablep->clearState(LLDrawable::IN_REBUILD_Q1);
- mBuildQ1.erase(curiter);
- }
- }
- else
- {
- mBuildQ1.erase(curiter);
- }
- }
-
- // Iterate through some drawables on the non-priority build queue
- S32 min_count = 16;
- S32 size = (S32) mBuildQ2.size();
- if (size > 1024)
- {
- min_count = llclamp((S32) (size * (F32) size/4096), 16, size);
- }
-
- S32 count = 0;
-
- max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime);
- LLSpatialGroup* last_group = NULL;
- LLSpatialBridge* last_bridge = NULL;
-
- for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin();
- iter != mBuildQ2.end(); )
- {
- LLDrawable::drawable_list_t::iterator curiter = iter++;
- LLDrawable* drawablep = *curiter;
-
- LLSpatialBridge* bridge = drawablep->isRoot() ? drawablep->getSpatialBridge() :
- drawablep->getParent()->getSpatialBridge();
-
- if (drawablep->getSpatialGroup() != last_group &&
- (!last_bridge || bridge != last_bridge) &&
- (update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count)
- {
- break;
- }
-
- //make sure updates don't stop in the middle of a spatial group
- //to avoid thrashing (objects are enqueued by group)
- last_group = drawablep->getSpatialGroup();
- last_bridge = bridge;
-
- BOOL update_complete = TRUE;
- if (!drawablep->isDead())
- {
- update_complete = updateDrawableGeom(drawablep, FALSE);
- count++;
- }
- if (update_complete)
- {
- drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
- mBuildQ2.erase(curiter);
- }
- }
-
- updateMovedList(mMovedBridge);
-}
-
-void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_VISIBLE);
-
- if(drawablep && !drawablep->isDead())
- {
- if (drawablep->isSpatialBridge())
- {
- const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable;
- llassert(root); // trying to catch a bad assumption
- if (root && // // this test may not be needed, see above
- root->getVObj()->isAttachment())
- {
- LLDrawable* rootparent = root->getParent();
- if (rootparent) // this IS sometimes NULL
- {
- LLViewerObject *vobj = rootparent->getVObj();
- llassert(vobj); // trying to catch a bad assumption
- if (vobj) // this test may not be needed, see above
- {
- const LLVOAvatar* av = vobj->asAvatar();
- if (av && av->isImpostor())
- {
- return;
- }
- }
- }
- }
- sCull->pushBridge((LLSpatialBridge*) drawablep);
- }
- else
- {
- sCull->pushDrawable(drawablep);
- }
-
- drawablep->setVisible(camera);
- }
-}
-
-void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
-{
- LLMemType mt_mm(LLMemType::MTYPE_PIPELINE_MARK_MOVED);
-
- if (!drawablep)
- {
- //llerrs << "Sending null drawable to moved list!" << llendl;
- return;
- }
-
- if (drawablep->isDead())
- {
- llwarns << "Marking NULL or dead drawable moved!" << llendl;
- return;
- }
-
- if (drawablep->getParent())
- {
- //ensure that parent drawables are moved first
- markMoved(drawablep->getParent(), damped_motion);
- }
-
- assertInitialized();
-
- if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
- {
- if (drawablep->isSpatialBridge())
- {
- mMovedBridge.push_back(drawablep);
- }
- else
- {
- mMovedList.push_back(drawablep);
- }
- drawablep->setState(LLDrawable::ON_MOVE_LIST);
- }
- if (damped_motion == FALSE)
- {
- drawablep->setState(LLDrawable::MOVE_UNDAMPED); // UNDAMPED trumps DAMPED
- }
- else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
- {
- drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
- }
-}
-
-void LLPipeline::markShift(LLDrawable *drawablep)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_SHIFT);
-
- if (!drawablep || drawablep->isDead())
- {
- return;
- }
-
- assertInitialized();
-
- if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST))
- {
- drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE);
- if (drawablep->getParent())
- {
- markShift(drawablep->getParent());
- }
- mShiftList.push_back(drawablep);
- drawablep->setState(LLDrawable::ON_SHIFT_LIST);
- }
-}
-
-void LLPipeline::shiftObjects(const LLVector3 &offset)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS);
-
- assertInitialized();
-
- glClear(GL_DEPTH_BUFFER_BIT);
- gDepthDirty = TRUE;
-
- LLVector4a offseta;
- offseta.load3(offset.mV);
-
- for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin();
- iter != mShiftList.end(); iter++)
- {
- LLDrawable *drawablep = *iter;
- if (drawablep->isDead())
- {
- continue;
- }
- drawablep->shiftPos(offseta);
- drawablep->clearState(LLDrawable::ON_SHIFT_LIST);
- }
- mShiftList.resize(0);
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- part->shift(offseta);
- }
- }
- }
-
- LLHUDText::shiftAll(offset);
- LLHUDNameTag::shiftAll(offset);
- display_update_camera();
-}
-
-void LLPipeline::markTextured(LLDrawable *drawablep)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_TEXTURED);
-
- if (drawablep && !drawablep->isDead() && assertInitialized())
- {
- mRetexturedList.insert(drawablep);
- }
-}
-
-void LLPipeline::markGLRebuild(LLGLUpdate* glu)
-{
- if (glu && !glu->mInQ)
- {
- LLGLUpdate::sGLQ.push_back(glu);
- glu->mInQ = TRUE;
- }
-}
-
-void LLPipeline::markPartitionMove(LLDrawable* drawable)
-{
- if (!drawable->isState(LLDrawable::PARTITION_MOVE) &&
- !drawable->getPositionGroup().equals3(LLVector4a::getZero()))
- {
- drawable->setState(LLDrawable::PARTITION_MOVE);
- mPartitionQ.push_back(drawable);
- }
-}
-
-void LLPipeline::processPartitionQ()
-{
- for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter)
- {
- LLDrawable* drawable = *iter;
- if (!drawable->isDead())
- {
- drawable->updateBinRadius();
- drawable->movePartition();
- }
- drawable->clearState(LLDrawable::PARTITION_MOVE);
- }
-
- mPartitionQ.clear();
-}
-
-void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
-
- if (group && !group->isDead() && group->mSpatialPartition)
- {
- if (group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD)
- {
- priority = TRUE;
- }
-
- if (priority)
- {
- if (!group->isState(LLSpatialGroup::IN_BUILD_Q1))
- {
- llassert_always(!mGroupQ1Locked);
-
- mGroupQ1.push_back(group);
- group->setState(LLSpatialGroup::IN_BUILD_Q1);
-
- if (group->isState(LLSpatialGroup::IN_BUILD_Q2))
- {
- LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group);
- if (iter != mGroupQ2.end())
- {
- mGroupQ2.erase(iter);
- }
- group->clearState(LLSpatialGroup::IN_BUILD_Q2);
- }
- }
- }
- else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1))
- {
- llassert_always(!mGroupQ2Locked);
- mGroupQ2.push_back(group);
- group->setState(LLSpatialGroup::IN_BUILD_Q2);
-
- }
- }
-}
-
-void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_REBUILD);
-
- if (drawablep && !drawablep->isDead() && assertInitialized())
- {
- if (!drawablep->isState(LLDrawable::BUILT))
- {
- priority = TRUE;
- }
- if (priority)
- {
- if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1))
- {
- mBuildQ1.push_back(drawablep);
- drawablep->setState(LLDrawable::IN_REBUILD_Q1); // mark drawable as being in priority queue
- }
- }
- else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2))
- {
- mBuildQ2.push_back(drawablep);
- drawablep->setState(LLDrawable::IN_REBUILD_Q2); // need flag here because it is just a list
- }
- if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION))
- {
- drawablep->getVObj()->setChanged(LLXform::SILHOUETTE);
- }
- drawablep->setState(flag);
- }
-}
-
-static LLFastTimer::DeclareTimer FTM_RESET_DRAWORDER("Reset Draw Order");
-
-void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
-{
- if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR,
- LLPipeline::RENDER_TYPE_GROUND,
- LLPipeline::RENDER_TYPE_TERRAIN,
- LLPipeline::RENDER_TYPE_TREE,
- LLPipeline::RENDER_TYPE_SKY,
- LLPipeline::RENDER_TYPE_VOIDWATER,
- LLPipeline::RENDER_TYPE_WATER,
- LLPipeline::END_RENDER_TYPES))
- {
- //clear faces from face pools
- LLFastTimer t(FTM_RESET_DRAWORDER);
- gPipeline.resetDrawOrders();
- }
-
- LLFastTimer ftm(FTM_STATESORT);
- LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
-
- //LLVertexBuffer::unbind();
-
- grabReferences(result);
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- group->checkOcclusion();
- if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
- {
- markOccluder(group);
- }
- else
- {
- group->setVisible();
- for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
- {
- markVisible(*i, camera);
- }
-
- if (!sDelayVBUpdate)
- { //rebuild mesh as soon as we know it's visible
- group->rebuildMesh();
- }
- }
- }
-
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
- {
- LLSpatialGroup* last_group = NULL;
- for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
- {
- LLCullResult::bridge_list_t::iterator cur_iter = i;
- LLSpatialBridge* bridge = *cur_iter;
- LLSpatialGroup* group = bridge->getSpatialGroup();
-
- if (last_group == NULL)
- {
- last_group = group;
- }
-
- if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
- {
- stateSort(bridge, camera);
- }
-
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
- last_group != group && last_group->changeLOD())
- {
- last_group->mLastUpdateDistance = last_group->mDistance;
- }
-
- last_group = group;
- }
-
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
- last_group && last_group->changeLOD())
- {
- last_group->mLastUpdateDistance = last_group->mDistance;
- }
- }
-
- for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- group->checkOcclusion();
- if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
- {
- markOccluder(group);
- }
- else
- {
- group->setVisible();
- stateSort(group, camera);
-
- if (!sDelayVBUpdate)
- { //rebuild mesh as soon as we know it's visible
- group->rebuildMesh();
- }
- }
- }
-
- {
- LLFastTimer ftm(FTM_STATESORT_DRAWABLE);
- for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList();
- iter != sCull->endVisibleList(); ++iter)
- {
- LLDrawable *drawablep = *iter;
- if (!drawablep->isDead())
- {
- stateSort(drawablep, camera);
- }
- }
- }
-
- postSort(camera);
-}
-
-void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
- if (group->changeLOD())
- {
- for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
- {
- LLDrawable* drawablep = *i;
- stateSort(drawablep, camera);
- }
-
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
- { //avoid redundant stateSort calls
- group->mLastUpdateDistance = group->mDistance;
- }
- }
-
-}
-
-void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
- if (bridge->getSpatialGroup()->changeLOD())
- {
- bool force_update = false;
- bridge->updateDistance(camera, force_update);
- }
-}
-
-void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
-
- if (!drawablep
- || drawablep->isDead()
- || !hasRenderType(drawablep->getRenderType()))
- {
- return;
- }
-
- if (LLSelectMgr::getInstance()->mHideSelectedObjects)
- {
- if (drawablep->getVObj().notNull() &&
- drawablep->getVObj()->isSelected())
- {
- return;
- }
- }
-
- if (drawablep->isAvatar())
- { //don't draw avatars beyond render distance or if we don't have a spatial group.
- if ((drawablep->getSpatialGroup() == NULL) ||
- (drawablep->getSpatialGroup()->mDistance > LLVOAvatar::sRenderDistance))
- {
- return;
- }
-
- LLVOAvatar* avatarp = (LLVOAvatar*) drawablep->getVObj().get();
- if (!avatarp->isVisible())
- {
- return;
- }
- }
-
- assertInitialized();
-
- if (hasRenderType(drawablep->mRenderType))
- {
- if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE))
- {
- drawablep->setVisible(camera, NULL, FALSE);
- }
- else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE))
- {
- // clear invisible flag here to avoid single frame glitch
- drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE);
- }
- }
-
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
- {
- //if (drawablep->isVisible()) isVisible() check here is redundant, if it wasn't visible, it wouldn't be here
- {
- if (!drawablep->isActive())
- {
- bool force_update = false;
- drawablep->updateDistance(camera, force_update);
- }
- else if (drawablep->isAvatar())
- {
- bool force_update = false;
- drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility()
- }
- }
- }
-
- if (!drawablep->getVOVolume())
- {
- for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
- iter != drawablep->mFaces.end(); iter++)
- {
- LLFace* facep = *iter;
-
- if (facep->hasGeometry())
- {
- if (facep->getPool())
- {
- facep->getPool()->enqueue(facep);
- }
- else
- {
- break;
- }
- }
- }
- }
-
-
- mNumVisibleFaces += drawablep->getNumFaces();
-}
-
-
-void forAllDrawables(LLCullResult::sg_list_t::iterator begin,
- LLCullResult::sg_list_t::iterator end,
- void (*func)(LLDrawable*))
-{
- for (LLCullResult::sg_list_t::iterator i = begin; i != end; ++i)
- {
- for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j)
- {
- func(*j);
- }
- }
-}
-
-void LLPipeline::forAllVisibleDrawables(void (*func)(LLDrawable*))
-{
- forAllDrawables(sCull->beginDrawableGroups(), sCull->endDrawableGroups(), func);
- forAllDrawables(sCull->beginVisibleGroups(), sCull->endVisibleGroups(), func);
-}
-
-//function for creating scripted beacons
-void renderScriptedBeacons(LLDrawable* drawablep)
-{
- LLViewerObject *vobj = drawablep->getVObj();
- if (vobj
- && !vobj->isAvatar()
- && !vobj->getParent()
- && vobj->flagScripted())
- {
- if (gPipeline.sRenderBeacons)
- {
- gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
- }
-
- if (gPipeline.sRenderHighlight)
- {
- S32 face_id;
- S32 count = drawablep->getNumFaces();
- for (face_id = 0; face_id < count; face_id++)
- {
- gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
- }
- }
- }
-}
-
-void renderScriptedTouchBeacons(LLDrawable* drawablep)
-{
- LLViewerObject *vobj = drawablep->getVObj();
- if (vobj
- && !vobj->isAvatar()
- && !vobj->getParent()
- && vobj->flagScripted()
- && vobj->flagHandleTouch())
- {
- if (gPipeline.sRenderBeacons)
- {
- gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
- }
-
- if (gPipeline.sRenderHighlight)
- {
- S32 face_id;
- S32 count = drawablep->getNumFaces();
- for (face_id = 0; face_id < count; face_id++)
- {
- gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
- }
- }
- }
-}
-
-void renderPhysicalBeacons(LLDrawable* drawablep)
-{
- LLViewerObject *vobj = drawablep->getVObj();
- if (vobj
- && !vobj->isAvatar()
- //&& !vobj->getParent()
- && vobj->flagUsePhysics())
- {
- if (gPipeline.sRenderBeacons)
- {
- gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
- }
-
- if (gPipeline.sRenderHighlight)
- {
- S32 face_id;
- S32 count = drawablep->getNumFaces();
- for (face_id = 0; face_id < count; face_id++)
- {
- gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
- }
- }
- }
-}
-
-void renderMOAPBeacons(LLDrawable* drawablep)
-{
- LLViewerObject *vobj = drawablep->getVObj();
-
- if(!vobj || vobj->isAvatar())
- return;
-
- BOOL beacon=FALSE;
- U8 tecount=vobj->getNumTEs();
- for(int x=0;x<tecount;x++)
- {
- if(vobj->getTE(x)->hasMedia())
- {
- beacon=TRUE;
- break;
- }
- }
- if(beacon==TRUE)
- {
- if (gPipeline.sRenderBeacons)
- {
- gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 1.f, 1.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
- }
-
- if (gPipeline.sRenderHighlight)
- {
- S32 face_id;
- S32 count = drawablep->getNumFaces();
- for (face_id = 0; face_id < count; face_id++)
- {
- gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
- }
- }
- }
-}
-
-void renderParticleBeacons(LLDrawable* drawablep)
-{
- // Look for attachments, objects, etc.
- LLViewerObject *vobj = drawablep->getVObj();
- if (vobj
- && vobj->isParticleSource())
- {
- if (gPipeline.sRenderBeacons)
- {
- LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f);
- gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
- }
-
- if (gPipeline.sRenderHighlight)
- {
- S32 face_id;
- S32 count = drawablep->getNumFaces();
- for (face_id = 0; face_id < count; face_id++)
- {
- gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
- }
- }
- }
-}
-
-void renderSoundHighlights(LLDrawable* drawablep)
-{
- // Look for attachments, objects, etc.
- LLViewerObject *vobj = drawablep->getVObj();
- if (vobj && vobj->isAudioSource())
- {
- if (gPipeline.sRenderHighlight)
- {
- S32 face_id;
- S32 count = drawablep->getNumFaces();
- for (face_id = 0; face_id < count; face_id++)
- {
- gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
- }
- }
- }
-}
-
-void LLPipeline::postSort(LLCamera& camera)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_POST_SORT);
- LLFastTimer ftm(FTM_STATESORT_POSTSORT);
-
- assertInitialized();
-
- llpushcallstacks ;
- //rebuild drawable geometry
- for (LLCullResult::sg_list_t::iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
- {
- LLSpatialGroup* group = *i;
- if (!sUseOcclusion ||
- !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
- {
- group->rebuildGeom();
- }
- }
- llpushcallstacks ;
- //rebuild groups
- sCull->assertDrawMapsEmpty();
-
- rebuildPriorityGroups();
- llpushcallstacks ;
-
- const S32 bin_count = 1024*8;
-
- static LLCullResult::drawinfo_list_t alpha_bins[bin_count];
- static U32 bin_size[bin_count];
-
- //clear one bin per frame to avoid memory bloat
- static S32 clear_idx = 0;
- clear_idx = (1+clear_idx)%bin_count;
- alpha_bins[clear_idx].clear();
-
- for (U32 j = 0; j < bin_count; j++)
- {
- bin_size[j] = 0;
- }
-
- //build render map
- for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
- {
- LLSpatialGroup* group = *i;
- if (sUseOcclusion &&
- group->isOcclusionState(LLSpatialGroup::OCCLUDED))
- {
- continue;
- }
-
- if (group->isState(LLSpatialGroup::NEW_DRAWINFO) && group->isState(LLSpatialGroup::GEOM_DIRTY))
- { //no way this group is going to be drawable without a rebuild
- group->rebuildGeom();
- }
-
- for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
- {
- LLSpatialGroup::drawmap_elem_t& src_vec = j->second;
- if (!hasRenderType(j->first))
- {
- continue;
- }
-
- for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
- {
- if (sMinRenderSize > 0.f)
- {
- LLVector4a bounds;
- bounds.setSub((*k)->mExtents[1],(*k)->mExtents[0]);
-
- if (llmax(llmax(bounds[0], bounds[1]), bounds[2]) > sMinRenderSize)
- {
- sCull->pushDrawInfo(j->first, *k);
- }
- }
- else
- {
- sCull->pushDrawInfo(j->first, *k);
- }
- }
- }
-
- if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA))
- {
- LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
-
- if (alpha != group->mDrawMap.end())
- { //store alpha groups for sorting
- LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
- {
- if (bridge)
- {
- LLCamera trans_camera = bridge->transformCamera(camera);
- group->updateDistance(trans_camera);
- }
- else
- {
- group->updateDistance(camera);
- }
- }
-
- if (hasRenderType(LLDrawPool::POOL_ALPHA))
- {
- sCull->pushAlphaGroup(group);
- }
- }
- }
- }
-
- if (!sShadowRender)
- {
- std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());
- }
- llpushcallstacks ;
- // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus
- if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender)
- {
- if (sRenderScriptedTouchBeacons)
- {
- // Only show the beacon on the root object.
- forAllVisibleDrawables(renderScriptedTouchBeacons);
- }
- else
- if (sRenderScriptedBeacons)
- {
- // Only show the beacon on the root object.
- forAllVisibleDrawables(renderScriptedBeacons);
- }
-
- if (sRenderPhysicalBeacons)
- {
- // Only show the beacon on the root object.
- forAllVisibleDrawables(renderPhysicalBeacons);
- }
-
- if(sRenderMOAPBeacons)
- {
- forAllVisibleDrawables(renderMOAPBeacons);
- }
-
- if (sRenderParticleBeacons)
- {
- forAllVisibleDrawables(renderParticleBeacons);
- }
-
- // If god mode, also show audio cues
- if (sRenderSoundBeacons && gAudiop)
- {
- // Walk all sound sources and render out beacons for them. Note, this isn't done in the ForAllVisibleDrawables function, because some are not visible.
- LLAudioEngine::source_map::iterator iter;
- for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
- {
- LLAudioSource *sourcep = iter->second;
-
- LLVector3d pos_global = sourcep->getPositionGlobal();
- LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global);
- if (gPipeline.sRenderBeacons)
- {
- //pos += LLVector3(0.f, 0.f, 0.2f);
- gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), DebugBeaconLineWidth);
- }
- }
- // now deal with highlights for all those seeable sound sources
- forAllVisibleDrawables(renderSoundHighlights);
- }
- }
- llpushcallstacks ;
- // If managing your telehub, draw beacons at telehub and currently selected spawnpoint.
- if (LLFloaterTelehub::renderBeacons())
- {
- LLFloaterTelehub::addBeacons();
- }
-
- if (!sShadowRender)
- {
- mSelectedFaces.clear();
-
- // Draw face highlights for selected faces.
- if (LLSelectMgr::getInstance()->getTEMode())
- {
- struct f : public LLSelectedTEFunctor
- {
- virtual bool apply(LLViewerObject* object, S32 te)
- {
- if (object->mDrawable)
- {
- gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te));
- }
- return true;
- }
- } func;
- LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
- }
- }
-
- //LLSpatialGroup::sNoDelete = FALSE;
- llpushcallstacks ;
-}
-
-
-void render_hud_elements()
-{
- LLMemType mt_rhe(LLMemType::MTYPE_PIPELINE_RENDER_HUD_ELS);
- LLFastTimer t(FTM_RENDER_UI);
- gPipeline.disableLights();
-
- LLGLDisable fog(GL_FOG);
- LLGLSUIDefault gls_ui;
-
- LLGLEnable stencil(GL_STENCIL_TEST);
- glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF);
- glStencilMask(0xFFFFFFFF);
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
- gGL.color4f(1,1,1,1);
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gUIProgram.bind();
- }
- LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-
- if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- LLGLEnable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
- gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d()
-
- // Draw the tracking overlays
- LLTracker::render3D();
-
- // Show the property lines
- LLWorld::getInstance()->renderPropertyLines();
- LLViewerParcelMgr::getInstance()->render();
- LLViewerParcelMgr::getInstance()->renderParcelCollision();
-
- // Render name tags.
- LLHUDObject::renderAll();
- }
- else if (gForceRenderLandFence)
- {
- // This is only set when not rendering the UI, for parcel snapshots
- LLViewerParcelMgr::getInstance()->render();
- }
- else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- {
- LLHUDText::renderAllHUD();
- }
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gUIProgram.unbind();
- }
- gGL.flush();
-}
-
-void LLPipeline::renderHighlights()
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_HL);
-
- assertInitialized();
-
- // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD)
- // Render highlighted faces.
- LLGLSPipelineAlpha gls_pipeline_alpha;
- LLColor4 color(1.f, 1.f, 1.f, 0.5f);
- LLGLEnable color_mat(GL_COLOR_MATERIAL);
- disableLights();
-
- if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && !mHighlightSet.empty())
- { //draw blurry highlight image over screen
- LLGLEnable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- LLGLDisable test(GL_ALPHA_TEST);
-
- LLGLEnable stencil(GL_STENCIL_TEST);
- gGL.flush();
- glStencilMask(0xFFFFFFFF);
- glClearStencil(1);
- glClear(GL_STENCIL_BUFFER_BIT);
-
- glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
- glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
-
- gGL.setColorMask(false, false);
- for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ++iter)
- {
- renderHighlight(iter->mItem->getVObj(), 1.f);
- }
- gGL.setColorMask(true, false);
-
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
-
- //gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
-
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
-
- gGL.getTexUnit(0)->bind(&mHighlight);
-
- LLVector2 tc1;
- LLVector2 tc2;
-
- tc1.setVec(0,0);
- tc2.setVec(2,2);
-
- gGL.begin(LLRender::TRIANGLES);
-
- F32 scale = RenderHighlightBrightness;
- LLColor4 color = RenderHighlightColor;
- F32 thickness = RenderHighlightThickness;
-
- for (S32 pass = 0; pass < 2; ++pass)
- {
- if (pass == 0)
- {
- gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
- }
- else
- {
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- }
-
- for (S32 i = 0; i < 8; ++i)
- {
- for (S32 j = 0; j < 8; ++j)
- {
- LLVector2 tc(i-4+0.5f, j-4+0.5f);
-
- F32 dist = 1.f-(tc.length()/sqrtf(32.f));
- dist *= scale/64.f;
-
- tc *= thickness;
- tc.mV[0] = (tc.mV[0])/mHighlight.getWidth();
- tc.mV[1] = (tc.mV[1])/mHighlight.getHeight();
-
- gGL.color4f(color.mV[0],
- color.mV[1],
- color.mV[2],
- color.mV[3]*dist);
-
- gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc.mV[0]+tc2.mV[0], tc.mV[1]+tc1.mV[1]);
- gGL.vertex2f(3,-1);
- }
- }
- }
-
- gGL.end();
-
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
-
- //gGL.setSceneBlendType(LLRender::BT_ALPHA);
- }
-
- if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
- {
- gHighlightProgram.bind();
- gGL.diffuseColor4f(1,1,1,0.5f);
- }
-
- if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
- {
- // Make sure the selection image gets downloaded and decoded
- if (!mFaceSelectImagep)
- {
- mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT);
- }
- mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA);
-
- U32 count = mSelectedFaces.size();
- for (U32 i = 0; i < count; i++)
- {
- LLFace *facep = mSelectedFaces[i];
- if (!facep || facep->getDrawable()->isDead())
- {
- llerrs << "Bad face on selection" << llendl;
- return;
- }
-
- facep->renderSelected(mFaceSelectImagep, color);
- }
- }
-
- if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
- {
- // Paint 'em red!
- color.setVec(1.f, 0.f, 0.f, 0.5f);
-
- int count = mHighlightFaces.size();
- for (S32 i = 0; i < count; i++)
- {
- LLFace* facep = mHighlightFaces[i];
- facep->renderSelected(LLViewerTexture::sNullImagep, color);
- }
- }
-
- // Contains a list of the faces of objects that are physical or
- // have touch-handlers.
- mHighlightFaces.clear();
-
- if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)
- {
- gHighlightProgram.unbind();
- }
-}
-
-//debug use
-U32 LLPipeline::sCurRenderPoolType = 0 ;
-
-void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_GEOM);
- LLFastTimer t(FTM_RENDER_GEOMETRY);
-
- assertInitialized();
-
- F32 saved_modelview[16];
- F32 saved_projection[16];
-
- //HACK: preserve/restore matrices around HUD render
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- {
- for (U32 i = 0; i < 16; i++)
- {
- saved_modelview[i] = gGLModelView[i];
- saved_projection[i] = gGLProjection[i];
- }
- }
-
- ///////////////////////////////////////////
- //
- // Sync and verify GL state
- //
- //
-
- stop_glerror();
-
- LLVertexBuffer::unbind();
-
- // Do verification of GL state
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
- if (mRenderDebugMask & RENDER_DEBUG_VERIFY)
- {
- if (!verify())
- {
- llerrs << "Pipeline verification failed!" << llendl;
- }
- }
-
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO");
-
- // Initialize lots of GL state to "safe" values
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.matrixMode(LLRender::MM_TEXTURE);
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
-
- LLGLSPipeline gls_pipeline;
- LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-
- LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2);
-
- // Toggle backface culling for debugging
- LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0);
- // Set fog
- BOOL use_fog = hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG);
- LLGLEnable fog_enable(use_fog &&
- !gPipeline.canUseWindLightShadersOnObjects() ? GL_FOG : 0);
- gSky.updateFog(camera.getFar());
- if (!use_fog)
- {
- sUnderWaterRender = FALSE;
- }
-
- gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sDefaultImagep);
- LLViewerFetchedTexture::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP);
-
-
- //////////////////////////////////////////////
- //
- // Actually render all of the geometry
- //
- //
- stop_glerror();
-
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools");
-
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- if (hasRenderType(poolp->getType()))
- {
- poolp->prerender();
- }
- }
-
- {
- LLFastTimer t(FTM_POOLS);
-
- // HACK: don't calculate local lights if we're rendering the HUD!
- // Removing this check will cause bad flickering when there are
- // HUD elements being rendered AND the user is in flycam mode -nyx
- if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- {
- calcNearbyLights(camera);
- setupHWLights(NULL);
- }
-
- BOOL occlude = sUseOcclusion > 1;
- U32 cur_type = 0;
-
- pool_set_t::iterator iter1 = mPools.begin();
- while ( iter1 != mPools.end() )
- {
- LLDrawPool *poolp = *iter1;
-
- cur_type = poolp->getType();
-
- //debug use
- sCurRenderPoolType = cur_type ;
-
- if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
- {
- occlude = FALSE;
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
- LLGLSLShader::bindNoShader();
- doOcclusion(camera);
- }
-
- pool_set_t::iterator iter2 = iter1;
- if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0)
- {
- LLFastTimer t(FTM_POOLRENDER);
-
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
-
- for( S32 i = 0; i < poolp->getNumPasses(); i++ )
- {
- LLVertexBuffer::unbind();
- poolp->beginRenderPass(i);
- for (iter2 = iter1; iter2 != mPools.end(); iter2++)
- {
- LLDrawPool *p = *iter2;
- if (p->getType() != cur_type)
- {
- break;
- }
-
- p->render(i);
- }
- poolp->endRenderPass(i);
- LLVertexBuffer::unbind();
- if (gDebugGL)
- {
- std::string msg = llformat("pass %d", i);
- LLGLState::checkStates(msg);
- //LLGLState::checkTextureChannels(msg);
- //LLGLState::checkClientArrays(msg);
- }
- }
- }
- else
- {
- // Skip all pools of this type
- for (iter2 = iter1; iter2 != mPools.end(); iter2++)
- {
- LLDrawPool *p = *iter2;
- if (p->getType() != cur_type)
- {
- break;
- }
- }
- }
- iter1 = iter2;
- stop_glerror();
- }
-
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPoolsEnd");
-
- LLVertexBuffer::unbind();
-
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
-
- if (occlude)
- {
- occlude = FALSE;
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
- LLGLSLShader::bindNoShader();
- doOcclusion(camera);
- }
- }
-
- LLVertexBuffer::unbind();
- LLGLState::checkStates();
-
- if (!LLPipeline::sImpostorRender)
- {
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights");
-
- if (!sReflectionRender)
- {
- renderHighlights();
- }
-
- // Contains a list of the faces of objects that are physical or
- // have touch-handlers.
- mHighlightFaces.clear();
-
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDebug");
-
- renderDebug();
-
- LLVertexBuffer::unbind();
-
- if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred)
- {
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- // Render debugging beacons.
- gObjectList.renderObjectBeacons();
- gObjectList.resetObjectBeacons();
- }
- else
- {
- // Make sure particle effects disappear
- LLHUDObject::renderAllForTimer();
- }
- }
- else
- {
- // Make sure particle effects disappear
- LLHUDObject::renderAllForTimer();
- }
-
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd");
-
- //HACK: preserve/restore matrices around HUD render
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- {
- for (U32 i = 0; i < 16; i++)
- {
- gGLModelView[i] = saved_modelview[i];
- gGLProjection[i] = saved_projection[i];
- }
- }
- }
-
- LLVertexBuffer::unbind();
-
- LLGLState::checkStates();
-// LLGLState::checkTextureChannels();
-// LLGLState::checkClientArrays();
-}
-
-void LLPipeline::renderGeomDeferred(LLCamera& camera)
-{
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred");
-
- LLMemType mt_rgd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED);
- LLFastTimer t(FTM_RENDER_GEOMETRY);
-
- LLFastTimer t2(FTM_POOLS);
-
- LLGLEnable cull(GL_CULL_FACE);
-
- LLGLEnable stencil(GL_STENCIL_TEST);
- glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
- stop_glerror();
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
- stop_glerror();
-
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- if (hasRenderType(poolp->getType()))
- {
- poolp->prerender();
- }
- }
-
- LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-
- LLVertexBuffer::unbind();
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
-
- U32 cur_type = 0;
-
- gGL.setColorMask(true, true);
-
- pool_set_t::iterator iter1 = mPools.begin();
-
- while ( iter1 != mPools.end() )
- {
- LLDrawPool *poolp = *iter1;
-
- cur_type = poolp->getType();
-
- pool_set_t::iterator iter2 = iter1;
- if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0)
- {
- LLFastTimer t(FTM_POOLRENDER);
-
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
-
- for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ )
- {
- LLVertexBuffer::unbind();
- poolp->beginDeferredPass(i);
- for (iter2 = iter1; iter2 != mPools.end(); iter2++)
- {
- LLDrawPool *p = *iter2;
- if (p->getType() != cur_type)
- {
- break;
- }
-
- p->renderDeferred(i);
- }
- poolp->endDeferredPass(i);
- LLVertexBuffer::unbind();
-
- if (gDebugGL || gDebugPipeline)
- {
- LLGLState::checkStates();
- }
- }
- }
- else
- {
- // Skip all pools of this type
- for (iter2 = iter1; iter2 != mPools.end(); iter2++)
- {
- LLDrawPool *p = *iter2;
- if (p->getType() != cur_type)
- {
- break;
- }
- }
- }
- iter1 = iter2;
- stop_glerror();
- }
-
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
-
- gGL.setColorMask(true, false);
-}
-
-void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
-{
- LLMemType mt_rgpd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF);
- LLFastTimer t(FTM_POOLS);
- U32 cur_type = 0;
-
- LLGLEnable cull(GL_CULL_FACE);
-
- LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-
- calcNearbyLights(camera);
- setupHWLights(NULL);
-
- gGL.setColorMask(true, false);
-
- pool_set_t::iterator iter1 = mPools.begin();
- BOOL occlude = LLPipeline::sUseOcclusion > 1;
-
- while ( iter1 != mPools.end() )
- {
- LLDrawPool *poolp = *iter1;
-
- cur_type = poolp->getType();
-
- if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
- {
- occlude = FALSE;
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
- LLGLSLShader::bindNoShader();
- doOcclusion(camera);
- gGL.setColorMask(true, false);
- }
-
- pool_set_t::iterator iter2 = iter1;
- if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0)
- {
- LLFastTimer t(FTM_POOLRENDER);
-
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
-
- for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ )
- {
- LLVertexBuffer::unbind();
- poolp->beginPostDeferredPass(i);
- for (iter2 = iter1; iter2 != mPools.end(); iter2++)
- {
- LLDrawPool *p = *iter2;
- if (p->getType() != cur_type)
- {
- break;
- }
-
- p->renderPostDeferred(i);
- }
- poolp->endPostDeferredPass(i);
- LLVertexBuffer::unbind();
-
- if (gDebugGL || gDebugPipeline)
- {
- LLGLState::checkStates();
- }
- }
- }
- else
- {
- // Skip all pools of this type
- for (iter2 = iter1; iter2 != mPools.end(); iter2++)
- {
- LLDrawPool *p = *iter2;
- if (p->getType() != cur_type)
- {
- break;
- }
- }
- }
- iter1 = iter2;
- stop_glerror();
- }
-
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
-
- if (occlude)
- {
- occlude = FALSE;
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
- LLGLSLShader::bindNoShader();
- doOcclusion(camera);
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
- }
-}
-
-void LLPipeline::renderGeomShadow(LLCamera& camera)
-{
- LLMemType mt_rgs(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_SHADOW);
- U32 cur_type = 0;
-
- LLGLEnable cull(GL_CULL_FACE);
-
- LLVertexBuffer::unbind();
-
- pool_set_t::iterator iter1 = mPools.begin();
-
- while ( iter1 != mPools.end() )
- {
- LLDrawPool *poolp = *iter1;
-
- cur_type = poolp->getType();
-
- pool_set_t::iterator iter2 = iter1;
- if (hasRenderType(poolp->getType()) && poolp->getNumShadowPasses() > 0)
- {
- poolp->prerender() ;
-
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
-
- for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ )
- {
- LLVertexBuffer::unbind();
- poolp->beginShadowPass(i);
- for (iter2 = iter1; iter2 != mPools.end(); iter2++)
- {
- LLDrawPool *p = *iter2;
- if (p->getType() != cur_type)
- {
- break;
- }
-
- p->renderShadow(i);
- }
- poolp->endShadowPass(i);
- LLVertexBuffer::unbind();
-
- LLGLState::checkStates();
- }
- }
- else
- {
- // Skip all pools of this type
- for (iter2 = iter1; iter2 != mPools.end(); iter2++)
- {
- LLDrawPool *p = *iter2;
- if (p->getType() != cur_type)
- {
- break;
- }
- }
- }
- iter1 = iter2;
- stop_glerror();
- }
-
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
-}
-
-
-void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type)
-{
- assertInitialized();
- S32 count = 0;
- if (render_type == LLRender::TRIANGLE_STRIP)
- {
- count = index_count-2;
- }
- else
- {
- count = index_count/3;
- }
-
- mTrianglesDrawn += count;
- mBatchCount++;
- mMaxBatchSize = llmax(mMaxBatchSize, count);
- mMinBatchSize = llmin(mMinBatchSize, count);
-
- if (LLPipeline::sRenderFrameTest)
- {
- gViewerWindow->getWindow()->swapBuffers();
- ms_sleep(16);
- }
-}
-
-void LLPipeline::renderPhysicsDisplay()
-{
- if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
- {
- return;
- }
-
- allocatePhysicsBuffer();
-
- gGL.flush();
- mPhysicsDisplay.bindTarget();
- glClearColor(0,0,0,1);
- gGL.setColorMask(true, true);
- mPhysicsDisplay.clear();
- glClearColor(0,0,0,0);
-
- gGL.setColorMask(true, false);
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gDebugProgram.bind();
- }
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- if (hasRenderType(part->mDrawableType))
- {
- part->renderPhysicsShapes();
- }
- }
- }
- }
-
- for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
- {
- LLSpatialBridge* bridge = *i;
- if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
- {
- gGL.pushMatrix();
- gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
- bridge->renderPhysicsShapes();
- gGL.popMatrix();
- }
- }
-
- gGL.flush();
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gDebugProgram.unbind();
- }
-
- mPhysicsDisplay.flush();
-}
-
-
-void LLPipeline::renderDebug()
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
-
- assertInitialized();
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gUIProgram.bind();
- }
-
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gPipeline.disableLights();
+/**
+ * @file pipeline.cpp
+ * @brief Rendering pipeline.
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "pipeline.h"
+
+// library includes
+#include "llaudioengine.h" // For debugging.
+#include "imageids.h"
+#include "llerror.h"
+#include "llviewercontrol.h"
+#include "llfasttimer.h"
+#include "llfontgl.h"
+#include "llmemtype.h"
+#include "llnamevalue.h"
+#include "llpointer.h"
+#include "llprimitive.h"
+#include "llvolume.h"
+#include "material_codes.h"
+#include "timing.h"
+#include "v3color.h"
+#include "llui.h"
+#include "llglheaders.h"
+#include "llrender.h"
+#include "llwindow.h" // swapBuffers()
+
+// newview includes
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "lldrawable.h"
+#include "lldrawpoolalpha.h"
+#include "lldrawpoolavatar.h"
+#include "lldrawpoolground.h"
+#include "lldrawpoolbump.h"
+#include "lldrawpooltree.h"
+#include "lldrawpoolwater.h"
+#include "llface.h"
+#include "llfeaturemanager.h"
+#include "llfloatertelehub.h"
+#include "llfloaterreg.h"
+#include "llgldbg.h"
+#include "llhudmanager.h"
+#include "llhudnametag.h"
+#include "llhudtext.h"
+#include "lllightconstants.h"
+#include "llmeshrepository.h"
+#include "llresmgr.h"
+#include "llselectmgr.h"
+#include "llsky.h"
+#include "lltracker.h"
+#include "lltool.h"
+#include "lltoolmgr.h"
+#include "llviewercamera.h"
+#include "llviewermediafocus.h"
+#include "llviewertexturelist.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h" // for audio debugging.
+#include "llviewerwindow.h" // For getSpinAxis
+#include "llvoavatarself.h"
+#include "llvoground.h"
+#include "llvosky.h"
+#include "llvotree.h"
+#include "llvovolume.h"
+#include "llvosurfacepatch.h"
+#include "llvowater.h"
+#include "llvotree.h"
+#include "llvopartgroup.h"
+#include "llworld.h"
+#include "llcubemap.h"
+#include "llviewershadermgr.h"
+#include "llviewerstats.h"
+#include "llviewerjoystick.h"
+#include "llviewerdisplay.h"
+#include "llwlparammanager.h"
+#include "llwaterparammanager.h"
+#include "llspatialpartition.h"
+#include "llmutelist.h"
+#include "lltoolpie.h"
+#include "llcurl.h"
+#include "llnotifications.h"
+#include "LLPathingLib.h"
+#include "llfloaterpathfindingconsole.h"
+
+#ifdef _DEBUG
+// Debug indices is disabled for now for debug performance - djs 4/24/02
+//#define DEBUG_INDICES
+#else
+//#define DEBUG_INDICES
+#endif
+
+//cached settings
+BOOL LLPipeline::RenderAvatarVP;
+BOOL LLPipeline::VertexShaderEnable;
+BOOL LLPipeline::WindLightUseAtmosShaders;
+BOOL LLPipeline::RenderDeferred;
+F32 LLPipeline::RenderDeferredSunWash;
+U32 LLPipeline::RenderFSAASamples;
+U32 LLPipeline::RenderResolutionDivisor;
+BOOL LLPipeline::RenderUIBuffer;
+S32 LLPipeline::RenderShadowDetail;
+BOOL LLPipeline::RenderDeferredSSAO;
+F32 LLPipeline::RenderShadowResolutionScale;
+BOOL LLPipeline::RenderLocalLights;
+BOOL LLPipeline::RenderDelayCreation;
+BOOL LLPipeline::RenderAnimateRes;
+BOOL LLPipeline::FreezeTime;
+S32 LLPipeline::DebugBeaconLineWidth;
+F32 LLPipeline::RenderHighlightBrightness;
+LLColor4 LLPipeline::RenderHighlightColor;
+F32 LLPipeline::RenderHighlightThickness;
+BOOL LLPipeline::RenderSpotLightsInNondeferred;
+LLColor4 LLPipeline::PreviewAmbientColor;
+LLColor4 LLPipeline::PreviewDiffuse0;
+LLColor4 LLPipeline::PreviewSpecular0;
+LLColor4 LLPipeline::PreviewDiffuse1;
+LLColor4 LLPipeline::PreviewSpecular1;
+LLColor4 LLPipeline::PreviewDiffuse2;
+LLColor4 LLPipeline::PreviewSpecular2;
+LLVector3 LLPipeline::PreviewDirection0;
+LLVector3 LLPipeline::PreviewDirection1;
+LLVector3 LLPipeline::PreviewDirection2;
+F32 LLPipeline::RenderGlowMinLuminance;
+F32 LLPipeline::RenderGlowMaxExtractAlpha;
+F32 LLPipeline::RenderGlowWarmthAmount;
+LLVector3 LLPipeline::RenderGlowLumWeights;
+LLVector3 LLPipeline::RenderGlowWarmthWeights;
+S32 LLPipeline::RenderGlowResolutionPow;
+S32 LLPipeline::RenderGlowIterations;
+F32 LLPipeline::RenderGlowWidth;
+F32 LLPipeline::RenderGlowStrength;
+BOOL LLPipeline::RenderDepthOfField;
+F32 LLPipeline::CameraFocusTransitionTime;
+F32 LLPipeline::CameraFNumber;
+F32 LLPipeline::CameraFocalLength;
+F32 LLPipeline::CameraFieldOfView;
+F32 LLPipeline::RenderShadowNoise;
+F32 LLPipeline::RenderShadowBlurSize;
+F32 LLPipeline::RenderSSAOScale;
+U32 LLPipeline::RenderSSAOMaxScale;
+F32 LLPipeline::RenderSSAOFactor;
+LLVector3 LLPipeline::RenderSSAOEffect;
+F32 LLPipeline::RenderShadowOffsetError;
+F32 LLPipeline::RenderShadowBiasError;
+F32 LLPipeline::RenderShadowOffset;
+F32 LLPipeline::RenderShadowBias;
+F32 LLPipeline::RenderSpotShadowOffset;
+F32 LLPipeline::RenderSpotShadowBias;
+F32 LLPipeline::RenderEdgeDepthCutoff;
+F32 LLPipeline::RenderEdgeNormCutoff;
+LLVector3 LLPipeline::RenderShadowGaussian;
+F32 LLPipeline::RenderShadowBlurDistFactor;
+BOOL LLPipeline::RenderDeferredAtmospheric;
+S32 LLPipeline::RenderReflectionDetail;
+F32 LLPipeline::RenderHighlightFadeTime;
+LLVector3 LLPipeline::RenderShadowClipPlanes;
+LLVector3 LLPipeline::RenderShadowOrthoClipPlanes;
+LLVector3 LLPipeline::RenderShadowNearDist;
+F32 LLPipeline::RenderFarClip;
+LLVector3 LLPipeline::RenderShadowSplitExponent;
+F32 LLPipeline::RenderShadowErrorCutoff;
+F32 LLPipeline::RenderShadowFOVCutoff;
+BOOL LLPipeline::CameraOffset;
+F32 LLPipeline::CameraMaxCoF;
+F32 LLPipeline::CameraDoFResScale;
+
+const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f;
+const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f;
+const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
+const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
+const S32 MAX_OFFSCREEN_GEOMETRY_CHANGES_PER_FRAME = 10;
+const U32 REFLECTION_MAP_RES = 128;
+const U32 DEFERRED_VB_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
+// Max number of occluders to search for. JC
+const S32 MAX_OCCLUDER_COUNT = 2;
+
+extern S32 gBoxFrame;
+//extern BOOL gHideSelectedObjects;
+extern BOOL gDisplaySwapBuffers;
+extern BOOL gDebugGL;
+
+BOOL gAvatarBacklight = FALSE;
+
+BOOL gDebugPipeline = FALSE;
+LLPipeline gPipeline;
+const LLMatrix4* gGLLastMatrix = NULL;
+
+LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Geometry");
+LLFastTimer::DeclareTimer FTM_RENDER_GRASS("Grass");
+LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE("Invisible");
+LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION("Occlusion");
+LLFastTimer::DeclareTimer FTM_RENDER_SHINY("Shiny");
+LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE("Simple");
+LLFastTimer::DeclareTimer FTM_RENDER_TERRAIN("Terrain");
+LLFastTimer::DeclareTimer FTM_RENDER_TREES("Trees");
+LLFastTimer::DeclareTimer FTM_RENDER_UI("UI");
+LLFastTimer::DeclareTimer FTM_RENDER_WATER("Water");
+LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY("Windlight Sky");
+LLFastTimer::DeclareTimer FTM_RENDER_ALPHA("Alpha Objects");
+LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS("Avatars");
+LLFastTimer::DeclareTimer FTM_RENDER_BUMP("Bump");
+LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT("Fullbright");
+LLFastTimer::DeclareTimer FTM_RENDER_GLOW("Glow");
+LLFastTimer::DeclareTimer FTM_GEO_UPDATE("Geo Update");
+LLFastTimer::DeclareTimer FTM_POOLRENDER("RenderPool");
+LLFastTimer::DeclareTimer FTM_POOLS("Pools");
+LLFastTimer::DeclareTimer FTM_RENDER_BLOOM_FBO("First FBO");
+LLFastTimer::DeclareTimer FTM_STATESORT("Sort Draw State");
+LLFastTimer::DeclareTimer FTM_PIPELINE("Pipeline");
+LLFastTimer::DeclareTimer FTM_CLIENT_COPY("Client Copy");
+LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading");
+
+
+static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");
+static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort");
+
+//----------------------------------------
+std::string gPoolNames[] =
+{
+ // Correspond to LLDrawpool enum render type
+ "NONE",
+ "POOL_SIMPLE",
+ "POOL_GROUND",
+ "POOL_FULLBRIGHT",
+ "POOL_BUMP",
+ "POOL_TERRAIN,"
+ "POOL_SKY",
+ "POOL_WL_SKY",
+ "POOL_TREE",
+ "POOL_GRASS",
+ "POOL_INVISIBLE",
+ "POOL_AVATAR",
+ "POOL_VOIDWATER",
+ "POOL_WATER",
+ "POOL_GLOW",
+ "POOL_ALPHA"
+};
+
+void drawBox(const LLVector3& c, const LLVector3& r);
+void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
+U32 nhpo2(U32 v);
+
+glh::matrix4f glh_copy_matrix(F32* src)
+{
+ glh::matrix4f ret;
+ ret.set_value(src);
+ return ret;
+}
+
+glh::matrix4f glh_get_current_modelview()
+{
+ return glh_copy_matrix(gGLModelView);
+}
+
+glh::matrix4f glh_get_current_projection()
+{
+ return glh_copy_matrix(gGLProjection);
+}
+
+glh::matrix4f glh_get_last_modelview()
+{
+ return glh_copy_matrix(gGLLastModelView);
+}
+
+glh::matrix4f glh_get_last_projection()
+{
+ return glh_copy_matrix(gGLLastProjection);
+}
+
+void glh_copy_matrix(const glh::matrix4f& src, F32* dst)
+{
+ for (U32 i = 0; i < 16; i++)
+ {
+ dst[i] = src.m[i];
+ }
+}
+
+void glh_set_current_modelview(const glh::matrix4f& mat)
+{
+ glh_copy_matrix(mat, gGLModelView);
+}
+
+void glh_set_current_projection(glh::matrix4f& mat)
+{
+ glh_copy_matrix(mat, gGLProjection);
+}
+
+glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar)
+{
+ glh::matrix4f ret(
+ 2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left),
+ 0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom),
+ 0.f, 0.f, -2.f/(zfar-znear), -(zfar+znear)/(zfar-znear),
+ 0.f, 0.f, 0.f, 1.f);
+
+ return ret;
+}
+
+void display_update_camera();
+//----------------------------------------
+
+S32 LLPipeline::sCompiles = 0;
+
+BOOL LLPipeline::sPickAvatar = TRUE;
+BOOL LLPipeline::sDynamicLOD = TRUE;
+BOOL LLPipeline::sShowHUDAttachments = TRUE;
+BOOL LLPipeline::sRenderMOAPBeacons = FALSE;
+BOOL LLPipeline::sRenderPhysicalBeacons = TRUE;
+BOOL LLPipeline::sRenderScriptedBeacons = FALSE;
+BOOL LLPipeline::sRenderScriptedTouchBeacons = TRUE;
+BOOL LLPipeline::sRenderParticleBeacons = FALSE;
+BOOL LLPipeline::sRenderSoundBeacons = FALSE;
+BOOL LLPipeline::sRenderBeacons = FALSE;
+BOOL LLPipeline::sRenderHighlight = TRUE;
+BOOL LLPipeline::sForceOldBakedUpload = FALSE;
+S32 LLPipeline::sUseOcclusion = 0;
+BOOL LLPipeline::sDelayVBUpdate = TRUE;
+BOOL LLPipeline::sAutoMaskAlphaDeferred = TRUE;
+BOOL LLPipeline::sAutoMaskAlphaNonDeferred = FALSE;
+BOOL LLPipeline::sDisableShaders = FALSE;
+BOOL LLPipeline::sRenderBump = TRUE;
+BOOL LLPipeline::sBakeSunlight = FALSE;
+BOOL LLPipeline::sNoAlpha = FALSE;
+BOOL LLPipeline::sUseTriStrips = TRUE;
+BOOL LLPipeline::sUseFarClip = TRUE;
+BOOL LLPipeline::sShadowRender = FALSE;
+BOOL LLPipeline::sWaterReflections = FALSE;
+BOOL LLPipeline::sRenderGlow = FALSE;
+BOOL LLPipeline::sReflectionRender = FALSE;
+BOOL LLPipeline::sImpostorRender = FALSE;
+BOOL LLPipeline::sUnderWaterRender = FALSE;
+BOOL LLPipeline::sTextureBindTest = FALSE;
+BOOL LLPipeline::sRenderFrameTest = FALSE;
+BOOL LLPipeline::sRenderAttachedLights = TRUE;
+BOOL LLPipeline::sRenderAttachedParticles = TRUE;
+BOOL LLPipeline::sRenderDeferred = FALSE;
+BOOL LLPipeline::sMemAllocationThrottled = FALSE;
+S32 LLPipeline::sVisibleLightCount = 0;
+F32 LLPipeline::sMinRenderSize = 0.f;
+
+
+static LLCullResult* sCull = NULL;
+
+static const U32 gl_cube_face[] =
+{
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
+};
+
+void validate_framebuffer_object();
+
+
+bool addDeferredAttachments(LLRenderTarget& target)
+{
+ return target.addColorAttachment(GL_RGBA) && //specular
+ target.addColorAttachment(GL_RGBA); //normal+z
+}
+
+LLPipeline::LLPipeline() :
+ mBackfaceCull(FALSE),
+ mBatchCount(0),
+ mMatrixOpCount(0),
+ mTextureMatrixOps(0),
+ mMaxBatchSize(0),
+ mMinBatchSize(0),
+ mMeanBatchSize(0),
+ mTrianglesDrawn(0),
+ mNumVisibleNodes(0),
+ mVerticesRelit(0),
+ mLightingChanges(0),
+ mGeometryChanges(0),
+ mNumVisibleFaces(0),
+
+ mInitialized(FALSE),
+ mVertexShadersEnabled(FALSE),
+ mVertexShadersLoaded(0),
+ mRenderDebugFeatureMask(0),
+ mRenderDebugMask(0),
+ mOldRenderDebugMask(0),
+ mGroupQ1Locked(false),
+ mGroupQ2Locked(false),
+ mResetVertexBuffers(false),
+ mLastRebuildPool(NULL),
+ mAlphaPool(NULL),
+ mSkyPool(NULL),
+ mTerrainPool(NULL),
+ mWaterPool(NULL),
+ mGroundPool(NULL),
+ mSimplePool(NULL),
+ mFullbrightPool(NULL),
+ mInvisiblePool(NULL),
+ mGlowPool(NULL),
+ mBumpPool(NULL),
+ mWLSkyPool(NULL),
+ mLightMask(0),
+ mLightMovingMask(0),
+ mLightingDetail(0),
+ mScreenWidth(0),
+ mScreenHeight(0)
+{
+ mNoiseMap = 0;
+ mTrueNoiseMap = 0;
+ mLightFunc = 0;
+}
+
+void LLPipeline::init()
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_INIT);
+
+ refreshCachedSettings();
+
+ gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
+ sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
+ sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
+ sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
+ LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
+ LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
+ LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
+ sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
+ sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
+
+ mInitialized = TRUE;
+
+ stop_glerror();
+
+ //create render pass pools
+ getPool(LLDrawPool::POOL_ALPHA);
+ getPool(LLDrawPool::POOL_SIMPLE);
+ getPool(LLDrawPool::POOL_GRASS);
+ getPool(LLDrawPool::POOL_FULLBRIGHT);
+ getPool(LLDrawPool::POOL_INVISIBLE);
+ getPool(LLDrawPool::POOL_BUMP);
+ getPool(LLDrawPool::POOL_GLOW);
+
+ LLViewerStats::getInstance()->mTrianglesDrawnStat.reset();
+ resetFrameStats();
+
+ for (U32 i = 0; i < NUM_RENDER_TYPES; ++i)
+ {
+ mRenderTypeEnabled[i] = TRUE; //all rendering types start enabled
+ }
+
+ mRenderDebugFeatureMask = 0xffffffff; // All debugging features on
+ mRenderDebugMask = 0; // All debug starts off
+
+ // Don't turn on ground when this is set
+ // Mac Books with intel 950s need this
+ if(!gSavedSettings.getBOOL("RenderGround"))
+ {
+ toggleRenderType(RENDER_TYPE_GROUND);
+ }
+
+ // make sure RenderPerformanceTest persists (hackity hack hack)
+ // disables non-object rendering (UI, sky, water, etc)
+ if (gSavedSettings.getBOOL("RenderPerformanceTest"))
+ {
+ gSavedSettings.setBOOL("RenderPerformanceTest", FALSE);
+ gSavedSettings.setBOOL("RenderPerformanceTest", TRUE);
+ }
+
+ mOldRenderDebugMask = mRenderDebugMask;
+
+ mBackfaceCull = TRUE;
+
+ stop_glerror();
+
+ // Enable features
+
+ LLViewerShaderMgr::instance()->setShaders();
+
+ stop_glerror();
+
+ for (U32 i = 0; i < 2; ++i)
+ {
+ mSpotLightFade[i] = 1.f;
+ }
+
+ mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0);
+ mDeferredVB->allocateBuffer(8, 0, true);
+ setLightingDetail(-1);
+
+ //
+ // Update all settings to trigger a cached settings refresh
+ //
+
+ gSavedSettings.getControl("RenderAutoMaskAlphaDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderUseFarClip")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderAvatarMaxVisible")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderDelayVBUpdate")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+
+ gSavedSettings.getControl("UseOcclusion")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+
+ gSavedSettings.getControl("VertexShaderEnable")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderAvatarVP")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("WindLightUseAtmosShaders")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderDeferredSunWash")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderFSAASamples")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderResolutionDivisor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderUIBuffer")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowDetail")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderDeferredSSAO")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowResolutionScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderLocalLights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderDelayCreation")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderAnimateRes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("FreezeTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("DebugBeaconLineWidth")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderHighlightBrightness")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderHighlightColor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderHighlightThickness")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderSpotLightsInNondeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("PreviewAmbientColor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("PreviewDiffuse0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("PreviewSpecular0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("PreviewDiffuse1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("PreviewSpecular1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("PreviewDiffuse2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("PreviewSpecular2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("PreviewDirection0")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("PreviewDirection1")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("PreviewDirection2")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderGlowMinLuminance")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderGlowMaxExtractAlpha")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderGlowWarmthAmount")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderGlowLumWeights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderGlowWarmthWeights")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderGlowResolutionPow")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderGlowIterations")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderGlowWidth")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderGlowStrength")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderDepthOfField")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("CameraFocusTransitionTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("CameraFNumber")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("CameraFocalLength")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("CameraFieldOfView")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowNoise")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowBlurSize")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderSSAOScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderSSAOMaxScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderSSAOFactor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderSSAOEffect")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowOffsetError")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowBiasError")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowBias")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderSpotShadowOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderSpotShadowBias")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderEdgeDepthCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderEdgeNormCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowGaussian")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowBlurDistFactor")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderDeferredAtmospheric")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderReflectionDetail")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderHighlightFadeTime")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowClipPlanes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowOrthoClipPlanes")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowNearDist")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderFarClip")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowSplitExponent")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowErrorCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("RenderShadowFOVCutoff")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("CameraOffset")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("CameraMaxCoF")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+ gSavedSettings.getControl("CameraDoFResScale")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
+}
+
+LLPipeline::~LLPipeline()
+{
+
+}
+
+void LLPipeline::cleanup()
+{
+ assertInitialized();
+
+ mGroupQ1.clear() ;
+ mGroupQ2.clear() ;
+
+ for(pool_set_t::iterator iter = mPools.begin();
+ iter != mPools.end(); )
+ {
+ pool_set_t::iterator curiter = iter++;
+ LLDrawPool* poolp = *curiter;
+ if (poolp->isFacePool())
+ {
+ LLFacePool* face_pool = (LLFacePool*) poolp;
+ if (face_pool->mReferences.empty())
+ {
+ mPools.erase(curiter);
+ removeFromQuickLookup( poolp );
+ delete poolp;
+ }
+ }
+ else
+ {
+ mPools.erase(curiter);
+ removeFromQuickLookup( poolp );
+ delete poolp;
+ }
+ }
+
+ if (!mTerrainPools.empty())
+ {
+ llwarns << "Terrain Pools not cleaned up" << llendl;
+ }
+ if (!mTreePools.empty())
+ {
+ llwarns << "Tree Pools not cleaned up" << llendl;
+ }
+
+ delete mAlphaPool;
+ mAlphaPool = NULL;
+ delete mSkyPool;
+ mSkyPool = NULL;
+ delete mTerrainPool;
+ mTerrainPool = NULL;
+ delete mWaterPool;
+ mWaterPool = NULL;
+ delete mGroundPool;
+ mGroundPool = NULL;
+ delete mSimplePool;
+ mSimplePool = NULL;
+ delete mFullbrightPool;
+ mFullbrightPool = NULL;
+ delete mInvisiblePool;
+ mInvisiblePool = NULL;
+ delete mGlowPool;
+ mGlowPool = NULL;
+ delete mBumpPool;
+ mBumpPool = NULL;
+ // don't delete wl sky pool it was handled above in the for loop
+ //delete mWLSkyPool;
+ mWLSkyPool = NULL;
+
+ releaseGLBuffers();
+
+ mFaceSelectImagep = NULL;
+
+ mMovedBridge.clear();
+
+ mInitialized = FALSE;
+
+ mDeferredVB = NULL;
+}
+
+//============================================================================
+
+void LLPipeline::destroyGL()
+{
+ stop_glerror();
+ unloadShaders();
+ mHighlightFaces.clear();
+
+ resetDrawOrders();
+
+ resetVertexBuffers();
+
+ releaseGLBuffers();
+
+ if (LLVertexBuffer::sEnableVBOs)
+ {
+ LLVertexBuffer::sEnableVBOs = FALSE;
+ }
+}
+
+static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture");
+
+//static
+void LLPipeline::throttleNewMemoryAllocation(BOOL disable)
+{
+ if(sMemAllocationThrottled != disable)
+ {
+ sMemAllocationThrottled = disable ;
+
+ if(sMemAllocationThrottled)
+ {
+ //send out notification
+ LLNotification::Params params("LowMemory");
+ LLNotifications::instance().add(params);
+
+ //release some memory.
+ }
+ }
+}
+
+void LLPipeline::resizeScreenTexture()
+{
+ LLFastTimer ft(FTM_RESIZE_SCREEN_TEXTURE);
+ if (gPipeline.canUseVertexShaders() && assertInitialized())
+ {
+ GLuint resX = gViewerWindow->getWorldViewWidthRaw();
+ GLuint resY = gViewerWindow->getWorldViewHeightRaw();
+
+ allocateScreenBuffer(resX,resY);
+ }
+}
+
+void LLPipeline::allocatePhysicsBuffer()
+{
+ GLuint resX = gViewerWindow->getWorldViewWidthRaw();
+ GLuint resY = gViewerWindow->getWorldViewHeightRaw();
+
+ if (mPhysicsDisplay.getWidth() != resX || mPhysicsDisplay.getHeight() != resY)
+ {
+ mPhysicsDisplay.allocate(resX, resY, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+ }
+}
+
+void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
+{
+ refreshCachedSettings();
+ U32 samples = RenderFSAASamples;
+
+ //try to allocate screen buffers at requested resolution and samples
+ // - on failure, shrink number of samples and try again
+ // - if not multisampled, shrink resolution and try again (favor X resolution over Y)
+ // Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state
+
+ if (!allocateScreenBuffer(resX, resY, samples))
+ {
+ releaseScreenBuffers();
+ //reduce number of samples
+ while (samples > 0)
+ {
+ samples /= 2;
+ if (allocateScreenBuffer(resX, resY, samples))
+ { //success
+ return;
+ }
+ releaseScreenBuffers();
+ }
+
+ samples = 0;
+
+ //reduce resolution
+ while (resY > 0 && resX > 0)
+ {
+ resY /= 2;
+ if (allocateScreenBuffer(resX, resY, samples))
+ {
+ return;
+ }
+ releaseScreenBuffers();
+
+ resX /= 2;
+ if (allocateScreenBuffer(resX, resY, samples))
+ {
+ return;
+ }
+ releaseScreenBuffers();
+ }
+
+ llwarns << "Unable to allocate screen buffer at any resolution!" << llendl;
+ }
+}
+
+
+bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
+{
+ refreshCachedSettings();
+
+ // remember these dimensions
+ mScreenWidth = resX;
+ mScreenHeight = resY;
+
+ U32 res_mod = RenderResolutionDivisor;
+
+ if (res_mod > 1 && res_mod < resX && res_mod < resY)
+ {
+ resX /= res_mod;
+ resY /= res_mod;
+ }
+
+ if (RenderUIBuffer)
+ {
+ if (!mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE))
+ {
+ return false;
+ }
+ }
+
+ if (LLPipeline::sRenderDeferred)
+ {
+ S32 shadow_detail = RenderShadowDetail;
+ BOOL ssao = RenderDeferredSSAO;
+
+ //allocate deferred rendering color buffers
+ if (!mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+ if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+ if (!addDeferredAttachments(mDeferredScreen)) return false;
+
+ if (!mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+ if (samples > 0)
+ {
+ if (!mFXAABuffer.allocate(nhpo2(resX), nhpo2(resY), GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
+ }
+ else
+ {
+ mFXAABuffer.release();
+ }
+
+ if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0)
+ { //only need mDeferredLight for shadows OR ssao OR dof OR fxaa
+ if (!mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
+ }
+ else
+ {
+ mDeferredLight.release();
+ }
+
+ F32 scale = RenderShadowResolutionScale;
+
+ if (shadow_detail > 0)
+ { //allocate 4 sun shadow maps
+ for (U32 i = 0; i < 4; i++)
+ {
+ if (!mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false;
+ }
+ }
+ else
+ {
+ for (U32 i = 0; i < 4; i++)
+ {
+ mShadow[i].release();
+ }
+ }
+
+ U32 width = nhpo2(U32(resX*scale))/2;
+ U32 height = width;
+
+ if (shadow_detail > 1)
+ { //allocate two spot shadow maps
+ for (U32 i = 4; i < 6; i++)
+ {
+ if (!mShadow[i].allocate(width, height, 0, TRUE, FALSE)) return false;
+ }
+ }
+ else
+ {
+ for (U32 i = 4; i < 6; i++)
+ {
+ mShadow[i].release();
+ }
+ }
+ }
+ else
+ {
+ mDeferredLight.release();
+
+ for (U32 i = 0; i < 6; i++)
+ {
+ mShadow[i].release();
+ }
+ mFXAABuffer.release();
+ mScreen.release();
+ mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
+ mDeferredDepth.release();
+
+ if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
+ }
+
+ if (LLPipeline::sRenderDeferred)
+ { //share depth buffer between deferred targets
+ mDeferredScreen.shareDepthBuffer(mScreen);
+ }
+
+ gGL.getTexUnit(0)->disable();
+
+ stop_glerror();
+
+ return true;
+}
+
+//static
+void LLPipeline::updateRenderDeferred()
+{
+ BOOL deferred = ((RenderDeferred &&
+ LLRenderTarget::sUseFBO &&
+ LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
+ VertexShaderEnable &&
+ RenderAvatarVP &&
+ WindLightUseAtmosShaders) ? TRUE : FALSE) &&
+ !gUseWireframe;
+
+ sRenderDeferred = deferred;
+ if (deferred)
+ { //must render glow when rendering deferred since post effect pass is needed to present any lighting at all
+ sRenderGlow = TRUE;
+ }
+}
+
+//static
+void LLPipeline::refreshCachedSettings()
+{
+ LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred");
+ LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred");
+ LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip");
+ LLVOAvatar::sMaxVisible = (U32)gSavedSettings.getS32("RenderAvatarMaxVisible");
+ LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate");
+
+ LLPipeline::sUseOcclusion =
+ (!gUseWireframe
+ && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion")
+ && gSavedSettings.getBOOL("UseOcclusion")
+ && gGLManager.mHasOcclusionQuery) ? 2 : 0;
+
+ VertexShaderEnable = gSavedSettings.getBOOL("VertexShaderEnable");
+ RenderAvatarVP = gSavedSettings.getBOOL("RenderAvatarVP");
+ WindLightUseAtmosShaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders");
+ RenderDeferred = gSavedSettings.getBOOL("RenderDeferred");
+ RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash");
+ RenderFSAASamples = gSavedSettings.getU32("RenderFSAASamples");
+ RenderResolutionDivisor = gSavedSettings.getU32("RenderResolutionDivisor");
+ RenderUIBuffer = gSavedSettings.getBOOL("RenderUIBuffer");
+ RenderShadowDetail = gSavedSettings.getS32("RenderShadowDetail");
+ RenderDeferredSSAO = gSavedSettings.getBOOL("RenderDeferredSSAO");
+ RenderShadowResolutionScale = gSavedSettings.getF32("RenderShadowResolutionScale");
+ RenderLocalLights = gSavedSettings.getBOOL("RenderLocalLights");
+ RenderDelayCreation = gSavedSettings.getBOOL("RenderDelayCreation");
+ RenderAnimateRes = gSavedSettings.getBOOL("RenderAnimateRes");
+ FreezeTime = gSavedSettings.getBOOL("FreezeTime");
+ DebugBeaconLineWidth = gSavedSettings.getS32("DebugBeaconLineWidth");
+ RenderHighlightBrightness = gSavedSettings.getF32("RenderHighlightBrightness");
+ RenderHighlightColor = gSavedSettings.getColor4("RenderHighlightColor");
+ RenderHighlightThickness = gSavedSettings.getF32("RenderHighlightThickness");
+ RenderSpotLightsInNondeferred = gSavedSettings.getBOOL("RenderSpotLightsInNondeferred");
+ PreviewAmbientColor = gSavedSettings.getColor4("PreviewAmbientColor");
+ PreviewDiffuse0 = gSavedSettings.getColor4("PreviewDiffuse0");
+ PreviewSpecular0 = gSavedSettings.getColor4("PreviewSpecular0");
+ PreviewDiffuse1 = gSavedSettings.getColor4("PreviewDiffuse1");
+ PreviewSpecular1 = gSavedSettings.getColor4("PreviewSpecular1");
+ PreviewDiffuse2 = gSavedSettings.getColor4("PreviewDiffuse2");
+ PreviewSpecular2 = gSavedSettings.getColor4("PreviewSpecular2");
+ PreviewDirection0 = gSavedSettings.getVector3("PreviewDirection0");
+ PreviewDirection1 = gSavedSettings.getVector3("PreviewDirection1");
+ PreviewDirection2 = gSavedSettings.getVector3("PreviewDirection2");
+ RenderGlowMinLuminance = gSavedSettings.getF32("RenderGlowMinLuminance");
+ RenderGlowMaxExtractAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha");
+ RenderGlowWarmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount");
+ RenderGlowLumWeights = gSavedSettings.getVector3("RenderGlowLumWeights");
+ RenderGlowWarmthWeights = gSavedSettings.getVector3("RenderGlowWarmthWeights");
+ RenderGlowResolutionPow = gSavedSettings.getS32("RenderGlowResolutionPow");
+ RenderGlowIterations = gSavedSettings.getS32("RenderGlowIterations");
+ RenderGlowWidth = gSavedSettings.getF32("RenderGlowWidth");
+ RenderGlowStrength = gSavedSettings.getF32("RenderGlowStrength");
+ RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField");
+ CameraFocusTransitionTime = gSavedSettings.getF32("CameraFocusTransitionTime");
+ CameraFNumber = gSavedSettings.getF32("CameraFNumber");
+ CameraFocalLength = gSavedSettings.getF32("CameraFocalLength");
+ CameraFieldOfView = gSavedSettings.getF32("CameraFieldOfView");
+ RenderShadowNoise = gSavedSettings.getF32("RenderShadowNoise");
+ RenderShadowBlurSize = gSavedSettings.getF32("RenderShadowBlurSize");
+ RenderSSAOScale = gSavedSettings.getF32("RenderSSAOScale");
+ RenderSSAOMaxScale = gSavedSettings.getU32("RenderSSAOMaxScale");
+ RenderSSAOFactor = gSavedSettings.getF32("RenderSSAOFactor");
+ RenderSSAOEffect = gSavedSettings.getVector3("RenderSSAOEffect");
+ RenderShadowOffsetError = gSavedSettings.getF32("RenderShadowOffsetError");
+ RenderShadowBiasError = gSavedSettings.getF32("RenderShadowBiasError");
+ RenderShadowOffset = gSavedSettings.getF32("RenderShadowOffset");
+ RenderShadowBias = gSavedSettings.getF32("RenderShadowBias");
+ RenderSpotShadowOffset = gSavedSettings.getF32("RenderSpotShadowOffset");
+ RenderSpotShadowBias = gSavedSettings.getF32("RenderSpotShadowBias");
+ RenderEdgeDepthCutoff = gSavedSettings.getF32("RenderEdgeDepthCutoff");
+ RenderEdgeNormCutoff = gSavedSettings.getF32("RenderEdgeNormCutoff");
+ RenderShadowGaussian = gSavedSettings.getVector3("RenderShadowGaussian");
+ RenderShadowBlurDistFactor = gSavedSettings.getF32("RenderShadowBlurDistFactor");
+ RenderDeferredAtmospheric = gSavedSettings.getBOOL("RenderDeferredAtmospheric");
+ RenderReflectionDetail = gSavedSettings.getS32("RenderReflectionDetail");
+ RenderHighlightFadeTime = gSavedSettings.getF32("RenderHighlightFadeTime");
+ RenderShadowClipPlanes = gSavedSettings.getVector3("RenderShadowClipPlanes");
+ RenderShadowOrthoClipPlanes = gSavedSettings.getVector3("RenderShadowOrthoClipPlanes");
+ RenderShadowNearDist = gSavedSettings.getVector3("RenderShadowNearDist");
+ RenderFarClip = gSavedSettings.getF32("RenderFarClip");
+ RenderShadowSplitExponent = gSavedSettings.getVector3("RenderShadowSplitExponent");
+ RenderShadowErrorCutoff = gSavedSettings.getF32("RenderShadowErrorCutoff");
+ RenderShadowFOVCutoff = gSavedSettings.getF32("RenderShadowFOVCutoff");
+ CameraOffset = gSavedSettings.getBOOL("CameraOffset");
+ CameraMaxCoF = gSavedSettings.getF32("CameraMaxCoF");
+ CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale");
+
+ updateRenderDeferred();
+}
+
+void LLPipeline::releaseGLBuffers()
+{
+ assertInitialized();
+
+ if (mNoiseMap)
+ {
+ LLImageGL::deleteTextures(1, &mNoiseMap);
+ mNoiseMap = 0;
+ }
+
+ if (mTrueNoiseMap)
+ {
+ LLImageGL::deleteTextures(1, &mTrueNoiseMap);
+ mTrueNoiseMap = 0;
+ }
+
+ if (mLightFunc)
+ {
+ LLImageGL::deleteTextures(1, &mLightFunc);
+ mLightFunc = 0;
+ }
+
+ mWaterRef.release();
+ mWaterDis.release();
+
+ for (U32 i = 0; i < 3; i++)
+ {
+ mGlow[i].release();
+ }
+
+ releaseScreenBuffers();
+
+ gBumpImageList.destroyGL();
+ LLVOAvatar::resetImpostors();
+}
+
+void LLPipeline::releaseScreenBuffers()
+{
+ mUIScreen.release();
+ mScreen.release();
+ mFXAABuffer.release();
+ mPhysicsDisplay.release();
+ mDeferredScreen.release();
+ mDeferredDepth.release();
+ mDeferredLight.release();
+
+ mHighlight.release();
+
+ for (U32 i = 0; i < 6; i++)
+ {
+ mShadow[i].release();
+ }
+}
+
+
+void LLPipeline::createGLBuffers()
+{
+ stop_glerror();
+ LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS);
+ assertInitialized();
+
+ updateRenderDeferred();
+
+ if (LLPipeline::sWaterReflections)
+ { //water reflection texture
+ U32 res = (U32) gSavedSettings.getS32("RenderWaterRefResolution");
+
+ mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE);
+ mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE);
+ }
+
+ mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE);
+
+ stop_glerror();
+
+ GLuint resX = gViewerWindow->getWorldViewWidthRaw();
+ GLuint resY = gViewerWindow->getWorldViewHeightRaw();
+
+ if (LLPipeline::sRenderGlow)
+ { //screen space glow buffers
+ const U32 glow_res = llmax(1,
+ llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow")));
+
+ for (U32 i = 0; i < 3; i++)
+ {
+ mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE);
+ }
+
+ allocateScreenBuffer(resX,resY);
+ mScreenWidth = 0;
+ mScreenHeight = 0;
+ }
+
+ if (sRenderDeferred)
+ {
+ if (!mNoiseMap)
+ {
+ const U32 noiseRes = 128;
+ LLVector3 noise[noiseRes*noiseRes];
+
+ F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f;
+ for (U32 i = 0; i < noiseRes*noiseRes; ++i)
+ {
+ noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f);
+ noise[i].normVec();
+ noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f;
+ }
+
+ LLImageGL::generateTextures(1, &mNoiseMap);
+
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ if (!mTrueNoiseMap)
+ {
+ const U32 noiseRes = 128;
+ F32 noise[noiseRes*noiseRes*3];
+ for (U32 i = 0; i < noiseRes*noiseRes*3; i++)
+ {
+ noise[i] = ll_frand()*2.0-1.0;
+ }
+
+ LLImageGL::generateTextures(1, &mTrueNoiseMap);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ if (!mLightFunc)
+ {
+ U32 lightResX = gSavedSettings.getU32("RenderSpecularResX");
+ U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
+ U8* lg = new U8[lightResX*lightResY];
+
+ for (U32 y = 0; y < lightResY; ++y)
+ {
+ for (U32 x = 0; x < lightResX; ++x)
+ {
+ //spec func
+ F32 sa = (F32) x/(lightResX-1);
+ F32 spec = (F32) y/(lightResY-1);
+ //lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255);
+
+ //F32 sp = acosf(sa)/(1.f-spec);
+
+ sa = powf(sa, gSavedSettings.getF32("RenderSpecularExponent"));
+ F32 a = acosf(sa*0.25f+0.75f);
+ F32 m = llmax(0.5f-spec*0.5f, 0.001f);
+ F32 t2 = tanf(a)/m;
+ t2 *= t2;
+
+ F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f;
+ F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2);
+
+ lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255);
+ }
+ }
+
+ LLImageGL::generateTextures(1, &mLightFunc);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R8, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, lg);
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
+
+ delete [] lg;
+ }
+ }
+
+ gBumpImageList.restoreGL();
+}
+
+void LLPipeline::restoreGL()
+{
+ LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_RESTORE_GL);
+ assertInitialized();
+
+ if (mVertexShadersEnabled)
+ {
+ LLViewerShaderMgr::instance()->setShaders();
+ }
+
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+ for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(i);
+ if (part)
+ {
+ part->restoreGL();
+ }
+ }
+ }
+}
+
+
+BOOL LLPipeline::canUseVertexShaders()
+{
+ static const std::string vertex_shader_enable_feature_string = "VertexShaderEnable";
+
+ if (sDisableShaders ||
+ !gGLManager.mHasVertexShader ||
+ !gGLManager.mHasFragmentShader ||
+ !LLFeatureManager::getInstance()->isFeatureAvailable(vertex_shader_enable_feature_string) ||
+ (assertInitialized() && mVertexShadersLoaded != 1) )
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+BOOL LLPipeline::canUseWindLightShaders() const
+{
+ return (!LLPipeline::sDisableShaders &&
+ gWLSkyProgram.mProgramObject != 0 &&
+ LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1);
+}
+
+BOOL LLPipeline::canUseWindLightShadersOnObjects() const
+{
+ return (canUseWindLightShaders()
+ && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0);
+}
+
+BOOL LLPipeline::canUseAntiAliasing() const
+{
+ return TRUE;
+}
+
+void LLPipeline::unloadShaders()
+{
+ LLMemType mt_us(LLMemType::MTYPE_PIPELINE_UNLOAD_SHADERS);
+ LLViewerShaderMgr::instance()->unloadShaders();
+
+ mVertexShadersLoaded = 0;
+}
+
+void LLPipeline::assertInitializedDoError()
+{
+ llerrs << "LLPipeline used when uninitialized." << llendl;
+}
+
+//============================================================================
+
+void LLPipeline::enableShadows(const BOOL enable_shadows)
+{
+ //should probably do something here to wrangle shadows....
+}
+
+S32 LLPipeline::getMaxLightingDetail() const
+{
+ /*if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)
+ {
+ return 3;
+ }
+ else*/
+ {
+ return 1;
+ }
+}
+
+S32 LLPipeline::setLightingDetail(S32 level)
+{
+ LLMemType mt_ld(LLMemType::MTYPE_PIPELINE_LIGHTING_DETAIL);
+ refreshCachedSettings();
+
+ if (level < 0)
+ {
+ if (RenderLocalLights)
+ {
+ level = 1;
+ }
+ else
+ {
+ level = 0;
+ }
+ }
+ level = llclamp(level, 0, getMaxLightingDetail());
+ mLightingDetail = level;
+
+ return mLightingDetail;
+}
+
+class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable>
+{
+public:
+ const std::set<LLViewerFetchedTexture*>& mTextures;
+
+ LLOctreeDirtyTexture(const std::set<LLViewerFetchedTexture*>& textures) : mTextures(textures) { }
+
+ virtual void visit(const LLOctreeNode<LLDrawable>* node)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
+
+ if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty())
+ {
+ for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
+ {
+ for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
+ {
+ LLDrawInfo* params = *j;
+ LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params->mTexture);
+ if (tex && mTextures.find(tex) != mTextures.end())
+ {
+ group->setState(LLSpatialGroup::GEOM_DIRTY);
+ }
+ }
+ }
+ }
+
+ for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
+ {
+ LLSpatialBridge* bridge = *i;
+ traverse(bridge->mOctree);
+ }
+ }
+};
+
+// Called when a texture changes # of channels (causes faces to move to alpha pool)
+void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerFetchedTexture*>& textures)
+{
+ assertInitialized();
+
+ // *TODO: This is inefficient and causes frame spikes; need a better way to do this
+ // Most of the time is spent in dirty.traverse.
+
+ for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+ {
+ LLDrawPool *poolp = *iter;
+ if (poolp->isFacePool())
+ {
+ ((LLFacePool*) poolp)->dirtyTextures(textures);
+ }
+ }
+
+ LLOctreeDirtyTexture dirty(textures);
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+ for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(i);
+ if (part)
+ {
+ dirty.traverse(part->mOctree);
+ }
+ }
+ }
+}
+
+LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
+{
+ assertInitialized();
+
+ LLDrawPool *poolp = NULL;
+ switch( type )
+ {
+ case LLDrawPool::POOL_SIMPLE:
+ poolp = mSimplePool;
+ break;
+
+ case LLDrawPool::POOL_GRASS:
+ poolp = mGrassPool;
+ break;
+
+ case LLDrawPool::POOL_FULLBRIGHT:
+ poolp = mFullbrightPool;
+ break;
+
+ case LLDrawPool::POOL_INVISIBLE:
+ poolp = mInvisiblePool;
+ break;
+
+ case LLDrawPool::POOL_GLOW:
+ poolp = mGlowPool;
+ break;
+
+ case LLDrawPool::POOL_TREE:
+ poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 );
+ break;
+
+ case LLDrawPool::POOL_TERRAIN:
+ poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 );
+ break;
+
+ case LLDrawPool::POOL_BUMP:
+ poolp = mBumpPool;
+ break;
+
+ case LLDrawPool::POOL_ALPHA:
+ poolp = mAlphaPool;
+ break;
+
+ case LLDrawPool::POOL_AVATAR:
+ break; // Do nothing
+
+ case LLDrawPool::POOL_SKY:
+ poolp = mSkyPool;
+ break;
+
+ case LLDrawPool::POOL_WATER:
+ poolp = mWaterPool;
+ break;
+
+ case LLDrawPool::POOL_GROUND:
+ poolp = mGroundPool;
+ break;
+
+ case LLDrawPool::POOL_WL_SKY:
+ poolp = mWLSkyPool;
+ break;
+
+ default:
+ llassert(0);
+ llerrs << "Invalid Pool Type in LLPipeline::findPool() type=" << type << llendl;
+ break;
+ }
+
+ return poolp;
+}
+
+
+LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerTexture *tex0)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ LLDrawPool *poolp = findPool(type, tex0);
+ if (poolp)
+ {
+ return poolp;
+ }
+
+ LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0);
+ addPool( new_poolp );
+
+ return new_poolp;
+}
+
+
+// static
+LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ U32 type = getPoolTypeFromTE(te, imagep);
+ return gPipeline.getPool(type, imagep);
+}
+
+//static
+U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
+{
+ LLMemType mt_gpt(LLMemType::MTYPE_PIPELINE_GET_POOL_TYPE);
+
+ if (!te || !imagep)
+ {
+ return 0;
+ }
+
+ bool alpha = te->getColor().mV[3] < 0.999f;
+ if (imagep)
+ {
+ alpha = alpha || (imagep->getComponents() == 4 && imagep->getType() != LLViewerTexture::MEDIA_TEXTURE) || (imagep->getComponents() == 2);
+ }
+
+ if (alpha)
+ {
+ return LLDrawPool::POOL_ALPHA;
+ }
+ else if ((te->getBumpmap() || te->getShiny()))
+ {
+ return LLDrawPool::POOL_BUMP;
+ }
+ else
+ {
+ return LLDrawPool::POOL_SIMPLE;
+ }
+}
+
+
+void LLPipeline::addPool(LLDrawPool *new_poolp)
+{
+ LLMemType mt_a(LLMemType::MTYPE_PIPELINE_ADD_POOL);
+ assertInitialized();
+ mPools.insert(new_poolp);
+ addToQuickLookup( new_poolp );
+}
+
+void LLPipeline::allocDrawable(LLViewerObject *vobj)
+{
+ LLMemType mt_ad(LLMemType::MTYPE_PIPELINE_ALLOCATE_DRAWABLE);
+ LLDrawable *drawable = new LLDrawable();
+ vobj->mDrawable = drawable;
+
+ drawable->mVObjp = vobj;
+
+ //encompass completely sheared objects by taking
+ //the most extreme point possible (<1,1,0.5>)
+ drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length());
+ if (vobj->isOrphaned())
+ {
+ drawable->setState(LLDrawable::FORCE_INVISIBLE);
+ }
+ drawable->updateXform(TRUE);
+}
+
+
+static LLFastTimer::DeclareTimer FTM_UNLINK("Unlink");
+static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_MOVE_LIST("Movelist");
+static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_SPATIAL_PARTITION("Spatial Partition");
+static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_LIGHT_SET("Light Set");
+static LLFastTimer::DeclareTimer FTM_REMOVE_FROM_HIGHLIGHT_SET("Highlight Set");
+
+void LLPipeline::unlinkDrawable(LLDrawable *drawable)
+{
+ LLFastTimer t(FTM_UNLINK);
+
+ assertInitialized();
+
+ LLPointer<LLDrawable> drawablep = drawable; // make sure this doesn't get deleted before we are done
+
+ // Based on flags, remove the drawable from the queues that it's on.
+ if (drawablep->isState(LLDrawable::ON_MOVE_LIST))
+ {
+ LLFastTimer t(FTM_REMOVE_FROM_MOVE_LIST);
+ LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep);
+ if (iter != mMovedList.end())
+ {
+ mMovedList.erase(iter);
+ }
+ }
+
+ if (drawablep->getSpatialGroup())
+ {
+ LLFastTimer t(FTM_REMOVE_FROM_SPATIAL_PARTITION);
+ if (!drawablep->getSpatialGroup()->mSpatialPartition->remove(drawablep, drawablep->getSpatialGroup()))
+ {
+#ifdef LL_RELEASE_FOR_DOWNLOAD
+ llwarns << "Couldn't remove object from spatial group!" << llendl;
+#else
+ llerrs << "Couldn't remove object from spatial group!" << llendl;
+#endif
+ }
+ }
+
+ {
+ LLFastTimer t(FTM_REMOVE_FROM_LIGHT_SET);
+ mLights.erase(drawablep);
+
+ for (light_set_t::iterator iter = mNearbyLights.begin();
+ iter != mNearbyLights.end(); iter++)
+ {
+ if (iter->drawable == drawablep)
+ {
+ mNearbyLights.erase(iter);
+ break;
+ }
+ }
+ }
+
+ {
+ LLFastTimer t(FTM_REMOVE_FROM_HIGHLIGHT_SET);
+ HighlightItem item(drawablep);
+ mHighlightSet.erase(item);
+
+ if (mHighlightObject == drawablep)
+ {
+ mHighlightObject = NULL;
+ }
+ }
+
+ for (U32 i = 0; i < 2; ++i)
+ {
+ if (mShadowSpotLight[i] == drawablep)
+ {
+ mShadowSpotLight[i] = NULL;
+ }
+
+ if (mTargetShadowSpotLight[i] == drawablep)
+ {
+ mTargetShadowSpotLight[i] = NULL;
+ }
+ }
+
+
+}
+
+U32 LLPipeline::addObject(LLViewerObject *vobj)
+{
+ LLMemType mt_ao(LLMemType::MTYPE_PIPELINE_ADD_OBJECT);
+
+ if (RenderDelayCreation)
+ {
+ mCreateQ.push_back(vobj);
+ }
+ else
+ {
+ createObject(vobj);
+ }
+
+ return 1;
+}
+
+void LLPipeline::createObjects(F32 max_dtime)
+{
+ LLFastTimer ftm(FTM_GEO_UPDATE);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS);
+
+ LLTimer update_timer;
+
+ while (!mCreateQ.empty() && update_timer.getElapsedTimeF32() < max_dtime)
+ {
+ LLViewerObject* vobj = mCreateQ.front();
+ if (!vobj->isDead())
+ {
+ createObject(vobj);
+ }
+ mCreateQ.pop_front();
+ }
+
+ //for (LLViewerObject::vobj_list_t::iterator iter = mCreateQ.begin(); iter != mCreateQ.end(); ++iter)
+ //{
+ // createObject(*iter);
+ //}
+
+ //mCreateQ.clear();
+}
+
+void LLPipeline::createObject(LLViewerObject* vobj)
+{
+ LLDrawable* drawablep = vobj->mDrawable;
+
+ if (!drawablep)
+ {
+ drawablep = vobj->createDrawable(this);
+ }
+ else
+ {
+ llerrs << "Redundant drawable creation!" << llendl;
+ }
+
+ llassert(drawablep);
+
+ if (vobj->getParent())
+ {
+ vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1
+ }
+ else
+ {
+ vobj->setDrawableParent(NULL); // LLPipeline::addObject 2
+ }
+
+ markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE);
+
+ if (drawablep->getVOVolume() && RenderAnimateRes)
+ {
+ // fun animated res
+ drawablep->updateXform(TRUE);
+ drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
+ drawablep->setScale(LLVector3(0,0,0));
+ drawablep->makeActive();
+ }
+}
+
+
+void LLPipeline::resetFrameStats()
+{
+ assertInitialized();
+
+ LLViewerStats::getInstance()->mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f);
+
+ if (mBatchCount > 0)
+ {
+ mMeanBatchSize = gPipeline.mTrianglesDrawn/gPipeline.mBatchCount;
+ }
+ mTrianglesDrawn = 0;
+ sCompiles = 0;
+ mVerticesRelit = 0;
+ mLightingChanges = 0;
+ mGeometryChanges = 0;
+ mNumVisibleFaces = 0;
+
+ if (mOldRenderDebugMask != mRenderDebugMask)
+ {
+ gObjectList.clearDebugText();
+ mOldRenderDebugMask = mRenderDebugMask;
+ }
+
+}
+
+//external functions for asynchronous updating
+void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep)
+{
+ if (FreezeTime)
+ {
+ return;
+ }
+ if (!drawablep)
+ {
+ llerrs << "updateMove called with NULL drawablep" << llendl;
+ return;
+ }
+ if (drawablep->isState(LLDrawable::EARLY_MOVE))
+ {
+ return;
+ }
+
+ assertInitialized();
+
+ // update drawable now
+ drawablep->clearState(LLDrawable::MOVE_UNDAMPED); // force to DAMPED
+ drawablep->updateMove(); // returns done
+ drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
+ // Put on move list so that EARLY_MOVE gets cleared
+ if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
+ {
+ mMovedList.push_back(drawablep);
+ drawablep->setState(LLDrawable::ON_MOVE_LIST);
+ }
+}
+
+void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep)
+{
+ if (FreezeTime)
+ {
+ return;
+ }
+ if (!drawablep)
+ {
+ llerrs << "updateMove called with NULL drawablep" << llendl;
+ return;
+ }
+ if (drawablep->isState(LLDrawable::EARLY_MOVE))
+ {
+ return;
+ }
+
+ assertInitialized();
+
+ // update drawable now
+ drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED
+ drawablep->updateMove();
+ drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
+ // Put on move list so that EARLY_MOVE gets cleared
+ if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
+ {
+ mMovedList.push_back(drawablep);
+ drawablep->setState(LLDrawable::ON_MOVE_LIST);
+ }
+}
+
+void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)
+{
+ for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin();
+ iter != moved_list.end(); )
+ {
+ LLDrawable::drawable_vector_t::iterator curiter = iter++;
+ LLDrawable *drawablep = *curiter;
+ BOOL done = TRUE;
+ if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE)))
+ {
+ done = drawablep->updateMove();
+ }
+ drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);
+ if (done)
+ {
+ drawablep->clearState(LLDrawable::ON_MOVE_LIST);
+ iter = moved_list.erase(curiter);
+ }
+ }
+}
+
+static LLFastTimer::DeclareTimer FTM_OCTREE_BALANCE("Balance Octree");
+static LLFastTimer::DeclareTimer FTM_UPDATE_MOVE("Update Move");
+
+void LLPipeline::updateMove()
+{
+ LLFastTimer t(FTM_UPDATE_MOVE);
+ LLMemType mt_um(LLMemType::MTYPE_PIPELINE_UPDATE_MOVE);
+
+ if (FreezeTime)
+ {
+ return;
+ }
+
+ assertInitialized();
+
+ {
+ static LLFastTimer::DeclareTimer ftm("Retexture");
+ LLFastTimer t(ftm);
+
+ for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin();
+ iter != mRetexturedList.end(); ++iter)
+ {
+ LLDrawable* drawablep = *iter;
+ if (drawablep && !drawablep->isDead())
+ {
+ drawablep->updateTexture();
+ }
+ }
+ mRetexturedList.clear();
+ }
+
+ {
+ static LLFastTimer::DeclareTimer ftm("Moved List");
+ LLFastTimer t(ftm);
+ updateMovedList(mMovedList);
+ }
+
+ //balance octrees
+ {
+ LLFastTimer ot(FTM_OCTREE_BALANCE);
+
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+ for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(i);
+ if (part)
+ {
+ part->mOctree->balance();
+ }
+ }
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Culling and occlusion testing
+/////////////////////////////////////////////////////////////////////////////
+
+//static
+F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
+{
+ LLVector3 lookAt = center - camera.getOrigin();
+ F32 dist = lookAt.length();
+
+ //ramp down distance for nearby objects
+ //shrink dist by dist/16.
+ if (dist < 16.f)
+ {
+ dist /= 16.f;
+ dist *= dist;
+ dist *= 16.f;
+ }
+
+ //get area of circle around node
+ F32 app_angle = atanf(size.length()/dist);
+ F32 radius = app_angle*LLDrawable::sCurPixelAngle;
+ return radius*radius * F_PI;
+}
+
+//static
+F32 LLPipeline::calcPixelArea(const LLVector4a& center, const LLVector4a& size, LLCamera &camera)
+{
+ LLVector4a origin;
+ origin.load3(camera.getOrigin().mV);
+
+ LLVector4a lookAt;
+ lookAt.setSub(center, origin);
+ F32 dist = lookAt.getLength3().getF32();
+
+ //ramp down distance for nearby objects
+ //shrink dist by dist/16.
+ if (dist < 16.f)
+ {
+ dist /= 16.f;
+ dist *= dist;
+ dist *= 16.f;
+ }
+
+ //get area of circle around node
+ F32 app_angle = atanf(size.getLength3().getF32()/dist);
+ F32 radius = app_angle*LLDrawable::sCurPixelAngle;
+ return radius*radius * F_PI;
+}
+
+void LLPipeline::grabReferences(LLCullResult& result)
+{
+ sCull = &result;
+}
+
+void LLPipeline::clearReferences()
+{
+ sCull = NULL;
+}
+
+void check_references(LLSpatialGroup* group, LLDrawable* drawable)
+{
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+ {
+ if (drawable == *i)
+ {
+ llerrs << "LLDrawable deleted while actively reference by LLPipeline." << llendl;
+ }
+ }
+}
+
+void check_references(LLDrawable* drawable, LLFace* face)
+{
+ for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+ {
+ if (drawable->getFace(i) == face)
+ {
+ llerrs << "LLFace deleted while actively referenced by LLPipeline." << llendl;
+ }
+ }
+}
+
+void check_references(LLSpatialGroup* group, LLFace* face)
+{
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+ {
+ LLDrawable* drawable = *i;
+ check_references(drawable, face);
+ }
+}
+
+void LLPipeline::checkReferences(LLFace* face)
+{
+#if 0
+ if (sCull)
+ {
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, face);
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, face);
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, face);
+ }
+
+ for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter)
+ {
+ LLDrawable* drawable = *iter;
+ check_references(drawable, face);
+ }
+ }
+#endif
+}
+
+void LLPipeline::checkReferences(LLDrawable* drawable)
+{
+#if 0
+ if (sCull)
+ {
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, drawable);
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, drawable);
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, drawable);
+ }
+
+ for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter)
+ {
+ if (drawable == *iter)
+ {
+ llerrs << "LLDrawable deleted while actively referenced by LLPipeline." << llendl;
+ }
+ }
+ }
+#endif
+}
+
+void check_references(LLSpatialGroup* group, LLDrawInfo* draw_info)
+{
+ for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
+ {
+ LLSpatialGroup::drawmap_elem_t& draw_vec = i->second;
+ for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j)
+ {
+ LLDrawInfo* params = *j;
+ if (params == draw_info)
+ {
+ llerrs << "LLDrawInfo deleted while actively referenced by LLPipeline." << llendl;
+ }
+ }
+ }
+}
+
+
+void LLPipeline::checkReferences(LLDrawInfo* draw_info)
+{
+#if 0
+ if (sCull)
+ {
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, draw_info);
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, draw_info);
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, draw_info);
+ }
+ }
+#endif
+}
+
+void LLPipeline::checkReferences(LLSpatialGroup* group)
+{
+#if 0
+ if (sCull)
+ {
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+ {
+ if (group == *iter)
+ {
+ llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
+ }
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
+ {
+ if (group == *iter)
+ {
+ llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
+ }
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+ {
+ if (group == *iter)
+ {
+ llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
+ }
+ }
+ }
+#endif
+}
+
+
+BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera)
+{
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+
+ for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(i);
+ if (part)
+ {
+ if (hasRenderType(part->mDrawableType))
+ {
+ if (part->visibleObjectsInFrustum(camera))
+ {
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& max)
+{
+ const F32 X = 65536.f;
+
+ min = LLVector3(X,X,X);
+ max = LLVector3(-X,-X,-X);
+
+ U32 saved_camera_id = LLViewerCamera::sCurCameraID;
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+
+ BOOL res = TRUE;
+
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+
+ for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(i);
+ if (part)
+ {
+ if (hasRenderType(part->mDrawableType))
+ {
+ if (!part->getVisibleExtents(camera, min, max))
+ {
+ res = FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ LLViewerCamera::sCurCameraID = saved_camera_id;
+
+ return res;
+}
+
+static LLFastTimer::DeclareTimer FTM_CULL("Object Culling");
+
+void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip, LLPlane* planep)
+{
+ LLFastTimer t(FTM_CULL);
+ LLMemType mt_uc(LLMemType::MTYPE_PIPELINE_UPDATE_CULL);
+
+ grabReferences(result);
+
+ sCull->clear();
+
+ BOOL to_texture = LLPipeline::sUseOcclusion > 1 &&
+ !hasRenderType(LLPipeline::RENDER_TYPE_HUD) &&
+ LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
+ gPipeline.canUseVertexShaders() &&
+ sRenderGlow;
+
+ if (to_texture)
+ {
+ mScreen.bindTarget();
+ }
+
+ if (sUseOcclusion > 1)
+ {
+ gGL.setColorMask(false, false);
+ }
+
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadMatrix(gGLLastProjection);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.pushMatrix();
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLLastModelView);
+
+
+ LLVertexBuffer::unbind();
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+
+ //setup a clip plane in projection matrix for reflection renders (prevents flickering from occlusion culling)
+ LLViewerRegion* region = gAgent.getRegion();
+ LLPlane plane;
+
+ if (planep)
+ {
+ plane = *planep;
+ }
+ else
+ {
+ if (region)
+ {
+ LLVector3 pnorm;
+ F32 height = region->getWaterHeight();
+ if (water_clip < 0)
+ { //camera is above water, clip plane points up
+ pnorm.setVec(0,0,1);
+ plane.setVec(pnorm, -height);
+ }
+ else if (water_clip > 0)
+ { //camera is below water, clip plane points down
+ pnorm = LLVector3(0,0,-1);
+ plane.setVec(pnorm, height);
+ }
+ }
+ }
+
+ glh::matrix4f modelview = glh_get_last_modelview();
+ glh::matrix4f proj = glh_get_last_projection();
+ LLGLUserClipPlane clip(plane, modelview, proj, water_clip != 0 && LLPipeline::sReflectionRender);
+
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+
+ bool bound_shader = false;
+ if (gPipeline.canUseVertexShaders() && LLGLSLShader::sCurBoundShader == 0)
+ { //if no shader is currently bound, use the occlusion shader instead of fixed function if we can
+ // (shadow render uses a special shader that clamps to clip planes)
+ bound_shader = true;
+ gOcclusionProgram.bind();
+ }
+
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+ if (water_clip != 0)
+ {
+ LLPlane plane(LLVector3(0,0, (F32) -water_clip), (F32) water_clip*region->getWaterHeight());
+ camera.setUserClipPlane(plane);
+ }
+ else
+ {
+ camera.disableUserClipPlane();
+ }
+
+ for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(i);
+ if (part)
+ {
+ if (hasRenderType(part->mDrawableType))
+ {
+ part->cull(camera);
+ }
+ }
+ }
+ }
+
+ if (bound_shader)
+ {
+ gOcclusionProgram.unbind();
+ }
+
+ camera.disableUserClipPlane();
+
+ if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) &&
+ gSky.mVOSkyp.notNull() &&
+ gSky.mVOSkyp->mDrawable.notNull())
+ {
+ gSky.mVOSkyp->mDrawable->setVisible(camera);
+ sCull->pushDrawable(gSky.mVOSkyp->mDrawable);
+ gSky.updateCull();
+ stop_glerror();
+ }
+
+ if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) &&
+ !gPipeline.canUseWindLightShaders() &&
+ gSky.mVOGroundp.notNull() &&
+ gSky.mVOGroundp->mDrawable.notNull() &&
+ !LLPipeline::sWaterReflections)
+ {
+ gSky.mVOGroundp->mDrawable->setVisible(camera);
+ sCull->pushDrawable(gSky.mVOGroundp->mDrawable);
+ }
+
+
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+
+ if (sUseOcclusion > 1)
+ {
+ gGL.setColorMask(true, false);
+ }
+
+ if (to_texture)
+ {
+ mScreen.flush();
+ }
+}
+
+void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
+{
+ if (group->getData().empty())
+ {
+ return;
+ }
+
+ group->setVisible();
+
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ {
+ group->updateDistance(camera);
+ }
+
+ const F32 MINIMUM_PIXEL_AREA = 16.f;
+
+ if (group->mPixelArea < MINIMUM_PIXEL_AREA)
+ {
+ return;
+ }
+
+ if (sMinRenderSize > 0.f &&
+ llmax(llmax(group->mBounds[1][0], group->mBounds[1][1]), group->mBounds[1][2]) < sMinRenderSize)
+ {
+ return;
+ }
+
+ assertInitialized();
+
+ if (!group->mSpatialPartition->mRenderByGroup)
+ { //render by drawable
+ sCull->pushDrawableGroup(group);
+ }
+ else
+ { //render by group
+ sCull->pushVisibleGroup(group);
+ }
+
+ mNumVisibleNodes++;
+}
+
+void LLPipeline::markOccluder(LLSpatialGroup* group)
+{
+ if (sUseOcclusion > 1 && group && !group->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION))
+ {
+ LLSpatialGroup* parent = group->getParent();
+
+ if (!parent || !parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
+ { //only mark top most occluders as active occlusion
+ sCull->pushOcclusionGroup(group);
+ group->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
+
+ if (parent &&
+ !parent->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION) &&
+ parent->getElementCount() == 0 &&
+ parent->needsUpdate())
+ {
+ sCull->pushOcclusionGroup(group);
+ parent->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
+ }
+ }
+ }
+}
+
+void LLPipeline::doOcclusion(LLCamera& camera)
+{
+ if (LLPipeline::sUseOcclusion > 1 && sCull->hasOcclusionGroups())
+ {
+ LLVertexBuffer::unbind();
+
+ if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
+ {
+ gGL.setColorMask(true, false, false, false);
+ }
+ else
+ {
+ gGL.setColorMask(false, false);
+ }
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+
+ LLGLDisable cull(GL_CULL_FACE);
+
+
+ bool bind_shader = LLGLSLShader::sNoFixedFunction && LLGLSLShader::sCurBoundShader == 0;
+ if (bind_shader)
+ {
+ if (LLPipeline::sShadowRender)
+ {
+ gDeferredShadowProgram.bind();
+ }
+ else
+ {
+ gOcclusionProgram.bind();
+ }
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ group->doOcclusion(&camera);
+ group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
+ }
+
+ if (bind_shader)
+ {
+ if (LLPipeline::sShadowRender)
+ {
+ gDeferredShadowProgram.unbind();
+ }
+ else
+ {
+ gOcclusionProgram.unbind();
+ }
+ }
+
+ gGL.setColorMask(true, false);
+ }
+}
+
+BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
+{
+ BOOL update_complete = drawablep->updateGeometry(priority);
+ if (update_complete && assertInitialized())
+ {
+ drawablep->setState(LLDrawable::BUILT);
+ mGeometryChanges++;
+ }
+ return update_complete;
+}
+
+void LLPipeline::updateGL()
+{
+ while (!LLGLUpdate::sGLQ.empty())
+ {
+ LLGLUpdate* glu = LLGLUpdate::sGLQ.front();
+ glu->updateGL();
+ glu->mInQ = FALSE;
+ LLGLUpdate::sGLQ.pop_front();
+ }
+}
+
+void LLPipeline::rebuildPriorityGroups()
+{
+ LLTimer update_timer;
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+
+ assertInitialized();
+
+ gMeshRepo.notifyLoadedMeshes();
+
+ mGroupQ1Locked = true;
+ // Iterate through all drawables on the priority build queue,
+ for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin();
+ iter != mGroupQ1.end(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ group->rebuildGeom();
+ group->clearState(LLSpatialGroup::IN_BUILD_Q1);
+ }
+
+ mGroupQ1.clear();
+ mGroupQ1Locked = false;
+
+}
+
+void LLPipeline::rebuildGroups()
+{
+ if (mGroupQ2.empty())
+ {
+ return;
+ }
+
+ mGroupQ2Locked = true;
+ // Iterate through some drawables on the non-priority build queue
+ S32 size = (S32) mGroupQ2.size();
+ S32 min_count = llclamp((S32) ((F32) (size * size)/4096*0.25f), 1, size);
+
+ S32 count = 0;
+
+ std::sort(mGroupQ2.begin(), mGroupQ2.end(), LLSpatialGroup::CompareUpdateUrgency());
+
+ LLSpatialGroup::sg_vector_t::iterator iter;
+ LLSpatialGroup::sg_vector_t::iterator last_iter = mGroupQ2.begin();
+
+ for (iter = mGroupQ2.begin();
+ iter != mGroupQ2.end() && count <= min_count; ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ last_iter = iter;
+
+ if (!group->isDead())
+ {
+ group->rebuildGeom();
+
+ if (group->mSpatialPartition->mRenderByGroup)
+ {
+ count++;
+ }
+ }
+
+ group->clearState(LLSpatialGroup::IN_BUILD_Q2);
+ }
+
+ mGroupQ2.erase(mGroupQ2.begin(), ++last_iter);
+
+ mGroupQ2Locked = false;
+
+ updateMovedList(mMovedBridge);
+}
+
+void LLPipeline::updateGeom(F32 max_dtime)
+{
+ LLTimer update_timer;
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_UPDATE_GEOM);
+ LLPointer<LLDrawable> drawablep;
+
+ LLFastTimer t(FTM_GEO_UPDATE);
+
+ assertInitialized();
+
+ // notify various object types to reset internal cost metrics, etc.
+ // for now, only LLVOVolume does this to throttle LOD changes
+ LLVOVolume::preUpdateGeom();
+
+ // Iterate through all drawables on the priority build queue,
+ for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin();
+ iter != mBuildQ1.end();)
+ {
+ LLDrawable::drawable_list_t::iterator curiter = iter++;
+ LLDrawable* drawablep = *curiter;
+ if (drawablep && !drawablep->isDead())
+ {
+ if (drawablep->isState(LLDrawable::IN_REBUILD_Q2))
+ {
+ drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
+ LLDrawable::drawable_list_t::iterator find = std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep);
+ if (find != mBuildQ2.end())
+ {
+ mBuildQ2.erase(find);
+ }
+ }
+
+ if (updateDrawableGeom(drawablep, TRUE))
+ {
+ drawablep->clearState(LLDrawable::IN_REBUILD_Q1);
+ mBuildQ1.erase(curiter);
+ }
+ }
+ else
+ {
+ mBuildQ1.erase(curiter);
+ }
+ }
+
+ // Iterate through some drawables on the non-priority build queue
+ S32 min_count = 16;
+ S32 size = (S32) mBuildQ2.size();
+ if (size > 1024)
+ {
+ min_count = llclamp((S32) (size * (F32) size/4096), 16, size);
+ }
+
+ S32 count = 0;
+
+ max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime);
+ LLSpatialGroup* last_group = NULL;
+ LLSpatialBridge* last_bridge = NULL;
+
+ for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin();
+ iter != mBuildQ2.end(); )
+ {
+ LLDrawable::drawable_list_t::iterator curiter = iter++;
+ LLDrawable* drawablep = *curiter;
+
+ LLSpatialBridge* bridge = drawablep->isRoot() ? drawablep->getSpatialBridge() :
+ drawablep->getParent()->getSpatialBridge();
+
+ if (drawablep->getSpatialGroup() != last_group &&
+ (!last_bridge || bridge != last_bridge) &&
+ (update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count)
+ {
+ break;
+ }
+
+ //make sure updates don't stop in the middle of a spatial group
+ //to avoid thrashing (objects are enqueued by group)
+ last_group = drawablep->getSpatialGroup();
+ last_bridge = bridge;
+
+ BOOL update_complete = TRUE;
+ if (!drawablep->isDead())
+ {
+ update_complete = updateDrawableGeom(drawablep, FALSE);
+ count++;
+ }
+ if (update_complete)
+ {
+ drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
+ mBuildQ2.erase(curiter);
+ }
+ }
+
+ updateMovedList(mMovedBridge);
+}
+
+void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_VISIBLE);
+
+ if(drawablep && !drawablep->isDead())
+ {
+ if (drawablep->isSpatialBridge())
+ {
+ const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable;
+ llassert(root); // trying to catch a bad assumption
+ if (root && // // this test may not be needed, see above
+ root->getVObj()->isAttachment())
+ {
+ LLDrawable* rootparent = root->getParent();
+ if (rootparent) // this IS sometimes NULL
+ {
+ LLViewerObject *vobj = rootparent->getVObj();
+ llassert(vobj); // trying to catch a bad assumption
+ if (vobj) // this test may not be needed, see above
+ {
+ const LLVOAvatar* av = vobj->asAvatar();
+ if (av && av->isImpostor())
+ {
+ return;
+ }
+ }
+ }
+ }
+ sCull->pushBridge((LLSpatialBridge*) drawablep);
+ }
+ else
+ {
+ sCull->pushDrawable(drawablep);
+ }
+
+ drawablep->setVisible(camera);
+ }
+}
+
+void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
+{
+ LLMemType mt_mm(LLMemType::MTYPE_PIPELINE_MARK_MOVED);
+
+ if (!drawablep)
+ {
+ //llerrs << "Sending null drawable to moved list!" << llendl;
+ return;
+ }
+
+ if (drawablep->isDead())
+ {
+ llwarns << "Marking NULL or dead drawable moved!" << llendl;
+ return;
+ }
+
+ if (drawablep->getParent())
+ {
+ //ensure that parent drawables are moved first
+ markMoved(drawablep->getParent(), damped_motion);
+ }
+
+ assertInitialized();
+
+ if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
+ {
+ if (drawablep->isSpatialBridge())
+ {
+ mMovedBridge.push_back(drawablep);
+ }
+ else
+ {
+ mMovedList.push_back(drawablep);
+ }
+ drawablep->setState(LLDrawable::ON_MOVE_LIST);
+ }
+ if (damped_motion == FALSE)
+ {
+ drawablep->setState(LLDrawable::MOVE_UNDAMPED); // UNDAMPED trumps DAMPED
+ }
+ else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
+ {
+ drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
+ }
+}
+
+void LLPipeline::markShift(LLDrawable *drawablep)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_SHIFT);
+
+ if (!drawablep || drawablep->isDead())
+ {
+ return;
+ }
+
+ assertInitialized();
+
+ if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST))
+ {
+ drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE);
+ if (drawablep->getParent())
+ {
+ markShift(drawablep->getParent());
+ }
+ mShiftList.push_back(drawablep);
+ drawablep->setState(LLDrawable::ON_SHIFT_LIST);
+ }
+}
+
+void LLPipeline::shiftObjects(const LLVector3 &offset)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS);
+
+ assertInitialized();
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+ gDepthDirty = TRUE;
+
+ LLVector4a offseta;
+ offseta.load3(offset.mV);
+
+ for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin();
+ iter != mShiftList.end(); iter++)
+ {
+ LLDrawable *drawablep = *iter;
+ if (drawablep->isDead())
+ {
+ continue;
+ }
+ drawablep->shiftPos(offseta);
+ drawablep->clearState(LLDrawable::ON_SHIFT_LIST);
+ }
+ mShiftList.resize(0);
+
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+ for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(i);
+ if (part)
+ {
+ part->shift(offseta);
+ }
+ }
+ }
+
+ LLHUDText::shiftAll(offset);
+ LLHUDNameTag::shiftAll(offset);
+ display_update_camera();
+}
+
+void LLPipeline::markTextured(LLDrawable *drawablep)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_TEXTURED);
+
+ if (drawablep && !drawablep->isDead() && assertInitialized())
+ {
+ mRetexturedList.insert(drawablep);
+ }
+}
+
+void LLPipeline::markGLRebuild(LLGLUpdate* glu)
+{
+ if (glu && !glu->mInQ)
+ {
+ LLGLUpdate::sGLQ.push_back(glu);
+ glu->mInQ = TRUE;
+ }
+}
+
+void LLPipeline::markPartitionMove(LLDrawable* drawable)
+{
+ if (!drawable->isState(LLDrawable::PARTITION_MOVE) &&
+ !drawable->getPositionGroup().equals3(LLVector4a::getZero()))
+ {
+ drawable->setState(LLDrawable::PARTITION_MOVE);
+ mPartitionQ.push_back(drawable);
+ }
+}
+
+void LLPipeline::processPartitionQ()
+{
+ for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter)
+ {
+ LLDrawable* drawable = *iter;
+ if (!drawable->isDead())
+ {
+ drawable->updateBinRadius();
+ drawable->movePartition();
+ }
+ drawable->clearState(LLDrawable::PARTITION_MOVE);
+ }
+
+ mPartitionQ.clear();
+}
+
+void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+
+ if (group && !group->isDead() && group->mSpatialPartition)
+ {
+ if (group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD)
+ {
+ priority = TRUE;
+ }
+
+ if (priority)
+ {
+ if (!group->isState(LLSpatialGroup::IN_BUILD_Q1))
+ {
+ llassert_always(!mGroupQ1Locked);
+
+ mGroupQ1.push_back(group);
+ group->setState(LLSpatialGroup::IN_BUILD_Q1);
+
+ if (group->isState(LLSpatialGroup::IN_BUILD_Q2))
+ {
+ LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group);
+ if (iter != mGroupQ2.end())
+ {
+ mGroupQ2.erase(iter);
+ }
+ group->clearState(LLSpatialGroup::IN_BUILD_Q2);
+ }
+ }
+ }
+ else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1))
+ {
+ llassert_always(!mGroupQ2Locked);
+ mGroupQ2.push_back(group);
+ group->setState(LLSpatialGroup::IN_BUILD_Q2);
+
+ }
+ }
+}
+
+void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_REBUILD);
+
+ if (drawablep && !drawablep->isDead() && assertInitialized())
+ {
+ if (!drawablep->isState(LLDrawable::BUILT))
+ {
+ priority = TRUE;
+ }
+ if (priority)
+ {
+ if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1))
+ {
+ mBuildQ1.push_back(drawablep);
+ drawablep->setState(LLDrawable::IN_REBUILD_Q1); // mark drawable as being in priority queue
+ }
+ }
+ else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2))
+ {
+ mBuildQ2.push_back(drawablep);
+ drawablep->setState(LLDrawable::IN_REBUILD_Q2); // need flag here because it is just a list
+ }
+ if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION))
+ {
+ drawablep->getVObj()->setChanged(LLXform::SILHOUETTE);
+ }
+ drawablep->setState(flag);
+ }
+}
+
+static LLFastTimer::DeclareTimer FTM_RESET_DRAWORDER("Reset Draw Order");
+
+void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
+{
+ if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR,
+ LLPipeline::RENDER_TYPE_GROUND,
+ LLPipeline::RENDER_TYPE_TERRAIN,
+ LLPipeline::RENDER_TYPE_TREE,
+ LLPipeline::RENDER_TYPE_SKY,
+ LLPipeline::RENDER_TYPE_VOIDWATER,
+ LLPipeline::RENDER_TYPE_WATER,
+ LLPipeline::END_RENDER_TYPES))
+ {
+ //clear faces from face pools
+ LLFastTimer t(FTM_RESET_DRAWORDER);
+ gPipeline.resetDrawOrders();
+ }
+
+ LLFastTimer ftm(FTM_STATESORT);
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+
+ //LLVertexBuffer::unbind();
+
+ grabReferences(result);
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ group->checkOcclusion();
+ if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+ {
+ markOccluder(group);
+ }
+ else
+ {
+ group->setVisible();
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+ {
+ markVisible(*i, camera);
+ }
+
+ if (!sDelayVBUpdate)
+ { //rebuild mesh as soon as we know it's visible
+ group->rebuildMesh();
+ }
+ }
+ }
+
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ {
+ LLSpatialGroup* last_group = NULL;
+ for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
+ {
+ LLCullResult::bridge_list_t::iterator cur_iter = i;
+ LLSpatialBridge* bridge = *cur_iter;
+ LLSpatialGroup* group = bridge->getSpatialGroup();
+
+ if (last_group == NULL)
+ {
+ last_group = group;
+ }
+
+ if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+ {
+ stateSort(bridge, camera);
+ }
+
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
+ last_group != group && last_group->changeLOD())
+ {
+ last_group->mLastUpdateDistance = last_group->mDistance;
+ }
+
+ last_group = group;
+ }
+
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
+ last_group && last_group->changeLOD())
+ {
+ last_group->mLastUpdateDistance = last_group->mDistance;
+ }
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ group->checkOcclusion();
+ if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+ {
+ markOccluder(group);
+ }
+ else
+ {
+ group->setVisible();
+ stateSort(group, camera);
+
+ if (!sDelayVBUpdate)
+ { //rebuild mesh as soon as we know it's visible
+ group->rebuildMesh();
+ }
+ }
+ }
+
+ {
+ LLFastTimer ftm(FTM_STATESORT_DRAWABLE);
+ for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList();
+ iter != sCull->endVisibleList(); ++iter)
+ {
+ LLDrawable *drawablep = *iter;
+ if (!drawablep->isDead())
+ {
+ stateSort(drawablep, camera);
+ }
+ }
+ }
+
+ postSort(camera);
+}
+
+void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+ if (group->changeLOD())
+ {
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+ {
+ LLDrawable* drawablep = *i;
+ stateSort(drawablep, camera);
+ }
+
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ { //avoid redundant stateSort calls
+ group->mLastUpdateDistance = group->mDistance;
+ }
+ }
+
+}
+
+void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+ if (bridge->getSpatialGroup()->changeLOD())
+ {
+ bool force_update = false;
+ bridge->updateDistance(camera, force_update);
+ }
+}
+
+void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+
+ if (!drawablep
+ || drawablep->isDead()
+ || !hasRenderType(drawablep->getRenderType()))
+ {
+ return;
+ }
+
+ if (LLSelectMgr::getInstance()->mHideSelectedObjects)
+ {
+ if (drawablep->getVObj().notNull() &&
+ drawablep->getVObj()->isSelected())
+ {
+ return;
+ }
+ }
+
+ if (drawablep->isAvatar())
+ { //don't draw avatars beyond render distance or if we don't have a spatial group.
+ if ((drawablep->getSpatialGroup() == NULL) ||
+ (drawablep->getSpatialGroup()->mDistance > LLVOAvatar::sRenderDistance))
+ {
+ return;
+ }
+
+ LLVOAvatar* avatarp = (LLVOAvatar*) drawablep->getVObj().get();
+ if (!avatarp->isVisible())
+ {
+ return;
+ }
+ }
+
+ assertInitialized();
+
+ if (hasRenderType(drawablep->mRenderType))
+ {
+ if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE))
+ {
+ drawablep->setVisible(camera, NULL, FALSE);
+ }
+ else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE))
+ {
+ // clear invisible flag here to avoid single frame glitch
+ drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE);
+ }
+ }
+
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ {
+ //if (drawablep->isVisible()) isVisible() check here is redundant, if it wasn't visible, it wouldn't be here
+ {
+ if (!drawablep->isActive())
+ {
+ bool force_update = false;
+ drawablep->updateDistance(camera, force_update);
+ }
+ else if (drawablep->isAvatar())
+ {
+ bool force_update = false;
+ drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility()
+ }
+ }
+ }
+
+ if (!drawablep->getVOVolume())
+ {
+ for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
+ iter != drawablep->mFaces.end(); iter++)
+ {
+ LLFace* facep = *iter;
+
+ if (facep->hasGeometry())
+ {
+ if (facep->getPool())
+ {
+ facep->getPool()->enqueue(facep);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+
+
+ mNumVisibleFaces += drawablep->getNumFaces();
+}
+
+
+void forAllDrawables(LLCullResult::sg_list_t::iterator begin,
+ LLCullResult::sg_list_t::iterator end,
+ void (*func)(LLDrawable*))
+{
+ for (LLCullResult::sg_list_t::iterator i = begin; i != end; ++i)
+ {
+ for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j)
+ {
+ func(*j);
+ }
+ }
+}
+
+void LLPipeline::forAllVisibleDrawables(void (*func)(LLDrawable*))
+{
+ forAllDrawables(sCull->beginDrawableGroups(), sCull->endDrawableGroups(), func);
+ forAllDrawables(sCull->beginVisibleGroups(), sCull->endVisibleGroups(), func);
+}
+
+//function for creating scripted beacons
+void renderScriptedBeacons(LLDrawable* drawablep)
+{
+ LLViewerObject *vobj = drawablep->getVObj();
+ if (vobj
+ && !vobj->isAvatar()
+ && !vobj->getParent()
+ && vobj->flagScripted())
+ {
+ if (gPipeline.sRenderBeacons)
+ {
+ gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
+ }
+
+ if (gPipeline.sRenderHighlight)
+ {
+ S32 face_id;
+ S32 count = drawablep->getNumFaces();
+ for (face_id = 0; face_id < count; face_id++)
+ {
+ gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+ }
+ }
+ }
+}
+
+void renderScriptedTouchBeacons(LLDrawable* drawablep)
+{
+ LLViewerObject *vobj = drawablep->getVObj();
+ if (vobj
+ && !vobj->isAvatar()
+ && !vobj->getParent()
+ && vobj->flagScripted()
+ && vobj->flagHandleTouch())
+ {
+ if (gPipeline.sRenderBeacons)
+ {
+ gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
+ }
+
+ if (gPipeline.sRenderHighlight)
+ {
+ S32 face_id;
+ S32 count = drawablep->getNumFaces();
+ for (face_id = 0; face_id < count; face_id++)
+ {
+ gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+ }
+ }
+ }
+}
+
+void renderPhysicalBeacons(LLDrawable* drawablep)
+{
+ LLViewerObject *vobj = drawablep->getVObj();
+ if (vobj
+ && !vobj->isAvatar()
+ //&& !vobj->getParent()
+ && vobj->flagUsePhysics())
+ {
+ if (gPipeline.sRenderBeacons)
+ {
+ gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
+ }
+
+ if (gPipeline.sRenderHighlight)
+ {
+ S32 face_id;
+ S32 count = drawablep->getNumFaces();
+ for (face_id = 0; face_id < count; face_id++)
+ {
+ gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+ }
+ }
+ }
+}
+
+void renderMOAPBeacons(LLDrawable* drawablep)
+{
+ LLViewerObject *vobj = drawablep->getVObj();
+
+ if(!vobj || vobj->isAvatar())
+ return;
+
+ BOOL beacon=FALSE;
+ U8 tecount=vobj->getNumTEs();
+ for(int x=0;x<tecount;x++)
+ {
+ if(vobj->getTE(x)->hasMedia())
+ {
+ beacon=TRUE;
+ break;
+ }
+ }
+ if(beacon==TRUE)
+ {
+ if (gPipeline.sRenderBeacons)
+ {
+ gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 1.f, 1.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
+ }
+
+ if (gPipeline.sRenderHighlight)
+ {
+ S32 face_id;
+ S32 count = drawablep->getNumFaces();
+ for (face_id = 0; face_id < count; face_id++)
+ {
+ gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+ }
+ }
+ }
+}
+
+void renderParticleBeacons(LLDrawable* drawablep)
+{
+ // Look for attachments, objects, etc.
+ LLViewerObject *vobj = drawablep->getVObj();
+ if (vobj
+ && vobj->isParticleSource())
+ {
+ if (gPipeline.sRenderBeacons)
+ {
+ LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f);
+ gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth);
+ }
+
+ if (gPipeline.sRenderHighlight)
+ {
+ S32 face_id;
+ S32 count = drawablep->getNumFaces();
+ for (face_id = 0; face_id < count; face_id++)
+ {
+ gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+ }
+ }
+ }
+}
+
+void renderSoundHighlights(LLDrawable* drawablep)
+{
+ // Look for attachments, objects, etc.
+ LLViewerObject *vobj = drawablep->getVObj();
+ if (vobj && vobj->isAudioSource())
+ {
+ if (gPipeline.sRenderHighlight)
+ {
+ S32 face_id;
+ S32 count = drawablep->getNumFaces();
+ for (face_id = 0; face_id < count; face_id++)
+ {
+ gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+ }
+ }
+ }
+}
+
+void LLPipeline::postSort(LLCamera& camera)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_POST_SORT);
+ LLFastTimer ftm(FTM_STATESORT_POSTSORT);
+
+ assertInitialized();
+
+ llpushcallstacks ;
+ //rebuild drawable geometry
+ for (LLCullResult::sg_list_t::iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
+ {
+ LLSpatialGroup* group = *i;
+ if (!sUseOcclusion ||
+ !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+ {
+ group->rebuildGeom();
+ }
+ }
+ llpushcallstacks ;
+ //rebuild groups
+ sCull->assertDrawMapsEmpty();
+
+ rebuildPriorityGroups();
+ llpushcallstacks ;
+
+ const S32 bin_count = 1024*8;
+
+ static LLCullResult::drawinfo_list_t alpha_bins[bin_count];
+ static U32 bin_size[bin_count];
+
+ //clear one bin per frame to avoid memory bloat
+ static S32 clear_idx = 0;
+ clear_idx = (1+clear_idx)%bin_count;
+ alpha_bins[clear_idx].clear();
+
+ for (U32 j = 0; j < bin_count; j++)
+ {
+ bin_size[j] = 0;
+ }
+
+ //build render map
+ for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
+ {
+ LLSpatialGroup* group = *i;
+ if (sUseOcclusion &&
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+ {
+ continue;
+ }
+
+ if (group->isState(LLSpatialGroup::NEW_DRAWINFO) && group->isState(LLSpatialGroup::GEOM_DIRTY))
+ { //no way this group is going to be drawable without a rebuild
+ group->rebuildGeom();
+ }
+
+ for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
+ {
+ LLSpatialGroup::drawmap_elem_t& src_vec = j->second;
+ if (!hasRenderType(j->first))
+ {
+ continue;
+ }
+
+ for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
+ {
+ if (sMinRenderSize > 0.f)
+ {
+ LLVector4a bounds;
+ bounds.setSub((*k)->mExtents[1],(*k)->mExtents[0]);
+
+ if (llmax(llmax(bounds[0], bounds[1]), bounds[2]) > sMinRenderSize)
+ {
+ sCull->pushDrawInfo(j->first, *k);
+ }
+ }
+ else
+ {
+ sCull->pushDrawInfo(j->first, *k);
+ }
+ }
+ }
+
+ if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA))
+ {
+ LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
+
+ if (alpha != group->mDrawMap.end())
+ { //store alpha groups for sorting
+ LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ {
+ if (bridge)
+ {
+ LLCamera trans_camera = bridge->transformCamera(camera);
+ group->updateDistance(trans_camera);
+ }
+ else
+ {
+ group->updateDistance(camera);
+ }
+ }
+
+ if (hasRenderType(LLDrawPool::POOL_ALPHA))
+ {
+ sCull->pushAlphaGroup(group);
+ }
+ }
+ }
+ }
+
+ if (!sShadowRender)
+ {
+ std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());
+ }
+ llpushcallstacks ;
+ // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus
+ if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender)
+ {
+ if (sRenderScriptedTouchBeacons)
+ {
+ // Only show the beacon on the root object.
+ forAllVisibleDrawables(renderScriptedTouchBeacons);
+ }
+ else
+ if (sRenderScriptedBeacons)
+ {
+ // Only show the beacon on the root object.
+ forAllVisibleDrawables(renderScriptedBeacons);
+ }
+
+ if (sRenderPhysicalBeacons)
+ {
+ // Only show the beacon on the root object.
+ forAllVisibleDrawables(renderPhysicalBeacons);
+ }
+
+ if(sRenderMOAPBeacons)
+ {
+ forAllVisibleDrawables(renderMOAPBeacons);
+ }
+
+ if (sRenderParticleBeacons)
+ {
+ forAllVisibleDrawables(renderParticleBeacons);
+ }
+
+ // If god mode, also show audio cues
+ if (sRenderSoundBeacons && gAudiop)
+ {
+ // Walk all sound sources and render out beacons for them. Note, this isn't done in the ForAllVisibleDrawables function, because some are not visible.
+ LLAudioEngine::source_map::iterator iter;
+ for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
+ {
+ LLAudioSource *sourcep = iter->second;
+
+ LLVector3d pos_global = sourcep->getPositionGlobal();
+ LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global);
+ if (gPipeline.sRenderBeacons)
+ {
+ //pos += LLVector3(0.f, 0.f, 0.2f);
+ gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), DebugBeaconLineWidth);
+ }
+ }
+ // now deal with highlights for all those seeable sound sources
+ forAllVisibleDrawables(renderSoundHighlights);
+ }
+ }
+ llpushcallstacks ;
+ // If managing your telehub, draw beacons at telehub and currently selected spawnpoint.
+ if (LLFloaterTelehub::renderBeacons())
+ {
+ LLFloaterTelehub::addBeacons();
+ }
+
+ if (!sShadowRender)
+ {
+ mSelectedFaces.clear();
+
+ // Draw face highlights for selected faces.
+ if (LLSelectMgr::getInstance()->getTEMode())
+ {
+ struct f : public LLSelectedTEFunctor
+ {
+ virtual bool apply(LLViewerObject* object, S32 te)
+ {
+ if (object->mDrawable)
+ {
+ gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te));
+ }
+ return true;
+ }
+ } func;
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
+ }
+ }
+
+ //LLSpatialGroup::sNoDelete = FALSE;
+ llpushcallstacks ;
+}
+
+
+void render_hud_elements()
+{
+ LLMemType mt_rhe(LLMemType::MTYPE_PIPELINE_RENDER_HUD_ELS);
+ LLFastTimer t(FTM_RENDER_UI);
+ gPipeline.disableLights();
+
+ LLGLDisable fog(GL_FOG);
+ LLGLSUIDefault gls_ui;
+
+ LLGLEnable stencil(GL_STENCIL_TEST);
+ glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF);
+ glStencilMask(0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
+ gGL.color4f(1,1,1,1);
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gUIProgram.bind();
+ }
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+
+ if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ LLGLEnable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+ gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d()
+
+ // Draw the tracking overlays
+ LLTracker::render3D();
+
+ // Show the property lines
+ LLWorld::getInstance()->renderPropertyLines();
+ LLViewerParcelMgr::getInstance()->render();
+ LLViewerParcelMgr::getInstance()->renderParcelCollision();
+
+ // Render name tags.
+ LLHUDObject::renderAll();
+ }
+ else if (gForceRenderLandFence)
+ {
+ // This is only set when not rendering the UI, for parcel snapshots
+ LLViewerParcelMgr::getInstance()->render();
+ }
+ else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ {
+ LLHUDText::renderAllHUD();
+ }
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gUIProgram.unbind();
+ }
+ gGL.flush();
+}
+
+void LLPipeline::renderHighlights()
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_HL);
+
+ assertInitialized();
+
+ // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD)
+ // Render highlighted faces.
+ LLGLSPipelineAlpha gls_pipeline_alpha;
+ LLColor4 color(1.f, 1.f, 1.f, 0.5f);
+ LLGLEnable color_mat(GL_COLOR_MATERIAL);
+ disableLights();
+
+ if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && !mHighlightSet.empty())
+ { //draw blurry highlight image over screen
+ LLGLEnable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ LLGLDisable test(GL_ALPHA_TEST);
+
+ LLGLEnable stencil(GL_STENCIL_TEST);
+ gGL.flush();
+ glStencilMask(0xFFFFFFFF);
+ glClearStencil(1);
+ glClear(GL_STENCIL_BUFFER_BIT);
+
+ glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+
+ gGL.setColorMask(false, false);
+ for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ++iter)
+ {
+ renderHighlight(iter->mItem->getVObj(), 1.f);
+ }
+ gGL.setColorMask(true, false);
+
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
+
+ //gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+
+ gGL.getTexUnit(0)->bind(&mHighlight);
+
+ LLVector2 tc1;
+ LLVector2 tc2;
+
+ tc1.setVec(0,0);
+ tc2.setVec(2,2);
+
+ gGL.begin(LLRender::TRIANGLES);
+
+ F32 scale = RenderHighlightBrightness;
+ LLColor4 color = RenderHighlightColor;
+ F32 thickness = RenderHighlightThickness;
+
+ for (S32 pass = 0; pass < 2; ++pass)
+ {
+ if (pass == 0)
+ {
+ gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+ }
+ else
+ {
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ }
+
+ for (S32 i = 0; i < 8; ++i)
+ {
+ for (S32 j = 0; j < 8; ++j)
+ {
+ LLVector2 tc(i-4+0.5f, j-4+0.5f);
+
+ F32 dist = 1.f-(tc.length()/sqrtf(32.f));
+ dist *= scale/64.f;
+
+ tc *= thickness;
+ tc.mV[0] = (tc.mV[0])/mHighlight.getWidth();
+ tc.mV[1] = (tc.mV[1])/mHighlight.getHeight();
+
+ gGL.color4f(color.mV[0],
+ color.mV[1],
+ color.mV[2],
+ color.mV[3]*dist);
+
+ gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc2.mV[1]);
+ gGL.vertex2f(-1,3);
+
+ gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc1.mV[1]);
+ gGL.vertex2f(-1,-1);
+
+ gGL.texCoord2f(tc.mV[0]+tc2.mV[0], tc.mV[1]+tc1.mV[1]);
+ gGL.vertex2f(3,-1);
+ }
+ }
+ }
+
+ gGL.end();
+
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+
+ //gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ }
+
+ if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+ {
+ gHighlightProgram.bind();
+ gGL.diffuseColor4f(1,1,1,0.5f);
+ }
+
+ if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
+ {
+ // Make sure the selection image gets downloaded and decoded
+ if (!mFaceSelectImagep)
+ {
+ mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT);
+ }
+ mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA);
+
+ U32 count = mSelectedFaces.size();
+ for (U32 i = 0; i < count; i++)
+ {
+ LLFace *facep = mSelectedFaces[i];
+ if (!facep || facep->getDrawable()->isDead())
+ {
+ llerrs << "Bad face on selection" << llendl;
+ return;
+ }
+
+ facep->renderSelected(mFaceSelectImagep, color);
+ }
+ }
+
+ if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
+ {
+ // Paint 'em red!
+ color.setVec(1.f, 0.f, 0.f, 0.5f);
+
+ int count = mHighlightFaces.size();
+ for (S32 i = 0; i < count; i++)
+ {
+ LLFace* facep = mHighlightFaces[i];
+ facep->renderSelected(LLViewerTexture::sNullImagep, color);
+ }
+ }
+
+ // Contains a list of the faces of objects that are physical or
+ // have touch-handlers.
+ mHighlightFaces.clear();
+
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)
+ {
+ gHighlightProgram.unbind();
+ }
+}
+
+//debug use
+U32 LLPipeline::sCurRenderPoolType = 0 ;
+
+void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_GEOM);
+ LLFastTimer t(FTM_RENDER_GEOMETRY);
+
+ assertInitialized();
+
+ F32 saved_modelview[16];
+ F32 saved_projection[16];
+
+ //HACK: preserve/restore matrices around HUD render
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ {
+ for (U32 i = 0; i < 16; i++)
+ {
+ saved_modelview[i] = gGLModelView[i];
+ saved_projection[i] = gGLProjection[i];
+ }
+ }
+
+ ///////////////////////////////////////////
+ //
+ // Sync and verify GL state
+ //
+ //
+
+ stop_glerror();
+
+ LLVertexBuffer::unbind();
+
+ // Do verification of GL state
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+ if (mRenderDebugMask & RENDER_DEBUG_VERIFY)
+ {
+ if (!verify())
+ {
+ llerrs << "Pipeline verification failed!" << llendl;
+ }
+ }
+
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO");
+
+ // Initialize lots of GL state to "safe" values
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.matrixMode(LLRender::MM_TEXTURE);
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+
+ LLGLSPipeline gls_pipeline;
+ LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
+ LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2);
+
+ // Toggle backface culling for debugging
+ LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0);
+ // Set fog
+ BOOL use_fog = hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG);
+ LLGLEnable fog_enable(use_fog &&
+ !gPipeline.canUseWindLightShadersOnObjects() ? GL_FOG : 0);
+ gSky.updateFog(camera.getFar());
+ if (!use_fog)
+ {
+ sUnderWaterRender = FALSE;
+ }
+
+ gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sDefaultImagep);
+ LLViewerFetchedTexture::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP);
+
+
+ //////////////////////////////////////////////
+ //
+ // Actually render all of the geometry
+ //
+ //
+ stop_glerror();
+
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools");
+
+ for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+ {
+ LLDrawPool *poolp = *iter;
+ if (hasRenderType(poolp->getType()))
+ {
+ poolp->prerender();
+ }
+ }
+
+ {
+ LLFastTimer t(FTM_POOLS);
+
+ // HACK: don't calculate local lights if we're rendering the HUD!
+ // Removing this check will cause bad flickering when there are
+ // HUD elements being rendered AND the user is in flycam mode -nyx
+ if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ {
+ calcNearbyLights(camera);
+ setupHWLights(NULL);
+ }
+
+ BOOL occlude = sUseOcclusion > 1;
+ U32 cur_type = 0;
+
+ pool_set_t::iterator iter1 = mPools.begin();
+ while ( iter1 != mPools.end() )
+ {
+ LLDrawPool *poolp = *iter1;
+
+ cur_type = poolp->getType();
+
+ //debug use
+ sCurRenderPoolType = cur_type ;
+
+ if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
+ {
+ occlude = FALSE;
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+ LLGLSLShader::bindNoShader();
+ doOcclusion(camera);
+ }
+
+ pool_set_t::iterator iter2 = iter1;
+ if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0)
+ {
+ LLFastTimer t(FTM_POOLRENDER);
+
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+
+ for( S32 i = 0; i < poolp->getNumPasses(); i++ )
+ {
+ LLVertexBuffer::unbind();
+ poolp->beginRenderPass(i);
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+
+ p->render(i);
+ }
+ poolp->endRenderPass(i);
+ LLVertexBuffer::unbind();
+ if (gDebugGL)
+ {
+ std::string msg = llformat("pass %d", i);
+ LLGLState::checkStates(msg);
+ //LLGLState::checkTextureChannels(msg);
+ //LLGLState::checkClientArrays(msg);
+ }
+ }
+ }
+ else
+ {
+ // Skip all pools of this type
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+ }
+ }
+ iter1 = iter2;
+ stop_glerror();
+ }
+
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPoolsEnd");
+
+ LLVertexBuffer::unbind();
+
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+
+ if (occlude)
+ {
+ occlude = FALSE;
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+ LLGLSLShader::bindNoShader();
+ doOcclusion(camera);
+ }
+ }
+
+ LLVertexBuffer::unbind();
+ LLGLState::checkStates();
+
+ if (!LLPipeline::sImpostorRender)
+ {
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights");
+
+ if (!sReflectionRender)
+ {
+ renderHighlights();
+ }
+
+ // Contains a list of the faces of objects that are physical or
+ // have touch-handlers.
+ mHighlightFaces.clear();
+
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDebug");
+
+ renderDebug();
+
+ LLVertexBuffer::unbind();
+
+ if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred)
+ {
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ // Render debugging beacons.
+ gObjectList.renderObjectBeacons();
+ gObjectList.resetObjectBeacons();
+ }
+ else
+ {
+ // Make sure particle effects disappear
+ LLHUDObject::renderAllForTimer();
+ }
+ }
+ else
+ {
+ // Make sure particle effects disappear
+ LLHUDObject::renderAllForTimer();
+ }
+
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd");
+
+ //HACK: preserve/restore matrices around HUD render
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ {
+ for (U32 i = 0; i < 16; i++)
+ {
+ gGLModelView[i] = saved_modelview[i];
+ gGLProjection[i] = saved_projection[i];
+ }
+ }
+ }
+
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+// LLGLState::checkTextureChannels();
+// LLGLState::checkClientArrays();
+}
+
+void LLPipeline::renderGeomDeferred(LLCamera& camera)
+{
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred");
+
+ LLMemType mt_rgd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED);
+ LLFastTimer t(FTM_RENDER_GEOMETRY);
+
+ LLFastTimer t2(FTM_POOLS);
+
+ LLGLEnable cull(GL_CULL_FACE);
+
+ LLGLEnable stencil(GL_STENCIL_TEST);
+ glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
+ stop_glerror();
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ stop_glerror();
+
+ for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+ {
+ LLDrawPool *poolp = *iter;
+ if (hasRenderType(poolp->getType()))
+ {
+ poolp->prerender();
+ }
+ }
+
+ LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ U32 cur_type = 0;
+
+ gGL.setColorMask(true, true);
+
+ pool_set_t::iterator iter1 = mPools.begin();
+
+ while ( iter1 != mPools.end() )
+ {
+ LLDrawPool *poolp = *iter1;
+
+ cur_type = poolp->getType();
+
+ pool_set_t::iterator iter2 = iter1;
+ if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0)
+ {
+ LLFastTimer t(FTM_POOLRENDER);
+
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+
+ for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ )
+ {
+ LLVertexBuffer::unbind();
+ poolp->beginDeferredPass(i);
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+
+ p->renderDeferred(i);
+ }
+ poolp->endDeferredPass(i);
+ LLVertexBuffer::unbind();
+
+ if (gDebugGL || gDebugPipeline)
+ {
+ LLGLState::checkStates();
+ }
+ }
+ }
+ else
+ {
+ // Skip all pools of this type
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+ }
+ }
+ iter1 = iter2;
+ stop_glerror();
+ }
+
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+
+ gGL.setColorMask(true, false);
+}
+
+void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
+{
+ LLMemType mt_rgpd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF);
+ LLFastTimer t(FTM_POOLS);
+ U32 cur_type = 0;
+
+ LLGLEnable cull(GL_CULL_FACE);
+
+ LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
+ calcNearbyLights(camera);
+ setupHWLights(NULL);
+
+ gGL.setColorMask(true, false);
+
+ pool_set_t::iterator iter1 = mPools.begin();
+ BOOL occlude = LLPipeline::sUseOcclusion > 1;
+
+ while ( iter1 != mPools.end() )
+ {
+ LLDrawPool *poolp = *iter1;
+
+ cur_type = poolp->getType();
+
+ if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
+ {
+ occlude = FALSE;
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+ LLGLSLShader::bindNoShader();
+ doOcclusion(camera);
+ gGL.setColorMask(true, false);
+ }
+
+ pool_set_t::iterator iter2 = iter1;
+ if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0)
+ {
+ LLFastTimer t(FTM_POOLRENDER);
+
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+
+ for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ )
+ {
+ LLVertexBuffer::unbind();
+ poolp->beginPostDeferredPass(i);
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+
+ p->renderPostDeferred(i);
+ }
+ poolp->endPostDeferredPass(i);
+ LLVertexBuffer::unbind();
+
+ if (gDebugGL || gDebugPipeline)
+ {
+ LLGLState::checkStates();
+ }
+ }
+ }
+ else
+ {
+ // Skip all pools of this type
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+ }
+ }
+ iter1 = iter2;
+ stop_glerror();
+ }
+
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+
+ if (occlude)
+ {
+ occlude = FALSE;
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+ LLGLSLShader::bindNoShader();
+ doOcclusion(camera);
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+ }
+}
+
+void LLPipeline::renderGeomShadow(LLCamera& camera)
+{
+ LLMemType mt_rgs(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_SHADOW);
+ U32 cur_type = 0;
+
+ LLGLEnable cull(GL_CULL_FACE);
+
+ LLVertexBuffer::unbind();
+
+ pool_set_t::iterator iter1 = mPools.begin();
+
+ while ( iter1 != mPools.end() )
+ {
+ LLDrawPool *poolp = *iter1;
+
+ cur_type = poolp->getType();
+
+ pool_set_t::iterator iter2 = iter1;
+ if (hasRenderType(poolp->getType()) && poolp->getNumShadowPasses() > 0)
+ {
+ poolp->prerender() ;
+
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+
+ for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ )
+ {
+ LLVertexBuffer::unbind();
+ poolp->beginShadowPass(i);
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+
+ p->renderShadow(i);
+ }
+ poolp->endShadowPass(i);
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+ }
+ }
+ else
+ {
+ // Skip all pools of this type
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+ }
+ }
+ iter1 = iter2;
+ stop_glerror();
+ }
+
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+}
+
+
+void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type)
+{
+ assertInitialized();
+ S32 count = 0;
+ if (render_type == LLRender::TRIANGLE_STRIP)
+ {
+ count = index_count-2;
+ }
+ else
+ {
+ count = index_count/3;
+ }
+
+ mTrianglesDrawn += count;
+ mBatchCount++;
+ mMaxBatchSize = llmax(mMaxBatchSize, count);
+ mMinBatchSize = llmin(mMinBatchSize, count);
+
+ if (LLPipeline::sRenderFrameTest)
+ {
+ gViewerWindow->getWindow()->swapBuffers();
+ ms_sleep(16);
+ }
+}
+
+void LLPipeline::renderPhysicsDisplay()
+{
+ if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
+ {
+ return;
+ }
+
+ allocatePhysicsBuffer();
+
+ gGL.flush();
+ mPhysicsDisplay.bindTarget();
+ glClearColor(0,0,0,1);
+ gGL.setColorMask(true, true);
+ mPhysicsDisplay.clear();
+ glClearColor(0,0,0,0);
+
+ gGL.setColorMask(true, false);
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gDebugProgram.bind();
+ }
+
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+ for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(i);
+ if (part)
+ {
+ if (hasRenderType(part->mDrawableType))
+ {
+ part->renderPhysicsShapes();
+ }
+ }
+ }
+ }
+
+ for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
+ {
+ LLSpatialBridge* bridge = *i;
+ if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
+ {
+ gGL.pushMatrix();
+ gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
+ bridge->renderPhysicsShapes();
+ gGL.popMatrix();
+ }
+ }
+
+ gGL.flush();
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gDebugProgram.unbind();
+ }
+
+ mPhysicsDisplay.flush();
+}
+
+
+void LLPipeline::renderDebug()
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+
+ assertInitialized();
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gUIProgram.bind();
+ }
+
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gPipeline.disableLights();
//Render any navmesh geometry
LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance();
@@ -4386,5490 +4372,5500 @@ void LLPipeline::renderDebug()
}
}
}
- gGL.flush();
- if (LLGLSLShader::sNoFixedFunction)
- {
- gUIProgram.unbind();
- }
-
- gGL.color4f(1,1,1,1);
-
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
- gGL.setColorMask(true, false);
-
- bool hud_only = hasRenderType(LLPipeline::RENDER_TYPE_HUD);
-
-
- if (!hud_only && !mDebugBlips.empty())
- { //render debug blips
- if (LLGLSLShader::sNoFixedFunction)
- {
- gUIProgram.bind();
- }
-
- gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep, true);
-
- glPointSize(8.f);
- LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
-
- gGL.begin(LLRender::POINTS);
- for (std::list<DebugBlip>::iterator iter = mDebugBlips.begin(); iter != mDebugBlips.end(); )
- {
- DebugBlip& blip = *iter;
-
- blip.mAge += gFrameIntervalSeconds;
- if (blip.mAge > 2.f)
- {
- mDebugBlips.erase(iter++);
- }
- else
- {
- iter++;
- }
-
- blip.mPosition.mV[2] += gFrameIntervalSeconds*2.f;
-
- gGL.color4fv(blip.mColor.mV);
- gGL.vertex3fv(blip.mPosition.mV);
- }
- gGL.end();
- gGL.flush();
- glPointSize(1.f);
- }
-
-
- // Debug stuff.
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- if ( hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES) ||
- !hud_only && hasRenderType(part->mDrawableType) )
- {
- part->renderDebug();
- }
- }
- }
- }
-
- for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
- {
- LLSpatialBridge* bridge = *i;
- if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
- {
- gGL.pushMatrix();
- gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
- bridge->renderDebug();
- gGL.popMatrix();
- }
- }
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gUIProgram.bind();
- }
-
- if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
- {
- LLVertexBuffer::unbind();
-
- LLGLEnable blend(GL_BLEND);
- LLGLDepthTest depth(TRUE, FALSE);
- LLGLDisable cull(GL_CULL_FACE);
-
- gGL.color4f(1,1,1,1);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- F32 a = 0.1f;
-
- F32 col[] =
- {
- 1,0,0,a,
- 0,1,0,a,
- 0,0,1,a,
- 1,0,1,a,
-
- 1,1,0,a,
- 0,1,1,a,
- 1,1,1,a,
- 1,0,1,a,
- };
-
- for (U32 i = 0; i < 8; i++)
- {
- LLVector3* frust = mShadowCamera[i].mAgentFrustum;
-
- if (i > 3)
- { //render shadow frusta as volumes
- if (mShadowFrustPoints[i-4].empty())
- {
- continue;
- }
-
- gGL.color4fv(col+(i-4)*4);
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
- gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
- gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
- gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
- gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
- gGL.end();
-
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.vertex3fv(frust[0].mV);
- gGL.vertex3fv(frust[1].mV);
- gGL.vertex3fv(frust[3].mV);
- gGL.vertex3fv(frust[2].mV);
- gGL.end();
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.vertex3fv(frust[4].mV);
- gGL.vertex3fv(frust[5].mV);
- gGL.vertex3fv(frust[7].mV);
- gGL.vertex3fv(frust[6].mV);
- gGL.end();
- }
-
-
- if (i < 4)
- {
-
- //if (i == 0 || !mShadowFrustPoints[i].empty())
- {
- //render visible point cloud
- gGL.flush();
- glPointSize(8.f);
- gGL.begin(LLRender::POINTS);
-
- F32* c = col+i*4;
- gGL.color3fv(c);
-
- for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j)
- {
- gGL.vertex3fv(mShadowFrustPoints[i][j].mV);
-
- }
- gGL.end();
-
- gGL.flush();
- glPointSize(1.f);
-
- LLVector3* ext = mShadowExtents[i];
- LLVector3 pos = (ext[0]+ext[1])*0.5f;
- LLVector3 size = (ext[1]-ext[0])*0.5f;
- drawBoxOutline(pos, size);
-
- //render camera frustum splits as outlines
- gGL.begin(LLRender::LINES);
- gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV);
- gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV);
- gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV);
- gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV);
- gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV);
- gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV);
- gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV);
- gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV);
- gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
- gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
- gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
- gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
- gGL.end();
- }
- }
-
- /*gGL.flush();
- glLineWidth(16-i*2);
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
- for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(j);
- if (part)
- {
- if (hasRenderType(part->mDrawableType))
- {
- part->renderIntersectingBBoxes(&mShadowCamera[i]);
- }
- }
- }
- }
- gGL.flush();
- glLineWidth(1.f);*/
- }
- }
-
- if (mRenderDebugMask & RENDER_DEBUG_WIND_VECTORS)
- {
- gAgent.getRegion()->mWind.renderVectors();
- }
-
- if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION)
- {
- // Debug composition layers
- F32 x, y;
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- if (gAgent.getRegion())
- {
- gGL.begin(LLRender::POINTS);
- // Draw the composition layer for the region that I'm in.
- for (x = 0; x <= 260; x++)
- {
- for (y = 0; y <= 260; y++)
- {
- if ((x > 255) || (y > 255))
- {
- gGL.color4f(1.f, 0.f, 0.f, 1.f);
- }
- else
- {
- gGL.color4f(0.f, 0.f, 1.f, 1.f);
- }
- F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y);
- z *= 5.f;
- z += 50.f;
- gGL.vertex3f(x, y, z);
- }
- }
- gGL.end();
- }
- }
-
- if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_BUILD_QUEUE)
- {
- U32 count = 0;
- U32 size = mGroupQ2.size();
- LLColor4 col;
-
- LLVertexBuffer::unbind();
- LLGLEnable blend(GL_BLEND);
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE);
- gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
-
- gGL.pushMatrix();
- gGL.loadMatrix(gGLModelView);
- gGLLastMatrix = NULL;
-
- for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); iter != mGroupQ2.end(); ++iter)
- {
- LLSpatialGroup* group = *iter;
- if (group->isDead())
- {
- continue;
- }
-
- LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
-
- if (bridge && (!bridge->mDrawable || bridge->mDrawable->isDead()))
- {
- continue;
- }
-
- if (bridge)
- {
- gGL.pushMatrix();
- gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
- }
-
- F32 alpha = llclamp((F32) (size-count)/size, 0.f, 1.f);
-
-
- LLVector2 c(1.f-alpha, alpha);
- c.normVec();
-
-
- ++count;
- col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.5f);
- group->drawObjectBox(col);
-
- if (bridge)
- {
- gGL.popMatrix();
- }
- }
-
- gGL.popMatrix();
- }
-
- gGL.flush();
- if (LLGLSLShader::sNoFixedFunction)
- {
- gUIProgram.unbind();
- }
-}
-
-void LLPipeline::rebuildPools()
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_REBUILD_POOLS);
-
- assertInitialized();
-
- S32 max_count = mPools.size();
- pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool);
- while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS)
- {
- if (iter1 == mPools.end())
- {
- iter1 = mPools.begin();
- }
- LLDrawPool* poolp = *iter1;
-
- if (poolp->isDead())
- {
- mPools.erase(iter1++);
- removeFromQuickLookup( poolp );
- if (poolp == mLastRebuildPool)
- {
- mLastRebuildPool = NULL;
- }
- delete poolp;
- }
- else
- {
- mLastRebuildPool = poolp;
- iter1++;
- }
- max_count--;
- }
-
- if (isAgentAvatarValid())
- {
- gAgentAvatarp->rebuildHUD();
- }
-}
-
-void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
-{
- LLMemType mt(LLMemType::MTYPE_PIPELINE_QUICK_LOOKUP);
-
- assertInitialized();
-
- switch( new_poolp->getType() )
- {
- case LLDrawPool::POOL_SIMPLE:
- if (mSimplePool)
- {
- llassert(0);
- llwarns << "Ignoring duplicate simple pool." << llendl;
- }
- else
- {
- mSimplePool = (LLRenderPass*) new_poolp;
- }
- break;
-
- case LLDrawPool::POOL_GRASS:
- if (mGrassPool)
- {
- llassert(0);
- llwarns << "Ignoring duplicate grass pool." << llendl;
- }
- else
- {
- mGrassPool = (LLRenderPass*) new_poolp;
- }
- break;
-
- case LLDrawPool::POOL_FULLBRIGHT:
- if (mFullbrightPool)
- {
- llassert(0);
- llwarns << "Ignoring duplicate simple pool." << llendl;
- }
- else
- {
- mFullbrightPool = (LLRenderPass*) new_poolp;
- }
- break;
-
- case LLDrawPool::POOL_INVISIBLE:
- if (mInvisiblePool)
- {
- llassert(0);
- llwarns << "Ignoring duplicate simple pool." << llendl;
- }
- else
- {
- mInvisiblePool = (LLRenderPass*) new_poolp;
- }
- break;
-
- case LLDrawPool::POOL_GLOW:
- if (mGlowPool)
- {
- llassert(0);
- llwarns << "Ignoring duplicate glow pool." << llendl;
- }
- else
- {
- mGlowPool = (LLRenderPass*) new_poolp;
- }
- break;
-
- case LLDrawPool::POOL_TREE:
- mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
- break;
-
- case LLDrawPool::POOL_TERRAIN:
- mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
- break;
-
- case LLDrawPool::POOL_BUMP:
- if (mBumpPool)
- {
- llassert(0);
- llwarns << "Ignoring duplicate bump pool." << llendl;
- }
- else
- {
- mBumpPool = new_poolp;
- }
- break;
-
- case LLDrawPool::POOL_ALPHA:
- if( mAlphaPool )
- {
- llassert(0);
- llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl;
- }
- else
- {
- mAlphaPool = new_poolp;
- }
- break;
-
- case LLDrawPool::POOL_AVATAR:
- break; // Do nothing
-
- case LLDrawPool::POOL_SKY:
- if( mSkyPool )
- {
- llassert(0);
- llwarns << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << llendl;
- }
- else
- {
- mSkyPool = new_poolp;
- }
- break;
-
- case LLDrawPool::POOL_WATER:
- if( mWaterPool )
- {
- llassert(0);
- llwarns << "LLPipeline::addPool(): Ignoring duplicate Water pool" << llendl;
- }
- else
- {
- mWaterPool = new_poolp;
- }
- break;
-
- case LLDrawPool::POOL_GROUND:
- if( mGroundPool )
- {
- llassert(0);
- llwarns << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << llendl;
- }
- else
- {
- mGroundPool = new_poolp;
- }
- break;
-
- case LLDrawPool::POOL_WL_SKY:
- if( mWLSkyPool )
- {
- llassert(0);
- llwarns << "LLPipeline::addPool(): Ignoring duplicate WLSky Pool" << llendl;
- }
- else
- {
- mWLSkyPool = new_poolp;
- }
- break;
-
- default:
- llassert(0);
- llwarns << "Invalid Pool Type in LLPipeline::addPool()" << llendl;
- break;
- }
-}
-
-void LLPipeline::removePool( LLDrawPool* poolp )
-{
- assertInitialized();
- removeFromQuickLookup(poolp);
- mPools.erase(poolp);
- delete poolp;
-}
-
-void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
-{
- assertInitialized();
- LLMemType mt(LLMemType::MTYPE_PIPELINE);
- switch( poolp->getType() )
- {
- case LLDrawPool::POOL_SIMPLE:
- llassert(mSimplePool == poolp);
- mSimplePool = NULL;
- break;
-
- case LLDrawPool::POOL_GRASS:
- llassert(mGrassPool == poolp);
- mGrassPool = NULL;
- break;
-
- case LLDrawPool::POOL_FULLBRIGHT:
- llassert(mFullbrightPool == poolp);
- mFullbrightPool = NULL;
- break;
-
- case LLDrawPool::POOL_INVISIBLE:
- llassert(mInvisiblePool == poolp);
- mInvisiblePool = NULL;
- break;
-
- case LLDrawPool::POOL_WL_SKY:
- llassert(mWLSkyPool == poolp);
- mWLSkyPool = NULL;
- break;
-
- case LLDrawPool::POOL_GLOW:
- llassert(mGlowPool == poolp);
- mGlowPool = NULL;
- break;
-
- case LLDrawPool::POOL_TREE:
- #ifdef _DEBUG
- {
- BOOL found = mTreePools.erase( (uintptr_t)poolp->getTexture() );
- llassert( found );
- }
- #else
- mTreePools.erase( (uintptr_t)poolp->getTexture() );
- #endif
- break;
-
- case LLDrawPool::POOL_TERRAIN:
- #ifdef _DEBUG
- {
- BOOL found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
- llassert( found );
- }
- #else
- mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
- #endif
- break;
-
- case LLDrawPool::POOL_BUMP:
- llassert( poolp == mBumpPool );
- mBumpPool = NULL;
- break;
-
- case LLDrawPool::POOL_ALPHA:
- llassert( poolp == mAlphaPool );
- mAlphaPool = NULL;
- break;
-
- case LLDrawPool::POOL_AVATAR:
- break; // Do nothing
-
- case LLDrawPool::POOL_SKY:
- llassert( poolp == mSkyPool );
- mSkyPool = NULL;
- break;
-
- case LLDrawPool::POOL_WATER:
- llassert( poolp == mWaterPool );
- mWaterPool = NULL;
- break;
-
- case LLDrawPool::POOL_GROUND:
- llassert( poolp == mGroundPool );
- mGroundPool = NULL;
- break;
-
- default:
- llassert(0);
- llwarns << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl;
- break;
- }
-}
-
-void LLPipeline::resetDrawOrders()
-{
- assertInitialized();
- // Iterate through all of the draw pools and rebuild them.
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- poolp->resetDrawOrders();
- }
-}
-
-//============================================================================
-// Once-per-frame setup of hardware lights,
-// including sun/moon, avatar backlight, and up to 6 local lights
-
-void LLPipeline::setupAvatarLights(BOOL for_edit)
-{
- assertInitialized();
-
- if (for_edit)
- {
- LLColor4 diffuse(1.f, 1.f, 1.f, 0.f);
- LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f); // w==0 => directional light
- LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview();
- LLMatrix4 camera_rot(camera_mat.getMat3());
- camera_rot.invert();
- LLVector4 light_pos = light_pos_cam * camera_rot;
-
- light_pos.normalize();
-
- LLLightState* light = gGL.getLight(1);
-
- mHWLightColors[1] = diffuse;
-
- light->setDiffuse(diffuse);
- light->setAmbient(LLColor4::black);
- light->setSpecular(LLColor4::black);
- light->setPosition(light_pos);
- light->setConstantAttenuation(1.f);
- light->setLinearAttenuation(0.f);
- light->setQuadraticAttenuation(0.f);
- light->setSpotExponent(0.f);
- light->setSpotCutoff(180.f);
- }
- else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini)
- {
- LLVector3 opposite_pos = -1.f * mSunDir;
- LLVector3 orthog_light_pos = mSunDir % LLVector3::z_axis;
- LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f);
- backlight_pos.normalize();
-
- LLColor4 light_diffuse = mSunDiffuse;
- LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f);
- F32 max_component = 0.001f;
- for (S32 i = 0; i < 3; i++)
- {
- if (backlight_diffuse.mV[i] > max_component)
- {
- max_component = backlight_diffuse.mV[i];
- }
- }
- F32 backlight_mag;
- if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
- {
- backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT;
- }
- else
- {
- backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT;
- }
- backlight_diffuse *= backlight_mag / max_component;
-
- mHWLightColors[1] = backlight_diffuse;
-
- LLLightState* light = gGL.getLight(1);
-
- light->setPosition(backlight_pos);
- light->setDiffuse(backlight_diffuse);
- light->setAmbient(LLColor4::black);
- light->setSpecular(LLColor4::black);
- light->setConstantAttenuation(1.f);
- light->setLinearAttenuation(0.f);
- light->setQuadraticAttenuation(0.f);
- light->setSpotExponent(0.f);
- light->setSpotCutoff(180.f);
- }
- else
- {
- LLLightState* light = gGL.getLight(1);
-
- mHWLightColors[1] = LLColor4::black;
-
- light->setDiffuse(LLColor4::black);
- light->setAmbient(LLColor4::black);
- light->setSpecular(LLColor4::black);
- }
-}
-
-static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist)
-{
- F32 inten = light->getLightIntensity();
- if (inten < .001f)
- {
- return max_dist;
- }
- F32 radius = light->getLightRadius();
- BOOL selected = light->isSelected();
- LLVector3 dpos = light->getRenderPosition() - cam_pos;
- F32 dist2 = dpos.lengthSquared();
- if (!selected && dist2 > (max_dist + radius)*(max_dist + radius))
- {
- return max_dist;
- }
- F32 dist = (F32) sqrt(dist2);
- dist *= 1.f / inten;
- dist -= radius;
- if (selected)
- {
- dist -= 10000.f; // selected lights get highest priority
- }
- if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE))
- {
- // moving lights get a little higher priority (too much causes artifacts)
- dist -= light->getLightRadius()*0.25f;
- }
- return dist;
-}
-
-void LLPipeline::calcNearbyLights(LLCamera& camera)
-{
- assertInitialized();
-
- if (LLPipeline::sReflectionRender)
- {
- return;
- }
-
- if (mLightingDetail >= 1)
- {
- // mNearbyLight (and all light_set_t's) are sorted such that
- // begin() == the closest light and rbegin() == the farthest light
- const S32 MAX_LOCAL_LIGHTS = 6;
-// LLVector3 cam_pos = gAgent.getCameraPositionAgent();
- LLVector3 cam_pos = LLViewerJoystick::getInstance()->getOverrideCamera() ?
- camera.getOrigin() :
- gAgent.getPositionAgent();
-
- F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad
-
- // UPDATE THE EXISTING NEARBY LIGHTS
- light_set_t cur_nearby_lights;
- for (light_set_t::iterator iter = mNearbyLights.begin();
- iter != mNearbyLights.end(); iter++)
- {
- const Light* light = &(*iter);
- LLDrawable* drawable = light->drawable;
- LLVOVolume* volight = drawable->getVOVolume();
- if (!volight || !drawable->isState(LLDrawable::LIGHT))
- {
- drawable->clearState(LLDrawable::NEARBY_LIGHT);
- continue;
- }
- if (light->fade <= -LIGHT_FADE_TIME)
- {
- drawable->clearState(LLDrawable::NEARBY_LIGHT);
- continue;
- }
- if (!sRenderAttachedLights && volight && volight->isAttachment())
- {
- drawable->clearState(LLDrawable::NEARBY_LIGHT);
- continue;
- }
-
- F32 dist = calc_light_dist(volight, cam_pos, max_dist);
- cur_nearby_lights.insert(Light(drawable, dist, light->fade));
- }
- mNearbyLights = cur_nearby_lights;
-
- // FIND NEW LIGHTS THAT ARE IN RANGE
- light_set_t new_nearby_lights;
- for (LLDrawable::drawable_set_t::iterator iter = mLights.begin();
- iter != mLights.end(); ++iter)
- {
- LLDrawable* drawable = *iter;
- LLVOVolume* light = drawable->getVOVolume();
- if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT))
- {
- continue;
- }
- if (light->isHUDAttachment())
- {
- continue; // no lighting from HUD objects
- }
- F32 dist = calc_light_dist(light, cam_pos, max_dist);
- if (dist >= max_dist)
- {
- continue;
- }
- if (!sRenderAttachedLights && light && light->isAttachment())
- {
- continue;
- }
- new_nearby_lights.insert(Light(drawable, dist, 0.f));
- if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS)
- {
- new_nearby_lights.erase(--new_nearby_lights.end());
- const Light& last = *new_nearby_lights.rbegin();
- max_dist = last.dist;
- }
- }
-
- // INSERT ANY NEW LIGHTS
- for (light_set_t::iterator iter = new_nearby_lights.begin();
- iter != new_nearby_lights.end(); iter++)
- {
- const Light* light = &(*iter);
- if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS)
- {
- mNearbyLights.insert(*light);
- ((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT);
- }
- else
- {
- // crazy cast so that we can overwrite the fade value
- // even though gcc enforces sets as const
- // (fade value doesn't affect sort so this is safe)
- Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin()))));
- if (light->dist < farthest_light->dist)
- {
- if (farthest_light->fade >= 0.f)
- {
- farthest_light->fade = -gFrameIntervalSeconds;
- }
- }
- else
- {
- break; // none of the other lights are closer
- }
- }
- }
-
- }
-}
-
-void LLPipeline::setupHWLights(LLDrawPool* pool)
-{
- assertInitialized();
-
- // Ambient
- if (!LLGLSLShader::sNoFixedFunction)
- {
- gGL.syncMatrices();
- LLColor4 ambient = gSky.getTotalAmbientColor();
- gGL.setAmbientLightColor(ambient);
- }
-
- // Light 0 = Sun or Moon (All objects)
- {
- if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
- {
- mSunDir.setVec(gSky.getSunDirection());
- mSunDiffuse.setVec(gSky.getSunDiffuseColor());
- }
- else
- {
- mSunDir.setVec(gSky.getMoonDirection());
- mSunDiffuse.setVec(gSky.getMoonDiffuseColor());
- }
-
- F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]);
- if (max_color > 1.f)
- {
- mSunDiffuse *= 1.f/max_color;
- }
- mSunDiffuse.clamp();
-
- LLVector4 light_pos(mSunDir, 0.0f);
- LLColor4 light_diffuse = mSunDiffuse;
- mHWLightColors[0] = light_diffuse;
-
- LLLightState* light = gGL.getLight(0);
- light->setPosition(light_pos);
- light->setDiffuse(light_diffuse);
- light->setAmbient(LLColor4::black);
- light->setSpecular(LLColor4::black);
- light->setConstantAttenuation(1.f);
- light->setLinearAttenuation(0.f);
- light->setQuadraticAttenuation(0.f);
- light->setSpotExponent(0.f);
- light->setSpotCutoff(180.f);
- }
-
- // Light 1 = Backlight (for avatars)
- // (set by enableLightsAvatar)
-
- S32 cur_light = 2;
-
- // Nearby lights = LIGHT 2-7
-
- mLightMovingMask = 0;
-
- if (mLightingDetail >= 1)
- {
- for (light_set_t::iterator iter = mNearbyLights.begin();
- iter != mNearbyLights.end(); ++iter)
- {
- LLDrawable* drawable = iter->drawable;
- LLVOVolume* light = drawable->getVOVolume();
- if (!light)
- {
- continue;
- }
- if (drawable->isState(LLDrawable::ACTIVE))
- {
- mLightMovingMask |= (1<<cur_light);
- }
-
- LLColor4 light_color = light->getLightColor();
- light_color.mV[3] = 0.0f;
-
- F32 fade = iter->fade;
- if (fade < LIGHT_FADE_TIME)
- {
- // fade in/out light
- if (fade >= 0.f)
- {
- fade = fade / LIGHT_FADE_TIME;
- ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds;
- }
- else
- {
- fade = 1.f + fade / LIGHT_FADE_TIME;
- ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds;
- }
- fade = llclamp(fade,0.f,1.f);
- light_color *= fade;
- }
-
- LLVector3 light_pos(light->getRenderPosition());
- LLVector4 light_pos_gl(light_pos, 1.0f);
-
- F32 light_radius = llmax(light->getLightRadius(), 0.001f);
-
- F32 x = (3.f * (1.f + light->getLightFalloff())); // why this magic? probably trying to match a historic behavior.
- float linatten = x / (light_radius); // % of brightness at radius
-
- mHWLightColors[cur_light] = light_color;
- LLLightState* light_state = gGL.getLight(cur_light);
-
- light_state->setPosition(light_pos_gl);
- light_state->setDiffuse(light_color);
- light_state->setAmbient(LLColor4::black);
- light_state->setConstantAttenuation(0.f);
- if (sRenderDeferred)
- {
- F32 size = light_radius*1.5f;
- light_state->setLinearAttenuation(size*size);
- light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f);
- }
- else
- {
- light_state->setLinearAttenuation(linatten);
- light_state->setQuadraticAttenuation(0.f);
- }
-
-
- if (light->isLightSpotlight() // directional (spot-)light
- && (LLPipeline::sRenderDeferred || RenderSpotLightsInNondeferred)) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on
- {
- LLVector3 spotparams = light->getSpotLightParams();
- LLQuaternion quat = light->getRenderRotation();
- LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction
- at_axis *= quat;
-
- light_state->setSpotDirection(at_axis);
- light_state->setSpotCutoff(90.f);
- light_state->setSpotExponent(2.f);
-
- const LLColor4 specular(0.f, 0.f, 0.f, 0.f);
- light_state->setSpecular(specular);
- }
- else // omnidirectional (point) light
- {
- light_state->setSpotExponent(0.f);
- light_state->setSpotCutoff(180.f);
-
- // we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight
- const LLColor4 specular(0.f, 0.f, 0.f, 1.f);
- light_state->setSpecular(specular);
- }
- cur_light++;
- if (cur_light >= 8)
- {
- break; // safety
- }
- }
- }
- for ( ; cur_light < 8 ; cur_light++)
- {
- mHWLightColors[cur_light] = LLColor4::black;
- LLLightState* light = gGL.getLight(cur_light);
-
- light->setDiffuse(LLColor4::black);
- light->setAmbient(LLColor4::black);
- light->setSpecular(LLColor4::black);
- }
- if (gAgentAvatarp &&
- gAgentAvatarp->mSpecialRenderMode == 3)
- {
- LLColor4 light_color = LLColor4::white;
- light_color.mV[3] = 0.0f;
-
- LLVector3 light_pos(LLViewerCamera::getInstance()->getOrigin());
- LLVector4 light_pos_gl(light_pos, 1.0f);
-
- F32 light_radius = 16.f;
-
- F32 x = 3.f;
- float linatten = x / (light_radius); // % of brightness at radius
-
- mHWLightColors[2] = light_color;
- LLLightState* light = gGL.getLight(2);
-
- light->setPosition(light_pos_gl);
- light->setDiffuse(light_color);
- light->setAmbient(LLColor4::black);
- light->setSpecular(LLColor4::black);
- light->setQuadraticAttenuation(0.f);
- light->setConstantAttenuation(0.f);
- light->setLinearAttenuation(linatten);
- light->setSpotExponent(0.f);
- light->setSpotCutoff(180.f);
- }
-
- // Init GL state
- if (!LLGLSLShader::sNoFixedFunction)
- {
- glDisable(GL_LIGHTING);
- }
-
- for (S32 i = 0; i < 8; ++i)
- {
- gGL.getLight(i)->disable();
- }
- mLightMask = 0;
-}
-
-void LLPipeline::enableLights(U32 mask)
-{
- assertInitialized();
-
- if (mLightingDetail == 0)
- {
- mask &= 0xf003; // sun and backlight only (and fullbright bit)
- }
- if (mLightMask != mask)
- {
- stop_glerror();
- if (!mLightMask)
- {
- if (!LLGLSLShader::sNoFixedFunction)
- {
- glEnable(GL_LIGHTING);
- }
- }
- if (mask)
- {
- stop_glerror();
- for (S32 i=0; i<8; i++)
- {
- LLLightState* light = gGL.getLight(i);
- if (mask & (1<<i))
- {
- light->enable();
- light->setDiffuse(mHWLightColors[i]);
- }
- else
- {
- light->disable();
- light->setDiffuse(LLColor4::black);
- }
- }
- stop_glerror();
- }
- else
- {
- if (!LLGLSLShader::sNoFixedFunction)
- {
- glDisable(GL_LIGHTING);
- }
- }
- mLightMask = mask;
- stop_glerror();
-
- LLColor4 ambient = gSky.getTotalAmbientColor();
- gGL.setAmbientLightColor(ambient);
- }
-}
-
-void LLPipeline::enableLightsStatic()
-{
- assertInitialized();
- U32 mask = 0x01; // Sun
- if (mLightingDetail >= 2)
- {
- mask |= mLightMovingMask; // Hardware moving lights
- }
- else
- {
- mask |= 0xff & (~2); // Hardware local lights
- }
- enableLights(mask);
-}
-
-void LLPipeline::enableLightsDynamic()
-{
- assertInitialized();
- U32 mask = 0xff & (~2); // Local lights
- enableLights(mask);
-
- if (isAgentAvatarValid() && getLightingDetail() <= 0)
- {
- if (gAgentAvatarp->mSpecialRenderMode == 0) // normal
- {
- gPipeline.enableLightsAvatar();
- }
- else if (gAgentAvatarp->mSpecialRenderMode >= 1) // anim preview
- {
- gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f));
- }
- }
-}
-
-void LLPipeline::enableLightsAvatar()
-{
- U32 mask = 0xff; // All lights
- setupAvatarLights(FALSE);
- enableLights(mask);
-}
-
-void LLPipeline::enableLightsPreview()
-{
- disableLights();
-
- if (!LLGLSLShader::sNoFixedFunction)
- {
- glEnable(GL_LIGHTING);
- }
-
- LLColor4 ambient = PreviewAmbientColor;
- gGL.setAmbientLightColor(ambient);
-
- LLColor4 diffuse0 = PreviewDiffuse0;
- LLColor4 specular0 = PreviewSpecular0;
- LLColor4 diffuse1 = PreviewDiffuse1;
- LLColor4 specular1 = PreviewSpecular1;
- LLColor4 diffuse2 = PreviewDiffuse2;
- LLColor4 specular2 = PreviewSpecular2;
-
- LLVector3 dir0 = PreviewDirection0;
- LLVector3 dir1 = PreviewDirection1;
- LLVector3 dir2 = PreviewDirection2;
-
- dir0.normVec();
- dir1.normVec();
- dir2.normVec();
-
- LLVector4 light_pos(dir0, 0.0f);
-
- LLLightState* light = gGL.getLight(0);
-
- light->enable();
- light->setPosition(light_pos);
- light->setDiffuse(diffuse0);
- light->setAmbient(LLColor4::black);
- light->setSpecular(specular0);
- light->setSpotExponent(0.f);
- light->setSpotCutoff(180.f);
-
- light_pos = LLVector4(dir1, 0.f);
-
- light = gGL.getLight(1);
- light->enable();
- light->setPosition(light_pos);
- light->setDiffuse(diffuse1);
- light->setAmbient(LLColor4::black);
- light->setSpecular(specular1);
- light->setSpotExponent(0.f);
- light->setSpotCutoff(180.f);
-
- light_pos = LLVector4(dir2, 0.f);
- light = gGL.getLight(2);
- light->enable();
- light->setPosition(light_pos);
- light->setDiffuse(diffuse2);
- light->setAmbient(LLColor4::black);
- light->setSpecular(specular2);
- light->setSpotExponent(0.f);
- light->setSpotCutoff(180.f);
-}
-
-
-void LLPipeline::enableLightsAvatarEdit(const LLColor4& color)
-{
- U32 mask = 0x2002; // Avatar backlight only, set ambient
- setupAvatarLights(TRUE);
- enableLights(mask);
-
- gGL.setAmbientLightColor(color);
-}
-
-void LLPipeline::enableLightsFullbright(const LLColor4& color)
-{
- assertInitialized();
- U32 mask = 0x1000; // Non-0 mask, set ambient
- enableLights(mask);
-
- gGL.setAmbientLightColor(color);
-}
-
-void LLPipeline::disableLights()
-{
- enableLights(0); // no lighting (full bright)
-}
-
-//============================================================================
-
-class LLMenuItemGL;
-class LLInvFVBridge;
-struct cat_folder_pair;
-class LLVOBranch;
-class LLVOLeaf;
-
-void LLPipeline::findReferences(LLDrawable *drawablep)
-{
- assertInitialized();
- if (mLights.find(drawablep) != mLights.end())
- {
- llinfos << "In mLights" << llendl;
- }
- if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end())
- {
- llinfos << "In mMovedList" << llendl;
- }
- if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end())
- {
- llinfos << "In mShiftList" << llendl;
- }
- if (mRetexturedList.find(drawablep) != mRetexturedList.end())
- {
- llinfos << "In mRetexturedList" << llendl;
- }
-
- if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end())
- {
- llinfos << "In mBuildQ1" << llendl;
- }
- if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end())
- {
- llinfos << "In mBuildQ2" << llendl;
- }
-
- S32 count;
-
- count = gObjectList.findReferences(drawablep);
- if (count)
- {
- llinfos << "In other drawables: " << count << " references" << llendl;
- }
-}
-
-BOOL LLPipeline::verify()
-{
- BOOL ok = assertInitialized();
- if (ok)
- {
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
- {
- LLDrawPool *poolp = *iter;
- if (!poolp->verify())
- {
- ok = FALSE;
- }
- }
- }
-
- if (!ok)
- {
- llwarns << "Pipeline verify failed!" << llendl;
- }
- return ok;
-}
-
-//////////////////////////////
-//
-// Collision detection
-//
-//
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- * A method to compute a ray-AABB intersection.
- * Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990
- * Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)
- * Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only)
- *
- * Hence this version is faster as well as more robust than the original one.
- *
- * Should work provided:
- * 1) the integer representation of 0.0f is 0x00000000
- * 2) the sign bit of the float is the most significant one
- *
- * Report bugs: p.terdiman@codercorner.com
- *
- * \param aabb [in] the axis-aligned bounding box
- * \param origin [in] ray origin
- * \param dir [in] ray direction
- * \param coord [out] impact coordinates
- * \return true if ray intersects AABB
- */
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//#define RAYAABB_EPSILON 0.00001f
-#define IR(x) ((U32&)x)
-
-bool LLRayAABB(const LLVector3 &center, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon)
-{
- BOOL Inside = TRUE;
- LLVector3 MinB = center - size;
- LLVector3 MaxB = center + size;
- LLVector3 MaxT;
- MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f;
-
- // Find candidate planes.
- for(U32 i=0;i<3;i++)
- {
- if(origin.mV[i] < MinB.mV[i])
- {
- coord.mV[i] = MinB.mV[i];
- Inside = FALSE;
-
- // Calculate T distances to candidate planes
- if(IR(dir.mV[i])) MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i];
- }
- else if(origin.mV[i] > MaxB.mV[i])
- {
- coord.mV[i] = MaxB.mV[i];
- Inside = FALSE;
-
- // Calculate T distances to candidate planes
- if(IR(dir.mV[i])) MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i];
- }
- }
-
- // Ray origin inside bounding box
- if(Inside)
- {
- coord = origin;
- return true;
- }
-
- // Get largest of the maxT's for final choice of intersection
- U32 WhichPlane = 0;
- if(MaxT.mV[1] > MaxT.mV[WhichPlane]) WhichPlane = 1;
- if(MaxT.mV[2] > MaxT.mV[WhichPlane]) WhichPlane = 2;
-
- // Check final candidate actually inside box
- if(IR(MaxT.mV[WhichPlane])&0x80000000) return false;
-
- for(U32 i=0;i<3;i++)
- {
- if(i!=WhichPlane)
- {
- coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i];
- if (epsilon > 0)
- {
- if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon) return false;
- }
- else
- {
- if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i]) return false;
- }
- }
- }
- return true; // ray hits box
-}
-
-//////////////////////////////
-//
-// Macros, functions, and inline methods from other classes
-//
-//
-
-void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)
-{
- if (drawablep && assertInitialized())
- {
- if (is_light)
- {
- mLights.insert(drawablep);
- drawablep->setState(LLDrawable::LIGHT);
- }
- else
- {
- drawablep->clearState(LLDrawable::LIGHT);
- mLights.erase(drawablep);
- }
- }
-}
-
-//static
-void LLPipeline::toggleRenderType(U32 type)
-{
- gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type];
- if (type == LLPipeline::RENDER_TYPE_WATER)
- {
- gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER] = !gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER];
- }
-}
-
-//static
-void LLPipeline::toggleRenderTypeControl(void* data)
-{
- U32 type = (U32)(intptr_t)data;
- U32 bit = (1<<type);
- if (gPipeline.hasRenderType(type))
- {
- llinfos << "Toggling render type mask " << std::hex << bit << " off" << std::dec << llendl;
- }
- else
- {
- llinfos << "Toggling render type mask " << std::hex << bit << " on" << std::dec << llendl;
- }
- gPipeline.toggleRenderType(type);
-}
-
-//static
-BOOL LLPipeline::hasRenderTypeControl(void* data)
-{
- U32 type = (U32)(intptr_t)data;
- return gPipeline.hasRenderType(type);
-}
-
-// Allows UI items labeled "Hide foo" instead of "Show foo"
-//static
-BOOL LLPipeline::toggleRenderTypeControlNegated(void* data)
-{
- S32 type = (S32)(intptr_t)data;
- return !gPipeline.hasRenderType(type);
-}
-
-//static
-void LLPipeline::toggleRenderDebug(void* data)
-{
- U32 bit = (U32)(intptr_t)data;
- if (gPipeline.hasRenderDebugMask(bit))
- {
- llinfos << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << llendl;
- }
- else
- {
- llinfos << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << llendl;
- }
- gPipeline.mRenderDebugMask ^= bit;
-}
-
-
-//static
-BOOL LLPipeline::toggleRenderDebugControl(void* data)
-{
- U32 bit = (U32)(intptr_t)data;
- return gPipeline.hasRenderDebugMask(bit);
-}
-
-//static
-void LLPipeline::toggleRenderDebugFeature(void* data)
-{
- U32 bit = (U32)(intptr_t)data;
- gPipeline.mRenderDebugFeatureMask ^= bit;
-}
-
-
-//static
-BOOL LLPipeline::toggleRenderDebugFeatureControl(void* data)
-{
- U32 bit = (U32)(intptr_t)data;
- return gPipeline.hasRenderDebugFeatureMask(bit);
-}
-
-void LLPipeline::setRenderDebugFeatureControl(U32 bit, bool value)
-{
- if (value)
- {
- gPipeline.mRenderDebugFeatureMask |= bit;
- }
- else
- {
- gPipeline.mRenderDebugFeatureMask &= !bit;
- }
-}
-
-// static
-void LLPipeline::setRenderScriptedBeacons(BOOL val)
-{
- sRenderScriptedBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderScriptedBeacons(void*)
-{
- sRenderScriptedBeacons = !sRenderScriptedBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderScriptedBeacons(void*)
-{
- return sRenderScriptedBeacons;
-}
-
-// static
-void LLPipeline::setRenderScriptedTouchBeacons(BOOL val)
-{
- sRenderScriptedTouchBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderScriptedTouchBeacons(void*)
-{
- sRenderScriptedTouchBeacons = !sRenderScriptedTouchBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderScriptedTouchBeacons(void*)
-{
- return sRenderScriptedTouchBeacons;
-}
-
-// static
-void LLPipeline::setRenderMOAPBeacons(BOOL val)
-{
- sRenderMOAPBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderMOAPBeacons(void*)
-{
- sRenderMOAPBeacons = !sRenderMOAPBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderMOAPBeacons(void*)
-{
- return sRenderMOAPBeacons;
-}
-
-// static
-void LLPipeline::setRenderPhysicalBeacons(BOOL val)
-{
- sRenderPhysicalBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderPhysicalBeacons(void*)
-{
- sRenderPhysicalBeacons = !sRenderPhysicalBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderPhysicalBeacons(void*)
-{
- return sRenderPhysicalBeacons;
-}
-
-// static
-void LLPipeline::setRenderParticleBeacons(BOOL val)
-{
- sRenderParticleBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderParticleBeacons(void*)
-{
- sRenderParticleBeacons = !sRenderParticleBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderParticleBeacons(void*)
-{
- return sRenderParticleBeacons;
-}
-
-// static
-void LLPipeline::setRenderSoundBeacons(BOOL val)
-{
- sRenderSoundBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderSoundBeacons(void*)
-{
- sRenderSoundBeacons = !sRenderSoundBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderSoundBeacons(void*)
-{
- return sRenderSoundBeacons;
-}
-
-// static
-void LLPipeline::setRenderBeacons(BOOL val)
-{
- sRenderBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderBeacons(void*)
-{
- sRenderBeacons = !sRenderBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderBeacons(void*)
-{
- return sRenderBeacons;
-}
-
-// static
-void LLPipeline::setRenderHighlights(BOOL val)
-{
- sRenderHighlight = val;
-}
-
-// static
-void LLPipeline::toggleRenderHighlights(void*)
-{
- sRenderHighlight = !sRenderHighlight;
-}
-
-// static
-BOOL LLPipeline::getRenderHighlights(void*)
-{
- return sRenderHighlight;
-}
-
-LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end,
- BOOL pick_transparent,
- S32* face_hit,
- LLVector3* intersection, // return the intersection point
- LLVector2* tex_coord, // return the texture coordinates of the intersection point
- LLVector3* normal, // return the surface normal at the intersection point
- LLVector3* bi_normal // return the surface bi-normal at the intersection point
- )
-{
- LLDrawable* drawable = NULL;
-
- LLVector3 local_end = end;
-
- LLVector3 position;
-
- sPickAvatar = FALSE; //LLToolMgr::getInstance()->inBuildMode() ? FALSE : TRUE;
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
-
- for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
- {
- if ((j == LLViewerRegion::PARTITION_VOLUME) ||
- (j == LLViewerRegion::PARTITION_BRIDGE) ||
- (j == LLViewerRegion::PARTITION_TERRAIN) ||
- (j == LLViewerRegion::PARTITION_TREE) ||
- (j == LLViewerRegion::PARTITION_GRASS)) // only check these partitions for now
- {
- LLSpatialPartition* part = region->getSpatialPartition(j);
- if (part && hasRenderType(part->mDrawableType))
- {
- LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
- if (hit)
- {
- drawable = hit;
- local_end = position;
- }
- }
- }
- }
- }
-
- if (!sPickAvatar)
- {
- //save hit info in case we need to restore
- //due to attachment override
- LLVector3 local_normal;
- LLVector3 local_binormal;
- LLVector2 local_texcoord;
- S32 local_face_hit = -1;
-
- if (face_hit)
- {
- local_face_hit = *face_hit;
- }
- if (tex_coord)
- {
- local_texcoord = *tex_coord;
- }
- if (bi_normal)
- {
- local_binormal = *bi_normal;
- }
- if (normal)
- {
- local_normal = *normal;
- }
-
- const F32 ATTACHMENT_OVERRIDE_DIST = 0.1f;
-
- //check against avatars
- sPickAvatar = TRUE;
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
-
- LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE);
- if (part && hasRenderType(part->mDrawableType))
- {
- LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
- if (hit)
- {
- if (!drawable ||
- !drawable->getVObj()->isAttachment() ||
- (position-local_end).magVec() > ATTACHMENT_OVERRIDE_DIST)
- { //avatar overrides if previously hit drawable is not an attachment or
- //attachment is far enough away from detected intersection
- drawable = hit;
- local_end = position;
- }
- else
- { //prioritize attachments over avatars
- position = local_end;
-
- if (face_hit)
- {
- *face_hit = local_face_hit;
- }
- if (tex_coord)
- {
- *tex_coord = local_texcoord;
- }
- if (bi_normal)
- {
- *bi_normal = local_binormal;
- }
- if (normal)
- {
- *normal = local_normal;
- }
- }
- }
- }
- }
- }
-
- //check all avatar nametags (silly, isn't it?)
- for (std::vector< LLCharacter* >::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end();
- ++iter)
- {
- LLVOAvatar* av = (LLVOAvatar*) *iter;
- if (av->mNameText.notNull()
- && av->mNameText->lineSegmentIntersect(start, local_end, position))
- {
- drawable = av->mDrawable;
- local_end = position;
- }
- }
-
- if (intersection)
- {
- *intersection = position;
- }
-
- return drawable ? drawable->getVObj().get() : NULL;
-}
-
-LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector3& start, const LLVector3& end,
- BOOL pick_transparent,
- S32* face_hit,
- LLVector3* intersection, // return the intersection point
- LLVector2* tex_coord, // return the texture coordinates of the intersection point
- LLVector3* normal, // return the surface normal at the intersection point
- LLVector3* bi_normal // return the surface bi-normal at the intersection point
- )
-{
- LLDrawable* drawable = NULL;
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
-
- BOOL toggle = FALSE;
- if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- {
- toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
- toggle = TRUE;
- }
-
- LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD);
- if (part)
- {
- LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, face_hit, intersection, tex_coord, normal, bi_normal);
- if (hit)
- {
- drawable = hit;
- }
- }
-
- if (toggle)
- {
- toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
- }
- }
- return drawable ? drawable->getVObj().get() : NULL;
-}
-
-LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj)
-{
- if (vobj)
- {
- LLViewerRegion* region = vobj->getRegion();
- if (region)
- {
- return region->getSpatialPartition(vobj->getPartitionType());
- }
- }
- return NULL;
-}
-
-void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
-{
- if (!drawable || drawable->isDead())
- {
- return;
- }
-
- for (S32 i = 0; i < drawable->getNumFaces(); i++)
- {
- LLFace* facep = drawable->getFace(i);
- facep->clearVertexBuffer();
- }
-}
-
-void LLPipeline::resetVertexBuffers()
-{
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- part->resetVertexBuffers();
- }
- }
- }
-
- resetDrawOrders();
-
- gSky.resetVertexBuffers();
-
- if ( LLPathingLib::getInstance() )
- {
- LLPathingLib::getInstance()->cleanupVBOManger();
- }
- LLVertexBuffer::cleanupClass();
-
- //delete all name pool caches
- LLGLNamePool::cleanupPools();
-
- if (LLVertexBuffer::sGLCount > 0)
- {
- llwarns << "VBO wipe failed." << llendl;
- }
-
- llassert(LLVertexBuffer::sGLCount == 0);
-
- LLVertexBuffer::unbind();
-
- sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
- sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
- LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
- LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
- LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
- LLVertexBuffer::sEnableVBOs = gSavedSettings.getBOOL("RenderVBOEnable");
- LLVertexBuffer::sDisableVBOMapping = LLVertexBuffer::sEnableVBOs && gSavedSettings.getBOOL("RenderVBOMappingDisable") ;
- sBakeSunlight = gSavedSettings.getBOOL("RenderBakeSunlight");
- sNoAlpha = gSavedSettings.getBOOL("RenderNoAlpha");
- LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind");
-
- LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping);
-}
-
-void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture, BOOL batch_texture)
-{
- LLMemType mt_ro(LLMemType::MTYPE_PIPELINE_RENDER_OBJECTS);
- assertInitialized();
- gGL.loadMatrix(gGLModelView);
- gGLLastMatrix = NULL;
- mSimplePool->pushBatches(type, mask, texture, batch_texture);
- gGL.loadMatrix(gGLModelView);
- gGLLastMatrix = NULL;
-}
-
-void apply_cube_face_rotation(U32 face)
-{
- switch (face)
- {
- case 0:
- gGL.rotatef(90.f, 0, 1, 0);
- gGL.rotatef(180.f, 1, 0, 0);
- break;
- case 2:
- gGL.rotatef(-90.f, 1, 0, 0);
- break;
- case 4:
- gGL.rotatef(180.f, 0, 1, 0);
- gGL.rotatef(180.f, 0, 0, 1);
- break;
- case 1:
- gGL.rotatef(-90.f, 0, 1, 0);
- gGL.rotatef(180.f, 1, 0, 0);
- break;
- case 3:
- gGL.rotatef(90, 1, 0, 0);
- break;
- case 5:
- gGL.rotatef(180, 0, 0, 1);
- break;
- }
-}
-
-void validate_framebuffer_object()
-{
- GLenum status;
- status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
- switch(status)
- {
- case GL_FRAMEBUFFER_COMPLETE:
- //framebuffer OK, no error.
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- // frame buffer not OK: probably means unsupported depth buffer format
- llerrs << "Framebuffer Incomplete Missing Attachment." << llendl;
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- // frame buffer not OK: probably means unsupported depth buffer format
- llerrs << "Framebuffer Incomplete Attachment." << llendl;
- break;
- case GL_FRAMEBUFFER_UNSUPPORTED:
- /* choose different formats */
- llerrs << "Framebuffer unsupported." << llendl;
- break;
- default:
- llerrs << "Unknown framebuffer status." << llendl;
- break;
- }
-}
-
-void LLPipeline::bindScreenToTexture()
-{
-
-}
-
-static LLFastTimer::DeclareTimer FTM_RENDER_BLOOM("Bloom");
-
-void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
-{
- LLMemType mt_ru(LLMemType::MTYPE_PIPELINE_RENDER_BLOOM);
- if (!(gPipeline.canUseVertexShaders() &&
- sRenderGlow))
- {
- return;
- }
-
- LLVertexBuffer::unbind();
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
-
- assertInitialized();
-
- if (gUseWireframe)
- {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- }
-
- LLVector2 tc1(0,0);
- LLVector2 tc2((F32) mScreen.getWidth()*2,
- (F32) mScreen.getHeight()*2);
-
- LLFastTimer ftm(FTM_RENDER_BLOOM);
- gGL.color4f(1,1,1,1);
- LLGLDepthTest depth(GL_FALSE);
- LLGLDisable blend(GL_BLEND);
- LLGLDisable cull(GL_CULL_FACE);
-
- enableLightsFullbright(LLColor4(1,1,1,1));
-
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- gGL.loadIdentity();
-
- LLGLDisable test(GL_ALPHA_TEST);
-
- gGL.setColorMask(true, true);
- glClearColor(0,0,0,0);
-
- {
- {
- LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
- mGlow[2].bindTarget();
- mGlow[2].clear();
- }
-
- gGlowExtractProgram.bind();
- F32 minLum = llmax((F32) RenderGlowMinLuminance, 0.0f);
- F32 maxAlpha = RenderGlowMaxExtractAlpha;
- F32 warmthAmount = RenderGlowWarmthAmount;
- LLVector3 lumWeights = RenderGlowLumWeights;
- LLVector3 warmthWeights = RenderGlowWarmthWeights;
-
-
- gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, minLum);
- gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha);
- gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1], lumWeights.mV[2]);
- gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1], warmthWeights.mV[2]);
- gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount);
- LLGLEnable blend_on(GL_BLEND);
- LLGLEnable test(GL_ALPHA_TEST);
-
- gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
-
- mScreen.bindTexture(0, 0);
-
- gGL.color4f(1,1,1,1);
- gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
-
- gGL.getTexUnit(0)->unbind(mScreen.getUsage());
-
- mGlow[2].flush();
- }
-
- tc1.setVec(0,0);
- tc2.setVec(2,2);
-
- // power of two between 1 and 1024
- U32 glowResPow = RenderGlowResolutionPow;
- const U32 glow_res = llmax(1,
- llmin(1024, 1 << glowResPow));
-
- S32 kernel = RenderGlowIterations*2;
- F32 delta = RenderGlowWidth / glow_res;
- // Use half the glow width if we have the res set to less than 9 so that it looks
- // almost the same in either case.
- if (glowResPow < 9)
- {
- delta *= 0.5f;
- }
- F32 strength = RenderGlowStrength;
-
- gGlowProgram.bind();
- gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength);
-
- for (S32 i = 0; i < kernel; i++)
- {
- {
- LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
- mGlow[i%2].bindTarget();
- mGlow[i%2].clear();
- }
-
- if (i == 0)
- {
- gGL.getTexUnit(0)->bind(&mGlow[2]);
- }
- else
- {
- gGL.getTexUnit(0)->bind(&mGlow[(i-1)%2]);
- }
-
- if (i%2 == 0)
- {
- gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0);
- }
- else
- {
- gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta);
- }
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
-
- mGlow[i%2].flush();
- }
-
- gGlowProgram.unbind();
-
- if (LLRenderTarget::sUseFBO)
- {
- LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- }
-
- gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
- gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
- gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
- gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-
- tc2.setVec((F32) mScreen.getWidth(),
- (F32) mScreen.getHeight());
-
- gGL.flush();
-
- LLVertexBuffer::unbind();
-
- if (LLPipeline::sRenderDeferred)
- {
-
- bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() &&
- !LLToolMgr::getInstance()->inBuildMode() &&
- RenderDepthOfField;
-
-
- bool multisample = RenderFSAASamples > 1 && mFXAABuffer.isComplete();
-
- gViewerWindow->setup3DViewport();
-
- if (dof_enabled)
- {
- LLGLSLShader* shader = &gDeferredPostProgram;
- LLGLDisable blend(GL_BLEND);
-
- //depth of field focal plane calculations
- static F32 current_distance = 16.f;
- static F32 start_distance = 16.f;
- static F32 transition_time = 1.f;
-
- LLVector3 focus_point;
-
- LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
- if (obj && obj->mDrawable && obj->isSelected())
- { //focus on selected media object
- S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
- if (obj && obj->mDrawable)
- {
- LLFace* face = obj->mDrawable->getFace(face_idx);
- if (face)
- {
- focus_point = face->getPositionAgent();
- }
- }
- }
-
- if (focus_point.isExactlyZero())
- {
- if (LLViewerJoystick::getInstance()->getOverrideCamera())
- { //focus on point under cursor
- focus_point = gDebugRaycastIntersection;
- }
- else if (gAgentCamera.cameraMouselook())
- { //focus on point under mouselook crosshairs
- gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
- NULL,
- &focus_point);
- }
- else
- {
- LLViewerObject* obj = gAgentCamera.getFocusObject();
- if (obj)
- { //focus on alt-zoom target
- focus_point = LLVector3(gAgentCamera.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal());
- }
- else
- { //focus on your avatar
- focus_point = gAgent.getPositionAgent();
- }
- }
- }
-
- LLVector3 eye = LLViewerCamera::getInstance()->getOrigin();
- F32 target_distance = 16.f;
- if (!focus_point.isExactlyZero())
- {
- target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point-eye);
- }
-
- if (transition_time >= 1.f &&
- fabsf(current_distance-target_distance)/current_distance > 0.01f)
- { //large shift happened, interpolate smoothly to new target distance
- transition_time = 0.f;
- start_distance = current_distance;
- }
- else if (transition_time < 1.f)
- { //currently in a transition, continue interpolating
- transition_time += 1.f/CameraFocusTransitionTime*gFrameIntervalSeconds;
- transition_time = llmin(transition_time, 1.f);
-
- F32 t = cosf(transition_time*F_PI+F_PI)*0.5f+0.5f;
- current_distance = start_distance + (target_distance-start_distance)*t;
- }
- else
- { //small or no change, just snap to target distance
- current_distance = target_distance;
- }
-
- //convert to mm
- F32 subject_distance = current_distance*1000.f;
- F32 fnumber = CameraFNumber;
- F32 default_focal_length = CameraFocalLength;
-
- F32 fov = LLViewerCamera::getInstance()->getView();
-
- const F32 default_fov = CameraFieldOfView * F_PI/180.f;
- //const F32 default_aspect_ratio = gSavedSettings.getF32("CameraAspectRatio");
-
- //F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight();
-
- F32 dv = 2.f*default_focal_length * tanf(default_fov/2.f);
- //F32 dh = 2.f*default_focal_length * tanf(default_fov*default_aspect_ratio/2.f);
-
- F32 focal_length = dv/(2*tanf(fov/2.f));
-
- //F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle);
-
- // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f))
- // where N = fnumber
- // s2 = dot distance
- // s1 = subject distance
- // f = focal length
- //
-
- F32 blur_constant = focal_length*focal_length/(fnumber*(subject_distance-focal_length));
- blur_constant /= 1000.f; //convert to meters for shader
- F32 magnification = focal_length/(subject_distance-focal_length);
-
- { //build diffuse+bloom+CoF
- mDeferredLight.bindTarget();
- shader = &gDeferredCoFProgram;
-
- bindDeferredShader(*shader);
-
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
- if (channel > -1)
- {
- mScreen.bindTexture(0, channel);
- }
-
- shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance/1000.f);
- shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
- shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f/LLDrawable::sCurPixelAngle));
- shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
- shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
- shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
-
- unbindDeferredShader(*shader);
- mDeferredLight.flush();
- }
-
- { //perform DoF sampling at half-res (preserve alpha channel)
- mScreen.bindTarget();
- glViewport(0,0,(GLsizei) (mScreen.getWidth()*CameraDoFResScale), (GLsizei) (mScreen.getHeight()*CameraDoFResScale));
- gGL.setColorMask(true, false);
-
- shader = &gDeferredPostProgram;
- bindDeferredShader(*shader);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
- if (channel > -1)
- {
- mDeferredLight.bindTexture(0, channel);
- }
-
- shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
- shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
-
- unbindDeferredShader(*shader);
- mScreen.flush();
- gGL.setColorMask(true, true);
- }
-
- { //combine result based on alpha
- if (multisample)
- {
- mDeferredLight.bindTarget();
- glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
- }
- else
- {
- gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
- gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
- gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
- gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- }
-
- shader = &gDeferredDoFCombineProgram;
- bindDeferredShader(*shader);
-
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
- if (channel > -1)
- {
- mScreen.bindTexture(0, channel);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
- }
-
- shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
- shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
-
- unbindDeferredShader(*shader);
-
- if (multisample)
- {
- mDeferredLight.flush();
- }
- }
- }
- else
- {
- if (multisample)
- {
- mDeferredLight.bindTarget();
- }
- LLGLSLShader* shader = &gDeferredPostNoDoFProgram;
-
- bindDeferredShader(*shader);
-
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
- if (channel > -1)
- {
- mScreen.bindTexture(0, channel);
- }
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
-
- unbindDeferredShader(*shader);
-
- if (multisample)
- {
- mDeferredLight.flush();
- }
- }
-
- if (multisample)
- {
- //bake out texture2D with RGBL for FXAA shader
- mFXAABuffer.bindTarget();
-
- S32 width = mScreen.getWidth();
- S32 height = mScreen.getHeight();
- glViewport(0, 0, width, height);
-
- LLGLSLShader* shader = &gGlowCombineFXAAProgram;
-
- shader->bind();
- shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height);
-
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
- if (channel > -1)
- {
- mDeferredLight.bindTexture(0, channel);
- }
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.vertex2f(-1,-1);
- gGL.vertex2f(-1,3);
- gGL.vertex2f(3,-1);
- gGL.end();
-
- gGL.flush();
-
- shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
- shader->unbind();
-
- mFXAABuffer.flush();
-
- shader = &gFXAAProgram;
- shader->bind();
-
- channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage());
- if (channel > -1)
- {
- mFXAABuffer.bindTexture(0, channel);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
- }
-
- gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
- gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
- gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
- gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-
- F32 scale_x = (F32) width/mFXAABuffer.getWidth();
- F32 scale_y = (F32) height/mFXAABuffer.getHeight();
- shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
- shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f/width*scale_x, 1.f/height*scale_y);
- shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f/width*scale_x, -0.5f/height*scale_y, 0.5f/width*scale_x, 0.5f/height*scale_y);
- shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f/width*scale_x, -2.f/height*scale_y, 2.f/width*scale_x, 2.f/height*scale_y);
-
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.vertex2f(-1,-1);
- gGL.vertex2f(-1,3);
- gGL.vertex2f(3,-1);
- gGL.end();
-
- gGL.flush();
- shader->unbind();
- }
- }
- else
- {
- U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
- LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
- buff->allocateBuffer(3,0,TRUE);
-
- LLStrider<LLVector3> v;
- LLStrider<LLVector2> uv1;
- LLStrider<LLVector2> uv2;
-
- buff->getVertexStrider(v);
- buff->getTexCoord0Strider(uv1);
- buff->getTexCoord1Strider(uv2);
-
- uv1[0] = LLVector2(0, 0);
- uv1[1] = LLVector2(0, 2);
- uv1[2] = LLVector2(2, 0);
-
- uv2[0] = LLVector2(0, 0);
- uv2[1] = LLVector2(0, tc2.mV[1]*2.f);
- uv2[2] = LLVector2(tc2.mV[0]*2.f, 0);
-
- v[0] = LLVector3(-1,-1,0);
- v[1] = LLVector3(-1,3,0);
- v[2] = LLVector3(3,-1,0);
-
- buff->flush();
-
- LLGLDisable blend(GL_BLEND);
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gGlowCombineProgram.bind();
- }
- else
- {
- //tex unit 0
- gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
- //tex unit 1
- gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
- }
-
- gGL.getTexUnit(0)->bind(&mGlow[1]);
- gGL.getTexUnit(1)->bind(&mScreen);
-
- LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-
- buff->setBuffer(mask);
- buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3);
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gGlowCombineProgram.unbind();
- }
- else
- {
- gGL.getTexUnit(1)->disable();
- gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
-
- gGL.getTexUnit(0)->activate();
- gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
- }
-
- }
-
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
- if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
- {
- if (LLGLSLShader::sNoFixedFunction)
- {
- gSplatTextureRectProgram.bind();
- }
-
- gGL.setColorMask(true, false);
-
- LLVector2 tc1(0,0);
- LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2,
- (F32) gViewerWindow->getWorldViewHeightRaw()*2);
-
- LLGLEnable blend(GL_BLEND);
- gGL.color4f(1,1,1,0.75f);
-
- gGL.getTexUnit(0)->bind(&mPhysicsDisplay);
-
- gGL.begin(LLRender::TRIANGLES);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,3);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(3,-1);
-
- gGL.end();
- gGL.flush();
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gSplatTextureRectProgram.unbind();
- }
- }
-
-
- if (LLRenderTarget::sUseFBO)
- { //copy depth buffer from mScreen to framebuffer
- LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(),
- 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
- }
-
-
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
-
- LLVertexBuffer::unbind();
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
-
-}
-
-static LLFastTimer::DeclareTimer FTM_BIND_DEFERRED("Bind Deferred");
-
-void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 noise_map)
-{
- LLFastTimer t(FTM_BIND_DEFERRED);
-
- if (noise_map == 0xFFFFFFFF)
- {
- noise_map = mNoiseMap;
- }
-
- shader.bind();
- S32 channel = 0;
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
- if (channel > -1)
- {
- mDeferredScreen.bindTexture(0,channel);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- }
-
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
- if (channel > -1)
- {
- mDeferredScreen.bindTexture(1, channel);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- }
-
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
- if (channel > -1)
- {
- mDeferredScreen.bindTexture(2, channel);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- }
-
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredDepth.getUsage());
- if (channel > -1)
- {
- gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
- stop_glerror();
-
- //glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
- //glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);
-
- stop_glerror();
-
- glh::matrix4f projection = glh_get_current_projection();
- glh::matrix4f inv_proj = projection.inverse();
-
- shader.uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
- shader.uniform4f(LLShaderMgr::VIEWPORT, (F32) gGLViewport[0],
- (F32) gGLViewport[1],
- (F32) gGLViewport[2],
- (F32) gGLViewport[3]);
- }
-
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_NOISE);
- if (channel > -1)
- {
- gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, noise_map);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- }
-
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC);
- if (channel > -1)
- {
- gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
- }
-
- stop_glerror();
-
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHT, mDeferredLight.getUsage());
- if (channel > -1)
- {
- if (light_index > 0)
- {
- mScreen.bindTexture(0, channel);
- }
- else
- {
- mDeferredLight.bindTexture(0, channel);
- }
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- }
-
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_BLOOM);
- if (channel > -1)
- {
- mGlow[1].bindTexture(0, channel);
- }
-
- stop_glerror();
-
- for (U32 i = 0; i < 4; i++)
- {
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE);
- stop_glerror();
- if (channel > -1)
- {
- stop_glerror();
- gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
- gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- stop_glerror();
-
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
- stop_glerror();
- }
- }
-
- for (U32 i = 4; i < 6; i++)
- {
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i);
- stop_glerror();
- if (channel > -1)
- {
- stop_glerror();
- gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
- gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- stop_glerror();
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
- stop_glerror();
- }
- }
-
- stop_glerror();
-
- F32 mat[16*6];
- for (U32 i = 0; i < 16; i++)
- {
- mat[i] = mSunShadowMatrix[0].m[i];
- mat[i+16] = mSunShadowMatrix[1].m[i];
- mat[i+32] = mSunShadowMatrix[2].m[i];
- mat[i+48] = mSunShadowMatrix[3].m[i];
- mat[i+64] = mSunShadowMatrix[4].m[i];
- mat[i+80] = mSunShadowMatrix[5].m[i];
- }
-
- shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_SHADOW_MATRIX, 6, FALSE, mat);
-
- stop_glerror();
-
- channel = shader.enableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
- if (channel > -1)
- {
- LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
- if (cube_map)
- {
- cube_map->enable(channel);
- cube_map->bind();
- F32* m = gGLModelView;
-
- F32 mat[] = { m[0], m[1], m[2],
- m[4], m[5], m[6],
- m[8], m[9], m[10] };
-
- shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat);
- }
- }
-
- shader.uniform4fv(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1, mSunClipPlanes.mV);
- shader.uniform1f(LLShaderMgr::DEFERRED_SUN_WASH, RenderDeferredSunWash);
- shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise);
- shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize);
-
- shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale);
- shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, RenderSSAOMaxScale);
-
- F32 ssao_factor = RenderSSAOFactor;
- shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR, ssao_factor);
- shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0/ssao_factor);
-
- LLVector3 ssao_effect = RenderSSAOEffect;
- F32 matrix_diag = (ssao_effect[0] + 2.0*ssao_effect[1])/3.0;
- F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0;
- // This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by
- // value factor, and scales remainder by saturation factor
- F32 ssao_effect_mat[] = { matrix_diag, matrix_nondiag, matrix_nondiag,
- matrix_nondiag, matrix_diag, matrix_nondiag,
- matrix_nondiag, matrix_nondiag, matrix_diag};
- shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_SSAO_EFFECT_MAT, 1, GL_FALSE, ssao_effect_mat);
-
- F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
- F32 shadow_bias_error = 1.f + RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
-
- shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
- shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear()*2.f);
- shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset*shadow_offset_error);
- shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, RenderShadowBias*shadow_bias_error);
- shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_OFFSET, RenderSpotShadowOffset);
- shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_BIAS, RenderSpotShadowBias);
-
- shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV);
- shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mShadow[0].getWidth(), mShadow[0].getHeight());
- shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mShadow[4].getWidth(), mShadow[4].getHeight());
- shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff);
- shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff);
-
-
- if (shader.getUniformLocation("norm_mat") >= 0)
- {
- glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose();
- shader.uniformMatrix4fv("norm_mat", 1, FALSE, norm_mat.m);
- }
-}
-
-static LLFastTimer::DeclareTimer FTM_GI_TRACE("Trace");
-static LLFastTimer::DeclareTimer FTM_GI_GATHER("Gather");
-static LLFastTimer::DeclareTimer FTM_SUN_SHADOW("Shadow Map");
-static LLFastTimer::DeclareTimer FTM_SOFTEN_SHADOW("Shadow Soften");
-static LLFastTimer::DeclareTimer FTM_EDGE_DETECTION("Find Edges");
-static LLFastTimer::DeclareTimer FTM_LOCAL_LIGHTS("Local Lights");
-static LLFastTimer::DeclareTimer FTM_ATMOSPHERICS("Atmospherics");
-static LLFastTimer::DeclareTimer FTM_FULLSCREEN_LIGHTS("Fullscreen Lights");
-static LLFastTimer::DeclareTimer FTM_PROJECTORS("Projectors");
-static LLFastTimer::DeclareTimer FTM_POST("Post");
-
-
-void LLPipeline::renderDeferredLighting()
-{
- if (!sCull)
- {
- return;
- }
-
- {
- LLFastTimer ftm(FTM_RENDER_DEFERRED);
-
- LLViewerCamera* camera = LLViewerCamera::getInstance();
- {
- LLGLDepthTest depth(GL_TRUE);
- mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
- 0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
- }
-
- LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-
- if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
- {
- gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
- }
-
- //ati doesn't seem to love actually using the stencil buffer on FBO's
- LLGLDisable stencil(GL_STENCIL_TEST);
- //glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
- //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-
- gGL.setColorMask(true, true);
-
- //draw a cube around every light
- LLVertexBuffer::unbind();
-
- LLGLEnable cull(GL_CULL_FACE);
- LLGLEnable blend(GL_BLEND);
-
- glh::matrix4f mat = glh_copy_matrix(gGLModelView);
-
- LLStrider<LLVector3> vert;
- mDeferredVB->getVertexStrider(vert);
- LLStrider<LLVector2> tc0;
- LLStrider<LLVector2> tc1;
- mDeferredVB->getTexCoord0Strider(tc0);
- mDeferredVB->getTexCoord1Strider(tc1);
-
- vert[0].set(-1,1,0);
- vert[1].set(-1,-3,0);
- vert[2].set(3,1,0);
-
- {
- setupHWLights(NULL); //to set mSunDir;
- LLVector4 dir(mSunDir, 0.f);
- glh::vec4f tc(dir.mV);
- mat.mult_matrix_vec(tc);
- mTransformedSunDir.set(tc.v);
- }
-
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
-
- if (RenderDeferredSSAO || RenderShadowDetail > 0)
- {
- mDeferredLight.bindTarget();
- { //paint shadow/SSAO light map (direct lighting lightmap)
- LLFastTimer ftm(FTM_SUN_SHADOW);
- bindDeferredShader(gDeferredSunProgram, 0);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- glClearColor(1,1,1,1);
- mDeferredLight.clear(GL_COLOR_BUFFER_BIT);
- glClearColor(0,0,0,0);
-
- glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
-
- const U32 slice = 32;
- F32 offset[slice*3];
- for (U32 i = 0; i < 4; i++)
- {
- for (U32 j = 0; j < 8; j++)
- {
- glh::vec3f v;
- v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i);
- v.normalize();
- inv_trans.mult_matrix_vec(v);
- v.normalize();
- offset[(i*8+j)*3+0] = v.v[0];
- offset[(i*8+j)*3+1] = v.v[2];
- offset[(i*8+j)*3+2] = v.v[1];
- }
- }
-
- gDeferredSunProgram.uniform3fv("offset", slice, offset);
- gDeferredSunProgram.uniform2f("screenRes", mDeferredLight.getWidth(), mDeferredLight.getHeight());
-
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- stop_glerror();
- }
-
- unbindDeferredShader(gDeferredSunProgram);
- }
- mDeferredLight.flush();
- }
-
- if (RenderDeferredSSAO)
- { //soften direct lighting lightmap
- LLFastTimer ftm(FTM_SOFTEN_SHADOW);
- //blur lightmap
- mScreen.bindTarget();
- glClearColor(1,1,1,1);
- mScreen.clear(GL_COLOR_BUFFER_BIT);
- glClearColor(0,0,0,0);
-
- bindDeferredShader(gDeferredBlurLightProgram);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- LLVector3 go = RenderShadowGaussian;
- const U32 kern_length = 4;
- F32 blur_size = RenderShadowBlurSize;
- F32 dist_factor = RenderShadowBlurDistFactor;
-
- // sample symmetrically with the middle sample falling exactly on 0.0
- F32 x = 0.f;
-
- LLVector3 gauss[32]; // xweight, yweight, offset
-
- for (U32 i = 0; i < kern_length; i++)
- {
- gauss[i].mV[0] = llgaussian(x, go.mV[0]);
- gauss[i].mV[1] = llgaussian(x, go.mV[1]);
- gauss[i].mV[2] = x;
- x += 1.f;
- }
-
- gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f);
- gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor);
- gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
- gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
-
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- stop_glerror();
- }
-
- mScreen.flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
-
- bindDeferredShader(gDeferredBlurLightProgram, 1);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- mDeferredLight.bindTarget();
-
- gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f);
-
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- stop_glerror();
- }
- mDeferredLight.flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
- }
-
- stop_glerror();
- gGL.popMatrix();
- stop_glerror();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- stop_glerror();
- gGL.popMatrix();
- stop_glerror();
-
- //copy depth and stencil from deferred screen
- //mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
- // 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-
- mScreen.bindTarget();
- // clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
- glClearColor(0,0,0,0);
- mScreen.clear(GL_COLOR_BUFFER_BIT);
-
- if (RenderDeferredAtmospheric)
- { //apply sunlight contribution
- LLFastTimer ftm(FTM_ATMOSPHERICS);
- bindDeferredShader(gDeferredSoftenProgram);
- {
- LLGLDepthTest depth(GL_FALSE);
- LLGLDisable blend(GL_BLEND);
- LLGLDisable test(GL_ALPHA_TEST);
-
- //full screen blit
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
-
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
- }
-
- unbindDeferredShader(gDeferredSoftenProgram);
- }
-
- { //render non-deferred geometry (fullbright, alpha, etc)
- LLGLDisable blend(GL_BLEND);
- LLGLDisable stencil(GL_STENCIL_TEST);
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
- gPipeline.pushRenderTypeMask();
-
- gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
- LLPipeline::RENDER_TYPE_CLOUDS,
- LLPipeline::RENDER_TYPE_WL_SKY,
- LLPipeline::END_RENDER_TYPES);
-
-
- renderGeomPostDeferred(*LLViewerCamera::getInstance());
- gPipeline.popRenderTypeMask();
- }
-
- BOOL render_local = RenderLocalLights;
-
- if (render_local)
- {
- gGL.setSceneBlendType(LLRender::BT_ADD);
- std::list<LLVector4> fullscreen_lights;
- LLDrawable::drawable_list_t spot_lights;
- LLDrawable::drawable_list_t fullscreen_spot_lights;
-
- for (U32 i = 0; i < 2; i++)
- {
- mTargetShadowSpotLight[i] = NULL;
- }
-
- std::list<LLVector4> light_colors;
-
- LLVertexBuffer::unbind();
- LLVector4a* v = (LLVector4a*) vert.get();
-
- {
- bindDeferredShader(gDeferredLightProgram);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
- LLGLDepthTest depth(GL_TRUE, GL_FALSE);
- for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
- {
- LLDrawable* drawablep = *iter;
-
- LLVOVolume* volume = drawablep->getVOVolume();
- if (!volume)
- {
- continue;
- }
-
- if (volume->isAttachment())
- {
- if (!sRenderAttachedLights)
- {
- continue;
- }
- }
-
-
- LLVector4a center;
- center.load3(drawablep->getPositionAgent().mV);
- const F32* c = center.getF32ptr();
- F32 s = volume->getLightRadius()*1.5f;
-
- LLColor3 col = volume->getLightColor();
-
- if (col.magVecSquared() < 0.001f)
- {
- continue;
- }
-
- if (s <= 0.001f)
- {
- continue;
- }
-
- LLVector4a sa;
- sa.splat(s);
- if (camera->AABBInFrustumNoFarClip(center, sa) == 0)
- {
- continue;
- }
-
- sVisibleLightCount++;
-
- glh::vec3f tc(c);
- mat.mult_matrix_vec(tc);
-
- //vertex positions are encoded so the 3 bits of their vertex index
- //correspond to their axis facing, with bit position 3,2,1 matching
- //axis facing x,y,z, bit set meaning positive facing, bit clear
- //meaning negative facing
- mDeferredVB->getVertexStrider(vert);
- v[0].set(c[0]-s,c[1]-s,c[2]-s); // 0 - 0000
- v[1].set(c[0]-s,c[1]-s,c[2]+s); // 1 - 0001
- v[2].set(c[0]-s,c[1]+s,c[2]-s); // 2 - 0010
- v[3].set(c[0]-s,c[1]+s,c[2]+s); // 3 - 0011
-
- v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100
- v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101
- v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110
- v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111
-
- if (camera->getOrigin().mV[0] > c[0] + s + 0.2f ||
- camera->getOrigin().mV[0] < c[0] - s - 0.2f ||
- camera->getOrigin().mV[1] > c[1] + s + 0.2f ||
- camera->getOrigin().mV[1] < c[1] - s - 0.2f ||
- camera->getOrigin().mV[2] > c[2] + s + 0.2f ||
- camera->getOrigin().mV[2] < c[2] - s - 0.2f)
- { //draw box if camera is outside box
- if (render_local)
- {
- if (volume->isLightSpotlight())
- {
- drawablep->getVOVolume()->updateSpotLightPriority();
- spot_lights.push_back(drawablep);
- continue;
- }
-
- LLFastTimer ftm(FTM_LOCAL_LIGHTS);
- //glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
- gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
- gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
- gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
- gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
- //gGL.diffuseColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
- gGL.syncMatrices();
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
- GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center));
- stop_glerror();
- }
- }
- else
- {
- if (volume->isLightSpotlight())
- {
- drawablep->getVOVolume()->updateSpotLightPriority();
- fullscreen_spot_lights.push_back(drawablep);
- continue;
- }
-
- fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s));
- light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f));
- }
- }
- unbindDeferredShader(gDeferredLightProgram);
- }
-
- if (!spot_lights.empty())
- {
- LLGLDepthTest depth(GL_TRUE, GL_FALSE);
- bindDeferredShader(gDeferredSpotLightProgram);
-
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
- gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-
- for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
- {
- LLFastTimer ftm(FTM_PROJECTORS);
- LLDrawable* drawablep = *iter;
-
- LLVOVolume* volume = drawablep->getVOVolume();
-
- LLVector4a center;
- center.load3(drawablep->getPositionAgent().mV);
- const F32* c = center.getF32ptr();
- F32 s = volume->getLightRadius()*1.5f;
-
- sVisibleLightCount++;
-
- glh::vec3f tc(c);
- mat.mult_matrix_vec(tc);
-
- setupSpotLight(gDeferredSpotLightProgram, drawablep);
-
- LLColor3 col = volume->getLightColor();
-
- //vertex positions are encoded so the 3 bits of their vertex index
- //correspond to their axis facing, with bit position 3,2,1 matching
- //axis facing x,y,z, bit set meaning positive facing, bit clear
- //meaning negative facing
- mDeferredVB->getVertexStrider(vert);
- v[0].set(c[0]-s,c[1]-s,c[2]-s); // 0 - 0000
- v[1].set(c[0]-s,c[1]-s,c[2]+s); // 1 - 0001
- v[2].set(c[0]-s,c[1]+s,c[2]-s); // 2 - 0010
- v[3].set(c[0]-s,c[1]+s,c[2]+s); // 3 - 0011
-
- v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100
- v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101
- v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110
- v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111
-
- gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
- gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
- gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
- gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
- gGL.syncMatrices();
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
- GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center));
- }
- gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
- unbindDeferredShader(gDeferredSpotLightProgram);
- }
-
- //reset mDeferredVB to fullscreen triangle
- mDeferredVB->getVertexStrider(vert);
- vert[0].set(-1,1,0);
- vert[1].set(-1,-3,0);
- vert[2].set(3,1,0);
-
- {
- bindDeferredShader(gDeferredMultiLightProgram);
-
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
- LLGLDepthTest depth(GL_FALSE);
-
- //full screen blit
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
-
- U32 count = 0;
-
- const U32 max_count = 8;
- LLVector4 light[max_count];
- LLVector4 col[max_count];
-
-// glVertexPointer(2, GL_FLOAT, 0, vert);
-
- F32 far_z = 0.f;
-
- while (!fullscreen_lights.empty())
- {
- LLFastTimer ftm(FTM_FULLSCREEN_LIGHTS);
- light[count] = fullscreen_lights.front();
- fullscreen_lights.pop_front();
- col[count] = light_colors.front();
- light_colors.pop_front();
-
- far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z);
-
- count++;
- if (count == max_count || fullscreen_lights.empty())
- {
- gDeferredMultiLightProgram.uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count);
- gDeferredMultiLightProgram.uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light);
- gDeferredMultiLightProgram.uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col);
- gDeferredMultiLightProgram.uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z);
- far_z = 0.f;
- count = 0;
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- }
- }
-
- unbindDeferredShader(gDeferredMultiLightProgram);
-
- bindDeferredShader(gDeferredMultiSpotLightProgram);
-
- gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
- for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
- {
- LLFastTimer ftm(FTM_PROJECTORS);
- LLDrawable* drawablep = *iter;
-
- LLVOVolume* volume = drawablep->getVOVolume();
-
- LLVector3 center = drawablep->getPositionAgent();
- F32* c = center.mV;
- F32 s = volume->getLightRadius()*1.5f;
-
- sVisibleLightCount++;
-
- glh::vec3f tc(c);
- mat.mult_matrix_vec(tc);
-
- setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
-
- LLColor3 col = volume->getLightColor();
-
- gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
- gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
- gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
- gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- }
-
- gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
- unbindDeferredShader(gDeferredMultiSpotLightProgram);
-
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
- }
- }
-
- gGL.setColorMask(true, true);
- }
-
- { //render non-deferred geometry (alpha, fullbright, glow)
- LLGLDisable blend(GL_BLEND);
- LLGLDisable stencil(GL_STENCIL_TEST);
-
- pushRenderTypeMask();
- andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA,
- LLPipeline::RENDER_TYPE_FULLBRIGHT,
- LLPipeline::RENDER_TYPE_VOLUME,
- LLPipeline::RENDER_TYPE_GLOW,
- LLPipeline::RENDER_TYPE_BUMP,
- LLPipeline::RENDER_TYPE_PASS_SIMPLE,
- LLPipeline::RENDER_TYPE_PASS_ALPHA,
- LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
- LLPipeline::RENDER_TYPE_PASS_BUMP,
- LLPipeline::RENDER_TYPE_PASS_POST_BUMP,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
- LLPipeline::RENDER_TYPE_PASS_GLOW,
- LLPipeline::RENDER_TYPE_PASS_GRASS,
- LLPipeline::RENDER_TYPE_PASS_SHINY,
- LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
- LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
- LLPipeline::RENDER_TYPE_AVATAR,
- END_RENDER_TYPES);
-
- renderGeomPostDeferred(*LLViewerCamera::getInstance());
- popRenderTypeMask();
- }
-
- {
- //render highlights, etc.
- renderHighlights();
- mHighlightFaces.clear();
-
- renderDebug();
-
- LLVertexBuffer::unbind();
-
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- // Render debugging beacons.
- gObjectList.renderObjectBeacons();
- gObjectList.resetObjectBeacons();
- }
- }
-
- mScreen.flush();
-
-}
-
-void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
-{
- //construct frustum
- LLVOVolume* volume = drawablep->getVOVolume();
- LLVector3 params = volume->getSpotLightParams();
-
- F32 fov = params.mV[0];
- F32 focus = params.mV[1];
-
- LLVector3 pos = drawablep->getPositionAgent();
- LLQuaternion quat = volume->getRenderRotation();
- LLVector3 scale = volume->getScale();
-
- //get near clip plane
- LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
- at_axis *= quat;
-
- LLVector3 np = pos+at_axis;
- at_axis.normVec();
-
- //get origin that has given fov for plane np, at_axis, and given scale
- F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
-
- LLVector3 origin = np - at_axis*dist;
-
- //matrix from volume space to agent space
- LLMatrix4 light_mat(quat, LLVector4(origin,1.f));
-
- glh::matrix4f light_to_agent((F32*) light_mat.mMatrix);
- glh::matrix4f light_to_screen = glh_get_current_modelview() * light_to_agent;
-
- glh::matrix4f screen_to_light = light_to_screen.inverse();
-
- F32 s = volume->getLightRadius()*1.5f;
- F32 near_clip = dist;
- F32 width = scale.mV[VX];
- F32 height = scale.mV[VY];
- F32 far_clip = s+dist-scale.mV[VZ];
-
- F32 fovy = fov * RAD_TO_DEG;
- F32 aspect = width/height;
-
- glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
- 0.f, 0.5f, 0.f, 0.5f,
- 0.f, 0.f, 0.5f, 0.5f,
- 0.f, 0.f, 0.f, 1.f);
-
- glh::vec3f p1(0, 0, -(near_clip+0.01f));
- glh::vec3f p2(0, 0, -(near_clip+1.f));
-
- glh::vec3f screen_origin(0, 0, 0);
-
- light_to_screen.mult_matrix_vec(p1);
- light_to_screen.mult_matrix_vec(p2);
- light_to_screen.mult_matrix_vec(screen_origin);
-
- glh::vec3f n = p2-p1;
- n.normalize();
-
- F32 proj_range = far_clip - near_clip;
- glh::matrix4f light_proj = gl_perspective(fovy, aspect, near_clip, far_clip);
- screen_to_light = trans * light_proj * screen_to_light;
- shader.uniformMatrix4fv(LLShaderMgr::PROJECTOR_MATRIX, 1, FALSE, screen_to_light.m);
- shader.uniform1f(LLShaderMgr::PROJECTOR_NEAR, near_clip);
- shader.uniform3fv(LLShaderMgr::PROJECTOR_P, 1, p1.v);
- shader.uniform3fv(LLShaderMgr::PROJECTOR_N, 1, n.v);
- shader.uniform3fv(LLShaderMgr::PROJECTOR_ORIGIN, 1, screen_origin.v);
- shader.uniform1f(LLShaderMgr::PROJECTOR_RANGE, proj_range);
- shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIANCE, params.mV[2]);
- S32 s_idx = -1;
-
- for (U32 i = 0; i < 2; i++)
- {
- if (mShadowSpotLight[i] == drawablep)
- {
- s_idx = i;
- }
- }
-
- shader.uniform1i(LLShaderMgr::PROJECTOR_SHADOW_INDEX, s_idx);
-
- if (s_idx >= 0)
- {
- shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f-mSpotLightFade[s_idx]);
- }
- else
- {
- shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f);
- }
-
- {
- LLDrawable* potential = drawablep;
- //determine if this is a good light for casting shadows
- F32 m_pri = volume->getSpotLightPriority();
-
- for (U32 i = 0; i < 2; i++)
- {
- F32 pri = 0.f;
-
- if (mTargetShadowSpotLight[i].notNull())
- {
- pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority();
- }
-
- if (m_pri > pri)
- {
- LLDrawable* temp = mTargetShadowSpotLight[i];
- mTargetShadowSpotLight[i] = potential;
- potential = temp;
- m_pri = pri;
- }
- }
- }
-
- LLViewerTexture* img = volume->getLightTexture();
-
- if (img == NULL)
- {
- img = LLViewerFetchedTexture::sWhiteImagep;
- }
-
- S32 channel = shader.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-
- if (channel > -1)
- {
- if (img)
- {
- gGL.getTexUnit(channel)->bind(img);
-
- F32 lod_range = logf(img->getWidth())/logf(2.f);
-
- shader.uniform1f(LLShaderMgr::PROJECTOR_FOCUS, focus);
- shader.uniform1f(LLShaderMgr::PROJECTOR_LOD, lod_range);
- shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIENT_LOD, llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f));
- }
- }
-
-}
-
-void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
-{
- stop_glerror();
- shader.disableTexture(LLShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
- shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
- shader.disableTexture(LLShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
- shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredScreen.getUsage());
- shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, mDeferredLight.getUsage());
- shader.disableTexture(LLShaderMgr::DIFFUSE_MAP);
- shader.disableTexture(LLShaderMgr::DEFERRED_BLOOM);
-
- for (U32 i = 0; i < 4; i++)
- {
- if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE) > -1)
- {
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
- }
- }
-
- for (U32 i = 4; i < 6; i++)
- {
- if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i) > -1)
- {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
- }
- }
-
- shader.disableTexture(LLShaderMgr::DEFERRED_NOISE);
- shader.disableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC);
-
- S32 channel = shader.disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
- if (channel > -1)
- {
- LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
- if (cube_map)
- {
- cube_map->disable();
- }
- }
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(0)->activate();
- shader.unbind();
-}
-
-inline float sgn(float a)
-{
- if (a > 0.0F) return (1.0F);
- if (a < 0.0F) return (-1.0F);
- return (0.0F);
-}
-
-void LLPipeline::generateWaterReflection(LLCamera& camera_in)
-{
- if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate)
- {
- BOOL skip_avatar_update = FALSE;
- if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
- {
- skip_avatar_update = TRUE;
- }
-
- if (!skip_avatar_update)
- {
- gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
- }
- LLVertexBuffer::unbind();
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
-
- LLCamera camera = camera_in;
- camera.setFar(camera.getFar()*0.87654321f);
- LLPipeline::sReflectionRender = TRUE;
-
- gPipeline.pushRenderTypeMask();
-
- glh::matrix4f projection = glh_get_current_projection();
- glh::matrix4f mat;
-
- stop_glerror();
- LLPlane plane;
-
- F32 height = gAgent.getRegion()->getWaterHeight();
- F32 to_clip = fabsf(camera.getOrigin().mV[2]-height);
- F32 pad = -to_clip*0.05f; //amount to "pad" clip plane by
-
- //plane params
- LLVector3 pnorm;
- F32 pd;
-
- S32 water_clip = 0;
- if (!LLViewerCamera::getInstance()->cameraUnderWater())
- { //camera is above water, clip plane points up
- pnorm.setVec(0,0,1);
- pd = -height;
- plane.setVec(pnorm, pd);
- water_clip = -1;
- }
- else
- { //camera is below water, clip plane points down
- pnorm = LLVector3(0,0,-1);
- pd = height;
- plane.setVec(pnorm, pd);
- water_clip = 1;
- }
-
- if (!LLViewerCamera::getInstance()->cameraUnderWater())
- { //generate planar reflection map
-
- //disable occlusion culling for reflection map for now
- S32 occlusion = LLPipeline::sUseOcclusion;
- LLPipeline::sUseOcclusion = 0;
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- glClearColor(0,0,0,0);
- mWaterRef.bindTarget();
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER0;
- gGL.setColorMask(true, true);
- mWaterRef.clear();
- gGL.setColorMask(true, false);
-
- mWaterRef.getViewport(gGLViewport);
-
- stop_glerror();
-
- gGL.pushMatrix();
-
- mat.set_scale(glh::vec3f(1,1,-1));
- mat.set_translate(glh::vec3f(0,0,height*2.f));
-
- glh::matrix4f current = glh_get_current_modelview();
-
- mat = current * mat;
-
- glh_set_current_modelview(mat);
- gGL.loadMatrix(mat.m);
-
- LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
-
- glh::matrix4f inv_mat = mat.inverse();
-
- glh::vec3f origin(0,0,0);
- inv_mat.mult_matrix_vec(origin);
-
- camera.setOrigin(origin.v);
-
- glCullFace(GL_FRONT);
-
- static LLCullResult ref_result;
-
- if (LLDrawPoolWater::sNeedsReflectionUpdate)
- {
- //initial sky pass (no user clip plane)
- { //mask out everything but the sky
- gPipeline.pushRenderTypeMask();
- gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
- LLPipeline::RENDER_TYPE_WL_SKY,
- LLPipeline::RENDER_TYPE_CLOUDS,
- LLPipeline::END_RENDER_TYPES);
-
- static LLCullResult result;
- updateCull(camera, result);
- stateSort(camera, result);
-
- renderGeom(camera, TRUE);
-
- gPipeline.popRenderTypeMask();
- }
-
- gPipeline.pushRenderTypeMask();
-
- clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
- LLPipeline::RENDER_TYPE_VOIDWATER,
- LLPipeline::RENDER_TYPE_GROUND,
- LLPipeline::RENDER_TYPE_SKY,
- LLPipeline::RENDER_TYPE_CLOUDS,
- LLPipeline::END_RENDER_TYPES);
-
- S32 detail = RenderReflectionDetail;
- if (detail > 0)
- { //mask out selected geometry based on reflection detail
- if (detail < 4)
- {
- clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES);
- if (detail < 3)
- {
- clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
- if (detail < 2)
- {
- clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES);
- }
- }
- }
-
- LLGLUserClipPlane clip_plane(plane, mat, projection);
- LLGLDisable cull(GL_CULL_FACE);
- updateCull(camera, ref_result, -water_clip, &plane);
- stateSort(camera, ref_result);
- }
-
- if (LLDrawPoolWater::sNeedsDistortionUpdate)
- {
- if (RenderReflectionDetail > 0)
- {
- gPipeline.grabReferences(ref_result);
- LLGLUserClipPlane clip_plane(plane, mat, projection);
- renderGeom(camera);
- }
- }
-
- gPipeline.popRenderTypeMask();
- }
- glCullFace(GL_BACK);
- gGL.popMatrix();
- mWaterRef.flush();
- glh_set_current_modelview(current);
- LLPipeline::sUseOcclusion = occlusion;
- }
-
- camera.setOrigin(camera_in.getOrigin());
- //render distortion map
- static BOOL last_update = TRUE;
- if (last_update)
- {
- camera.setFar(camera_in.getFar());
- clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
- LLPipeline::RENDER_TYPE_VOIDWATER,
- LLPipeline::RENDER_TYPE_GROUND,
- END_RENDER_TYPES);
- stop_glerror();
-
- LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? FALSE : TRUE;
-
- if (LLPipeline::sUnderWaterRender)
- {
- clearRenderTypeMask(LLPipeline::RENDER_TYPE_GROUND,
- LLPipeline::RENDER_TYPE_SKY,
- LLPipeline::RENDER_TYPE_CLOUDS,
- LLPipeline::RENDER_TYPE_WL_SKY,
- END_RENDER_TYPES);
- }
- LLViewerCamera::updateFrustumPlanes(camera);
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- LLColor4& col = LLDrawPoolWater::sWaterFogColor;
- glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
- mWaterDis.bindTarget();
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1;
- mWaterDis.getViewport(gGLViewport);
-
- if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate)
- {
- //clip out geometry on the same side of water as the camera
- mat = glh_get_current_modelview();
- LLPlane plane(-pnorm, -(pd+pad));
-
- LLGLUserClipPlane clip_plane(plane, mat, projection);
- static LLCullResult result;
- updateCull(camera, result, water_clip, &plane);
- stateSort(camera, result);
-
- gGL.setColorMask(true, true);
- mWaterDis.clear();
- gGL.setColorMask(true, false);
-
- renderGeom(camera);
-
- }
-
- LLPipeline::sUnderWaterRender = FALSE;
- mWaterDis.flush();
- }
- last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
-
- LLRenderTarget::unbindTarget();
-
- LLPipeline::sReflectionRender = FALSE;
-
- if (!LLRenderTarget::sUseFBO)
- {
- glClear(GL_DEPTH_BUFFER_BIT);
- }
- glClearColor(0.f, 0.f, 0.f, 0.f);
- gViewerWindow->setup3DViewport();
- gPipeline.popRenderTypeMask();
- LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
- LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
- LLPlane npnorm(-pnorm, -pd);
- LLViewerCamera::getInstance()->setUserClipPlane(npnorm);
-
- LLGLState::checkStates();
-
- if (!skip_avatar_update)
- {
- gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
- }
-
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- }
-}
-
-glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up)
-{
- glh::matrix4f ret;
-
- LLVector3 dirN;
- LLVector3 upN;
- LLVector3 lftN;
-
- lftN = dir % up;
- lftN.normVec();
-
- upN = lftN % dir;
- upN.normVec();
-
- dirN = dir;
- dirN.normVec();
-
- ret.m[ 0] = lftN[0];
- ret.m[ 1] = upN[0];
- ret.m[ 2] = -dirN[0];
- ret.m[ 3] = 0.f;
-
- ret.m[ 4] = lftN[1];
- ret.m[ 5] = upN[1];
- ret.m[ 6] = -dirN[1];
- ret.m[ 7] = 0.f;
-
- ret.m[ 8] = lftN[2];
- ret.m[ 9] = upN[2];
- ret.m[10] = -dirN[2];
- ret.m[11] = 0.f;
-
- ret.m[12] = -(lftN*pos);
- ret.m[13] = -(upN*pos);
- ret.m[14] = dirN*pos;
- ret.m[15] = 1.f;
-
- return ret;
-}
-
-glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max)
-{
- glh::matrix4f ret;
- ret.m[ 0] = 2/(max[0]-min[0]);
- ret.m[ 4] = 0;
- ret.m[ 8] = 0;
- ret.m[12] = -(max[0]+min[0])/(max[0]-min[0]);
-
- ret.m[ 1] = 0;
- ret.m[ 5] = 2/(max[1]-min[1]);
- ret.m[ 9] = 0;
- ret.m[13] = -(max[1]+min[1])/(max[1]-min[1]);
-
- ret.m[ 2] = 0;
- ret.m[ 6] = 0;
- ret.m[10] = 2/(max[2]-min[2]);
- ret.m[14] = -(max[2]+min[2])/(max[2]-min[2]);
-
- ret.m[ 3] = 0;
- ret.m[ 7] = 0;
- ret.m[11] = 0;
- ret.m[15] = 1;
-
- return ret;
-}
-
-static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows");
-static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow");
-static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow");
-
-void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion)
-{
- LLFastTimer t(FTM_SHADOW_RENDER);
-
- //clip out geometry on the same side of water as the camera
- S32 occlude = LLPipeline::sUseOcclusion;
- if (!use_occlusion)
- {
- LLPipeline::sUseOcclusion = 0;
- }
- LLPipeline::sShadowRender = TRUE;
-
- U32 types[] = {
- LLRenderPass::PASS_SIMPLE,
- LLRenderPass::PASS_FULLBRIGHT,
- LLRenderPass::PASS_SHINY,
- LLRenderPass::PASS_BUMP,
- LLRenderPass::PASS_FULLBRIGHT_SHINY
- };
-
- LLGLEnable cull(GL_CULL_FACE);
-
- if (use_shader)
- {
- gDeferredShadowProgram.bind();
- }
-
- updateCull(shadow_cam, result);
- stateSort(shadow_cam, result);
-
- //generate shadow map
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadMatrix(proj.m);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- gGL.loadMatrix(gGLModelView);
-
- stop_glerror();
- gGLLastMatrix = NULL;
-
- {
- //LLGLDepthTest depth(GL_TRUE);
- //glClear(GL_DEPTH_BUFFER_BIT);
- }
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- stop_glerror();
-
- //glCullFace(GL_FRONT);
-
- LLVertexBuffer::unbind();
-
- {
- if (!use_shader)
- { //occlusion program is general purpose depth-only no-textures
- gOcclusionProgram.bind();
- }
-
- gGL.diffuseColor4f(1,1,1,1);
- gGL.setColorMask(false, false);
-
- LLFastTimer ftm(FTM_SHADOW_SIMPLE);
- gGL.getTexUnit(0)->disable();
- for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i)
- {
- renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
- }
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- if (!use_shader)
- {
- gOcclusionProgram.unbind();
- }
- }
-
- if (use_shader)
- {
- gDeferredShadowProgram.unbind();
- renderGeomShadow(shadow_cam);
- gDeferredShadowProgram.bind();
- }
- else
- {
- renderGeomShadow(shadow_cam);
- }
-
- {
- LLFastTimer ftm(FTM_SHADOW_ALPHA);
- gDeferredShadowAlphaMaskProgram.bind();
- gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f);
-
- U32 mask = LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_TEXCOORD0 |
- LLVertexBuffer::MAP_COLOR |
- LLVertexBuffer::MAP_TEXTURE_INDEX;
-
- renderObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE);
- renderObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE);
- renderObjects(LLRenderPass::PASS_ALPHA, mask, TRUE, TRUE);
- gDeferredTreeShadowProgram.bind();
- gDeferredTreeShadowProgram.setMinimumAlpha(0.598f);
- renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
- }
-
- //glCullFace(GL_BACK);
-
- gDeferredShadowProgram.bind();
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
- doOcclusion(shadow_cam);
-
- if (use_shader)
- {
- gDeferredShadowProgram.unbind();
- }
-
- gGL.setColorMask(true, true);
-
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
- gGLLastMatrix = NULL;
-
- LLPipeline::sUseOcclusion = occlude;
- LLPipeline::sShadowRender = FALSE;
-}
-
-static LLFastTimer::DeclareTimer FTM_VISIBLE_CLOUD("Visible Cloud");
-BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir)
-{
- LLFastTimer t(FTM_VISIBLE_CLOUD);
- //get point cloud of intersection of frust and min, max
-
- if (getVisibleExtents(camera, min, max))
- {
- return FALSE;
- }
-
- //get set of planes on bounding box
- LLPlane bp[] = {
- LLPlane(min, LLVector3(-1,0,0)),
- LLPlane(min, LLVector3(0,-1,0)),
- LLPlane(min, LLVector3(0,0,-1)),
- LLPlane(max, LLVector3(1,0,0)),
- LLPlane(max, LLVector3(0,1,0)),
- LLPlane(max, LLVector3(0,0,1))};
-
- //potential points
- std::vector<LLVector3> pp;
-
- //add corners of AABB
- pp.push_back(LLVector3(min.mV[0], min.mV[1], min.mV[2]));
- pp.push_back(LLVector3(max.mV[0], min.mV[1], min.mV[2]));
- pp.push_back(LLVector3(min.mV[0], max.mV[1], min.mV[2]));
- pp.push_back(LLVector3(max.mV[0], max.mV[1], min.mV[2]));
- pp.push_back(LLVector3(min.mV[0], min.mV[1], max.mV[2]));
- pp.push_back(LLVector3(max.mV[0], min.mV[1], max.mV[2]));
- pp.push_back(LLVector3(min.mV[0], max.mV[1], max.mV[2]));
- pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2]));
-
- //add corners of camera frustum
- for (U32 i = 0; i < 8; i++)
- {
- pp.push_back(camera.mAgentFrustum[i]);
- }
-
-
- //bounding box line segments
- U32 bs[] =
- {
- 0,1,
- 1,3,
- 3,2,
- 2,0,
-
- 4,5,
- 5,7,
- 7,6,
- 6,4,
-
- 0,4,
- 1,5,
- 3,7,
- 2,6
- };
-
- for (U32 i = 0; i < 12; i++)
- { //for each line segment in bounding box
- for (U32 j = 0; j < 6; j++)
- { //for each plane in camera frustum
- const LLPlane& cp = camera.getAgentPlane(j);
- const LLVector3& v1 = pp[bs[i*2+0]];
- const LLVector3& v2 = pp[bs[i*2+1]];
- LLVector3 n;
- cp.getVector3(n);
-
- LLVector3 line = v1-v2;
-
- F32 d1 = line*n;
- F32 d2 = -cp.dist(v2);
-
- F32 t = d2/d1;
-
- if (t > 0.f && t < 1.f)
- {
- LLVector3 intersect = v2+line*t;
- pp.push_back(intersect);
- }
- }
- }
-
- //camera frustum line segments
- const U32 fs[] =
- {
- 0,1,
- 1,2,
- 2,3,
- 3,0,
-
- 4,5,
- 5,6,
- 6,7,
- 7,4,
-
- 0,4,
- 1,5,
- 2,6,
- 3,7
- };
-
- LLVector3 center = (max+min)*0.5f;
- LLVector3 size = (max-min)*0.5f;
-
- for (U32 i = 0; i < 12; i++)
- {
- for (U32 j = 0; j < 6; ++j)
- {
- const LLVector3& v1 = pp[fs[i*2+0]+8];
- const LLVector3& v2 = pp[fs[i*2+1]+8];
- const LLPlane& cp = bp[j];
- LLVector3 n;
- cp.getVector3(n);
-
- LLVector3 line = v1-v2;
-
- F32 d1 = line*n;
- F32 d2 = -cp.dist(v2);
-
- F32 t = d2/d1;
-
- if (t > 0.f && t < 1.f)
- {
- LLVector3 intersect = v2+line*t;
- pp.push_back(intersect);
- }
- }
- }
-
- LLVector3 ext[] = { min-LLVector3(0.05f,0.05f,0.05f),
- max+LLVector3(0.05f,0.05f,0.05f) };
-
- for (U32 i = 0; i < pp.size(); ++i)
- {
- bool found = true;
-
- const F32* p = pp[i].mV;
-
- for (U32 j = 0; j < 3; ++j)
- {
- if (p[j] < ext[0].mV[j] ||
- p[j] > ext[1].mV[j])
- {
- found = false;
- break;
- }
- }
-
- for (U32 j = 0; j < 6; ++j)
- {
- const LLPlane& cp = camera.getAgentPlane(j);
- F32 dist = cp.dist(pp[i]);
- if (dist > 0.05f) //point is above some plane, not contained
- {
- found = false;
- break;
- }
- }
-
- if (found)
- {
- fp.push_back(pp[i]);
- }
- }
-
- if (fp.empty())
- {
- return FALSE;
- }
-
- return TRUE;
-}
-
-void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade)
-{
- if (obj && obj->getVolume())
- {
- for (LLViewerObject::child_list_t::const_iterator iter = obj->getChildren().begin(); iter != obj->getChildren().end(); ++iter)
- {
- renderHighlight(*iter, fade);
- }
-
- LLDrawable* drawable = obj->mDrawable;
- if (drawable)
- {
- for (S32 i = 0; i < drawable->getNumFaces(); ++i)
- {
- LLFace* face = drawable->getFace(i);
- if (face)
- {
- face->renderSelected(LLViewerTexture::sNullImagep, LLColor4(1,1,1,fade));
- }
- }
- }
- }
-}
-
-void LLPipeline::generateHighlight(LLCamera& camera)
-{
- //render highlighted object as white into offscreen render target
- if (mHighlightObject.notNull())
- {
- mHighlightSet.insert(HighlightItem(mHighlightObject));
- }
-
- if (!mHighlightSet.empty())
- {
- F32 transition = gFrameIntervalSeconds/RenderHighlightFadeTime;
-
- LLGLDisable test(GL_ALPHA_TEST);
- LLGLDepthTest depth(GL_FALSE);
- mHighlight.bindTarget();
- disableLights();
- gGL.setColorMask(true, true);
- mHighlight.clear();
-
- gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
- for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); )
- {
- std::set<HighlightItem>::iterator cur_iter = iter++;
-
- if (cur_iter->mItem.isNull())
- {
- mHighlightSet.erase(cur_iter);
- continue;
- }
-
- if (cur_iter->mItem == mHighlightObject)
- {
- cur_iter->incrFade(transition);
- }
- else
- {
- cur_iter->incrFade(-transition);
- if (cur_iter->mFade <= 0.f)
- {
- mHighlightSet.erase(cur_iter);
- continue;
- }
- }
-
- renderHighlight(cur_iter->mItem->getVObj(), cur_iter->mFade);
- }
-
- mHighlight.flush();
- gGL.setColorMask(true, false);
- gViewerWindow->setup3DViewport();
- }
-}
-
-
-void LLPipeline::generateSunShadow(LLCamera& camera)
-{
- if (!sRenderDeferred || RenderShadowDetail <= 0)
- {
- return;
- }
-
- BOOL skip_avatar_update = FALSE;
- if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
- {
-
- skip_avatar_update = TRUE;
- }
-
- if (!skip_avatar_update)
- {
- gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
- }
-
- F64 last_modelview[16];
- F64 last_projection[16];
- for (U32 i = 0; i < 16; i++)
- { //store last_modelview of world camera
- last_modelview[i] = gGLLastModelView[i];
- last_projection[i] = gGLLastProjection[i];
- }
-
- pushRenderTypeMask();
- andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE,
- LLPipeline::RENDER_TYPE_ALPHA,
- LLPipeline::RENDER_TYPE_GRASS,
- LLPipeline::RENDER_TYPE_FULLBRIGHT,
- LLPipeline::RENDER_TYPE_BUMP,
- LLPipeline::RENDER_TYPE_VOLUME,
- LLPipeline::RENDER_TYPE_AVATAR,
- LLPipeline::RENDER_TYPE_TREE,
- LLPipeline::RENDER_TYPE_TERRAIN,
- LLPipeline::RENDER_TYPE_WATER,
- LLPipeline::RENDER_TYPE_VOIDWATER,
- LLPipeline::RENDER_TYPE_PASS_ALPHA,
- LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
- LLPipeline::RENDER_TYPE_PASS_GRASS,
- LLPipeline::RENDER_TYPE_PASS_SIMPLE,
- LLPipeline::RENDER_TYPE_PASS_BUMP,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
- LLPipeline::RENDER_TYPE_PASS_SHINY,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
- END_RENDER_TYPES);
-
- gGL.setColorMask(false, false);
-
- //get sun view matrix
-
- //store current projection/modelview matrix
- glh::matrix4f saved_proj = glh_get_current_projection();
- glh::matrix4f saved_view = glh_get_current_modelview();
- glh::matrix4f inv_view = saved_view.inverse();
-
- glh::matrix4f view[6];
- glh::matrix4f proj[6];
-
- //clip contains parallel split distances for 3 splits
- LLVector3 clip = RenderShadowClipPlanes;
-
- //F32 slope_threshold = gSavedSettings.getF32("RenderShadowSlopeThreshold");
-
- //far clip on last split is minimum of camera view distance and 128
- mSunClipPlanes = LLVector4(clip, clip.mV[2] * clip.mV[2]/clip.mV[1]);
-
- clip = RenderShadowOrthoClipPlanes;
- mSunOrthoClipPlanes = LLVector4(clip, clip.mV[2]*clip.mV[2]/clip.mV[1]);
-
- //currently used for amount to extrude frusta corners for constructing shadow frusta
- LLVector3 n = RenderShadowNearDist;
- //F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
-
- //put together a universal "near clip" plane for shadow frusta
- LLPlane shadow_near_clip;
- {
- LLVector3 p = gAgent.getPositionAgent();
- p += mSunDir * RenderFarClip*2.f;
- shadow_near_clip.setVec(p, mSunDir);
- }
-
- LLVector3 lightDir = -mSunDir;
- lightDir.normVec();
-
- glh::vec3f light_dir(lightDir.mV);
-
- //create light space camera matrix
-
- LLVector3 at = lightDir;
-
- LLVector3 up = camera.getAtAxis();
-
- if (fabsf(up*lightDir) > 0.75f)
- {
- up = camera.getUpAxis();
- }
-
- /*LLVector3 left = up%at;
- up = at%left;*/
-
- up.normVec();
- at.normVec();
-
-
- LLCamera main_camera = camera;
-
- F32 near_clip = 0.f;
- {
- //get visible point cloud
- std::vector<LLVector3> fp;
-
- main_camera.calcAgentFrustumPlanes(main_camera.mAgentFrustum);
-
- LLVector3 min,max;
- getVisiblePointCloud(main_camera,min,max,fp);
-
- if (fp.empty())
- {
- if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
- {
- mShadowCamera[0] = main_camera;
- mShadowExtents[0][0] = min;
- mShadowExtents[0][1] = max;
-
- mShadowFrustPoints[0].clear();
- mShadowFrustPoints[1].clear();
- mShadowFrustPoints[2].clear();
- mShadowFrustPoints[3].clear();
- }
- popRenderTypeMask();
-
- if (!skip_avatar_update)
- {
- gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
- }
-
- return;
- }
-
- //get good split distances for frustum
- for (U32 i = 0; i < fp.size(); ++i)
- {
- glh::vec3f v(fp[i].mV);
- saved_view.mult_matrix_vec(v);
- fp[i].setVec(v.v);
- }
-
- min = fp[0];
- max = fp[0];
-
- //get camera space bounding box
- for (U32 i = 1; i < fp.size(); ++i)
- {
- update_min_max(min, max, fp[i]);
- }
-
- near_clip = -max.mV[2];
- F32 far_clip = -min.mV[2]*2.f;
-
- //far_clip = llmin(far_clip, 128.f);
- far_clip = llmin(far_clip, camera.getFar());
-
- F32 range = far_clip-near_clip;
-
- LLVector3 split_exp = RenderShadowSplitExponent;
-
- F32 da = 1.f-llmax( fabsf(lightDir*up), fabsf(lightDir*camera.getLeftAxis()) );
-
- da = powf(da, split_exp.mV[2]);
-
-
- F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da;
-
-
- for (U32 i = 0; i < 4; ++i)
- {
- F32 x = (F32)(i+1)/4.f;
- x = powf(x, sxp);
- mSunClipPlanes.mV[i] = near_clip+range*x;
- }
- }
-
- // convenience array of 4 near clip plane distances
- F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
-
-
- if (mSunDiffuse == LLColor4::black)
- { //sun diffuse is totally black, shadows don't matter
- LLGLDepthTest depth(GL_TRUE);
-
- for (S32 j = 0; j < 4; j++)
- {
- mShadow[j].bindTarget();
- mShadow[j].clear();
- mShadow[j].flush();
- }
- }
- else
- {
- for (S32 j = 0; j < 4; j++)
- {
- if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
- {
- mShadowFrustPoints[j].clear();
- }
-
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+j;
-
- //restore render matrices
- glh_set_current_modelview(saved_view);
- glh_set_current_projection(saved_proj);
-
- LLVector3 eye = camera.getOrigin();
-
- //camera used for shadow cull/render
- LLCamera shadow_cam;
-
- //create world space camera frustum for this split
- shadow_cam = camera;
- shadow_cam.setFar(16.f);
-
- LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
-
- LLVector3* frust = shadow_cam.mAgentFrustum;
-
- LLVector3 pn = shadow_cam.getAtAxis();
-
- LLVector3 min, max;
-
- //construct 8 corners of split frustum section
- for (U32 i = 0; i < 4; i++)
- {
- LLVector3 delta = frust[i+4]-eye;
- delta += (frust[i+4]-frust[(i+2)%4+4])*0.05f;
- delta.normVec();
- F32 dp = delta*pn;
- frust[i] = eye + (delta*dist[j]*0.95f)/dp;
- frust[i+4] = eye + (delta*dist[j+1]*1.05f)/dp;
- }
-
- shadow_cam.calcAgentFrustumPlanes(frust);
- shadow_cam.mFrustumCornerDist = 0.f;
-
- if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
- {
- mShadowCamera[j] = shadow_cam;
- }
-
- std::vector<LLVector3> fp;
-
- if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir))
- {
- //no possible shadow receivers
- if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
- {
- mShadowExtents[j][0] = LLVector3();
- mShadowExtents[j][1] = LLVector3();
- mShadowCamera[j+4] = shadow_cam;
- }
-
- mShadow[j].bindTarget();
- {
- LLGLDepthTest depth(GL_TRUE);
- mShadow[j].clear();
- }
- mShadow[j].flush();
-
- mShadowError.mV[j] = 0.f;
- mShadowFOV.mV[j] = 0.f;
-
- continue;
- }
-
- if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
- {
- mShadowExtents[j][0] = min;
- mShadowExtents[j][1] = max;
- mShadowFrustPoints[j] = fp;
- }
-
-
- //find a good origin for shadow projection
- LLVector3 origin;
-
- //get a temporary view projection
- view[j] = look(camera.getOrigin(), lightDir, -up);
-
- std::vector<LLVector3> wpf;
-
- for (U32 i = 0; i < fp.size(); i++)
- {
- glh::vec3f p = glh::vec3f(fp[i].mV);
- view[j].mult_matrix_vec(p);
- wpf.push_back(LLVector3(p.v));
- }
-
- min = wpf[0];
- max = wpf[0];
-
- for (U32 i = 0; i < fp.size(); ++i)
- { //get AABB in camera space
- update_min_max(min, max, wpf[i]);
- }
-
- // Construct a perspective transform with perspective along y-axis that contains
- // points in wpf
- //Known:
- // - far clip plane
- // - near clip plane
- // - points in frustum
- //Find:
- // - origin
-
- //get some "interesting" points of reference
- LLVector3 center = (min+max)*0.5f;
- LLVector3 size = (max-min)*0.5f;
- LLVector3 near_center = center;
- near_center.mV[1] += size.mV[1]*2.f;
-
-
- //put all points in wpf in quadrant 0, reletive to center of min/max
- //get the best fit line using least squares
- F32 bfm = 0.f;
- F32 bfb = 0.f;
-
- for (U32 i = 0; i < wpf.size(); ++i)
- {
- wpf[i] -= center;
- wpf[i].mV[0] = fabsf(wpf[i].mV[0]);
- wpf[i].mV[2] = fabsf(wpf[i].mV[2]);
- }
-
- if (!wpf.empty())
- {
- F32 sx = 0.f;
- F32 sx2 = 0.f;
- F32 sy = 0.f;
- F32 sxy = 0.f;
-
- for (U32 i = 0; i < wpf.size(); ++i)
- {
- sx += wpf[i].mV[0];
- sx2 += wpf[i].mV[0]*wpf[i].mV[0];
- sy += wpf[i].mV[1];
- sxy += wpf[i].mV[0]*wpf[i].mV[1];
- }
-
- bfm = (sy*sx-wpf.size()*sxy)/(sx*sx-wpf.size()*sx2);
- bfb = (sx*sxy-sy*sx2)/(sx*sx-bfm*sx2);
- }
-
- {
- // best fit line is y=bfm*x+bfb
-
- //find point that is furthest to the right of line
- F32 off_x = -1.f;
- LLVector3 lp;
-
- for (U32 i = 0; i < wpf.size(); ++i)
- {
- //y = bfm*x+bfb
- //x = (y-bfb)/bfm
- F32 lx = (wpf[i].mV[1]-bfb)/bfm;
-
- lx = wpf[i].mV[0]-lx;
-
- if (off_x < lx)
- {
- off_x = lx;
- lp = wpf[i];
- }
- }
-
- //get line with slope bfm through lp
- // bfb = y-bfm*x
- bfb = lp.mV[1]-bfm*lp.mV[0];
-
- //calculate error
- mShadowError.mV[j] = 0.f;
-
- for (U32 i = 0; i < wpf.size(); ++i)
- {
- F32 lx = (wpf[i].mV[1]-bfb)/bfm;
- mShadowError.mV[j] += fabsf(wpf[i].mV[0]-lx);
- }
-
- mShadowError.mV[j] /= wpf.size();
- mShadowError.mV[j] /= size.mV[0];
-
- if (mShadowError.mV[j] > RenderShadowErrorCutoff)
- { //just use ortho projection
- mShadowFOV.mV[j] = -1.f;
- origin.clearVec();
- proj[j] = gl_ortho(min.mV[0], max.mV[0],
- min.mV[1], max.mV[1],
- -max.mV[2], -min.mV[2]);
- }
- else
- {
- //origin is where line x = 0;
- origin.setVec(0,bfb,0);
-
- F32 fovz = 1.f;
- F32 fovx = 1.f;
-
- LLVector3 zp;
- LLVector3 xp;
-
- for (U32 i = 0; i < wpf.size(); ++i)
- {
- LLVector3 atz = wpf[i]-origin;
- atz.mV[0] = 0.f;
- atz.normVec();
- if (fovz > -atz.mV[1])
- {
- zp = wpf[i];
- fovz = -atz.mV[1];
- }
-
- LLVector3 atx = wpf[i]-origin;
- atx.mV[2] = 0.f;
- atx.normVec();
- if (fovx > -atx.mV[1])
- {
- fovx = -atx.mV[1];
- xp = wpf[i];
- }
- }
-
- fovx = acos(fovx);
- fovz = acos(fovz);
-
- F32 cutoff = llmin((F32) RenderShadowFOVCutoff, 1.4f);
-
- mShadowFOV.mV[j] = fovx;
-
- if (fovx < cutoff && fovz > cutoff)
- {
- //x is a good fit, but z is too big, move away from zp enough so that fovz matches cutoff
- F32 d = zp.mV[2]/tan(cutoff);
- F32 ny = zp.mV[1] + fabsf(d);
-
- origin.mV[1] = ny;
-
- fovz = 1.f;
- fovx = 1.f;
-
- for (U32 i = 0; i < wpf.size(); ++i)
- {
- LLVector3 atz = wpf[i]-origin;
- atz.mV[0] = 0.f;
- atz.normVec();
- fovz = llmin(fovz, -atz.mV[1]);
-
- LLVector3 atx = wpf[i]-origin;
- atx.mV[2] = 0.f;
- atx.normVec();
- fovx = llmin(fovx, -atx.mV[1]);
- }
-
- fovx = acos(fovx);
- fovz = acos(fovz);
-
- mShadowFOV.mV[j] = cutoff;
- }
-
-
- origin += center;
-
- F32 ynear = -(max.mV[1]-origin.mV[1]);
- F32 yfar = -(min.mV[1]-origin.mV[1]);
-
- if (ynear < 0.1f) //keep a sensible near clip plane
- {
- F32 diff = 0.1f-ynear;
- origin.mV[1] += diff;
- ynear += diff;
- yfar += diff;
- }
-
- if (fovx > cutoff)
- { //just use ortho projection
- origin.clearVec();
- mShadowError.mV[j] = -1.f;
- proj[j] = gl_ortho(min.mV[0], max.mV[0],
- min.mV[1], max.mV[1],
- -max.mV[2], -min.mV[2]);
- }
- else
- {
- //get perspective projection
- view[j] = view[j].inverse();
-
- glh::vec3f origin_agent(origin.mV);
-
- //translate view to origin
- view[j].mult_matrix_vec(origin_agent);
-
- eye = LLVector3(origin_agent.v);
-
- if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
- {
- mShadowFrustOrigin[j] = eye;
- }
-
- view[j] = look(LLVector3(origin_agent.v), lightDir, -up);
-
- F32 fx = 1.f/tanf(fovx);
- F32 fz = 1.f/tanf(fovz);
-
- proj[j] = glh::matrix4f(-fx, 0, 0, 0,
- 0, (yfar+ynear)/(ynear-yfar), 0, (2.f*yfar*ynear)/(ynear-yfar),
- 0, 0, -fz, 0,
- 0, -1.f, 0, 0);
- }
- }
- }
-
- //shadow_cam.setFar(128.f);
- shadow_cam.setOriginAndLookAt(eye, up, center);
-
- shadow_cam.setOrigin(0,0,0);
-
- glh_set_current_modelview(view[j]);
- glh_set_current_projection(proj[j]);
-
- LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
-
- //shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR);
- shadow_cam.getAgentPlane(LLCamera::AGENT_PLANE_NEAR).set(shadow_near_clip);
-
- //translate and scale to from [-1, 1] to [0, 1]
- glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
- 0.f, 0.5f, 0.f, 0.5f,
- 0.f, 0.f, 0.5f, 0.5f,
- 0.f, 0.f, 0.f, 1.f);
-
- glh_set_current_modelview(view[j]);
- glh_set_current_projection(proj[j]);
-
- for (U32 i = 0; i < 16; i++)
- {
- gGLLastModelView[i] = mShadowModelview[j].m[i];
- gGLLastProjection[i] = mShadowProjection[j].m[i];
- }
-
- mShadowModelview[j] = view[j];
- mShadowProjection[j] = proj[j];
-
-
- mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view;
-
- stop_glerror();
-
- mShadow[j].bindTarget();
- mShadow[j].getViewport(gGLViewport);
- mShadow[j].clear();
-
- {
- static LLCullResult result[4];
-
- //LLGLEnable enable(GL_DEPTH_CLAMP_NV);
- renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE);
- }
-
- mShadow[j].flush();
-
- if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
- {
- LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
- mShadowCamera[j+4] = shadow_cam;
- }
- }
- }
-
-
- //hack to disable projector shadows
- bool gen_shadow = RenderShadowDetail > 1;
-
- if (gen_shadow)
- {
- F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f);
-
- //update shadow targets
- for (U32 i = 0; i < 2; i++)
- { //for each current shadow
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW4+i;
-
- if (mShadowSpotLight[i].notNull() &&
- (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
- mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
- { //keep this spotlight
- mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
- }
- else
- { //fade out this light
- mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
-
- if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
- { //faded out, grab one of the pending spots (whichever one isn't already taken)
- if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
- {
- mShadowSpotLight[i] = mTargetShadowSpotLight[0];
- }
- else
- {
- mShadowSpotLight[i] = mTargetShadowSpotLight[1];
- }
- }
- }
- }
-
- for (S32 i = 0; i < 2; i++)
- {
- glh_set_current_modelview(saved_view);
- glh_set_current_projection(saved_proj);
-
- if (mShadowSpotLight[i].isNull())
- {
- continue;
- }
-
- LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
-
- if (!volume)
- {
- mShadowSpotLight[i] = NULL;
- continue;
- }
-
- LLDrawable* drawable = mShadowSpotLight[i];
-
- LLVector3 params = volume->getSpotLightParams();
- F32 fov = params.mV[0];
-
- //get agent->light space matrix (modelview)
- LLVector3 center = drawable->getPositionAgent();
- LLQuaternion quat = volume->getRenderRotation();
-
- //get near clip plane
- LLVector3 scale = volume->getScale();
- LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
- at_axis *= quat;
-
- LLVector3 np = center+at_axis;
- at_axis.normVec();
-
- //get origin that has given fov for plane np, at_axis, and given scale
- F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
-
- LLVector3 origin = np - at_axis*dist;
-
- LLMatrix4 mat(quat, LLVector4(origin, 1.f));
-
- view[i+4] = glh::matrix4f((F32*) mat.mMatrix);
-
- view[i+4] = view[i+4].inverse();
-
- //get perspective matrix
- F32 near_clip = dist+0.01f;
- F32 width = scale.mV[VX];
- F32 height = scale.mV[VY];
- F32 far_clip = dist+volume->getLightRadius()*1.5f;
-
- F32 fovy = fov * RAD_TO_DEG;
- F32 aspect = width/height;
-
- proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip);
-
- //translate and scale to from [-1, 1] to [0, 1]
- glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
- 0.f, 0.5f, 0.f, 0.5f,
- 0.f, 0.f, 0.5f, 0.5f,
- 0.f, 0.f, 0.f, 1.f);
-
- glh_set_current_modelview(view[i+4]);
- glh_set_current_projection(proj[i+4]);
-
- mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view;
-
- for (U32 j = 0; j < 16; j++)
- {
- gGLLastModelView[j] = mShadowModelview[i+4].m[j];
- gGLLastProjection[j] = mShadowProjection[i+4].m[j];
- }
-
- mShadowModelview[i+4] = view[i+4];
- mShadowProjection[i+4] = proj[i+4];
-
- LLCamera shadow_cam = camera;
- shadow_cam.setFar(far_clip);
- shadow_cam.setOrigin(origin);
-
- LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
-
- stop_glerror();
-
- mShadow[i+4].bindTarget();
- mShadow[i+4].getViewport(gGLViewport);
- mShadow[i+4].clear();
-
- static LLCullResult result[2];
-
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4;
-
- renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE);
-
- mShadow[i+4].flush();
- }
- }
- else
- { //no spotlight shadows
- mShadowSpotLight[0] = mShadowSpotLight[1] = NULL;
- }
-
-
- if (!CameraOffset)
- {
- glh_set_current_modelview(saved_view);
- glh_set_current_projection(saved_proj);
- }
- else
- {
- glh_set_current_modelview(view[1]);
- glh_set_current_projection(proj[1]);
- gGL.loadMatrix(view[1].m);
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.loadMatrix(proj[1].m);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- }
- gGL.setColorMask(true, false);
-
- for (U32 i = 0; i < 16; i++)
- {
- gGLLastModelView[i] = last_modelview[i];
- gGLLastProjection[i] = last_projection[i];
- }
-
- popRenderTypeMask();
-
- if (!skip_avatar_update)
- {
- gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
- }
-}
-
-void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture)
-{
- for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
- {
- LLSpatialGroup* group = *i;
- if (!group->isDead() &&
- (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) &&
- gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
- group->mDrawMap.find(type) != group->mDrawMap.end())
- {
- pass->renderGroup(group,type,mask,texture);
- }
- }
-}
-
-void LLPipeline::generateImpostor(LLVOAvatar* avatar)
-{
- LLMemType mt_gi(LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR);
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
-
- static LLCullResult result;
- result.clear();
- grabReferences(result);
-
- if (!avatar || !avatar->mDrawable)
- {
- return;
- }
-
- assertInitialized();
-
- bool muted = avatar->isVisuallyMuted();
-
- pushRenderTypeMask();
-
- if (muted)
- {
- andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
- }
- else
- {
- andRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME,
- LLPipeline::RENDER_TYPE_AVATAR,
- LLPipeline::RENDER_TYPE_BUMP,
- LLPipeline::RENDER_TYPE_GRASS,
- LLPipeline::RENDER_TYPE_SIMPLE,
- LLPipeline::RENDER_TYPE_FULLBRIGHT,
- LLPipeline::RENDER_TYPE_ALPHA,
- LLPipeline::RENDER_TYPE_INVISIBLE,
- LLPipeline::RENDER_TYPE_PASS_SIMPLE,
- LLPipeline::RENDER_TYPE_PASS_ALPHA,
- LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
- LLPipeline::RENDER_TYPE_PASS_SHINY,
- LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
- LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
- END_RENDER_TYPES);
- }
-
- S32 occlusion = sUseOcclusion;
- sUseOcclusion = 0;
- sReflectionRender = sRenderDeferred ? FALSE : TRUE;
- sShadowRender = TRUE;
- sImpostorRender = TRUE;
-
- LLViewerCamera* viewer_camera = LLViewerCamera::getInstance();
- markVisible(avatar->mDrawable, *viewer_camera);
- LLVOAvatar::sUseImpostors = FALSE;
-
- LLVOAvatar::attachment_map_t::iterator iter;
- for (iter = avatar->mAttachmentPoints.begin();
- iter != avatar->mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment *attachment = iter->second;
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- if (LLViewerObject* attached_object = (*attachment_iter))
- {
- markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
- }
- }
- }
-
- stateSort(*LLViewerCamera::getInstance(), result);
-
- const LLVector4a* ext = avatar->mDrawable->getSpatialExtents();
- LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset());
-
- LLCamera camera = *viewer_camera;
-
- camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis());
-
- LLVector2 tdim;
-
-
- LLVector4a half_height;
- half_height.setSub(ext[1], ext[0]);
- half_height.mul(0.5f);
-
- LLVector4a left;
- left.load3(camera.getLeftAxis().mV);
- left.mul(left);
- left.normalize3fast();
-
- LLVector4a up;
- up.load3(camera.getUpAxis().mV);
- up.mul(up);
- up.normalize3fast();
-
- tdim.mV[0] = fabsf(half_height.dot3(left).getF32());
- tdim.mV[1] = fabsf(half_height.dot3(up).getF32());
-
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
-
- F32 distance = (pos-camera.getOrigin()).length();
- F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG;
- F32 aspect = tdim.mV[0]/tdim.mV[1];
- glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f);
- glh_set_current_projection(persp);
- gGL.loadMatrix(persp.m);
-
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- glh::matrix4f mat;
- camera.getOpenGLTransform(mat.m);
-
- mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat;
-
- gGL.loadMatrix(mat.m);
- glh_set_current_modelview(mat);
-
- glClearColor(0.0f,0.0f,0.0f,0.0f);
- gGL.setColorMask(true, true);
-
- // get the number of pixels per angle
- F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView());
-
- //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing)
- U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512);
- U32 resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512);
-
- if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() ||
- resY != avatar->mImpostor.getHeight())
- {
- avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE);
-
- if (LLPipeline::sRenderDeferred)
- {
- addDeferredAttachments(avatar->mImpostor);
- }
-
- gGL.getTexUnit(0)->bind(&avatar->mImpostor);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
-
- avatar->mImpostor.bindTarget();
-
- if (LLPipeline::sRenderDeferred)
- {
- avatar->mImpostor.clear();
- renderGeomDeferred(camera);
- renderGeomPostDeferred(camera);
- }
- else
- {
- LLGLEnable scissor(GL_SCISSOR_TEST);
- glScissor(0, 0, resX, resY);
- avatar->mImpostor.clear();
- renderGeom(camera);
- }
-
- { //create alpha mask based on depth buffer (grey out if muted)
- if (LLPipeline::sRenderDeferred)
- {
- GLuint buff = GL_COLOR_ATTACHMENT0;
- glDrawBuffersARB(1, &buff);
- }
-
- LLGLDisable blend(GL_BLEND);
-
- if (muted)
- {
- gGL.setColorMask(true, true);
- }
- else
- {
- gGL.setColorMask(false, true);
- }
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER);
-
- gGL.flush();
-
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
-
- static const F32 clip_plane = 0.99999f;
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gUIProgram.bind();
- }
-
- gGL.color4ub(64,64,64,255);
- gGL.begin(LLRender::QUADS);
- gGL.vertex3f(-1, -1, clip_plane);
- gGL.vertex3f(1, -1, clip_plane);
- gGL.vertex3f(1, 1, clip_plane);
- gGL.vertex3f(-1, 1, clip_plane);
- gGL.end();
- gGL.flush();
-
- if (LLGLSLShader::sNoFixedFunction)
- {
- gUIProgram.unbind();
- }
-
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
- }
-
- avatar->mImpostor.flush();
-
- avatar->setImpostorDim(tdim);
-
- LLVOAvatar::sUseImpostors = TRUE;
- sUseOcclusion = occlusion;
- sReflectionRender = FALSE;
- sImpostorRender = FALSE;
- sShadowRender = FALSE;
- popRenderTypeMask();
-
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
-
- avatar->mNeedsImpostorUpdate = FALSE;
- avatar->cacheImpostorValues();
-
- LLVertexBuffer::unbind();
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
-}
-
-BOOL LLPipeline::hasRenderBatches(const U32 type) const
-{
- return sCull->getRenderMapSize(type) > 0;
-}
-
-LLCullResult::drawinfo_list_t::iterator LLPipeline::beginRenderMap(U32 type)
-{
- return sCull->beginRenderMap(type);
-}
-
-LLCullResult::drawinfo_list_t::iterator LLPipeline::endRenderMap(U32 type)
-{
- return sCull->endRenderMap(type);
-}
-
-LLCullResult::sg_list_t::iterator LLPipeline::beginAlphaGroups()
-{
- return sCull->beginAlphaGroups();
-}
-
-LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups()
-{
- return sCull->endAlphaGroups();
-}
-
-BOOL LLPipeline::hasRenderType(const U32 type) const
-{
- // STORM-365 : LLViewerJointAttachment::setAttachmentVisibility() is setting type to 0 to actually mean "do not render"
- // We then need to test that value here and return FALSE to prevent attachment to render (in mouselook for instance)
- // TODO: reintroduce RENDER_TYPE_NONE in LLRenderTypeMask and initialize its mRenderTypeEnabled[RENDER_TYPE_NONE] to FALSE explicitely
- return (type == 0 ? FALSE : mRenderTypeEnabled[type]);
-}
-
-void LLPipeline::setRenderTypeMask(U32 type, ...)
-{
- va_list args;
-
- va_start(args, type);
- while (type < END_RENDER_TYPES)
- {
- mRenderTypeEnabled[type] = TRUE;
- type = va_arg(args, U32);
- }
- va_end(args);
-
- if (type > END_RENDER_TYPES)
- {
- llerrs << "Invalid render type." << llendl;
- }
-}
-
-BOOL LLPipeline::hasAnyRenderType(U32 type, ...) const
-{
- va_list args;
-
- va_start(args, type);
- while (type < END_RENDER_TYPES)
- {
- if (mRenderTypeEnabled[type])
- {
- return TRUE;
- }
- type = va_arg(args, U32);
- }
- va_end(args);
-
- if (type > END_RENDER_TYPES)
- {
- llerrs << "Invalid render type." << llendl;
- }
-
- return FALSE;
-}
-
-void LLPipeline::pushRenderTypeMask()
-{
- std::string cur_mask;
- cur_mask.assign((const char*) mRenderTypeEnabled, sizeof(mRenderTypeEnabled));
- mRenderTypeEnableStack.push(cur_mask);
-}
-
-void LLPipeline::popRenderTypeMask()
-{
- if (mRenderTypeEnableStack.empty())
- {
- llerrs << "Depleted render type stack." << llendl;
- }
-
- memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled));
- mRenderTypeEnableStack.pop();
-}
-
-void LLPipeline::andRenderTypeMask(U32 type, ...)
-{
- va_list args;
-
- BOOL tmp[NUM_RENDER_TYPES];
- for (U32 i = 0; i < NUM_RENDER_TYPES; ++i)
- {
- tmp[i] = FALSE;
- }
-
- va_start(args, type);
- while (type < END_RENDER_TYPES)
- {
- if (mRenderTypeEnabled[type])
- {
- tmp[type] = TRUE;
- }
-
- type = va_arg(args, U32);
- }
- va_end(args);
-
- if (type > END_RENDER_TYPES)
- {
- llerrs << "Invalid render type." << llendl;
- }
-
- for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i)
- {
- mRenderTypeEnabled[i] = tmp[i];
- }
-
-}
-
-void LLPipeline::clearRenderTypeMask(U32 type, ...)
-{
- va_list args;
-
- va_start(args, type);
- while (type < END_RENDER_TYPES)
- {
- mRenderTypeEnabled[type] = FALSE;
-
- type = va_arg(args, U32);
- }
- va_end(args);
-
- if (type > END_RENDER_TYPES)
- {
- llerrs << "Invalid render type." << llendl;
- }
-}
-
-void LLPipeline::addDebugBlip(const LLVector3& position, const LLColor4& color)
-{
- DebugBlip blip(position, color);
- mDebugBlips.push_back(blip);
-}
-
+ gGL.flush();
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gUIProgram.unbind();
+ }
+
+ gGL.color4f(1,1,1,1);
+
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+ gGL.setColorMask(true, false);
+
+ bool hud_only = hasRenderType(LLPipeline::RENDER_TYPE_HUD);
+
+
+ if (!hud_only && !mDebugBlips.empty())
+ { //render debug blips
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gUIProgram.bind();
+ }
+
+ gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep, true);
+
+ glPointSize(8.f);
+ LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
+
+ gGL.begin(LLRender::POINTS);
+ for (std::list<DebugBlip>::iterator iter = mDebugBlips.begin(); iter != mDebugBlips.end(); )
+ {
+ DebugBlip& blip = *iter;
+
+ blip.mAge += gFrameIntervalSeconds;
+ if (blip.mAge > 2.f)
+ {
+ mDebugBlips.erase(iter++);
+ }
+ else
+ {
+ iter++;
+ }
+
+ blip.mPosition.mV[2] += gFrameIntervalSeconds*2.f;
+
+ gGL.color4fv(blip.mColor.mV);
+ gGL.vertex3fv(blip.mPosition.mV);
+ }
+ gGL.end();
+ gGL.flush();
+ glPointSize(1.f);
+ }
+
+
+ // Debug stuff.
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+ for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(i);
+ if (part)
+ {
+ if ( hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES) ||
+ !hud_only && hasRenderType(part->mDrawableType) )
+ {
+ part->renderDebug();
+ }
+ }
+ }
+ }
+
+ for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
+ {
+ LLSpatialBridge* bridge = *i;
+ if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
+ {
+ gGL.pushMatrix();
+ gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
+ bridge->renderDebug();
+ gGL.popMatrix();
+ }
+ }
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gUIProgram.bind();
+ }
+
+ if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ LLVertexBuffer::unbind();
+
+ LLGLEnable blend(GL_BLEND);
+ LLGLDepthTest depth(TRUE, FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+
+ gGL.color4f(1,1,1,1);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ F32 a = 0.1f;
+
+ F32 col[] =
+ {
+ 1,0,0,a,
+ 0,1,0,a,
+ 0,0,1,a,
+ 1,0,1,a,
+
+ 1,1,0,a,
+ 0,1,1,a,
+ 1,1,1,a,
+ 1,0,1,a,
+ };
+
+ for (U32 i = 0; i < 8; i++)
+ {
+ LLVector3* frust = mShadowCamera[i].mAgentFrustum;
+
+ if (i > 3)
+ { //render shadow frusta as volumes
+ if (mShadowFrustPoints[i-4].empty())
+ {
+ continue;
+ }
+
+ gGL.color4fv(col+(i-4)*4);
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+ gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
+ gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
+ gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
+ gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+ gGL.end();
+
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex3fv(frust[0].mV);
+ gGL.vertex3fv(frust[1].mV);
+ gGL.vertex3fv(frust[3].mV);
+ gGL.vertex3fv(frust[2].mV);
+ gGL.end();
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex3fv(frust[4].mV);
+ gGL.vertex3fv(frust[5].mV);
+ gGL.vertex3fv(frust[7].mV);
+ gGL.vertex3fv(frust[6].mV);
+ gGL.end();
+ }
+
+
+ if (i < 4)
+ {
+
+ //if (i == 0 || !mShadowFrustPoints[i].empty())
+ {
+ //render visible point cloud
+ gGL.flush();
+ glPointSize(8.f);
+ gGL.begin(LLRender::POINTS);
+
+ F32* c = col+i*4;
+ gGL.color3fv(c);
+
+ for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j)
+ {
+ gGL.vertex3fv(mShadowFrustPoints[i][j].mV);
+
+ }
+ gGL.end();
+
+ gGL.flush();
+ glPointSize(1.f);
+
+ LLVector3* ext = mShadowExtents[i];
+ LLVector3 pos = (ext[0]+ext[1])*0.5f;
+ LLVector3 size = (ext[1]-ext[0])*0.5f;
+ drawBoxOutline(pos, size);
+
+ //render camera frustum splits as outlines
+ gGL.begin(LLRender::LINES);
+ gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV);
+ gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV);
+ gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV);
+ gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV);
+ gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV);
+ gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV);
+ gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV);
+ gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV);
+ gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+ gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
+ gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
+ gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
+ gGL.end();
+ }
+ }
+
+ /*gGL.flush();
+ glLineWidth(16-i*2);
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+ for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(j);
+ if (part)
+ {
+ if (hasRenderType(part->mDrawableType))
+ {
+ part->renderIntersectingBBoxes(&mShadowCamera[i]);
+ }
+ }
+ }
+ }
+ gGL.flush();
+ glLineWidth(1.f);*/
+ }
+ }
+
+ if (mRenderDebugMask & RENDER_DEBUG_WIND_VECTORS)
+ {
+ gAgent.getRegion()->mWind.renderVectors();
+ }
+
+ if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION)
+ {
+ // Debug composition layers
+ F32 x, y;
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ if (gAgent.getRegion())
+ {
+ gGL.begin(LLRender::POINTS);
+ // Draw the composition layer for the region that I'm in.
+ for (x = 0; x <= 260; x++)
+ {
+ for (y = 0; y <= 260; y++)
+ {
+ if ((x > 255) || (y > 255))
+ {
+ gGL.color4f(1.f, 0.f, 0.f, 1.f);
+ }
+ else
+ {
+ gGL.color4f(0.f, 0.f, 1.f, 1.f);
+ }
+ F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y);
+ z *= 5.f;
+ z += 50.f;
+ gGL.vertex3f(x, y, z);
+ }
+ }
+ gGL.end();
+ }
+ }
+
+ if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_BUILD_QUEUE)
+ {
+ U32 count = 0;
+ U32 size = mGroupQ2.size();
+ LLColor4 col;
+
+ LLVertexBuffer::unbind();
+ LLGLEnable blend(GL_BLEND);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
+
+ gGL.pushMatrix();
+ gGL.loadMatrix(gGLModelView);
+ gGLLastMatrix = NULL;
+
+ for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); iter != mGroupQ2.end(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ if (group->isDead())
+ {
+ continue;
+ }
+
+ LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
+
+ if (bridge && (!bridge->mDrawable || bridge->mDrawable->isDead()))
+ {
+ continue;
+ }
+
+ if (bridge)
+ {
+ gGL.pushMatrix();
+ gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
+ }
+
+ F32 alpha = llclamp((F32) (size-count)/size, 0.f, 1.f);
+
+
+ LLVector2 c(1.f-alpha, alpha);
+ c.normVec();
+
+
+ ++count;
+ col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.5f);
+ group->drawObjectBox(col);
+
+ if (bridge)
+ {
+ gGL.popMatrix();
+ }
+ }
+
+ gGL.popMatrix();
+ }
+
+ gGL.flush();
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gUIProgram.unbind();
+ }
+}
+
+void LLPipeline::rebuildPools()
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_REBUILD_POOLS);
+
+ assertInitialized();
+
+ S32 max_count = mPools.size();
+ pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool);
+ while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS)
+ {
+ if (iter1 == mPools.end())
+ {
+ iter1 = mPools.begin();
+ }
+ LLDrawPool* poolp = *iter1;
+
+ if (poolp->isDead())
+ {
+ mPools.erase(iter1++);
+ removeFromQuickLookup( poolp );
+ if (poolp == mLastRebuildPool)
+ {
+ mLastRebuildPool = NULL;
+ }
+ delete poolp;
+ }
+ else
+ {
+ mLastRebuildPool = poolp;
+ iter1++;
+ }
+ max_count--;
+ }
+
+ if (isAgentAvatarValid())
+ {
+ gAgentAvatarp->rebuildHUD();
+ }
+}
+
+void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
+{
+ LLMemType mt(LLMemType::MTYPE_PIPELINE_QUICK_LOOKUP);
+
+ assertInitialized();
+
+ switch( new_poolp->getType() )
+ {
+ case LLDrawPool::POOL_SIMPLE:
+ if (mSimplePool)
+ {
+ llassert(0);
+ llwarns << "Ignoring duplicate simple pool." << llendl;
+ }
+ else
+ {
+ mSimplePool = (LLRenderPass*) new_poolp;
+ }
+ break;
+
+ case LLDrawPool::POOL_GRASS:
+ if (mGrassPool)
+ {
+ llassert(0);
+ llwarns << "Ignoring duplicate grass pool." << llendl;
+ }
+ else
+ {
+ mGrassPool = (LLRenderPass*) new_poolp;
+ }
+ break;
+
+ case LLDrawPool::POOL_FULLBRIGHT:
+ if (mFullbrightPool)
+ {
+ llassert(0);
+ llwarns << "Ignoring duplicate simple pool." << llendl;
+ }
+ else
+ {
+ mFullbrightPool = (LLRenderPass*) new_poolp;
+ }
+ break;
+
+ case LLDrawPool::POOL_INVISIBLE:
+ if (mInvisiblePool)
+ {
+ llassert(0);
+ llwarns << "Ignoring duplicate simple pool." << llendl;
+ }
+ else
+ {
+ mInvisiblePool = (LLRenderPass*) new_poolp;
+ }
+ break;
+
+ case LLDrawPool::POOL_GLOW:
+ if (mGlowPool)
+ {
+ llassert(0);
+ llwarns << "Ignoring duplicate glow pool." << llendl;
+ }
+ else
+ {
+ mGlowPool = (LLRenderPass*) new_poolp;
+ }
+ break;
+
+ case LLDrawPool::POOL_TREE:
+ mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
+ break;
+
+ case LLDrawPool::POOL_TERRAIN:
+ mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
+ break;
+
+ case LLDrawPool::POOL_BUMP:
+ if (mBumpPool)
+ {
+ llassert(0);
+ llwarns << "Ignoring duplicate bump pool." << llendl;
+ }
+ else
+ {
+ mBumpPool = new_poolp;
+ }
+ break;
+
+ case LLDrawPool::POOL_ALPHA:
+ if( mAlphaPool )
+ {
+ llassert(0);
+ llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl;
+ }
+ else
+ {
+ mAlphaPool = new_poolp;
+ }
+ break;
+
+ case LLDrawPool::POOL_AVATAR:
+ break; // Do nothing
+
+ case LLDrawPool::POOL_SKY:
+ if( mSkyPool )
+ {
+ llassert(0);
+ llwarns << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << llendl;
+ }
+ else
+ {
+ mSkyPool = new_poolp;
+ }
+ break;
+
+ case LLDrawPool::POOL_WATER:
+ if( mWaterPool )
+ {
+ llassert(0);
+ llwarns << "LLPipeline::addPool(): Ignoring duplicate Water pool" << llendl;
+ }
+ else
+ {
+ mWaterPool = new_poolp;
+ }
+ break;
+
+ case LLDrawPool::POOL_GROUND:
+ if( mGroundPool )
+ {
+ llassert(0);
+ llwarns << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << llendl;
+ }
+ else
+ {
+ mGroundPool = new_poolp;
+ }
+ break;
+
+ case LLDrawPool::POOL_WL_SKY:
+ if( mWLSkyPool )
+ {
+ llassert(0);
+ llwarns << "LLPipeline::addPool(): Ignoring duplicate WLSky Pool" << llendl;
+ }
+ else
+ {
+ mWLSkyPool = new_poolp;
+ }
+ break;
+
+ default:
+ llassert(0);
+ llwarns << "Invalid Pool Type in LLPipeline::addPool()" << llendl;
+ break;
+ }
+}
+
+void LLPipeline::removePool( LLDrawPool* poolp )
+{
+ assertInitialized();
+ removeFromQuickLookup(poolp);
+ mPools.erase(poolp);
+ delete poolp;
+}
+
+void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
+{
+ assertInitialized();
+ LLMemType mt(LLMemType::MTYPE_PIPELINE);
+ switch( poolp->getType() )
+ {
+ case LLDrawPool::POOL_SIMPLE:
+ llassert(mSimplePool == poolp);
+ mSimplePool = NULL;
+ break;
+
+ case LLDrawPool::POOL_GRASS:
+ llassert(mGrassPool == poolp);
+ mGrassPool = NULL;
+ break;
+
+ case LLDrawPool::POOL_FULLBRIGHT:
+ llassert(mFullbrightPool == poolp);
+ mFullbrightPool = NULL;
+ break;
+
+ case LLDrawPool::POOL_INVISIBLE:
+ llassert(mInvisiblePool == poolp);
+ mInvisiblePool = NULL;
+ break;
+
+ case LLDrawPool::POOL_WL_SKY:
+ llassert(mWLSkyPool == poolp);
+ mWLSkyPool = NULL;
+ break;
+
+ case LLDrawPool::POOL_GLOW:
+ llassert(mGlowPool == poolp);
+ mGlowPool = NULL;
+ break;
+
+ case LLDrawPool::POOL_TREE:
+ #ifdef _DEBUG
+ {
+ BOOL found = mTreePools.erase( (uintptr_t)poolp->getTexture() );
+ llassert( found );
+ }
+ #else
+ mTreePools.erase( (uintptr_t)poolp->getTexture() );
+ #endif
+ break;
+
+ case LLDrawPool::POOL_TERRAIN:
+ #ifdef _DEBUG
+ {
+ BOOL found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
+ llassert( found );
+ }
+ #else
+ mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
+ #endif
+ break;
+
+ case LLDrawPool::POOL_BUMP:
+ llassert( poolp == mBumpPool );
+ mBumpPool = NULL;
+ break;
+
+ case LLDrawPool::POOL_ALPHA:
+ llassert( poolp == mAlphaPool );
+ mAlphaPool = NULL;
+ break;
+
+ case LLDrawPool::POOL_AVATAR:
+ break; // Do nothing
+
+ case LLDrawPool::POOL_SKY:
+ llassert( poolp == mSkyPool );
+ mSkyPool = NULL;
+ break;
+
+ case LLDrawPool::POOL_WATER:
+ llassert( poolp == mWaterPool );
+ mWaterPool = NULL;
+ break;
+
+ case LLDrawPool::POOL_GROUND:
+ llassert( poolp == mGroundPool );
+ mGroundPool = NULL;
+ break;
+
+ default:
+ llassert(0);
+ llwarns << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl;
+ break;
+ }
+}
+
+void LLPipeline::resetDrawOrders()
+{
+ assertInitialized();
+ // Iterate through all of the draw pools and rebuild them.
+ for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+ {
+ LLDrawPool *poolp = *iter;
+ poolp->resetDrawOrders();
+ }
+}
+
+//============================================================================
+// Once-per-frame setup of hardware lights,
+// including sun/moon, avatar backlight, and up to 6 local lights
+
+void LLPipeline::setupAvatarLights(BOOL for_edit)
+{
+ assertInitialized();
+
+ if (for_edit)
+ {
+ LLColor4 diffuse(1.f, 1.f, 1.f, 0.f);
+ LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f); // w==0 => directional light
+ LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview();
+ LLMatrix4 camera_rot(camera_mat.getMat3());
+ camera_rot.invert();
+ LLVector4 light_pos = light_pos_cam * camera_rot;
+
+ light_pos.normalize();
+
+ LLLightState* light = gGL.getLight(1);
+
+ mHWLightColors[1] = diffuse;
+
+ light->setDiffuse(diffuse);
+ light->setAmbient(LLColor4::black);
+ light->setSpecular(LLColor4::black);
+ light->setPosition(light_pos);
+ light->setConstantAttenuation(1.f);
+ light->setLinearAttenuation(0.f);
+ light->setQuadraticAttenuation(0.f);
+ light->setSpotExponent(0.f);
+ light->setSpotCutoff(180.f);
+ }
+ else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini)
+ {
+ LLVector3 opposite_pos = -1.f * mSunDir;
+ LLVector3 orthog_light_pos = mSunDir % LLVector3::z_axis;
+ LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f);
+ backlight_pos.normalize();
+
+ LLColor4 light_diffuse = mSunDiffuse;
+ LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f);
+ F32 max_component = 0.001f;
+ for (S32 i = 0; i < 3; i++)
+ {
+ if (backlight_diffuse.mV[i] > max_component)
+ {
+ max_component = backlight_diffuse.mV[i];
+ }
+ }
+ F32 backlight_mag;
+ if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
+ {
+ backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT;
+ }
+ else
+ {
+ backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT;
+ }
+ backlight_diffuse *= backlight_mag / max_component;
+
+ mHWLightColors[1] = backlight_diffuse;
+
+ LLLightState* light = gGL.getLight(1);
+
+ light->setPosition(backlight_pos);
+ light->setDiffuse(backlight_diffuse);
+ light->setAmbient(LLColor4::black);
+ light->setSpecular(LLColor4::black);
+ light->setConstantAttenuation(1.f);
+ light->setLinearAttenuation(0.f);
+ light->setQuadraticAttenuation(0.f);
+ light->setSpotExponent(0.f);
+ light->setSpotCutoff(180.f);
+ }
+ else
+ {
+ LLLightState* light = gGL.getLight(1);
+
+ mHWLightColors[1] = LLColor4::black;
+
+ light->setDiffuse(LLColor4::black);
+ light->setAmbient(LLColor4::black);
+ light->setSpecular(LLColor4::black);
+ }
+}
+
+static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist)
+{
+ F32 inten = light->getLightIntensity();
+ if (inten < .001f)
+ {
+ return max_dist;
+ }
+ F32 radius = light->getLightRadius();
+ BOOL selected = light->isSelected();
+ LLVector3 dpos = light->getRenderPosition() - cam_pos;
+ F32 dist2 = dpos.lengthSquared();
+ if (!selected && dist2 > (max_dist + radius)*(max_dist + radius))
+ {
+ return max_dist;
+ }
+ F32 dist = (F32) sqrt(dist2);
+ dist *= 1.f / inten;
+ dist -= radius;
+ if (selected)
+ {
+ dist -= 10000.f; // selected lights get highest priority
+ }
+ if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE))
+ {
+ // moving lights get a little higher priority (too much causes artifacts)
+ dist -= light->getLightRadius()*0.25f;
+ }
+ return dist;
+}
+
+void LLPipeline::calcNearbyLights(LLCamera& camera)
+{
+ assertInitialized();
+
+ if (LLPipeline::sReflectionRender)
+ {
+ return;
+ }
+
+ if (mLightingDetail >= 1)
+ {
+ // mNearbyLight (and all light_set_t's) are sorted such that
+ // begin() == the closest light and rbegin() == the farthest light
+ const S32 MAX_LOCAL_LIGHTS = 6;
+// LLVector3 cam_pos = gAgent.getCameraPositionAgent();
+ LLVector3 cam_pos = LLViewerJoystick::getInstance()->getOverrideCamera() ?
+ camera.getOrigin() :
+ gAgent.getPositionAgent();
+
+ F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad
+
+ // UPDATE THE EXISTING NEARBY LIGHTS
+ light_set_t cur_nearby_lights;
+ for (light_set_t::iterator iter = mNearbyLights.begin();
+ iter != mNearbyLights.end(); iter++)
+ {
+ const Light* light = &(*iter);
+ LLDrawable* drawable = light->drawable;
+ LLVOVolume* volight = drawable->getVOVolume();
+ if (!volight || !drawable->isState(LLDrawable::LIGHT))
+ {
+ drawable->clearState(LLDrawable::NEARBY_LIGHT);
+ continue;
+ }
+ if (light->fade <= -LIGHT_FADE_TIME)
+ {
+ drawable->clearState(LLDrawable::NEARBY_LIGHT);
+ continue;
+ }
+ if (!sRenderAttachedLights && volight && volight->isAttachment())
+ {
+ drawable->clearState(LLDrawable::NEARBY_LIGHT);
+ continue;
+ }
+
+ F32 dist = calc_light_dist(volight, cam_pos, max_dist);
+ cur_nearby_lights.insert(Light(drawable, dist, light->fade));
+ }
+ mNearbyLights = cur_nearby_lights;
+
+ // FIND NEW LIGHTS THAT ARE IN RANGE
+ light_set_t new_nearby_lights;
+ for (LLDrawable::drawable_set_t::iterator iter = mLights.begin();
+ iter != mLights.end(); ++iter)
+ {
+ LLDrawable* drawable = *iter;
+ LLVOVolume* light = drawable->getVOVolume();
+ if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT))
+ {
+ continue;
+ }
+ if (light->isHUDAttachment())
+ {
+ continue; // no lighting from HUD objects
+ }
+ F32 dist = calc_light_dist(light, cam_pos, max_dist);
+ if (dist >= max_dist)
+ {
+ continue;
+ }
+ if (!sRenderAttachedLights && light && light->isAttachment())
+ {
+ continue;
+ }
+ new_nearby_lights.insert(Light(drawable, dist, 0.f));
+ if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS)
+ {
+ new_nearby_lights.erase(--new_nearby_lights.end());
+ const Light& last = *new_nearby_lights.rbegin();
+ max_dist = last.dist;
+ }
+ }
+
+ // INSERT ANY NEW LIGHTS
+ for (light_set_t::iterator iter = new_nearby_lights.begin();
+ iter != new_nearby_lights.end(); iter++)
+ {
+ const Light* light = &(*iter);
+ if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS)
+ {
+ mNearbyLights.insert(*light);
+ ((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT);
+ }
+ else
+ {
+ // crazy cast so that we can overwrite the fade value
+ // even though gcc enforces sets as const
+ // (fade value doesn't affect sort so this is safe)
+ Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin()))));
+ if (light->dist < farthest_light->dist)
+ {
+ if (farthest_light->fade >= 0.f)
+ {
+ farthest_light->fade = -gFrameIntervalSeconds;
+ }
+ }
+ else
+ {
+ break; // none of the other lights are closer
+ }
+ }
+ }
+
+ }
+}
+
+void LLPipeline::setupHWLights(LLDrawPool* pool)
+{
+ assertInitialized();
+
+ // Ambient
+ if (!LLGLSLShader::sNoFixedFunction)
+ {
+ gGL.syncMatrices();
+ LLColor4 ambient = gSky.getTotalAmbientColor();
+ gGL.setAmbientLightColor(ambient);
+ }
+
+ // Light 0 = Sun or Moon (All objects)
+ {
+ if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
+ {
+ mSunDir.setVec(gSky.getSunDirection());
+ mSunDiffuse.setVec(gSky.getSunDiffuseColor());
+ }
+ else
+ {
+ mSunDir.setVec(gSky.getMoonDirection());
+ mSunDiffuse.setVec(gSky.getMoonDiffuseColor());
+ }
+
+ F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]);
+ if (max_color > 1.f)
+ {
+ mSunDiffuse *= 1.f/max_color;
+ }
+ mSunDiffuse.clamp();
+
+ LLVector4 light_pos(mSunDir, 0.0f);
+ LLColor4 light_diffuse = mSunDiffuse;
+ mHWLightColors[0] = light_diffuse;
+
+ LLLightState* light = gGL.getLight(0);
+ light->setPosition(light_pos);
+ light->setDiffuse(light_diffuse);
+ light->setAmbient(LLColor4::black);
+ light->setSpecular(LLColor4::black);
+ light->setConstantAttenuation(1.f);
+ light->setLinearAttenuation(0.f);
+ light->setQuadraticAttenuation(0.f);
+ light->setSpotExponent(0.f);
+ light->setSpotCutoff(180.f);
+ }
+
+ // Light 1 = Backlight (for avatars)
+ // (set by enableLightsAvatar)
+
+ S32 cur_light = 2;
+
+ // Nearby lights = LIGHT 2-7
+
+ mLightMovingMask = 0;
+
+ if (mLightingDetail >= 1)
+ {
+ for (light_set_t::iterator iter = mNearbyLights.begin();
+ iter != mNearbyLights.end(); ++iter)
+ {
+ LLDrawable* drawable = iter->drawable;
+ LLVOVolume* light = drawable->getVOVolume();
+ if (!light)
+ {
+ continue;
+ }
+ if (drawable->isState(LLDrawable::ACTIVE))
+ {
+ mLightMovingMask |= (1<<cur_light);
+ }
+
+ LLColor4 light_color = light->getLightColor();
+ light_color.mV[3] = 0.0f;
+
+ F32 fade = iter->fade;
+ if (fade < LIGHT_FADE_TIME)
+ {
+ // fade in/out light
+ if (fade >= 0.f)
+ {
+ fade = fade / LIGHT_FADE_TIME;
+ ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds;
+ }
+ else
+ {
+ fade = 1.f + fade / LIGHT_FADE_TIME;
+ ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds;
+ }
+ fade = llclamp(fade,0.f,1.f);
+ light_color *= fade;
+ }
+
+ LLVector3 light_pos(light->getRenderPosition());
+ LLVector4 light_pos_gl(light_pos, 1.0f);
+
+ F32 light_radius = llmax(light->getLightRadius(), 0.001f);
+
+ F32 x = (3.f * (1.f + light->getLightFalloff())); // why this magic? probably trying to match a historic behavior.
+ float linatten = x / (light_radius); // % of brightness at radius
+
+ mHWLightColors[cur_light] = light_color;
+ LLLightState* light_state = gGL.getLight(cur_light);
+
+ light_state->setPosition(light_pos_gl);
+ light_state->setDiffuse(light_color);
+ light_state->setAmbient(LLColor4::black);
+ light_state->setConstantAttenuation(0.f);
+ if (sRenderDeferred)
+ {
+ F32 size = light_radius*1.5f;
+ light_state->setLinearAttenuation(size*size);
+ light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f);
+ }
+ else
+ {
+ light_state->setLinearAttenuation(linatten);
+ light_state->setQuadraticAttenuation(0.f);
+ }
+
+
+ if (light->isLightSpotlight() // directional (spot-)light
+ && (LLPipeline::sRenderDeferred || RenderSpotLightsInNondeferred)) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on
+ {
+ LLVector3 spotparams = light->getSpotLightParams();
+ LLQuaternion quat = light->getRenderRotation();
+ LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction
+ at_axis *= quat;
+
+ light_state->setSpotDirection(at_axis);
+ light_state->setSpotCutoff(90.f);
+ light_state->setSpotExponent(2.f);
+
+ const LLColor4 specular(0.f, 0.f, 0.f, 0.f);
+ light_state->setSpecular(specular);
+ }
+ else // omnidirectional (point) light
+ {
+ light_state->setSpotExponent(0.f);
+ light_state->setSpotCutoff(180.f);
+
+ // we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight
+ const LLColor4 specular(0.f, 0.f, 0.f, 1.f);
+ light_state->setSpecular(specular);
+ }
+ cur_light++;
+ if (cur_light >= 8)
+ {
+ break; // safety
+ }
+ }
+ }
+ for ( ; cur_light < 8 ; cur_light++)
+ {
+ mHWLightColors[cur_light] = LLColor4::black;
+ LLLightState* light = gGL.getLight(cur_light);
+
+ light->setDiffuse(LLColor4::black);
+ light->setAmbient(LLColor4::black);
+ light->setSpecular(LLColor4::black);
+ }
+ if (gAgentAvatarp &&
+ gAgentAvatarp->mSpecialRenderMode == 3)
+ {
+ LLColor4 light_color = LLColor4::white;
+ light_color.mV[3] = 0.0f;
+
+ LLVector3 light_pos(LLViewerCamera::getInstance()->getOrigin());
+ LLVector4 light_pos_gl(light_pos, 1.0f);
+
+ F32 light_radius = 16.f;
+
+ F32 x = 3.f;
+ float linatten = x / (light_radius); // % of brightness at radius
+
+ mHWLightColors[2] = light_color;
+ LLLightState* light = gGL.getLight(2);
+
+ light->setPosition(light_pos_gl);
+ light->setDiffuse(light_color);
+ light->setAmbient(LLColor4::black);
+ light->setSpecular(LLColor4::black);
+ light->setQuadraticAttenuation(0.f);
+ light->setConstantAttenuation(0.f);
+ light->setLinearAttenuation(linatten);
+ light->setSpotExponent(0.f);
+ light->setSpotCutoff(180.f);
+ }
+
+ // Init GL state
+ if (!LLGLSLShader::sNoFixedFunction)
+ {
+ glDisable(GL_LIGHTING);
+ }
+
+ for (S32 i = 0; i < 8; ++i)
+ {
+ gGL.getLight(i)->disable();
+ }
+ mLightMask = 0;
+}
+
+void LLPipeline::enableLights(U32 mask)
+{
+ assertInitialized();
+
+ if (mLightingDetail == 0)
+ {
+ mask &= 0xf003; // sun and backlight only (and fullbright bit)
+ }
+ if (mLightMask != mask)
+ {
+ stop_glerror();
+ if (!mLightMask)
+ {
+ if (!LLGLSLShader::sNoFixedFunction)
+ {
+ glEnable(GL_LIGHTING);
+ }
+ }
+ if (mask)
+ {
+ stop_glerror();
+ for (S32 i=0; i<8; i++)
+ {
+ LLLightState* light = gGL.getLight(i);
+ if (mask & (1<<i))
+ {
+ light->enable();
+ light->setDiffuse(mHWLightColors[i]);
+ }
+ else
+ {
+ light->disable();
+ light->setDiffuse(LLColor4::black);
+ }
+ }
+ stop_glerror();
+ }
+ else
+ {
+ if (!LLGLSLShader::sNoFixedFunction)
+ {
+ glDisable(GL_LIGHTING);
+ }
+ }
+ mLightMask = mask;
+ stop_glerror();
+
+ LLColor4 ambient = gSky.getTotalAmbientColor();
+ gGL.setAmbientLightColor(ambient);
+ }
+}
+
+void LLPipeline::enableLightsStatic()
+{
+ assertInitialized();
+ U32 mask = 0x01; // Sun
+ if (mLightingDetail >= 2)
+ {
+ mask |= mLightMovingMask; // Hardware moving lights
+ }
+ else
+ {
+ mask |= 0xff & (~2); // Hardware local lights
+ }
+ enableLights(mask);
+}
+
+void LLPipeline::enableLightsDynamic()
+{
+ assertInitialized();
+ U32 mask = 0xff & (~2); // Local lights
+ enableLights(mask);
+
+ if (isAgentAvatarValid() && getLightingDetail() <= 0)
+ {
+ if (gAgentAvatarp->mSpecialRenderMode == 0) // normal
+ {
+ gPipeline.enableLightsAvatar();
+ }
+ else if (gAgentAvatarp->mSpecialRenderMode >= 1) // anim preview
+ {
+ gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f));
+ }
+ }
+}
+
+void LLPipeline::enableLightsAvatar()
+{
+ U32 mask = 0xff; // All lights
+ setupAvatarLights(FALSE);
+ enableLights(mask);
+}
+
+void LLPipeline::enableLightsPreview()
+{
+ disableLights();
+
+ if (!LLGLSLShader::sNoFixedFunction)
+ {
+ glEnable(GL_LIGHTING);
+ }
+
+ LLColor4 ambient = PreviewAmbientColor;
+ gGL.setAmbientLightColor(ambient);
+
+ LLColor4 diffuse0 = PreviewDiffuse0;
+ LLColor4 specular0 = PreviewSpecular0;
+ LLColor4 diffuse1 = PreviewDiffuse1;
+ LLColor4 specular1 = PreviewSpecular1;
+ LLColor4 diffuse2 = PreviewDiffuse2;
+ LLColor4 specular2 = PreviewSpecular2;
+
+ LLVector3 dir0 = PreviewDirection0;
+ LLVector3 dir1 = PreviewDirection1;
+ LLVector3 dir2 = PreviewDirection2;
+
+ dir0.normVec();
+ dir1.normVec();
+ dir2.normVec();
+
+ LLVector4 light_pos(dir0, 0.0f);
+
+ LLLightState* light = gGL.getLight(0);
+
+ light->enable();
+ light->setPosition(light_pos);
+ light->setDiffuse(diffuse0);
+ light->setAmbient(LLColor4::black);
+ light->setSpecular(specular0);
+ light->setSpotExponent(0.f);
+ light->setSpotCutoff(180.f);
+
+ light_pos = LLVector4(dir1, 0.f);
+
+ light = gGL.getLight(1);
+ light->enable();
+ light->setPosition(light_pos);
+ light->setDiffuse(diffuse1);
+ light->setAmbient(LLColor4::black);
+ light->setSpecular(specular1);
+ light->setSpotExponent(0.f);
+ light->setSpotCutoff(180.f);
+
+ light_pos = LLVector4(dir2, 0.f);
+ light = gGL.getLight(2);
+ light->enable();
+ light->setPosition(light_pos);
+ light->setDiffuse(diffuse2);
+ light->setAmbient(LLColor4::black);
+ light->setSpecular(specular2);
+ light->setSpotExponent(0.f);
+ light->setSpotCutoff(180.f);
+}
+
+
+void LLPipeline::enableLightsAvatarEdit(const LLColor4& color)
+{
+ U32 mask = 0x2002; // Avatar backlight only, set ambient
+ setupAvatarLights(TRUE);
+ enableLights(mask);
+
+ gGL.setAmbientLightColor(color);
+}
+
+void LLPipeline::enableLightsFullbright(const LLColor4& color)
+{
+ assertInitialized();
+ U32 mask = 0x1000; // Non-0 mask, set ambient
+ enableLights(mask);
+
+ gGL.setAmbientLightColor(color);
+}
+
+void LLPipeline::disableLights()
+{
+ enableLights(0); // no lighting (full bright)
+}
+
+//============================================================================
+
+class LLMenuItemGL;
+class LLInvFVBridge;
+struct cat_folder_pair;
+class LLVOBranch;
+class LLVOLeaf;
+
+void LLPipeline::findReferences(LLDrawable *drawablep)
+{
+ assertInitialized();
+ if (mLights.find(drawablep) != mLights.end())
+ {
+ llinfos << "In mLights" << llendl;
+ }
+ if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end())
+ {
+ llinfos << "In mMovedList" << llendl;
+ }
+ if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end())
+ {
+ llinfos << "In mShiftList" << llendl;
+ }
+ if (mRetexturedList.find(drawablep) != mRetexturedList.end())
+ {
+ llinfos << "In mRetexturedList" << llendl;
+ }
+
+ if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end())
+ {
+ llinfos << "In mBuildQ1" << llendl;
+ }
+ if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end())
+ {
+ llinfos << "In mBuildQ2" << llendl;
+ }
+
+ S32 count;
+
+ count = gObjectList.findReferences(drawablep);
+ if (count)
+ {
+ llinfos << "In other drawables: " << count << " references" << llendl;
+ }
+}
+
+BOOL LLPipeline::verify()
+{
+ BOOL ok = assertInitialized();
+ if (ok)
+ {
+ for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+ {
+ LLDrawPool *poolp = *iter;
+ if (!poolp->verify())
+ {
+ ok = FALSE;
+ }
+ }
+ }
+
+ if (!ok)
+ {
+ llwarns << "Pipeline verify failed!" << llendl;
+ }
+ return ok;
+}
+
+//////////////////////////////
+//
+// Collision detection
+//
+//
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * A method to compute a ray-AABB intersection.
+ * Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990
+ * Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)
+ * Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only)
+ *
+ * Hence this version is faster as well as more robust than the original one.
+ *
+ * Should work provided:
+ * 1) the integer representation of 0.0f is 0x00000000
+ * 2) the sign bit of the float is the most significant one
+ *
+ * Report bugs: p.terdiman@codercorner.com
+ *
+ * \param aabb [in] the axis-aligned bounding box
+ * \param origin [in] ray origin
+ * \param dir [in] ray direction
+ * \param coord [out] impact coordinates
+ * \return true if ray intersects AABB
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//#define RAYAABB_EPSILON 0.00001f
+#define IR(x) ((U32&)x)
+
+bool LLRayAABB(const LLVector3 &center, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon)
+{
+ BOOL Inside = TRUE;
+ LLVector3 MinB = center - size;
+ LLVector3 MaxB = center + size;
+ LLVector3 MaxT;
+ MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f;
+
+ // Find candidate planes.
+ for(U32 i=0;i<3;i++)
+ {
+ if(origin.mV[i] < MinB.mV[i])
+ {
+ coord.mV[i] = MinB.mV[i];
+ Inside = FALSE;
+
+ // Calculate T distances to candidate planes
+ if(IR(dir.mV[i])) MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i];
+ }
+ else if(origin.mV[i] > MaxB.mV[i])
+ {
+ coord.mV[i] = MaxB.mV[i];
+ Inside = FALSE;
+
+ // Calculate T distances to candidate planes
+ if(IR(dir.mV[i])) MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i];
+ }
+ }
+
+ // Ray origin inside bounding box
+ if(Inside)
+ {
+ coord = origin;
+ return true;
+ }
+
+ // Get largest of the maxT's for final choice of intersection
+ U32 WhichPlane = 0;
+ if(MaxT.mV[1] > MaxT.mV[WhichPlane]) WhichPlane = 1;
+ if(MaxT.mV[2] > MaxT.mV[WhichPlane]) WhichPlane = 2;
+
+ // Check final candidate actually inside box
+ if(IR(MaxT.mV[WhichPlane])&0x80000000) return false;
+
+ for(U32 i=0;i<3;i++)
+ {
+ if(i!=WhichPlane)
+ {
+ coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i];
+ if (epsilon > 0)
+ {
+ if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon) return false;
+ }
+ else
+ {
+ if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i]) return false;
+ }
+ }
+ }
+ return true; // ray hits box
+}
+
+//////////////////////////////
+//
+// Macros, functions, and inline methods from other classes
+//
+//
+
+void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)
+{
+ if (drawablep && assertInitialized())
+ {
+ if (is_light)
+ {
+ mLights.insert(drawablep);
+ drawablep->setState(LLDrawable::LIGHT);
+ }
+ else
+ {
+ drawablep->clearState(LLDrawable::LIGHT);
+ mLights.erase(drawablep);
+ }
+ }
+}
+
+//static
+void LLPipeline::toggleRenderType(U32 type)
+{
+ gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type];
+ if (type == LLPipeline::RENDER_TYPE_WATER)
+ {
+ gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER] = !gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER];
+ }
+}
+
+//static
+void LLPipeline::toggleRenderTypeControl(void* data)
+{
+ U32 type = (U32)(intptr_t)data;
+ U32 bit = (1<<type);
+ if (gPipeline.hasRenderType(type))
+ {
+ llinfos << "Toggling render type mask " << std::hex << bit << " off" << std::dec << llendl;
+ }
+ else
+ {
+ llinfos << "Toggling render type mask " << std::hex << bit << " on" << std::dec << llendl;
+ }
+ gPipeline.toggleRenderType(type);
+}
+
+//static
+BOOL LLPipeline::hasRenderTypeControl(void* data)
+{
+ U32 type = (U32)(intptr_t)data;
+ return gPipeline.hasRenderType(type);
+}
+
+// Allows UI items labeled "Hide foo" instead of "Show foo"
+//static
+BOOL LLPipeline::toggleRenderTypeControlNegated(void* data)
+{
+ S32 type = (S32)(intptr_t)data;
+ return !gPipeline.hasRenderType(type);
+}
+
+//static
+void LLPipeline::toggleRenderDebug(void* data)
+{
+ U32 bit = (U32)(intptr_t)data;
+ if (gPipeline.hasRenderDebugMask(bit))
+ {
+ llinfos << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << llendl;
+ }
+ else
+ {
+ llinfos << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << llendl;
+ }
+ gPipeline.mRenderDebugMask ^= bit;
+}
+
+
+//static
+BOOL LLPipeline::toggleRenderDebugControl(void* data)
+{
+ U32 bit = (U32)(intptr_t)data;
+ return gPipeline.hasRenderDebugMask(bit);
+}
+
+//static
+void LLPipeline::toggleRenderDebugFeature(void* data)
+{
+ U32 bit = (U32)(intptr_t)data;
+ gPipeline.mRenderDebugFeatureMask ^= bit;
+}
+
+
+//static
+BOOL LLPipeline::toggleRenderDebugFeatureControl(void* data)
+{
+ U32 bit = (U32)(intptr_t)data;
+ return gPipeline.hasRenderDebugFeatureMask(bit);
+}
+
+void LLPipeline::setRenderDebugFeatureControl(U32 bit, bool value)
+{
+ if (value)
+ {
+ gPipeline.mRenderDebugFeatureMask |= bit;
+ }
+ else
+ {
+ gPipeline.mRenderDebugFeatureMask &= !bit;
+ }
+}
+
+// static
+void LLPipeline::setRenderScriptedBeacons(BOOL val)
+{
+ sRenderScriptedBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderScriptedBeacons(void*)
+{
+ sRenderScriptedBeacons = !sRenderScriptedBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderScriptedBeacons(void*)
+{
+ return sRenderScriptedBeacons;
+}
+
+// static
+void LLPipeline::setRenderScriptedTouchBeacons(BOOL val)
+{
+ sRenderScriptedTouchBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderScriptedTouchBeacons(void*)
+{
+ sRenderScriptedTouchBeacons = !sRenderScriptedTouchBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderScriptedTouchBeacons(void*)
+{
+ return sRenderScriptedTouchBeacons;
+}
+
+// static
+void LLPipeline::setRenderMOAPBeacons(BOOL val)
+{
+ sRenderMOAPBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderMOAPBeacons(void*)
+{
+ sRenderMOAPBeacons = !sRenderMOAPBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderMOAPBeacons(void*)
+{
+ return sRenderMOAPBeacons;
+}
+
+// static
+void LLPipeline::setRenderPhysicalBeacons(BOOL val)
+{
+ sRenderPhysicalBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderPhysicalBeacons(void*)
+{
+ sRenderPhysicalBeacons = !sRenderPhysicalBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderPhysicalBeacons(void*)
+{
+ return sRenderPhysicalBeacons;
+}
+
+// static
+void LLPipeline::setRenderParticleBeacons(BOOL val)
+{
+ sRenderParticleBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderParticleBeacons(void*)
+{
+ sRenderParticleBeacons = !sRenderParticleBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderParticleBeacons(void*)
+{
+ return sRenderParticleBeacons;
+}
+
+// static
+void LLPipeline::setRenderSoundBeacons(BOOL val)
+{
+ sRenderSoundBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderSoundBeacons(void*)
+{
+ sRenderSoundBeacons = !sRenderSoundBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderSoundBeacons(void*)
+{
+ return sRenderSoundBeacons;
+}
+
+// static
+void LLPipeline::setRenderBeacons(BOOL val)
+{
+ sRenderBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderBeacons(void*)
+{
+ sRenderBeacons = !sRenderBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderBeacons(void*)
+{
+ return sRenderBeacons;
+}
+
+// static
+void LLPipeline::setRenderHighlights(BOOL val)
+{
+ sRenderHighlight = val;
+}
+
+// static
+void LLPipeline::toggleRenderHighlights(void*)
+{
+ sRenderHighlight = !sRenderHighlight;
+}
+
+// static
+BOOL LLPipeline::getRenderHighlights(void*)
+{
+ return sRenderHighlight;
+}
+
+LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end,
+ BOOL pick_transparent,
+ S32* face_hit,
+ LLVector3* intersection, // return the intersection point
+ LLVector2* tex_coord, // return the texture coordinates of the intersection point
+ LLVector3* normal, // return the surface normal at the intersection point
+ LLVector3* bi_normal // return the surface bi-normal at the intersection point
+ )
+{
+ LLDrawable* drawable = NULL;
+
+ LLVector3 local_end = end;
+
+ LLVector3 position;
+
+ sPickAvatar = FALSE; //LLToolMgr::getInstance()->inBuildMode() ? FALSE : TRUE;
+
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+
+ for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
+ {
+ if ((j == LLViewerRegion::PARTITION_VOLUME) ||
+ (j == LLViewerRegion::PARTITION_BRIDGE) ||
+ (j == LLViewerRegion::PARTITION_TERRAIN) ||
+ (j == LLViewerRegion::PARTITION_TREE) ||
+ (j == LLViewerRegion::PARTITION_GRASS)) // only check these partitions for now
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(j);
+ if (part && hasRenderType(part->mDrawableType))
+ {
+ LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
+ if (hit)
+ {
+ drawable = hit;
+ local_end = position;
+ }
+ }
+ }
+ }
+ }
+
+ if (!sPickAvatar)
+ {
+ //save hit info in case we need to restore
+ //due to attachment override
+ LLVector3 local_normal;
+ LLVector3 local_binormal;
+ LLVector2 local_texcoord;
+ S32 local_face_hit = -1;
+
+ if (face_hit)
+ {
+ local_face_hit = *face_hit;
+ }
+ if (tex_coord)
+ {
+ local_texcoord = *tex_coord;
+ }
+ if (bi_normal)
+ {
+ local_binormal = *bi_normal;
+ }
+ if (normal)
+ {
+ local_normal = *normal;
+ }
+
+ const F32 ATTACHMENT_OVERRIDE_DIST = 0.1f;
+
+ //check against avatars
+ sPickAvatar = TRUE;
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+
+ LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE);
+ if (part && hasRenderType(part->mDrawableType))
+ {
+ LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
+ if (hit)
+ {
+ if (!drawable ||
+ !drawable->getVObj()->isAttachment() ||
+ (position-local_end).magVec() > ATTACHMENT_OVERRIDE_DIST)
+ { //avatar overrides if previously hit drawable is not an attachment or
+ //attachment is far enough away from detected intersection
+ drawable = hit;
+ local_end = position;
+ }
+ else
+ { //prioritize attachments over avatars
+ position = local_end;
+
+ if (face_hit)
+ {
+ *face_hit = local_face_hit;
+ }
+ if (tex_coord)
+ {
+ *tex_coord = local_texcoord;
+ }
+ if (bi_normal)
+ {
+ *bi_normal = local_binormal;
+ }
+ if (normal)
+ {
+ *normal = local_normal;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //check all avatar nametags (silly, isn't it?)
+ for (std::vector< LLCharacter* >::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end();
+ ++iter)
+ {
+ LLVOAvatar* av = (LLVOAvatar*) *iter;
+ if (av->mNameText.notNull()
+ && av->mNameText->lineSegmentIntersect(start, local_end, position))
+ {
+ drawable = av->mDrawable;
+ local_end = position;
+ }
+ }
+
+ if (intersection)
+ {
+ *intersection = position;
+ }
+
+ return drawable ? drawable->getVObj().get() : NULL;
+}
+
+LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector3& start, const LLVector3& end,
+ BOOL pick_transparent,
+ S32* face_hit,
+ LLVector3* intersection, // return the intersection point
+ LLVector2* tex_coord, // return the texture coordinates of the intersection point
+ LLVector3* normal, // return the surface normal at the intersection point
+ LLVector3* bi_normal // return the surface bi-normal at the intersection point
+ )
+{
+ LLDrawable* drawable = NULL;
+
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+
+ BOOL toggle = FALSE;
+ if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ {
+ toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ toggle = TRUE;
+ }
+
+ LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD);
+ if (part)
+ {
+ LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, face_hit, intersection, tex_coord, normal, bi_normal);
+ if (hit)
+ {
+ drawable = hit;
+ }
+ }
+
+ if (toggle)
+ {
+ toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ }
+ }
+ return drawable ? drawable->getVObj().get() : NULL;
+}
+
+LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj)
+{
+ if (vobj)
+ {
+ LLViewerRegion* region = vobj->getRegion();
+ if (region)
+ {
+ return region->getSpatialPartition(vobj->getPartitionType());
+ }
+ }
+ return NULL;
+}
+
+void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
+{
+ if (!drawable)
+ {
+ return;
+ }
+
+ for (S32 i = 0; i < drawable->getNumFaces(); i++)
+ {
+ LLFace* facep = drawable->getFace(i);
+ facep->clearVertexBuffer();
+ }
+}
+
+void LLPipeline::resetVertexBuffers()
+{
+ mResetVertexBuffers = true;
+}
+
+void LLPipeline::doResetVertexBuffers()
+{
+ if (!mResetVertexBuffers)
+ {
+ return;
+ }
+
+ mResetVertexBuffers = false;
+
+ for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+ for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(i);
+ if (part)
+ {
+ part->resetVertexBuffers();
+ }
+ }
+ }
+
+ resetDrawOrders();
+
+ gSky.resetVertexBuffers();
+
+ if ( LLPathingLib::getInstance() )
+ {
+ LLPathingLib::getInstance()->cleanupVBOManger();
+ }
+ LLVertexBuffer::cleanupClass();
+
+ //delete all name pool caches
+ LLGLNamePool::cleanupPools();
+
+ if (LLVertexBuffer::sGLCount > 0)
+ {
+ llwarns << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << llendl;
+ }
+
+ LLVertexBuffer::unbind();
+
+ sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
+ sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
+ LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
+ LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
+ LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw");
+ LLVertexBuffer::sEnableVBOs = gSavedSettings.getBOOL("RenderVBOEnable");
+ LLVertexBuffer::sDisableVBOMapping = LLVertexBuffer::sEnableVBOs && gSavedSettings.getBOOL("RenderVBOMappingDisable") ;
+ sBakeSunlight = gSavedSettings.getBOOL("RenderBakeSunlight");
+ sNoAlpha = gSavedSettings.getBOOL("RenderNoAlpha");
+ LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind");
+
+ LLVertexBuffer::initClass(LLVertexBuffer::sEnableVBOs, LLVertexBuffer::sDisableVBOMapping);
+}
+
+void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture, BOOL batch_texture)
+{
+ LLMemType mt_ro(LLMemType::MTYPE_PIPELINE_RENDER_OBJECTS);
+ assertInitialized();
+ gGL.loadMatrix(gGLModelView);
+ gGLLastMatrix = NULL;
+ mSimplePool->pushBatches(type, mask, texture, batch_texture);
+ gGL.loadMatrix(gGLModelView);
+ gGLLastMatrix = NULL;
+}
+
+void apply_cube_face_rotation(U32 face)
+{
+ switch (face)
+ {
+ case 0:
+ gGL.rotatef(90.f, 0, 1, 0);
+ gGL.rotatef(180.f, 1, 0, 0);
+ break;
+ case 2:
+ gGL.rotatef(-90.f, 1, 0, 0);
+ break;
+ case 4:
+ gGL.rotatef(180.f, 0, 1, 0);
+ gGL.rotatef(180.f, 0, 0, 1);
+ break;
+ case 1:
+ gGL.rotatef(-90.f, 0, 1, 0);
+ gGL.rotatef(180.f, 1, 0, 0);
+ break;
+ case 3:
+ gGL.rotatef(90, 1, 0, 0);
+ break;
+ case 5:
+ gGL.rotatef(180, 0, 0, 1);
+ break;
+ }
+}
+
+void validate_framebuffer_object()
+{
+ GLenum status;
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
+ switch(status)
+ {
+ case GL_FRAMEBUFFER_COMPLETE:
+ //framebuffer OK, no error.
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ // frame buffer not OK: probably means unsupported depth buffer format
+ llerrs << "Framebuffer Incomplete Missing Attachment." << llendl;
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ // frame buffer not OK: probably means unsupported depth buffer format
+ llerrs << "Framebuffer Incomplete Attachment." << llendl;
+ break;
+ case GL_FRAMEBUFFER_UNSUPPORTED:
+ /* choose different formats */
+ llerrs << "Framebuffer unsupported." << llendl;
+ break;
+ default:
+ llerrs << "Unknown framebuffer status." << llendl;
+ break;
+ }
+}
+
+void LLPipeline::bindScreenToTexture()
+{
+
+}
+
+static LLFastTimer::DeclareTimer FTM_RENDER_BLOOM("Bloom");
+
+void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
+{
+ LLMemType mt_ru(LLMemType::MTYPE_PIPELINE_RENDER_BLOOM);
+ if (!(gPipeline.canUseVertexShaders() &&
+ sRenderGlow))
+ {
+ return;
+ }
+
+ LLVertexBuffer::unbind();
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+
+ assertInitialized();
+
+ if (gUseWireframe)
+ {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+
+ LLVector2 tc1(0,0);
+ LLVector2 tc2((F32) mScreen.getWidth()*2,
+ (F32) mScreen.getHeight()*2);
+
+ LLFastTimer ftm(FTM_RENDER_BLOOM);
+ gGL.color4f(1,1,1,1);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable cull(GL_CULL_FACE);
+
+ enableLightsFullbright(LLColor4(1,1,1,1));
+
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+
+ LLGLDisable test(GL_ALPHA_TEST);
+
+ gGL.setColorMask(true, true);
+ glClearColor(0,0,0,0);
+
+ {
+ {
+ LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
+ mGlow[2].bindTarget();
+ mGlow[2].clear();
+ }
+
+ gGlowExtractProgram.bind();
+ F32 minLum = llmax((F32) RenderGlowMinLuminance, 0.0f);
+ F32 maxAlpha = RenderGlowMaxExtractAlpha;
+ F32 warmthAmount = RenderGlowWarmthAmount;
+ LLVector3 lumWeights = RenderGlowLumWeights;
+ LLVector3 warmthWeights = RenderGlowWarmthWeights;
+
+
+ gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, minLum);
+ gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha);
+ gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1], lumWeights.mV[2]);
+ gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1], warmthWeights.mV[2]);
+ gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount);
+ LLGLEnable blend_on(GL_BLEND);
+ LLGLEnable test(GL_ALPHA_TEST);
+
+ gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+
+ mScreen.bindTexture(0, 0);
+
+ gGL.color4f(1,1,1,1);
+ gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1,-1);
+
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1,3);
+
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3,-1);
+
+ gGL.end();
+
+ gGL.getTexUnit(0)->unbind(mScreen.getUsage());
+
+ mGlow[2].flush();
+ }
+
+ tc1.setVec(0,0);
+ tc2.setVec(2,2);
+
+ // power of two between 1 and 1024
+ U32 glowResPow = RenderGlowResolutionPow;
+ const U32 glow_res = llmax(1,
+ llmin(1024, 1 << glowResPow));
+
+ S32 kernel = RenderGlowIterations*2;
+ F32 delta = RenderGlowWidth / glow_res;
+ // Use half the glow width if we have the res set to less than 9 so that it looks
+ // almost the same in either case.
+ if (glowResPow < 9)
+ {
+ delta *= 0.5f;
+ }
+ F32 strength = RenderGlowStrength;
+
+ gGlowProgram.bind();
+ gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength);
+
+ for (S32 i = 0; i < kernel; i++)
+ {
+ {
+ LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
+ mGlow[i%2].bindTarget();
+ mGlow[i%2].clear();
+ }
+
+ if (i == 0)
+ {
+ gGL.getTexUnit(0)->bind(&mGlow[2]);
+ }
+ else
+ {
+ gGL.getTexUnit(0)->bind(&mGlow[(i-1)%2]);
+ }
+
+ if (i%2 == 0)
+ {
+ gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0);
+ }
+ else
+ {
+ gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta);
+ }
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1,-1);
+
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1,3);
+
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3,-1);
+
+ gGL.end();
+
+ mGlow[i%2].flush();
+ }
+
+ gGlowProgram.unbind();
+
+ if (LLRenderTarget::sUseFBO)
+ {
+ LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+
+ gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+ gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+ gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+ gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+
+ tc2.setVec((F32) mScreen.getWidth(),
+ (F32) mScreen.getHeight());
+
+ gGL.flush();
+
+ LLVertexBuffer::unbind();
+
+ if (LLPipeline::sRenderDeferred)
+ {
+
+ bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() &&
+ !LLToolMgr::getInstance()->inBuildMode() &&
+ RenderDepthOfField;
+
+
+ bool multisample = RenderFSAASamples > 1 && mFXAABuffer.isComplete();
+
+ gViewerWindow->setup3DViewport();
+
+ if (dof_enabled)
+ {
+ LLGLSLShader* shader = &gDeferredPostProgram;
+ LLGLDisable blend(GL_BLEND);
+
+ //depth of field focal plane calculations
+ static F32 current_distance = 16.f;
+ static F32 start_distance = 16.f;
+ static F32 transition_time = 1.f;
+
+ LLVector3 focus_point;
+
+ LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
+ if (obj && obj->mDrawable && obj->isSelected())
+ { //focus on selected media object
+ S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
+ if (obj && obj->mDrawable)
+ {
+ LLFace* face = obj->mDrawable->getFace(face_idx);
+ if (face)
+ {
+ focus_point = face->getPositionAgent();
+ }
+ }
+ }
+
+ if (focus_point.isExactlyZero())
+ {
+ if (LLViewerJoystick::getInstance()->getOverrideCamera())
+ { //focus on point under cursor
+ focus_point = gDebugRaycastIntersection;
+ }
+ else if (gAgentCamera.cameraMouselook())
+ { //focus on point under mouselook crosshairs
+ gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
+ NULL,
+ &focus_point);
+ }
+ else
+ {
+ LLViewerObject* obj = gAgentCamera.getFocusObject();
+ if (obj)
+ { //focus on alt-zoom target
+ focus_point = LLVector3(gAgentCamera.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal());
+ }
+ else
+ { //focus on your avatar
+ focus_point = gAgent.getPositionAgent();
+ }
+ }
+ }
+
+ LLVector3 eye = LLViewerCamera::getInstance()->getOrigin();
+ F32 target_distance = 16.f;
+ if (!focus_point.isExactlyZero())
+ {
+ target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point-eye);
+ }
+
+ if (transition_time >= 1.f &&
+ fabsf(current_distance-target_distance)/current_distance > 0.01f)
+ { //large shift happened, interpolate smoothly to new target distance
+ transition_time = 0.f;
+ start_distance = current_distance;
+ }
+ else if (transition_time < 1.f)
+ { //currently in a transition, continue interpolating
+ transition_time += 1.f/CameraFocusTransitionTime*gFrameIntervalSeconds;
+ transition_time = llmin(transition_time, 1.f);
+
+ F32 t = cosf(transition_time*F_PI+F_PI)*0.5f+0.5f;
+ current_distance = start_distance + (target_distance-start_distance)*t;
+ }
+ else
+ { //small or no change, just snap to target distance
+ current_distance = target_distance;
+ }
+
+ //convert to mm
+ F32 subject_distance = current_distance*1000.f;
+ F32 fnumber = CameraFNumber;
+ F32 default_focal_length = CameraFocalLength;
+
+ F32 fov = LLViewerCamera::getInstance()->getView();
+
+ const F32 default_fov = CameraFieldOfView * F_PI/180.f;
+ //const F32 default_aspect_ratio = gSavedSettings.getF32("CameraAspectRatio");
+
+ //F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight();
+
+ F32 dv = 2.f*default_focal_length * tanf(default_fov/2.f);
+ //F32 dh = 2.f*default_focal_length * tanf(default_fov*default_aspect_ratio/2.f);
+
+ F32 focal_length = dv/(2*tanf(fov/2.f));
+
+ //F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle);
+
+ // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f))
+ // where N = fnumber
+ // s2 = dot distance
+ // s1 = subject distance
+ // f = focal length
+ //
+
+ F32 blur_constant = focal_length*focal_length/(fnumber*(subject_distance-focal_length));
+ blur_constant /= 1000.f; //convert to meters for shader
+ F32 magnification = focal_length/(subject_distance-focal_length);
+
+ { //build diffuse+bloom+CoF
+ mDeferredLight.bindTarget();
+ shader = &gDeferredCoFProgram;
+
+ bindDeferredShader(*shader);
+
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ if (channel > -1)
+ {
+ mScreen.bindTexture(0, channel);
+ }
+
+ shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance/1000.f);
+ shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
+ shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f/LLDrawable::sCurPixelAngle));
+ shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
+ shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+ shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1,-1);
+
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1,3);
+
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3,-1);
+
+ gGL.end();
+
+ unbindDeferredShader(*shader);
+ mDeferredLight.flush();
+ }
+
+ { //perform DoF sampling at half-res (preserve alpha channel)
+ mScreen.bindTarget();
+ glViewport(0,0,(GLsizei) (mScreen.getWidth()*CameraDoFResScale), (GLsizei) (mScreen.getHeight()*CameraDoFResScale));
+ gGL.setColorMask(true, false);
+
+ shader = &gDeferredPostProgram;
+ bindDeferredShader(*shader);
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+ if (channel > -1)
+ {
+ mDeferredLight.bindTexture(0, channel);
+ }
+
+ shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+ shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1,-1);
+
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1,3);
+
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3,-1);
+
+ gGL.end();
+
+ unbindDeferredShader(*shader);
+ mScreen.flush();
+ gGL.setColorMask(true, true);
+ }
+
+ { //combine result based on alpha
+ if (multisample)
+ {
+ mDeferredLight.bindTarget();
+ glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
+ }
+ else
+ {
+ gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+ gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+ gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+ gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+ }
+
+ shader = &gDeferredDoFCombineProgram;
+ bindDeferredShader(*shader);
+
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ if (channel > -1)
+ {
+ mScreen.bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+ shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1,-1);
+
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1,3);
+
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3,-1);
+
+ gGL.end();
+
+ unbindDeferredShader(*shader);
+
+ if (multisample)
+ {
+ mDeferredLight.flush();
+ }
+ }
+ }
+ else
+ {
+ if (multisample)
+ {
+ mDeferredLight.bindTarget();
+ }
+ LLGLSLShader* shader = &gDeferredPostNoDoFProgram;
+
+ bindDeferredShader(*shader);
+
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ if (channel > -1)
+ {
+ mScreen.bindTexture(0, channel);
+ }
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1,-1);
+
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1,3);
+
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3,-1);
+
+ gGL.end();
+
+ unbindDeferredShader(*shader);
+
+ if (multisample)
+ {
+ mDeferredLight.flush();
+ }
+ }
+
+ if (multisample)
+ {
+ //bake out texture2D with RGBL for FXAA shader
+ mFXAABuffer.bindTarget();
+
+ S32 width = mScreen.getWidth();
+ S32 height = mScreen.getHeight();
+ glViewport(0, 0, width, height);
+
+ LLGLSLShader* shader = &gGlowCombineFXAAProgram;
+
+ shader->bind();
+ shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height);
+
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+ if (channel > -1)
+ {
+ mDeferredLight.bindTexture(0, channel);
+ }
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex2f(-1,-1);
+ gGL.vertex2f(-1,3);
+ gGL.vertex2f(3,-1);
+ gGL.end();
+
+ gGL.flush();
+
+ shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+ shader->unbind();
+
+ mFXAABuffer.flush();
+
+ shader = &gFXAAProgram;
+ shader->bind();
+
+ channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage());
+ if (channel > -1)
+ {
+ mFXAABuffer.bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ }
+
+ gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+ gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+ gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+ gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+ glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+
+ F32 scale_x = (F32) width/mFXAABuffer.getWidth();
+ F32 scale_y = (F32) height/mFXAABuffer.getHeight();
+ shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
+ shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f/width*scale_x, 1.f/height*scale_y);
+ shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f/width*scale_x, -0.5f/height*scale_y, 0.5f/width*scale_x, 0.5f/height*scale_y);
+ shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f/width*scale_x, -2.f/height*scale_y, 2.f/width*scale_x, 2.f/height*scale_y);
+
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.vertex2f(-1,-1);
+ gGL.vertex2f(-1,3);
+ gGL.vertex2f(3,-1);
+ gGL.end();
+
+ gGL.flush();
+ shader->unbind();
+ }
+ }
+ else
+ {
+ U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
+ LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
+ buff->allocateBuffer(3,0,TRUE);
+
+ LLStrider<LLVector3> v;
+ LLStrider<LLVector2> uv1;
+ LLStrider<LLVector2> uv2;
+
+ buff->getVertexStrider(v);
+ buff->getTexCoord0Strider(uv1);
+ buff->getTexCoord1Strider(uv2);
+
+ uv1[0] = LLVector2(0, 0);
+ uv1[1] = LLVector2(0, 2);
+ uv1[2] = LLVector2(2, 0);
+
+ uv2[0] = LLVector2(0, 0);
+ uv2[1] = LLVector2(0, tc2.mV[1]*2.f);
+ uv2[2] = LLVector2(tc2.mV[0]*2.f, 0);
+
+ v[0] = LLVector3(-1,-1,0);
+ v[1] = LLVector3(-1,3,0);
+ v[2] = LLVector3(3,-1,0);
+
+ buff->flush();
+
+ LLGLDisable blend(GL_BLEND);
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gGlowCombineProgram.bind();
+ }
+ else
+ {
+ //tex unit 0
+ gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
+ //tex unit 1
+ gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
+ }
+
+ gGL.getTexUnit(0)->bind(&mGlow[1]);
+ gGL.getTexUnit(1)->bind(&mScreen);
+
+ LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
+ buff->setBuffer(mask);
+ buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3);
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gGlowCombineProgram.unbind();
+ }
+ else
+ {
+ gGL.getTexUnit(1)->disable();
+ gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+ gGL.getTexUnit(0)->activate();
+ gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+ }
+
+ }
+
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+ if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
+ {
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gSplatTextureRectProgram.bind();
+ }
+
+ gGL.setColorMask(true, false);
+
+ LLVector2 tc1(0,0);
+ LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2,
+ (F32) gViewerWindow->getWorldViewHeightRaw()*2);
+
+ LLGLEnable blend(GL_BLEND);
+ gGL.color4f(1,1,1,0.75f);
+
+ gGL.getTexUnit(0)->bind(&mPhysicsDisplay);
+
+ gGL.begin(LLRender::TRIANGLES);
+ gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+ gGL.vertex2f(-1,-1);
+
+ gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+ gGL.vertex2f(-1,3);
+
+ gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+ gGL.vertex2f(3,-1);
+
+ gGL.end();
+ gGL.flush();
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gSplatTextureRectProgram.unbind();
+ }
+ }
+
+
+ if (LLRenderTarget::sUseFBO)
+ { //copy depth buffer from mScreen to framebuffer
+ LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(),
+ 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ }
+
+
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+
+}
+
+static LLFastTimer::DeclareTimer FTM_BIND_DEFERRED("Bind Deferred");
+
+void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 noise_map)
+{
+ LLFastTimer t(FTM_BIND_DEFERRED);
+
+ if (noise_map == 0xFFFFFFFF)
+ {
+ noise_map = mNoiseMap;
+ }
+
+ shader.bind();
+ S32 channel = 0;
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
+ if (channel > -1)
+ {
+ mDeferredScreen.bindTexture(0,channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
+ if (channel > -1)
+ {
+ mDeferredScreen.bindTexture(1, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
+ if (channel > -1)
+ {
+ mDeferredScreen.bindTexture(2, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredDepth.getUsage());
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
+ stop_glerror();
+
+ //glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+ //glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);
+
+ stop_glerror();
+
+ glh::matrix4f projection = glh_get_current_projection();
+ glh::matrix4f inv_proj = projection.inverse();
+
+ shader.uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
+ shader.uniform4f(LLShaderMgr::VIEWPORT, (F32) gGLViewport[0],
+ (F32) gGLViewport[1],
+ (F32) gGLViewport[2],
+ (F32) gGLViewport[3]);
+ }
+
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_NOISE);
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, noise_map);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC);
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
+ }
+
+ stop_glerror();
+
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHT, mDeferredLight.getUsage());
+ if (channel > -1)
+ {
+ if (light_index > 0)
+ {
+ mScreen.bindTexture(0, channel);
+ }
+ else
+ {
+ mDeferredLight.bindTexture(0, channel);
+ }
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_BLOOM);
+ if (channel > -1)
+ {
+ mGlow[1].bindTexture(0, channel);
+ }
+
+ stop_glerror();
+
+ for (U32 i = 0; i < 4; i++)
+ {
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE);
+ stop_glerror();
+ if (channel > -1)
+ {
+ stop_glerror();
+ gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+ stop_glerror();
+ }
+ }
+
+ for (U32 i = 4; i < 6; i++)
+ {
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i);
+ stop_glerror();
+ if (channel > -1)
+ {
+ stop_glerror();
+ gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+ stop_glerror();
+ }
+ }
+
+ stop_glerror();
+
+ F32 mat[16*6];
+ for (U32 i = 0; i < 16; i++)
+ {
+ mat[i] = mSunShadowMatrix[0].m[i];
+ mat[i+16] = mSunShadowMatrix[1].m[i];
+ mat[i+32] = mSunShadowMatrix[2].m[i];
+ mat[i+48] = mSunShadowMatrix[3].m[i];
+ mat[i+64] = mSunShadowMatrix[4].m[i];
+ mat[i+80] = mSunShadowMatrix[5].m[i];
+ }
+
+ shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_SHADOW_MATRIX, 6, FALSE, mat);
+
+ stop_glerror();
+
+ channel = shader.enableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
+ if (channel > -1)
+ {
+ LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
+ if (cube_map)
+ {
+ cube_map->enable(channel);
+ cube_map->bind();
+ F32* m = gGLModelView;
+
+ F32 mat[] = { m[0], m[1], m[2],
+ m[4], m[5], m[6],
+ m[8], m[9], m[10] };
+
+ shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat);
+ }
+ }
+
+ shader.uniform4fv(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1, mSunClipPlanes.mV);
+ shader.uniform1f(LLShaderMgr::DEFERRED_SUN_WASH, RenderDeferredSunWash);
+ shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise);
+ shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize);
+
+ shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale);
+ shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, RenderSSAOMaxScale);
+
+ F32 ssao_factor = RenderSSAOFactor;
+ shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR, ssao_factor);
+ shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0/ssao_factor);
+
+ LLVector3 ssao_effect = RenderSSAOEffect;
+ F32 matrix_diag = (ssao_effect[0] + 2.0*ssao_effect[1])/3.0;
+ F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0;
+ // This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by
+ // value factor, and scales remainder by saturation factor
+ F32 ssao_effect_mat[] = { matrix_diag, matrix_nondiag, matrix_nondiag,
+ matrix_nondiag, matrix_diag, matrix_nondiag,
+ matrix_nondiag, matrix_nondiag, matrix_diag};
+ shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_SSAO_EFFECT_MAT, 1, GL_FALSE, ssao_effect_mat);
+
+ F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
+ F32 shadow_bias_error = 1.f + RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
+
+ shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
+ shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear()*2.f);
+ shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset*shadow_offset_error);
+ shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, RenderShadowBias*shadow_bias_error);
+ shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_OFFSET, RenderSpotShadowOffset);
+ shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_BIAS, RenderSpotShadowBias);
+
+ shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV);
+ shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mShadow[0].getWidth(), mShadow[0].getHeight());
+ shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mShadow[4].getWidth(), mShadow[4].getHeight());
+ shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff);
+ shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff);
+
+
+ if (shader.getUniformLocation("norm_mat") >= 0)
+ {
+ glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose();
+ shader.uniformMatrix4fv("norm_mat", 1, FALSE, norm_mat.m);
+ }
+}
+
+static LLFastTimer::DeclareTimer FTM_GI_TRACE("Trace");
+static LLFastTimer::DeclareTimer FTM_GI_GATHER("Gather");
+static LLFastTimer::DeclareTimer FTM_SUN_SHADOW("Shadow Map");
+static LLFastTimer::DeclareTimer FTM_SOFTEN_SHADOW("Shadow Soften");
+static LLFastTimer::DeclareTimer FTM_EDGE_DETECTION("Find Edges");
+static LLFastTimer::DeclareTimer FTM_LOCAL_LIGHTS("Local Lights");
+static LLFastTimer::DeclareTimer FTM_ATMOSPHERICS("Atmospherics");
+static LLFastTimer::DeclareTimer FTM_FULLSCREEN_LIGHTS("Fullscreen Lights");
+static LLFastTimer::DeclareTimer FTM_PROJECTORS("Projectors");
+static LLFastTimer::DeclareTimer FTM_POST("Post");
+
+
+void LLPipeline::renderDeferredLighting()
+{
+ if (!sCull)
+ {
+ return;
+ }
+
+ {
+ LLFastTimer ftm(FTM_RENDER_DEFERRED);
+
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ {
+ LLGLDepthTest depth(GL_TRUE);
+ mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
+ 0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ }
+
+ LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ {
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ }
+
+ //ati doesn't seem to love actually using the stencil buffer on FBO's
+ LLGLDisable stencil(GL_STENCIL_TEST);
+ //glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
+ //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+ gGL.setColorMask(true, true);
+
+ //draw a cube around every light
+ LLVertexBuffer::unbind();
+
+ LLGLEnable cull(GL_CULL_FACE);
+ LLGLEnable blend(GL_BLEND);
+
+ glh::matrix4f mat = glh_copy_matrix(gGLModelView);
+
+ LLStrider<LLVector3> vert;
+ mDeferredVB->getVertexStrider(vert);
+ LLStrider<LLVector2> tc0;
+ LLStrider<LLVector2> tc1;
+ mDeferredVB->getTexCoord0Strider(tc0);
+ mDeferredVB->getTexCoord1Strider(tc1);
+
+ vert[0].set(-1,1,0);
+ vert[1].set(-1,-3,0);
+ vert[2].set(3,1,0);
+
+ {
+ setupHWLights(NULL); //to set mSunDir;
+ LLVector4 dir(mSunDir, 0.f);
+ glh::vec4f tc(dir.mV);
+ mat.mult_matrix_vec(tc);
+ mTransformedSunDir.set(tc.v);
+ }
+
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+
+ if (RenderDeferredSSAO || RenderShadowDetail > 0)
+ {
+ mDeferredLight.bindTarget();
+ { //paint shadow/SSAO light map (direct lighting lightmap)
+ LLFastTimer ftm(FTM_SUN_SHADOW);
+ bindDeferredShader(gDeferredSunProgram, 0);
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ glClearColor(1,1,1,1);
+ mDeferredLight.clear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0,0,0,0);
+
+ glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
+
+ const U32 slice = 32;
+ F32 offset[slice*3];
+ for (U32 i = 0; i < 4; i++)
+ {
+ for (U32 j = 0; j < 8; j++)
+ {
+ glh::vec3f v;
+ v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i);
+ v.normalize();
+ inv_trans.mult_matrix_vec(v);
+ v.normalize();
+ offset[(i*8+j)*3+0] = v.v[0];
+ offset[(i*8+j)*3+1] = v.v[2];
+ offset[(i*8+j)*3+2] = v.v[1];
+ }
+ }
+
+ gDeferredSunProgram.uniform3fv("offset", slice, offset);
+ gDeferredSunProgram.uniform2f("screenRes", mDeferredLight.getWidth(), mDeferredLight.getHeight());
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
+
+ unbindDeferredShader(gDeferredSunProgram);
+ }
+ mDeferredLight.flush();
+ }
+
+ if (RenderDeferredSSAO)
+ { //soften direct lighting lightmap
+ LLFastTimer ftm(FTM_SOFTEN_SHADOW);
+ //blur lightmap
+ mScreen.bindTarget();
+ glClearColor(1,1,1,1);
+ mScreen.clear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0,0,0,0);
+
+ bindDeferredShader(gDeferredBlurLightProgram);
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ LLVector3 go = RenderShadowGaussian;
+ const U32 kern_length = 4;
+ F32 blur_size = RenderShadowBlurSize;
+ F32 dist_factor = RenderShadowBlurDistFactor;
+
+ // sample symmetrically with the middle sample falling exactly on 0.0
+ F32 x = 0.f;
+
+ LLVector3 gauss[32]; // xweight, yweight, offset
+
+ for (U32 i = 0; i < kern_length; i++)
+ {
+ gauss[i].mV[0] = llgaussian(x, go.mV[0]);
+ gauss[i].mV[1] = llgaussian(x, go.mV[1]);
+ gauss[i].mV[2] = x;
+ x += 1.f;
+ }
+
+ gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f);
+ gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor);
+ gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
+ gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
+
+ mScreen.flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
+
+ bindDeferredShader(gDeferredBlurLightProgram, 1);
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ mDeferredLight.bindTarget();
+
+ gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f);
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
+ mDeferredLight.flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
+ }
+
+ stop_glerror();
+ gGL.popMatrix();
+ stop_glerror();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ stop_glerror();
+ gGL.popMatrix();
+ stop_glerror();
+
+ //copy depth and stencil from deferred screen
+ //mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
+ // 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+
+ mScreen.bindTarget();
+ // clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
+ glClearColor(0,0,0,0);
+ mScreen.clear(GL_COLOR_BUFFER_BIT);
+
+ if (RenderDeferredAtmospheric)
+ { //apply sunlight contribution
+ LLFastTimer ftm(FTM_ATMOSPHERICS);
+ bindDeferredShader(gDeferredSoftenProgram);
+ {
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+
+ //full screen blit
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+ }
+
+ unbindDeferredShader(gDeferredSoftenProgram);
+ }
+
+ { //render non-deferred geometry (fullbright, alpha, etc)
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable stencil(GL_STENCIL_TEST);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+ gPipeline.pushRenderTypeMask();
+
+ gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
+ LLPipeline::RENDER_TYPE_CLOUDS,
+ LLPipeline::RENDER_TYPE_WL_SKY,
+ LLPipeline::END_RENDER_TYPES);
+
+
+ renderGeomPostDeferred(*LLViewerCamera::getInstance());
+ gPipeline.popRenderTypeMask();
+ }
+
+ BOOL render_local = RenderLocalLights;
+
+ if (render_local)
+ {
+ gGL.setSceneBlendType(LLRender::BT_ADD);
+ std::list<LLVector4> fullscreen_lights;
+ LLDrawable::drawable_list_t spot_lights;
+ LLDrawable::drawable_list_t fullscreen_spot_lights;
+
+ for (U32 i = 0; i < 2; i++)
+ {
+ mTargetShadowSpotLight[i] = NULL;
+ }
+
+ std::list<LLVector4> light_colors;
+
+ LLVertexBuffer::unbind();
+ LLVector4a* v = (LLVector4a*) vert.get();
+
+ {
+ bindDeferredShader(gDeferredLightProgram);
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
+ {
+ LLDrawable* drawablep = *iter;
+
+ LLVOVolume* volume = drawablep->getVOVolume();
+ if (!volume)
+ {
+ continue;
+ }
+
+ if (volume->isAttachment())
+ {
+ if (!sRenderAttachedLights)
+ {
+ continue;
+ }
+ }
+
+
+ LLVector4a center;
+ center.load3(drawablep->getPositionAgent().mV);
+ const F32* c = center.getF32ptr();
+ F32 s = volume->getLightRadius()*1.5f;
+
+ LLColor3 col = volume->getLightColor();
+
+ if (col.magVecSquared() < 0.001f)
+ {
+ continue;
+ }
+
+ if (s <= 0.001f)
+ {
+ continue;
+ }
+
+ LLVector4a sa;
+ sa.splat(s);
+ if (camera->AABBInFrustumNoFarClip(center, sa) == 0)
+ {
+ continue;
+ }
+
+ sVisibleLightCount++;
+
+ glh::vec3f tc(c);
+ mat.mult_matrix_vec(tc);
+
+ //vertex positions are encoded so the 3 bits of their vertex index
+ //correspond to their axis facing, with bit position 3,2,1 matching
+ //axis facing x,y,z, bit set meaning positive facing, bit clear
+ //meaning negative facing
+ mDeferredVB->getVertexStrider(vert);
+ v[0].set(c[0]-s,c[1]-s,c[2]-s); // 0 - 0000
+ v[1].set(c[0]-s,c[1]-s,c[2]+s); // 1 - 0001
+ v[2].set(c[0]-s,c[1]+s,c[2]-s); // 2 - 0010
+ v[3].set(c[0]-s,c[1]+s,c[2]+s); // 3 - 0011
+
+ v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100
+ v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101
+ v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110
+ v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111
+
+ if (camera->getOrigin().mV[0] > c[0] + s + 0.2f ||
+ camera->getOrigin().mV[0] < c[0] - s - 0.2f ||
+ camera->getOrigin().mV[1] > c[1] + s + 0.2f ||
+ camera->getOrigin().mV[1] < c[1] - s - 0.2f ||
+ camera->getOrigin().mV[2] > c[2] + s + 0.2f ||
+ camera->getOrigin().mV[2] < c[2] - s - 0.2f)
+ { //draw box if camera is outside box
+ if (render_local)
+ {
+ if (volume->isLightSpotlight())
+ {
+ drawablep->getVOVolume()->updateSpotLightPriority();
+ spot_lights.push_back(drawablep);
+ continue;
+ }
+
+ LLFastTimer ftm(FTM_LOCAL_LIGHTS);
+ //glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
+ gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
+ gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
+ gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
+ gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
+ //gGL.diffuseColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
+ gGL.syncMatrices();
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center));
+ stop_glerror();
+ }
+ }
+ else
+ {
+ if (volume->isLightSpotlight())
+ {
+ drawablep->getVOVolume()->updateSpotLightPriority();
+ fullscreen_spot_lights.push_back(drawablep);
+ continue;
+ }
+
+ fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s));
+ light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f));
+ }
+ }
+ unbindDeferredShader(gDeferredLightProgram);
+ }
+
+ if (!spot_lights.empty())
+ {
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ bindDeferredShader(gDeferredSpotLightProgram);
+
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+
+ gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+
+ for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
+ {
+ LLFastTimer ftm(FTM_PROJECTORS);
+ LLDrawable* drawablep = *iter;
+
+ LLVOVolume* volume = drawablep->getVOVolume();
+
+ LLVector4a center;
+ center.load3(drawablep->getPositionAgent().mV);
+ const F32* c = center.getF32ptr();
+ F32 s = volume->getLightRadius()*1.5f;
+
+ sVisibleLightCount++;
+
+ glh::vec3f tc(c);
+ mat.mult_matrix_vec(tc);
+
+ setupSpotLight(gDeferredSpotLightProgram, drawablep);
+
+ LLColor3 col = volume->getLightColor();
+
+ //vertex positions are encoded so the 3 bits of their vertex index
+ //correspond to their axis facing, with bit position 3,2,1 matching
+ //axis facing x,y,z, bit set meaning positive facing, bit clear
+ //meaning negative facing
+ mDeferredVB->getVertexStrider(vert);
+ v[0].set(c[0]-s,c[1]-s,c[2]-s); // 0 - 0000
+ v[1].set(c[0]-s,c[1]-s,c[2]+s); // 1 - 0001
+ v[2].set(c[0]-s,c[1]+s,c[2]-s); // 2 - 0010
+ v[3].set(c[0]-s,c[1]+s,c[2]+s); // 3 - 0011
+
+ v[4].set(c[0]+s,c[1]-s,c[2]-s); // 4 - 0100
+ v[5].set(c[0]+s,c[1]-s,c[2]+s); // 5 - 0101
+ v[6].set(c[0]+s,c[1]+s,c[2]-s); // 6 - 0110
+ v[7].set(c[0]+s,c[1]+s,c[2]+s); // 7 - 0111
+
+ gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
+ gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
+ gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
+ gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
+ gGL.syncMatrices();
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_SHORT, get_box_fan_indices_ptr(camera, center));
+ }
+ gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+ unbindDeferredShader(gDeferredSpotLightProgram);
+ }
+
+ //reset mDeferredVB to fullscreen triangle
+ mDeferredVB->getVertexStrider(vert);
+ vert[0].set(-1,1,0);
+ vert[1].set(-1,-3,0);
+ vert[2].set(3,1,0);
+
+ {
+ bindDeferredShader(gDeferredMultiLightProgram);
+
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+
+ LLGLDepthTest depth(GL_FALSE);
+
+ //full screen blit
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+
+ U32 count = 0;
+
+ const U32 max_count = 8;
+ LLVector4 light[max_count];
+ LLVector4 col[max_count];
+
+// glVertexPointer(2, GL_FLOAT, 0, vert);
+
+ F32 far_z = 0.f;
+
+ while (!fullscreen_lights.empty())
+ {
+ LLFastTimer ftm(FTM_FULLSCREEN_LIGHTS);
+ light[count] = fullscreen_lights.front();
+ fullscreen_lights.pop_front();
+ col[count] = light_colors.front();
+ light_colors.pop_front();
+
+ far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z);
+
+ count++;
+ if (count == max_count || fullscreen_lights.empty())
+ {
+ gDeferredMultiLightProgram.uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count);
+ gDeferredMultiLightProgram.uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light);
+ gDeferredMultiLightProgram.uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col);
+ gDeferredMultiLightProgram.uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z);
+ far_z = 0.f;
+ count = 0;
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ }
+ }
+
+ unbindDeferredShader(gDeferredMultiLightProgram);
+
+ bindDeferredShader(gDeferredMultiSpotLightProgram);
+
+ gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+
+ for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
+ {
+ LLFastTimer ftm(FTM_PROJECTORS);
+ LLDrawable* drawablep = *iter;
+
+ LLVOVolume* volume = drawablep->getVOVolume();
+
+ LLVector3 center = drawablep->getPositionAgent();
+ F32* c = center.mV;
+ F32 s = volume->getLightRadius()*1.5f;
+
+ sVisibleLightCount++;
+
+ glh::vec3f tc(c);
+ mat.mult_matrix_vec(tc);
+
+ setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
+
+ LLColor3 col = volume->getLightColor();
+
+ gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
+ gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s*s);
+ gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
+ gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ }
+
+ gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+ unbindDeferredShader(gDeferredMultiSpotLightProgram);
+
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+ }
+ }
+
+ gGL.setColorMask(true, true);
+ }
+
+ { //render non-deferred geometry (alpha, fullbright, glow)
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable stencil(GL_STENCIL_TEST);
+
+ pushRenderTypeMask();
+ andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA,
+ LLPipeline::RENDER_TYPE_FULLBRIGHT,
+ LLPipeline::RENDER_TYPE_VOLUME,
+ LLPipeline::RENDER_TYPE_GLOW,
+ LLPipeline::RENDER_TYPE_BUMP,
+ LLPipeline::RENDER_TYPE_PASS_SIMPLE,
+ LLPipeline::RENDER_TYPE_PASS_ALPHA,
+ LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
+ LLPipeline::RENDER_TYPE_PASS_BUMP,
+ LLPipeline::RENDER_TYPE_PASS_POST_BUMP,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
+ LLPipeline::RENDER_TYPE_PASS_GLOW,
+ LLPipeline::RENDER_TYPE_PASS_GRASS,
+ LLPipeline::RENDER_TYPE_PASS_SHINY,
+ LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
+ LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
+ LLPipeline::RENDER_TYPE_AVATAR,
+ END_RENDER_TYPES);
+
+ renderGeomPostDeferred(*LLViewerCamera::getInstance());
+ popRenderTypeMask();
+ }
+
+ {
+ //render highlights, etc.
+ renderHighlights();
+ mHighlightFaces.clear();
+
+ renderDebug();
+
+ LLVertexBuffer::unbind();
+
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ // Render debugging beacons.
+ gObjectList.renderObjectBeacons();
+ gObjectList.resetObjectBeacons();
+ }
+ }
+
+ mScreen.flush();
+
+}
+
+void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
+{
+ //construct frustum
+ LLVOVolume* volume = drawablep->getVOVolume();
+ LLVector3 params = volume->getSpotLightParams();
+
+ F32 fov = params.mV[0];
+ F32 focus = params.mV[1];
+
+ LLVector3 pos = drawablep->getPositionAgent();
+ LLQuaternion quat = volume->getRenderRotation();
+ LLVector3 scale = volume->getScale();
+
+ //get near clip plane
+ LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
+ at_axis *= quat;
+
+ LLVector3 np = pos+at_axis;
+ at_axis.normVec();
+
+ //get origin that has given fov for plane np, at_axis, and given scale
+ F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
+
+ LLVector3 origin = np - at_axis*dist;
+
+ //matrix from volume space to agent space
+ LLMatrix4 light_mat(quat, LLVector4(origin,1.f));
+
+ glh::matrix4f light_to_agent((F32*) light_mat.mMatrix);
+ glh::matrix4f light_to_screen = glh_get_current_modelview() * light_to_agent;
+
+ glh::matrix4f screen_to_light = light_to_screen.inverse();
+
+ F32 s = volume->getLightRadius()*1.5f;
+ F32 near_clip = dist;
+ F32 width = scale.mV[VX];
+ F32 height = scale.mV[VY];
+ F32 far_clip = s+dist-scale.mV[VZ];
+
+ F32 fovy = fov * RAD_TO_DEG;
+ F32 aspect = width/height;
+
+ glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
+
+ glh::vec3f p1(0, 0, -(near_clip+0.01f));
+ glh::vec3f p2(0, 0, -(near_clip+1.f));
+
+ glh::vec3f screen_origin(0, 0, 0);
+
+ light_to_screen.mult_matrix_vec(p1);
+ light_to_screen.mult_matrix_vec(p2);
+ light_to_screen.mult_matrix_vec(screen_origin);
+
+ glh::vec3f n = p2-p1;
+ n.normalize();
+
+ F32 proj_range = far_clip - near_clip;
+ glh::matrix4f light_proj = gl_perspective(fovy, aspect, near_clip, far_clip);
+ screen_to_light = trans * light_proj * screen_to_light;
+ shader.uniformMatrix4fv(LLShaderMgr::PROJECTOR_MATRIX, 1, FALSE, screen_to_light.m);
+ shader.uniform1f(LLShaderMgr::PROJECTOR_NEAR, near_clip);
+ shader.uniform3fv(LLShaderMgr::PROJECTOR_P, 1, p1.v);
+ shader.uniform3fv(LLShaderMgr::PROJECTOR_N, 1, n.v);
+ shader.uniform3fv(LLShaderMgr::PROJECTOR_ORIGIN, 1, screen_origin.v);
+ shader.uniform1f(LLShaderMgr::PROJECTOR_RANGE, proj_range);
+ shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIANCE, params.mV[2]);
+ S32 s_idx = -1;
+
+ for (U32 i = 0; i < 2; i++)
+ {
+ if (mShadowSpotLight[i] == drawablep)
+ {
+ s_idx = i;
+ }
+ }
+
+ shader.uniform1i(LLShaderMgr::PROJECTOR_SHADOW_INDEX, s_idx);
+
+ if (s_idx >= 0)
+ {
+ shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f-mSpotLightFade[s_idx]);
+ }
+ else
+ {
+ shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f);
+ }
+
+ {
+ LLDrawable* potential = drawablep;
+ //determine if this is a good light for casting shadows
+ F32 m_pri = volume->getSpotLightPriority();
+
+ for (U32 i = 0; i < 2; i++)
+ {
+ F32 pri = 0.f;
+
+ if (mTargetShadowSpotLight[i].notNull())
+ {
+ pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority();
+ }
+
+ if (m_pri > pri)
+ {
+ LLDrawable* temp = mTargetShadowSpotLight[i];
+ mTargetShadowSpotLight[i] = potential;
+ potential = temp;
+ m_pri = pri;
+ }
+ }
+ }
+
+ LLViewerTexture* img = volume->getLightTexture();
+
+ if (img == NULL)
+ {
+ img = LLViewerFetchedTexture::sWhiteImagep;
+ }
+
+ S32 channel = shader.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+
+ if (channel > -1)
+ {
+ if (img)
+ {
+ gGL.getTexUnit(channel)->bind(img);
+
+ F32 lod_range = logf(img->getWidth())/logf(2.f);
+
+ shader.uniform1f(LLShaderMgr::PROJECTOR_FOCUS, focus);
+ shader.uniform1f(LLShaderMgr::PROJECTOR_LOD, lod_range);
+ shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIENT_LOD, llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f));
+ }
+ }
+
+}
+
+void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
+{
+ stop_glerror();
+ shader.disableTexture(LLShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
+ shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
+ shader.disableTexture(LLShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
+ shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredScreen.getUsage());
+ shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, mDeferredLight.getUsage());
+ shader.disableTexture(LLShaderMgr::DIFFUSE_MAP);
+ shader.disableTexture(LLShaderMgr::DEFERRED_BLOOM);
+
+ for (U32 i = 0; i < 4; i++)
+ {
+ if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE) > -1)
+ {
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+ }
+ }
+
+ for (U32 i = 4; i < 6; i++)
+ {
+ if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i) > -1)
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+ }
+ }
+
+ shader.disableTexture(LLShaderMgr::DEFERRED_NOISE);
+ shader.disableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC);
+
+ S32 channel = shader.disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
+ if (channel > -1)
+ {
+ LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
+ if (cube_map)
+ {
+ cube_map->disable();
+ }
+ }
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.getTexUnit(0)->activate();
+ shader.unbind();
+}
+
+inline float sgn(float a)
+{
+ if (a > 0.0F) return (1.0F);
+ if (a < 0.0F) return (-1.0F);
+ return (0.0F);
+}
+
+void LLPipeline::generateWaterReflection(LLCamera& camera_in)
+{
+ if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate)
+ {
+ BOOL skip_avatar_update = FALSE;
+ if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
+ {
+ skip_avatar_update = TRUE;
+ }
+
+ if (!skip_avatar_update)
+ {
+ gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
+ }
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ LLCamera camera = camera_in;
+ camera.setFar(camera.getFar()*0.87654321f);
+ LLPipeline::sReflectionRender = TRUE;
+
+ gPipeline.pushRenderTypeMask();
+
+ glh::matrix4f projection = glh_get_current_projection();
+ glh::matrix4f mat;
+
+ stop_glerror();
+ LLPlane plane;
+
+ F32 height = gAgent.getRegion()->getWaterHeight();
+ F32 to_clip = fabsf(camera.getOrigin().mV[2]-height);
+ F32 pad = -to_clip*0.05f; //amount to "pad" clip plane by
+
+ //plane params
+ LLVector3 pnorm;
+ F32 pd;
+
+ S32 water_clip = 0;
+ if (!LLViewerCamera::getInstance()->cameraUnderWater())
+ { //camera is above water, clip plane points up
+ pnorm.setVec(0,0,1);
+ pd = -height;
+ plane.setVec(pnorm, pd);
+ water_clip = -1;
+ }
+ else
+ { //camera is below water, clip plane points down
+ pnorm = LLVector3(0,0,-1);
+ pd = height;
+ plane.setVec(pnorm, pd);
+ water_clip = 1;
+ }
+
+ if (!LLViewerCamera::getInstance()->cameraUnderWater())
+ { //generate planar reflection map
+
+ //disable occlusion culling for reflection map for now
+ S32 occlusion = LLPipeline::sUseOcclusion;
+ LLPipeline::sUseOcclusion = 0;
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ glClearColor(0,0,0,0);
+ mWaterRef.bindTarget();
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER0;
+ gGL.setColorMask(true, true);
+ mWaterRef.clear();
+ gGL.setColorMask(true, false);
+
+ mWaterRef.getViewport(gGLViewport);
+
+ stop_glerror();
+
+ gGL.pushMatrix();
+
+ mat.set_scale(glh::vec3f(1,1,-1));
+ mat.set_translate(glh::vec3f(0,0,height*2.f));
+
+ glh::matrix4f current = glh_get_current_modelview();
+
+ mat = current * mat;
+
+ glh_set_current_modelview(mat);
+ gGL.loadMatrix(mat.m);
+
+ LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
+
+ glh::matrix4f inv_mat = mat.inverse();
+
+ glh::vec3f origin(0,0,0);
+ inv_mat.mult_matrix_vec(origin);
+
+ camera.setOrigin(origin.v);
+
+ glCullFace(GL_FRONT);
+
+ static LLCullResult ref_result;
+
+ if (LLDrawPoolWater::sNeedsReflectionUpdate)
+ {
+ //initial sky pass (no user clip plane)
+ { //mask out everything but the sky
+ gPipeline.pushRenderTypeMask();
+ gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
+ LLPipeline::RENDER_TYPE_WL_SKY,
+ LLPipeline::RENDER_TYPE_CLOUDS,
+ LLPipeline::END_RENDER_TYPES);
+
+ static LLCullResult result;
+ updateCull(camera, result);
+ stateSort(camera, result);
+
+ renderGeom(camera, TRUE);
+
+ gPipeline.popRenderTypeMask();
+ }
+
+ gPipeline.pushRenderTypeMask();
+
+ clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
+ LLPipeline::RENDER_TYPE_VOIDWATER,
+ LLPipeline::RENDER_TYPE_GROUND,
+ LLPipeline::RENDER_TYPE_SKY,
+ LLPipeline::RENDER_TYPE_CLOUDS,
+ LLPipeline::END_RENDER_TYPES);
+
+ S32 detail = RenderReflectionDetail;
+ if (detail > 0)
+ { //mask out selected geometry based on reflection detail
+ if (detail < 4)
+ {
+ clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES);
+ if (detail < 3)
+ {
+ clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
+ if (detail < 2)
+ {
+ clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES);
+ }
+ }
+ }
+
+ LLGLUserClipPlane clip_plane(plane, mat, projection);
+ LLGLDisable cull(GL_CULL_FACE);
+ updateCull(camera, ref_result, -water_clip, &plane);
+ stateSort(camera, ref_result);
+ }
+
+ if (LLDrawPoolWater::sNeedsDistortionUpdate)
+ {
+ if (RenderReflectionDetail > 0)
+ {
+ gPipeline.grabReferences(ref_result);
+ LLGLUserClipPlane clip_plane(plane, mat, projection);
+ renderGeom(camera);
+ }
+ }
+
+ gPipeline.popRenderTypeMask();
+ }
+ glCullFace(GL_BACK);
+ gGL.popMatrix();
+ mWaterRef.flush();
+ glh_set_current_modelview(current);
+ LLPipeline::sUseOcclusion = occlusion;
+ }
+
+ camera.setOrigin(camera_in.getOrigin());
+ //render distortion map
+ static BOOL last_update = TRUE;
+ if (last_update)
+ {
+ camera.setFar(camera_in.getFar());
+ clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
+ LLPipeline::RENDER_TYPE_VOIDWATER,
+ LLPipeline::RENDER_TYPE_GROUND,
+ END_RENDER_TYPES);
+ stop_glerror();
+
+ LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? FALSE : TRUE;
+
+ if (LLPipeline::sUnderWaterRender)
+ {
+ clearRenderTypeMask(LLPipeline::RENDER_TYPE_GROUND,
+ LLPipeline::RENDER_TYPE_SKY,
+ LLPipeline::RENDER_TYPE_CLOUDS,
+ LLPipeline::RENDER_TYPE_WL_SKY,
+ END_RENDER_TYPES);
+ }
+ LLViewerCamera::updateFrustumPlanes(camera);
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ LLColor4& col = LLDrawPoolWater::sWaterFogColor;
+ glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
+ mWaterDis.bindTarget();
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1;
+ mWaterDis.getViewport(gGLViewport);
+
+ if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate)
+ {
+ //clip out geometry on the same side of water as the camera
+ mat = glh_get_current_modelview();
+ LLPlane plane(-pnorm, -(pd+pad));
+
+ LLGLUserClipPlane clip_plane(plane, mat, projection);
+ static LLCullResult result;
+ updateCull(camera, result, water_clip, &plane);
+ stateSort(camera, result);
+
+ gGL.setColorMask(true, true);
+ mWaterDis.clear();
+ gGL.setColorMask(true, false);
+
+ renderGeom(camera);
+
+ }
+
+ LLPipeline::sUnderWaterRender = FALSE;
+ mWaterDis.flush();
+ }
+ last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
+
+ LLRenderTarget::unbindTarget();
+
+ LLPipeline::sReflectionRender = FALSE;
+
+ if (!LLRenderTarget::sUseFBO)
+ {
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+ glClearColor(0.f, 0.f, 0.f, 0.f);
+ gViewerWindow->setup3DViewport();
+ gPipeline.popRenderTypeMask();
+ LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
+ LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
+ LLPlane npnorm(-pnorm, -pd);
+ LLViewerCamera::getInstance()->setUserClipPlane(npnorm);
+
+ LLGLState::checkStates();
+
+ if (!skip_avatar_update)
+ {
+ gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
+ }
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ }
+}
+
+glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up)
+{
+ glh::matrix4f ret;
+
+ LLVector3 dirN;
+ LLVector3 upN;
+ LLVector3 lftN;
+
+ lftN = dir % up;
+ lftN.normVec();
+
+ upN = lftN % dir;
+ upN.normVec();
+
+ dirN = dir;
+ dirN.normVec();
+
+ ret.m[ 0] = lftN[0];
+ ret.m[ 1] = upN[0];
+ ret.m[ 2] = -dirN[0];
+ ret.m[ 3] = 0.f;
+
+ ret.m[ 4] = lftN[1];
+ ret.m[ 5] = upN[1];
+ ret.m[ 6] = -dirN[1];
+ ret.m[ 7] = 0.f;
+
+ ret.m[ 8] = lftN[2];
+ ret.m[ 9] = upN[2];
+ ret.m[10] = -dirN[2];
+ ret.m[11] = 0.f;
+
+ ret.m[12] = -(lftN*pos);
+ ret.m[13] = -(upN*pos);
+ ret.m[14] = dirN*pos;
+ ret.m[15] = 1.f;
+
+ return ret;
+}
+
+glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max)
+{
+ glh::matrix4f ret;
+ ret.m[ 0] = 2/(max[0]-min[0]);
+ ret.m[ 4] = 0;
+ ret.m[ 8] = 0;
+ ret.m[12] = -(max[0]+min[0])/(max[0]-min[0]);
+
+ ret.m[ 1] = 0;
+ ret.m[ 5] = 2/(max[1]-min[1]);
+ ret.m[ 9] = 0;
+ ret.m[13] = -(max[1]+min[1])/(max[1]-min[1]);
+
+ ret.m[ 2] = 0;
+ ret.m[ 6] = 0;
+ ret.m[10] = 2/(max[2]-min[2]);
+ ret.m[14] = -(max[2]+min[2])/(max[2]-min[2]);
+
+ ret.m[ 3] = 0;
+ ret.m[ 7] = 0;
+ ret.m[11] = 0;
+ ret.m[15] = 1;
+
+ return ret;
+}
+
+static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows");
+static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow");
+static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow");
+
+void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion)
+{
+ LLFastTimer t(FTM_SHADOW_RENDER);
+
+ //clip out geometry on the same side of water as the camera
+ S32 occlude = LLPipeline::sUseOcclusion;
+ if (!use_occlusion)
+ {
+ LLPipeline::sUseOcclusion = 0;
+ }
+ LLPipeline::sShadowRender = TRUE;
+
+ U32 types[] = {
+ LLRenderPass::PASS_SIMPLE,
+ LLRenderPass::PASS_FULLBRIGHT,
+ LLRenderPass::PASS_SHINY,
+ LLRenderPass::PASS_BUMP,
+ LLRenderPass::PASS_FULLBRIGHT_SHINY
+ };
+
+ LLGLEnable cull(GL_CULL_FACE);
+
+ if (use_shader)
+ {
+ gDeferredShadowProgram.bind();
+ }
+
+ updateCull(shadow_cam, result);
+ stateSort(shadow_cam, result);
+
+ //generate shadow map
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadMatrix(proj.m);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.pushMatrix();
+ gGL.loadMatrix(gGLModelView);
+
+ stop_glerror();
+ gGLLastMatrix = NULL;
+
+ {
+ //LLGLDepthTest depth(GL_TRUE);
+ //glClear(GL_DEPTH_BUFFER_BIT);
+ }
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ stop_glerror();
+
+ //glCullFace(GL_FRONT);
+
+ LLVertexBuffer::unbind();
+
+ {
+ if (!use_shader)
+ { //occlusion program is general purpose depth-only no-textures
+ gOcclusionProgram.bind();
+ }
+
+ gGL.diffuseColor4f(1,1,1,1);
+ gGL.setColorMask(false, false);
+
+ LLFastTimer ftm(FTM_SHADOW_SIMPLE);
+ gGL.getTexUnit(0)->disable();
+ for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i)
+ {
+ renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
+ }
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ if (!use_shader)
+ {
+ gOcclusionProgram.unbind();
+ }
+ }
+
+ if (use_shader)
+ {
+ gDeferredShadowProgram.unbind();
+ renderGeomShadow(shadow_cam);
+ gDeferredShadowProgram.bind();
+ }
+ else
+ {
+ renderGeomShadow(shadow_cam);
+ }
+
+ {
+ LLFastTimer ftm(FTM_SHADOW_ALPHA);
+ gDeferredShadowAlphaMaskProgram.bind();
+ gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f);
+
+ U32 mask = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_TEXCOORD0 |
+ LLVertexBuffer::MAP_COLOR |
+ LLVertexBuffer::MAP_TEXTURE_INDEX;
+
+ renderObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE);
+ renderObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE);
+ renderObjects(LLRenderPass::PASS_ALPHA, mask, TRUE, TRUE);
+ gDeferredTreeShadowProgram.bind();
+ gDeferredTreeShadowProgram.setMinimumAlpha(0.598f);
+ renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
+ }
+
+ //glCullFace(GL_BACK);
+
+ gDeferredShadowProgram.bind();
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
+ doOcclusion(shadow_cam);
+
+ if (use_shader)
+ {
+ gDeferredShadowProgram.unbind();
+ }
+
+ gGL.setColorMask(true, true);
+
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+ gGLLastMatrix = NULL;
+
+ LLPipeline::sUseOcclusion = occlude;
+ LLPipeline::sShadowRender = FALSE;
+}
+
+static LLFastTimer::DeclareTimer FTM_VISIBLE_CLOUD("Visible Cloud");
+BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir)
+{
+ LLFastTimer t(FTM_VISIBLE_CLOUD);
+ //get point cloud of intersection of frust and min, max
+
+ if (getVisibleExtents(camera, min, max))
+ {
+ return FALSE;
+ }
+
+ //get set of planes on bounding box
+ LLPlane bp[] = {
+ LLPlane(min, LLVector3(-1,0,0)),
+ LLPlane(min, LLVector3(0,-1,0)),
+ LLPlane(min, LLVector3(0,0,-1)),
+ LLPlane(max, LLVector3(1,0,0)),
+ LLPlane(max, LLVector3(0,1,0)),
+ LLPlane(max, LLVector3(0,0,1))};
+
+ //potential points
+ std::vector<LLVector3> pp;
+
+ //add corners of AABB
+ pp.push_back(LLVector3(min.mV[0], min.mV[1], min.mV[2]));
+ pp.push_back(LLVector3(max.mV[0], min.mV[1], min.mV[2]));
+ pp.push_back(LLVector3(min.mV[0], max.mV[1], min.mV[2]));
+ pp.push_back(LLVector3(max.mV[0], max.mV[1], min.mV[2]));
+ pp.push_back(LLVector3(min.mV[0], min.mV[1], max.mV[2]));
+ pp.push_back(LLVector3(max.mV[0], min.mV[1], max.mV[2]));
+ pp.push_back(LLVector3(min.mV[0], max.mV[1], max.mV[2]));
+ pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2]));
+
+ //add corners of camera frustum
+ for (U32 i = 0; i < 8; i++)
+ {
+ pp.push_back(camera.mAgentFrustum[i]);
+ }
+
+
+ //bounding box line segments
+ U32 bs[] =
+ {
+ 0,1,
+ 1,3,
+ 3,2,
+ 2,0,
+
+ 4,5,
+ 5,7,
+ 7,6,
+ 6,4,
+
+ 0,4,
+ 1,5,
+ 3,7,
+ 2,6
+ };
+
+ for (U32 i = 0; i < 12; i++)
+ { //for each line segment in bounding box
+ for (U32 j = 0; j < 6; j++)
+ { //for each plane in camera frustum
+ const LLPlane& cp = camera.getAgentPlane(j);
+ const LLVector3& v1 = pp[bs[i*2+0]];
+ const LLVector3& v2 = pp[bs[i*2+1]];
+ LLVector3 n;
+ cp.getVector3(n);
+
+ LLVector3 line = v1-v2;
+
+ F32 d1 = line*n;
+ F32 d2 = -cp.dist(v2);
+
+ F32 t = d2/d1;
+
+ if (t > 0.f && t < 1.f)
+ {
+ LLVector3 intersect = v2+line*t;
+ pp.push_back(intersect);
+ }
+ }
+ }
+
+ //camera frustum line segments
+ const U32 fs[] =
+ {
+ 0,1,
+ 1,2,
+ 2,3,
+ 3,0,
+
+ 4,5,
+ 5,6,
+ 6,7,
+ 7,4,
+
+ 0,4,
+ 1,5,
+ 2,6,
+ 3,7
+ };
+
+ LLVector3 center = (max+min)*0.5f;
+ LLVector3 size = (max-min)*0.5f;
+
+ for (U32 i = 0; i < 12; i++)
+ {
+ for (U32 j = 0; j < 6; ++j)
+ {
+ const LLVector3& v1 = pp[fs[i*2+0]+8];
+ const LLVector3& v2 = pp[fs[i*2+1]+8];
+ const LLPlane& cp = bp[j];
+ LLVector3 n;
+ cp.getVector3(n);
+
+ LLVector3 line = v1-v2;
+
+ F32 d1 = line*n;
+ F32 d2 = -cp.dist(v2);
+
+ F32 t = d2/d1;
+
+ if (t > 0.f && t < 1.f)
+ {
+ LLVector3 intersect = v2+line*t;
+ pp.push_back(intersect);
+ }
+ }
+ }
+
+ LLVector3 ext[] = { min-LLVector3(0.05f,0.05f,0.05f),
+ max+LLVector3(0.05f,0.05f,0.05f) };
+
+ for (U32 i = 0; i < pp.size(); ++i)
+ {
+ bool found = true;
+
+ const F32* p = pp[i].mV;
+
+ for (U32 j = 0; j < 3; ++j)
+ {
+ if (p[j] < ext[0].mV[j] ||
+ p[j] > ext[1].mV[j])
+ {
+ found = false;
+ break;
+ }
+ }
+
+ for (U32 j = 0; j < 6; ++j)
+ {
+ const LLPlane& cp = camera.getAgentPlane(j);
+ F32 dist = cp.dist(pp[i]);
+ if (dist > 0.05f) //point is above some plane, not contained
+ {
+ found = false;
+ break;
+ }
+ }
+
+ if (found)
+ {
+ fp.push_back(pp[i]);
+ }
+ }
+
+ if (fp.empty())
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade)
+{
+ if (obj && obj->getVolume())
+ {
+ for (LLViewerObject::child_list_t::const_iterator iter = obj->getChildren().begin(); iter != obj->getChildren().end(); ++iter)
+ {
+ renderHighlight(*iter, fade);
+ }
+
+ LLDrawable* drawable = obj->mDrawable;
+ if (drawable)
+ {
+ for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+ {
+ LLFace* face = drawable->getFace(i);
+ if (face)
+ {
+ face->renderSelected(LLViewerTexture::sNullImagep, LLColor4(1,1,1,fade));
+ }
+ }
+ }
+ }
+}
+
+void LLPipeline::generateHighlight(LLCamera& camera)
+{
+ //render highlighted object as white into offscreen render target
+ if (mHighlightObject.notNull())
+ {
+ mHighlightSet.insert(HighlightItem(mHighlightObject));
+ }
+
+ if (!mHighlightSet.empty())
+ {
+ F32 transition = gFrameIntervalSeconds/RenderHighlightFadeTime;
+
+ LLGLDisable test(GL_ALPHA_TEST);
+ LLGLDepthTest depth(GL_FALSE);
+ mHighlight.bindTarget();
+ disableLights();
+ gGL.setColorMask(true, true);
+ mHighlight.clear();
+
+ gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
+ for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); )
+ {
+ std::set<HighlightItem>::iterator cur_iter = iter++;
+
+ if (cur_iter->mItem.isNull())
+ {
+ mHighlightSet.erase(cur_iter);
+ continue;
+ }
+
+ if (cur_iter->mItem == mHighlightObject)
+ {
+ cur_iter->incrFade(transition);
+ }
+ else
+ {
+ cur_iter->incrFade(-transition);
+ if (cur_iter->mFade <= 0.f)
+ {
+ mHighlightSet.erase(cur_iter);
+ continue;
+ }
+ }
+
+ renderHighlight(cur_iter->mItem->getVObj(), cur_iter->mFade);
+ }
+
+ mHighlight.flush();
+ gGL.setColorMask(true, false);
+ gViewerWindow->setup3DViewport();
+ }
+}
+
+
+void LLPipeline::generateSunShadow(LLCamera& camera)
+{
+ if (!sRenderDeferred || RenderShadowDetail <= 0)
+ {
+ return;
+ }
+
+ BOOL skip_avatar_update = FALSE;
+ if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
+ {
+
+ skip_avatar_update = TRUE;
+ }
+
+ if (!skip_avatar_update)
+ {
+ gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
+ }
+
+ F64 last_modelview[16];
+ F64 last_projection[16];
+ for (U32 i = 0; i < 16; i++)
+ { //store last_modelview of world camera
+ last_modelview[i] = gGLLastModelView[i];
+ last_projection[i] = gGLLastProjection[i];
+ }
+
+ pushRenderTypeMask();
+ andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE,
+ LLPipeline::RENDER_TYPE_ALPHA,
+ LLPipeline::RENDER_TYPE_GRASS,
+ LLPipeline::RENDER_TYPE_FULLBRIGHT,
+ LLPipeline::RENDER_TYPE_BUMP,
+ LLPipeline::RENDER_TYPE_VOLUME,
+ LLPipeline::RENDER_TYPE_AVATAR,
+ LLPipeline::RENDER_TYPE_TREE,
+ LLPipeline::RENDER_TYPE_TERRAIN,
+ LLPipeline::RENDER_TYPE_WATER,
+ LLPipeline::RENDER_TYPE_VOIDWATER,
+ LLPipeline::RENDER_TYPE_PASS_ALPHA,
+ LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
+ LLPipeline::RENDER_TYPE_PASS_GRASS,
+ LLPipeline::RENDER_TYPE_PASS_SIMPLE,
+ LLPipeline::RENDER_TYPE_PASS_BUMP,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
+ LLPipeline::RENDER_TYPE_PASS_SHINY,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
+ END_RENDER_TYPES);
+
+ gGL.setColorMask(false, false);
+
+ //get sun view matrix
+
+ //store current projection/modelview matrix
+ glh::matrix4f saved_proj = glh_get_current_projection();
+ glh::matrix4f saved_view = glh_get_current_modelview();
+ glh::matrix4f inv_view = saved_view.inverse();
+
+ glh::matrix4f view[6];
+ glh::matrix4f proj[6];
+
+ //clip contains parallel split distances for 3 splits
+ LLVector3 clip = RenderShadowClipPlanes;
+
+ //F32 slope_threshold = gSavedSettings.getF32("RenderShadowSlopeThreshold");
+
+ //far clip on last split is minimum of camera view distance and 128
+ mSunClipPlanes = LLVector4(clip, clip.mV[2] * clip.mV[2]/clip.mV[1]);
+
+ clip = RenderShadowOrthoClipPlanes;
+ mSunOrthoClipPlanes = LLVector4(clip, clip.mV[2]*clip.mV[2]/clip.mV[1]);
+
+ //currently used for amount to extrude frusta corners for constructing shadow frusta
+ LLVector3 n = RenderShadowNearDist;
+ //F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
+
+ //put together a universal "near clip" plane for shadow frusta
+ LLPlane shadow_near_clip;
+ {
+ LLVector3 p = gAgent.getPositionAgent();
+ p += mSunDir * RenderFarClip*2.f;
+ shadow_near_clip.setVec(p, mSunDir);
+ }
+
+ LLVector3 lightDir = -mSunDir;
+ lightDir.normVec();
+
+ glh::vec3f light_dir(lightDir.mV);
+
+ //create light space camera matrix
+
+ LLVector3 at = lightDir;
+
+ LLVector3 up = camera.getAtAxis();
+
+ if (fabsf(up*lightDir) > 0.75f)
+ {
+ up = camera.getUpAxis();
+ }
+
+ /*LLVector3 left = up%at;
+ up = at%left;*/
+
+ up.normVec();
+ at.normVec();
+
+
+ LLCamera main_camera = camera;
+
+ F32 near_clip = 0.f;
+ {
+ //get visible point cloud
+ std::vector<LLVector3> fp;
+
+ main_camera.calcAgentFrustumPlanes(main_camera.mAgentFrustum);
+
+ LLVector3 min,max;
+ getVisiblePointCloud(main_camera,min,max,fp);
+
+ if (fp.empty())
+ {
+ if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ mShadowCamera[0] = main_camera;
+ mShadowExtents[0][0] = min;
+ mShadowExtents[0][1] = max;
+
+ mShadowFrustPoints[0].clear();
+ mShadowFrustPoints[1].clear();
+ mShadowFrustPoints[2].clear();
+ mShadowFrustPoints[3].clear();
+ }
+ popRenderTypeMask();
+
+ if (!skip_avatar_update)
+ {
+ gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
+ }
+
+ return;
+ }
+
+ //get good split distances for frustum
+ for (U32 i = 0; i < fp.size(); ++i)
+ {
+ glh::vec3f v(fp[i].mV);
+ saved_view.mult_matrix_vec(v);
+ fp[i].setVec(v.v);
+ }
+
+ min = fp[0];
+ max = fp[0];
+
+ //get camera space bounding box
+ for (U32 i = 1; i < fp.size(); ++i)
+ {
+ update_min_max(min, max, fp[i]);
+ }
+
+ near_clip = -max.mV[2];
+ F32 far_clip = -min.mV[2]*2.f;
+
+ //far_clip = llmin(far_clip, 128.f);
+ far_clip = llmin(far_clip, camera.getFar());
+
+ F32 range = far_clip-near_clip;
+
+ LLVector3 split_exp = RenderShadowSplitExponent;
+
+ F32 da = 1.f-llmax( fabsf(lightDir*up), fabsf(lightDir*camera.getLeftAxis()) );
+
+ da = powf(da, split_exp.mV[2]);
+
+
+ F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da;
+
+
+ for (U32 i = 0; i < 4; ++i)
+ {
+ F32 x = (F32)(i+1)/4.f;
+ x = powf(x, sxp);
+ mSunClipPlanes.mV[i] = near_clip+range*x;
+ }
+ }
+
+ // convenience array of 4 near clip plane distances
+ F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
+
+
+ if (mSunDiffuse == LLColor4::black)
+ { //sun diffuse is totally black, shadows don't matter
+ LLGLDepthTest depth(GL_TRUE);
+
+ for (S32 j = 0; j < 4; j++)
+ {
+ mShadow[j].bindTarget();
+ mShadow[j].clear();
+ mShadow[j].flush();
+ }
+ }
+ else
+ {
+ for (S32 j = 0; j < 4; j++)
+ {
+ if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ mShadowFrustPoints[j].clear();
+ }
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+j;
+
+ //restore render matrices
+ glh_set_current_modelview(saved_view);
+ glh_set_current_projection(saved_proj);
+
+ LLVector3 eye = camera.getOrigin();
+
+ //camera used for shadow cull/render
+ LLCamera shadow_cam;
+
+ //create world space camera frustum for this split
+ shadow_cam = camera;
+ shadow_cam.setFar(16.f);
+
+ LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+
+ LLVector3* frust = shadow_cam.mAgentFrustum;
+
+ LLVector3 pn = shadow_cam.getAtAxis();
+
+ LLVector3 min, max;
+
+ //construct 8 corners of split frustum section
+ for (U32 i = 0; i < 4; i++)
+ {
+ LLVector3 delta = frust[i+4]-eye;
+ delta += (frust[i+4]-frust[(i+2)%4+4])*0.05f;
+ delta.normVec();
+ F32 dp = delta*pn;
+ frust[i] = eye + (delta*dist[j]*0.95f)/dp;
+ frust[i+4] = eye + (delta*dist[j+1]*1.05f)/dp;
+ }
+
+ shadow_cam.calcAgentFrustumPlanes(frust);
+ shadow_cam.mFrustumCornerDist = 0.f;
+
+ if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ mShadowCamera[j] = shadow_cam;
+ }
+
+ std::vector<LLVector3> fp;
+
+ if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir))
+ {
+ //no possible shadow receivers
+ if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ mShadowExtents[j][0] = LLVector3();
+ mShadowExtents[j][1] = LLVector3();
+ mShadowCamera[j+4] = shadow_cam;
+ }
+
+ mShadow[j].bindTarget();
+ {
+ LLGLDepthTest depth(GL_TRUE);
+ mShadow[j].clear();
+ }
+ mShadow[j].flush();
+
+ mShadowError.mV[j] = 0.f;
+ mShadowFOV.mV[j] = 0.f;
+
+ continue;
+ }
+
+ if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ mShadowExtents[j][0] = min;
+ mShadowExtents[j][1] = max;
+ mShadowFrustPoints[j] = fp;
+ }
+
+
+ //find a good origin for shadow projection
+ LLVector3 origin;
+
+ //get a temporary view projection
+ view[j] = look(camera.getOrigin(), lightDir, -up);
+
+ std::vector<LLVector3> wpf;
+
+ for (U32 i = 0; i < fp.size(); i++)
+ {
+ glh::vec3f p = glh::vec3f(fp[i].mV);
+ view[j].mult_matrix_vec(p);
+ wpf.push_back(LLVector3(p.v));
+ }
+
+ min = wpf[0];
+ max = wpf[0];
+
+ for (U32 i = 0; i < fp.size(); ++i)
+ { //get AABB in camera space
+ update_min_max(min, max, wpf[i]);
+ }
+
+ // Construct a perspective transform with perspective along y-axis that contains
+ // points in wpf
+ //Known:
+ // - far clip plane
+ // - near clip plane
+ // - points in frustum
+ //Find:
+ // - origin
+
+ //get some "interesting" points of reference
+ LLVector3 center = (min+max)*0.5f;
+ LLVector3 size = (max-min)*0.5f;
+ LLVector3 near_center = center;
+ near_center.mV[1] += size.mV[1]*2.f;
+
+
+ //put all points in wpf in quadrant 0, reletive to center of min/max
+ //get the best fit line using least squares
+ F32 bfm = 0.f;
+ F32 bfb = 0.f;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ wpf[i] -= center;
+ wpf[i].mV[0] = fabsf(wpf[i].mV[0]);
+ wpf[i].mV[2] = fabsf(wpf[i].mV[2]);
+ }
+
+ if (!wpf.empty())
+ {
+ F32 sx = 0.f;
+ F32 sx2 = 0.f;
+ F32 sy = 0.f;
+ F32 sxy = 0.f;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ sx += wpf[i].mV[0];
+ sx2 += wpf[i].mV[0]*wpf[i].mV[0];
+ sy += wpf[i].mV[1];
+ sxy += wpf[i].mV[0]*wpf[i].mV[1];
+ }
+
+ bfm = (sy*sx-wpf.size()*sxy)/(sx*sx-wpf.size()*sx2);
+ bfb = (sx*sxy-sy*sx2)/(sx*sx-bfm*sx2);
+ }
+
+ {
+ // best fit line is y=bfm*x+bfb
+
+ //find point that is furthest to the right of line
+ F32 off_x = -1.f;
+ LLVector3 lp;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ //y = bfm*x+bfb
+ //x = (y-bfb)/bfm
+ F32 lx = (wpf[i].mV[1]-bfb)/bfm;
+
+ lx = wpf[i].mV[0]-lx;
+
+ if (off_x < lx)
+ {
+ off_x = lx;
+ lp = wpf[i];
+ }
+ }
+
+ //get line with slope bfm through lp
+ // bfb = y-bfm*x
+ bfb = lp.mV[1]-bfm*lp.mV[0];
+
+ //calculate error
+ mShadowError.mV[j] = 0.f;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ F32 lx = (wpf[i].mV[1]-bfb)/bfm;
+ mShadowError.mV[j] += fabsf(wpf[i].mV[0]-lx);
+ }
+
+ mShadowError.mV[j] /= wpf.size();
+ mShadowError.mV[j] /= size.mV[0];
+
+ if (mShadowError.mV[j] > RenderShadowErrorCutoff)
+ { //just use ortho projection
+ mShadowFOV.mV[j] = -1.f;
+ origin.clearVec();
+ proj[j] = gl_ortho(min.mV[0], max.mV[0],
+ min.mV[1], max.mV[1],
+ -max.mV[2], -min.mV[2]);
+ }
+ else
+ {
+ //origin is where line x = 0;
+ origin.setVec(0,bfb,0);
+
+ F32 fovz = 1.f;
+ F32 fovx = 1.f;
+
+ LLVector3 zp;
+ LLVector3 xp;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ LLVector3 atz = wpf[i]-origin;
+ atz.mV[0] = 0.f;
+ atz.normVec();
+ if (fovz > -atz.mV[1])
+ {
+ zp = wpf[i];
+ fovz = -atz.mV[1];
+ }
+
+ LLVector3 atx = wpf[i]-origin;
+ atx.mV[2] = 0.f;
+ atx.normVec();
+ if (fovx > -atx.mV[1])
+ {
+ fovx = -atx.mV[1];
+ xp = wpf[i];
+ }
+ }
+
+ fovx = acos(fovx);
+ fovz = acos(fovz);
+
+ F32 cutoff = llmin((F32) RenderShadowFOVCutoff, 1.4f);
+
+ mShadowFOV.mV[j] = fovx;
+
+ if (fovx < cutoff && fovz > cutoff)
+ {
+ //x is a good fit, but z is too big, move away from zp enough so that fovz matches cutoff
+ F32 d = zp.mV[2]/tan(cutoff);
+ F32 ny = zp.mV[1] + fabsf(d);
+
+ origin.mV[1] = ny;
+
+ fovz = 1.f;
+ fovx = 1.f;
+
+ for (U32 i = 0; i < wpf.size(); ++i)
+ {
+ LLVector3 atz = wpf[i]-origin;
+ atz.mV[0] = 0.f;
+ atz.normVec();
+ fovz = llmin(fovz, -atz.mV[1]);
+
+ LLVector3 atx = wpf[i]-origin;
+ atx.mV[2] = 0.f;
+ atx.normVec();
+ fovx = llmin(fovx, -atx.mV[1]);
+ }
+
+ fovx = acos(fovx);
+ fovz = acos(fovz);
+
+ mShadowFOV.mV[j] = cutoff;
+ }
+
+
+ origin += center;
+
+ F32 ynear = -(max.mV[1]-origin.mV[1]);
+ F32 yfar = -(min.mV[1]-origin.mV[1]);
+
+ if (ynear < 0.1f) //keep a sensible near clip plane
+ {
+ F32 diff = 0.1f-ynear;
+ origin.mV[1] += diff;
+ ynear += diff;
+ yfar += diff;
+ }
+
+ if (fovx > cutoff)
+ { //just use ortho projection
+ origin.clearVec();
+ mShadowError.mV[j] = -1.f;
+ proj[j] = gl_ortho(min.mV[0], max.mV[0],
+ min.mV[1], max.mV[1],
+ -max.mV[2], -min.mV[2]);
+ }
+ else
+ {
+ //get perspective projection
+ view[j] = view[j].inverse();
+
+ glh::vec3f origin_agent(origin.mV);
+
+ //translate view to origin
+ view[j].mult_matrix_vec(origin_agent);
+
+ eye = LLVector3(origin_agent.v);
+
+ if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ mShadowFrustOrigin[j] = eye;
+ }
+
+ view[j] = look(LLVector3(origin_agent.v), lightDir, -up);
+
+ F32 fx = 1.f/tanf(fovx);
+ F32 fz = 1.f/tanf(fovz);
+
+ proj[j] = glh::matrix4f(-fx, 0, 0, 0,
+ 0, (yfar+ynear)/(ynear-yfar), 0, (2.f*yfar*ynear)/(ynear-yfar),
+ 0, 0, -fz, 0,
+ 0, -1.f, 0, 0);
+ }
+ }
+ }
+
+ //shadow_cam.setFar(128.f);
+ shadow_cam.setOriginAndLookAt(eye, up, center);
+
+ shadow_cam.setOrigin(0,0,0);
+
+ glh_set_current_modelview(view[j]);
+ glh_set_current_projection(proj[j]);
+
+ LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+
+ //shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR);
+ shadow_cam.getAgentPlane(LLCamera::AGENT_PLANE_NEAR).set(shadow_near_clip);
+
+ //translate and scale to from [-1, 1] to [0, 1]
+ glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
+
+ glh_set_current_modelview(view[j]);
+ glh_set_current_projection(proj[j]);
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ gGLLastModelView[i] = mShadowModelview[j].m[i];
+ gGLLastProjection[i] = mShadowProjection[j].m[i];
+ }
+
+ mShadowModelview[j] = view[j];
+ mShadowProjection[j] = proj[j];
+
+
+ mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view;
+
+ stop_glerror();
+
+ mShadow[j].bindTarget();
+ mShadow[j].getViewport(gGLViewport);
+ mShadow[j].clear();
+
+ {
+ static LLCullResult result[4];
+
+ //LLGLEnable enable(GL_DEPTH_CLAMP_NV);
+ renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE);
+ }
+
+ mShadow[j].flush();
+
+ if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+ mShadowCamera[j+4] = shadow_cam;
+ }
+ }
+ }
+
+
+ //hack to disable projector shadows
+ bool gen_shadow = RenderShadowDetail > 1;
+
+ if (gen_shadow)
+ {
+ F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f);
+
+ //update shadow targets
+ for (U32 i = 0; i < 2; i++)
+ { //for each current shadow
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW4+i;
+
+ if (mShadowSpotLight[i].notNull() &&
+ (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
+ mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
+ { //keep this spotlight
+ mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
+ }
+ else
+ { //fade out this light
+ mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
+
+ if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
+ { //faded out, grab one of the pending spots (whichever one isn't already taken)
+ if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[0];
+ }
+ else
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[1];
+ }
+ }
+ }
+ }
+
+ for (S32 i = 0; i < 2; i++)
+ {
+ glh_set_current_modelview(saved_view);
+ glh_set_current_projection(saved_proj);
+
+ if (mShadowSpotLight[i].isNull())
+ {
+ continue;
+ }
+
+ LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
+
+ if (!volume)
+ {
+ mShadowSpotLight[i] = NULL;
+ continue;
+ }
+
+ LLDrawable* drawable = mShadowSpotLight[i];
+
+ LLVector3 params = volume->getSpotLightParams();
+ F32 fov = params.mV[0];
+
+ //get agent->light space matrix (modelview)
+ LLVector3 center = drawable->getPositionAgent();
+ LLQuaternion quat = volume->getRenderRotation();
+
+ //get near clip plane
+ LLVector3 scale = volume->getScale();
+ LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
+ at_axis *= quat;
+
+ LLVector3 np = center+at_axis;
+ at_axis.normVec();
+
+ //get origin that has given fov for plane np, at_axis, and given scale
+ F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
+
+ LLVector3 origin = np - at_axis*dist;
+
+ LLMatrix4 mat(quat, LLVector4(origin, 1.f));
+
+ view[i+4] = glh::matrix4f((F32*) mat.mMatrix);
+
+ view[i+4] = view[i+4].inverse();
+
+ //get perspective matrix
+ F32 near_clip = dist+0.01f;
+ F32 width = scale.mV[VX];
+ F32 height = scale.mV[VY];
+ F32 far_clip = dist+volume->getLightRadius()*1.5f;
+
+ F32 fovy = fov * RAD_TO_DEG;
+ F32 aspect = width/height;
+
+ proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip);
+
+ //translate and scale to from [-1, 1] to [0, 1]
+ glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
+
+ glh_set_current_modelview(view[i+4]);
+ glh_set_current_projection(proj[i+4]);
+
+ mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view;
+
+ for (U32 j = 0; j < 16; j++)
+ {
+ gGLLastModelView[j] = mShadowModelview[i+4].m[j];
+ gGLLastProjection[j] = mShadowProjection[i+4].m[j];
+ }
+
+ mShadowModelview[i+4] = view[i+4];
+ mShadowProjection[i+4] = proj[i+4];
+
+ LLCamera shadow_cam = camera;
+ shadow_cam.setFar(far_clip);
+ shadow_cam.setOrigin(origin);
+
+ LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+
+ stop_glerror();
+
+ mShadow[i+4].bindTarget();
+ mShadow[i+4].getViewport(gGLViewport);
+ mShadow[i+4].clear();
+
+ static LLCullResult result[2];
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4;
+
+ renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE);
+
+ mShadow[i+4].flush();
+ }
+ }
+ else
+ { //no spotlight shadows
+ mShadowSpotLight[0] = mShadowSpotLight[1] = NULL;
+ }
+
+
+ if (!CameraOffset)
+ {
+ glh_set_current_modelview(saved_view);
+ glh_set_current_projection(saved_proj);
+ }
+ else
+ {
+ glh_set_current_modelview(view[1]);
+ glh_set_current_projection(proj[1]);
+ gGL.loadMatrix(view[1].m);
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.loadMatrix(proj[1].m);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ }
+ gGL.setColorMask(true, false);
+
+ for (U32 i = 0; i < 16; i++)
+ {
+ gGLLastModelView[i] = last_modelview[i];
+ gGLLastProjection[i] = last_projection[i];
+ }
+
+ popRenderTypeMask();
+
+ if (!skip_avatar_update)
+ {
+ gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
+ }
+}
+
+void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture)
+{
+ for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
+ {
+ LLSpatialGroup* group = *i;
+ if (!group->isDead() &&
+ (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) &&
+ gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
+ group->mDrawMap.find(type) != group->mDrawMap.end())
+ {
+ pass->renderGroup(group,type,mask,texture);
+ }
+ }
+}
+
+void LLPipeline::generateImpostor(LLVOAvatar* avatar)
+{
+ LLMemType mt_gi(LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR);
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ static LLCullResult result;
+ result.clear();
+ grabReferences(result);
+
+ if (!avatar || !avatar->mDrawable)
+ {
+ return;
+ }
+
+ assertInitialized();
+
+ bool muted = avatar->isVisuallyMuted();
+
+ pushRenderTypeMask();
+
+ if (muted)
+ {
+ andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
+ }
+ else
+ {
+ andRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME,
+ LLPipeline::RENDER_TYPE_AVATAR,
+ LLPipeline::RENDER_TYPE_BUMP,
+ LLPipeline::RENDER_TYPE_GRASS,
+ LLPipeline::RENDER_TYPE_SIMPLE,
+ LLPipeline::RENDER_TYPE_FULLBRIGHT,
+ LLPipeline::RENDER_TYPE_ALPHA,
+ LLPipeline::RENDER_TYPE_INVISIBLE,
+ LLPipeline::RENDER_TYPE_PASS_SIMPLE,
+ LLPipeline::RENDER_TYPE_PASS_ALPHA,
+ LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
+ LLPipeline::RENDER_TYPE_PASS_SHINY,
+ LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
+ LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
+ END_RENDER_TYPES);
+ }
+
+ S32 occlusion = sUseOcclusion;
+ sUseOcclusion = 0;
+ sReflectionRender = sRenderDeferred ? FALSE : TRUE;
+ sShadowRender = TRUE;
+ sImpostorRender = TRUE;
+
+ LLViewerCamera* viewer_camera = LLViewerCamera::getInstance();
+ markVisible(avatar->mDrawable, *viewer_camera);
+ LLVOAvatar::sUseImpostors = FALSE;
+
+ LLVOAvatar::attachment_map_t::iterator iter;
+ for (iter = avatar->mAttachmentPoints.begin();
+ iter != avatar->mAttachmentPoints.end();
+ ++iter)
+ {
+ LLViewerJointAttachment *attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ if (LLViewerObject* attached_object = (*attachment_iter))
+ {
+ markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
+ }
+ }
+ }
+
+ stateSort(*LLViewerCamera::getInstance(), result);
+
+ const LLVector4a* ext = avatar->mDrawable->getSpatialExtents();
+ LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset());
+
+ LLCamera camera = *viewer_camera;
+
+ camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis());
+
+ LLVector2 tdim;
+
+
+ LLVector4a half_height;
+ half_height.setSub(ext[1], ext[0]);
+ half_height.mul(0.5f);
+
+ LLVector4a left;
+ left.load3(camera.getLeftAxis().mV);
+ left.mul(left);
+ left.normalize3fast();
+
+ LLVector4a up;
+ up.load3(camera.getUpAxis().mV);
+ up.mul(up);
+ up.normalize3fast();
+
+ tdim.mV[0] = fabsf(half_height.dot3(left).getF32());
+ tdim.mV[1] = fabsf(half_height.dot3(up).getF32());
+
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+
+ F32 distance = (pos-camera.getOrigin()).length();
+ F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG;
+ F32 aspect = tdim.mV[0]/tdim.mV[1];
+ glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f);
+ glh_set_current_projection(persp);
+ gGL.loadMatrix(persp.m);
+
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.pushMatrix();
+ glh::matrix4f mat;
+ camera.getOpenGLTransform(mat.m);
+
+ mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat;
+
+ gGL.loadMatrix(mat.m);
+ glh_set_current_modelview(mat);
+
+ glClearColor(0.0f,0.0f,0.0f,0.0f);
+ gGL.setColorMask(true, true);
+
+ // get the number of pixels per angle
+ F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView());
+
+ //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing)
+ U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512);
+ U32 resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512);
+
+ if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() ||
+ resY != avatar->mImpostor.getHeight())
+ {
+ avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE);
+
+ if (LLPipeline::sRenderDeferred)
+ {
+ addDeferredAttachments(avatar->mImpostor);
+ }
+
+ gGL.getTexUnit(0)->bind(&avatar->mImpostor);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ }
+
+ avatar->mImpostor.bindTarget();
+
+ if (LLPipeline::sRenderDeferred)
+ {
+ avatar->mImpostor.clear();
+ renderGeomDeferred(camera);
+ renderGeomPostDeferred(camera);
+ }
+ else
+ {
+ LLGLEnable scissor(GL_SCISSOR_TEST);
+ glScissor(0, 0, resX, resY);
+ avatar->mImpostor.clear();
+ renderGeom(camera);
+ }
+
+ { //create alpha mask based on depth buffer (grey out if muted)
+ if (LLPipeline::sRenderDeferred)
+ {
+ GLuint buff = GL_COLOR_ATTACHMENT0;
+ glDrawBuffersARB(1, &buff);
+ }
+
+ LLGLDisable blend(GL_BLEND);
+
+ if (muted)
+ {
+ gGL.setColorMask(true, true);
+ }
+ else
+ {
+ gGL.setColorMask(false, true);
+ }
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER);
+
+ gGL.flush();
+
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+
+ static const F32 clip_plane = 0.99999f;
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gUIProgram.bind();
+ }
+
+ gGL.color4ub(64,64,64,255);
+ gGL.begin(LLRender::QUADS);
+ gGL.vertex3f(-1, -1, clip_plane);
+ gGL.vertex3f(1, -1, clip_plane);
+ gGL.vertex3f(1, 1, clip_plane);
+ gGL.vertex3f(-1, 1, clip_plane);
+ gGL.end();
+ gGL.flush();
+
+ if (LLGLSLShader::sNoFixedFunction)
+ {
+ gUIProgram.unbind();
+ }
+
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+ }
+
+ avatar->mImpostor.flush();
+
+ avatar->setImpostorDim(tdim);
+
+ LLVOAvatar::sUseImpostors = TRUE;
+ sUseOcclusion = occlusion;
+ sReflectionRender = FALSE;
+ sImpostorRender = FALSE;
+ sShadowRender = FALSE;
+ popRenderTypeMask();
+
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+
+ avatar->mNeedsImpostorUpdate = FALSE;
+ avatar->cacheImpostorValues();
+
+ LLVertexBuffer::unbind();
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+}
+
+BOOL LLPipeline::hasRenderBatches(const U32 type) const
+{
+ return sCull->getRenderMapSize(type) > 0;
+}
+
+LLCullResult::drawinfo_list_t::iterator LLPipeline::beginRenderMap(U32 type)
+{
+ return sCull->beginRenderMap(type);
+}
+
+LLCullResult::drawinfo_list_t::iterator LLPipeline::endRenderMap(U32 type)
+{
+ return sCull->endRenderMap(type);
+}
+
+LLCullResult::sg_list_t::iterator LLPipeline::beginAlphaGroups()
+{
+ return sCull->beginAlphaGroups();
+}
+
+LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups()
+{
+ return sCull->endAlphaGroups();
+}
+
+BOOL LLPipeline::hasRenderType(const U32 type) const
+{
+ // STORM-365 : LLViewerJointAttachment::setAttachmentVisibility() is setting type to 0 to actually mean "do not render"
+ // We then need to test that value here and return FALSE to prevent attachment to render (in mouselook for instance)
+ // TODO: reintroduce RENDER_TYPE_NONE in LLRenderTypeMask and initialize its mRenderTypeEnabled[RENDER_TYPE_NONE] to FALSE explicitely
+ return (type == 0 ? FALSE : mRenderTypeEnabled[type]);
+}
+
+void LLPipeline::setRenderTypeMask(U32 type, ...)
+{
+ va_list args;
+
+ va_start(args, type);
+ while (type < END_RENDER_TYPES)
+ {
+ mRenderTypeEnabled[type] = TRUE;
+ type = va_arg(args, U32);
+ }
+ va_end(args);
+
+ if (type > END_RENDER_TYPES)
+ {
+ llerrs << "Invalid render type." << llendl;
+ }
+}
+
+BOOL LLPipeline::hasAnyRenderType(U32 type, ...) const
+{
+ va_list args;
+
+ va_start(args, type);
+ while (type < END_RENDER_TYPES)
+ {
+ if (mRenderTypeEnabled[type])
+ {
+ return TRUE;
+ }
+ type = va_arg(args, U32);
+ }
+ va_end(args);
+
+ if (type > END_RENDER_TYPES)
+ {
+ llerrs << "Invalid render type." << llendl;
+ }
+
+ return FALSE;
+}
+
+void LLPipeline::pushRenderTypeMask()
+{
+ std::string cur_mask;
+ cur_mask.assign((const char*) mRenderTypeEnabled, sizeof(mRenderTypeEnabled));
+ mRenderTypeEnableStack.push(cur_mask);
+}
+
+void LLPipeline::popRenderTypeMask()
+{
+ if (mRenderTypeEnableStack.empty())
+ {
+ llerrs << "Depleted render type stack." << llendl;
+ }
+
+ memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled));
+ mRenderTypeEnableStack.pop();
+}
+
+void LLPipeline::andRenderTypeMask(U32 type, ...)
+{
+ va_list args;
+
+ BOOL tmp[NUM_RENDER_TYPES];
+ for (U32 i = 0; i < NUM_RENDER_TYPES; ++i)
+ {
+ tmp[i] = FALSE;
+ }
+
+ va_start(args, type);
+ while (type < END_RENDER_TYPES)
+ {
+ if (mRenderTypeEnabled[type])
+ {
+ tmp[type] = TRUE;
+ }
+
+ type = va_arg(args, U32);
+ }
+ va_end(args);
+
+ if (type > END_RENDER_TYPES)
+ {
+ llerrs << "Invalid render type." << llendl;
+ }
+
+ for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i)
+ {
+ mRenderTypeEnabled[i] = tmp[i];
+ }
+
+}
+
+void LLPipeline::clearRenderTypeMask(U32 type, ...)
+{
+ va_list args;
+
+ va_start(args, type);
+ while (type < END_RENDER_TYPES)
+ {
+ mRenderTypeEnabled[type] = FALSE;
+
+ type = va_arg(args, U32);
+ }
+ va_end(args);
+
+ if (type > END_RENDER_TYPES)
+ {
+ llerrs << "Invalid render type." << llendl;
+ }
+}
+
+void LLPipeline::addDebugBlip(const LLVector3& position, const LLColor4& color)
+{
+ DebugBlip blip(position, color);
+ mDebugBlips.push_back(blip);
+}
+
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 9c78048c46..3c4e389ce0 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -111,6 +111,7 @@ public:
void destroyGL();
void restoreGL();
void resetVertexBuffers();
+ void doResetVertexBuffers();
void resizeScreenTexture();
void releaseGLBuffers();
void releaseScreenBuffers();
@@ -653,6 +654,8 @@ protected:
bool mGroupQ2Locked;
bool mGroupQ1Locked;
+ bool mResetVertexBuffers; //if true, clear vertex buffers on next update
+
LLViewerObject::vobj_list_t mCreateQ;
LLDrawable::drawable_set_t mRetexturedList;
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 8baaa14595..b616e2327b 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -615,6 +615,9 @@
name="PanelFocusBackgroundColor"
reference="DkGray2" />
<color
+ name="PanelNotificationBackground"
+ value="1 0.3 0.3 0" />
+ <color
name="ParcelHoverColor"
reference="White" />
<color
@@ -747,6 +750,9 @@
name="TitleBarFocusColor"
reference="White_10" />
<color
+ name="ToastBackground"
+ value="0.3 0.3 0.3 0" />
+ <color
name="ToolTipBgColor"
value="0.937 0.89 0.655 1" />
<color
diff --git a/indra/newview/skins/default/textures/checker.png b/indra/newview/skins/default/textures/checker.png
new file mode 100644
index 0000000000..1ab87e3f02
--- /dev/null
+++ b/indra/newview/skins/default/textures/checker.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/map_avatar_unknown_32.tga b/indra/newview/skins/default/textures/map_avatar_unknown_32.tga
new file mode 100644
index 0000000000..d1192478c6
--- /dev/null
+++ b/indra/newview/skins/default/textures/map_avatar_unknown_32.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index ee8b7ba082..d5d58235a4 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -122,6 +122,8 @@ with the same filename but different name
<texture name="Checkbox_Press" file_name="widgets/Checkbox_Press.png" preload="true" />
<texture name="Check_Mark" file_name="icons/check_mark.png" preload="true" />
+ <texture name="Checker" file_name="checker.png" preload="false" />
+
<texture name="Command_AboutLand_Icon" file_name="toolbar_icons/land.png" preload="true" />
<texture name="Command_Appearance_Icon" file_name="toolbar_icons/appearance.png" preload="true" />
<texture name="Command_Avatar_Icon" file_name="toolbar_icons/avatars.png" preload="true" />
diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml
index 930bbaa8cb..d11373ce1d 100644
--- a/indra/newview/skins/default/xui/en/floater_aaa.xml
+++ b/indra/newview/skins/default/xui/en/floater_aaa.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
- legacy_header_height="18"
can_minimize="false"
can_tear_off="false"
can_resize="true"
@@ -16,67 +15,98 @@
save_dock_state="true"
save_visibility="true"
single_instance="true"
- width="320">
- <string name="nudge_parabuild" translate="false">Nudge 1</string>
- <string name="test_the_vlt">This string CHANGE2 is extracted.</string>
- <string name="testing_eli">Just a test. changes.</string>
- <text_editor
- parse_urls="true"
- bg_readonly_color="ChatHistoryBgColor"
- bg_writeable_color="ChatHistoryBgColor"
- border_visible="false"
- follows="all"
- font="SansSerif"
- left="1"
- top="20"
- layout="topleft"
- height="260"
- name="chat_history"
- max_length="200000"
- parse_highlights="true"
- text_color="ChatHistoryTextColor"
- text_readonly_color="ChatHistoryTextColor"
- translate="false"
- track_end="true"
- wrap="true"
- width="320">
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- Really long line that is long enough to wrap once with jyg descenders.
- </text_editor>
+ width="650">
+ <text left="0"
+ follows="left|top|bottom"
+ top="5"
+ clip_partial="true"
+ bottom="-5"
+ width="100"
+ valign="top">
+this
+is
+some
+text
+that
+is
+top
+aligned</text>
+ <text left_pad="5"
+ follows="left|top|bottom"
+ top="5"
+ bottom="-5"
+ clip_partial="true"
+ width="100"
+ valign="center">
+this
+is
+some
+text
+that
+is
+center
+aligned</text>
+ <text left_pad="5"
+ follows="left|top|bottom"
+ top="5"
+ clip_partial="true"
+ bottom="-5"
+ width="100"
+ valign="bottom">
+this
+is
+some
+text
+that
+is
+bottom
+aligned</text>
+ <text_editor left_pad="5"
+ follows="left|top|bottom"
+ top="5"
+ clip_partial="true"
+ bottom="-5"
+ width="100"
+ valign="top">
+this
+is
+some
+text
+that
+is
+top
+aligned
+ </text_editor>
+ <text_editor left_pad="5"
+ follows="left|top|bottom"
+ top="5"
+ bottom="-5"
+ clip_partial="true"
+ width="100"
+ valign="center">
+this
+is
+some
+text
+that
+is
+center
+aligned
+ </text_editor>
+ <text_editor left_pad="5"
+ follows="left|top|bottom"
+ top="5"
+ clip_partial="true"
+ bottom="-5"
+ width="100"
+ valign="bottom">
+this
+is
+some
+text
+that
+is
+bottom
+aligned
+ </text_editor>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 1d5a6740b7..3a6c2678c1 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -192,12 +192,12 @@
type="string"
length="1"
follows="left|top"
- height="20"
+ height="18"
layout="topleft"
left_pad="2"
valign="center"
name="ContentRatingText"
- top_delta="0"
+ top_delta="-2"
width="250">
Adult
</text>
@@ -209,7 +209,7 @@
layout="topleft"
left="10"
name="Owner:"
- top_pad="1"
+ top_pad="3"
width="100">
Owner:
</text>
@@ -736,7 +736,7 @@
height="16"
layout="topleft"
left_pad="10"
- top_delta="-3"
+ top_delta="-1"
mouse_opaque="false"
name="region_maturity_text"
valign="center"
@@ -1210,7 +1210,7 @@ Only large parcels can be listed in search.
type="string"
length="1"
follows="left|top"
- text_color="white"
+ text_color="White"
height="16"
layout="topleft"
left="10"
@@ -1500,7 +1500,7 @@ Only large parcels can be listed in search.
layout="topleft"
left="20"
name="Snapshot:"
- text_color="white"
+ text_color="White"
top="225"
width="200">
Snapshot:
@@ -1546,7 +1546,7 @@ Only large parcels can be listed in search.
layout="topleft"
left="255"
top="282"
- text_color="white"
+ text_color="White"
name="landing_point"
word_wrap="true"
width="200">
@@ -1576,7 +1576,7 @@ Only large parcels can be listed in search.
<text
type="string"
length="1"
- text_color="white"
+ text_color="White"
follows="left|top"
height="16"
layout="topleft"
@@ -1951,7 +1951,7 @@ Only large parcels can be listed in search.
name="access_estate_defined">
(Defined by the Estate)
</panel.string>
- <panel.string
+ <panel.string
name="estate_override">
One or more of these options is set at the estate level
</panel.string>
@@ -2085,7 +2085,7 @@ Only large parcels can be listed in search.
column_padding="0"
follows="top|bottom"
heading_height="14"
- height="120"
+ height="125"
layout="topleft"
left="0"
multi_select="true"
@@ -2134,7 +2134,7 @@ Only large parcels can be listed in search.
column_padding="0"
follows="top|bottom"
heading_height="14"
- height="120"
+ height="125"
layout="topleft"
left="0"
multi_select="true"
diff --git a/indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml b/indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml
new file mode 100644
index 0000000000..b5538a511c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="190"
+ layout="topleft"
+ name="Anim Preview"
+ help_topic="animation_anim_preview"
+ title="ANIMATION.ANIM"
+ width="300">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="name_label"
+ top="20"
+ width="275">
+ Name:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="19"
+ layout="topleft"
+ left_delta="0"
+ max_length_bytes="63"
+ name="name_form"
+ top_pad="0"
+ width="280" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="description_label"
+ top_pad="10"
+ width="270">
+ Description:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="19"
+ layout="topleft"
+ left_delta="0"
+ max_length_bytes="127"
+ name="description_form"
+ top_pad="0"
+ width="280" />
+ <button
+ follows="left|bottom"
+ height="22"
+ label="Upload (L$[AMOUNT])"
+ layout="topleft"
+ left="45"
+ name="ok_btn"
+ top_pad="60"
+ width="150" />
+ <button
+ follows="right|bottom"
+ height="22"
+ label="Cancel"
+ label_selected="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ left_pad="5"
+ width="90" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_animation_preview.xml b/indra/newview/skins/default/xui/en/floater_animation_bvh_preview.xml
index cb6b2f6ebc..cb6b2f6ebc 100644
--- a/indra/newview/skins/default/xui/en/floater_animation_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_animation_bvh_preview.xml
diff --git a/indra/newview/skins/default/xui/en/floater_build_options.xml b/indra/newview/skins/default/xui/en/floater_build_options.xml
index 35918e9705..38428b36fc 100644
--- a/indra/newview/skins/default/xui/en/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/en/floater_build_options.xml
@@ -1,70 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
legacy_header_height="18"
- height="198"
+ height="170"
layout="topleft"
name="build options floater"
help_topic="build_options_floater"
save_rect="true"
title="GRID OPTIONS"
width="264">
- <floater.string
- name="grid_screen_text">
- Screen
- </floater.string>
- <floater.string
- name="grid_local_text">
- Local
- </floater.string>
- <floater.string
- name="grid_world_text">
- World
- </floater.string>
- <floater.string
- name="grid_reference_text">
- Reference
- </floater.string>
- <floater.string
- name="grid_attachment_text">
- Attachment
- </floater.string>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="16"
- layout="topleft"
- left="10"
- tool_tip="Grid opacity"
- name="grid_mode_label"
- top_pad="30"
- width="123">
- Mode
- </text>
- <combo_box
- height="23"
- layout="topleft"
- left_pad="9"
- follows="left|top"
- name="combobox grid mode"
- tool_tip="Choose the type of grid ruler for positioning the object"
- top_delta="-3"
- width="108">
- <combo_box.item
- label="World grid"
- name="World"
- value="World" />
- <combo_box.item
- label="Local grid"
- name="Local"
- value="Local" />
- <combo_box.item
- label="Reference grid"
- name="Reference"
- value="Reference" />
- <combo_box.commit_callback
- function="GridOptions.gridMode"/>
- </combo_box>
<spinner
control_name="GridResolution"
follows="left|top"
@@ -77,7 +20,7 @@
max_val="5"
min_val="0.01"
name="GridResolution"
- top_pad="4"
+ top_pad="30"
width="200" />
<spinner
control_name="GridDrawSize"
diff --git a/indra/newview/skins/default/xui/en/floater_buy_contents.xml b/indra/newview/skins/default/xui/en/floater_buy_contents.xml
index 92001534e7..ac96a70805 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_contents.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_contents.xml
@@ -62,7 +62,7 @@
layout="topleft"
left="10"
name="buy_text"
- text_color="white"
+ text_color="White"
top="220"
use_ellipses="true"
width="260">
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
index 6afa24d04a..553c5d51d0 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -215,7 +215,7 @@
<text
type="string"
length="1"
- text_color="0.7 0.7 0.7 0.5"
+ text_color="LtGray_50"
follows="top|left"
layout="topleft"
halign="right"
@@ -229,7 +229,7 @@
<text
type="string"
length="1"
- text_color="0.7 0.7 0.7 0.5"
+ text_color="LtGray_50"
follows="top|left"
layout="topleft"
halign="right"
@@ -243,7 +243,7 @@ Re-enter amount to see the latest exchange rate.
<text
type="string"
length="1"
- text_color="0.7 0.7 0.7 0.5"
+ text_color="LtGray_50"
follows="top|left"
layout="topleft"
halign="right"
@@ -257,7 +257,7 @@ Re-enter amount to see the latest exchange rate.
<text
type="string"
length="1"
- text_color="0.7 0.7 0.7 0.5"
+ text_color="LtGray_50"
follows="top|left"
layout="topleft"
halign="right"
diff --git a/indra/newview/skins/default/xui/en/floater_buy_object.xml b/indra/newview/skins/default/xui/en/floater_buy_object.xml
index 8dfb6ba00c..5fdd4aa49d 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_object.xml
@@ -89,7 +89,7 @@
left_delta="0"
line_spacing.pixels="7"
name="buy_text"
- text_color="white"
+ text_color="White"
top_pad="5"
use_ellipses="true"
width="260"
@@ -106,7 +106,7 @@ Buy for L$[AMOUNT] from:
left_delta="0"
line_spacing.pixels="7"
name="buy_name_text"
- text_color="white"
+ text_color="White"
top_pad="5"
use_ellipses="true"
width="260">
diff --git a/indra/newview/skins/default/xui/en/floater_choose_group.xml b/indra/newview/skins/default/xui/en/floater_choose_group.xml
index dc1ee5f24e..2cf6e682fd 100644
--- a/indra/newview/skins/default/xui/en/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/en/floater_choose_group.xml
@@ -20,7 +20,7 @@
Choose a group:
</text>
<scroll_list
- height="160"
+ height="165"
layout="topleft"
left_delta="0"
name="group list"
diff --git a/indra/newview/skins/default/xui/en/floater_fast_timers.xml b/indra/newview/skins/default/xui/en/floater_fast_timers.xml
index 49aa8f3840..77adb5524e 100644
--- a/indra/newview/skins/default/xui/en/floater_fast_timers.xml
+++ b/indra/newview/skins/default/xui/en/floater_fast_timers.xml
@@ -22,7 +22,6 @@
top="5"
width="180"
height="40"
- pad_bottom="-5"
label="Pause"
font="SansSerifHuge"/>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
index 6f387f4800..3d33d19de5 100644
--- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml
@@ -99,7 +99,7 @@
halign="center"
font="SansSerifMedium"
font_shadow="hard"
- valign="bottom">
+ valign="top">
Drag items here to create folders
</text>
</panel>
@@ -114,8 +114,8 @@
height="20"
wrap="true"
halign="left"
- valign="bottom"
- font="SansSerif" />
+ valign="center"
+ font="SansSerif"/>
<button
label="Send to Marketplace"
tool_tip="Push to my Marketplace Storefront"
diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml
index eebc5ddc72..0e211551e6 100644
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -117,18 +117,18 @@
name="lod_tab_border"
top_pad="0"
width="619" />
- <text
- follows="left|top"
- height="18"
- initial_value="Source"
- layout="topleft"
- left="75"
- name="source"
- text_color="ModelUploaderLabels"
- top="15"
- valign="center"
- value="Source"
- width="335" />
+ <text
+ follows="left|top"
+ height="18"
+ initial_value="Source"
+ layout="topleft"
+ left="75"
+ name="source"
+ text_color="ModelUploaderLabels"
+ top="15"
+ valign="center"
+ value="Source"
+ width="335"/>
<text
follows="left|top"
halign="right"
@@ -163,7 +163,7 @@
name="high_label"
text_color="ModelUploaderLabels"
top_pad="10"
- valign="center"
+ valign="top"
value="High"
width="65" />
<combo_box
@@ -240,34 +240,34 @@
<text
follows="left|top"
halign="right"
- height="18"
+ height="15"
initial_value="0"
layout="topleft"
left_pad="0"
name="high_triangles"
- valign="center"
+ valign="top"
value="0"
width="65" />
<text
follows="left|top"
halign="right"
- height="18"
+ height="15"
initial_value="0"
layout="topleft"
left_pad="0"
name="high_vertices"
- valign="center"
+ valign="top"
value="0"
width="65" />
<text
follows="left|top"
halign="center"
- height="18"
+ height="15"
initial_value=""
layout="topleft"
left_pad="0"
name="high_status"
- valign="center"
+ valign="top"
value=""
width="65" />
<icon
@@ -277,7 +277,7 @@
left_delta="20"
mouse_opaque="true"
name="status_icon_high"
- top_delta="0"
+ top_delta="-2"
width="16" />
<text
follows="left|top"
@@ -288,7 +288,7 @@
name="medium_label"
text_color="ModelUploaderLabels"
top_pad="15"
- valign="center"
+ valign="top"
value="Medium"
width="65" />
<combo_box
@@ -368,34 +368,34 @@
<text
follows="left|top"
halign="right"
- height="18"
+ height="15"
initial_value="0"
layout="topleft"
left_pad="0"
name="medium_triangles"
- valign="center"
+ valign="top"
value="0"
width="65" />
<text
follows="left|top"
halign="right"
- height="18"
+ height="15"
initial_value="0"
layout="topleft"
left_pad="0"
name="medium_vertices"
- valign="center"
+ valign="top"
value="0"
width="65" />
<text
follows="left|top"
halign="center"
- height="18"
+ height="15"
initial_value=""
layout="topleft"
left_pad="0"
name="medium_status"
- valign="center"
+ valign="top"
value=""
width="65" />
<icon
@@ -405,7 +405,7 @@
left_delta="20"
mouse_opaque="true"
name="status_icon_medium"
- top_delta="0"
+ top_delta="-2"
width="16" />
<text
follows="left|top"
@@ -416,7 +416,7 @@
name="low_label"
text_color="ModelUploaderLabels"
top_pad="15"
- valign="center"
+ valign="top"
value="Low"
width="65" />
<combo_box
@@ -496,34 +496,34 @@
<text
follows="left|top"
halign="right"
- height="18"
+ height="15"
initial_value="0"
layout="topleft"
left_pad="0"
name="low_triangles"
- valign="center"
+ valign="top"
value="0"
width="65" />
<text
follows="left|top"
halign="right"
- height="18"
+ height="15"
initial_value="0"
layout="topleft"
left_pad="0"
name="low_vertices"
- valign="center"
+ valign="top"
value="0"
width="65" />
<text
follows="left|top"
halign="center"
- height="18"
+ height="15"
initial_value=""
layout="topleft"
left_pad="0"
name="low_status"
- valign="center"
+ valign="top"
value=""
width="65" />
<icon
@@ -533,7 +533,7 @@
left_delta="20"
mouse_opaque="true"
name="status_icon_low"
- top_delta="0"
+ top_delta="-2"
width="16" />
<text
follows="left|top"
@@ -544,7 +544,7 @@
name="lowest_label"
text_color="ModelUploaderLabels"
top_pad="15"
- valign="center"
+ valign="top"
value="Lowest"
width="65" />
<combo_box
@@ -624,34 +624,34 @@
<text
follows="left|top"
halign="right"
- height="18"
+ height="15"
initial_value="0"
layout="topleft"
left_pad="0"
name="lowest_triangles"
- valign="center"
+ valign="top"
value="0"
width="65" />
<text
follows="left|top"
halign="right"
- height="18"
+ height="15"
initial_value="0"
layout="topleft"
left_pad="0"
name="lowest_vertices"
- valign="center"
+ valign="top"
value="0"
width="65" />
<text
follows="left|top"
halign="center"
- height="18"
+ height="15"
initial_value=""
layout="topleft"
left_pad="0"
name="lowest_status"
- valign="center"
+ valign="top"
value=""
width="65" />
<icon
diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml
index 402868bb97..b2662331b0 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences.xml
@@ -100,7 +100,7 @@
help_topic="preferences_colors_tab"
name="colors" />
<panel
- class="panel_preference"
+ class="panel_preference_privacy"
filename="panel_preferences_privacy.xml"
label="Privacy"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_preview_animation.xml b/indra/newview/skins/default/xui/en/floater_preview_animation.xml
index 8427c7b06f..3ea5f54f2c 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_animation.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_animation.xml
@@ -41,18 +41,26 @@
label_selected="Stop"
layout="topleft"
left="10"
- name="Anim play btn"
+ name="Inworld"
tool_tip="Play this animation so that others can see it"
top="47"
- width="125" />
+ width="125">
+ <button.commit_callback
+ function="PreviewAnim.Play"
+ parameter="Inworld" />
+ </button>
<button
height="20"
label="Play Locally"
label_selected="Stop"
layout="topleft"
left_pad="5"
- name="Anim audition btn"
+ name="Locally"
tool_tip="Play this animation so that only you can see it"
top_delta="0"
- width="125" />
+ width="125">
+ <button.commit_callback
+ function="PreviewAnim.Play"
+ parameter="Locally" />
+ </button>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
index f95f21e63a..a04050e7eb 100644
--- a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
@@ -32,6 +32,26 @@
bg_alpha_color="blue"
height="11"
min_height="0"
+ visible="false"
+ background_visible="true">
+ <text follows="top|left|right" halign="center" text_color="white">flex</text>
+ </layout_panel>
+ <layout_panel name="flex"
+ auto_resize="true"
+ user_resize="true"
+ bg_alpha_color="blue"
+ height="11"
+ min_height="0"
+ visible="true"
+ background_visible="true">
+ <text follows="top|left|right" halign="center" text_color="white">flex</text>
+ </layout_panel>
+ <layout_panel name="flex"
+ auto_resize="true"
+ user_resize="true"
+ bg_alpha_color="blue"
+ height="11"
+ min_height="0"
background_visible="true">
<text follows="top|left|right" halign="center" text_color="white">flex</text>
</layout_panel>
diff --git a/indra/newview/skins/default/xui/en/floater_test_text_vertical_aligment.xml b/indra/newview/skins/default/xui/en/floater_test_text_vertical_aligment.xml
new file mode 100644
index 0000000000..d11373ce1d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_test_text_vertical_aligment.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_minimize="false"
+ can_tear_off="false"
+ can_resize="true"
+ can_drag_on_left="false"
+ can_close="true"
+ can_dock="true"
+ bevel_style="in"
+ height="300"
+ layout="topleft"
+ name="Test Floater"
+ save_rect="true"
+ title="TEST FLOATER"
+ save_dock_state="true"
+ save_visibility="true"
+ single_instance="true"
+ width="650">
+ <text left="0"
+ follows="left|top|bottom"
+ top="5"
+ clip_partial="true"
+ bottom="-5"
+ width="100"
+ valign="top">
+this
+is
+some
+text
+that
+is
+top
+aligned</text>
+ <text left_pad="5"
+ follows="left|top|bottom"
+ top="5"
+ bottom="-5"
+ clip_partial="true"
+ width="100"
+ valign="center">
+this
+is
+some
+text
+that
+is
+center
+aligned</text>
+ <text left_pad="5"
+ follows="left|top|bottom"
+ top="5"
+ clip_partial="true"
+ bottom="-5"
+ width="100"
+ valign="bottom">
+this
+is
+some
+text
+that
+is
+bottom
+aligned</text>
+ <text_editor left_pad="5"
+ follows="left|top|bottom"
+ top="5"
+ clip_partial="true"
+ bottom="-5"
+ width="100"
+ valign="top">
+this
+is
+some
+text
+that
+is
+top
+aligned
+ </text_editor>
+ <text_editor left_pad="5"
+ follows="left|top|bottom"
+ top="5"
+ bottom="-5"
+ clip_partial="true"
+ width="100"
+ valign="center">
+this
+is
+some
+text
+that
+is
+center
+aligned
+ </text_editor>
+ <text_editor left_pad="5"
+ follows="left|top|bottom"
+ top="5"
+ clip_partial="true"
+ bottom="-5"
+ width="100"
+ valign="bottom">
+this
+is
+some
+text
+that
+is
+bottom
+aligned
+ </text_editor>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_textbox.xml b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
index 2df9bb35fe..1d31fbd6dc 100644
--- a/indra/newview/skins/default/xui/en/floater_test_textbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
@@ -8,21 +8,7 @@
help_topic="floater_test_textbox"
translate="false"
width="800">
- <text
- type="string"
- length="1"
- height="90"
- layout="topleft"
- left="10"
- top_pad="30"
- width="300">
- First line of multiple lines
-Second line of multiple lines
-Third line of multiple lines
-Fourth line of multiple lines
-Fifth line of multiple lines
- </text>
- <text
+ <text
clip_partial="true"
top_pad="10"
left="10"
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index f9147ea650..2d63c94fe1 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -14,7 +14,27 @@
save_visibility="true"
sound_flags="0"
width="295">
- <floater.string
+ <floater.string
+ name="grid_screen_text">
+ Screen
+ </floater.string>
+ <floater.string
+ name="grid_local_text">
+ Local
+ </floater.string>
+ <floater.string
+ name="grid_world_text">
+ World
+ </floater.string>
+ <floater.string
+ name="grid_reference_text">
+ Reference
+ </floater.string>
+ <floater.string
+ name="grid_attachment_text">
+ Attachment
+ </floater.string>
+ <floater.string
name="status_rotate">
Drag colored bands to rotate object
</floater.string>
@@ -312,20 +332,48 @@
top_pad="0"
name="checkbox snap to grid"
width="134" />
- <button
- left_pad="0"
- label="Options..."
+ <combo_box
+ height="20"
+ layout="topleft"
+ follows="left|top"
+ name="combobox grid mode"
+ tool_tip="Choose the type of grid ruler for positioning the object"
+ top="83"
+ left="195"
+ top_pad="0"
+ width="60">
+ <combo_box.item
+ label="World"
+ name="World"
+ value="World" />
+ <combo_box.item
+ label="Local"
+ name="Local"
+ value="Local" />
+ <combo_box.item
+ label="Reference"
+ name="Reference"
+ value="Reference" />
+ <combo_box.commit_callback
+ function="BuildTool.gridMode"/>
+ </combo_box>
+
+ <button
+ left="259"
+ label=""
+ image_selected="ForwardArrow_Press"
+ image_unselected="ForwardArrow_Off"
layout="topleft"
follows="top|left"
name="Options..."
tool_tip="See more grid options"
top="83"
- right="-35"
- width="65"
- height="21" >
+ width="25"
+ height="20" >
<button.commit_callback
function="BuildTool.gridOptions"/>
</button>
+
<button
follows="left|top"
height="20"
diff --git a/indra/newview/skins/default/xui/en/floater_toybox.xml b/indra/newview/skins/default/xui/en/floater_toybox.xml
index 72e6187a14..fcaae9d172 100644
--- a/indra/newview/skins/default/xui/en/floater_toybox.xml
+++ b/indra/newview/skins/default/xui/en/floater_toybox.xml
@@ -18,7 +18,7 @@
<text
follows="left|top"
font="SansSerifMedium"
- valign="bottom"
+ valign="top"
halign="left"
height="20"
layout="topleft"
@@ -33,7 +33,7 @@
<text
follows="left|top"
font="SansSerifMedium"
- valign="bottom"
+ valign="top"
halign="left"
height="20"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
index cea19ec75c..d99b29f324 100644
--- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
@@ -71,7 +71,7 @@
layout="topleft"
left_pad="10"
name="user_text"
- text_color="white"
+ text_color="White"
top="4"
use_ellipses="true"
value="My Avatar:"
diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml
index 8d14c974b4..bfeb8fc470 100644
--- a/indra/newview/skins/default/xui/en/inspect_object.xml
+++ b/indra/newview/skins/default/xui/en/inspect_object.xml
@@ -56,7 +56,7 @@ owner secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
halign="right"
right="-5"
name="price_text"
- text_color="white"
+ text_color="White"
top="60"
font_shadow="none"
width="60">
@@ -90,6 +90,7 @@ L$30,000
follows="all"
font="SansSerifSmall"
height="13"
+ clip="false"
name="object_media_url"
width="207"
left_pad="2"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index f70d4db0f2..5faafecef7 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -1667,7 +1667,7 @@ Unable to create output file: [FILE]
icon="alertmodal.tga"
name="DoNotSupportBulkAnimationUpload"
type="alertmodal">
-[APP_NAME] does not currently support bulk upload of animation files.
+[APP_NAME] does not currently support bulk upload of BVH format animation files.
<tag>fail</tag>
</notification>
@@ -6409,11 +6409,11 @@ Grant this request?
<form name="form">
<button
index="-2"
- name="Mute"
+ name="Client_Side_Mute"
text="Block"/>
<button
index="-1"
- name="Ignore"
+ name="Client_Side_Ignore"
text="Ignore"/>
</form>
</notification>
@@ -6428,11 +6428,11 @@ Grant this request?
<form name="form">
<button
index="-2"
- name="Mute"
+ name="Client_Side_Mute"
text="Block"/>
<button
index="-1"
- name="Ignore"
+ name="Client_Side_Ignore"
text="Ignore"/>
</form>
</notification>
diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml
index 1e6a31d388..7c67fd7f83 100644
--- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml
+++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml
@@ -28,7 +28,7 @@
layout="topleft"
left_pad="10"
name="title_text"
- text_color="white"
+ text_color="White"
top="5"
width="250">
Block List
diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml
index 2645d472f9..5c5c718bdf 100644
--- a/indra/newview/skins/default/xui/en/panel_chat_header.xml
+++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml
@@ -23,7 +23,7 @@
<text
parse_urls="false"
allow_scroll="false"
- v_pad = "7"
+ v_pad = "6"
read_only = "true"
follows="left|right"
font.style="BOLD"
@@ -37,7 +37,7 @@
top="0"
translate="false"
use_ellipses="true"
- valign="bottom"
+ valign="top"
value="TestString PleaseIgnore" />
<text
allow_scroll="false"
@@ -49,7 +49,7 @@
left_pad="5"
name="time_box"
right="-5"
- top="8"
+ top="7"
value="23:30"
width="110" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_chat_item.xml b/indra/newview/skins/default/xui/en/panel_chat_item.xml
index 6af1105400..1b97de2b05 100644
--- a/indra/newview/skins/default/xui/en/panel_chat_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_chat_item.xml
@@ -16,13 +16,13 @@
top="3"
width="18" />
<text_chat
- top="5"
+ top="3"
left="30"
height="120"
text_color="white"
word_wrap="true"
mouse_opaque="true"
- valign="bottom"
+ valign="top"
name="msg_text">
</text_chat>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml
index df459b4083..4b05ab27e4 100644
--- a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml
@@ -29,7 +29,7 @@
width="380" />
<icon
height="16"
- color="0.75 0.75 0.75 1"
+ color="LtGray"
follows="top|left"
image_name="Inv_Object"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
index 69a692e2c4..f34b913218 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml
@@ -164,7 +164,7 @@
layout="topleft"
left_pad="8"
name="edit_wearable_title"
- text_color="white"
+ text_color="White"
top="3"
value="Editing Shape"
use_ellipses="true"
@@ -190,7 +190,7 @@
layout="topleft"
left="10"
name="description_text"
- text_color="white"
+ text_color="White"
top="10"
value="Shape:"
width="150" />
@@ -254,7 +254,7 @@
name="description"
prevalidate_callback="ascii"
select_on_focus="true"
- text_color="black"
+ text_color="Black"
top_pad="3"
width="290" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml
index a7178dc288..eea2606125 100644
--- a/indra/newview/skins/default/xui/en/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml
@@ -172,7 +172,7 @@ including the Everyone and Owner Roles.
draw_heading="true"
draw_stripes="false"
heading_height="23"
- height="130"
+ height="132"
layout="topleft"
search_column="1"
left="0"
diff --git a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml
index 383e637ace..413e22e444 100644
--- a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<inbox_inventory_panel
+ accepts_drag_and_drop="false"
name="inventory_inbox"
start_folder="Received Items"
follows="all" layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_instant_message.xml b/indra/newview/skins/default/xui/en/panel_instant_message.xml
index 4251128714..2e5d650902 100644
--- a/indra/newview/skins/default/xui/en/panel_instant_message.xml
+++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml
@@ -15,7 +15,7 @@
<panel
background_visible="true"
bevel_style="in"
- bg_alpha_color="black"
+ bg_alpha_color="Black"
follows="top"
height="24"
label="im_header"
@@ -64,7 +64,7 @@
left_pad="5"
name="user_name"
parse_urls="false"
- text_color="white"
+ text_color="White"
top="8"
translate="false"
use_ellipses="true"
@@ -90,7 +90,7 @@
layout="topleft"
left="10"
name="message"
- text_color="white"
+ text_color="White"
top="33"
use_ellipses="true"
value=""
diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
index d2088594dd..fd6e96b9a7 100644
--- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
@@ -271,7 +271,7 @@
<text_editor
bg_readonly_color="DkGray2"
follows="all"
- height="70"
+ height="75"
layout="topleft"
left="0"
max_length="127"
@@ -288,7 +288,7 @@
layout="topleft"
left="0"
name="folder_label"
- top_pad="15"
+ top_pad="10"
value="Landmark location:"
width="290" />
<combo_box
diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
index d6d8b2a83e..1c882bb099 100644
--- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -80,7 +80,6 @@
top="16"
width="288" />
<recent_inventory_panel
- accepts_drag_and_drop="false"
bg_opaque_color="DkGray2"
bg_alpha_color="DkGray2"
background_visible="true"
diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
index 4bf420b79f..3edeb9aa36 100644
--- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
@@ -70,7 +70,7 @@
layout="topleft"
auto_resize="true"
user_resize="true"
- min_width="480"
+ min_width="410"
name="navigation_layout_panel"
width="480">
<panel
@@ -148,15 +148,15 @@
layout="topleft"
auto_resize="true"
user_resize="true"
- min_width="315"
+ min_width="185"
name="favorites_layout_panel"
- width="315">
+ width="320">
<icon
follows="top|left"
height="25"
image_name="ChatBarHandle"
layout="topleft"
- left="-318"
+ left="-323"
name="resize_handle"
top="4"
width="5" />
@@ -171,16 +171,17 @@
name="favorite"
image_drag_indication="Accordion_ArrowOpened_Off"
tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!"
- width="311">
+ width="320">
<label
follows="left|top"
- height="15"
+ height="13"
layout="topleft"
left="10"
name="favorites_bar_label"
text_color="LtGray"
tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!"
- top="12"
+ top="13"
+ valign="bottom"
width="102">
Favorites Bar
</label>
diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml
index d492f9bd68..d683116eb8 100644
--- a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml
@@ -1,35 +1,63 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel
- height="300"
follows="all"
+ height="300"
+ help_topic="nearby_chat"
layout="topleft"
name="nearby_chat"
- help_topic="nearby_chat"
width="320">
- <check_box
- bottom_delta="36"
- control_name="TranslateChat"
- enabled="true"
- height="16"
- label="Translate chat"
- layout="topleft"
- left="5"
- name="translate_chat_checkbox"
- width="230" />
- <chat_history
- parse_urls="true"
- bg_readonly_color="ChatHistoryBgColor"
- bg_writeable_color="ChatHistoryBgColor"
- follows="all"
- left="5"
- top_delta="17"
- layout="topleft"
- height="260"
- name="chat_history"
- parse_highlights="true"
- text_color="ChatHistoryTextColor"
- text_readonly_color="ChatHistoryTextColor"
- right_widget_pad="5"
- left_widget_pad="0"
- width="315" />
+ <layout_stack
+ follows="all"
+ height="295"
+ layout="topleft"
+ left="0"
+ name="stack"
+ top="5"
+ orientation="vertical"
+ width="320">
+ <layout_panel
+ auto_resize="false"
+ height="26"
+ layout="topleft"
+ left_delta="0"
+ name="translate_chat_checkbox_lp"
+ top_delta="0"
+ visible="true"
+ width="313">
+ <check_box
+ top="10"
+ control_name="TranslateChat"
+ enabled="true"
+ height="16"
+ label="Translate chat"
+ layout="topleft"
+ left="5"
+ name="translate_chat_checkbox"
+ width="300" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="true"
+ height="277"
+ left_delta="0"
+ layout="topleft"
+ name="chat_history_lp"
+ width="318">
+ <chat_history
+ bg_readonly_color="ChatHistoryBgColor"
+ bg_writeable_color="ChatHistoryBgColor"
+ follows="all"
+ layout="topleft"
+ left="5"
+ left_widget_pad="0"
+ height="272"
+ name="chat_history"
+ parse_highlights="true"
+ parse_urls="true"
+ right_widget_pad="5"
+ text_color="ChatHistoryTextColor"
+ text_readonly_color="ChatHistoryTextColor"
+ top="0"
+ width="313" />
+ </layout_panel>
+ </layout_stack>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml
index f6f62ac54e..94c468e1bb 100644
--- a/indra/newview/skins/default/xui/en/panel_notification.xml
+++ b/indra/newview/skins/default/xui/en/panel_notification.xml
@@ -3,8 +3,8 @@
background_opaque="false"
border_visible="false"
background_visible="true"
- bg_alpha_color="1 0.3 0.3 0"
- bg_opaque_color="1 0.3 0.3 0"
+ bg_alpha_color="PanelNotificationBackground"
+ bg_opaque_color="PanelNotificationBackground"
label="notification_panel"
layout="topleft"
left="0"
@@ -20,8 +20,8 @@
border_visible="false"
bevel_style="none"
background_visible="true"
- bg_alpha_color="0.3 0.3 0.3 0"
- bg_opaque_color="0.3 0.3 0.3 0"
+ bg_alpha_color="ToastBackground"
+ bg_opaque_color="ToastBackground"
follows="left|right|top"
height="100"
label="info_panel"
@@ -39,7 +39,7 @@
left="10"
name="text_box"
read_only="true"
- text_color="white"
+ text_color="White"
top="10"
visible="false"
width="285"
@@ -52,7 +52,7 @@
layout="topleft"
left="10"
name="caution_text_box"
- text_color="1 0.82 0.46 1"
+ text_color="NotifyCautionBoxColor"
top="10"
visible="false"
width="285"
@@ -60,7 +60,7 @@
<text_editor
h_pad="0"
v_pad="0"
- bg_readonly_color="0.0 0.0 0.0 0"
+ bg_readonly_color="Transparent"
border_visible="false"
embedded_items="false"
enabled="false"
@@ -73,8 +73,8 @@
name="text_editor_box"
read_only="true"
tab_stop="false"
- text_color="white"
- text_readonly_color="white"
+ text_color="White"
+ text_readonly_color="White"
top="10"
visible="false"
width="285"
diff --git a/indra/newview/skins/default/xui/en/panel_online_status_toast.xml b/indra/newview/skins/default/xui/en/panel_online_status_toast.xml
index b1a7697e83..dadbd9c9ab 100644
--- a/indra/newview/skins/default/xui/en/panel_online_status_toast.xml
+++ b/indra/newview/skins/default/xui/en/panel_online_status_toast.xml
@@ -25,7 +25,7 @@
layout="topleft"
left_pad="5"
name="message"
- text_color="white"
+ text_color="White"
top="15"
use_ellipses="true"
value=""
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
index 9827180aa7..24882988b0 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
@@ -331,7 +331,7 @@
</text>
<radio_group
control_name="LetterKeysFocusChatBar"
- height="20"
+ height="34"
layout="topleft"
left="35"
top_pad="0"
@@ -339,7 +339,7 @@
<radio_item
label="Starts local chat"
name="radio_start_chat"
- top_delta="20"
+ top="0"
layout="topleft"
height="16"
left="0"
@@ -364,7 +364,7 @@
layout="topleft"
left="30"
name="title_afk_text"
- top_pad="15"
+ top_pad="5"
width="190">
Away timeout:
</text>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index 1f92244eb9..b71586aab1 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -63,7 +63,7 @@
layout="topleft"
left_pad="0"
name="mute_chb_label"
- top_delta="0"
+ top_delta="-1"
width="150"
wrap="true">
Mute when minimized
diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml
index d453a970e7..22c1139cdb 100644
--- a/indra/newview/skins/default/xui/en/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml
@@ -67,7 +67,6 @@
label_shadow="true"
name="buyL"
pad_right="0"
- pad_bottom="2"
tool_tip="Click to buy more L$"
top="0"
width="80" />
@@ -87,7 +86,6 @@
left_pad="0"
label_shadow="true"
name="goShop"
- pad_bottom="2"
tool_tip="Open Second Life Marketplace"
top="0"
width="65" />
diff --git a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
index 5e74689c5a..007b73a4bc 100644
--- a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
@@ -13,7 +13,7 @@
follows="left|right"
background_opaque="false"
background_visible="true"
- bg_alpha_color="0.0 0.0 0.0 0.0" >
+ bg_alpha_color="SysWellItemUnselected" >
<text
clip_partial="true"
top="2"
@@ -22,7 +22,7 @@
height="28"
layout="topleft"
follows="right|left"
- text_color="white"
+ text_color="White"
use_ellipses="true"
word_wrap="true"
mouse_opaque="false"
diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
index c89e1dc215..c5b0be0616 100644
--- a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
@@ -44,7 +44,7 @@
parse_urls="false"
use_ellipses="true"
name="region"
- text_color="white"
+ text_color="White"
top="4"
value="..."
width="330" />
diff --git a/indra/newview/skins/default/xui/en/panel_toast.xml b/indra/newview/skins/default/xui/en/panel_toast.xml
index 062c403a26..0b5aff54ca 100644
--- a/indra/newview/skins/default/xui/en/panel_toast.xml
+++ b/indra/newview/skins/default/xui/en/panel_toast.xml
@@ -59,7 +59,7 @@
left="20"
name="toast_text"
word_wrap="true"
- text_color="white"
+ text_color="White"
top="5"
translate="false"
use_ellipses="true"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
index 29aa6d1039..ee790e8dd4 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -48,7 +48,7 @@
height="300"
width="330" />
</layout_panel>
- <layout_panel
+ <layout_panel
width="330"
layout="topleft"
auto_resize="true"
@@ -73,6 +73,7 @@
<string name="InboxLabelWithArg">Received items ([NUM])</string>
<string name="InboxLabelNoArg">Received items</string>
<button
+ control_name="InventoryInboxToggleState"
label="Received items"
font="SansSerifMedium"
name="inbox_btn"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index d6b5f3559f..749f0e9ad9 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -369,6 +369,9 @@ Please try logging in again in a minute.</string>
<string name="anim_yes_happy">Yes (Happy)</string>
<string name="anim_yes_head">Yes</string>
+ <!-- build floater -->
+ <string name="multiple_textures">Multiple</string>
+
<!-- world map -->
<string name="texture_loading">Loading...</string>
<string name="worldmap_offline">Offline</string>
@@ -3238,6 +3241,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="IM_to_label">To</string>
<string name="IM_moderator_label">(Moderator)</string>
<string name="Saved_message">(Saved [LONG_TIMESTAMP])</string>
+ <string name="IM_unblock_only_groups_friends">To see this message, you must uncheck &apos;Only friends and groups can call or IM me&apos; in Preferences/Privacy.</string>
<!-- voice calls -->
<string name="answered_call">Your call has been answered</string>
diff --git a/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml b/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml
index 1bb3188cc8..8a4ccb19f9 100644
--- a/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml
+++ b/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml
@@ -17,13 +17,13 @@
<voice_call_invited_style
font="SansSerifSmall"
font.style="NORMAL"
- color="0.5 0.5 0.5 0.5"/>
+ color="AvatarListItemIconVoiceInvitedColor"/>
<!-- styles for avatar item JOINED to voice call -->
<voice_call_joined_style
font="SansSerifSmall"
font.style="NORMAL"
- color="white"/>
+ color="White"/>
<!-- styles for avatar item which HAS LEFT voice call -->
<voice_call_left_style
@@ -35,11 +35,11 @@
<online_style
font="SansSerifSmall"
font.style="NORMAL"
- color="white"/>
+ color="White"/>
<!-- styles for OFFLINE avatar item -->
<offline_style
font="SansSerifSmall"
font.style="NORMAL"
- color="0.5 0.5 0.5 1.0"/>
+ color="Gray"/>
</avatar_list_item>
diff --git a/indra/newview/skins/default/xui/en/widgets/bodyparts_list_item.xml b/indra/newview/skins/default/xui/en/widgets/bodyparts_list_item.xml
index 0eec002006..0016a8cf53 100644
--- a/indra/newview/skins/default/xui/en/widgets/bodyparts_list_item.xml
+++ b/indra/newview/skins/default/xui/en/widgets/bodyparts_list_item.xml
@@ -24,7 +24,7 @@
parse_urls="false"
use_ellipses="true"
name="item_name"
- text_color="white"
+ text_color="White"
top="5"
value="..."
width="359" />
diff --git a/indra/newview/skins/default/xui/en/widgets/button.xml b/indra/newview/skins/default/xui/en/widgets/button.xml
index e2baba92a3..2b2c3faf91 100644
--- a/indra/newview/skins/default/xui/en/widgets/button.xml
+++ b/indra/newview/skins/default/xui/en/widgets/button.xml
@@ -21,7 +21,7 @@
font="SansSerifSmall"
hover_glow_amount="0.15"
halign="center"
- pad_bottom="3"
+ pad_bottom="1"
height="23"
scale_image="true"
handle_right_mouse="true"
diff --git a/indra/newview/skins/default/xui/en/widgets/check_box.xml b/indra/newview/skins/default/xui/en/widgets/check_box.xml
index cca64fad2a..8947024e45 100644
--- a/indra/newview/skins/default/xui/en/widgets/check_box.xml
+++ b/indra/newview/skins/default/xui/en/widgets/check_box.xml
@@ -10,7 +10,7 @@
text_readonly_color="LabelDisabledColor"/>
<check_box.check_button name="CheckboxCtrl Button"
left="2"
- bottom="2"
+ bottom="1"
width="13"
height="13"
commit_on_return="false"
diff --git a/indra/newview/skins/default/xui/en/widgets/clothing_list_item.xml b/indra/newview/skins/default/xui/en/widgets/clothing_list_item.xml
index 96d72c78a6..d83f44737e 100644
--- a/indra/newview/skins/default/xui/en/widgets/clothing_list_item.xml
+++ b/indra/newview/skins/default/xui/en/widgets/clothing_list_item.xml
@@ -24,7 +24,7 @@
parse_urls="false"
use_ellipses="true"
name="item_name"
- text_color="white"
+ text_color="White"
top="5"
value="..."
width="359" />
diff --git a/indra/newview/skins/default/xui/en/widgets/dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/en/widgets/dummy_clothing_list_item.xml
index 6c60624805..8c805da048 100644
--- a/indra/newview/skins/default/xui/en/widgets/dummy_clothing_list_item.xml
+++ b/indra/newview/skins/default/xui/en/widgets/dummy_clothing_list_item.xml
@@ -9,7 +9,7 @@
width="380">
<item_icon
height="16"
- color="0.75 0.75 0.75 1"
+ color="LtGray"
follows="top|left"
image_name="Inv_Object"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
index 3e2202b20f..0586119681 100644
--- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml
+++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
@@ -11,7 +11,7 @@ label_pad_left - padding to the left of tab button labels
halign="center"
font="SansSerifSmall"
tab_height="21"
- label_pad_bottom="2"
+ label_pad_bottom="1"
label_pad_left="4">
<!--
Possible additional attributes for tabs:
diff --git a/indra/newview/tests/llworldmipmap_test.cpp b/indra/newview/tests/llworldmipmap_test.cpp
index 4c0959d1a9..e7ef017760 100644
--- a/indra/newview/tests/llworldmipmap_test.cpp
+++ b/indra/newview/tests/llworldmipmap_test.cpp
@@ -100,9 +100,9 @@ namespace tut
{
S32 level = mMap->scaleToLevel(0.0);
ensure("scaleToLevel() test 1 failed", level == LLWorldMipmap::MAP_LEVELS);
- level = mMap->scaleToLevel(LLWorldMipmap::MAP_TILE_SIZE);
+ level = mMap->scaleToLevel((F32)LLWorldMipmap::MAP_TILE_SIZE);
ensure("scaleToLevel() test 2 failed", level == 1);
- level = mMap->scaleToLevel(10 * LLWorldMipmap::MAP_TILE_SIZE);
+ level = mMap->scaleToLevel(10.f * LLWorldMipmap::MAP_TILE_SIZE);
ensure("scaleToLevel() test 3 failed", level == 1);
}
// Test 2 : globalToMipmap()
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 0931c4ec9b..9bf755c8f8 100644
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -1047,9 +1047,13 @@ class Linux_i686Manifest(LinuxManifest):
self.path("libuuid.so.16")
self.path("libuuid.so.16.0.22")
self.path("libSDL-1.2.so.0.11.3")
+ self.path("libSDL-1.2.so.0")
self.path("libdirectfb-1.4.so.5.0.4")
+ self.path("libdirectfb-1.4.so.5")
self.path("libfusion-1.4.so.5.0.4")
+ self.path("libfusion-1.4.so.5")
self.path("libdirect-1.4.so.5.0.4")
+ self.path("libdirect-1.4.so.5")
self.path("libopenjpeg.so.1.4.0")
self.path("libopenjpeg.so.1")
self.path("libopenjpeg.so")
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index ffdb0cb976..e58e7293fb 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -37,6 +37,7 @@
#include "linden_common.h"
#include "llerrorcontrol.h"
#include "lltut.h"
+#include "stringize.h"
#include "apr_pools.h"
#include "apr_getopt.h"
@@ -53,6 +54,22 @@
#include <gtest/gtest.h>
#endif
+#if LL_MSVC
+#pragma warning (push)
+#pragma warning (disable : 4702) // warning C4702: unreachable code
+#endif
+#include <boost/iostreams/tee.hpp>
+#include <boost/iostreams/stream.hpp>
+#if LL_MSVC
+#pragma warning (pop)
+#endif
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/foreach.hpp>
+#include <boost/lambda/lambda.hpp>
+
namespace tut
{
std::string sSourceDir;
@@ -69,8 +86,24 @@ public:
mPassedTests(0),
mFailedTests(0),
mSkippedTests(0),
- mStream(stream)
+ // By default, capture a shared_ptr to std::cout, with a no-op "deleter"
+ // so that destroying the shared_ptr makes no attempt to delete std::cout.
+ mStream(boost::shared_ptr<std::ostream>(&std::cout, boost::lambda::_1))
{
+ if (stream)
+ {
+ // We want a boost::iostreams::tee_device that will stream to two
+ // std::ostreams.
+ typedef boost::iostreams::tee_device<std::ostream, std::ostream> TeeDevice;
+ // More than that, though, we want an actual stream using that
+ // device.
+ typedef boost::iostreams::stream<TeeDevice> TeeStream;
+ // Allocate and assign in two separate steps, per Herb Sutter.
+ // (Until we turn on C++11 support, have to wrap *stream with
+ // boost::ref() due to lack of perfect forwarding.)
+ boost::shared_ptr<std::ostream> pstream(new TeeStream(std::cout, boost::ref(*stream)));
+ mStream = pstream;
+ }
}
~LLTestCallback()
@@ -83,18 +116,21 @@ public:
}
virtual void group_started(const std::string& name) {
- std::cout << "Unit test group_started name=" << name << std::endl;
+ *mStream << "Unit test group_started name=" << name << std::endl;
}
virtual void group_completed(const std::string& name) {
- std::cout << "Unit test group_completed name=" << name << std::endl;
+ *mStream << "Unit test group_completed name=" << name << std::endl;
}
virtual void test_completed(const tut::test_result& tr)
{
++mTotalTests;
std::ostringstream out;
- out << "[" << tr.group << ", " << tr.test << "] ";
+ out << "[" << tr.group << ", " << tr.test;
+ if (! tr.name.empty())
+ out << ": " << tr.name;
+ out << "] ";
switch(tr.result)
{
case tut::test_result::ok:
@@ -123,56 +159,43 @@ public:
break;
default:
++mFailedTests;
- out << "unknown";
+ out << "unknown (tr.result == " << tr.result << ")";
}
if(mVerboseMode || (tr.result != tut::test_result::ok))
{
+ *mStream << out.str();
if(!tr.message.empty())
{
- out << ": '" << tr.message << "'";
- }
- if (mStream)
- {
- *mStream << out.str() << std::endl;
+ *mStream << ": '" << tr.message << "'";
}
-
- std::cout << out.str() << std::endl;
- }
- }
-
- virtual void run_completed()
- {
- if (mStream)
- {
- run_completed_(*mStream);
+ *mStream << std::endl;
}
- run_completed_(std::cout);
}
virtual int getFailedTests() const { return mFailedTests; }
- virtual void run_completed_(std::ostream &stream)
+ virtual void run_completed()
{
- stream << "\tTotal Tests:\t" << mTotalTests << std::endl;
- stream << "\tPassed Tests:\t" << mPassedTests;
+ *mStream << "\tTotal Tests:\t" << mTotalTests << std::endl;
+ *mStream << "\tPassed Tests:\t" << mPassedTests;
if (mPassedTests == mTotalTests)
{
- stream << "\tYAY!! \\o/";
+ *mStream << "\tYAY!! \\o/";
}
- stream << std::endl;
+ *mStream << std::endl;
if (mSkippedTests > 0)
{
- stream << "\tSkipped known failures:\t" << mSkippedTests
+ *mStream << "\tSkipped known failures:\t" << mSkippedTests
<< std::endl;
}
if(mFailedTests > 0)
{
- stream << "*********************************" << std::endl;
- stream << "Failed Tests:\t" << mFailedTests << std::endl;
- stream << "Please report or fix the problem." << std::endl;
- stream << "*********************************" << std::endl;
+ *mStream << "*********************************" << std::endl;
+ *mStream << "Failed Tests:\t" << mFailedTests << std::endl;
+ *mStream << "Please report or fix the problem." << std::endl;
+ *mStream << "*********************************" << std::endl;
}
}
@@ -182,7 +205,7 @@ protected:
int mPassedTests;
int mFailedTests;
int mSkippedTests;
- std::ostream *mStream;
+ boost::shared_ptr<std::ostream> mStream;
};
// TeamCity specific class which emits service messages
@@ -192,84 +215,111 @@ class LLTCTestCallback : public LLTestCallback
{
public:
LLTCTestCallback(bool verbose_mode, std::ostream *stream) :
- LLTestCallback(verbose_mode, stream),
- mTCStream()
+ LLTestCallback(verbose_mode, stream)
{
}
~LLTCTestCallback()
{
- }
+ }
virtual void group_started(const std::string& name) {
LLTestCallback::group_started(name);
- mTCStream << "\n##teamcity[testSuiteStarted name='" << name << "']" << std::endl;
+ std::cout << "\n##teamcity[testSuiteStarted name='" << escape(name) << "']" << std::endl;
}
virtual void group_completed(const std::string& name) {
LLTestCallback::group_completed(name);
- mTCStream << "##teamcity[testSuiteFinished name='" << name << "']" << std::endl;
+ std::cout << "##teamcity[testSuiteFinished name='" << escape(name) << "']" << std::endl;
}
virtual void test_completed(const tut::test_result& tr)
{
+ std::string testname(STRINGIZE(tr.group << "." << tr.test));
+ if (! tr.name.empty())
+ {
+ testname.append(":");
+ testname.append(tr.name);
+ }
+ testname = escape(testname);
+
+ // Sadly, tut::callback doesn't give us control at test start; have to
+ // backfill start message into TC output.
+ std::cout << "##teamcity[testStarted name='" << testname << "']" << std::endl;
+
+ // now forward call to base class so any output produced there is in
+ // the right TC context
LLTestCallback::test_completed(tr);
switch(tr.result)
{
case tut::test_result::ok:
- mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
- mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
break;
+
case tut::test_result::fail:
- mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
- mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl;
- mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
- break;
case tut::test_result::ex:
- mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
- mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl;
- mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
- break;
case tut::test_result::warn:
- mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
- mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl;
- mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
- break;
case tut::test_result::term:
- mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
- mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl;
- mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
+ std::cout << "##teamcity[testFailed name='" << testname
+ << "' message='" << escape(tr.message) << "']" << std::endl;
break;
+
case tut::test_result::skip:
- mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl;
- mTCStream << "##teamcity[testIgnored name='" << tr.group << "." << tr.test << "']" << std::endl;
- mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;
+ std::cout << "##teamcity[testIgnored name='" << testname << "']" << std::endl;
break;
+
default:
break;
}
+ std::cout << "##teamcity[testFinished name='" << testname << "']" << std::endl;
}
- virtual void run_completed()
+ static std::string escape(const std::string& str)
{
- LLTestCallback::run_completed();
-
- // dump the TC reporting results to cout
- tc_run_completed_(std::cout);
- }
-
- virtual void tc_run_completed_(std::ostream &stream)
- {
-
- // dump the TC reporting results to cout
- stream << mTCStream.str() << std::endl;
+ // Per http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ServiceMessages
+ std::string result;
+ BOOST_FOREACH(char c, str)
+ {
+ switch (c)
+ {
+ case '\'':
+ result.append("|'");
+ break;
+ case '\n':
+ result.append("|n");
+ break;
+ case '\r':
+ result.append("|r");
+ break;
+/*==========================================================================*|
+ // These are not possible 'char' values from a std::string.
+ case '\u0085': // next line
+ result.append("|x");
+ break;
+ case '\u2028': // line separator
+ result.append("|l");
+ break;
+ case '\u2029': // paragraph separator
+ result.append("|p");
+ break;
+|*==========================================================================*/
+ case '|':
+ result.append("||");
+ break;
+ case '[':
+ result.append("|[");
+ break;
+ case ']':
+ result.append("|]");
+ break;
+ default:
+ result.push_back(c);
+ break;
+ }
+ }
+ return result;
}
-
-protected:
- std::ostringstream mTCStream;
-
};
@@ -359,7 +409,7 @@ int main(int argc, char **argv)
apr_getopt_t* os = NULL;
if(APR_SUCCESS != apr_getopt_init(&os, pool, argc, argv))
{
- std::cerr << "Unable to pool" << std::endl;
+ std::cerr << "apr_getopt_init() failed" << std::endl;
return 1;
}
@@ -373,7 +423,7 @@ int main(int argc, char **argv)
apr_status_t apr_err;
const char* opt_arg = NULL;
int opt_id = 0;
- std::ofstream *output = NULL;
+ boost::scoped_ptr<std::ofstream> output;
const char *touch = NULL;
while(true)
@@ -403,7 +453,7 @@ int main(int argc, char **argv)
verbose_mode = true;
break;
case 'o':
- output = new std::ofstream;
+ output.reset(new std::ofstream);
output->open(opt_arg);
break;
case 's': // --sourcedir
@@ -437,11 +487,11 @@ int main(int argc, char **argv)
LLTestCallback* mycallback;
if (getenv("TEAMCITY_PROJECT_NAME"))
{
- mycallback = new LLTCTestCallback(verbose_mode, output);
+ mycallback = new LLTCTestCallback(verbose_mode, output.get());
}
else
{
- mycallback = new LLTestCallback(verbose_mode, output);
+ mycallback = new LLTestCallback(verbose_mode, output.get());
}
tut::runner.get().set_callback(mycallback);
@@ -463,12 +513,6 @@ int main(int argc, char **argv)
std::cin.get();
}
- if (output)
- {
- output->close();
- delete output;
- }
-
if (touch && success)
{
std::ofstream s;
diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
index 1888f191e2..2e18218667 100644
--- a/indra/viewer_components/updater/llupdaterservice.cpp
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -447,7 +447,7 @@ void LLUpdaterServiceImpl::restartTimer(unsigned int seconds)
LL_INFOS("UpdaterService") << "will check for update again in " <<
seconds << " seconds" << LL_ENDL;
mTimer.start();
- mTimer.setTimerExpirySec(seconds);
+ mTimer.setTimerExpirySec((F32)seconds);
LLEventPumps::instance().obtain("mainloop").listen(
sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1));
}