From 35df5441d3e2789663532c948731aff3a1e04728 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Mon, 14 Jun 2010 12:04:49 +0200 Subject: llmediaplugins first step --- linden/doc/LICENSE-logos.txt | 23 + linden/doc/contributions.txt | 7 +- linden/etc/message.xml | 16 + linden/indra/CMakeLists.txt | 10 +- linden/indra/cmake/00-Common.cmake | 4 +- linden/indra/cmake/FindNDOF.cmake | 39 + linden/indra/cmake/GStreamer010Plugin.cmake | 39 + linden/indra/cmake/Glui.cmake | 28 + linden/indra/cmake/Glut.cmake | 19 + linden/indra/cmake/LLAudio.cmake | 2 - linden/indra/cmake/LLMedia.cmake | 13 - linden/indra/cmake/LLPlugin.cmake | 8 + linden/indra/cmake/MediaPluginBase.cmake | 8 + linden/indra/cmake/Mozlib.cmake | 47 - linden/indra/cmake/NDOF.cmake | 32 +- linden/indra/cmake/OPENAL.cmake | 13 +- linden/indra/cmake/OPENAL.cmake.imp | 115 ++ linden/indra/cmake/PluginAPI.cmake | 16 + linden/indra/cmake/QuickTimePlugin.cmake | 46 + linden/indra/cmake/WebKitLibPlugin.cmake | 55 + ...den%2findra%2fcmake%2fCopyWinLibs.cmake.rej.txt | 257 +++ linden/indra/llaudio/CMakeLists.txt | 43 +- linden/indra/llaudio/audioengine.cpp | 1904 ----------------- linden/indra/llaudio/audioengine.h | 466 ----- linden/indra/llaudio/audioengine_fmod.cpp | 1093 ---------- linden/indra/llaudio/audioengine_fmod.h | 161 -- linden/indra/llaudio/audioengine_openal.cpp | 574 ------ linden/indra/llaudio/audioengine_openal.h | 114 - linden/indra/llaudio/listener.cpp | 153 -- linden/indra/llaudio/listener.h | 80 - linden/indra/llaudio/listener_ds3d.h | 76 - linden/indra/llaudio/listener_fmod.cpp | 143 -- linden/indra/llaudio/listener_fmod.h | 67 - linden/indra/llaudio/listener_openal.cpp | 125 -- linden/indra/llaudio/listener_openal.h | 68 - linden/indra/llaudio/llaudiodecodemgr.cpp | 62 +- linden/indra/llaudio/llaudioengine.cpp | 1801 ++++++++++++++++ linden/indra/llaudio/llaudioengine.h | 457 ++++ linden/indra/llaudio/llaudioengine_fmod.cpp | 766 +++++++ linden/indra/llaudio/llaudioengine_fmod.h | 129 ++ linden/indra/llaudio/llaudioengine_openal.cpp | 546 +++++ linden/indra/llaudio/llaudioengine_openal.h | 114 + linden/indra/llaudio/lllistener.cpp | 142 ++ linden/indra/llaudio/lllistener.h | 78 + linden/indra/llaudio/lllistener_ds3d.h | 74 + linden/indra/llaudio/lllistener_fmod.cpp | 131 ++ linden/indra/llaudio/lllistener_fmod.h | 64 + linden/indra/llaudio/lllistener_openal.cpp | 116 ++ linden/indra/llaudio/lllistener_openal.h | 64 + linden/indra/llaudio/llstreamingaudio.h | 56 + linden/indra/llaudio/llstreamingaudio_fmod.cpp | 362 ++++ linden/indra/llaudio/llstreamingaudio_fmod.h | 68 + linden/indra/llaudio/llvorbisdecode.cpp | 326 +++ linden/indra/llaudio/llvorbisdecode.h | 42 + linden/indra/llaudio/llvorbisencode.cpp | 505 +++++ linden/indra/llaudio/llvorbisencode.h | 64 + linden/indra/llaudio/llwindgen.h | 136 ++ linden/indra/llaudio/vorbisdecode.cpp | 326 --- linden/indra/llaudio/vorbisdecode.h | 42 - linden/indra/llaudio/vorbisencode.h | 53 - linden/indra/llaudio/windgen.h | 136 -- linden/indra/llcommon/CMakeLists.txt | 2 + linden/indra/llcommon/llerrorcontrol.h | 1 + linden/indra/llcommon/llprocesslauncher.cpp | 346 ++++ linden/indra/llcommon/llprocesslauncher.h | 86 + linden/indra/llinventory/llparcel.cpp | 125 ++ linden/indra/llinventory/llparcel.h | 25 + linden/indra/llmath/CMakeLists.txt | 1 + linden/indra/llmath/llmath.h | 10 +- linden/indra/llmath/llvolume.cpp | 8 +- linden/indra/llmath/llvolume.h | 10 +- linden/indra/llmath/v3math.h | 4 +- linden/indra/llmedia/CMakeLists.txt | 79 - linden/indra/llmedia/llgstplaythread.cpp | 54 - linden/indra/llmedia/llgstplaythread.h | 62 - linden/indra/llmedia/llmediabase.h | 265 --- linden/indra/llmedia/llmediaemitter.h | 104 - linden/indra/llmedia/llmediaimplcommon.cpp | 552 ----- linden/indra/llmedia/llmediaimplcommon.h | 164 -- linden/indra/llmedia/llmediaimplexample1.cpp | 231 --- linden/indra/llmedia/llmediaimplexample1.h | 73 - linden/indra/llmedia/llmediaimplexample2.cpp | 198 -- linden/indra/llmedia/llmediaimplexample2.h | 76 - linden/indra/llmedia/llmediaimplfactory.cpp | 105 - linden/indra/llmedia/llmediaimplfactory.h | 100 - linden/indra/llmedia/llmediaimplgstreamer.h | 164 -- .../indra/llmedia/llmediaimplgstreamervidplug.cpp | 448 ---- linden/indra/llmedia/llmediaimplgstreamervidplug.h | 106 - linden/indra/llmedia/llmediaimplllmozlib.cpp | 624 ------ linden/indra/llmedia/llmediaimplllmozlib.h | 127 -- linden/indra/llmedia/llmediaimplquicktime.cpp | 657 ------ linden/indra/llmedia/llmediaimplquicktime.h | 112 - linden/indra/llmedia/llmediaimplregister.h | 60 - linden/indra/llmedia/llmediamanager.cpp | 295 --- linden/indra/llmedia/llmediamanager.h | 127 -- linden/indra/llmedia/llmediaobserver.h | 116 -- linden/indra/llmessage/tests/commtest.h | 83 + linden/indra/llmessage/tests/llcurl_stub.cpp | 100 + .../llmessage/tests/llhttpclientadapter_test.cpp | 170 ++ .../tests/lltemplatemessagedispatcher_test.cpp | 165 ++ .../llmessage/tests/lltesthttpclientadapter.cpp | 67 + .../llmessage/tests/lltesthttpclientadapter.h | 63 + .../indra/llmessage/tests/lltestmessagesender.cpp | 44 + linden/indra/llmessage/tests/lltestmessagesender.h | 57 + .../tests/lltrustedmessageservice_test.cpp | 146 ++ linden/indra/llmessage/tests/networkio.h | 116 ++ .../indra/llmessage/tests/test_llsdmessage_peer.py | 153 ++ linden/indra/llplugin/CMakeLists.txt | 55 + linden/indra/llplugin/llpluginclassmedia.cpp | 1162 +++++++++++ linden/indra/llplugin/llpluginclassmedia.h | 352 ++++ linden/indra/llplugin/llpluginclassmediaowner.h | 82 + linden/indra/llplugin/llplugininstance.cpp | 172 ++ linden/indra/llplugin/llplugininstance.h | 104 + linden/indra/llplugin/llpluginmessage.cpp | 442 ++++ linden/indra/llplugin/llpluginmessage.h | 142 ++ linden/indra/llplugin/llpluginmessageclasses.h | 57 + linden/indra/llplugin/llpluginmessagepipe.cpp | 316 +++ linden/indra/llplugin/llpluginmessagepipe.h | 92 + linden/indra/llplugin/llpluginprocesschild.cpp | 490 +++++ linden/indra/llplugin/llpluginprocesschild.h | 112 + linden/indra/llplugin/llpluginprocessparent.cpp | 714 +++++++ linden/indra/llplugin/llpluginprocessparent.h | 169 ++ linden/indra/llplugin/llpluginsharedmemory.cpp | 506 +++++ linden/indra/llplugin/llpluginsharedmemory.h | 130 ++ linden/indra/llplugin/slplugin/CMakeLists.txt | 55 + linden/indra/llplugin/slplugin/slplugin.cpp | 288 +++ linden/indra/llplugin/slplugin/slplugin_info.plist | 12 + linden/indra/llui/CMakeLists.txt | 15 +- linden/indra/llui/llbutton.cpp | 5 + linden/indra/llui/llbutton.h | 3 +- linden/indra/llui/llfloater.cpp | 8 +- linden/indra/llui/llfocusmgr.cpp | 84 +- linden/indra/llui/llfocusmgr.h | 49 +- linden/indra/llui/lliconctrl.cpp | 6 + linden/indra/llui/lliconctrl.h | 2 + linden/indra/llui/llmultisliderctrl.cpp | 3 - linden/indra/llui/llpanel.cpp | 19 +- linden/indra/llui/llpanel.h | 3 + linden/indra/llui/llsliderctrl.cpp | 2 - linden/indra/llui/llspinctrl.cpp | 1 - linden/indra/llui/lltextparser.cpp | 48 +- linden/indra/llui/lltextparser.h | 7 +- linden/indra/llui/llui.cpp | 1 - linden/indra/llui/lluictrl.cpp | 55 +- linden/indra/llui/lluictrl.h | 26 +- linden/indra/llui/llview.cpp | 7 +- linden/indra/llui/llview.h | 14 +- linden/indra/llvfs/CMakeLists.txt | 2 +- linden/indra/llvfs/lldir.cpp | 6 + linden/indra/llvfs/lldir.h | 6 + linden/indra/llvfs/lldir_linux.cpp | 43 +- linden/indra/llvfs/lldir_linux.h | 3 + linden/indra/llvfs/lldir_mac.cpp | 15 + linden/indra/llvfs/lldir_mac.h | 3 + linden/indra/llvfs/lldir_solaris.cpp | 2 + linden/indra/llvfs/lldir_win32.cpp | 15 + linden/indra/llvfs/lldir_win32.h | 3 + linden/indra/llwindow/CMakeLists.txt | 14 +- linden/indra/media_plugins/CMakeLists.txt | 11 + linden/indra/media_plugins/base/CMakeLists.txt | 41 + .../indra/media_plugins/base/media_plugin_base.cpp | 155 ++ .../indra/media_plugins/base/media_plugin_base.exp | 1 + .../indra/media_plugins/base/media_plugin_base.h | 112 + linden/indra/media_plugins/example/CMakeLists.txt | 74 + .../media_plugins/example/media_plugin_example.cpp | 488 +++++ .../media_plugins/gstreamer010/CMakeLists.txt | 71 + .../gstreamer010/llmediaimplgstreamer.h | 57 + .../gstreamer010/llmediaimplgstreamer_syms.cpp | 171 ++ .../gstreamer010/llmediaimplgstreamer_syms.h | 78 + .../gstreamer010/llmediaimplgstreamer_syms_raw.inc | 51 + .../llmediaimplgstreamer_syms_rawv.inc | 5 + .../llmediaimplgstreamertriviallogging.h | 53 + .../gstreamer010/llmediaimplgstreamervidplug.cpp | 532 +++++ .../gstreamer010/llmediaimplgstreamervidplug.h | 109 + .../gstreamer010/media_plugin_gstreamer010.cpp | 1202 +++++++++++ .../gstreamer010/media_plugin_gstreamer010.cpp~ | 1219 +++++++++++ .../indra/media_plugins/quicktime/CMakeLists.txt | 83 + .../quicktime/media_plugin_quicktime.cpp | 985 +++++++++ linden/indra/media_plugins/webkit/CMakeLists.txt | 82 + .../media_plugins/webkit/media_plugin_webkit.cpp | 932 +++++++++ linden/indra/newview/CMakeLists.txt | 100 +- linden/indra/newview/app_settings/settings.xml | 35 +- linden/indra/newview/chatbar_as_cmdline.cpp | 4 +- linden/indra/newview/floatervoicelicense.cpp | 4 +- linden/indra/newview/floatervoicelicense.h | 8 +- linden/indra/newview/llagent.cpp | 6 + linden/indra/newview/llappviewer.cpp | 20 +- linden/indra/newview/llappviewerlinux.cpp | 2 +- linden/indra/newview/llappviewermacosx.cpp | 4 +- linden/indra/newview/llassetuploadresponders.cpp | 5 +- linden/indra/newview/llaudiosourcevo.h | 2 +- linden/indra/newview/llchatbar.cpp | 2 +- linden/indra/newview/llcommandhandler.cpp | 6 +- linden/indra/newview/llcommandhandler.h | 10 +- linden/indra/newview/llfirstuse.cpp | 4 +- linden/indra/newview/llfloaterabout.cpp | 27 +- linden/indra/newview/llfloateravatarinfo.cpp | 2 +- linden/indra/newview/llfloaterchat.cpp | 54 +- linden/indra/newview/llfloaterchat.h | 2 + linden/indra/newview/llfloaterclassified.cpp | 2 +- linden/indra/newview/llfloaterevent.cpp | 2 +- linden/indra/newview/llfloatergroupinfo.cpp | 2 +- linden/indra/newview/llfloaterhandler.cpp | 4 +- linden/indra/newview/llfloaterhandler.h | 2 +- linden/indra/newview/llfloaterhtmlhelp.h | 90 - linden/indra/newview/llfloaterhtmlsimple.cpp | 6 +- linden/indra/newview/llfloaterhud.cpp | 4 +- linden/indra/newview/llfloaterhud.h | 4 +- linden/indra/newview/llfloaterland.cpp | 12 + linden/indra/newview/llfloaterland.h | 3 + linden/indra/newview/llfloatermediabrowser.cpp | 398 ++++ linden/indra/newview/llfloatermediabrowser.h | 102 + linden/indra/newview/llfloaterobjectiminfo.cpp | 6 +- linden/indra/newview/llfloaterparcel.cpp | 2 +- linden/indra/newview/llfloaterpreference.cpp | 8 +- linden/indra/newview/llfloatertos.cpp | 33 +- linden/indra/newview/llfloatertos.h | 7 +- linden/indra/newview/llfloaterurlentry.cpp | 2 +- linden/indra/newview/llhoverview.cpp | 3 +- linden/indra/newview/llhoverview.h | 3 + linden/indra/newview/llhudview.cpp | 13 +- linden/indra/newview/llhudview.h | 2 +- linden/indra/newview/llimpanel.cpp | 2 +- linden/indra/newview/llloginhandler.cpp | 2 +- linden/indra/newview/llloginhandler.h | 2 +- linden/indra/newview/llmediactrl.cpp | 1201 +++++++++++ linden/indra/newview/llmediactrl.h | 201 ++ linden/indra/newview/llmediaremotectrl.cpp | 57 +- linden/indra/newview/llmimetypes.cpp | 24 + linden/indra/newview/llmimetypes.h | 6 + linden/indra/newview/lloverlaybar.cpp | 17 +- linden/indra/newview/llpanelaudioprefs.cpp | 4 +- linden/indra/newview/llpanelavatar.cpp | 60 +- linden/indra/newview/llpanelavatar.h | 16 +- linden/indra/newview/llpanelclassified.cpp | 2 +- linden/indra/newview/llpaneldebug.cpp | 2 +- linden/indra/newview/llpaneldirfind.cpp | 42 +- linden/indra/newview/llpaneldirfind.h | 15 +- linden/indra/newview/llpaneldirgroups.cpp | 1 + linden/indra/newview/llpanelface.cpp | 33 +- linden/indra/newview/llpanellandaudio.cpp | 195 ++ linden/indra/newview/llpanellandaudio.h | 63 + linden/indra/newview/llpanellandmedia.cpp | 292 ++- linden/indra/newview/llpanellandmedia.h | 25 +- linden/indra/newview/llpanellogin.cpp | 55 +- linden/indra/newview/llpanellogin.h | 8 +- linden/indra/newview/llpanelmediahud.cpp | 667 ++++++ linden/indra/newview/llpanelmediahud.h | 110 + linden/indra/newview/llpanelpermissions.cpp | 2 +- linden/indra/newview/llpanelweb.cpp | 65 +- linden/indra/newview/llprefsvoice.cpp | 4 +- linden/indra/newview/llpreviewscript.cpp | 14 +- linden/indra/newview/llpreviewsound.cpp | 2 +- linden/indra/newview/llselectmgr.cpp | 11 +- linden/indra/newview/llstartup.cpp | 37 +- linden/indra/newview/llstatusbar.cpp | 2 +- linden/indra/newview/lltoolcomp.cpp | 4 - linden/indra/newview/lltoolcomp.h | 1 + linden/indra/newview/lltoolgun.cpp | 7 +- linden/indra/newview/lltoolgun.h | 2 + linden/indra/newview/lltoolmgr.cpp | 14 +- linden/indra/newview/lltoolmorph.cpp | 2 +- linden/indra/newview/lltoolpie.cpp | 208 +- linden/indra/newview/lltoolpie.h | 1 + linden/indra/newview/lltoolplacer.cpp | 2 +- linden/indra/newview/llurldispatcher.cpp | 22 +- linden/indra/newview/llurldispatcher.h | 6 +- linden/indra/newview/llvieweraudio.cpp | 3 +- linden/indra/newview/llviewercontrol.cpp | 19 +- linden/indra/newview/llviewergesture.cpp | 2 +- linden/indra/newview/llviewerimagelist.cpp | 2 +- linden/indra/newview/llviewerkeyboard.cpp | 2 +- linden/indra/newview/llviewermedia.cpp | 1390 ++++++++----- linden/indra/newview/llviewermedia.h | 200 +- .../indra/newview/llviewermedia_streamingaudio.cpp | 169 ++ .../indra/newview/llviewermedia_streamingaudio.h | 69 + linden/indra/newview/llviewermediafocus.cpp | 359 ++++ linden/indra/newview/llviewermediafocus.h | 91 + linden/indra/newview/llviewermediaobserver.h | 71 + linden/indra/newview/llviewermenu.cpp | 34 +- linden/indra/newview/llviewermenufile.cpp | 2 +- linden/indra/newview/llviewermessage.cpp | 8 +- linden/indra/newview/llviewerobject.cpp | 2 +- linden/indra/newview/llviewerparcelmedia.cpp | 350 +++- linden/indra/newview/llviewerparcelmedia.h | 31 +- .../indra/newview/llviewerparcelmediaautoplay.cpp | 2 +- linden/indra/newview/llviewerparcelmediaautoplay.h | 1 - linden/indra/newview/llviewerparcelmgr.cpp | 80 +- linden/indra/newview/llviewerparcelmgr.h | 5 + linden/indra/newview/llviewerregion.cpp | 6 +- linden/indra/newview/llviewertexteditor.cpp | 2 +- linden/indra/newview/llviewerwindow.cpp | 58 +- linden/indra/newview/llvoavatar.cpp | 17 +- linden/indra/newview/llvovolume.cpp | 2 +- linden/indra/newview/llweb.cpp | 2 +- .../newview/mozilla-powerpc-darwin-readme.txt | 71 - linden/indra/newview/pipeline.cpp | 2 +- .../newview/skins/default/textures/textures.xml | 20 +- .../skins/default/xui/en-us/floater_about_land.xml | 744 +++++-- .../default/xui/en-us/floater_media_browser.xml | 21 +- .../newview/skins/default/xui/en-us/mime_types.xml | 456 ---- .../skins/default/xui/en-us/mime_types_linux.xml | 445 ++++ .../skins/default/xui/en-us/mime_types_mac.xml | 445 ++++ .../skins/default/xui/en-us/mime_types_windows.xml | 445 ++++ .../newview/skins/default/xui/en-us/panel_bars.xml | 3 - .../newview/skins/default/xui/en-us/panel_hud.xml | 4 + .../skins/default/xui/en-us/panel_media_hud.xml | 68 + linden/indra/newview/viewer_manifest.py | 126 +- linden/indra/newview/viewer_manifest.py~ | 1176 +++++++++++ linden/indra/test_apps/llplugintest/CMakeLists.txt | 378 ++++ linden/indra/test_apps/llplugintest/bookmarks.txt | 28 + .../test_apps/llplugintest/demo_media_plugin.cpp | 472 +++++ .../test_apps/llplugintest/demo_media_plugin_2.cpp | 578 ++++++ .../indra/test_apps/llplugintest/demo_plugin.cpp | 220 ++ .../test_apps/llplugintest/llmediaplugintest.cpp | 2179 ++++++++++++++++++++ .../test_apps/llplugintest/llmediaplugintest.h | 201 ++ .../test_apps/llplugintest/media_mappings.txt | 3 + .../test_apps/llplugintest/media_plugin_test.cpp | 511 +++++ .../test_apps/llplugintest/media_simple_test.cpp | 460 +++++ .../indra/test_apps/llplugintest/plugin_host.cpp | 92 + .../llplugintest/plugin_process_launcher.cpp | 197 ++ linden/install.xml | 23 +- 322 files changed, 35699 insertions(+), 12802 deletions(-) create mode 100644 linden/doc/LICENSE-logos.txt create mode 100644 linden/indra/cmake/FindNDOF.cmake create mode 100644 linden/indra/cmake/GStreamer010Plugin.cmake create mode 100644 linden/indra/cmake/Glui.cmake create mode 100644 linden/indra/cmake/Glut.cmake delete mode 100644 linden/indra/cmake/LLMedia.cmake create mode 100644 linden/indra/cmake/LLPlugin.cmake create mode 100644 linden/indra/cmake/MediaPluginBase.cmake create mode 100644 linden/indra/cmake/OPENAL.cmake.imp create mode 100644 linden/indra/cmake/PluginAPI.cmake create mode 100644 linden/indra/cmake/QuickTimePlugin.cmake create mode 100644 linden/indra/cmake/WebKitLibPlugin.cmake create mode 100644 linden/indra/cmake/linden%2findra%2fcmake%2fCopyWinLibs.cmake.rej.txt delete mode 100644 linden/indra/llaudio/audioengine.cpp delete mode 100644 linden/indra/llaudio/audioengine.h delete mode 100644 linden/indra/llaudio/audioengine_fmod.cpp delete mode 100644 linden/indra/llaudio/audioengine_fmod.h delete mode 100644 linden/indra/llaudio/audioengine_openal.cpp delete mode 100644 linden/indra/llaudio/audioengine_openal.h delete mode 100644 linden/indra/llaudio/listener_openal.cpp delete mode 100644 linden/indra/llaudio/listener_openal.h create mode 100644 linden/indra/llaudio/llaudioengine.cpp create mode 100644 linden/indra/llaudio/llaudioengine.h create mode 100644 linden/indra/llaudio/llaudioengine_fmod.cpp create mode 100644 linden/indra/llaudio/llaudioengine_fmod.h create mode 100644 linden/indra/llaudio/llaudioengine_openal.cpp create mode 100644 linden/indra/llaudio/llaudioengine_openal.h create mode 100644 linden/indra/llaudio/lllistener.cpp create mode 100644 linden/indra/llaudio/lllistener.h create mode 100644 linden/indra/llaudio/lllistener_ds3d.h create mode 100644 linden/indra/llaudio/lllistener_fmod.cpp create mode 100644 linden/indra/llaudio/lllistener_fmod.h create mode 100644 linden/indra/llaudio/lllistener_openal.cpp create mode 100644 linden/indra/llaudio/lllistener_openal.h create mode 100644 linden/indra/llaudio/llstreamingaudio.h create mode 100644 linden/indra/llaudio/llstreamingaudio_fmod.cpp create mode 100644 linden/indra/llaudio/llstreamingaudio_fmod.h create mode 100644 linden/indra/llaudio/llvorbisdecode.cpp create mode 100644 linden/indra/llaudio/llvorbisdecode.h create mode 100644 linden/indra/llaudio/llvorbisencode.cpp create mode 100644 linden/indra/llaudio/llvorbisencode.h create mode 100644 linden/indra/llaudio/llwindgen.h delete mode 100644 linden/indra/llaudio/vorbisdecode.cpp delete mode 100644 linden/indra/llaudio/vorbisdecode.h delete mode 100644 linden/indra/llaudio/vorbisencode.h delete mode 100644 linden/indra/llaudio/windgen.h create mode 100644 linden/indra/llcommon/llprocesslauncher.cpp create mode 100644 linden/indra/llcommon/llprocesslauncher.h delete mode 100644 linden/indra/llmedia/CMakeLists.txt delete mode 100644 linden/indra/llmedia/llgstplaythread.cpp delete mode 100644 linden/indra/llmedia/llgstplaythread.h delete mode 100644 linden/indra/llmedia/llmediabase.h delete mode 100644 linden/indra/llmedia/llmediaemitter.h delete mode 100644 linden/indra/llmedia/llmediaimplcommon.cpp delete mode 100644 linden/indra/llmedia/llmediaimplcommon.h delete mode 100644 linden/indra/llmedia/llmediaimplexample1.cpp delete mode 100644 linden/indra/llmedia/llmediaimplexample1.h delete mode 100644 linden/indra/llmedia/llmediaimplexample2.cpp delete mode 100644 linden/indra/llmedia/llmediaimplexample2.h delete mode 100644 linden/indra/llmedia/llmediaimplfactory.cpp delete mode 100644 linden/indra/llmedia/llmediaimplfactory.h delete mode 100644 linden/indra/llmedia/llmediaimplgstreamer.h delete mode 100644 linden/indra/llmedia/llmediaimplgstreamervidplug.cpp delete mode 100644 linden/indra/llmedia/llmediaimplgstreamervidplug.h delete mode 100644 linden/indra/llmedia/llmediaimplllmozlib.cpp delete mode 100644 linden/indra/llmedia/llmediaimplllmozlib.h delete mode 100644 linden/indra/llmedia/llmediaimplquicktime.cpp delete mode 100644 linden/indra/llmedia/llmediaimplquicktime.h delete mode 100644 linden/indra/llmedia/llmediaimplregister.h delete mode 100644 linden/indra/llmedia/llmediamanager.cpp delete mode 100644 linden/indra/llmedia/llmediamanager.h delete mode 100644 linden/indra/llmedia/llmediaobserver.h create mode 100644 linden/indra/llmessage/tests/commtest.h create mode 100644 linden/indra/llmessage/tests/llcurl_stub.cpp create mode 100644 linden/indra/llmessage/tests/llhttpclientadapter_test.cpp create mode 100644 linden/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp create mode 100644 linden/indra/llmessage/tests/lltesthttpclientadapter.cpp create mode 100644 linden/indra/llmessage/tests/lltesthttpclientadapter.h create mode 100644 linden/indra/llmessage/tests/lltestmessagesender.cpp create mode 100644 linden/indra/llmessage/tests/lltestmessagesender.h create mode 100644 linden/indra/llmessage/tests/lltrustedmessageservice_test.cpp create mode 100644 linden/indra/llmessage/tests/networkio.h create mode 100644 linden/indra/llmessage/tests/test_llsdmessage_peer.py create mode 100644 linden/indra/llplugin/CMakeLists.txt create mode 100644 linden/indra/llplugin/llpluginclassmedia.cpp create mode 100644 linden/indra/llplugin/llpluginclassmedia.h create mode 100644 linden/indra/llplugin/llpluginclassmediaowner.h create mode 100644 linden/indra/llplugin/llplugininstance.cpp create mode 100644 linden/indra/llplugin/llplugininstance.h create mode 100644 linden/indra/llplugin/llpluginmessage.cpp create mode 100644 linden/indra/llplugin/llpluginmessage.h create mode 100644 linden/indra/llplugin/llpluginmessageclasses.h create mode 100644 linden/indra/llplugin/llpluginmessagepipe.cpp create mode 100644 linden/indra/llplugin/llpluginmessagepipe.h create mode 100644 linden/indra/llplugin/llpluginprocesschild.cpp create mode 100644 linden/indra/llplugin/llpluginprocesschild.h create mode 100644 linden/indra/llplugin/llpluginprocessparent.cpp create mode 100644 linden/indra/llplugin/llpluginprocessparent.h create mode 100644 linden/indra/llplugin/llpluginsharedmemory.cpp create mode 100644 linden/indra/llplugin/llpluginsharedmemory.h create mode 100644 linden/indra/llplugin/slplugin/CMakeLists.txt create mode 100644 linden/indra/llplugin/slplugin/slplugin.cpp create mode 100644 linden/indra/llplugin/slplugin/slplugin_info.plist create mode 100644 linden/indra/media_plugins/CMakeLists.txt create mode 100644 linden/indra/media_plugins/base/CMakeLists.txt create mode 100644 linden/indra/media_plugins/base/media_plugin_base.cpp create mode 100644 linden/indra/media_plugins/base/media_plugin_base.exp create mode 100644 linden/indra/media_plugins/base/media_plugin_base.h create mode 100644 linden/indra/media_plugins/example/CMakeLists.txt create mode 100644 linden/indra/media_plugins/example/media_plugin_example.cpp create mode 100644 linden/indra/media_plugins/gstreamer010/CMakeLists.txt create mode 100644 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h create mode 100644 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp create mode 100644 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h create mode 100644 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc create mode 100644 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc create mode 100644 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h create mode 100644 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp create mode 100644 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h create mode 100644 linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp create mode 100755 linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp~ create mode 100644 linden/indra/media_plugins/quicktime/CMakeLists.txt create mode 100644 linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp create mode 100644 linden/indra/media_plugins/webkit/CMakeLists.txt create mode 100644 linden/indra/media_plugins/webkit/media_plugin_webkit.cpp delete mode 100644 linden/indra/newview/llfloaterhtmlhelp.h create mode 100644 linden/indra/newview/llfloatermediabrowser.cpp create mode 100644 linden/indra/newview/llfloatermediabrowser.h create mode 100644 linden/indra/newview/llmediactrl.cpp create mode 100644 linden/indra/newview/llmediactrl.h create mode 100644 linden/indra/newview/llpanellandaudio.cpp create mode 100644 linden/indra/newview/llpanellandaudio.h create mode 100644 linden/indra/newview/llpanelmediahud.cpp create mode 100644 linden/indra/newview/llpanelmediahud.h create mode 100644 linden/indra/newview/llviewermedia_streamingaudio.cpp create mode 100644 linden/indra/newview/llviewermedia_streamingaudio.h create mode 100644 linden/indra/newview/llviewermediafocus.cpp create mode 100644 linden/indra/newview/llviewermediafocus.h create mode 100644 linden/indra/newview/llviewermediaobserver.h create mode 100644 linden/indra/newview/skins/default/xui/en-us/mime_types_linux.xml create mode 100644 linden/indra/newview/skins/default/xui/en-us/mime_types_mac.xml create mode 100644 linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml create mode 100644 linden/indra/newview/skins/default/xui/en-us/panel_hud.xml create mode 100644 linden/indra/newview/skins/default/xui/en-us/panel_media_hud.xml create mode 100755 linden/indra/newview/viewer_manifest.py~ create mode 100644 linden/indra/test_apps/llplugintest/CMakeLists.txt create mode 100644 linden/indra/test_apps/llplugintest/bookmarks.txt create mode 100644 linden/indra/test_apps/llplugintest/demo_media_plugin.cpp create mode 100644 linden/indra/test_apps/llplugintest/demo_media_plugin_2.cpp create mode 100644 linden/indra/test_apps/llplugintest/demo_plugin.cpp create mode 100644 linden/indra/test_apps/llplugintest/llmediaplugintest.cpp create mode 100644 linden/indra/test_apps/llplugintest/llmediaplugintest.h create mode 100644 linden/indra/test_apps/llplugintest/media_mappings.txt create mode 100644 linden/indra/test_apps/llplugintest/media_plugin_test.cpp create mode 100644 linden/indra/test_apps/llplugintest/media_simple_test.cpp create mode 100644 linden/indra/test_apps/llplugintest/plugin_host.cpp create mode 100644 linden/indra/test_apps/llplugintest/plugin_process_launcher.cpp mode change 100755 => 100644 linden/install.xml (limited to 'linden') diff --git a/linden/doc/LICENSE-logos.txt b/linden/doc/LICENSE-logos.txt new file mode 100644 index 0000000..e63c48e --- /dev/null +++ b/linden/doc/LICENSE-logos.txt @@ -0,0 +1,23 @@ +COPYRIGHT AND PERMISSION NOTICE + +Second Life(TM) Viewer Artwork. Copyright (C) 2008 Linden Research, Inc. + +Linden Research, Inc. ("Linden Lab") licenses the Second Life viewer +artwork and other works in the files distributed with this Notice under +the Creative Commons Attribution-Share Alike 3.0 License, available at +http://creativecommons.org/licenses/by-sa/3.0/legalcode. For the license +summary, see http://creativecommons.org/licenses/by-sa/3.0/. + +Notwithstanding the foregoing, all of Linden Lab's trademarks, including +but not limited to the Second Life brand name and Second Life Eye-in-Hand +logo, are subject to our trademark policy at +http://secondlife.com/corporate/trademark/. + +If you distribute any copies or adaptations of the Second Life viewer +artwork or any other works in these files, you must include this Notice +and clearly identify any changes made to the original works. Include +this Notice and information where copyright notices are usually included, +for example, after your own copyright notice acknowledging your use of +the Second Life viewer artwork, in a text file distributed with your +program, in your application's About window, or on a credits page for +your work. diff --git a/linden/doc/contributions.txt b/linden/doc/contributions.txt index c3d5e59..329fc28 100644 --- a/linden/doc/contributions.txt +++ b/linden/doc/contributions.txt @@ -85,11 +85,6 @@ Alissa Sabre VWR-7087 VWR-7153 VWR-7168 -<<<<<<< HEAD -======= - VWR-7087 - VWR-7086 ->>>>>>> origin/next VWR-9190 VWR-10728 VWR-12620 @@ -558,6 +553,8 @@ TBBle Kurosawa VWR-1892 Teardrops Fall VWR-5366 +Techwolf Lupindo + SNOW-334 tenebrous pau VWR-247 Tharax Ferraris diff --git a/linden/etc/message.xml b/linden/etc/message.xml index dd149dd..6598344 100644 --- a/linden/etc/message.xml +++ b/linden/etc/message.xml @@ -377,7 +377,23 @@ trusted-sender true + + ParcelMediaURLFilter + + flavor + llsd + trusted-sender + false + + ParcelNavigateMedia + + flavor + llsd + trusted-sender + false + + ParcelObjectOwnersReply flavor diff --git a/linden/indra/CMakeLists.txt b/linden/indra/CMakeLists.txt index 8dca9d8..64e0079 100644 --- a/linden/indra/CMakeLists.txt +++ b/linden/indra/CMakeLists.txt @@ -42,7 +42,6 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llimage) add_subdirectory(${LIBS_OPEN_PREFIX}llimagej2coj) add_subdirectory(${LIBS_OPEN_PREFIX}llinventory) add_subdirectory(${LIBS_OPEN_PREFIX}llmath) -add_subdirectory(${LIBS_OPEN_PREFIX}llmedia) add_subdirectory(${LIBS_OPEN_PREFIX}llmessage) add_subdirectory(${LIBS_OPEN_PREFIX}llprimitive) add_subdirectory(${LIBS_OPEN_PREFIX}llrender) @@ -59,8 +58,17 @@ endif (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts) add_custom_target(viewer) if (VIEWER) add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger) + add_subdirectory(${LIBS_OPEN_PREFIX}llplugin) add_subdirectory(${LIBS_OPEN_PREFIX}llui) + # viewer media plugins + add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins) + + # llplugin testbed code (is this the right way to include it?) + if (NOT LINUX) + add_subdirectory(${VIEWER_PREFIX}test_apps/llplugintest) + endif (NOT LINUX) + if (LINUX) add_subdirectory(${VIEWER_PREFIX}linux_crash_logger) add_dependencies(viewer linux-crash-logger-strip-target) diff --git a/linden/indra/cmake/00-Common.cmake b/linden/indra/cmake/00-Common.cmake index d1f379c..d335cb0 100644 --- a/linden/indra/cmake/00-Common.cmake +++ b/linden/indra/cmake/00-Common.cmake @@ -9,9 +9,9 @@ include(Variables) set(CMAKE_CXX_FLAGS_DEBUG "-D_DEBUG -DLL_DEBUG=1") set(CMAKE_CXX_FLAGS_RELEASE - "-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -D_SECURE_SCL=0 -DNDEBUG") + "-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -D_SECURE_SCL=0 -DLL_SEND_CRASH_REPORTS=1 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO - "-DLL_RELEASE=1 -D_SECURE_SCL=0 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1") + "-DLL_RELEASE=1 -D_SECURE_SCL=0 -DLL_SEND_CRASH_REPORTS=0 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1") # Don't bother with a MinSizeRel build. diff --git a/linden/indra/cmake/FindNDOF.cmake b/linden/indra/cmake/FindNDOF.cmake new file mode 100644 index 0000000..f980e34 --- /dev/null +++ b/linden/indra/cmake/FindNDOF.cmake @@ -0,0 +1,39 @@ +# -*- cmake -*- + +# - Find NDOF +# Find the NDOF includes and library +# This module defines +# NDOF_INCLUDE_DIR, where to find ndofdev_external.h, etc. +# NDOF_LIBRARY, the library needed to use NDOF. +# NDOF_FOUND, If false, do not try to use NDOF. + +find_path(NDOF_INCLUDE_DIR ndofdev_external.h + PATH_SUFFIXES ndofdev + ) + +set(NDOF_NAMES ${NDOF_NAMES} ndofdev libndofdev) +find_library(NDOF_LIBRARY + NAMES ${NDOF_NAMES} + ) + +if (NDOF_LIBRARY AND NDOF_INCLUDE_DIR) + set(NDOF_FOUND "YES") +else (NDOF_LIBRARY AND NDOF_INCLUDE_DIR) + set(NDOF_FOUND "NO") +endif (NDOF_LIBRARY AND NDOF_INCLUDE_DIR) + + +if (NDOF_FOUND) + if (NOT NDOF_FIND_QUIETLY) + message(STATUS "Found NDOF: Library in '${NDOF_LIBRARY}' and header in '${NDOF_INCLUDE_DIR}' ") + endif (NOT NDOF_FIND_QUIETLY) +else (NDOF_FOUND) + if (NDOF_FIND_REQUIRED) + message(FATAL_ERROR "Could not find NDOF library!") + endif (NDOF_FIND_REQUIRED) +endif (NDOF_FOUND) + +mark_as_advanced( + NDOF_LIBRARY + NDOF_INCLUDE_DIR + ) diff --git a/linden/indra/cmake/GStreamer010Plugin.cmake b/linden/indra/cmake/GStreamer010Plugin.cmake new file mode 100644 index 0000000..0d33483 --- /dev/null +++ b/linden/indra/cmake/GStreamer010Plugin.cmake @@ -0,0 +1,39 @@ +# -*- cmake -*- +include(Prebuilt) + +if (STANDALONE) + include(FindPkgConfig) + + pkg_check_modules(GSTREAMER010 REQUIRED gstreamer-0.10) + pkg_check_modules(GSTREAMER010_PLUGINS_BASE REQUIRED gstreamer-plugins-base-0.10) +elseif (LINUX) + use_prebuilt_binary(gstreamer) + # possible libxml should have its own .cmake file instead + use_prebuilt_binary(libxml) + set(GSTREAMER010_FOUND ON FORCE BOOL) + set(GSTREAMER010_PLUGINS_BASE_FOUND ON FORCE BOOL) + set(GSTREAMER010_INCLUDE_DIRS + ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/gstreamer-0.10 + ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0 + ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/libxml2 + ) + # We don't need to explicitly link against gstreamer itself, because + # LLMediaImplGStreamer probes for the system's copy at runtime. + set(GSTREAMER010_LIBRARIES + gobject-2.0 + gmodule-2.0 + dl + gthread-2.0 + rt + glib-2.0 + ) +endif (STANDALONE) + +if (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND) + set(GSTREAMER010 ON CACHE BOOL "Build with GStreamer-0.10 streaming media support.") +endif (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND) + +if (GSTREAMER010) + add_definitions(-DLL_GSTREAMER010_ENABLED=1) +endif (GSTREAMER010) + diff --git a/linden/indra/cmake/Glui.cmake b/linden/indra/cmake/Glui.cmake new file mode 100644 index 0000000..f62a568 --- /dev/null +++ b/linden/indra/cmake/Glui.cmake @@ -0,0 +1,28 @@ +# -*- cmake -*- +include(Linking) +include(Prebuilt) + +if (STANDALONE) + set(GLUI OFF CACHE BOOL + "GLUI support for the llplugin/llmedia test apps.") +else (STANDALONE) + use_prebuilt_binary(glui) + set(GLUI ON CACHE BOOL + "GLUI support for the llplugin/llmedia test apps.") +endif (STANDALONE) + +if (LINUX) + set(GLUI ON CACHE BOOL + "llplugin media apps HACK for Linux.") +endif (LINUX) + +if (DARWIN OR LINUX) + set(GLUI_LIBRARY + glui) +endif (DARWIN OR LINUX) + +if (WINDOWS) + set(GLUI_LIBRARY + debug glui32.lib + optimized glui32.lib) +endif (WINDOWS) diff --git a/linden/indra/cmake/Glut.cmake b/linden/indra/cmake/Glut.cmake new file mode 100644 index 0000000..314da30 --- /dev/null +++ b/linden/indra/cmake/Glut.cmake @@ -0,0 +1,19 @@ +# -*- cmake -*- +include(Linking) +include(Prebuilt) + +if (WINDOWS) + use_prebuilt_binary(freeglut) + set(GLUT_LIBRARY + debug freeglut_static.lib + optimized freeglut_static.lib) +endif (WINDOWS) + +if (LINUX) + FIND_LIBRARY(GLUT_LIBRARY glut) +endif (LINUX) + +if (DARWIN) + include(CMakeFindFrameworks) + find_library(GLUT_LIBRARY GLUT) +endif (DARWIN) diff --git a/linden/indra/cmake/LLAudio.cmake b/linden/indra/cmake/LLAudio.cmake index 625e212..89b790c 100644 --- a/linden/indra/cmake/LLAudio.cmake +++ b/linden/indra/cmake/LLAudio.cmake @@ -1,11 +1,9 @@ # -*- cmake -*- include(Audio) -include(OPENAL) set(LLAUDIO_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llaudio - ${OPENAL_INCLUDE_DIRS} ) set(LLAUDIO_LIBRARIES llaudio ${OPENAL_LIBRARIES}) diff --git a/linden/indra/cmake/LLMedia.cmake b/linden/indra/cmake/LLMedia.cmake deleted file mode 100644 index 8a36a69..0000000 --- a/linden/indra/cmake/LLMedia.cmake +++ /dev/null @@ -1,13 +0,0 @@ -# -*- cmake -*- - -include(GStreamer) - -set(LLMEDIA_INCLUDE_DIRS - ${LIBS_OPEN_DIR}/llmedia - ) - -set(LLMEDIA_LIBRARIES - llmedia - ${GSTREAMER_LIBRARIES} - ${GSTREAMER_PLUGINS_BASE_LIBRARIES} - ) diff --git a/linden/indra/cmake/LLPlugin.cmake b/linden/indra/cmake/LLPlugin.cmake new file mode 100644 index 0000000..9722f16 --- /dev/null +++ b/linden/indra/cmake/LLPlugin.cmake @@ -0,0 +1,8 @@ +# -*- cmake -*- + + +set(LLPLUGIN_INCLUDE_DIRS + ${LIBS_OPEN_DIR}/llplugin + ) + +set(LLPLUGIN_LIBRARIES llplugin) diff --git a/linden/indra/cmake/MediaPluginBase.cmake b/linden/indra/cmake/MediaPluginBase.cmake new file mode 100644 index 0000000..2be035b --- /dev/null +++ b/linden/indra/cmake/MediaPluginBase.cmake @@ -0,0 +1,8 @@ +# -*- cmake -*- + + +set(MEDIA_PLUGIN_BASE_INCLUDE_DIRS + ${LIBS_OPEN_DIR}/media_plugins/base/ + ) + +set(MEDIA_PLUGIN_BASE_LIBRARIES media_plugin_base) diff --git a/linden/indra/cmake/Mozlib.cmake b/linden/indra/cmake/Mozlib.cmake index e9555df..e69de29 100644 --- a/linden/indra/cmake/Mozlib.cmake +++ b/linden/indra/cmake/Mozlib.cmake @@ -1,47 +0,0 @@ -# -*- cmake -*- -include(Linking) -include(Prebuilt) - -if (STANDALONE) - set(MOZLIB OFF CACHE BOOL - "Enable Mozilla support in the viewer (requires llmozlib library).") -else (STANDALONE) - use_prebuilt_binary(llmozlib) - set(MOZLIB ON CACHE BOOL - "Enable Mozilla support in the viewer (requires llmozlib library).") -endif (STANDALONE) - -if (MOZLIB) - add_definitions(-DLL_LLMOZLIB_ENABLED=1) - - if (LINUX) - link_directories(${CMAKE_SOURCE_DIR}/newview/app_settings/mozilla-runtime-linux-${ARCH}) - set(MOZLIB_LIBRARIES - llmozlib2 - mozjs - nspr4 - plc4 - plds4 - xpcom - xul - profdirserviceprovider_s - ) - elseif (WINDOWS) - if (MSVC71) - set(MOZLIB_LIBRARIES - debug llmozlib2d - optimized llmozlib2) - elseif (MSVC80 OR MSVC90) - set(MOZLIB_LIBRARIES - debug llmozlib2d-vc80 - optimized llmozlib2-vc80) - endif (MSVC71) - else (LINUX) - set(MOZLIB_LIBRARIES - optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libllmozlib2.dylib - debug ${ARCH_PREBUILT_DIRS_DEBUG}/libllmozlib2.dylib - ) - endif (LINUX) -else (MOZLIB) - add_definitions(-DLL_LLMOZLIB_ENABLED=0) -endif (MOZLIB) diff --git a/linden/indra/cmake/NDOF.cmake b/linden/indra/cmake/NDOF.cmake index dad74e9..bdf5db1 100644 --- a/linden/indra/cmake/NDOF.cmake +++ b/linden/indra/cmake/NDOF.cmake @@ -1,14 +1,28 @@ # -*- cmake -*- include(Prebuilt) -use_prebuilt_binary(ndofdev) +if (STANDALONE) + include(FindNDOF) + if(NOT NDOF_FOUND) + message(STATUS "Building without N-DoF joystick support") + endif(NOT NDOF_FOUND) +else (STANDALONE) + use_prebuilt_binary(ndofdev) -if (WINDOWS OR DARWIN OR LINUX) - add_definitions(-DLIB_NDOF=1) -endif (WINDOWS OR DARWIN OR LINUX) + if (WINDOWS) + set(NDOF_LIBRARY libndofdev) + elseif (DARWIN OR LINUX) + set(NDOF_LIBRARY ndofdev) + endif (WINDOWS) + + set(NDOF_INCLUDE_DIR ${ARCH_PREBUILT_DIRS}/include/ndofdev) + set(NDOF_FOUND 1) +endif (STANDALONE) -if (WINDOWS) - set(NDOF_LIBRARY libndofdev) -elseif (DARWIN OR LINUX) - set(NDOF_LIBRARY ndofdev) -endif (WINDOWS) +if (NDOF_FOUND) + add_definitions(-DLIB_NDOF=1) + include_directories(${NDOF_INCLUDE_DIR}) +else (NDOF_FOUND) + set(NDOF_INCLUDE_DIR "") + set(NDOF_LIBRARY "") +endif (NDOF_FOUND) diff --git a/linden/indra/cmake/OPENAL.cmake b/linden/indra/cmake/OPENAL.cmake index 4f0e0cc..f7ebfe6 100644 --- a/linden/indra/cmake/OPENAL.cmake +++ b/linden/indra/cmake/OPENAL.cmake @@ -1,10 +1,12 @@ # -*- cmake -*- - -include(Variables) include(Linking) +include(Prebuilt) -set(OPENAL ON CACHE BOOL "Enable OpenAL") - +if (LINUX) + set(OPENAL ON CACHE BOOL "Enable OpenAL") +else (LINUX) + set(OPENAL OFF CACHE BOOL "Enable OpenAL") +endif (LINUX) if (OPENAL) @@ -109,5 +111,8 @@ if (OPENAL) set(OPENAL_FOUND TRUE CACHE BOOL "Found OpenAL and ALUT libraries successfully" ) +endif (OPENAL) +if (OPENAL) + message(STATUS "Building with OpenAL audio support") endif (OPENAL) diff --git a/linden/indra/cmake/OPENAL.cmake.imp b/linden/indra/cmake/OPENAL.cmake.imp new file mode 100644 index 0000000..60abef3 --- /dev/null +++ b/linden/indra/cmake/OPENAL.cmake.imp @@ -0,0 +1,115 @@ +# -*- cmake -*- + +include(Variables) +include(Linking) + +set(OPENAL ON CACHE BOOL "Enable OpenAL") + + +if (OPENAL) + + # message(STATUS "Building with OpenAL audio support") + + # OPENAL_LIB + use_prebuilt_binary(openal) + + if (WINDOWS) + set(OPENAL_LIB + optimized ${ARCH_PREBUILT_DIRS_RELEASE}/openal32.lib + debug ${ARCH_PREBUILT_DIRS_DEBUG}/openal32.lib + ) + + elseif (DARWIN) + # Look for for system's OpenAL.framework + find_library(OPENAL_LIB + NAMES openal.1 + PATHS ${ARCH_PREBUILT_DIRS_RELEASE} + NO_DEFAULT_PATH + ) + else (WINDOWS) + set(OPENAL_LIB openal) + endif (WINDOWS) + + if (NOT OPENAL_LIB) + message(FATAL_ERROR "OpenAL not found!") + else (NOT OPENAL_LIB) + # message(STATUS "OpenAL found: ${OPENAL_LIB}") + endif (NOT OPENAL_LIB) + + + + # OPENAL_INCLUDE_DIR + + if (DARWIN) + set(OPENAL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/AL) + else (DARWIN) + find_path(OPENAL_INCLUDE_DIR + NAMES al.h + PATHS ${LIBS_PREBUILT_DIR}/include/AL + ) + endif (DARWIN) + + if (NOT OPENAL_INCLUDE_DIR) + message(FATAL_ERROR "al.h not found!") + else (NOT OPENAL_INCLUDE_DIR) + # message(STATUS "al.h found in: ${OPENAL_INCLUDE_DIR}") + endif (NOT OPENAL_INCLUDE_DIR) + + + + # ALUT_LIB + + if (WINDOWS) + set(ALUT_LIB + optimized ${ARCH_PREBUILT_DIRS_RELEASE}/alut.lib + debug ${ARCH_PREBUILT_DIRS_DEBUG}/alut.lib + ) + elseif (DARWIN) + find_library( ALUT_LIB + NAMES alut.0 + PATHS ${ARCH_PREBUILT_DIRS_RELEASE} + NO_DEFAULT_PATH + ) + else (WINDOWS) + set(ALUT_LIB alut) + endif (WINDOWS) + + if (NOT ALUT_LIB) + message(FATAL_ERROR "ALUT not found!") + else (NOT ALUT_LIB) + # message(STATUS "ALUT found: ${ALUT_LIB}") + endif (NOT ALUT_LIB) + + + + # ALUT_INCLUDE_DIR + + find_path(ALUT_INCLUDE_DIR + NAMES alut.h + PATHS ${OPENAL_INCLUDE_DIR} + ) + + if (NOT ALUT_INCLUDE_DIR) + message(FATAL_ERROR "alut.h not found!") + else (NOT ALUT_INCLUDE_DIR) + # message(STATUS "alut.h found in: ${ALUT_INCLUDE_DIR}") + endif (NOT ALUT_INCLUDE_DIR) + + + + set(OPENAL_LIBRARIES + ${OPENAL_LIB} + ${ALUT_LIB} + ) + + set(OPENAL_INCLUDE_DIRS + ${OPENAL_INCLUDE_DIR} + ${ALUT_INCLUDE_DIR} + ) + + + set(OPENAL_FOUND TRUE CACHE BOOL + "Found OpenAL and ALUT libraries successfully" + ) + +endif (OPENAL) diff --git a/linden/indra/cmake/PluginAPI.cmake b/linden/indra/cmake/PluginAPI.cmake new file mode 100644 index 0000000..d1649e8 --- /dev/null +++ b/linden/indra/cmake/PluginAPI.cmake @@ -0,0 +1,16 @@ +# -*- cmake -*- + +if (WINDOWS) + set(PLUGIN_API_WINDOWS_LIBRARIES + wsock32 + ws2_32 + psapi + netapi32 + advapi32 + user32 + ) +else (WINDOWS) + set(PLUGIN_API_WINDOWS_LIBRARIES "") +endif (WINDOWS) + + diff --git a/linden/indra/cmake/QuickTimePlugin.cmake b/linden/indra/cmake/QuickTimePlugin.cmake new file mode 100644 index 0000000..8afd8f3 --- /dev/null +++ b/linden/indra/cmake/QuickTimePlugin.cmake @@ -0,0 +1,46 @@ +# -*- cmake -*- + +if(INSTALL_PROPRIETARY) + include(Prebuilt) + use_prebuilt_binary(quicktime) +endif(INSTALL_PROPRIETARY) + +if (DARWIN) + include(CMakeFindFrameworks) + find_library(QUICKTIME_LIBRARY QuickTime) +elseif (WINDOWS) + set(QUICKTIME_SDK_DIR "$ENV{PROGRAMFILES}/QuickTime SDK" + CACHE PATH "Location of the QuickTime SDK.") + + find_library(DEBUG_QUICKTIME_LIBRARY qtmlclient + PATHS + ${ARCH_PREBUILT_DIRS_DEBUG} + "${QUICKTIME_SDK_DIR}\\libraries" + ) + + find_library(RELEASE_QUICKTIME_LIBRARY qtmlclient + PATHS + ${ARCH_PREBUILT_DIRS_RELEASE} + "${QUICKTIME_SDK_DIR}\\libraries" + ) + + if (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY) + set(QUICKTIME_LIBRARY + optimized ${RELEASE_QUICKTIME_LIBRARY} + debug ${DEBUG_QUICKTIME_LIBRARY} + ) + + endif (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY) + + include_directories( + ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/quicktime + "${QUICKTIME_SDK_DIR}\\CIncludes" + ) +endif (DARWIN) + +mark_as_advanced(QUICKTIME_LIBRARY) + +if (QUICKTIME_LIBRARY) + set(QUICKTIME ON CACHE BOOL "Build with QuickTime streaming media support.") +endif (QUICKTIME_LIBRARY) + diff --git a/linden/indra/cmake/WebKitLibPlugin.cmake b/linden/indra/cmake/WebKitLibPlugin.cmake new file mode 100644 index 0000000..23958fe --- /dev/null +++ b/linden/indra/cmake/WebKitLibPlugin.cmake @@ -0,0 +1,55 @@ +# -*- cmake -*- +include(Linking) +include(Prebuilt) + +if (STANDALONE) + set(WEBKITLIBPLUGIN OFF CACHE BOOL + "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.") +else (STANDALONE) + use_prebuilt_binary(llqtwebkit) + set(WEBKITLIBPLUGIN ON CACHE BOOL + "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.") +endif (STANDALONE) + +if (WINDOWS) + set(WEBKIT_PLUGIN_LIBRARIES + debug llqtwebkitd + debug QtWebKitd4 + debug QtOpenGLd4 + debug QtNetworkd4 + debug QtGuid4 + debug QtCored4 + debug qtmaind + optimized llqtwebkit + optimized QtWebKit4 + optimized QtOpenGL4 + optimized QtNetwork4 + optimized QtGui4 + optimized QtCore4 + optimized qtmain + ) +elseif (DARWIN) + set(WEBKIT_PLUGIN_LIBRARIES + optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib + debug ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib + ) +elseif (LINUX) + if (STANDALONE) + set(WEBKIT_PLUGIN_LIBRARIES llqtwebkit) + else (STANDALONE) + set(WEBKIT_PLUGIN_LIBRARIES + llqtwebkit + qgif + qjpeg + QtWebKit + QtOpenGL + QtNetwork + QtGui + QtCore + fontconfig + X11 + Xrender + GL + ) + endif (STANDALONE) +endif (WINDOWS) diff --git a/linden/indra/cmake/linden%2findra%2fcmake%2fCopyWinLibs.cmake.rej.txt b/linden/indra/cmake/linden%2findra%2fcmake%2fCopyWinLibs.cmake.rej.txt new file mode 100644 index 0000000..295c9fe --- /dev/null +++ b/linden/indra/cmake/linden%2findra%2fcmake%2fCopyWinLibs.cmake.rej.txt @@ -0,0 +1,257 @@ +*************** +*** 15,35 **** + wrap_oal.dll + ) + + set(debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") + set(debug_files +- freebl3.dll +- js3250.dll +- nspr4.dll +- nss3.dll +- nssckbi.dll +- plc4.dll +- plds4.dll +- smime3.dll +- softokn3.dll +- ssl3.dll +- xpcom.dll +- xul.dll + openjpegd.dll +- windbgdlg.exe + ) + +--- 15,30 ---- + wrap_oal.dll + ) ++ copy_if_different( ++ ${vivox_src_dir} ++ "${CMAKE_CURRENT_BINARY_DIR}/Debug" ++ out_targets ++ ${vivox_files} ++ ) ++ set(all_targets ${all_targets} ${out_targets}) ++ + + set(debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") + set(debug_files + openjpegd.dll + ) + +*************** +*** 42,50 **** + set(all_targets ${all_targets} ${out_targets}) + +- copy_if_different( +- ${vivox_src_dir} +- "${CMAKE_CURRENT_BINARY_DIR}/Debug" +- out_targets +- ${vivox_files} + ) + set(all_targets ${all_targets} ${out_targets}) +--- 37,206 ---- + set(all_targets ${all_targets} ${out_targets}) + ++ # Debug config runtime files required for the plugin test mule ++ set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") ++ set(plugintest_debug_files ++ libeay32.dll ++ libglib-2.0-0.dll ++ libgmodule-2.0-0.dll ++ libgobject-2.0-0.dll ++ libgthread-2.0-0.dll ++ qtcored4.dll ++ qtguid4.dll ++ qtnetworkd4.dll ++ qtopengld4.dll ++ qtwebkitd4.dll ++ ssleay32.dll ++ ) ++ copy_if_different( ++ ${plugintest_debug_src_dir} ++ "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Debug" ++ out_targets ++ ${plugintest_debug_files} ++ ) ++ set(all_targets ${all_targets} ${out_targets}) ++ ++ # Debug config runtime files required for the plugin test mule (Qt image format plugins) ++ set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/imageformats") ++ set(plugintest_debug_files ++ qgifd4.dll ++ qicod4.dll ++ qjpegd4.dll ++ qmngd4.dll ++ qsvgd4.dll ++ qtiffd4.dll ++ ) ++ copy_if_different( ++ ${plugintest_debug_src_dir} ++ "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Debug/imageformats" ++ out_targets ++ ${plugintest_debug_files} ++ ) ++ set(all_targets ${all_targets} ${out_targets}) ++ ++ copy_if_different( ++ ${plugintest_debug_src_dir} ++ "${CMAKE_CURRENT_BINARY_DIR}/llplugin/imageformats" ++ out_targets ++ ${plugintest_debug_files} ++ ) ++ set(all_targets ${all_targets} ${out_targets}) ++ ++ # Release & ReleaseDebInfo config runtime files required for the plugin test mule ++ set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") ++ set(plugintest_release_files ++ libeay32.dll ++ libglib-2.0-0.dll ++ libgmodule-2.0-0.dll ++ libgobject-2.0-0.dll ++ libgthread-2.0-0.dll ++ # llkdu.dll (not required for plugin test) ++ qtcore4.dll ++ qtgui4.dll ++ qtnetwork4.dll ++ qtopengl4.dll ++ qtwebkit4.dll ++ ssleay32.dll ++ ) ++ copy_if_different( ++ ${plugintest_release_src_dir} ++ "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Release" ++ out_targets ++ ${plugintest_release_files} ++ ) ++ set(all_targets ${all_targets} ${out_targets}) ++ ++ copy_if_different( ++ ${plugintest_release_src_dir} ++ "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/RelWithDebInfo" ++ out_targets ++ ${plugintest_release_files} ++ ) ++ set(all_targets ${all_targets} ${out_targets}) ++ ++ # Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt image format plugins) ++ set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/imageformats") ++ set(plugintest_release_files ++ qgif4.dll ++ qico4.dll ++ qjpeg4.dll ++ qmng4.dll ++ qsvg4.dll ++ qtiff4.dll ++ ) ++ copy_if_different( ++ ${plugintest_release_src_dir} ++ "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Release/imageformats" ++ out_targets ++ ${plugintest_release_files} ++ ) ++ set(all_targets ${all_targets} ${out_targets}) ++ ++ copy_if_different( ++ ${plugintest_release_src_dir} ++ "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/RelWithDebInfo/imageformats" ++ out_targets ++ ${plugintest_release_files} ++ ) ++ set(all_targets ${all_targets} ${out_targets}) ++ ++ copy_if_different( ++ ${plugintest_release_src_dir} ++ "${CMAKE_CURRENT_BINARY_DIR}/Release/llplugin/imageformats" ++ out_targets ++ ${plugintest_release_files} ++ ) ++ set(all_targets ${all_targets} ${out_targets}) ++ ++ copy_if_different( ++ ${plugintest_release_src_dir} ++ "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin/imageformats" ++ out_targets ++ ${plugintest_release_files} ++ ) ++ set(all_targets ${all_targets} ${out_targets}) ++ ++ # Debug config runtime files required for the plugins ++ set(plugins_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") ++ set(plugins_debug_files ++ libeay32.dll ++ qtcored4.dll ++ qtguid4.dll ++ qtnetworkd4.dll ++ qtopengld4.dll ++ qtwebkitd4.dll ++ ssleay32.dll ++ ) ++ copy_if_different( ++ ${plugins_debug_src_dir} ++ "${CMAKE_CURRENT_BINARY_DIR}/Debug/llplugin" ++ out_targets ++ ${plugins_debug_files} ++ ) ++ set(all_targets ${all_targets} ${out_targets}) ++ ++ # Release & ReleaseDebInfo config runtime files required for the plugins ++ set(plugins_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") ++ set(plugins_release_files ++ libeay32.dll ++ qtcore4.dll ++ qtgui4.dll ++ qtnetwork4.dll ++ qtopengl4.dll ++ qtwebkit4.dll ++ ssleay32.dll ++ ) ++ copy_if_different( ++ ${plugins_release_src_dir} ++ "${CMAKE_CURRENT_BINARY_DIR}/Release/llplugin" ++ out_targets ++ ${plugins_release_files} ++ ) ++ set(all_targets ${all_targets} ${out_targets}) ++ ++ copy_if_different( ++ ${plugins_release_src_dir} ++ "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin" ++ out_targets ++ ${plugins_release_files} + ) + set(all_targets ${all_targets} ${out_targets}) +*************** +*** 52,67 **** + set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") + set(release_files +- freebl3.dll +- js3250.dll +- nspr4.dll +- nss3.dll +- nssckbi.dll +- plc4.dll +- plds4.dll +- smime3.dll +- softokn3.dll +- ssl3.dll +- xpcom.dll +- xul.dll + openjpeg.dll + ) +--- 208,211 ---- + set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") + set(release_files + openjpeg.dll + ) +*************** +*** 252,256 **** + ${debug_appconfig_file} + ) +- add_dependencies(copy_win_libs prepare) + + if(EXISTS ${internal_llkdu_path}) +--- 396,399 ---- + ${debug_appconfig_file} + ) + + if(EXISTS ${internal_llkdu_path}) diff --git a/linden/indra/llaudio/CMakeLists.txt b/linden/indra/llaudio/CMakeLists.txt index 0a668f9..1a0527c 100644 --- a/linden/indra/llaudio/CMakeLists.txt +++ b/linden/indra/llaudio/CMakeLists.txt @@ -4,6 +4,7 @@ project(llaudio) # Current starting point for CMake. Seems rather arbitrary - MC include(00-Common) +include(LLAudio) include(Audio) include(OPENAL) include(FMOD) @@ -12,9 +13,9 @@ include(LLCommon) include(LLMath) include(LLMessage) include(LLVFS) -include(LLMedia) include_directories( + ${LLAUDIO_INCLUDE_DIRS} ${FMOD_INCLUDE_DIR} ${LLCOMMON_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} @@ -26,43 +27,43 @@ include_directories( ${VORBIS_INCLUDE_DIRS} ${OPENAL_LIB_INCLUDE_DIRS} ${FREEAULT_LIB_INCLUDE_DIRS} - ${LLMEDIA_INCLUDE_DIRS} - ${GSTREAMER_INCLUDE_DIRS} ) set(llaudio_SOURCE_FILES - audioengine.cpp - listener.cpp + llaudioengine.cpp + lllistener.cpp llaudiodecodemgr.cpp - vorbisdecode.cpp - vorbisencode.cpp + llvorbisdecode.cpp + llvorbisencode.cpp ) set(llaudio_HEADER_FILES CMakeLists.txt - audioengine.h - listener.h + llaudioengine.h + lllistener.h llaudiodecodemgr.h - vorbisdecode.h - vorbisencode.h - windgen.h + llvorbisdecode.h + llvorbisencode.h + llwindgen.h ) if (FMOD) list(APPEND llaudio_SOURCE_FILES - audioengine_fmod.cpp - listener_fmod.cpp + llaudioengine_fmod.cpp + lllistener_fmod.cpp + llstreamingaudio_fmod.cpp ) list(APPEND llaudio_HEADER_FILES - audioengine_fmod.h - listener_fmod.h + llaudioengine_fmod.h + lllistener_fmod.h + llstreamingaudio_fmod.h ) if (LINUX) if (${CXX_VERSION} MATCHES "4.[23]") - set_source_files_properties(audioengine_fmod.cpp + set_source_files_properties(llaudioengine_fmod.cpp COMPILE_FLAGS -Wno-error=write-strings) endif (${CXX_VERSION} MATCHES "4.[23]") endif (LINUX) @@ -70,13 +71,13 @@ endif (FMOD) if (OPENAL) list(APPEND llaudio_SOURCE_FILES - audioengine_openal.cpp - listener_openal.cpp + llaudioengine_openal.cpp + lllistener_openal.cpp ) list(APPEND llaudio_HEADER_FILES - audioengine_openal.h - listener_openal.h + llaudioengine_openal.h + lllistener_openal.h ) endif (OPENAL) diff --git a/linden/indra/llaudio/audioengine.cpp b/linden/indra/llaudio/audioengine.cpp deleted file mode 100644 index 1900c38..0000000 --- a/linden/indra/llaudio/audioengine.cpp +++ /dev/null @@ -1,1904 +0,0 @@ - /** - * @file audioengine.cpp - * @brief implementation of LLAudioEngine class abstracting the Open - * AL audio support - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include - -#include "linden_common.h" - -#include "audioengine.h" - -#include "llerror.h" -#include "llmath.h" - -#include "sound_ids.h" // temporary hack for min/max distances - -#include "llvfs.h" -#include "lldir.h" -#include "llaudiodecodemgr.h" -#include "llassetstorage.h" - -#include "llmediamanager.h" -#include "llmediabase.h" -#include "llmediaimplcommon.h" - -// necessary for grabbing sounds from sim (implemented in viewer) -extern void request_sound(const LLUUID &sound_guid); - -LLAudioEngine* gAudiop = NULL; - - -// -// LLAudioEngine implementation -// - - -LLAudioEngine::LLAudioEngine() -{ - setDefaults(); -} - - -LLAudioEngine::~LLAudioEngine() -{ -} - - -void LLAudioEngine::setDefaults() -{ - mMaxWindGain = 1.f; - - mListenerp = NULL; - - mMuted = false; - mUserData = NULL; - - mLastStatus = 0; - - mNumChannels = 0; - mEnableWind = false; - - S32 i; - for (i = 0; i < MAX_CHANNELS; i++) - { - mChannels[i] = NULL; - } - for (i = 0; i < MAX_BUFFERS; i++) - { - mBuffers[i] = NULL; - } - - mMasterGain = 1.f; - mInternetStreamGain = 0.125f; - mNextWindUpdate = 0.f; - - mInternetStreamMedia = NULL; - mInternetStreamURL.clear(); - - mStatus = LLMediaBase::STATUS_UNKNOWN; - - for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++) - mSecondaryGain[i] = 1.0f; -} - - -bool LLAudioEngine::init(const S32 num_channels, void* userdata) -{ - setDefaults(); - - mNumChannels = num_channels; - mUserData = userdata; - - allocateListener(); - - // Initialize the decode manager - gAudioDecodeMgrp = new LLAudioDecodeMgr; - - llinfos << "LLAudioEngine::init() AudioEngine successfully initialized" << llendl; - - return true; -} - - -void LLAudioEngine::shutdown() -{ - // Clean up decode manager - delete gAudioDecodeMgrp; - gAudioDecodeMgrp = NULL; - - // Clean up wind source - cleanupWind(); - - // Clean up audio sources - source_map::iterator iter_src; - for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++) - { - delete iter_src->second; - } - - - // Clean up audio data - data_map::iterator iter_data; - for (iter_data = mAllData.begin(); iter_data != mAllData.end(); iter_data++) - { - delete iter_data->second; - } - - - // Clean up channels - S32 i; - for (i = 0; i < MAX_CHANNELS; i++) - { - delete mChannels[i]; - mChannels[i] = NULL; - } - - // Clean up buffers - for (i = 0; i < MAX_BUFFERS; i++) - { - delete mBuffers[i]; - mBuffers[i] = NULL; - } - - delete mInternetStreamMedia; - mInternetStreamMedia = NULL; - mInternetStreamURL.clear(); -} - - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -LLMediaBase::EStatus LLAudioEngine::getStatus() -{ - return mStatus; -} - - -// virtual -void LLAudioEngine::startInternetStream(const std::string& url) -{ - llinfos << "entered startInternetStream()" << llendl; - - if (!mInternetStreamMedia) - { - LLMediaManager* mgr = LLMediaManager::getInstance(); - if (mgr) - { - mInternetStreamMedia = mgr->createSourceFromMimeType(LLURI(url).scheme(), "audio/mpeg"); // assumes that whatever media implementation supports mp3 also supports vorbis. - llinfos << "mInternetStreamMedia is now " << mInternetStreamMedia << llendl; - } - } - - if(!mInternetStreamMedia) - { - return; - } - // Check for a dead stream from gstreamer, just in case - else if(getStatus() == LLMediaBase::STATUS_DEAD) - { - llinfos << "don't play dead stream urls"<< llendl; - mInternetStreamURL.clear(); - mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_STOP); - mInternetStreamMedia->updateMedia(); - stopInternetStream(); - } - else if (url.empty()) - { - llinfos << "url is emptly. Setting stream to NULL"<< llendl; - mInternetStreamURL.clear(); - mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_STOP); - mInternetStreamMedia->updateMedia(); - } - // Stream appears to be good, attempting to play - else - { - // stop any other stream first - stopInternetStream(); - - llinfos << "Starting internet stream: " << url << llendl; - mInternetStreamURL = url; - mInternetStreamMedia->navigateTo(url); - //llinfos << "Playing....." << llendl; - mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_START); - mInternetStreamMedia->updateMedia(); - mStatus = LLMediaBase::STATUS_STARTED; - } -} - -// virtual -void LLAudioEngine::stopInternetStream() -{ - llinfos << "entered stopInternetStream()" << llendl; - mInternetStreamURL.clear(); - - if(mInternetStreamMedia) - { - if(!mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_STOP)) - { - llinfos << "attempting to stop stream failed!" << llendl; - } - mInternetStreamMedia->updateMedia(); - } - - mInternetStreamURL.clear(); -} - -// virtual -void LLAudioEngine::pauseInternetStream(int pause) -{ - llinfos << "entered pauseInternetStream()" << llendl; - - if(!mInternetStreamMedia) - return; - - if(pause) - { - if(! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_PAUSE)) - { - llinfos << "attempting to pause stream failed!" << llendl; - } - } else { - if(! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_START)) - { - llinfos << "attempting to unpause stream failed!" << llendl; - } - } - mInternetStreamMedia->updateMedia(); -} - -// virtual -void LLAudioEngine::updateInternetStream() -{ - if (mInternetStreamMedia) - mInternetStreamMedia->updateMedia(); -} - -// virtual -int LLAudioEngine::isInternetStreamPlaying() -{ - if (!mInternetStreamMedia) - return 0; - - if (mInternetStreamMedia->getStatus() == LLMediaBase::STATUS_STARTED) - { - return 1; // Active and playing - } - - if (mInternetStreamMedia->getStatus() == LLMediaBase::STATUS_PAUSED) - { - return 2; // paused - } - - return 0; // Stopped -} - -// virtual -void LLAudioEngine::getInternetStreamInfo(char* artist, char* title) -{ - artist[0] = 0; - title[0] = 0; -} - -// virtual -void LLAudioEngine::setInternetStreamGain(F32 vol) -{ - mInternetStreamGain = vol; - - if(!mInternetStreamMedia) - return; - - vol = llclamp(vol, 0.f, 1.f); - mInternetStreamMedia->setVolume(vol); - mInternetStreamMedia->updateMedia(); -} - -// virtual -const std::string& LLAudioEngine::getInternetStreamURL() -{ - return mInternetStreamURL; -} - - -void LLAudioEngine::updateChannels() -{ - S32 i; - for (i = 0; i < MAX_CHANNELS; i++) - { - if (mChannels[i]) - { - // set secondary gain if type is available - LLAudioSource* source = mChannels[i]->getSource(); - if (source) - { - mChannels[i]->setSecondaryGain(mSecondaryGain[source->getType()]); - } - - mChannels[i]->updateBuffer(); - mChannels[i]->update3DPosition(); - mChannels[i]->updateLoop(); - } - } -} - -static const F32 default_max_decode_time = .002f; // 2 ms -void LLAudioEngine::idle(F32 max_decode_time) -{ - if (max_decode_time <= 0.f) - { - max_decode_time = default_max_decode_time; - } - - // "Update" all of our audio sources, clean up dead ones. - // Primarily does position updating, cleanup of unused audio sources. - // Also does regeneration of the current priority of each audio source. - - if (getMuted()) - { - setInternalGain(0.f); - } - else - { - setInternalGain(getMasterGain()); - } - - S32 i; - for (i = 0; i < MAX_BUFFERS; i++) - { - if (mBuffers[i]) - { - mBuffers[i]->mInUse = false; - } - } - - F32 max_priority = -1.f; - LLAudioSource *max_sourcep = NULL; // Maximum priority source without a channel - source_map::iterator iter; - for (iter = mAllSources.begin(); iter != mAllSources.end();) - { - LLAudioSource *sourcep = iter->second; - - // Update this source - sourcep->update(); - sourcep->updatePriority(); - - if (sourcep->isDone()) - { - // The source is done playing, clean it up. - delete sourcep; - mAllSources.erase(iter++); - continue; - } - - if (!sourcep->getChannel() && sourcep->getCurrentBuffer()) - { - // We could potentially play this sound if its priority is high enough. - if (sourcep->getPriority() > max_priority) - { - max_priority = sourcep->getPriority(); - max_sourcep = sourcep; - } - } - - // Move on to the next source - iter++; - } - - // Now, do priority-based organization of audio sources. - // All channels used, check priorities. - // Find channel with lowest priority - if (max_sourcep) - { - LLAudioChannel *channelp = getFreeChannel(max_priority); - if (channelp) - { - //LL_INFOS("AudioEngine") << "Replacing source in channel due to priority!" << llendl; - max_sourcep->setChannel(channelp); - channelp->setSource(max_sourcep); - if (max_sourcep->isSyncSlave()) - { - // A sync slave, it doesn't start playing until it's synced up with the master. - // Flag this channel as waiting for sync, and return true. - channelp->setWaiting(true); - } - else - { - channelp->setWaiting(false); - if (channelp->mCurrentBufferp) - { - channelp->play(); - } - } - } - } - - - // Do this BEFORE we update the channels - // Update the channels to sync up with any changes that the source made, - // such as changing what sound was playing. - updateChannels(); - - // Update queued sounds (switch to next queued data if the current has finished playing) - for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter) - { - // This is lame, instead of this I could actually iterate through all the sources - // attached to each channel, since only those with active channels - // can have anything interesting happen with their queue? (Maybe not true) - LLAudioSource *sourcep = iter->second; - if (!sourcep->mQueuedDatap) - { - // Nothing queued, so we don't care. - continue; - } - - LLAudioChannel *channelp = sourcep->getChannel(); - if (!channelp) - { - // This sound isn't playing, so we just process move the queue - sourcep->mCurrentDatap = sourcep->mQueuedDatap; - sourcep->mQueuedDatap = NULL; - - // Reset the timer so the source doesn't die. - sourcep->mAgeTimer.reset(); - // Make sure we have the buffer set up if we just decoded the data - if (sourcep->mCurrentDatap) - { - updateBufferForData(sourcep->mCurrentDatap); - } - - // Actually play the associated data. - sourcep->setupChannel(); - channelp = sourcep->getChannel(); - if (channelp) - { - channelp->updateBuffer(); - sourcep->getChannel()->play(); - } - continue; - } - else - { - // Check to see if the current sound is done playing, or looped. - if (!channelp->isPlaying()) - { - sourcep->mCurrentDatap = sourcep->mQueuedDatap; - sourcep->mQueuedDatap = NULL; - - // Reset the timer so the source doesn't die. - sourcep->mAgeTimer.reset(); - - // Make sure we have the buffer set up if we just decoded the data - if (sourcep->mCurrentDatap) - { - updateBufferForData(sourcep->mCurrentDatap); - } - - // Actually play the associated data. - sourcep->setupChannel(); - channelp->updateBuffer(); - sourcep->getChannel()->play(); - } - else if (sourcep->isLoop()) - { - // It's a loop, we need to check and see if we're done with it. - if (channelp->mLoopedThisFrame) - { - sourcep->mCurrentDatap = sourcep->mQueuedDatap; - sourcep->mQueuedDatap = NULL; - - // Actually, should do a time sync so if we're a loop master/slave - // we don't drift away. - sourcep->setupChannel(); - sourcep->getChannel()->play(); - } - } - } - } - - // Lame, update the channels AGAIN. - // Update the channels to sync up with any changes that the source made, - // such as changing what sound was playing. - updateChannels(); - - // Hack! For now, just use a global sync master; - LLAudioSource *sync_masterp = NULL; - LLAudioChannel *master_channelp = NULL; - F32 max_sm_priority = -1.f; - for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter) - { - LLAudioSource *sourcep = iter->second; - if (sourcep->isSyncMaster()) - { - if (sourcep->getPriority() > max_sm_priority) - { - sync_masterp = sourcep; - master_channelp = sync_masterp->getChannel(); - max_sm_priority = sourcep->getPriority(); - } - } - } - - if (master_channelp && master_channelp->mLoopedThisFrame) - { - // Synchronize loop slaves with their masters - // Update queued sounds (switch to next queued data if the current has finished playing) - for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter) - { - LLAudioSource *sourcep = iter->second; - - if (!sourcep->isSyncSlave()) - { - // Not a loop slave, we don't need to do anything - continue; - } - - LLAudioChannel *channelp = sourcep->getChannel(); - if (!channelp) - { - // Not playing, don't need to bother. - continue; - } - - if (!channelp->isPlaying()) - { - // Now we need to check if our loop master has just looped, and - // start playback if that's the case. - if (sync_masterp->getChannel()) - { - channelp->playSynced(master_channelp); - channelp->setWaiting(false); - } - } - } - } - - // Sync up everything that the audio engine needs done. - commitDeferredChanges(); - - // Flush unused buffers that are stale enough - for (i = 0; i < MAX_BUFFERS; i++) - { - if (mBuffers[i]) - { - if (!mBuffers[i]->mInUse && mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > 30.f) - { - //LL_INFOS("AudioEngine") << "Flushing unused buffer!" << llendl; - mBuffers[i]->mAudioDatap->mBufferp = NULL; - delete mBuffers[i]; - mBuffers[i] = NULL; - } - } - } - - - // Clear all of the looped flags for the channels - for (i = 0; i < MAX_CHANNELS; i++) - { - if (mChannels[i]) - { - mChannels[i]->mLoopedThisFrame = false; - } - } - - // Decode audio files - gAudioDecodeMgrp->processQueue(max_decode_time); - - // Call this every frame, just in case we somehow - // missed picking it up in all the places that can add - // or request new data. - startNextTransfer(); - - updateInternetStream(); -} - - - -bool LLAudioEngine::updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid) -{ - if (!adp) - { - return false; - } - - // Update the audio buffer first - load a sound if we have it. - // Note that this could potentially cause us to waste time updating buffers - // for sounds that actually aren't playing, although this should be mitigated - // by the fact that we limit the number of buffers, and we flush buffers based - // on priority. - if (!adp->getBuffer()) - { - if (adp->hasDecodedData()) - { - return adp->load(); - } - else if (adp->hasLocalData()) - { - if (audio_uuid.notNull()) - { - gAudioDecodeMgrp->addDecodeRequest(audio_uuid); - } - } - else - { - return false; - } - } - return true; -} - - -void LLAudioEngine::enableWind(bool enable) -{ - if (enable && (!mEnableWind)) - { - initWind(); - mEnableWind = enable; - } - else if (mEnableWind && (!enable)) - { - mEnableWind = enable; - cleanupWind(); - } -} - - -LLAudioBuffer *LLAudioEngine::getFreeBuffer() -{ - static clock_t last_info = 0; - static bool spamming = FALSE; - - S32 i; - for (i = 0; i < MAX_BUFFERS; i++) - { - if (!mBuffers[i]) - { - mBuffers[i] = createBuffer(); - return mBuffers[i]; - } - } - - - // Grab the oldest unused buffer - F32 max_age = -1.f; - S32 buffer_id = -1; - for (i = 0; i < MAX_BUFFERS; i++) - { - if (mBuffers[i]) - { - if (!mBuffers[i]->mInUse) - { - if (mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > max_age) - { - max_age = mBuffers[i]->mLastUseTimer.getElapsedTimeF32(); - buffer_id = i; - } - } - } - } - - if (buffer_id >= 0) - { - if (clock() - last_info > CLOCKS_PER_SEC) - { - // Do not spam us with such messages... - llinfos << "Taking over unused buffer " << buffer_id << llendl; - last_info = clock(); - } - else if (!spamming) - { - // ... but warn us *once* when the buffer freeing frequency is abnormal. - llwarns << "Excessive buffer freeing frequency, info messages throttled." << llendl; - spamming = true; - } - mBuffers[buffer_id]->mAudioDatap->mBufferp = NULL; - delete mBuffers[buffer_id]; - mBuffers[buffer_id] = createBuffer(); - return mBuffers[buffer_id]; - } - return NULL; -} - - -LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority) -{ - S32 i; - for (i = 0; i < mNumChannels; i++) - { - if (!mChannels[i]) - { - // No channel allocated here, use it. - mChannels[i] = createChannel(); - return mChannels[i]; - } - else - { - // Channel is allocated but not playing right now, use it. - if (!mChannels[i]->isPlaying() && !mChannels[i]->isWaiting()) - { - mChannels[i]->cleanup(); - if (mChannels[i]->getSource()) - { - mChannels[i]->getSource()->setChannel(NULL); - } - return mChannels[i]; - } - } - } - - // All channels used, check priorities. - // Find channel with lowest priority and see if we want to replace it. - F32 min_priority = 10000.f; - LLAudioChannel *min_channelp = NULL; - - for (i = 0; i < mNumChannels; i++) - { - LLAudioChannel *channelp = mChannels[i]; - LLAudioSource *sourcep = channelp->getSource(); - if (sourcep && sourcep->getPriority() < min_priority) - { - min_channelp = channelp; - min_priority = sourcep->getPriority(); - } - } - - if (min_priority > priority || !min_channelp) - { - // All playing channels have higher priority, return. - return NULL; - } - - // Flush the minimum priority channel, and return it. - min_channelp->cleanup(); - min_channelp->getSource()->setChannel(NULL); - return min_channelp; -} - - -void LLAudioEngine::cleanupBuffer(LLAudioBuffer *bufferp) -{ - S32 i; - for (i = 0; i < MAX_BUFFERS; i++) - { - if (mBuffers[i] == bufferp) - { - delete mBuffers[i]; - mBuffers[i] = NULL; - } - } -} - - -bool LLAudioEngine::preloadSound(const LLUUID &uuid) -{ - gAudiop->getAudioData(uuid); // We don't care about the return value, this is just to make sure - // that we have an entry, which will mean that the audio engine knows about this - - if (gAudioDecodeMgrp->addDecodeRequest(uuid)) - { - // This means that we do have a local copy, and we're working on decoding it. - return true; - } - - // At some point we need to have the audio/asset system check the static VFS - // before it goes off and fetches stuff from the server. - //llwarns << "Used internal preload for non-local sound" << llendl; - return false; -} - - -bool LLAudioEngine::isWindEnabled() -{ - return mEnableWind; -} - - -void LLAudioEngine::setMuted(bool muted) -{ - mMuted = muted; - enableWind(!mMuted); -} - - -void LLAudioEngine::setMasterGain(const F32 gain) -{ - mMasterGain = gain; - setInternalGain(gain); -} - -F32 LLAudioEngine::getMasterGain() -{ - return mMasterGain; -} - -void LLAudioEngine::setSecondaryGain(S32 type, F32 gain) -{ - llassert(type < LLAudioEngine::AUDIO_TYPE_COUNT); - - mSecondaryGain[type] = gain; -} - -F32 LLAudioEngine::getSecondaryGain(S32 type) -{ - return mSecondaryGain[type]; -} - -F32 LLAudioEngine::getInternetStreamGain() -{ - return mInternetStreamGain; -} - -void LLAudioEngine::setMaxWindGain(F32 gain) -{ - mMaxWindGain = gain; -} - - -F64 LLAudioEngine::mapWindVecToGain(LLVector3 wind_vec) -{ - F64 gain = 0.0; - - gain = wind_vec.magVec(); - - if (gain) - { - if (gain > 20) - { - gain = 20; - } - gain = gain/20.0; - } - - return (gain); -} - - -F64 LLAudioEngine::mapWindVecToPitch(LLVector3 wind_vec) -{ - LLVector3 listen_right; - F64 theta; - - // Wind frame is in listener-relative coordinates - LLVector3 norm_wind = wind_vec; - norm_wind.normVec(); - listen_right.setVec(1.0,0.0,0.0); - - // measure angle between wind vec and listener right axis (on 0,PI) - theta = acos(norm_wind * listen_right); - - // put it on 0, 1 - theta /= F_PI; - - // put it on [0, 0.5, 0] - if (theta > 0.5) theta = 1.0-theta; - if (theta < 0) theta = 0; - - return (theta); -} - - -F64 LLAudioEngine::mapWindVecToPan(LLVector3 wind_vec) -{ - LLVector3 listen_right; - F64 theta; - - // Wind frame is in listener-relative coordinates - listen_right.setVec(1.0,0.0,0.0); - - LLVector3 norm_wind = wind_vec; - norm_wind.normVec(); - - // measure angle between wind vec and listener right axis (on 0,PI) - theta = acos(norm_wind * listen_right); - - // put it on 0, 1 - theta /= F_PI; - - return (theta); -} - - -void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, - const S32 type, const LLVector3d &pos_global) -{ - // Create a new source (since this can't be associated with an existing source. - //LL_INFOS("AudioEngine") << "Localized: " << audio_uuid << llendl; - - //If we cannot hear it, dont even try to load the sound. - if (mMuted || gain == 0.0) - { - return; - } - - LLUUID source_id; - source_id.generate(); - - LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain, type); - gAudiop->addAudioSource(asp); - if (pos_global.isExactlyZero()) - { - asp->setAmbient(true); - } - else - { - asp->setPositionGlobal(pos_global); - } - asp->updatePriority(); - asp->play(audio_uuid); -} - - -void LLAudioEngine::setListenerPos(LLVector3 aVec) -{ - mListenerp->setPosition(aVec); -} - - -LLVector3 LLAudioEngine::getListenerPos() -{ - if (mListenerp) - { - return(mListenerp->getPosition()); - } - else - { - return(LLVector3::zero); - } -} - - -void LLAudioEngine::setListenerVelocity(LLVector3 aVec) -{ - mListenerp->setVelocity(aVec); -} - - -void LLAudioEngine::translateListener(LLVector3 aVec) -{ - mListenerp->translate(aVec); -} - - -void LLAudioEngine::orientListener(LLVector3 up, LLVector3 at) -{ - mListenerp->orient(up, at); -} - - -void LLAudioEngine::setListener(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at) -{ - mListenerp->set(pos,vel,up,at); -} - - -void LLAudioEngine::setDopplerFactor(F32 factor) -{ - if (mListenerp) - { - mListenerp->setDopplerFactor(factor); - } -} - - -F32 LLAudioEngine::getDopplerFactor() -{ - if (mListenerp) - { - return mListenerp->getDopplerFactor(); - } - else - { - return 0.f; - } -} - - -void LLAudioEngine::setDistanceFactor(F32 factor) -{ - if (mListenerp) - { - mListenerp->setDistanceFactor(factor); - } -} - - -F32 LLAudioEngine::getDistanceFactor() -{ - if (mListenerp) - { - return mListenerp->getDistanceFactor(); - } - else - { - return 0.f; - } -} - - -void LLAudioEngine::setRolloffFactor(F32 factor) -{ - if (mListenerp) - { - mListenerp->setRolloffFactor(factor); - } -} - - -F32 LLAudioEngine::getRolloffFactor() -{ - if (mListenerp) - { - return mListenerp->getRolloffFactor(); - } - else - { - return 0.f; - } -} - - -void LLAudioEngine::commitDeferredChanges() -{ - mListenerp->commitDeferredChanges(); -} - - -LLAudioSource *LLAudioEngine::findAudioSource(const LLUUID &source_id) -{ - source_map::iterator iter; - iter = mAllSources.find(source_id); - - if (iter == mAllSources.end()) - { - return NULL; - } - else - { - return iter->second; - } -} - - -LLAudioData *LLAudioEngine::getAudioData(const LLUUID &audio_uuid) -{ - data_map::iterator iter; - iter = mAllData.find(audio_uuid); - if (iter == mAllData.end()) - { - // Create the new audio data - LLAudioData *adp = new LLAudioData(audio_uuid); - mAllData[audio_uuid] = adp; - return adp; - } - else - { - return iter->second; - } -} - -void LLAudioEngine::addAudioSource(LLAudioSource *asp) -{ - mAllSources[asp->getID()] = asp; -} - - -void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp) -{ - source_map::iterator iter; - iter = mAllSources.find(asp->getID()); - if (iter == mAllSources.end()) - { - llwarns << "Cleaning up unknown audio source!" << llendl; - return; - } - delete asp; - mAllSources.erase(iter); -} - - -bool LLAudioEngine::hasDecodedFile(const LLUUID &uuid) -{ - std::string uuid_str; - uuid.toString(uuid_str); - - std::string wav_path; - wav_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str); - wav_path += ".dsf"; - - if (gDirUtilp->fileExists(wav_path)) - { - return true; - } - else - { - return false; - } -} - - -bool LLAudioEngine::hasLocalFile(const LLUUID &uuid) -{ - // See if it's in the VFS. - return gVFS->getExists(uuid, LLAssetType::AT_SOUND); -} - - -void LLAudioEngine::startNextTransfer() -{ - //LL_INFOS("AudioEngine") << "LLAudioEngine::startNextTransfer()" << llendl; - if (mCurrentTransfer.notNull() || getMuted()) - { - //LL_INFOS("AudioEngine") << "Transfer in progress, aborting" << llendl; - return; - } - - // Get the ID for the next asset that we want to transfer. - // Pick one in the following order: - LLUUID asset_id; - S32 i; - LLAudioSource *asp = NULL; - LLAudioData *adp = NULL; - data_map::iterator data_iter; - - // Check all channels for currently playing sounds. - F32 max_pri = -1.f; - for (i = 0; i < MAX_CHANNELS; i++) - { - if (!mChannels[i]) - { - continue; - } - - asp = mChannels[i]->getSource(); - if (!asp) - { - continue; - } - if (asp->getPriority() <= max_pri) - { - continue; - } - - if (asp->getPriority() <= max_pri) - { - continue; - } - - adp = asp->getCurrentData(); - if (!adp) - { - continue; - } - - if (!adp->hasLocalData() && adp->hasValidData()) - { - asset_id = adp->getID(); - max_pri = asp->getPriority(); - } - } - - // Check all channels for currently queued sounds. - if (asset_id.isNull()) - { - max_pri = -1.f; - for (i = 0; i < MAX_CHANNELS; i++) - { - if (!mChannels[i]) - { - continue; - } - - LLAudioSource *asp; - asp = mChannels[i]->getSource(); - if (!asp) - { - continue; - } - - if (asp->getPriority() <= max_pri) - { - continue; - } - - adp = asp->getQueuedData(); - if (!adp) - { - continue; - } - - if (!adp->hasLocalData() && adp->hasValidData()) - { - asset_id = adp->getID(); - max_pri = asp->getPriority(); - } - } - } - - // Check all live channels for other sounds (preloads). - if (asset_id.isNull()) - { - max_pri = -1.f; - for (i = 0; i < MAX_CHANNELS; i++) - { - if (!mChannels[i]) - { - continue; - } - - LLAudioSource *asp; - asp = mChannels[i]->getSource(); - if (!asp) - { - continue; - } - - if (asp->getPriority() <= max_pri) - { - continue; - } - - - for (data_iter = asp->mPreloadMap.begin(); data_iter != asp->mPreloadMap.end(); data_iter++) - { - LLAudioData *adp = data_iter->second; - if (!adp) - { - continue; - } - - if (!adp->hasLocalData() && adp->hasValidData()) - { - asset_id = adp->getID(); - max_pri = asp->getPriority(); - } - } - } - } - - // Check all sources - if (asset_id.isNull()) - { - max_pri = -1.f; - source_map::iterator source_iter; - for (source_iter = mAllSources.begin(); source_iter != mAllSources.end(); source_iter++) - { - asp = source_iter->second; - if (!asp) - { - continue; - } - - if (asp->getPriority() <= max_pri) - { - continue; - } - - adp = asp->getCurrentData(); - if (adp && !adp->hasLocalData() && adp->hasValidData()) - { - asset_id = adp->getID(); - max_pri = asp->getPriority(); - continue; - } - - adp = asp->getQueuedData(); - if (adp && !adp->hasLocalData() && adp->hasValidData()) - { - asset_id = adp->getID(); - max_pri = asp->getPriority(); - continue; - } - - for (data_iter = asp->mPreloadMap.begin(); data_iter != asp->mPreloadMap.end(); data_iter++) - { - LLAudioData *adp = data_iter->second; - if (!adp) - { - continue; - } - - if (!adp->hasLocalData() && adp->hasValidData()) - { - asset_id = adp->getID(); - max_pri = asp->getPriority(); - break; - } - } - } - } - - if (asset_id.notNull()) - { - LL_INFOS("AudioEngine") << "Getting asset data for: " << asset_id << llendl; - gAudiop->mCurrentTransfer = asset_id; - gAudiop->mCurrentTransferTimer.reset(); - gAssetStorage->getAssetData(asset_id, LLAssetType::AT_SOUND, - assetCallback, NULL); - } - else - { - //LL_INFOS("AudioEngine") << "No pending transfers?" << llendl; - } -} - - -// static -void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status) -{ - if (result_code) - { - LL_INFOS("AudioEngine") << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << llendl; - // Need to mark data as bad to avoid constant rerequests. - LLAudioData *adp = gAudiop->getAudioData(uuid); - if (adp) - { - adp->setHasValidData(false); - adp->setHasLocalData(false); - adp->setHasDecodedData(false); - } - } - else - { - LLAudioData *adp = gAudiop->getAudioData(uuid); - if (!adp) - { - // Should never happen - llwarns << "Got asset callback without audio data for " << uuid << llendl; - } - else - { - adp->setHasValidData(true); - adp->setHasLocalData(true); - gAudioDecodeMgrp->addDecodeRequest(uuid); - } - } - gAudiop->mCurrentTransfer = LLUUID::null; - gAudiop->startNextTransfer(); -} - - -// -// LLAudioSource implementation -// - - -LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain, const S32 type) -: mID(id), - mOwnerID(owner_id), - mPriority(0.f), - mGain(gain), - mType(type), - mAmbient(false), - mLoop(false), - mSyncMaster(false), - mSyncSlave(false), - mQueueSounds(false), - mPlayedOnce(false), - mChannelp(NULL), - mCurrentDatap(NULL), - mQueuedDatap(NULL) -{ -} - - -LLAudioSource::~LLAudioSource() -{ - if (mChannelp) - { - // Stop playback of this sound - mChannelp->setSource(NULL); - mChannelp = NULL; - } -} - - -void LLAudioSource::setChannel(LLAudioChannel *channelp) -{ - if (channelp == mChannelp) - { - return; - } - - mChannelp = channelp; -} - - -void LLAudioSource::update() -{ - if (!getCurrentBuffer()) - { - if (getCurrentData()) - { - // Hack - try and load the sound. Will do this as a callback - // on decode later. - if (getCurrentData()->load()) - { - play(getCurrentData()->getID()); - } - } - } -} - -void LLAudioSource::updatePriority() -{ - if (isAmbient()) - { - mPriority = 1.f; - } - else - { - // Priority is based on distance - LLVector3 dist_vec; - dist_vec.setVec(getPositionGlobal()); - dist_vec -= gAudiop->getListenerPos(); - F32 dist_squared = llmax(1.f, dist_vec.magVecSquared()); - - mPriority = mGain / dist_squared; - } -} - -bool LLAudioSource::setupChannel() -{ - LLAudioData *adp = getCurrentData(); - - if (!adp->getBuffer()) - { - // We're not ready to play back the sound yet, so don't try and allocate a channel for it. - //llwarns << "Aborting, no buffer" << llendl; - return false; - } - - - if (!mChannelp) - { - // Update the priority, in case we need to push out another channel. - updatePriority(); - - setChannel(gAudiop->getFreeChannel(getPriority())); - } - - if (!mChannelp) - { - // Ugh, we don't have any free channels. - // Now we have to reprioritize. - // For now, just don't play the sound. - //llwarns << "Aborting, no free channels" << llendl; - return false; - } - - mChannelp->setSource(this); - return true; -} - - -bool LLAudioSource::play(const LLUUID &audio_uuid) -{ - if (audio_uuid.isNull()) - { - if (getChannel()) - { - getChannel()->setSource(NULL); - setChannel(NULL); - addAudioData(NULL, true); - } - } - // Reset our age timeout if someone attempts to play the source. - mAgeTimer.reset(); - - LLAudioData *adp = gAudiop->getAudioData(audio_uuid); - - bool has_buffer = gAudiop->updateBufferForData(adp, audio_uuid); - - - addAudioData(adp); - - if (!has_buffer) - { - // Don't bother trying to set up a channel or anything, we don't have an audio buffer. - return false; - } - - if (!setupChannel()) - { - return false; - } - - if (isSyncSlave()) - { - // A sync slave, it doesn't start playing until it's synced up with the master. - // Flag this channel as waiting for sync, and return true. - getChannel()->setWaiting(true); - return true; - } - - getChannel()->play(); - return true; -} - - -bool LLAudioSource::isDone() -{ - const F32 MAX_AGE = 60.f; - const F32 MAX_UNPLAYED_AGE = 15.f; - - if (isLoop()) - { - // Looped sources never die on their own. - return false; - } - - - if (hasPendingPreloads()) - { - return false; - } - - if (mQueuedDatap) - { - // Don't kill this sound if we've got something queued up to play. - return false; - } - - F32 elapsed = mAgeTimer.getElapsedTimeF32(); - - // This is a single-play source - if (!mChannelp) - { - if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce) - { - // We don't have a channel assigned, and it's been - // over 5 seconds since we tried to play it. Don't bother. - //llinfos << "No channel assigned, source is done" << llendl; - return true; - } - else - { - return false; - } - } - - if (mChannelp->isPlaying()) - { - if (elapsed > MAX_AGE) - { - // Arbitarily cut off non-looped sounds when they're old. - return true; - } - else - { - // Sound is still playing and we haven't timed out, don't kill it. - return false; - } - } - - if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce) - { - // The sound isn't playing back after 5 seconds or we're already done playing it, kill it. - return true; - } - - return false; -} - - -void LLAudioSource::addAudioData(LLAudioData *adp, const bool set_current) -{ - // Only handle a single piece of audio data associated with a source right now, - // until I implement prefetch. - if (set_current) - { - if (!mCurrentDatap) - { - mCurrentDatap = adp; - if (mChannelp) - { - mChannelp->updateBuffer(); - mChannelp->play(); - } - - // Make sure the audio engine knows that we want to request this sound. - gAudiop->startNextTransfer(); - return; - } - else if (mQueueSounds) - { - // If we have current data, and we're queuing, put - // the object onto the queue. - if (mQueuedDatap) - { - // We only queue one sound at a time, and it's a FIFO. - // Don't put it onto the queue. - return; - } - - if (adp == mCurrentDatap && isLoop()) - { - // No point in queueing the same sound if - // we're looping. - return; - } - mQueuedDatap = adp; - - // Make sure the audio engine knows that we want to request this sound. - gAudiop->startNextTransfer(); - } - else - { - if (mCurrentDatap != adp) - { - // Right now, if we're currently playing this sound in a channel, we - // update the buffer that the channel's associated with - // and play it. This may not be the correct behavior. - mCurrentDatap = adp; - if (mChannelp) - { - mChannelp->updateBuffer(); - mChannelp->play(); - } - // Make sure the audio engine knows that we want to request this sound. - gAudiop->startNextTransfer(); - } - } - } - else - { - // Add it to the preload list. - mPreloadMap[adp->getID()] = adp; - gAudiop->startNextTransfer(); - } -} - - -bool LLAudioSource::hasPendingPreloads() const -{ - // Check to see if we've got any preloads on deck for this source - data_map::const_iterator iter; - for (iter = mPreloadMap.begin(); iter != mPreloadMap.end(); iter++) - { - LLAudioData *adp = iter->second; - // note: a bad UUID will forever be !hasDecodedData() - // but also !hasValidData(), hence the check for hasValidData() - if (!adp->hasDecodedData() && adp->hasValidData()) - { - // This source is still waiting for a preload - return true; - } - } - - return false; -} - - -LLAudioData *LLAudioSource::getCurrentData() -{ - return mCurrentDatap; -} - -LLAudioData *LLAudioSource::getQueuedData() -{ - return mQueuedDatap; -} - -LLAudioBuffer *LLAudioSource::getCurrentBuffer() -{ - if (!mCurrentDatap) - { - return NULL; - } - - return mCurrentDatap->getBuffer(); -} - - - - -// -// LLAudioChannel implementation -// - - -LLAudioChannel::LLAudioChannel() : - mCurrentSourcep(NULL), - mCurrentBufferp(NULL), - mLoopedThisFrame(false), - mWaiting(false), - mSecondaryGain(1.0f) -{ -} - - -LLAudioChannel::~LLAudioChannel() -{ - // Need to disconnect any sources which are using this channel. - //LL_INFOS("AudioEngine") << "Cleaning up audio channel" << llendl; - if (mCurrentSourcep) - { - mCurrentSourcep->setChannel(NULL); - } - mCurrentBufferp = NULL; -} - - -void LLAudioChannel::setSource(LLAudioSource *sourcep) -{ - //LL_INFOS("AudioEngine") << this << ": setSource(" << sourcep << ")" << llendl; - - if (!sourcep) - { - // Clearing the source for this channel, don't need to do anything. - //LL_INFOS("AudioEngine") << "Clearing source for channel" << llendl; - cleanup(); - mCurrentSourcep = NULL; - mWaiting = false; - return; - } - - if (sourcep == mCurrentSourcep) - { - // Don't reallocate the channel, this will make FMOD goofy. - //LL_INFOS("AudioEngine") << "Calling setSource with same source!" << llendl; - } - - mCurrentSourcep = sourcep; - - - updateBuffer(); - update3DPosition(); -} - - -bool LLAudioChannel::updateBuffer() -{ - if (!mCurrentSourcep) - { - // This channel isn't associated with any source, nothing - // to be updated - return false; - } - - // Initialize the channel's gain setting for this sound. - if(gAudiop) - { - setSecondaryGain(gAudiop->getSecondaryGain(mCurrentSourcep->getType())); - } - - LLAudioBuffer *bufferp = mCurrentSourcep->getCurrentBuffer(); - if (bufferp == mCurrentBufferp) - { - if (bufferp) - { - // The source hasn't changed what buffer it's playing - bufferp->mLastUseTimer.reset(); - bufferp->mInUse = true; - } - return false; - } - - // - // The source changed what buffer it's playing. We need to clean up - // the existing channel - // - cleanup(); - - mCurrentBufferp = bufferp; - if (bufferp) - { - bufferp->mLastUseTimer.reset(); - bufferp->mInUse = true; - } - - if (!mCurrentBufferp) - { - // There's no new buffer to be played, so we just abort. - return false; - } - - return true; -} - - - - -// -// LLAudioData implementation -// - - -LLAudioData::LLAudioData(const LLUUID &uuid) : - mID(uuid), - mBufferp(NULL), - mHasLocalData(false), - mHasDecodedData(false), - mHasValidData(true) -{ - if (uuid.isNull()) - { - // This is a null sound. - return; - } - - if (gAudiop && gAudiop->hasDecodedFile(uuid)) - { - // Already have a decoded version, don't need to decode it. - mHasLocalData = true; - mHasDecodedData = true; - } - else if (gAssetStorage && gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND)) - { - mHasLocalData = true; - } -} - - -bool LLAudioData::load() -{ - static clock_t last_info = 0; - - // For now, just assume we're going to use one buffer per audiodata. - if (mBufferp) - { - // We already have this sound in a buffer, don't do anything. - llinfos << "Already have a buffer for this sound, don't bother loading!" << llendl; - return true; - } - - mBufferp = gAudiop->getFreeBuffer(); - if (!mBufferp) - { - // No free buffers, abort. - if (clock() - last_info > CLOCKS_PER_SEC) // Do not spam us with such messages - { - llinfos << "Not able to allocate a new audio buffer, aborting." << llendl; - last_info = clock(); - } - return false; - } - - std::string uuid_str; - std::string wav_path; - mID.toString(uuid_str); - wav_path= gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str) + ".dsf"; - - if (!mBufferp->loadWAV(wav_path)) - { - // Hrm. Right now, let's unset the buffer, since it's empty. - gAudiop->cleanupBuffer(mBufferp); - mBufferp = NULL; - - // Maybe it was removed by another instance. Send it to the preload queue. - gAudiop->preloadSound(mID); - - return false; - } - mBufferp->mAudioDatap = this; - return true; -} - - diff --git a/linden/indra/llaudio/audioengine.h b/linden/indra/llaudio/audioengine.h deleted file mode 100644 index e46091c..0000000 --- a/linden/indra/llaudio/audioengine.h +++ /dev/null @@ -1,466 +0,0 @@ -/** - * @file audioengine.h - * @brief Definition of LLAudioEngine base class abstracting the audio support - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - - -#ifndef LL_AUDIOENGINE_H -#define LL_AUDIOENGINE_H - -#include -#include - -#include "listener.h" -#include "v3math.h" -#include "v3dmath.h" -#include "listener.h" -#include "lltimer.h" -#include "lluuid.h" -#include "llframetimer.h" -#include "llassettype.h" - -#include "llmediabase.h" - -class LLMediaBase; - -const F32 LL_WIND_UPDATE_INTERVAL = 0.1f; -const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water -const F32 LL_WIND_UNDERWATER_CENTER_FREQ = 20.f; - -const F32 ATTACHED_OBJECT_TIMEOUT = 5.0f; -const F32 DEFAULT_MIN_DISTANCE = 2.0f; - -#define MAX_CHANNELS 30 -// Number of maximum rezzed objects with sounds + sounds without an object + UI sounds. -#define MAX_BUFFERS 100 - -// This define is intended to allow us to switch from os based wav -// file loading to vfs based wav file loading. The problem is that I -// am unconvinced that the LLWaveFile works for loading sounds from -// memory. So, until that is fixed up, changed, whatever, this remains -// undefined. -//#define USE_WAV_VFILE - -class LLVFS; - -class LLAudioSource; -class LLAudioData; -class LLAudioChannel; -class LLAudioChannelOpenAL; -class LLAudioBuffer; - - - -// -// LLAudioEngine definition -// - -class LLAudioEngine -{ - friend class LLAudioChannelOpenAL; // bleh. channel needs some listener methods. - -public: - enum LLAudioType - { - AUDIO_TYPE_NONE = 0, - AUDIO_TYPE_SFX = 1, - AUDIO_TYPE_UI = 2, - AUDIO_TYPE_AMBIENT = 3, - AUDIO_TYPE_GESTURE = 4, - AUDIO_TYPE_COUNT = 5 // last - }; - - LLAudioEngine(); - virtual ~LLAudioEngine(); - - // initialization/startup/shutdown - virtual bool init(const S32 num_channels, void *userdata); - virtual std::string getDriverName(bool verbose) = 0; - virtual void shutdown(); - - // Used by the mechanics of the engine - //virtual void processQueue(const LLUUID &sound_guid); - virtual void setListener(LLVector3 pos,LLVector3 vel,LLVector3 up,LLVector3 at); - virtual void updateWind(LLVector3 direction, F32 camera_height_above_water) = 0; - virtual void idle(F32 max_decode_time = 0.f); - virtual void updateChannels(); - - // - // "End user" functionality - // - virtual bool isWindEnabled(); - virtual void enableWind(bool state_b); - - // Use these for temporarily muting the audio system. - // Does not change buffers, initialization, etc. but - // stops playing new sounds. - virtual void setMuted(bool muted); - virtual bool getMuted() const { return mMuted; } - - F32 getMasterGain(); - void setMasterGain(F32 gain); - - F32 getSecondaryGain(S32 type); - void setSecondaryGain(S32 type, F32 gain); - - F32 getInternetStreamGain(); - - virtual void setDopplerFactor(F32 factor); - virtual F32 getDopplerFactor(); - virtual void setDistanceFactor(F32 factor); - virtual F32 getDistanceFactor(); - virtual void setRolloffFactor(F32 factor); - virtual F32 getRolloffFactor(); - virtual void setMaxWindGain(F32 gain); - - - // Methods actually related to setting up and removing sounds - // Owner ID is the owner of the object making the request - void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, - const S32 type = LLAudioEngine::AUDIO_TYPE_NONE, - const LLVector3d &pos_global = LLVector3d::zero); - bool preloadSound(const LLUUID &id); - - void addAudioSource(LLAudioSource *asp); - void cleanupAudioSource(LLAudioSource *asp); - - LLAudioSource *findAudioSource(const LLUUID &source_id); - LLAudioData *getAudioData(const LLUUID &audio_uuid); - - - // Internet stream methods - virtual void startInternetStream(const std::string& url); - virtual void stopInternetStream(); - virtual void pauseInternetStream(int pause); - virtual void updateInternetStream(); - virtual int isInternetStreamPlaying(); - virtual void getInternetStreamInfo(char* artist, char* title); - // use a value from 0.0 to 1.0, inclusive - virtual void setInternetStreamGain(F32 vol); - virtual const std::string& getInternetStreamURL(); - virtual LLMediaBase::EStatus getStatus(); - - // For debugging usage - virtual LLVector3 getListenerPos(); - - LLAudioBuffer *getFreeBuffer(); // Get a free buffer, or flush an existing one if you have to. - LLAudioChannel *getFreeChannel(const F32 priority); // Get a free channel or flush an existing one if your priority is higher - void cleanupBuffer(LLAudioBuffer *bufferp); - - bool hasDecodedFile(const LLUUID &uuid); - bool hasLocalFile(const LLUUID &uuid); - - bool updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid = LLUUID::null); - - - // Asset callback when we're retrieved a sound from the asset server. - void startNextTransfer(); - static void assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status); - - friend class LLPipeline; // For debugging - - LLMediaBase * getStreamMedia() { return mInternetStreamMedia; } -public: - F32 mMaxWindGain; // Hack. Public to set before fade in? - -protected: - virtual LLAudioBuffer *createBuffer() = 0; - virtual LLAudioChannel *createChannel() = 0; - - virtual void initWind() = 0; - virtual void cleanupWind() = 0; - virtual void setInternalGain(F32 gain) = 0; - - void commitDeferredChanges(); - - virtual void allocateListener() = 0; - - - // listener methods - virtual void setListenerPos(LLVector3 vec); - virtual void setListenerVelocity(LLVector3 vec); - virtual void orientListener(LLVector3 up, LLVector3 at); - virtual void translateListener(LLVector3 vec); - - - F64 mapWindVecToGain(LLVector3 wind_vec); - F64 mapWindVecToPitch(LLVector3 wind_vec); - F64 mapWindVecToPan(LLVector3 wind_vec); - -protected: - LLListener *mListenerp; - - bool mMuted; - void* mUserData; - - S32 mLastStatus; - - S32 mNumChannels; - bool mEnableWind; - - LLUUID mCurrentTransfer; // Audio file currently being transferred by the system - LLFrameTimer mCurrentTransferTimer; - - // A list of all audio sources that are known to the viewer at this time. - // This is most likely a superset of the ones that we actually have audio - // data for, or are playing back. - typedef std::map source_map; - typedef std::map data_map; - - source_map mAllSources; - data_map mAllData; - - LLAudioChannel *mChannels[MAX_CHANNELS]; - - // Buffers needs to change into a different data structure, as the number of buffers - // that we have active should be limited by RAM usage, not count. - LLAudioBuffer *mBuffers[MAX_BUFFERS]; - - F32 mMasterGain; - F32 mSecondaryGain[AUDIO_TYPE_COUNT]; - - // Hack! Internet streams are treated differently from other sources! - F32 mInternetStreamGain; - std::string mInternetStreamURL; - - F32 mNextWindUpdate; - - LLFrameTimer mWindUpdateTimer; - - LLMediaBase::EStatus mStatus; - -private: - void setDefaults(); - LLMediaBase *mInternetStreamMedia; -}; - - - - -// -// Standard audio source. Can be derived from for special sources, such as those attached to objects. -// - - -class LLAudioSource -{ -public: - // owner_id is the id of the agent responsible for making this sound - // play, for example, the owner of the object currently playing it - LLAudioSource(const LLUUID &id, const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE); - virtual ~LLAudioSource(); - - virtual void update(); // Update this audio source - void updatePriority(); - - void preload(const LLUUID &audio_id); // Only used for preloading UI sounds, now. - - void addAudioData(LLAudioData *adp, bool set_current = TRUE); - - void setAmbient(const bool ambient) { mAmbient = ambient; } - bool isAmbient() const { return mAmbient; } - - void setLoop(const bool loop) { mLoop = loop; } - bool isLoop() const { return mLoop; } - - void setSyncMaster(const bool master) { mSyncMaster = master; } - bool isSyncMaster() const { return mSyncMaster; } - - void setSyncSlave(const bool slave) { mSyncSlave = slave; } - bool isSyncSlave() const { return mSyncSlave; } - - void setQueueSounds(const bool queue) { mQueueSounds = queue; } - bool isQueueSounds() const { return mQueueSounds; } - - void setPlayedOnce(const bool played_once) { mPlayedOnce = played_once; } - - void setType(S32 type) { mType = type; } - S32 getType() { return mType; } - - void setPositionGlobal(const LLVector3d &position_global) { mPositionGlobal = position_global; } - LLVector3d getPositionGlobal() const { return mPositionGlobal; } - LLVector3 getVelocity() const { return mVelocity; } - F32 getPriority() const { return mPriority; } - - // Gain should always be clamped between 0 and 1. - F32 getGain() const { return mGain; } - virtual void setGain(const F32 gain) { mGain = llclamp(gain, 0.f, 1.f); } - - const LLUUID &getID() const { return mID; } - bool isDone(); - - LLAudioData *getCurrentData(); - LLAudioData *getQueuedData(); - LLAudioBuffer *getCurrentBuffer(); - - bool setupChannel(); - bool play(const LLUUID &audio_id); // Start the audio source playing - - bool hasPendingPreloads() const; // Has preloads that haven't been done yet - - friend class LLAudioEngine; - friend class LLAudioChannel; -protected: - void setChannel(LLAudioChannel *channelp); - LLAudioChannel *getChannel() const { return mChannelp; } - -protected: - LLUUID mID; // The ID of the source is that of the object if it's attached to an object. - LLUUID mOwnerID; // owner of the object playing the sound - F32 mPriority; - F32 mGain; - bool mAmbient; - bool mLoop; - bool mSyncMaster; - bool mSyncSlave; - bool mQueueSounds; - bool mPlayedOnce; - S32 mType; - LLVector3d mPositionGlobal; - LLVector3 mVelocity; - - //LLAudioSource *mSyncMasterp; // If we're a slave, the source that we're synced to. - LLAudioChannel *mChannelp; // If we're currently playing back, this is the channel that we're assigned to. - LLAudioData *mCurrentDatap; - LLAudioData *mQueuedDatap; - - typedef std::map data_map; - data_map mPreloadMap; - - LLFrameTimer mAgeTimer; -}; - - - - -// -// Generic metadata about a particular piece of audio data. -// The actual data is handled by the derived LLAudioBuffer classes which are -// derived for each audio engine. -// - - -class LLAudioData -{ -public: - LLAudioData(const LLUUID &uuid); - bool load(); - - LLUUID getID() const { return mID; } - LLAudioBuffer *getBuffer() const { return mBufferp; } - - bool hasLocalData() const { return mHasLocalData; } - bool hasDecodedData() const { return mHasDecodedData; } - bool hasValidData() const { return mHasValidData; } - - void setHasLocalData(const bool hld) { mHasLocalData = hld; } - void setHasDecodedData(const bool hdd) { mHasDecodedData = hdd; } - void setHasValidData(const bool hvd) { mHasValidData = hvd; } - - friend class LLAudioEngine; // Severe laziness, bad. - -protected: - LLUUID mID; - LLAudioBuffer *mBufferp; // If this data is being used by the audio system, a pointer to the buffer will be set here. - bool mHasLocalData; - bool mHasDecodedData; - bool mHasValidData; -}; - - -// -// Base class for an audio channel, i.e. a channel which is capable of playing back a sound. -// Management of channels is done generically, methods for actually manipulating the channel -// are derived for each audio engine. -// - - -class LLAudioChannel -{ -public: - LLAudioChannel(); - virtual ~LLAudioChannel(); - - virtual void setSource(LLAudioSource *sourcep); - LLAudioSource *getSource() const { return mCurrentSourcep; } - - void setSecondaryGain(F32 gain) { mSecondaryGain = gain; } - F32 getSecondaryGain() { return mSecondaryGain; } - - friend class LLAudioEngine; - friend class LLAudioSource; -protected: - virtual void play() = 0; - virtual void playSynced(LLAudioChannel *channelp) = 0; - virtual void cleanup() = 0; - virtual bool isPlaying() = 0; - void setWaiting(const bool waiting) { mWaiting = waiting; } - bool isWaiting() const { return mWaiting; } - - virtual bool updateBuffer(); // Check to see if the buffer associated with the source changed, and update if necessary. - virtual void update3DPosition() = 0; - virtual void updateLoop() = 0; // Update your loop/completion status, for use by queueing/syncing. -protected: - LLAudioSource *mCurrentSourcep; - LLAudioBuffer *mCurrentBufferp; - bool mLoopedThisFrame; - bool mWaiting; // Waiting for sync. - F32 mSecondaryGain; -}; - - - - -// Basically an interface class to the engine-specific implementation -// of audio data that's ready for playback. -// Will likely get more complex as we decide to do stuff like real streaming audio. - - -class LLAudioBuffer -{ -public: - virtual ~LLAudioBuffer() {}; - virtual bool loadWAV(const std::string& filename) = 0; - virtual U32 getLength() = 0; - - friend class LLAudioEngine; - friend class LLAudioChannel; - friend class LLAudioData; -protected: - bool mInUse; - LLAudioData *mAudioDatap; - LLFrameTimer mLastUseTimer; -}; - - - -extern LLAudioEngine* gAudiop; - -#endif diff --git a/linden/indra/llaudio/audioengine_fmod.cpp b/linden/indra/llaudio/audioengine_fmod.cpp deleted file mode 100644 index 938c2aa..0000000 --- a/linden/indra/llaudio/audioengine_fmod.cpp +++ /dev/null @@ -1,1093 +0,0 @@ -/** - * @file audioengine_fmod.cpp - * @brief Implementation of LLAudioEngine class abstracting the audio support as a FMOD 3D implementation - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "audioengine_fmod.h" -#include "listener_fmod.h" - -#include "llerror.h" -#include "llmath.h" -#include "llrand.h" - -#include "fmod.h" -#include "fmod_errors.h" -#include "lldir.h" -#include "llapr.h" - -#include "sound_ids.h" - -extern "C" { - void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata); -} - -FSOUND_DSPUNIT *gWindDSP = NULL; - - -// Safe strcpy -#if 0 //(unused) //LL_WINDOWS || LL_LINUX -static size_t strlcpy( char* dest, const char* src, size_t dst_size ) -{ - size_t source_len = 0; - size_t min_len = 0; - if( dst_size > 0 ) - { - if( src ) - { - source_len = strlen(src); /*Flawfinder: ignore*/ - min_len = llmin( dst_size - 1, source_len ); - memcpy(dest, src, min_len); /*Flawfinder: ignore*/ - } - dest[min_len] = '\0'; - } - return source_len; -} -#else -// apple ships with the non-standard strlcpy in /usr/include/string.h: -// size_t strlcpy(char *, const char *, size_t); -#endif - - -LLAudioEngine_FMOD::LLAudioEngine_FMOD() -{ - mInited = false; - mCurrentInternetStreamp = NULL; - mInternetStreamChannel = -1; - mWindGen = NULL; -} - - -LLAudioEngine_FMOD::~LLAudioEngine_FMOD() -{ -} - - -bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) -{ - mFadeIn = -10000; - - LLAudioEngine::init(num_channels, userdata); - - // Reserve one extra channel for the http stream. - if (!FSOUND_SetMinHardwareChannels(num_channels + 1)) - { - LL_WARNS("AppInit") << "FMOD::init[0](), error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - } - - LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() initializing FMOD" << LL_ENDL; - - F32 version = FSOUND_GetVersion(); - if (version < FMOD_VERSION) - { - LL_WARNS("AppInit") << "Error : You are using the wrong FMOD version (" << version - << ")! You should be using FMOD " << FMOD_VERSION << LL_ENDL; - //return false; - } - - U32 fmod_flags = 0x0; - -#if LL_WINDOWS - // Windows needs to know which window is frontmost. - // This must be called before FSOUND_Init() per the FMOD docs. - // This could be used to let FMOD handle muting when we lose focus, - // but we don't actually want to do that because we want to distinguish - // between minimized and not-focused states. - if (!FSOUND_SetHWND(userdata)) - { - LL_WARNS("AppInit") << "Error setting FMOD window: " - << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - return false; - } - // Play audio when we don't have focus. - // (For example, IM client on top of us.) - // This means we also try to play audio when minimized, - // so we manually handle muting in that case. JC - fmod_flags |= FSOUND_INIT_GLOBALFOCUS; -#endif - -#if LL_LINUX - // initialize the FMOD engine - - // This is a hack to use only FMOD's basic FPU mixer - // when the LL_VALGRIND environmental variable is set, - // otherwise valgrind will fall over on FMOD's MMX detection - if (getenv("LL_VALGRIND")) /*Flawfinder: ignore*/ - { - LL_INFOS("AppInit") << "Pacifying valgrind in FMOD init." << LL_ENDL; - FSOUND_SetMixer(FSOUND_MIXER_QUALITY_FPU); - } - - // If we don't set an output method, Linux FMOD always - // decides on OSS and fails otherwise. So we'll manually - // try ESD, then OSS, then ALSA. - // Why this order? See SL-13250, but in short, OSS emulated - // on top of ALSA is ironically more reliable than raw ALSA. - // Ack, and ESD has more reliable failure modes - but has worse - // latency - than all of them, so wins for now. - bool audio_ok = false; - - if (!audio_ok) - if (NULL == getenv("LL_BAD_FMOD_ESD")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying ESD audio output..." << LL_ENDL; - if(FSOUND_SetOutput(FSOUND_OUTPUT_ESD) && - FSOUND_Init(44100, num_channels, fmod_flags)) - { - LL_DEBUGS("AppInit") << "ESD audio output initialized OKAY" - << LL_ENDL; - audio_ok = true; - } else { - LL_WARNS("AppInit") << "ESD audio output FAILED to initialize: " - << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - } - } else { - LL_DEBUGS("AppInit") << "ESD audio output SKIPPED" << LL_ENDL; - } - - if (!audio_ok) - if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL; - if(FSOUND_SetOutput(FSOUND_OUTPUT_OSS) && - FSOUND_Init(44100, num_channels, fmod_flags)) - { - LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL; - audio_ok = true; - } else { - LL_WARNS("AppInit") << "OSS audio output FAILED to initialize: " - << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - } - } else { - LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; - } - - if (!audio_ok) - if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; - if(FSOUND_SetOutput(FSOUND_OUTPUT_ALSA) && - FSOUND_Init(44100, num_channels, fmod_flags)) - { - LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; - audio_ok = true; - } else { - LL_WARNS("AppInit") << "ALSA audio output FAILED to initialize: " - << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - } - } else { - LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; - } - - if (!audio_ok) - { - LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; - return false; - } - - // On Linux, FMOD causes a SIGPIPE for some netstream error - // conditions (an FMOD bug); ignore SIGPIPE so it doesn't crash us. - // NOW FIXED in FMOD 3.x since 2006-10-01. - //signal(SIGPIPE, SIG_IGN); - - // We're interested in logging which output method we - // ended up with, for QA purposes. - switch (FSOUND_GetOutput()) - { - case FSOUND_OUTPUT_NOSOUND: LL_DEBUGS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; - case FSOUND_OUTPUT_OSS: LL_DEBUGS("AppInit") << "Audio output: OSS" << LL_ENDL; break; - case FSOUND_OUTPUT_ESD: LL_DEBUGS("AppInit") << "Audio output: ESD" << LL_ENDL; break; - case FSOUND_OUTPUT_ALSA: LL_DEBUGS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; - default: LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; - }; - -#else // LL_LINUX - - // initialize the FMOD engine - if (!FSOUND_Init(44100, num_channels, fmod_flags)) - { - LL_WARNS("AppInit") << "Error initializing FMOD: " - << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - return false; - } - -#endif - - initInternetStream(); - - LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL; - - mInited = true; - - return true; -} - - -std::string LLAudioEngine_FMOD::getDriverName(bool verbose) -{ - if (verbose) - { - F32 version = FSOUND_GetVersion(); - return llformat("FMOD version %f", version); - } - else - { - return "FMOD"; - } -} - - -void LLAudioEngine_FMOD::allocateListener(void) -{ - mListenerp = (LLListener *) new LLListener_FMOD(); - if (!mListenerp) - { - llwarns << "Listener creation failed" << llendl; - } -} - - -void LLAudioEngine_FMOD::shutdown() -{ - if (gWindDSP) - { - FSOUND_DSP_SetActive(gWindDSP,false); - FSOUND_DSP_Free(gWindDSP); - } - - stopInternetStream(); - - LLAudioEngine::shutdown(); - - llinfos << "LLAudioEngine_FMOD::shutdown() closing FMOD" << llendl; - FSOUND_Close(); - llinfos << "LLAudioEngine_FMOD::shutdown() done closing FMOD" << llendl; - - delete mListenerp; - mListenerp = NULL; -} - - -LLAudioBuffer *LLAudioEngine_FMOD::createBuffer() -{ - return new LLAudioBufferFMOD(); -} - - -LLAudioChannel *LLAudioEngine_FMOD::createChannel() -{ - return new LLAudioChannelFMOD(); -} - - -void LLAudioEngine_FMOD::initWind() -{ - mWindGen = new LLWindGen; - - if (!gWindDSP) - { - gWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen); - } - if (gWindDSP) - { - FSOUND_DSP_SetActive(gWindDSP, true); - } - mNextWindUpdate = 0.0; -} - - -void LLAudioEngine_FMOD::cleanupWind() -{ - if (gWindDSP) - { - FSOUND_DSP_SetActive(gWindDSP, false); - FSOUND_DSP_Free(gWindDSP); - gWindDSP = NULL; - } - - delete mWindGen; - mWindGen = NULL; -} - - -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::updateWind(LLVector3 wind_vec, F32 camera_height_above_water) -{ - LLVector3 wind_pos; - F64 pitch; - F64 center_freq; - - if (!mEnableWind) - { - return; - } - - if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) - { - - // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) - // need to convert this to the conventional orientation DS3D and OpenAL use - // where +X = right, +Y = up, +Z = backwards - - wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); - - // cerr << "Wind update" << endl; - - pitch = 1.0 + mapWindVecToPitch(wind_vec); - center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); - - mWindGen->mTargetFreq = (F32)center_freq; - mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; - mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); - } -} - -/* -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::setSourceMinDistance(U16 source_num, F64 distance) -{ - if (!mInited) - { - return; - } - if (mBuffer[source_num]) - { - mMinDistance[source_num] = (F32) distance; - if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num])) - { - llwarns << "FMOD::setSourceMinDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - } -} - -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::setSourceMaxDistance(U16 source_num, F64 distance) -{ - if (!mInited) - { - return; - } - if (mBuffer[source_num]) - { - mMaxDistance[source_num] = (F32) distance; - if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num])) - { - llwarns << "FMOD::setSourceMaxDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - } -} - -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::get3DParams(S32 source_num, S32 *volume, S32 *freq, S32 *inside, S32 *outside, LLVector3 *orient, S32 *out_volume, F32 *min_dist, F32 *max_dist) -{ - *volume = 0; - *freq = 0; - *inside = 0; - *outside = 0; - *orient = LLVector3::zero; - *out_volume = 0; - *min_dist = 0.f; - *max_dist = 0.f; -} - -*/ - - -//----------------------------------------------------------------------- -void LLAudioEngine_FMOD::setInternalGain(F32 gain) -{ - if (!mInited) - { - return; - } - - gain = llclamp( gain, 0.0f, 1.0f ); - FSOUND_SetSFXMasterVolume( llround( 255.0f * gain ) ); - - if ( mInternetStreamChannel != -1 ) - { - F32 clamp_internet_stream_gain = llclamp( mInternetStreamGain, 0.0f, 1.0f ); - FSOUND_SetVolumeAbsolute( mInternetStreamChannel, llround( 255.0f * clamp_internet_stream_gain ) ); - } -} - -// -// LLAudioChannelFMOD implementation -// - -LLAudioChannelFMOD::LLAudioChannelFMOD() : LLAudioChannel(), mChannelID(0), mLastSamplePos(0) -{ -} - - -LLAudioChannelFMOD::~LLAudioChannelFMOD() -{ - cleanup(); -} - - -bool LLAudioChannelFMOD::updateBuffer() -{ - if (LLAudioChannel::updateBuffer()) - { - // Base class update returned true, which means that we need to actually - // set up the channel for a different buffer. - - LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentSourcep->getCurrentBuffer(); - - // Grab the FMOD sample associated with the buffer - FSOUND_SAMPLE *samplep = bufferp->getSample(); - if (!samplep) - { - // This is bad, there should ALWAYS be a sample associated with a legit - // buffer. - llerrs << "No FMOD sample!" << llendl; - return false; - } - - - // Actually play the sound. Start it off paused so we can do all the necessary - // setup. - mChannelID = FSOUND_PlaySoundEx(FSOUND_FREE, samplep, FSOUND_DSP_GetSFXUnit(), true); - - //llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl; - } - - // If we have a source for the channel, we need to update its gain. - if (mCurrentSourcep) - { - // SJB: warnings can spam and hurt framerate, disabling - if (!FSOUND_SetVolume(mChannelID, llround(getSecondaryGain() * mCurrentSourcep->getGain() * 255.0f))) - { -// llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - - if (!FSOUND_SetLoopMode(mChannelID, mCurrentSourcep->isLoop() ? FSOUND_LOOP_NORMAL : FSOUND_LOOP_OFF)) - { -// llwarns << "Channel " << mChannelID << "Source ID: " << mCurrentSourcep->getID() -// << " at " << mCurrentSourcep->getPositionGlobal() << llendl; -// llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - } - - return true; -} - - -void LLAudioChannelFMOD::update3DPosition() -{ - if (!mChannelID) - { - // We're not actually a live channel (i.e., we're not playing back anything) - return; - } - - LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentBufferp; - if (!bufferp) - { - // We don't have a buffer associated with us (should really have been picked up - // by the above if. - return; - } - - if (mCurrentSourcep->isAmbient()) - { - // Ambient sound, don't need to do any positional updates. - bufferp->set3DMode(false); - } - else - { - // Localized sound. Update the position and velocity of the sound. - bufferp->set3DMode(true); - - LLVector3 float_pos; - float_pos.setVec(mCurrentSourcep->getPositionGlobal()); - if (!FSOUND_3D_SetAttributes(mChannelID, float_pos.mV, mCurrentSourcep->getVelocity().mV)) - { - LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::update3DPosition error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; - } - } -} - - -void LLAudioChannelFMOD::updateLoop() -{ - if (!mChannelID) - { - // May want to clear up the loop/sample counters. - return; - } - - // - // Hack: We keep track of whether we looped or not by seeing when the - // sample position looks like it's going backwards. Not reliable; may - // yield false negatives. - // - U32 cur_pos = FSOUND_GetCurrentPosition(mChannelID); - if (cur_pos < (U32)mLastSamplePos) - { - mLoopedThisFrame = true; - } - mLastSamplePos = cur_pos; -} - - -void LLAudioChannelFMOD::cleanup() -{ - if (!mChannelID) - { - //llinfos << "Aborting cleanup with no channelID." << llendl; - return; - } - - //llinfos << "Cleaning up channel: " << mChannelID << llendl; - if (!FSOUND_StopSound(mChannelID)) - { - LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::cleanup error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - - mCurrentBufferp = NULL; - mChannelID = 0; -} - - -void LLAudioChannelFMOD::play() -{ - if (!mChannelID) - { - llwarns << "Playing without a channelID, aborting" << llendl; - return; - } - - if (!FSOUND_SetPaused(mChannelID, false)) - { - llwarns << "LLAudioChannelFMOD::play error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - getSource()->setPlayedOnce(true); -} - - -void LLAudioChannelFMOD::playSynced(LLAudioChannel *channelp) -{ - LLAudioChannelFMOD *fmod_channelp = (LLAudioChannelFMOD*)channelp; - if (!(fmod_channelp->mChannelID && mChannelID)) - { - // Don't have channels allocated to both the master and the slave - return; - } - - U32 position = FSOUND_GetCurrentPosition(fmod_channelp->mChannelID) % mCurrentBufferp->getLength(); - // Try to match the position of our sync master - if (!FSOUND_SetCurrentPosition(mChannelID, position)) - { - llwarns << "LLAudioChannelFMOD::playSynced unable to set current position" << llendl; - } - - // Start us playing - play(); -} - - -bool LLAudioChannelFMOD::isPlaying() -{ - if (!mChannelID) - { - return false; - } - - return FSOUND_IsPlaying(mChannelID) && (!FSOUND_GetPaused(mChannelID)); -} - - - -// -// LLAudioBufferFMOD implementation -// - - -LLAudioBufferFMOD::LLAudioBufferFMOD() -{ - mSamplep = NULL; -} - - -LLAudioBufferFMOD::~LLAudioBufferFMOD() -{ - if (mSamplep) - { - // Clean up the associated FMOD sample if it exists. - FSOUND_Sample_Free(mSamplep); - mSamplep = NULL; - } -} - - -bool LLAudioBufferFMOD::loadWAV(const std::string& filename) -{ - // Try to open a wav file from disk. This will eventually go away, as we don't - // really want to block doing this. - if (filename.empty()) - { - // invalid filename, abort. - return false; - } - - if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB)) - { - // File not found, abort. - return false; - } - - if (mSamplep) - { - // If there's already something loaded in this buffer, clean it up. - FSOUND_Sample_Free(mSamplep); - mSamplep = NULL; - } - - // Load up the wav file into an fmod sample -#if LL_WINDOWS - // MikeS. - Loading the sound file manually and then handing it over to FMOD, - // since FMOD uses posix IO internally, - // which doesn't work with unicode file paths. - LLFILE* sound_file = LLFile::fopen(filename,"rb"); /* Flawfinder: ignore */ - if (sound_file) - { - fseek(sound_file,0,SEEK_END); - U32 file_length = ftell(sound_file); //Find the length of the file by seeking to the end and getting the offset - size_t read_count; - fseek(sound_file,0,SEEK_SET); //Seek back to the beginning - char* buffer = new char[file_length]; - llassert(buffer); - read_count = fread((void*)buffer,file_length,1,sound_file);//Load it.. - if(ferror(sound_file)==0 && (read_count == 1)){//No read error, and we got 1 chunk of our size... - unsigned int mode_flags = FSOUND_LOOP_NORMAL | FSOUND_LOADMEMORY; - //FSOUND_16BITS | FSOUND_MONO | FSOUND_LOADMEMORY | FSOUND_LOOP_NORMAL; - mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, buffer, mode_flags , 0, file_length); - } - delete[] buffer; - fclose(sound_file); - } -#else - mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, filename.c_str(), FSOUND_LOOP_NORMAL, 0, 0); -#endif - - if (!mSamplep) - { - // We failed to load the file for some reason. - llwarns << "Could not load data '" << filename << "': " - << FMOD_ErrorString(FSOUND_GetError()) << llendl; - - // - // If we EVER want to load wav files provided by end users, we need - // to rethink this! - // - // file is probably corrupt - remove it. - LLFile::remove(filename); - return false; - } - - // Everything went well, return true - return true; -} - - -U32 LLAudioBufferFMOD::getLength() -{ - if (!mSamplep) - { - return 0; - } - - return FSOUND_Sample_GetLength(mSamplep); -} - - -void LLAudioBufferFMOD::set3DMode(bool use3d) -{ - U16 current_mode = FSOUND_Sample_GetMode(mSamplep); - - if (use3d) - { - if (!FSOUND_Sample_SetMode(mSamplep, (current_mode & (~FSOUND_2D)))) - { - llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - } - else - { - if (!FSOUND_Sample_SetMode(mSamplep, current_mode | FSOUND_2D)) - { - llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; - } - } -} - - - -//--------------------------------------------------------------------------- -// Internet Streaming -//--------------------------------------------------------------------------- -void LLAudioEngine_FMOD::initInternetStream() -{ - // Number of milliseconds of audio to buffer for the audio card. - // Must be larger than the usual Second Life frame stutter time. - FSOUND_Stream_SetBufferSize(200); - - // Here's where we set the size of the network buffer and some buffering - // parameters. In this case we want a network buffer of 16k, we want it - // to prebuffer 40% of that when we first connect, and we want it - // to rebuffer 80% of that whenever we encounter a buffer underrun. - - // Leave the net buffer properties at the default. - //FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80); - mInternetStreamURL.clear(); -} - - -void LLAudioEngine_FMOD::startInternetStream(const std::string& url) -{ - if (!mInited) - { - llwarns << "startInternetStream before audio initialized" << llendl; - return; - } - - // "stop" stream but don't clear url, etc. in calse url == mInternetStreamURL - stopInternetStream(); - if (!url.empty()) - { - llinfos << "Starting internet stream: " << url << llendl; - mCurrentInternetStreamp = new LLAudioStreamFMOD(url); - mInternetStreamURL = url; - } - else - { - llinfos << "Set internet stream to null" << llendl; - mInternetStreamURL.clear(); - } -} - - -signed char F_CALLBACKAPI LLAudioEngine_FMOD::callbackMetaData(char *name, char *value, void *userdata) -{ - /* - LLAudioEngine_FMOD* self = (LLAudioEngine_FMOD*)userdata; - - if (!strcmp("ARTIST", name)) - { - strlcpy(self->mInternetStreamArtist, value, 256); - self->mInternetStreamNewMetaData = true; - return true; - } - - if (!strcmp("TITLE", name)) - { - strlcpy(self->mInternetStreamTitle, value, 256); - self->mInternetStreamNewMetaData = true; - return true; - } - */ - - return true; -} - - -void LLAudioEngine_FMOD::updateInternetStream() -{ - // Kill dead internet streams, if possible - std::list::iterator iter; - for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();) - { - LLAudioStreamFMOD *streamp = *iter; - if (streamp->stopStream()) - { - llinfos << "Closed dead stream" << llendl; - delete streamp; - mDeadStreams.erase(iter++); - } - else - { - iter++; - } - } - - // Don't do anything if there are no streams playing - if (!mCurrentInternetStreamp) - { - return; - } - - int open_state = mCurrentInternetStreamp->getOpenState(); - - if (!open_state) - { - // Stream is live - - - // start the stream if it's ready - if (mInternetStreamChannel < 0) - { - mInternetStreamChannel = mCurrentInternetStreamp->startStream(); - - if (mInternetStreamChannel != -1) - { - // Reset volume to previously set volume - setInternetStreamGain(mInternetStreamGain); - FSOUND_SetPaused(mInternetStreamChannel, false); - //FSOUND_Stream_Net_SetMetadataCallback(mInternetStream, callbackMetaData, this); - } - } - } - - switch(open_state) - { - default: - case 0: - // success - break; - case -1: - // stream handle is invalid - llwarns << "InternetStream - invalid handle" << llendl; - stopInternetStream(); - return; - case -2: - // opening - //strlcpy(mInternetStreamArtist, "Opening", 256); - break; - case -3: - // failed to open, file not found, perhaps - llwarns << "InternetSteam - failed to open" << llendl; - stopInternetStream(); - return; - case -4: - // connecting - //strlcpy(mInternetStreamArtist, "Connecting", 256); - break; - case -5: - // buffering - //strlcpy(mInternetStreamArtist, "Buffering", 256); - break; - } - -} - -void LLAudioEngine_FMOD::stopInternetStream() -{ - if (mInternetStreamChannel != -1) - { - FSOUND_SetPaused(mInternetStreamChannel, true); - FSOUND_SetPriority(mInternetStreamChannel, 0); - mInternetStreamChannel = -1; - } - - if (mCurrentInternetStreamp) - { - llinfos << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << llendl; - if (mCurrentInternetStreamp->stopStream()) - { - delete mCurrentInternetStreamp; - } - else - { - llwarns << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << llendl; - mDeadStreams.push_back(mCurrentInternetStreamp); - } - mCurrentInternetStreamp = NULL; - //mInternetStreamURL.clear(); - } -} - -void LLAudioEngine_FMOD::pauseInternetStream(int pause) -{ - if (pause < 0) - { - pause = mCurrentInternetStreamp ? 1 : 0; - } - - if (pause) - { - if (mCurrentInternetStreamp) - { - stopInternetStream(); - } - } - else - { - startInternetStream(mInternetStreamURL); - } -} - - -// A stream is "playing" if it has been requested to start. That -// doesn't necessarily mean audio is coming out of the speakers. -int LLAudioEngine_FMOD::isInternetStreamPlaying() -{ - if (mCurrentInternetStreamp) - { - return 1; // Active and playing - } - else if (!mInternetStreamURL.empty()) - { - return 2; // "Paused" - } - else - { - return 0; - } -} - - -void LLAudioEngine_FMOD::setInternetStreamGain(F32 vol) -{ - mInternetStreamGain = vol; - - if (mInternetStreamChannel != -1) - { - vol = llclamp(vol, 0.f, 1.f); - int vol_int = llround(vol * 255.f); - FSOUND_SetVolumeAbsolute(mInternetStreamChannel, vol_int); - } -} - - -LLAudioStreamFMOD::LLAudioStreamFMOD(const std::string& url) : - mInternetStream(NULL), - mReady(false) -{ - mInternetStreamURL = url; - mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0); - if (!mInternetStream) - { - llwarns << "Couldn't open fmod stream, error " - << FMOD_ErrorString(FSOUND_GetError()) - << llendl; - mReady = false; - return; - } - - mReady = true; -} - -int LLAudioStreamFMOD::startStream() -{ - // We need a live and opened stream before we try and play it. - if (!mInternetStream || getOpenState()) - { - llwarns << "No internet stream to start playing!" << llendl; - return -1; - } - - // Make sure the stream is set to 2D mode. - FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D); - - return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, true); -} - -bool LLAudioStreamFMOD::stopStream() -{ - if (mInternetStream) - { - int read_percent = 0; - int status = 0; - int bitrate = 0; - unsigned int flags = 0x0; - FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags); - - bool close = true; - switch (status) - { - case FSOUND_STREAM_NET_CONNECTING: - close = false; - break; - case FSOUND_STREAM_NET_NOTCONNECTED: - case FSOUND_STREAM_NET_BUFFERING: - case FSOUND_STREAM_NET_READY: - case FSOUND_STREAM_NET_ERROR: - default: - close = true; - } - - if (close) - { - FSOUND_Stream_Close(mInternetStream); - mInternetStream = NULL; - return true; - } - else - { - return false; - } - } - else - { - return true; - } -} - -int LLAudioStreamFMOD::getOpenState() -{ - int open_state = FSOUND_Stream_GetOpenState(mInternetStream); - return open_state; -} - -void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata) -{ - // originalbuffer = fmod's original mixbuffer. - // newbuffer = the buffer passed from the previous DSP unit. - // length = length in samples at this mix time. - // param = user parameter passed through in FSOUND_DSP_Create. - // - // modify the buffer in some fashion - - LLWindGen *windgen = - (LLWindGen *)userdata; - U8 stride; - -#if LL_DARWIN - stride = sizeof(LLAudioEngine_FMOD::MIXBUFFERFORMAT); -#else - int mixertype = FSOUND_GetMixer(); - if (mixertype == FSOUND_MIXER_BLENDMODE || - mixertype == FSOUND_MIXER_QUALITY_FPU) - { - stride = 4; - } - else - { - stride = 2; - } -#endif - - newbuffer = windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT *)newbuffer, length, stride); - - return newbuffer; -} diff --git a/linden/indra/llaudio/audioengine_fmod.h b/linden/indra/llaudio/audioengine_fmod.h deleted file mode 100644 index d0d2e1b..0000000 --- a/linden/indra/llaudio/audioengine_fmod.h +++ /dev/null @@ -1,161 +0,0 @@ -/** - * @file audioengine_fmod.h - * @brief Definition of LLAudioEngine class abstracting the audio - * support as a FMOD 3D implementation - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_AUDIOENGINE_FMOD_H -#define LL_AUDIOENGINE_FMOD_H - -#include "audioengine.h" -#include "listener_fmod.h" -#include "windgen.h" - -#include "fmod.h" - -class LLAudioStreamFMOD; - -class LLAudioEngine_FMOD : public LLAudioEngine -{ -public: - LLAudioEngine_FMOD(); - virtual ~LLAudioEngine_FMOD(); - - // initialization/startup/shutdown - virtual bool init(const S32 num_channels, void *user_data); - virtual std::string getDriverName(bool verbose); - virtual void allocateListener(); - - virtual void shutdown(); - - // Internet stream methods - virtual void initInternetStream(); - virtual void startInternetStream(const std::string& url); - virtual void updateInternetStream(); - virtual void stopInternetStream(); - virtual void pauseInternetStream(int pause); - virtual int isInternetStreamPlaying(); - virtual void setInternetStreamGain(F32 vol); - - /*virtual*/ void initWind(); - /*virtual*/ void cleanupWind(); - - /*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water); - -#if LL_DARWIN - typedef S32 MIXBUFFERFORMAT; -#else - typedef S16 MIXBUFFERFORMAT; -#endif - -protected: - /*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to. - /*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel. - - /*virtual*/ void setInternalGain(F32 gain); -protected: - static signed char F_CALLBACKAPI callbackMetaData(char* name, char* value, void* userdata); - - LLAudioStreamFMOD *mCurrentInternetStreamp; - int mInternetStreamChannel; - - std::list mDeadStreams; - - //F32 mMinDistance[MAX_BUFFERS]; - //F32 mMaxDistance[MAX_BUFFERS]; - - S32 mFadeIn; - bool mInited; - - // On Windows, userdata is the HWND of the application window. - void* mUserData; - - LLWindGen *mWindGen; -}; - - -class LLAudioChannelFMOD : public LLAudioChannel -{ -public: - LLAudioChannelFMOD(); - virtual ~LLAudioChannelFMOD(); - -protected: - /*virtual*/ void play(); - /*virtual*/ void playSynced(LLAudioChannel *channelp); - /*virtual*/ void cleanup(); - /*virtual*/ bool isPlaying(); - - /*virtual*/ bool updateBuffer(); - /*virtual*/ void update3DPosition(); - /*virtual*/ void updateLoop(); - -protected: - int mChannelID; - S32 mLastSamplePos; -}; - - -class LLAudioBufferFMOD : public LLAudioBuffer -{ -public: - LLAudioBufferFMOD(); - virtual ~LLAudioBufferFMOD(); - - /*virtual*/ bool loadWAV(const std::string& filename); - /*virtual*/ U32 getLength(); - friend class LLAudioChannelFMOD; - - void set3DMode(bool use3d); -protected: - FSOUND_SAMPLE *getSample() { return mSamplep; } -protected: - FSOUND_SAMPLE *mSamplep; -}; - -class LLAudioStreamFMOD -{ -public: - LLAudioStreamFMOD(const std::string& url); - int startStream(); - bool stopStream(); // Returns true if the stream was successfully stopped. - bool ready(); - - const std::string& getURL() { return mInternetStreamURL; } - - int getOpenState(); -protected: - FSOUND_STREAM* mInternetStream; - bool mReady; - - std::string mInternetStreamURL; -}; - -#endif // LL_AUDIOENGINE_FMOD_H diff --git a/linden/indra/llaudio/audioengine_openal.cpp b/linden/indra/llaudio/audioengine_openal.cpp deleted file mode 100644 index 84305f0..0000000 --- a/linden/indra/llaudio/audioengine_openal.cpp +++ /dev/null @@ -1,574 +0,0 @@ -/** - * @file audioengine_openal.cpp - * @brief implementation of audio engine using OpenAL - * support as a OpenAL 3D implementation - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "lldir.h" - -#include "audioengine_openal.h" -#include "listener_openal.h" - - -LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() - : - mWindGen(NULL), - mWindBuf(NULL), - mWindBufFreq(0), - mWindBufSamples(0), - mWindBufBytes(0), - mWindSource(AL_NONE), - mNumEmptyWindALBuffers(MAX_NUM_WIND_BUFFERS) -{ -} - -// virtual -LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL() -{ -} - -static ALboolean alutInitHelp(const char **errorstring) -{ - ALboolean result = AL_FALSE; - ALenum err = AL_NO_ERROR; -#if LL_WINDOWS - __try { - result = alutInit(NULL, NULL); - err = alutGetError(); - alGetError(); // hit loading of wrap_oal.dll - if(!result) *errorstring = alutGetErrorString(err); - } __except( EXCEPTION_EXECUTE_HANDLER ) { - *errorstring = "[Exception]"; - result = AL_FALSE; - } - return result; -#else - result = alutInit(NULL, NULL); - if(!result) { - err = alutGetError(); - *errorstring = alutGetErrorString(err); - } - return result; -#endif -} - -// virtual -bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata) -{ - const char *errorstring = "(null)"; - mWindGen = NULL; - LLAudioEngine::init(num_channels, userdata); - - if(!alutInitHelp(&errorstring)) - { - llwarns << "LLAudioEngine_OpenAL::init() ALUT initialization failed: " << errorstring << llendl; - return false; - } - - llinfos << "LLAudioEngine_OpenAL::init() OpenAL successfully initialized" << llendl; - - llinfos << "OpenAL version: " - << ll_safe_string(alGetString(AL_VERSION)) << llendl; - llinfos << "OpenAL vendor: " - << ll_safe_string(alGetString(AL_VENDOR)) << llendl; - llinfos << "OpenAL renderer: " - << ll_safe_string(alGetString(AL_RENDERER)) << llendl; - - ALint major = alutGetMajorVersion (); - ALint minor = alutGetMinorVersion (); - llinfos << "ALUT version: " << major << "." << minor << llendl; - - ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext()); - - alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major); - alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor); - llinfos << "ALC version: " << major << "." << minor << llendl; - - llinfos << "ALC default device: " - << ll_safe_string(alcGetString(device, - ALC_DEFAULT_DEVICE_SPECIFIER)) - << llendl; - - return true; -} - -// virtual -std::string LLAudioEngine_OpenAL::getDriverName(bool verbose) -{ - ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext()); - std::ostringstream version; - - version << - "OpenAL"; - - if (verbose) - { - version << - ", version " << - ll_safe_string(alGetString(AL_VERSION)) << - " / " << - ll_safe_string(alGetString(AL_VENDOR)) << - " / " << - ll_safe_string(alGetString(AL_RENDERER)); - - if (device) - version << - ": " << - ll_safe_string(alcGetString(device, - ALC_DEFAULT_DEVICE_SPECIFIER)); - } - - return version.str(); -} - -// virtual -void LLAudioEngine_OpenAL::allocateListener() -{ - mListenerp = (LLListener *) new LLListener_OpenAL(); - if(!mListenerp) - { - llwarns << "LLAudioEngine_OpenAL::allocateListener() Listener creation failed" << llendl; - } -} - -// virtual -void LLAudioEngine_OpenAL::shutdown() -{ - llinfos << "About to LLAudioEngine::shutdown()" << llendl; - LLAudioEngine::shutdown(); - - llinfos << "About to alutExit()" << llendl; - if(!alutExit()) - { - llwarns << "Nuts." << llendl; - llwarns << "LLAudioEngine_OpenAL::shutdown() ALUT shutdown failed: " << alutGetErrorString (alutGetError ()) << llendl; - } - - llinfos << "LLAudioEngine_OpenAL::shutdown() OpenAL successfully shut down" << llendl; - - delete mListenerp; - mListenerp = NULL; -} - -LLAudioBuffer *LLAudioEngine_OpenAL::createBuffer() -{ - return new LLAudioBufferOpenAL(); -} - -LLAudioChannel *LLAudioEngine_OpenAL::createChannel() -{ - return new LLAudioChannelOpenAL(); -} - -void LLAudioEngine_OpenAL::setInternalGain(F32 gain) -{ - //llinfos << "LLAudioEngine_OpenAL::setInternalGain() Gain: " << gain << llendl; - alListenerf(AL_GAIN, gain); -} - -LLAudioChannelOpenAL::LLAudioChannelOpenAL() - : - mALSource(AL_NONE), - mLastSamplePos(0) -{ - alGenSources(1, &mALSource); -} - -LLAudioChannelOpenAL::~LLAudioChannelOpenAL() -{ - cleanup(); - alDeleteSources(1, &mALSource); -} - -void LLAudioChannelOpenAL::cleanup() -{ - alSourceStop(mALSource); - mCurrentBufferp = NULL; -} - -void LLAudioChannelOpenAL::play() -{ - if (mALSource == AL_NONE) - { - llwarns << "Playing without a mALSource, aborting" << llendl; - return; - } - - if(!isPlaying()) - { - alSourcePlay(mALSource); - getSource()->setPlayedOnce(true); - } -} - -void LLAudioChannelOpenAL::playSynced(LLAudioChannel *channelp) -{ - if (channelp) - { - LLAudioChannelOpenAL *masterchannelp = - (LLAudioChannelOpenAL*)channelp; - if (mALSource != AL_NONE && - masterchannelp->mALSource != AL_NONE) - { - // we have channels allocated to master and slave - ALfloat master_offset; - alGetSourcef(masterchannelp->mALSource, AL_SEC_OFFSET, - &master_offset); - - llinfos << "Syncing with master at " << master_offset - << "sec" << llendl; - // *TODO: detect when this fails, maybe use AL_SAMPLE_ - alSourcef(mALSource, AL_SEC_OFFSET, master_offset); - } - } - play(); -} - -bool LLAudioChannelOpenAL::isPlaying() -{ - if (mALSource != AL_NONE) - { - ALint state; - alGetSourcei(mALSource, AL_SOURCE_STATE, &state); - if(state == AL_PLAYING) - { - return true; - } - } - - return false; -} - -bool LLAudioChannelOpenAL::updateBuffer() -{ - if (LLAudioChannel::updateBuffer()) - { - // Base class update returned true, which means that we need to actually - // set up the source for a different buffer. - LLAudioBufferOpenAL *bufferp = (LLAudioBufferOpenAL *)mCurrentSourcep->getCurrentBuffer(); - ALuint buffer = bufferp->getBuffer(); - alSourcei(mALSource, AL_BUFFER, buffer); - mLastSamplePos = 0; - } - - if (mCurrentSourcep) - { - alSourcef(mALSource, AL_GAIN, - mCurrentSourcep->getGain() * getSecondaryGain()); - alSourcei(mALSource, AL_LOOPING, - mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE); - alSourcef(mALSource, AL_ROLLOFF_FACTOR, - gAudiop->mListenerp->getRolloffFactor()); - alSourcef(mALSource, AL_REFERENCE_DISTANCE, - gAudiop->mListenerp->getDistanceFactor()); - } - - return true; -} - - -void LLAudioChannelOpenAL::updateLoop() -{ - if (mALSource == AL_NONE) - { - return; - } - - // Hack: We keep track of whether we looped or not by seeing when the - // sample position looks like it's going backwards. Not reliable; may - // yield false negatives. - // - ALint cur_pos; - alGetSourcei(mALSource, AL_SAMPLE_OFFSET, &cur_pos); - if (cur_pos < mLastSamplePos) - { - mLoopedThisFrame = true; - } - mLastSamplePos = cur_pos; -} - - -void LLAudioChannelOpenAL::update3DPosition() -{ - if(!mCurrentSourcep) - { - return; - } - if (mCurrentSourcep->isAmbient()) - { - alSource3f(mALSource, AL_POSITION, 0.0, 0.0, 0.0); - alSource3f(mALSource, AL_VELOCITY, 0.0, 0.0, 0.0); - alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_TRUE); - } else { - LLVector3 float_pos; - float_pos.setVec(mCurrentSourcep->getPositionGlobal()); - alSourcefv(mALSource, AL_POSITION, float_pos.mV); - alSourcefv(mALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV); - alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_FALSE); - } - - alSourcef(mALSource, AL_GAIN, mCurrentSourcep->getGain() * getSecondaryGain()); -} - -LLAudioBufferOpenAL::LLAudioBufferOpenAL() -{ - mALBuffer = AL_NONE; -} - -LLAudioBufferOpenAL::~LLAudioBufferOpenAL() -{ - cleanup(); -} - -void LLAudioBufferOpenAL::cleanup() -{ - if(mALBuffer != AL_NONE) - { - alDeleteBuffers(1, &mALBuffer); - mALBuffer = AL_NONE; - } -} - -bool LLAudioBufferOpenAL::loadWAV(const std::string& filename) -{ - cleanup(); - mALBuffer = alutCreateBufferFromFile(filename.c_str()); - if(mALBuffer == AL_NONE) - { - ALenum error = alutGetError(); - if (gDirUtilp->fileExists(filename)) - { - llwarns << - "LLAudioBufferOpenAL::loadWAV() Error loading " - << filename - << " " << alutGetErrorString(error) << llendl; - } - else - { - // It's common for the file to not actually exist. - lldebugs << - "LLAudioBufferOpenAL::loadWAV() Error loading " - << filename - << " " << alutGetErrorString(error) << llendl; - } - return false; - } - - return true; -} - -U32 LLAudioBufferOpenAL::getLength() -{ - if(mALBuffer == AL_NONE) - { - return 0; - } - ALint length; - alGetBufferi(mALBuffer, AL_SIZE, &length); - return length / 2; // convert size in bytes to size in (16-bit) samples -} - -// ------------ - -void LLAudioEngine_OpenAL::initWind() -{ - ALenum error; - llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl; - - mNumEmptyWindALBuffers = MAX_NUM_WIND_BUFFERS; - - alGetError(); /* clear error */ - - alGenSources(1,&mWindSource); - - if((error=alGetError()) != AL_NO_ERROR) - { - llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind sources: "<; - - mWindBufFreq = mWindGen->getInputSamplingRate(); - mWindBufSamples = llceil(mWindBufFreq * 0.05f); // 1/20th sec - WIND_BUFFER_SIZE_SEC - mWindBufBytes = mWindBufSamples * 2 /*stereo*/ * sizeof(WIND_SAMPLE_T); - - mWindBuf = new WIND_SAMPLE_T [mWindBufSamples * 2 /*stereo*/]; - - if(mWindBuf==NULL) - { - llerrs << "LLAudioEngine_OpenAL::initWind() Error creating wind memory buffer" << llendl; - mEnableWind=false; - } - - llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl; -} - -void LLAudioEngine_OpenAL::cleanupWind() -{ - llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl; - - if (mWindSource != AL_NONE) - { - // detach and delete all outstanding buffers on the wind source - alSourceStop(mWindSource); - ALint processed; - alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed); - while (processed--) - { - ALuint buffer = AL_NONE; - alSourceUnqueueBuffers(mWindSource, 1, &buffer); - alDeleteBuffers(1, &buffer); - } - - // delete the wind source itself - alDeleteSources(1, &mWindSource); - - mWindSource = AL_NONE; - } - - delete[] mWindBuf; - mWindBuf = NULL; - - delete mWindGen; - mWindGen = NULL; -} - -void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude) -{ - LLVector3 wind_pos; - F64 pitch; - F64 center_freq; - ALenum error; - - if (!mEnableWind) - return; - - if(!mWindBuf) - return; - - if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) - { - - // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) - // need to convert this to the conventional orientation DS3D and OpenAL use - // where +X = right, +Y = up, +Z = backwards - - wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); - - pitch = 1.0 + mapWindVecToPitch(wind_vec); - center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); - - mWindGen->mTargetFreq = (F32)center_freq; - mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; - mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); - - alSourcei(mWindSource, AL_LOOPING, AL_FALSE); - alSource3f(mWindSource, AL_POSITION, 0.0, 0.0, 0.0); - alSource3f(mWindSource, AL_VELOCITY, 0.0, 0.0, 0.0); - alSourcef(mWindSource, AL_ROLLOFF_FACTOR, 0.0); - alSourcei(mWindSource, AL_SOURCE_RELATIVE, AL_TRUE); - } - - // ok lets make a wind buffer now - - ALint processed, queued, unprocessed; - alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed); - alGetSourcei(mWindSource, AL_BUFFERS_QUEUED, &queued); - unprocessed = queued - processed; - - // ensure that there are always at least 3x as many filled buffers - // queued as we managed to empty since last time. - mNumEmptyWindALBuffers = llmin(mNumEmptyWindALBuffers + processed * 3 - unprocessed, MAX_NUM_WIND_BUFFERS-unprocessed); - mNumEmptyWindALBuffers = llmax(mNumEmptyWindALBuffers, 0); - - //llinfos << "mNumEmptyWindALBuffers: " << mNumEmptyWindALBuffers <<" (" << unprocessed << ":" << processed << ")" << llendl; - - while(processed--) // unqueue old buffers - { - ALuint buffer; - ALenum error; - alGetError(); /* clear error */ - alSourceUnqueueBuffers(mWindSource, 1, &buffer); - error = alGetError(); - if(error != AL_NO_ERROR) - { - llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << llendl; - } - else - { - alDeleteBuffers(1, &buffer); - } - } - - unprocessed += mNumEmptyWindALBuffers; - while (mNumEmptyWindALBuffers > 0) // fill+queue new buffers - { - ALuint buffer; - alGetError(); /* clear error */ - alGenBuffers(1,&buffer); - if((error=alGetError()) != AL_NO_ERROR) - { - llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind buffer: " << error << llendl; - break; - } - - alBufferData(buffer, - AL_FORMAT_STEREO16, - mWindGen->windGenerate(mWindBuf, - mWindBufSamples, 2), - mWindBufBytes, - mWindBufFreq); - error = alGetError(); - if(error != AL_NO_ERROR) - { - llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (bufferdata) buffers" << llendl; - } - - alSourceQueueBuffers(mWindSource, 1, &buffer); - error = alGetError(); - if(error != AL_NO_ERROR) - { - llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (queuing) buffers" << llendl; - } - - --mNumEmptyWindALBuffers; - } - - ALint playing; - alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing); - if(playing != AL_PLAYING) - { - alSourcePlay(mWindSource); - - lldebugs << "Wind had stopped - probably ran out of buffers - restarting: " << (unprocessed+mNumEmptyWindALBuffers) << " now queued." << llendl; - } -} - diff --git a/linden/indra/llaudio/audioengine_openal.h b/linden/indra/llaudio/audioengine_openal.h deleted file mode 100644 index 8c8bfd9..0000000 --- a/linden/indra/llaudio/audioengine_openal.h +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @file audioengine_openal.cpp - * @brief implementation of audio engine using OpenAL - * support as a OpenAL 3D implementation - * - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - - -#ifndef LL_AUDIOENGINE_OPENAL_H -#define LL_AUDIOENGINE_OPENAL_H - -#include "audioengine.h" -#include "listener_openal.h" -#include "windgen.h" - - -class LLAudioEngine_OpenAL : public LLAudioEngine -{ - public: - LLAudioEngine_OpenAL(); - virtual ~LLAudioEngine_OpenAL(); - - virtual bool init(const S32 num_channels, void *user_data); - virtual std::string getDriverName(bool verbose); - virtual void allocateListener(); - - virtual void shutdown(); - - void setInternalGain(F32 gain); - - LLAudioBuffer* createBuffer(); - LLAudioChannel* createChannel(); - - /*virtual*/ void initWind(); - /*virtual*/ void cleanupWind(); - /*virtual*/ void updateWind(LLVector3 direction, F32 camera_altitude); - - private: - void * windDSP(void *newbuffer, int length); - typedef S16 WIND_SAMPLE_T; - LLWindGen *mWindGen; - S16 *mWindBuf; - U32 mWindBufFreq; - U32 mWindBufSamples; - U32 mWindBufBytes; - ALuint mWindSource; - int mNumEmptyWindALBuffers; - - static const int MAX_NUM_WIND_BUFFERS = 80; -}; - -class LLAudioChannelOpenAL : public LLAudioChannel -{ - public: - LLAudioChannelOpenAL(); - virtual ~LLAudioChannelOpenAL(); - protected: - /*virtual*/ void play(); - /*virtual*/ void playSynced(LLAudioChannel *channelp); - /*virtual*/ void cleanup(); - /*virtual*/ bool isPlaying(); - - /*virtual*/ bool updateBuffer(); - /*virtual*/ void update3DPosition(); - /*virtual*/ void updateLoop(); - - ALuint mALSource; - ALint mLastSamplePos; -}; - -class LLAudioBufferOpenAL : public LLAudioBuffer{ - public: - LLAudioBufferOpenAL(); - virtual ~LLAudioBufferOpenAL(); - - bool loadWAV(const std::string& filename); - U32 getLength(); - - friend class LLAudioChannelOpenAL; - protected: - void cleanup(); - ALuint getBuffer() {return mALBuffer;} - - ALuint mALBuffer; -}; - -#endif diff --git a/linden/indra/llaudio/listener.cpp b/linden/indra/llaudio/listener.cpp index e2dc30e..e69de29 100644 --- a/linden/indra/llaudio/listener.cpp +++ b/linden/indra/llaudio/listener.cpp @@ -1,153 +0,0 @@ -/** - * @file listener.cpp - * @brief Implementation of LISTENER class abstracting the audio support - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "listener.h" - -#define DEFAULT_AT 0.0f,0.0f,-1.0f -#define DEFAULT_UP 0.0f,1.0f,0.0f - -//----------------------------------------------------------------------- -// constructor -//----------------------------------------------------------------------- -LLListener::LLListener() -{ - init(); -} - -//----------------------------------------------------------------------- -LLListener::~LLListener() -{ -} - -//----------------------------------------------------------------------- -void LLListener::init(void) -{ - mPosition.zeroVec(); - mListenAt.setVec(DEFAULT_AT); - mListenUp.setVec(DEFAULT_UP); - mVelocity.zeroVec(); -} - -//----------------------------------------------------------------------- -void LLListener::translate(LLVector3 offset) -{ - mPosition += offset; -} - -//----------------------------------------------------------------------- -void LLListener::setPosition(LLVector3 pos) -{ - mPosition = pos; -} - -//----------------------------------------------------------------------- -LLVector3 LLListener::getPosition(void) -{ - return(mPosition); -} - -//----------------------------------------------------------------------- -LLVector3 LLListener::getAt(void) -{ - return(mListenAt); -} - -//----------------------------------------------------------------------- -LLVector3 LLListener::getUp(void) -{ - return(mListenUp); -} - -//----------------------------------------------------------------------- -void LLListener::setVelocity(LLVector3 vel) -{ - mVelocity = vel; -} - -//----------------------------------------------------------------------- -void LLListener::orient(LLVector3 up, LLVector3 at) -{ - mListenUp = up; - mListenAt = at; -} - -//----------------------------------------------------------------------- -void LLListener::set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at) -{ - mPosition = pos; - mVelocity = vel; - - setPosition(pos); - setVelocity(vel); - orient(up,at); -} - -//----------------------------------------------------------------------- -void LLListener::setDopplerFactor(F32 factor) -{ -} - -//----------------------------------------------------------------------- -F32 LLListener::getDopplerFactor() -{ - return (1.f); -} - -//----------------------------------------------------------------------- -void LLListener::setDistanceFactor(F32 factor) -{ -} - -//----------------------------------------------------------------------- -F32 LLListener::getDistanceFactor() -{ - return (1.f); -} - -//----------------------------------------------------------------------- -void LLListener::setRolloffFactor(F32 factor) -{ -} - -//----------------------------------------------------------------------- -F32 LLListener::getRolloffFactor() -{ - return (1.f); -} - -//----------------------------------------------------------------------- -void LLListener::commitDeferredChanges() -{ -} - diff --git a/linden/indra/llaudio/listener.h b/linden/indra/llaudio/listener.h index 4137304..e69de29 100644 --- a/linden/indra/llaudio/listener.h +++ b/linden/indra/llaudio/listener.h @@ -1,80 +0,0 @@ -/** - * @file listener.h - * @brief Description of LISTENER base class abstracting the audio support. - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LISTENER_H -#define LL_LISTENER_H - -#include "v3math.h" - -class LLListener -{ - private: - protected: - LLVector3 mPosition; - LLVector3 mVelocity; - LLVector3 mListenAt; - LLVector3 mListenUp; - - public: - - private: - protected: - public: - LLListener(); - virtual ~LLListener(); - virtual void init(); - - virtual void set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at); - - virtual void setPosition(LLVector3 pos); - virtual void setVelocity(LLVector3 vel); - - virtual void orient(LLVector3 up, LLVector3 at); - virtual void translate(LLVector3 offset); - - virtual void setDopplerFactor(F32 factor); - virtual void setDistanceFactor(F32 factor); - virtual void setRolloffFactor(F32 factor); - - virtual LLVector3 getPosition(); - virtual LLVector3 getAt(); - virtual LLVector3 getUp(); - - virtual F32 getDopplerFactor(); - virtual F32 getDistanceFactor(); - virtual F32 getRolloffFactor(); - - virtual void commitDeferredChanges(); -}; - -#endif - diff --git a/linden/indra/llaudio/listener_ds3d.h b/linden/indra/llaudio/listener_ds3d.h index 3121e12..e69de29 100644 --- a/linden/indra/llaudio/listener_ds3d.h +++ b/linden/indra/llaudio/listener_ds3d.h @@ -1,76 +0,0 @@ -/** - * @file listener_ds3d.h - * @brief Description of LISTENER class abstracting the audio support - * as a DirectSound 3D implementation (windows only) - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LISTENER_DS3D_H -#define LL_LISTENER_DS3D_H - -#include "listener.h" - -#include -#include -#include - -class LLListener_DS3D : public LLListener -{ - private: - protected: - IDirectSound3DListener8 *m3DListener; - public: - - private: - protected: - public: - LLListener_DS3D(); - virtual ~LLListener_DS3D(); - virtual void init(); - - virtual void setDS3DLPtr (IDirectSound3DListener8 *listener_p); - - virtual void translate(LLVector3 offset); - virtual void setPosition(LLVector3 pos); - virtual void setVelocity(LLVector3 vel); - virtual void orient(LLVector3 up, LLVector3 at); - - virtual void setDopplerFactor(F32 factor); - virtual F32 getDopplerFactor(); - virtual void setDistanceFactor(F32 factor); - virtual F32 getDistanceFactor(); - virtual void setRolloffFactor(F32 factor); - virtual F32 getRolloffFactor(); - - virtual void commitDeferredChanges(); -}; - -#endif - - diff --git a/linden/indra/llaudio/listener_fmod.cpp b/linden/indra/llaudio/listener_fmod.cpp index 4bbb3d9..e69de29 100644 --- a/linden/indra/llaudio/listener_fmod.cpp +++ b/linden/indra/llaudio/listener_fmod.cpp @@ -1,143 +0,0 @@ -/** - * @file listener_fmod.cpp - * @brief implementation of LISTENER class abstracting the audio - * support as a FMOD 3D implementation (windows only) - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "audioengine.h" -#include "listener_fmod.h" -#include "fmod.h" - -//----------------------------------------------------------------------- -// constructor -//----------------------------------------------------------------------- -LLListener_FMOD::LLListener_FMOD() -{ - init(); -} - -//----------------------------------------------------------------------- -LLListener_FMOD::~LLListener_FMOD() -{ -} - -//----------------------------------------------------------------------- -void LLListener_FMOD::init(void) -{ - // do inherited - LLListener::init(); - mDopplerFactor = 1.0f; - mDistanceFactor = 1.0f; - mRolloffFactor = 1.0f; -} - -//----------------------------------------------------------------------- -void LLListener_FMOD::translate(LLVector3 offset) -{ - LLListener::translate(offset); - - FSOUND_3D_Listener_SetAttributes(mPosition.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); -} - -//----------------------------------------------------------------------- -void LLListener_FMOD::setPosition(LLVector3 pos) -{ - LLListener::setPosition(pos); - - FSOUND_3D_Listener_SetAttributes(pos.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); -} - -//----------------------------------------------------------------------- -void LLListener_FMOD::setVelocity(LLVector3 vel) -{ - LLListener::setVelocity(vel); - - FSOUND_3D_Listener_SetAttributes(NULL, vel.mV, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); -} - -//----------------------------------------------------------------------- -void LLListener_FMOD::orient(LLVector3 up, LLVector3 at) -{ - LLListener::orient(up, at); - - // Welcome to the transition between right and left - // (coordinate systems, that is) - // Leaving the at vector alone results in a L/R reversal - // since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed - at = -at; - - FSOUND_3D_Listener_SetAttributes(NULL, NULL, at.mV[0],at.mV[1],at.mV[2], up.mV[0],up.mV[1],up.mV[2]); -} - -//----------------------------------------------------------------------- -void LLListener_FMOD::commitDeferredChanges() -{ - FSOUND_Update(); -} - - -void LLListener_FMOD::setRolloffFactor(F32 factor) -{ - mRolloffFactor = factor; - FSOUND_3D_SetRolloffFactor(factor); -} - - -F32 LLListener_FMOD::getRolloffFactor() -{ - return mRolloffFactor; -} - - -void LLListener_FMOD::setDopplerFactor(F32 factor) -{ - mDopplerFactor = factor; - FSOUND_3D_SetDopplerFactor(factor); -} - - -F32 LLListener_FMOD::getDopplerFactor() -{ - return mDopplerFactor; -} - - -void LLListener_FMOD::setDistanceFactor(F32 factor) -{ - mDistanceFactor = factor; - FSOUND_3D_SetDistanceFactor(factor); -} - - -F32 LLListener_FMOD::getDistanceFactor() -{ - return mDistanceFactor; -} diff --git a/linden/indra/llaudio/listener_fmod.h b/linden/indra/llaudio/listener_fmod.h index 5f372ab..e69de29 100644 --- a/linden/indra/llaudio/listener_fmod.h +++ b/linden/indra/llaudio/listener_fmod.h @@ -1,67 +0,0 @@ -/** - * @file listener_fmod.h - * @brief Description of LISTENER class abstracting the audio support - * as an FMOD 3D implementation (windows and Linux) - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LISTENER_FMOD_H -#define LL_LISTENER_FMOD_H - -#include "listener.h" - -class LLListener_FMOD : public LLListener -{ - public: - LLListener_FMOD(); - virtual ~LLListener_FMOD(); - virtual void init(); - - virtual void translate(LLVector3 offset); - virtual void setPosition(LLVector3 pos); - virtual void setVelocity(LLVector3 vel); - virtual void orient(LLVector3 up, LLVector3 at); - virtual void commitDeferredChanges(); - - virtual void setDopplerFactor(F32 factor); - virtual F32 getDopplerFactor(); - virtual void setDistanceFactor(F32 factor); - virtual F32 getDistanceFactor(); - virtual void setRolloffFactor(F32 factor); - virtual F32 getRolloffFactor(); - - protected: - F32 mDopplerFactor; - F32 mDistanceFactor; - F32 mRolloffFactor; -}; - -#endif - - diff --git a/linden/indra/llaudio/listener_openal.cpp b/linden/indra/llaudio/listener_openal.cpp deleted file mode 100644 index d0ef9b2..0000000 --- a/linden/indra/llaudio/listener_openal.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @file audioengine_openal.cpp - * @brief implementation of audio engine using OpenAL - * support as a OpenAL 3D implementation - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "audioengine.h" - -#include "listener_openal.h" - -LLListener_OpenAL::LLListener_OpenAL() -{ - init(); -} - -LLListener_OpenAL::~LLListener_OpenAL() -{ -} - -void LLListener_OpenAL::translate(LLVector3 offset) -{ - //llinfos << "LLListener_OpenAL::translate() : " << offset << llendl; - LLListener::translate(offset); -} - -void LLListener_OpenAL::setPosition(LLVector3 pos) -{ - //llinfos << "LLListener_OpenAL::setPosition() : " << pos << llendl; - LLListener::setPosition(pos); -} - -void LLListener_OpenAL::setVelocity(LLVector3 vel) -{ - LLListener::setVelocity(vel); -} - -void LLListener_OpenAL::orient(LLVector3 up, LLVector3 at) -{ - //llinfos << "LLListener_OpenAL::orient() up: " << up << " at: " << at << llendl; - LLListener::orient(up, at); -} - -void LLListener_OpenAL::commitDeferredChanges() -{ - ALfloat orientation[6]; - orientation[0] = mListenAt.mV[0]; - orientation[1] = mListenAt.mV[1]; - orientation[2] = mListenAt.mV[2]; - orientation[3] = mListenUp.mV[0]; - orientation[4] = mListenUp.mV[1]; - orientation[5] = mListenUp.mV[2]; - - ALfloat velocity[3]; - velocity[0] = mVelocity.mV[0]; - velocity[1] = mVelocity.mV[1]; - velocity[2] = mVelocity.mV[2]; - - alListenerfv(AL_ORIENTATION, orientation); - alListenerfv(AL_POSITION, mPosition.mV); - alListenerfv(AL_VELOCITY, velocity); -} - -void LLListener_OpenAL::setDopplerFactor(F32 factor) -{ - //llinfos << "LLListener_OpenAL::setDopplerFactor() : " << factor << llendl; - alDopplerFactor(factor); -} - -F32 LLListener_OpenAL::getDopplerFactor() -{ - ALfloat factor; - factor = alGetFloat(AL_DOPPLER_FACTOR); - //llinfos << "LLListener_OpenAL::getDopplerFactor() : " << factor << llendl; - return factor; -} - - -void LLListener_OpenAL::setRolloffFactor(F32 factor) -{ - mRolloffFactor = factor; -} - -F32 LLListener_OpenAL::getRolloffFactor() -{ - return mRolloffFactor; -} - - -void LLListener_OpenAL::setDistanceFactor(F32 factor) -{ - mDistanceFactor = factor; -} - -F32 LLListener_OpenAL::getDistanceFactor() -{ - return mDistanceFactor; -} diff --git a/linden/indra/llaudio/listener_openal.h b/linden/indra/llaudio/listener_openal.h deleted file mode 100644 index 2b79ada..0000000 --- a/linden/indra/llaudio/listener_openal.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file listener_openal.h - * @brief Description of LISTENER class abstracting the audio support - * as an OpenAL implementation - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LISTENER_OPENAL_H -#define LL_LISTENER_OPENAL_H - -#include "listener.h" - - -//#include "AL/al.h" -#include "AL/alut.h" - -class LLListener_OpenAL : public LLListener -{ - public: - LLListener_OpenAL(); - virtual ~LLListener_OpenAL(); - - virtual void translate(LLVector3 offset); - virtual void setPosition(LLVector3 pos); - virtual void setVelocity(LLVector3 vel); - virtual void orient(LLVector3 up, LLVector3 at); - virtual void commitDeferredChanges(); - - virtual void setDopplerFactor(F32 factor); - virtual F32 getDopplerFactor(); - virtual void setDistanceFactor(F32 factor); - virtual F32 getDistanceFactor(); - virtual void setRolloffFactor(F32 factor); - virtual F32 getRolloffFactor(); - - protected: - F32 mDistanceFactor; - F32 mRolloffFactor; -}; - -#endif - diff --git a/linden/indra/llaudio/llaudiodecodemgr.cpp b/linden/indra/llaudio/llaudiodecodemgr.cpp index afb3c33..a14d4ec 100644 --- a/linden/indra/llaudio/llaudiodecodemgr.cpp +++ b/linden/indra/llaudio/llaudiodecodemgr.cpp @@ -33,18 +33,18 @@ #include "llaudiodecodemgr.h" -#include "vorbisdecode.h" -#include "audioengine.h" +#include "llvorbisdecode.h" +#include "llaudioengine.h" #include "lllfsthread.h" #include "llvfile.h" #include "llstring.h" #include "lldir.h" #include "llendianswizzle.h" -#include "audioengine.h" #include "llassetstorage.h" #include "vorbis/codec.h" #include "vorbis/vorbisfile.h" +#include "llvorbisencode.h" extern LLAudioEngine *gAudiop; @@ -218,11 +218,42 @@ BOOL LLVorbisDecodeState::initDecode() return(FALSE); } - size_t size_guess = (size_t)ov_pcm_total(&mVF, -1); + S32 sample_count = ov_pcm_total(&mVF, -1); + size_t size_guess = (size_t)sample_count; vorbis_info* vi = ov_info(&mVF, -1); size_guess *= vi->channels; size_guess *= 2; size_guess += 2048; + + bool abort_decode = false; + + if( vi->channels < 1 || vi->channels > LLVORBIS_CLIP_MAX_CHANNELS ) + { + abort_decode = true; + llwarns << "Bad channel count: " << vi->channels << llendl; + } + + if( (size_t)sample_count > LLVORBIS_CLIP_REJECT_SAMPLES ) + { + abort_decode = true; + llwarns << "Illegal sample count: " << sample_count << llendl; + } + + if( size_guess > LLVORBIS_CLIP_REJECT_SIZE ) + { + abort_decode = true; + llwarns << "Illegal sample size: " << size_guess << llendl; + } + + if( abort_decode ) + { + llwarns << "Canceling initDecode. Bad asset: " << mUUID << llendl; + llwarns << "Bad asset encoded by: " << ov_comment(&mVF,-1)->vendor << llendl; + delete mInFilep; + mInFilep = NULL; + return FALSE; + } + mWAVBuffer.reserve(size_guess); mWAVBuffer.resize(WAV_HEADER_SIZE); @@ -375,16 +406,16 @@ BOOL LLVorbisDecodeState::finishDecode() // write "data" chunk length, in little-endian format S32 data_length = mWAVBuffer.size() - WAV_HEADER_SIZE; - mWAVBuffer[40] = (data_length - 8) & 0x000000FF; - mWAVBuffer[41] = ((data_length - 8)>> 8) & 0x000000FF; - mWAVBuffer[42] = ((data_length - 8)>> 16) & 0x000000FF; - mWAVBuffer[43] = ((data_length - 8)>> 24) & 0x000000FF; - + mWAVBuffer[40] = (data_length) & 0x000000FF; + mWAVBuffer[41] = (data_length >> 8) & 0x000000FF; + mWAVBuffer[42] = (data_length >> 16) & 0x000000FF; + mWAVBuffer[43] = (data_length >> 24) & 0x000000FF; // write overall "RIFF" length, in little-endian format - mWAVBuffer[4] = (data_length + 28) & 0x000000FF; - mWAVBuffer[5] = ((data_length + 28) >> 8) & 0x000000FF; - mWAVBuffer[6] = ((data_length + 28) >> 16) & 0x000000FF; - mWAVBuffer[7] = ((data_length + 28) >> 24) & 0x000000FF; + data_length += 36; + mWAVBuffer[4] = (data_length) & 0x000000FF; + mWAVBuffer[5] = (data_length >> 8) & 0x000000FF; + mWAVBuffer[6] = (data_length >> 16) & 0x000000FF; + mWAVBuffer[7] = (data_length >> 24) & 0x000000FF; // // FUDGECAKES!!! Vorbis encode/decode messes up loop point transitions (pop) @@ -396,8 +427,7 @@ BOOL LLVorbisDecodeState::finishDecode() S32 fade_length; char pcmout[4096]; /*Flawfinder: ignore*/ - fade_length = llmin((S32)128,(S32)(data_length)/8); - + fade_length = llmin((S32)128,(S32)(data_length-36)/8); if((S32)mWAVBuffer.size() >= (WAV_HEADER_SIZE + 2* fade_length)) { memcpy(pcmout, &mWAVBuffer[WAV_HEADER_SIZE], (2 * fade_length)); /*Flawfinder: ignore*/ @@ -437,7 +467,7 @@ BOOL LLVorbisDecodeState::finishDecode() } } - if (0 == data_length) + if (36 == data_length) { llwarns << "BAD Vorbis decode in finishDecode!" << llendl; mValid = FALSE; diff --git a/linden/indra/llaudio/llaudioengine.cpp b/linden/indra/llaudio/llaudioengine.cpp new file mode 100644 index 0000000..bed791a --- /dev/null +++ b/linden/indra/llaudio/llaudioengine.cpp @@ -0,0 +1,1801 @@ + /** + * @file audioengine.cpp + * @brief implementation of LLAudioEngine class abstracting the Open + * AL audio support + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include + +#include "linden_common.h" + +#include "llaudioengine.h" +#include "llstreamingaudio.h" + +#include "llerror.h" +#include "llmath.h" + +#include "sound_ids.h" // temporary hack for min/max distances + +#include "llvfs.h" +#include "lldir.h" +#include "llaudiodecodemgr.h" +#include "llassetstorage.h" + + +// necessary for grabbing sounds from sim (implemented in viewer) +extern void request_sound(const LLUUID &sound_guid); + +LLAudioEngine* gAudiop = NULL; + + +// +// LLAudioEngine implementation +// + + +LLAudioEngine::LLAudioEngine() +{ + setDefaults(); +} + + +LLAudioEngine::~LLAudioEngine() +{ +} + +LLStreamingAudioInterface* LLAudioEngine::getStreamingAudioImpl() +{ + return mStreamingAudioImpl; +} + +void LLAudioEngine::setStreamingAudioImpl(LLStreamingAudioInterface *impl) +{ + mStreamingAudioImpl = impl; +} + +void LLAudioEngine::setDefaults() +{ + mMaxWindGain = 1.f; + + mListenerp = NULL; + + mMuted = false; + mUserData = NULL; + + mLastStatus = 0; + + mNumChannels = 0; + mEnableWind = false; + + S32 i; + for (i = 0; i < MAX_CHANNELS; i++) + { + mChannels[i] = NULL; + } + for (i = 0; i < MAX_BUFFERS; i++) + { + mBuffers[i] = NULL; + } + + mMasterGain = 1.f; + mInternalGain = 0.f; + mNextWindUpdate = 0.f; + + mStreamingAudioImpl = NULL; + + for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++) + mSecondaryGain[i] = 1.0f; +} + + +bool LLAudioEngine::init(const S32 num_channels, void* userdata) +{ + setDefaults(); + + mNumChannels = num_channels; + mUserData = userdata; + + allocateListener(); + + // Initialize the decode manager + gAudioDecodeMgrp = new LLAudioDecodeMgr; + + llinfos << "LLAudioEngine::init() AudioEngine successfully initialized" << llendl; + + return true; +} + + +void LLAudioEngine::shutdown() +{ + // Clean up decode manager + delete gAudioDecodeMgrp; + gAudioDecodeMgrp = NULL; + + // Clean up wind source + cleanupWind(); + + // Clean up audio sources + source_map::iterator iter_src; + for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++) + { + delete iter_src->second; + } + + + // Clean up audio data + data_map::iterator iter_data; + for (iter_data = mAllData.begin(); iter_data != mAllData.end(); iter_data++) + { + delete iter_data->second; + } + + + // Clean up channels + S32 i; + for (i = 0; i < MAX_CHANNELS; i++) + { + delete mChannels[i]; + mChannels[i] = NULL; + } + + // Clean up buffers + for (i = 0; i < MAX_BUFFERS; i++) + { + delete mBuffers[i]; + mBuffers[i] = NULL; + } +} + + +// virtual +void LLAudioEngine::startInternetStream(const std::string& url) +{ + if (mStreamingAudioImpl) + mStreamingAudioImpl->start(url); +} + + +// virtual +void LLAudioEngine::stopInternetStream() +{ + if (mStreamingAudioImpl) + mStreamingAudioImpl->stop(); +} + +// virtual +void LLAudioEngine::pauseInternetStream(int pause) +{ + if (mStreamingAudioImpl) + mStreamingAudioImpl->pause(pause); +} + +// virtual +void LLAudioEngine::updateInternetStream() +{ + if (mStreamingAudioImpl) + mStreamingAudioImpl->update(); +} + +// virtual +int LLAudioEngine::isInternetStreamPlaying() +{ + if (mStreamingAudioImpl) + return mStreamingAudioImpl->isPlaying(); + + return 0; // Stopped +} + + +// virtual +void LLAudioEngine::setInternetStreamGain(F32 vol) +{ + if (mStreamingAudioImpl) + mStreamingAudioImpl->setGain(vol); +} + +// virtual +std::string LLAudioEngine::getInternetStreamURL() +{ + if (mStreamingAudioImpl) + return mStreamingAudioImpl->getURL(); + else return std::string(); +} + + +void LLAudioEngine::updateChannels() +{ + S32 i; + for (i = 0; i < MAX_CHANNELS; i++) + { + if (mChannels[i]) + { + mChannels[i]->updateBuffer(); + mChannels[i]->update3DPosition(); + mChannels[i]->updateLoop(); + } + } +} + +static const F32 default_max_decode_time = .002f; // 2 ms +void LLAudioEngine::idle(F32 max_decode_time) +{ + if (max_decode_time <= 0.f) + { + max_decode_time = default_max_decode_time; + } + + // "Update" all of our audio sources, clean up dead ones. + // Primarily does position updating, cleanup of unused audio sources. + // Also does regeneration of the current priority of each audio source. + + S32 i; + for (i = 0; i < MAX_BUFFERS; i++) + { + if (mBuffers[i]) + { + mBuffers[i]->mInUse = false; + } + } + + F32 max_priority = -1.f; + LLAudioSource *max_sourcep = NULL; // Maximum priority source without a channel + source_map::iterator iter; + for (iter = mAllSources.begin(); iter != mAllSources.end();) + { + LLAudioSource *sourcep = iter->second; + + // Update this source + sourcep->update(); + sourcep->updatePriority(); + + if (sourcep->isDone()) + { + // The source is done playing, clean it up. + delete sourcep; + mAllSources.erase(iter++); + continue; + } + + if (sourcep->isMuted()) + { + ++iter; + continue; + } + + if (!sourcep->getChannel() && sourcep->getCurrentBuffer()) + { + // We could potentially play this sound if its priority is high enough. + if (sourcep->getPriority() > max_priority) + { + max_priority = sourcep->getPriority(); + max_sourcep = sourcep; + } + } + + // Move on to the next source + iter++; + } + + // Now, do priority-based organization of audio sources. + // All channels used, check priorities. + // Find channel with lowest priority + if (max_sourcep) + { + LLAudioChannel *channelp = getFreeChannel(max_priority); + if (channelp) + { + //llinfos << "Replacing source in channel due to priority!" << llendl; + max_sourcep->setChannel(channelp); + channelp->setSource(max_sourcep); + if (max_sourcep->isSyncSlave()) + { + // A sync slave, it doesn't start playing until it's synced up with the master. + // Flag this channel as waiting for sync, and return true. + channelp->setWaiting(true); + } + else + { + channelp->setWaiting(false); + if (channelp->mCurrentBufferp) + { + channelp->play(); + } + } + } + } + + + // Do this BEFORE we update the channels + // Update the channels to sync up with any changes that the source made, + // such as changing what sound was playing. + updateChannels(); + + // Update queued sounds (switch to next queued data if the current has finished playing) + for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter) + { + // This is lame, instead of this I could actually iterate through all the sources + // attached to each channel, since only those with active channels + // can have anything interesting happen with their queue? (Maybe not true) + LLAudioSource *sourcep = iter->second; + if (!sourcep->mQueuedDatap || sourcep->isMuted()) + { + // Muted, or nothing queued, so we don't care. + continue; + } + + LLAudioChannel *channelp = sourcep->getChannel(); + if (!channelp) + { + // This sound isn't playing, so we just process move the queue + sourcep->mCurrentDatap = sourcep->mQueuedDatap; + sourcep->mQueuedDatap = NULL; + + // Reset the timer so the source doesn't die. + sourcep->mAgeTimer.reset(); + // Make sure we have the buffer set up if we just decoded the data + if (sourcep->mCurrentDatap) + { + updateBufferForData(sourcep->mCurrentDatap); + } + + // Actually play the associated data. + sourcep->setupChannel(); + channelp = sourcep->getChannel(); + if (channelp) + { + channelp->updateBuffer(); + sourcep->getChannel()->play(); + } + continue; + } + else + { + // Check to see if the current sound is done playing, or looped. + if (!channelp->isPlaying()) + { + sourcep->mCurrentDatap = sourcep->mQueuedDatap; + sourcep->mQueuedDatap = NULL; + + // Reset the timer so the source doesn't die. + sourcep->mAgeTimer.reset(); + + // Make sure we have the buffer set up if we just decoded the data + if (sourcep->mCurrentDatap) + { + updateBufferForData(sourcep->mCurrentDatap); + } + + // Actually play the associated data. + sourcep->setupChannel(); + channelp->updateBuffer(); + sourcep->getChannel()->play(); + } + else if (sourcep->isLoop()) + { + // It's a loop, we need to check and see if we're done with it. + if (channelp->mLoopedThisFrame) + { + sourcep->mCurrentDatap = sourcep->mQueuedDatap; + sourcep->mQueuedDatap = NULL; + + // Actually, should do a time sync so if we're a loop master/slave + // we don't drift away. + sourcep->setupChannel(); + sourcep->getChannel()->play(); + } + } + } + } + + // Lame, update the channels AGAIN. + // Update the channels to sync up with any changes that the source made, + // such as changing what sound was playing. + updateChannels(); + + // Hack! For now, just use a global sync master; + LLAudioSource *sync_masterp = NULL; + LLAudioChannel *master_channelp = NULL; + F32 max_sm_priority = -1.f; + for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter) + { + LLAudioSource *sourcep = iter->second; + if (sourcep->isMuted()) + { + continue; + } + if (sourcep->isSyncMaster()) + { + if (sourcep->getPriority() > max_sm_priority) + { + sync_masterp = sourcep; + master_channelp = sync_masterp->getChannel(); + max_sm_priority = sourcep->getPriority(); + } + } + } + + if (master_channelp && master_channelp->mLoopedThisFrame) + { + // Synchronize loop slaves with their masters + // Update queued sounds (switch to next queued data if the current has finished playing) + for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter) + { + LLAudioSource *sourcep = iter->second; + + if (!sourcep->isSyncSlave()) + { + // Not a loop slave, we don't need to do anything + continue; + } + + LLAudioChannel *channelp = sourcep->getChannel(); + if (!channelp) + { + // Not playing, don't need to bother. + continue; + } + + if (!channelp->isPlaying()) + { + // Now we need to check if our loop master has just looped, and + // start playback if that's the case. + if (sync_masterp->getChannel()) + { + channelp->playSynced(master_channelp); + channelp->setWaiting(false); + } + } + } + } + + // Sync up everything that the audio engine needs done. + commitDeferredChanges(); + + // Flush unused buffers that are stale enough + for (i = 0; i < MAX_BUFFERS; i++) + { + if (mBuffers[i]) + { + if (!mBuffers[i]->mInUse && mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > 30.f) + { + //llinfos << "Flushing unused buffer!" << llendl; + mBuffers[i]->mAudioDatap->mBufferp = NULL; + delete mBuffers[i]; + mBuffers[i] = NULL; + } + } + } + + + // Clear all of the looped flags for the channels + for (i = 0; i < MAX_CHANNELS; i++) + { + if (mChannels[i]) + { + mChannels[i]->mLoopedThisFrame = false; + } + } + + // Decode audio files + gAudioDecodeMgrp->processQueue(max_decode_time); + + // Call this every frame, just in case we somehow + // missed picking it up in all the places that can add + // or request new data. + startNextTransfer(); + + updateInternetStream(); +} + + + +bool LLAudioEngine::updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid) +{ + if (!adp) + { + return false; + } + + // Update the audio buffer first - load a sound if we have it. + // Note that this could potentially cause us to waste time updating buffers + // for sounds that actually aren't playing, although this should be mitigated + // by the fact that we limit the number of buffers, and we flush buffers based + // on priority. + if (!adp->getBuffer()) + { + if (adp->hasDecodedData()) + { + return adp->load(); + } + else if (adp->hasLocalData()) + { + if (audio_uuid.notNull()) + { + gAudioDecodeMgrp->addDecodeRequest(audio_uuid); + } + } + else + { + return false; + } + } + return true; +} + + +void LLAudioEngine::enableWind(bool enable) +{ + if (enable && (!mEnableWind)) + { + initWind(); + mEnableWind = enable; + } + else if (mEnableWind && (!enable)) + { + mEnableWind = enable; + cleanupWind(); + } +} + + +LLAudioBuffer * LLAudioEngine::getFreeBuffer() +{ + static clock_t last_info = 0; + static bool spamming = FALSE; + + S32 i; + for (i = 0; i < MAX_BUFFERS; i++) + { + if (!mBuffers[i]) + { + mBuffers[i] = createBuffer(); + return mBuffers[i]; + } + } + + + // Grab the oldest unused buffer + F32 max_age = -1.f; + S32 buffer_id = -1; + for (i = 0; i < MAX_BUFFERS; i++) + { + if (mBuffers[i]) + { + if (!mBuffers[i]->mInUse) + { + if (mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > max_age) + { + max_age = mBuffers[i]->mLastUseTimer.getElapsedTimeF32(); + buffer_id = i; + } + } + } + } + + if (buffer_id >= 0) + { + if (clock() - last_info > CLOCKS_PER_SEC) + { + // Do not spam us with such messages... + llinfos << "Taking over unused buffer " << buffer_id << llendl; + last_info = clock(); + } + else if (!spamming) + { + // ... but warn us *once* when the buffer freeing frequency is abnormal. + llwarns << "Excessive buffer freeing frequency, info messages throttled." << llendl; + spamming = true; + } + mBuffers[buffer_id]->mAudioDatap->mBufferp = NULL; + delete mBuffers[buffer_id]; + mBuffers[buffer_id] = createBuffer(); + return mBuffers[buffer_id]; + } + return NULL; +} + + +LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority) +{ + S32 i; + for (i = 0; i < mNumChannels; i++) + { + if (!mChannels[i]) + { + // No channel allocated here, use it. + mChannels[i] = createChannel(); + return mChannels[i]; + } + else + { + // Channel is allocated but not playing right now, use it. + if (!mChannels[i]->isPlaying() && !mChannels[i]->isWaiting()) + { + mChannels[i]->cleanup(); + if (mChannels[i]->getSource()) + { + mChannels[i]->getSource()->setChannel(NULL); + } + return mChannels[i]; + } + } + } + + // All channels used, check priorities. + // Find channel with lowest priority and see if we want to replace it. + F32 min_priority = 10000.f; + LLAudioChannel *min_channelp = NULL; + + for (i = 0; i < mNumChannels; i++) + { + LLAudioChannel *channelp = mChannels[i]; + LLAudioSource *sourcep = channelp->getSource(); + if (sourcep && sourcep->getPriority() < min_priority) + { + min_channelp = channelp; + min_priority = sourcep->getPriority(); + } + } + + if (min_priority > priority || !min_channelp) + { + // All playing channels have higher priority, return. + return NULL; + } + + // Flush the minimum priority channel, and return it. + min_channelp->cleanup(); + min_channelp->getSource()->setChannel(NULL); + return min_channelp; +} + + +void LLAudioEngine::cleanupBuffer(LLAudioBuffer *bufferp) +{ + S32 i; + for (i = 0; i < MAX_BUFFERS; i++) + { + if (mBuffers[i] == bufferp) + { + delete mBuffers[i]; + mBuffers[i] = NULL; + } + } +} + + +bool LLAudioEngine::preloadSound(const LLUUID &uuid) +{ + gAudiop->getAudioData(uuid); // We don't care about the return value, this is just to make sure + // that we have an entry, which will mean that the audio engine knows about this + + if (gAudioDecodeMgrp->addDecodeRequest(uuid)) + { + // This means that we do have a local copy, and we're working on decoding it. + return true; + } + + // At some point we need to have the audio/asset system check the static VFS + // before it goes off and fetches stuff from the server. + //llwarns << "Used internal preload for non-local sound" << llendl; + return false; +} + + +bool LLAudioEngine::isWindEnabled() +{ + return mEnableWind; +} + + +void LLAudioEngine::setMuted(bool muted) +{ + if (muted != mMuted) + { + mMuted = muted; + setMasterGain(mMasterGain); + } + enableWind(!mMuted); +} + +void LLAudioEngine::setMasterGain(const F32 gain) +{ + mMasterGain = gain; + F32 internal_gain = getMuted() ? 0.f : gain; + if (internal_gain != mInternalGain) + { + mInternalGain = internal_gain; + setInternalGain(mInternalGain); + } +} + +F32 LLAudioEngine::getMasterGain() +{ + return mMasterGain; +} + +void LLAudioEngine::setSecondaryGain(S32 type, F32 gain) +{ + llassert(type < LLAudioEngine::AUDIO_TYPE_COUNT); + + mSecondaryGain[type] = gain; +} + +F32 LLAudioEngine::getSecondaryGain(S32 type) +{ + return mSecondaryGain[type]; +} + +F32 LLAudioEngine::getInternetStreamGain() +{ + if (mStreamingAudioImpl) + return mStreamingAudioImpl->getGain(); + else + return 1.0f; +} + +void LLAudioEngine::setMaxWindGain(F32 gain) +{ + mMaxWindGain = gain; +} + + +F64 LLAudioEngine::mapWindVecToGain(LLVector3 wind_vec) +{ + F64 gain = 0.0; + + gain = wind_vec.magVec(); + + if (gain) + { + if (gain > 20) + { + gain = 20; + } + gain = gain/20.0; + } + + return (gain); +} + + +F64 LLAudioEngine::mapWindVecToPitch(LLVector3 wind_vec) +{ + LLVector3 listen_right; + F64 theta; + + // Wind frame is in listener-relative coordinates + LLVector3 norm_wind = wind_vec; + norm_wind.normVec(); + listen_right.setVec(1.0,0.0,0.0); + + // measure angle between wind vec and listener right axis (on 0,PI) + theta = acos(norm_wind * listen_right); + + // put it on 0, 1 + theta /= F_PI; + + // put it on [0, 0.5, 0] + if (theta > 0.5) theta = 1.0-theta; + if (theta < 0) theta = 0; + + return (theta); +} + + +F64 LLAudioEngine::mapWindVecToPan(LLVector3 wind_vec) +{ + LLVector3 listen_right; + F64 theta; + + // Wind frame is in listener-relative coordinates + listen_right.setVec(1.0,0.0,0.0); + + LLVector3 norm_wind = wind_vec; + norm_wind.normVec(); + + // measure angle between wind vec and listener right axis (on 0,PI) + theta = acos(norm_wind * listen_right); + + // put it on 0, 1 + theta /= F_PI; + + return (theta); +} + + +void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, + const S32 type, const LLVector3d &pos_global) +{ + // Create a new source (since this can't be associated with an existing source. + //llinfos << "Localized: " << audio_uuid << llendl; + + if (mMuted) + { + return; + } + + LLUUID source_id; + source_id.generate(); + + LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain, type); + gAudiop->addAudioSource(asp); + if (pos_global.isExactlyZero()) + { + asp->setAmbient(true); + } + else + { + asp->setPositionGlobal(pos_global); + } + asp->updatePriority(); + asp->play(audio_uuid); +} + + +void LLAudioEngine::setListenerPos(LLVector3 aVec) +{ + mListenerp->setPosition(aVec); +} + + +LLVector3 LLAudioEngine::getListenerPos() +{ + if (mListenerp) + { + return(mListenerp->getPosition()); + } + else + { + return(LLVector3::zero); + } +} + + +void LLAudioEngine::setListenerVelocity(LLVector3 aVec) +{ + mListenerp->setVelocity(aVec); +} + + +void LLAudioEngine::translateListener(LLVector3 aVec) +{ + mListenerp->translate(aVec); +} + + +void LLAudioEngine::orientListener(LLVector3 up, LLVector3 at) +{ + mListenerp->orient(up, at); +} + + +void LLAudioEngine::setListener(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at) +{ + mListenerp->set(pos,vel,up,at); +} + + +void LLAudioEngine::setDopplerFactor(F32 factor) +{ + if (mListenerp) + { + mListenerp->setDopplerFactor(factor); + } +} + + +F32 LLAudioEngine::getDopplerFactor() +{ + if (mListenerp) + { + return mListenerp->getDopplerFactor(); + } + else + { + return 0.f; + } +} + + +void LLAudioEngine::setRolloffFactor(F32 factor) +{ + if (mListenerp) + { + mListenerp->setRolloffFactor(factor); + } +} + + +F32 LLAudioEngine::getRolloffFactor() +{ + if (mListenerp) + { + return mListenerp->getRolloffFactor(); + } + else + { + return 0.f; + } +} + + +void LLAudioEngine::commitDeferredChanges() +{ + mListenerp->commitDeferredChanges(); +} + + +LLAudioSource * LLAudioEngine::findAudioSource(const LLUUID &source_id) +{ + source_map::iterator iter; + iter = mAllSources.find(source_id); + + if (iter == mAllSources.end()) + { + return NULL; + } + else + { + return iter->second; + } +} + + +LLAudioData * LLAudioEngine::getAudioData(const LLUUID &audio_uuid) +{ + data_map::iterator iter; + iter = mAllData.find(audio_uuid); + if (iter == mAllData.end()) + { + // Create the new audio data + LLAudioData *adp = new LLAudioData(audio_uuid); + mAllData[audio_uuid] = adp; + return adp; + } + else + { + return iter->second; + } +} + +void LLAudioEngine::addAudioSource(LLAudioSource *asp) +{ + mAllSources[asp->getID()] = asp; +} + + +void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp) +{ + source_map::iterator iter; + iter = mAllSources.find(asp->getID()); + if (iter == mAllSources.end()) + { + llwarns << "Cleaning up unknown audio source!" << llendl; + return; + } + delete asp; + mAllSources.erase(iter); +} + + +bool LLAudioEngine::hasDecodedFile(const LLUUID &uuid) +{ + std::string uuid_str; + uuid.toString(uuid_str); + + std::string wav_path; + wav_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str); + wav_path += ".dsf"; + + if (gDirUtilp->fileExists(wav_path)) + { + return true; + } + else + { + return false; + } +} + + +bool LLAudioEngine::hasLocalFile(const LLUUID &uuid) +{ + // See if it's in the VFS. + return gVFS->getExists(uuid, LLAssetType::AT_SOUND); +} + + +void LLAudioEngine::startNextTransfer() +{ + //llinfos << "LLAudioEngine::startNextTransfer()" << llendl; + if (mCurrentTransfer.notNull() || getMuted()) + { + //llinfos << "Transfer in progress, aborting" << llendl; + return; + } + + // Get the ID for the next asset that we want to transfer. + // Pick one in the following order: + LLUUID asset_id; + S32 i; + LLAudioSource *asp = NULL; + LLAudioData *adp = NULL; + data_map::iterator data_iter; + + // Check all channels for currently playing sounds. + F32 max_pri = -1.f; + for (i = 0; i < MAX_CHANNELS; i++) + { + if (!mChannels[i]) + { + continue; + } + + asp = mChannels[i]->getSource(); + if (!asp) + { + continue; + } + if (asp->getPriority() <= max_pri) + { + continue; + } + + if (asp->getPriority() <= max_pri) + { + continue; + } + + adp = asp->getCurrentData(); + if (!adp) + { + continue; + } + + if (!adp->hasLocalData() && adp->hasValidData()) + { + asset_id = adp->getID(); + max_pri = asp->getPriority(); + } + } + + // Check all channels for currently queued sounds. + if (asset_id.isNull()) + { + max_pri = -1.f; + for (i = 0; i < MAX_CHANNELS; i++) + { + if (!mChannels[i]) + { + continue; + } + + LLAudioSource *asp; + asp = mChannels[i]->getSource(); + if (!asp) + { + continue; + } + + if (asp->getPriority() <= max_pri) + { + continue; + } + + adp = asp->getQueuedData(); + if (!adp) + { + continue; + } + + if (!adp->hasLocalData() && adp->hasValidData()) + { + asset_id = adp->getID(); + max_pri = asp->getPriority(); + } + } + } + + // Check all live channels for other sounds (preloads). + if (asset_id.isNull()) + { + max_pri = -1.f; + for (i = 0; i < MAX_CHANNELS; i++) + { + if (!mChannels[i]) + { + continue; + } + + LLAudioSource *asp; + asp = mChannels[i]->getSource(); + if (!asp) + { + continue; + } + + if (asp->getPriority() <= max_pri) + { + continue; + } + + + for (data_iter = asp->mPreloadMap.begin(); data_iter != asp->mPreloadMap.end(); data_iter++) + { + LLAudioData *adp = data_iter->second; + if (!adp) + { + continue; + } + + if (!adp->hasLocalData() && adp->hasValidData()) + { + asset_id = adp->getID(); + max_pri = asp->getPriority(); + } + } + } + } + + // Check all sources + if (asset_id.isNull()) + { + max_pri = -1.f; + source_map::iterator source_iter; + for (source_iter = mAllSources.begin(); source_iter != mAllSources.end(); source_iter++) + { + asp = source_iter->second; + if (!asp) + { + continue; + } + + if (asp->getPriority() <= max_pri) + { + continue; + } + + adp = asp->getCurrentData(); + if (adp && !adp->hasLocalData() && adp->hasValidData()) + { + asset_id = adp->getID(); + max_pri = asp->getPriority(); + continue; + } + + adp = asp->getQueuedData(); + if (adp && !adp->hasLocalData() && adp->hasValidData()) + { + asset_id = adp->getID(); + max_pri = asp->getPriority(); + continue; + } + + for (data_iter = asp->mPreloadMap.begin(); data_iter != asp->mPreloadMap.end(); data_iter++) + { + LLAudioData *adp = data_iter->second; + if (!adp) + { + continue; + } + + if (!adp->hasLocalData() && adp->hasValidData()) + { + asset_id = adp->getID(); + max_pri = asp->getPriority(); + break; + } + } + } + } + + if (asset_id.notNull()) + { + llinfos << "Getting asset data for: " << asset_id << llendl; + gAudiop->mCurrentTransfer = asset_id; + gAudiop->mCurrentTransferTimer.reset(); + gAssetStorage->getAssetData(asset_id, LLAssetType::AT_SOUND, + assetCallback, NULL); + } + else + { + //llinfos << "No pending transfers?" << llendl; + } +} + + +// static +void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status) +{ + if (result_code) + { + llinfos << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << llendl; + // Need to mark data as bad to avoid constant rerequests. + LLAudioData *adp = gAudiop->getAudioData(uuid); + if (adp) + { + adp->setHasValidData(false); + adp->setHasLocalData(false); + adp->setHasDecodedData(false); + } + } + else + { + LLAudioData *adp = gAudiop->getAudioData(uuid); + if (!adp) + { + // Should never happen + llwarns << "Got asset callback without audio data for " << uuid << llendl; + } + else + { + adp->setHasValidData(true); + adp->setHasLocalData(true); + gAudioDecodeMgrp->addDecodeRequest(uuid); + } + } + gAudiop->mCurrentTransfer = LLUUID::null; + gAudiop->startNextTransfer(); +} + + +// +// LLAudioSource implementation +// + + +LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain, const S32 type) +: mID(id), + mOwnerID(owner_id), + mPriority(0.f), + mGain(gain), + mSourceMuted(false), + mAmbient(false), + mLoop(false), + mSyncMaster(false), + mSyncSlave(false), + mQueueSounds(false), + mPlayedOnce(false), + mType(type), + mChannelp(NULL), + mCurrentDatap(NULL), + mQueuedDatap(NULL) +{ +} + + +LLAudioSource::~LLAudioSource() +{ + if (mChannelp) + { + // Stop playback of this sound + mChannelp->setSource(NULL); + mChannelp = NULL; + } +} + + +void LLAudioSource::setChannel(LLAudioChannel *channelp) +{ + if (channelp == mChannelp) + { + return; + } + + mChannelp = channelp; +} + + +void LLAudioSource::update() +{ + if (!getCurrentBuffer()) + { + if (getCurrentData()) + { + // Hack - try and load the sound. Will do this as a callback + // on decode later. + if (getCurrentData()->load()) + { + play(getCurrentData()->getID()); + } + } + } +} + +void LLAudioSource::updatePriority() +{ + if (isAmbient()) + { + mPriority = 1.f; + } + else if (isMuted()) + { + mPriority = 0.f; + } + else + { + // Priority is based on distance + LLVector3 dist_vec; + dist_vec.setVec(getPositionGlobal()); + dist_vec -= gAudiop->getListenerPos(); + F32 dist_squared = llmax(1.f, dist_vec.magVecSquared()); + + mPriority = mGain / dist_squared; + } +} + +bool LLAudioSource::setupChannel() +{ + LLAudioData *adp = getCurrentData(); + + if (!adp->getBuffer()) + { + // We're not ready to play back the sound yet, so don't try and allocate a channel for it. + //llwarns << "Aborting, no buffer" << llendl; + return false; + } + + + if (!mChannelp) + { + // Update the priority, in case we need to push out another channel. + updatePriority(); + + setChannel(gAudiop->getFreeChannel(getPriority())); + } + + if (!mChannelp) + { + // Ugh, we don't have any free channels. + // Now we have to reprioritize. + // For now, just don't play the sound. + //llwarns << "Aborting, no free channels" << llendl; + return false; + } + + mChannelp->setSource(this); + return true; +} + + +bool LLAudioSource::play(const LLUUID &audio_uuid) +{ + // Special abuse of play(); don't play a sound, but kill it. + if (audio_uuid.isNull()) + { + if (getChannel()) + { + getChannel()->setSource(NULL); + setChannel(NULL); + if (!isMuted()) + { + mCurrentDatap = NULL; + } + } + return false; + } + + // Reset our age timeout if someone attempts to play the source. + mAgeTimer.reset(); + + LLAudioData *adp = gAudiop->getAudioData(audio_uuid); + addAudioData(adp); + + if (isMuted()) + { + return false; + } + + bool has_buffer = gAudiop->updateBufferForData(adp, audio_uuid); + if (!has_buffer) + { + // Don't bother trying to set up a channel or anything, we don't have an audio buffer. + return false; + } + + if (!setupChannel()) + { + return false; + } + + if (isSyncSlave()) + { + // A sync slave, it doesn't start playing until it's synced up with the master. + // Flag this channel as waiting for sync, and return true. + getChannel()->setWaiting(true); + return true; + } + + getChannel()->play(); + return true; +} + + +bool LLAudioSource::isDone() const +{ + const F32 MAX_AGE = 60.f; + const F32 MAX_UNPLAYED_AGE = 15.f; + const F32 MAX_MUTED_AGE = 11.f; + + if (isLoop()) + { + // Looped sources never die on their own. + return false; + } + + if (hasPendingPreloads()) + { + return false; + } + + if (mQueuedDatap) + { + // Don't kill this sound if we've got something queued up to play. + return false; + } + + F32 elapsed = mAgeTimer.getElapsedTimeF32(); + + // This is a single-play source + if (!mChannelp) + { + if ((elapsed > (mSourceMuted ? MAX_MUTED_AGE : MAX_UNPLAYED_AGE)) || mPlayedOnce) + { + // We don't have a channel assigned, and it's been + // over 15 seconds since we tried to play it. Don't bother. + //llinfos << "No channel assigned, source is done" << llendl; + return true; + } + else + { + return false; + } + } + + if (mChannelp->isPlaying()) + { + if (elapsed > MAX_AGE) + { + // Arbitarily cut off non-looped sounds when they're old. + return true; + } + else + { + // Sound is still playing and we haven't timed out, don't kill it. + return false; + } + } + + if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce) + { + // The sound isn't playing back after 15 seconds or we're already done playing it, kill it. + return true; + } + + return false; +} + + +void LLAudioSource::addAudioData(LLAudioData *adp, const bool set_current) +{ + // Only handle a single piece of audio data associated with a source right now, + // until I implement prefetch. + if (set_current) + { + if (!mCurrentDatap) + { + mCurrentDatap = adp; + if (mChannelp) + { + mChannelp->updateBuffer(); + mChannelp->play(); + } + + // Make sure the audio engine knows that we want to request this sound. + gAudiop->startNextTransfer(); + return; + } + else if (mQueueSounds) + { + // If we have current data, and we're queuing, put + // the object onto the queue. + if (mQueuedDatap) + { + // We only queue one sound at a time, and it's a FIFO. + // Don't put it onto the queue. + return; + } + + if (adp == mCurrentDatap && isLoop()) + { + // No point in queueing the same sound if + // we're looping. + return; + } + mQueuedDatap = adp; + + // Make sure the audio engine knows that we want to request this sound. + gAudiop->startNextTransfer(); + } + else + { + if (mCurrentDatap != adp) + { + // Right now, if we're currently playing this sound in a channel, we + // update the buffer that the channel's associated with + // and play it. This may not be the correct behavior. + mCurrentDatap = adp; + if (mChannelp) + { + mChannelp->updateBuffer(); + mChannelp->play(); + } + // Make sure the audio engine knows that we want to request this sound. + gAudiop->startNextTransfer(); + } + } + } + else + { + // Add it to the preload list. + mPreloadMap[adp->getID()] = adp; + gAudiop->startNextTransfer(); + } +} + + +bool LLAudioSource::hasPendingPreloads() const +{ + // Check to see if we've got any preloads on deck for this source + data_map::const_iterator iter; + for (iter = mPreloadMap.begin(); iter != mPreloadMap.end(); iter++) + { + LLAudioData *adp = iter->second; + // note: a bad UUID will forever be !hasDecodedData() + // but also !hasValidData(), hence the check for hasValidData() + if (!adp->hasDecodedData() && adp->hasValidData()) + { + // This source is still waiting for a preload + return true; + } + } + + return false; +} + + +LLAudioData * LLAudioSource::getCurrentData() +{ + return mCurrentDatap; +} + +LLAudioData * LLAudioSource::getQueuedData() +{ + return mQueuedDatap; +} + +LLAudioBuffer * LLAudioSource::getCurrentBuffer() +{ + if (!mCurrentDatap) + { + return NULL; + } + + return mCurrentDatap->getBuffer(); +} + + + + +// +// LLAudioChannel implementation +// + + +LLAudioChannel::LLAudioChannel() : + mCurrentSourcep(NULL), + mCurrentBufferp(NULL), + mLoopedThisFrame(false), + mWaiting(false), + mSecondaryGain(1.0f) +{ +} + + +LLAudioChannel::~LLAudioChannel() +{ + // Need to disconnect any sources which are using this channel. + //llinfos << "Cleaning up audio channel" << llendl; + if (mCurrentSourcep) + { + mCurrentSourcep->setChannel(NULL); + } + mCurrentBufferp = NULL; +} + + +void LLAudioChannel::setSource(LLAudioSource *sourcep) +{ + //llinfos << this << ": setSource(" << sourcep << ")" << llendl; + + if (!sourcep) + { + // Clearing the source for this channel, don't need to do anything. + //llinfos << "Clearing source for channel" << llendl; + cleanup(); + mCurrentSourcep = NULL; + mWaiting = false; + return; + } + + if (sourcep == mCurrentSourcep) + { + // Don't reallocate the channel, this will make FMOD goofy. + //llinfos << "Calling setSource with same source!" << llendl; + } + + mCurrentSourcep = sourcep; + + + updateBuffer(); + update3DPosition(); +} + + +bool LLAudioChannel::updateBuffer() +{ + if (!mCurrentSourcep) + { + // This channel isn't associated with any source, nothing + // to be updated + return false; + } + + // Initialize the channel's gain setting for this sound. + if(gAudiop) + { + setSecondaryGain(gAudiop->getSecondaryGain(mCurrentSourcep->getType())); + } + + LLAudioBuffer *bufferp = mCurrentSourcep->getCurrentBuffer(); + if (bufferp == mCurrentBufferp) + { + if (bufferp) + { + // The source hasn't changed what buffer it's playing + bufferp->mLastUseTimer.reset(); + bufferp->mInUse = true; + } + return false; + } + + // + // The source changed what buffer it's playing. We need to clean up + // the existing channel + // + cleanup(); + + mCurrentBufferp = bufferp; + if (bufferp) + { + bufferp->mLastUseTimer.reset(); + bufferp->mInUse = true; + } + + if (!mCurrentBufferp) + { + // There's no new buffer to be played, so we just abort. + return false; + } + + return true; +} + + + + +// +// LLAudioData implementation +// + + +LLAudioData::LLAudioData(const LLUUID &uuid) : + mID(uuid), + mBufferp(NULL), + mHasLocalData(false), + mHasDecodedData(false), + mHasValidData(true) +{ + if (uuid.isNull()) + { + // This is a null sound. + return; + } + + if (gAudiop && gAudiop->hasDecodedFile(uuid)) + { + // Already have a decoded version, don't need to decode it. + mHasLocalData = true; + mHasDecodedData = true; + } + else if (gAssetStorage && gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND)) + { + mHasLocalData = true; + } +} + + +bool LLAudioData::load() +{ + static clock_t last_info = 0; + + // For now, just assume we're going to use one buffer per audiodata. + if (mBufferp) + { + // We already have this sound in a buffer, don't do anything. + llinfos << "Already have a buffer for this sound, don't bother loading!" << llendl; + return true; + } + + mBufferp = gAudiop->getFreeBuffer(); + if (!mBufferp) + { + // No free buffers, abort. + if (clock() - last_info > CLOCKS_PER_SEC) // Do not spam us with such messages + { + llinfos << "Not able to allocate a new audio buffer, aborting." << llendl; + last_info = clock(); + } + return false; + } + + std::string uuid_str; + std::string wav_path; + mID.toString(uuid_str); + wav_path= gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str) + ".dsf"; + + if (!mBufferp->loadWAV(wav_path)) + { + // Hrm. Right now, let's unset the buffer, since it's empty. + gAudiop->cleanupBuffer(mBufferp); + mBufferp = NULL; + + // Maybe it was removed by another instance. Send it to the preload queue. + gAudiop->preloadSound(mID); + + return false; + } + mBufferp->mAudioDatap = this; + return true; +} + + diff --git a/linden/indra/llaudio/llaudioengine.h b/linden/indra/llaudio/llaudioengine.h new file mode 100644 index 0000000..a1b240e --- /dev/null +++ b/linden/indra/llaudio/llaudioengine.h @@ -0,0 +1,457 @@ +/** + * @file audioengine.h + * @brief Definition of LLAudioEngine base class abstracting the audio support + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#ifndef LL_AUDIOENGINE_H +#define LL_AUDIOENGINE_H + +#include +#include + +#include "v3math.h" +#include "v3dmath.h" +#include "lltimer.h" +#include "lluuid.h" +#include "llframetimer.h" +#include "llassettype.h" + +#include "lllistener.h" + +const F32 LL_WIND_UPDATE_INTERVAL = 0.1f; +const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water +const F32 LL_WIND_UNDERWATER_CENTER_FREQ = 20.f; + +const F32 ATTACHED_OBJECT_TIMEOUT = 5.0f; +const F32 DEFAULT_MIN_DISTANCE = 2.0f; + +#define MAX_CHANNELS 30 +// Number of maximum rezzed objects with sounds + sounds without an object + UI sounds. +#define MAX_BUFFERS 100 + +// This define is intended to allow us to switch from os based wav +// file loading to vfs based wav file loading. The problem is that I +// am unconvinced that the LLWaveFile works for loading sounds from +// memory. So, until that is fixed up, changed, whatever, this remains +// undefined. +//#define USE_WAV_VFILE + +class LLVFS; + +class LLAudioSource; +class LLAudioData; +class LLAudioChannel; +class LLAudioChannelOpenAL; +class LLAudioBuffer; +class LLStreamingAudioInterface; + + +// +// LLAudioEngine definition +// + +class LLAudioEngine +{ + friend class LLAudioChannelOpenAL; // bleh. channel needs some listener methods. + +public: + enum LLAudioType + { + AUDIO_TYPE_NONE = 0, + AUDIO_TYPE_SFX = 1, + AUDIO_TYPE_UI = 2, + AUDIO_TYPE_AMBIENT = 3, + AUDIO_TYPE_GESTURE = 4, + AUDIO_TYPE_COUNT = 5 // last + }; + + LLAudioEngine(); + virtual ~LLAudioEngine(); + + // initialization/startup/shutdown + virtual bool init(const S32 num_channels, void *userdata); + virtual std::string getDriverName(bool verbose) = 0; + virtual void shutdown(); + + // Used by the mechanics of the engine + //virtual void processQueue(const LLUUID &sound_guid); + virtual void setListener(LLVector3 pos,LLVector3 vel,LLVector3 up,LLVector3 at); + virtual void updateWind(LLVector3 direction, F32 camera_height_above_water) = 0; + virtual void idle(F32 max_decode_time = 0.f); + virtual void updateChannels(); + + // + // "End user" functionality + // + virtual bool isWindEnabled(); + virtual void enableWind(bool state_b); + + // Use these for temporarily muting the audio system. + // Does not change buffers, initialization, etc. but + // stops playing new sounds. + void setMuted(bool muted); + bool getMuted() const { return mMuted; } +#ifdef USE_PLUGIN_MEDIA + LLPluginClassMedia* initializeMedia(const std::string& media_type); +#endif + F32 getMasterGain(); + void setMasterGain(F32 gain); + + F32 getSecondaryGain(S32 type); + void setSecondaryGain(S32 type, F32 gain); + + F32 getInternetStreamGain(); + + virtual void setDopplerFactor(F32 factor); + virtual F32 getDopplerFactor(); + virtual void setRolloffFactor(F32 factor); + virtual F32 getRolloffFactor(); + virtual void setMaxWindGain(F32 gain); + + + // Methods actually related to setting up and removing sounds + // Owner ID is the owner of the object making the request + void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, + const S32 type = LLAudioEngine::AUDIO_TYPE_NONE, + const LLVector3d &pos_global = LLVector3d::zero); + bool preloadSound(const LLUUID &id); + + void addAudioSource(LLAudioSource *asp); + void cleanupAudioSource(LLAudioSource *asp); + + LLAudioSource *findAudioSource(const LLUUID &source_id); + LLAudioData *getAudioData(const LLUUID &audio_uuid); + + // Internet stream implementation manipulation + LLStreamingAudioInterface *getStreamingAudioImpl(); + void setStreamingAudioImpl(LLStreamingAudioInterface *impl); + // Internet stream methods - these will call down into the *mStreamingAudioImpl if it exists + void startInternetStream(const std::string& url); + void stopInternetStream(); + void pauseInternetStream(int pause); + void updateInternetStream(); // expected to be called often + int isInternetStreamPlaying(); + // use a value from 0.0 to 1.0, inclusive + void setInternetStreamGain(F32 vol); + std::string getInternetStreamURL(); + + // For debugging usage + virtual LLVector3 getListenerPos(); + + LLAudioBuffer *getFreeBuffer(); // Get a free buffer, or flush an existing one if you have to. + LLAudioChannel *getFreeChannel(const F32 priority); // Get a free channel or flush an existing one if your priority is higher + void cleanupBuffer(LLAudioBuffer *bufferp); + + bool hasDecodedFile(const LLUUID &uuid); + bool hasLocalFile(const LLUUID &uuid); + + bool updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid = LLUUID::null); + + + // Asset callback when we're retrieved a sound from the asset server. + void startNextTransfer(); + static void assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status); + + friend class LLPipeline; // For debugging +public: + F32 mMaxWindGain; // Hack. Public to set before fade in? + +protected: + virtual LLAudioBuffer *createBuffer() = 0; + virtual LLAudioChannel *createChannel() = 0; + + virtual void initWind() = 0; + virtual void cleanupWind() = 0; + virtual void setInternalGain(F32 gain) = 0; + + void commitDeferredChanges(); + + virtual void allocateListener() = 0; + + + // listener methods + virtual void setListenerPos(LLVector3 vec); + virtual void setListenerVelocity(LLVector3 vec); + virtual void orientListener(LLVector3 up, LLVector3 at); + virtual void translateListener(LLVector3 vec); + + + F64 mapWindVecToGain(LLVector3 wind_vec); + F64 mapWindVecToPitch(LLVector3 wind_vec); + F64 mapWindVecToPan(LLVector3 wind_vec); + +protected: + LLListener *mListenerp; + + bool mMuted; + void* mUserData; + + S32 mLastStatus; + + S32 mNumChannels; + bool mEnableWind; + + LLUUID mCurrentTransfer; // Audio file currently being transferred by the system + LLFrameTimer mCurrentTransferTimer; + + // A list of all audio sources that are known to the viewer at this time. + // This is most likely a superset of the ones that we actually have audio + // data for, or are playing back. + typedef std::map source_map; + typedef std::map data_map; + + source_map mAllSources; + data_map mAllData; + + LLAudioChannel *mChannels[MAX_CHANNELS]; + + // Buffers needs to change into a different data structure, as the number of buffers + // that we have active should be limited by RAM usage, not count. + LLAudioBuffer *mBuffers[MAX_BUFFERS]; + + F32 mMasterGain; + F32 mInternalGain; // Actual gain set; either mMasterGain or 0 when mMuted is true. + F32 mSecondaryGain[AUDIO_TYPE_COUNT]; + + F32 mNextWindUpdate; + + LLFrameTimer mWindUpdateTimer; + +private: + void setDefaults(); + LLStreamingAudioInterface *mStreamingAudioImpl; +}; + + + + +// +// Standard audio source. Can be derived from for special sources, such as those attached to objects. +// + + +class LLAudioSource +{ +public: + // owner_id is the id of the agent responsible for making this sound + // play, for example, the owner of the object currently playing it + LLAudioSource(const LLUUID &id, const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE); + virtual ~LLAudioSource(); + + virtual void update(); // Update this audio source + void updatePriority(); + + void preload(const LLUUID &audio_id); // Only used for preloading UI sounds, now. + + void addAudioData(LLAudioData *adp, bool set_current = TRUE); + + void setAmbient(const bool ambient) { mAmbient = ambient; } + bool isAmbient() const { return mAmbient; } + + void setLoop(const bool loop) { mLoop = loop; } + bool isLoop() const { return mLoop; } + + void setSyncMaster(const bool master) { mSyncMaster = master; } + bool isSyncMaster() const { return mSyncMaster; } + + void setSyncSlave(const bool slave) { mSyncSlave = slave; } + bool isSyncSlave() const { return mSyncSlave; } + + void setQueueSounds(const bool queue) { mQueueSounds = queue; } + bool isQueueSounds() const { return mQueueSounds; } + + void setPlayedOnce(const bool played_once) { mPlayedOnce = played_once; } + + void setType(S32 type) { mType = type; } + S32 getType() { return mType; } + + void setPositionGlobal(const LLVector3d &position_global) { mPositionGlobal = position_global; } + LLVector3d getPositionGlobal() const { return mPositionGlobal; } + LLVector3 getVelocity() const { return mVelocity; } + F32 getPriority() const { return mPriority; } + + // Gain should always be clamped between 0 and 1. + F32 getGain() const { return mGain; } + virtual void setGain(const F32 gain) { mGain = llclamp(gain, 0.f, 1.f); } + + const LLUUID &getID() const { return mID; } + bool isDone() const; + bool isMuted() const { return mSourceMuted; } + + LLAudioData *getCurrentData(); + LLAudioData *getQueuedData(); + LLAudioBuffer *getCurrentBuffer(); + + bool setupChannel(); + bool play(const LLUUID &audio_id); // Start the audio source playing + + bool hasPendingPreloads() const; // Has preloads that haven't been done yet + + friend class LLAudioEngine; + friend class LLAudioChannel; +protected: + void setChannel(LLAudioChannel *channelp); + LLAudioChannel *getChannel() const { return mChannelp; } + +protected: + LLUUID mID; // The ID of the source is that of the object if it's attached to an object. + LLUUID mOwnerID; // owner of the object playing the sound + F32 mPriority; + F32 mGain; + bool mSourceMuted; + bool mAmbient; + bool mLoop; + bool mSyncMaster; + bool mSyncSlave; + bool mQueueSounds; + bool mPlayedOnce; + S32 mType; + LLVector3d mPositionGlobal; + LLVector3 mVelocity; + + //LLAudioSource *mSyncMasterp; // If we're a slave, the source that we're synced to. + LLAudioChannel *mChannelp; // If we're currently playing back, this is the channel that we're assigned to. + LLAudioData *mCurrentDatap; + LLAudioData *mQueuedDatap; + + typedef std::map data_map; + data_map mPreloadMap; + + LLFrameTimer mAgeTimer; +}; + + + + +// +// Generic metadata about a particular piece of audio data. +// The actual data is handled by the derived LLAudioBuffer classes which are +// derived for each audio engine. +// + + +class LLAudioData +{ +public: + LLAudioData(const LLUUID &uuid); + bool load(); + + LLUUID getID() const { return mID; } + LLAudioBuffer *getBuffer() const { return mBufferp; } + + bool hasLocalData() const { return mHasLocalData; } + bool hasDecodedData() const { return mHasDecodedData; } + bool hasValidData() const { return mHasValidData; } + + void setHasLocalData(const bool hld) { mHasLocalData = hld; } + void setHasDecodedData(const bool hdd) { mHasDecodedData = hdd; } + void setHasValidData(const bool hvd) { mHasValidData = hvd; } + + friend class LLAudioEngine; // Severe laziness, bad. + +protected: + LLUUID mID; + LLAudioBuffer *mBufferp; // If this data is being used by the audio system, a pointer to the buffer will be set here. + bool mHasLocalData; + bool mHasDecodedData; + bool mHasValidData; +}; + + +// +// Base class for an audio channel, i.e. a channel which is capable of playing back a sound. +// Management of channels is done generically, methods for actually manipulating the channel +// are derived for each audio engine. +// + + +class LLAudioChannel +{ +public: + LLAudioChannel(); + virtual ~LLAudioChannel(); + + virtual void setSource(LLAudioSource *sourcep); + LLAudioSource *getSource() const { return mCurrentSourcep; } + + void setSecondaryGain(F32 gain) { mSecondaryGain = gain; } + F32 getSecondaryGain() { return mSecondaryGain; } + + friend class LLAudioEngine; + friend class LLAudioSource; +protected: + virtual void play() = 0; + virtual void playSynced(LLAudioChannel *channelp) = 0; + virtual void cleanup() = 0; + virtual bool isPlaying() = 0; + void setWaiting(const bool waiting) { mWaiting = waiting; } + bool isWaiting() const { return mWaiting; } + + virtual bool updateBuffer(); // Check to see if the buffer associated with the source changed, and update if necessary. + virtual void update3DPosition() = 0; + virtual void updateLoop() = 0; // Update your loop/completion status, for use by queueing/syncing. +protected: + LLAudioSource *mCurrentSourcep; + LLAudioBuffer *mCurrentBufferp; + bool mLoopedThisFrame; + bool mWaiting; // Waiting for sync. + F32 mSecondaryGain; +}; + + + + +// Basically an interface class to the engine-specific implementation +// of audio data that's ready for playback. +// Will likely get more complex as we decide to do stuff like real streaming audio. + + +class LLAudioBuffer +{ +public: + virtual ~LLAudioBuffer() {}; + virtual bool loadWAV(const std::string& filename) = 0; + virtual U32 getLength() = 0; + + friend class LLAudioEngine; + friend class LLAudioChannel; + friend class LLAudioData; +protected: + bool mInUse; + LLAudioData *mAudioDatap; + LLFrameTimer mLastUseTimer; +}; + + + +extern LLAudioEngine* gAudiop; + +#endif diff --git a/linden/indra/llaudio/llaudioengine_fmod.cpp b/linden/indra/llaudio/llaudioengine_fmod.cpp new file mode 100644 index 0000000..85ae863 --- /dev/null +++ b/linden/indra/llaudio/llaudioengine_fmod.cpp @@ -0,0 +1,766 @@ +/** + * @file audioengine_fmod.cpp + * @brief Implementation of LLAudioEngine class abstracting the audio support as a FMOD 3D implementation + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llstreamingaudio.h" +#include "llstreamingaudio_fmod.h" + +#include "llaudioengine_fmod.h" +#include "lllistener_fmod.h" + +#include "llerror.h" +#include "llmath.h" +#include "llrand.h" + +#include "fmod.h" +#include "fmod_errors.h" +#include "lldir.h" +#include "llapr.h" + +#include "sound_ids.h" + + +extern "C" { + void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata); +} + +FSOUND_DSPUNIT *gWindDSP = NULL; + + +LLAudioEngine_FMOD::LLAudioEngine_FMOD() +{ + mInited = false; + mWindGen = NULL; +} + + +LLAudioEngine_FMOD::~LLAudioEngine_FMOD() +{ +} + + +bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) +{ + LLAudioEngine::init(num_channels, userdata); + + // Reserve one extra channel for the http stream. + if (!FSOUND_SetMinHardwareChannels(num_channels + 1)) + { + LL_WARNS("AppInit") << "FMOD::init[0](), error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; + } + + LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() initializing FMOD" << LL_ENDL; + + F32 version = FSOUND_GetVersion(); + if (version < FMOD_VERSION) + { + LL_WARNS("AppInit") << "Error : You are using the wrong FMOD version (" << version + << ")! You should be using FMOD " << FMOD_VERSION << LL_ENDL; + //return false; + } + + U32 fmod_flags = 0x0; + +#if LL_WINDOWS + // Windows needs to know which window is frontmost. + // This must be called before FSOUND_Init() per the FMOD docs. + // This could be used to let FMOD handle muting when we lose focus, + // but we don't actually want to do that because we want to distinguish + // between minimized and not-focused states. + if (!FSOUND_SetHWND(userdata)) + { + LL_WARNS("AppInit") << "Error setting FMOD window: " + << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; + return false; + } + // Play audio when we don't have focus. + // (For example, IM client on top of us.) + // This means we also try to play audio when minimized, + // so we manually handle muting in that case. JC + fmod_flags |= FSOUND_INIT_GLOBALFOCUS; +#endif + +#if LL_LINUX + // initialize the FMOD engine + + // This is a hack to use only FMOD's basic FPU mixer + // when the LL_VALGRIND environmental variable is set, + // otherwise valgrind will fall over on FMOD's MMX detection + if (getenv("LL_VALGRIND")) /*Flawfinder: ignore*/ + { + LL_INFOS("AppInit") << "Pacifying valgrind in FMOD init." << LL_ENDL; + FSOUND_SetMixer(FSOUND_MIXER_QUALITY_FPU); + } + + // If we don't set an output method, Linux FMOD always + // decides on OSS and fails otherwise. So we'll manually + // try ESD, then OSS, then ALSA. + // Why this order? See SL-13250, but in short, OSS emulated + // on top of ALSA is ironically more reliable than raw ALSA. + // Ack, and ESD has more reliable failure modes - but has worse + // latency - than all of them, so wins for now. + bool audio_ok = false; + + if (!audio_ok) + if (NULL == getenv("LL_BAD_FMOD_ESD")) /*Flawfinder: ignore*/ + { + LL_DEBUGS("AppInit") << "Trying ESD audio output..." << LL_ENDL; + if(FSOUND_SetOutput(FSOUND_OUTPUT_ESD) && + FSOUND_Init(44100, num_channels, fmod_flags)) + { + LL_DEBUGS("AppInit") << "ESD audio output initialized OKAY" + << LL_ENDL; + audio_ok = true; + } else { + LL_WARNS("AppInit") << "ESD audio output FAILED to initialize: " + << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; + } + } else { + LL_DEBUGS("AppInit") << "ESD audio output SKIPPED" << LL_ENDL; + } + + if (!audio_ok) + if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/ + { + LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL; + if(FSOUND_SetOutput(FSOUND_OUTPUT_OSS) && + FSOUND_Init(44100, num_channels, fmod_flags)) + { + LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL; + audio_ok = true; + } else { + LL_WARNS("AppInit") << "OSS audio output FAILED to initialize: " + << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; + } + } else { + LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; + } + + if (!audio_ok) + if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/ + { + LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; + if(FSOUND_SetOutput(FSOUND_OUTPUT_ALSA) && + FSOUND_Init(44100, num_channels, fmod_flags)) + { + LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; + audio_ok = true; + } else { + LL_WARNS("AppInit") << "ALSA audio output FAILED to initialize: " + << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; + } + } else { + LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL; + } + + if (!audio_ok) + { + LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; + return false; + } + + // On Linux, FMOD causes a SIGPIPE for some netstream error + // conditions (an FMOD bug); ignore SIGPIPE so it doesn't crash us. + // NOW FIXED in FMOD 3.x since 2006-10-01. + //signal(SIGPIPE, SIG_IGN); + + // We're interested in logging which output method we + // ended up with, for QA purposes. + switch (FSOUND_GetOutput()) + { + case FSOUND_OUTPUT_NOSOUND: LL_DEBUGS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; + case FSOUND_OUTPUT_OSS: LL_DEBUGS("AppInit") << "Audio output: OSS" << LL_ENDL; break; + case FSOUND_OUTPUT_ESD: LL_DEBUGS("AppInit") << "Audio output: ESD" << LL_ENDL; break; + case FSOUND_OUTPUT_ALSA: LL_DEBUGS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; + default: LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; + }; + +#else // LL_LINUX + + // initialize the FMOD engine + if (!FSOUND_Init(44100, num_channels, fmod_flags)) + { + LL_WARNS("AppInit") << "Error initializing FMOD: " + << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; + return false; + } + +#endif + + // set up our favourite FMOD-native streaming audio implementation if none has already been added + if (!getStreamingAudioImpl()) // no existing implementation added + setStreamingAudioImpl(new LLStreamingAudio_FMOD()); + + LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL; + + mInited = true; + + return true; +} + + +std::string LLAudioEngine_FMOD::getDriverName(bool verbose) +{ + if (verbose) + { + F32 version = FSOUND_GetVersion(); + return llformat("FMOD version %f", version); + } + else + { + return "FMOD"; + } +} + + +void LLAudioEngine_FMOD::allocateListener(void) +{ + mListenerp = (LLListener *) new LLListener_FMOD(); + if (!mListenerp) + { + llwarns << "Listener creation failed" << llendl; + } +} + + +void LLAudioEngine_FMOD::shutdown() +{ + if (gWindDSP) + { + FSOUND_DSP_SetActive(gWindDSP,false); + FSOUND_DSP_Free(gWindDSP); + } + + stopInternetStream(); + + LLAudioEngine::shutdown(); + + llinfos << "LLAudioEngine_FMOD::shutdown() closing FMOD" << llendl; + FSOUND_Close(); + llinfos << "LLAudioEngine_FMOD::shutdown() done closing FMOD" << llendl; + + delete mListenerp; + mListenerp = NULL; +} + + +LLAudioBuffer * LLAudioEngine_FMOD::createBuffer() +{ + return new LLAudioBufferFMOD(); +} + + +LLAudioChannel * LLAudioEngine_FMOD::createChannel() +{ + return new LLAudioChannelFMOD(); +} + + +void LLAudioEngine_FMOD::initWind() +{ + mWindGen = new LLWindGen; + + if (!gWindDSP) + { + gWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen); + } + if (gWindDSP) + { + FSOUND_DSP_SetActive(gWindDSP, true); + } + mNextWindUpdate = 0.0; +} + + +void LLAudioEngine_FMOD::cleanupWind() +{ + if (gWindDSP) + { + FSOUND_DSP_SetActive(gWindDSP, false); + FSOUND_DSP_Free(gWindDSP); + gWindDSP = NULL; + } + + delete mWindGen; + mWindGen = NULL; +} + + +//----------------------------------------------------------------------- +void LLAudioEngine_FMOD::updateWind(LLVector3 wind_vec, F32 camera_height_above_water) +{ + LLVector3 wind_pos; + F64 pitch; + F64 center_freq; + + if (!mEnableWind) + { + return; + } + + if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) + { + + // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) + // need to convert this to the conventional orientation DS3D and OpenAL use + // where +X = right, +Y = up, +Z = backwards + + wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); + + // cerr << "Wind update" << endl; + + pitch = 1.0 + mapWindVecToPitch(wind_vec); + center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); + + mWindGen->mTargetFreq = (F32)center_freq; + mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; + mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); + } +} + +/* +//----------------------------------------------------------------------- +void LLAudioEngine_FMOD::setSourceMinDistance(U16 source_num, F64 distance) +{ + if (!mInited) + { + return; + } + if (mBuffer[source_num]) + { + mMinDistance[source_num] = (F32) distance; + if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num])) + { + llwarns << "FMOD::setSourceMinDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; + } + } +} + +//----------------------------------------------------------------------- +void LLAudioEngine_FMOD::setSourceMaxDistance(U16 source_num, F64 distance) +{ + if (!mInited) + { + return; + } + if (mBuffer[source_num]) + { + mMaxDistance[source_num] = (F32) distance; + if (!FSOUND_Sample_SetMinMaxDistance(mBuffer[source_num],mMinDistance[source_num], mMaxDistance[source_num])) + { + llwarns << "FMOD::setSourceMaxDistance(" << source_num << "), error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; + } + } +} + +//----------------------------------------------------------------------- +void LLAudioEngine_FMOD::get3DParams(S32 source_num, S32 *volume, S32 *freq, S32 *inside, S32 *outside, LLVector3 *orient, S32 *out_volume, F32 *min_dist, F32 *max_dist) +{ + *volume = 0; + *freq = 0; + *inside = 0; + *outside = 0; + *orient = LLVector3::zero; + *out_volume = 0; + *min_dist = 0.f; + *max_dist = 0.f; +} + +*/ + + +//----------------------------------------------------------------------- +void LLAudioEngine_FMOD::setInternalGain(F32 gain) +{ + if (!mInited) + { + return; + } + + gain = llclamp( gain, 0.0f, 1.0f ); + FSOUND_SetSFXMasterVolume( llround( 255.0f * gain ) ); + + LLStreamingAudioInterface *saimpl = getStreamingAudioImpl(); + if ( saimpl ) + { + // fmod likes its streaming audio channel gain re-asserted after + // master volume change. + saimpl->setGain(saimpl->getGain()); + } +} + +// +// LLAudioChannelFMOD implementation +// + +LLAudioChannelFMOD::LLAudioChannelFMOD() : LLAudioChannel(), mChannelID(0), mLastSamplePos(0) +{ +} + + +LLAudioChannelFMOD::~LLAudioChannelFMOD() +{ + cleanup(); +} + + +bool LLAudioChannelFMOD::updateBuffer() +{ + if (LLAudioChannel::updateBuffer()) + { + // Base class update returned true, which means that we need to actually + // set up the channel for a different buffer. + + LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentSourcep->getCurrentBuffer(); + + // Grab the FMOD sample associated with the buffer + FSOUND_SAMPLE *samplep = bufferp->getSample(); + if (!samplep) + { + // This is bad, there should ALWAYS be a sample associated with a legit + // buffer. + llerrs << "No FMOD sample!" << llendl; + return false; + } + + + // Actually play the sound. Start it off paused so we can do all the necessary + // setup. + mChannelID = FSOUND_PlaySoundEx(FSOUND_FREE, samplep, FSOUND_DSP_GetSFXUnit(), true); + + //llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl; + } + + // If we have a source for the channel, we need to update its gain. + if (mCurrentSourcep) + { + // SJB: warnings can spam and hurt framerate, disabling + if (!FSOUND_SetVolume(mChannelID, llround(getSecondaryGain() * mCurrentSourcep->getGain() * 255.0f))) + { +// llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; + } + + if (!FSOUND_SetLoopMode(mChannelID, mCurrentSourcep->isLoop() ? FSOUND_LOOP_NORMAL : FSOUND_LOOP_OFF)) + { +// llwarns << "Channel " << mChannelID << "Source ID: " << mCurrentSourcep->getID() +// << " at " << mCurrentSourcep->getPositionGlobal() << llendl; +// llwarns << "LLAudioChannelFMOD::updateBuffer error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; + } + } + + return true; +} + + +void LLAudioChannelFMOD::update3DPosition() +{ + if (!mChannelID) + { + // We're not actually a live channel (i.e., we're not playing back anything) + return; + } + + LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentBufferp; + if (!bufferp) + { + // We don't have a buffer associated with us (should really have been picked up + // by the above if. + return; + } + + if (mCurrentSourcep->isAmbient()) + { + // Ambient sound, don't need to do any positional updates. + bufferp->set3DMode(false); + } + else + { + // Localized sound. Update the position and velocity of the sound. + bufferp->set3DMode(true); + + LLVector3 float_pos; + float_pos.setVec(mCurrentSourcep->getPositionGlobal()); + if (!FSOUND_3D_SetAttributes(mChannelID, float_pos.mV, mCurrentSourcep->getVelocity().mV)) + { + LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::update3DPosition error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; + } + } +} + + +void LLAudioChannelFMOD::updateLoop() +{ + if (!mChannelID) + { + // May want to clear up the loop/sample counters. + return; + } + + // + // Hack: We keep track of whether we looped or not by seeing when the + // sample position looks like it's going backwards. Not reliable; may + // yield false negatives. + // + U32 cur_pos = FSOUND_GetCurrentPosition(mChannelID); + if (cur_pos < (U32)mLastSamplePos) + { + mLoopedThisFrame = true; + } + mLastSamplePos = cur_pos; +} + + +void LLAudioChannelFMOD::cleanup() +{ + if (!mChannelID) + { + //llinfos << "Aborting cleanup with no channelID." << llendl; + return; + } + + //llinfos << "Cleaning up channel: " << mChannelID << llendl; + if (!FSOUND_StopSound(mChannelID)) + { + LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::cleanup error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; + } + + mCurrentBufferp = NULL; + mChannelID = 0; +} + + +void LLAudioChannelFMOD::play() +{ + if (!mChannelID) + { + llwarns << "Playing without a channelID, aborting" << llendl; + return; + } + + if (!FSOUND_SetPaused(mChannelID, false)) + { + llwarns << "LLAudioChannelFMOD::play error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; + } + getSource()->setPlayedOnce(true); +} + + +void LLAudioChannelFMOD::playSynced(LLAudioChannel *channelp) +{ + LLAudioChannelFMOD *fmod_channelp = (LLAudioChannelFMOD*)channelp; + if (!(fmod_channelp->mChannelID && mChannelID)) + { + // Don't have channels allocated to both the master and the slave + return; + } + + U32 position = FSOUND_GetCurrentPosition(fmod_channelp->mChannelID) % mCurrentBufferp->getLength(); + // Try to match the position of our sync master + if (!FSOUND_SetCurrentPosition(mChannelID, position)) + { + llwarns << "LLAudioChannelFMOD::playSynced unable to set current position" << llendl; + } + + // Start us playing + play(); +} + + +bool LLAudioChannelFMOD::isPlaying() +{ + if (!mChannelID) + { + return false; + } + + return FSOUND_IsPlaying(mChannelID) && (!FSOUND_GetPaused(mChannelID)); +} + + + +// +// LLAudioBufferFMOD implementation +// + + +LLAudioBufferFMOD::LLAudioBufferFMOD() +{ + mSamplep = NULL; +} + + +LLAudioBufferFMOD::~LLAudioBufferFMOD() +{ + if (mSamplep) + { + // Clean up the associated FMOD sample if it exists. + FSOUND_Sample_Free(mSamplep); + mSamplep = NULL; + } +} + + +bool LLAudioBufferFMOD::loadWAV(const std::string& filename) +{ + // Try to open a wav file from disk. This will eventually go away, as we don't + // really want to block doing this. + if (filename.empty()) + { + // invalid filename, abort. + return false; + } + + if (!LLAPRFile::isExist(filename, LL_APR_RPB)) + { + // File not found, abort. + return false; + } + + if (mSamplep) + { + // If there's already something loaded in this buffer, clean it up. + FSOUND_Sample_Free(mSamplep); + mSamplep = NULL; + } + + // Load up the wav file into an fmod sample +#if LL_WINDOWS + // MikeS. - Loading the sound file manually and then handing it over to FMOD, + // since FMOD uses posix IO internally, + // which doesn't work with unicode file paths. + LLFILE* sound_file = LLFile::fopen(filename,"rb"); /* Flawfinder: ignore */ + if (sound_file) + { + fseek(sound_file,0,SEEK_END); + U32 file_length = ftell(sound_file); //Find the length of the file by seeking to the end and getting the offset + size_t read_count; + fseek(sound_file,0,SEEK_SET); //Seek back to the beginning + char* buffer = new char[file_length]; + llassert(buffer); + read_count = fread((void*)buffer,file_length,1,sound_file);//Load it.. + if(ferror(sound_file)==0 && (read_count == 1)){//No read error, and we got 1 chunk of our size... + unsigned int mode_flags = FSOUND_LOOP_NORMAL | FSOUND_LOADMEMORY; + //FSOUND_16BITS | FSOUND_MONO | FSOUND_LOADMEMORY | FSOUND_LOOP_NORMAL; + mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, buffer, mode_flags , 0, file_length); + } + delete[] buffer; + fclose(sound_file); + } +#else + mSamplep = FSOUND_Sample_Load(FSOUND_UNMANAGED, filename.c_str(), FSOUND_LOOP_NORMAL, 0, 0); +#endif + + if (!mSamplep) + { + // We failed to load the file for some reason. + llwarns << "Could not load data '" << filename << "': " + << FMOD_ErrorString(FSOUND_GetError()) << llendl; + + // + // If we EVER want to load wav files provided by end users, we need + // to rethink this! + // + // file is probably corrupt - remove it. + LLFile::remove(filename); + return false; + } + + // Everything went well, return true + return true; +} + + +U32 LLAudioBufferFMOD::getLength() +{ + if (!mSamplep) + { + return 0; + } + + return FSOUND_Sample_GetLength(mSamplep); +} + + +void LLAudioBufferFMOD::set3DMode(bool use3d) +{ + U16 current_mode = FSOUND_Sample_GetMode(mSamplep); + + if (use3d) + { + if (!FSOUND_Sample_SetMode(mSamplep, (current_mode & (~FSOUND_2D)))) + { + llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; + } + } + else + { + if (!FSOUND_Sample_SetMode(mSamplep, current_mode | FSOUND_2D)) + { + llwarns << "LLAudioBufferFMOD::set3DMode error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; + } + } +} + + +void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata) +{ + // originalbuffer = fmod's original mixbuffer. + // newbuffer = the buffer passed from the previous DSP unit. + // length = length in samples at this mix time. + // param = user parameter passed through in FSOUND_DSP_Create. + // + // modify the buffer in some fashion + + LLWindGen *windgen = + (LLWindGen *)userdata; + U8 stride; + +#if LL_DARWIN + stride = sizeof(LLAudioEngine_FMOD::MIXBUFFERFORMAT); +#else + int mixertype = FSOUND_GetMixer(); + if (mixertype == FSOUND_MIXER_BLENDMODE || + mixertype == FSOUND_MIXER_QUALITY_FPU) + { + stride = 4; + } + else + { + stride = 2; + } +#endif + + newbuffer = windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT *)newbuffer, length, stride); + + return newbuffer; +} diff --git a/linden/indra/llaudio/llaudioengine_fmod.h b/linden/indra/llaudio/llaudioengine_fmod.h new file mode 100644 index 0000000..3968657 --- /dev/null +++ b/linden/indra/llaudio/llaudioengine_fmod.h @@ -0,0 +1,129 @@ +/** + * @file audioengine_fmod.h + * @brief Definition of LLAudioEngine class abstracting the audio + * support as a FMOD 3D implementation + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_AUDIOENGINE_FMOD_H +#define LL_AUDIOENGINE_FMOD_H + +#include "llaudioengine.h" +#include "lllistener_fmod.h" +#include "llwindgen.h" + +#include "fmod.h" + +class LLAudioStreamManagerFMOD; + +class LLAudioEngine_FMOD : public LLAudioEngine +{ +public: + LLAudioEngine_FMOD(); + virtual ~LLAudioEngine_FMOD(); + + // initialization/startup/shutdown + virtual bool init(const S32 num_channels, void *user_data); + virtual std::string getDriverName(bool verbose); + virtual void allocateListener(); + + virtual void shutdown(); + + /*virtual*/ void initWind(); + /*virtual*/ void cleanupWind(); + + /*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water); + +#if LL_DARWIN + typedef S32 MIXBUFFERFORMAT; +#else + typedef S16 MIXBUFFERFORMAT; +#endif + +protected: + /*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to. + /*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel. + + /*virtual*/ void setInternalGain(F32 gain); +protected: + static signed char F_CALLBACKAPI callbackMetaData(char* name, char* value, void* userdata); + + //F32 mMinDistance[MAX_BUFFERS]; + //F32 mMaxDistance[MAX_BUFFERS]; + + bool mInited; + + // On Windows, userdata is the HWND of the application window. + void* mUserData; + + LLWindGen *mWindGen; +}; + + +class LLAudioChannelFMOD : public LLAudioChannel +{ +public: + LLAudioChannelFMOD(); + virtual ~LLAudioChannelFMOD(); + +protected: + /*virtual*/ void play(); + /*virtual*/ void playSynced(LLAudioChannel *channelp); + /*virtual*/ void cleanup(); + /*virtual*/ bool isPlaying(); + + /*virtual*/ bool updateBuffer(); + /*virtual*/ void update3DPosition(); + /*virtual*/ void updateLoop(); + +protected: + int mChannelID; + S32 mLastSamplePos; +}; + + +class LLAudioBufferFMOD : public LLAudioBuffer +{ +public: + LLAudioBufferFMOD(); + virtual ~LLAudioBufferFMOD(); + + /*virtual*/ bool loadWAV(const std::string& filename); + /*virtual*/ U32 getLength(); + friend class LLAudioChannelFMOD; + + void set3DMode(bool use3d); +protected: + FSOUND_SAMPLE *getSample() { return mSamplep; } +protected: + FSOUND_SAMPLE *mSamplep; +}; + + +#endif // LL_AUDIOENGINE_FMOD_H diff --git a/linden/indra/llaudio/llaudioengine_openal.cpp b/linden/indra/llaudio/llaudioengine_openal.cpp new file mode 100644 index 0000000..99ab18e --- /dev/null +++ b/linden/indra/llaudio/llaudioengine_openal.cpp @@ -0,0 +1,546 @@ +/** + * @file audioengine_openal.cpp + * @brief implementation of audio engine using OpenAL + * support as a OpenAL 3D implementation + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "lldir.h" + +#include "llaudioengine_openal.h" +#include "lllistener_openal.h" + + +LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() + : + mWindGen(NULL), + mWindBuf(NULL), + mWindBufFreq(0), + mWindBufSamples(0), + mWindBufBytes(0), + mWindSource(AL_NONE), + mNumEmptyWindALBuffers(MAX_NUM_WIND_BUFFERS) +{ +} + +// virtual +LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL() +{ +} + +// virtual +bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata) +{ + mWindGen = NULL; + LLAudioEngine::init(num_channels, userdata); + + if(!alutInit(NULL, NULL)) + { + llwarns << "LLAudioEngine_OpenAL::init() ALUT initialization failed: " << alutGetErrorString (alutGetError ()) << llendl; + return false; + } + + llinfos << "LLAudioEngine_OpenAL::init() OpenAL successfully initialized" << llendl; + + llinfos << "OpenAL version: " + << ll_safe_string(alGetString(AL_VERSION)) << llendl; + llinfos << "OpenAL vendor: " + << ll_safe_string(alGetString(AL_VENDOR)) << llendl; + llinfos << "OpenAL renderer: " + << ll_safe_string(alGetString(AL_RENDERER)) << llendl; + + ALint major = alutGetMajorVersion (); + ALint minor = alutGetMinorVersion (); + llinfos << "ALUT version: " << major << "." << minor << llendl; + + ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext()); + + alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major); + alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor); + llinfos << "ALC version: " << major << "." << minor << llendl; + + llinfos << "ALC default device: " + << ll_safe_string(alcGetString(device, + ALC_DEFAULT_DEVICE_SPECIFIER)) + << llendl; + + return true; +} + +// virtual +std::string LLAudioEngine_OpenAL::getDriverName(bool verbose) +{ + ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext()); + std::ostringstream version; + + version << + "OpenAL"; + + if (verbose) + { + version << + ", version " << + ll_safe_string(alGetString(AL_VERSION)) << + " / " << + ll_safe_string(alGetString(AL_VENDOR)) << + " / " << + ll_safe_string(alGetString(AL_RENDERER)); + + if (device) + version << + ": " << + ll_safe_string(alcGetString(device, + ALC_DEFAULT_DEVICE_SPECIFIER)); + } + + return version.str(); +} + +// virtual +void LLAudioEngine_OpenAL::allocateListener() +{ + mListenerp = (LLListener *) new LLListener_OpenAL(); + if(!mListenerp) + { + llwarns << "LLAudioEngine_OpenAL::allocateListener() Listener creation failed" << llendl; + } +} + +// virtual +void LLAudioEngine_OpenAL::shutdown() +{ + llinfos << "About to LLAudioEngine::shutdown()" << llendl; + LLAudioEngine::shutdown(); + + llinfos << "About to alutExit()" << llendl; + if(!alutExit()) + { + llwarns << "Nuts." << llendl; + llwarns << "LLAudioEngine_OpenAL::shutdown() ALUT shutdown failed: " << alutGetErrorString (alutGetError ()) << llendl; + } + + llinfos << "LLAudioEngine_OpenAL::shutdown() OpenAL successfully shut down" << llendl; + + delete mListenerp; + mListenerp = NULL; +} + +LLAudioBuffer *LLAudioEngine_OpenAL::createBuffer() +{ + return new LLAudioBufferOpenAL(); +} + +LLAudioChannel *LLAudioEngine_OpenAL::createChannel() +{ + return new LLAudioChannelOpenAL(); +} + +void LLAudioEngine_OpenAL::setInternalGain(F32 gain) +{ + //llinfos << "LLAudioEngine_OpenAL::setInternalGain() Gain: " << gain << llendl; + alListenerf(AL_GAIN, gain); +} + +LLAudioChannelOpenAL::LLAudioChannelOpenAL() + : + mALSource(AL_NONE), + mLastSamplePos(0) +{ + alGenSources(1, &mALSource); +} + +LLAudioChannelOpenAL::~LLAudioChannelOpenAL() +{ + cleanup(); + alDeleteSources(1, &mALSource); +} + +void LLAudioChannelOpenAL::cleanup() +{ + alSourceStop(mALSource); + mCurrentBufferp = NULL; +} + +void LLAudioChannelOpenAL::play() +{ + if (mALSource == AL_NONE) + { + llwarns << "Playing without a mALSource, aborting" << llendl; + return; + } + + if(!isPlaying()) + { + alSourcePlay(mALSource); + getSource()->setPlayedOnce(true); + } +} + +void LLAudioChannelOpenAL::playSynced(LLAudioChannel *channelp) +{ + if (channelp) + { + LLAudioChannelOpenAL *masterchannelp = + (LLAudioChannelOpenAL*)channelp; + if (mALSource != AL_NONE && + masterchannelp->mALSource != AL_NONE) + { + // we have channels allocated to master and slave + ALfloat master_offset; + alGetSourcef(masterchannelp->mALSource, AL_SEC_OFFSET, + &master_offset); + + llinfos << "Syncing with master at " << master_offset + << "sec" << llendl; + // *TODO: detect when this fails, maybe use AL_SAMPLE_ + alSourcef(mALSource, AL_SEC_OFFSET, master_offset); + } + } + play(); +} + +bool LLAudioChannelOpenAL::isPlaying() +{ + if (mALSource != AL_NONE) + { + ALint state; + alGetSourcei(mALSource, AL_SOURCE_STATE, &state); + if(state == AL_PLAYING) + { + return true; + } + } + + return false; +} + +bool LLAudioChannelOpenAL::updateBuffer() +{ + if (LLAudioChannel::updateBuffer()) + { + // Base class update returned true, which means that we need to actually + // set up the source for a different buffer. + LLAudioBufferOpenAL *bufferp = (LLAudioBufferOpenAL *)mCurrentSourcep->getCurrentBuffer(); + ALuint buffer = bufferp->getBuffer(); + alSourcei(mALSource, AL_BUFFER, buffer); + mLastSamplePos = 0; + } + + if (mCurrentSourcep) + { + alSourcef(mALSource, AL_GAIN, + mCurrentSourcep->getGain() * getSecondaryGain()); + alSourcei(mALSource, AL_LOOPING, + mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE); + alSourcef(mALSource, AL_ROLLOFF_FACTOR, + gAudiop->mListenerp->getRolloffFactor()); + } + + return true; +} + + +void LLAudioChannelOpenAL::updateLoop() +{ + if (mALSource == AL_NONE) + { + return; + } + + // Hack: We keep track of whether we looped or not by seeing when the + // sample position looks like it's going backwards. Not reliable; may + // yield false negatives. + // + ALint cur_pos; + alGetSourcei(mALSource, AL_SAMPLE_OFFSET, &cur_pos); + if (cur_pos < mLastSamplePos) + { + mLoopedThisFrame = true; + } + mLastSamplePos = cur_pos; +} + + +void LLAudioChannelOpenAL::update3DPosition() +{ + if(!mCurrentSourcep) + { + return; + } + if (mCurrentSourcep->isAmbient()) + { + alSource3f(mALSource, AL_POSITION, 0.0, 0.0, 0.0); + alSource3f(mALSource, AL_VELOCITY, 0.0, 0.0, 0.0); + alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_TRUE); + } else { + LLVector3 float_pos; + float_pos.setVec(mCurrentSourcep->getPositionGlobal()); + alSourcefv(mALSource, AL_POSITION, float_pos.mV); + alSourcefv(mALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV); + alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_FALSE); + } + + alSourcef(mALSource, AL_GAIN, mCurrentSourcep->getGain() * getSecondaryGain()); +} + +LLAudioBufferOpenAL::LLAudioBufferOpenAL() +{ + mALBuffer = AL_NONE; +} + +LLAudioBufferOpenAL::~LLAudioBufferOpenAL() +{ + cleanup(); +} + +void LLAudioBufferOpenAL::cleanup() +{ + if(mALBuffer != AL_NONE) + { + alDeleteBuffers(1, &mALBuffer); + mALBuffer = AL_NONE; + } +} + +bool LLAudioBufferOpenAL::loadWAV(const std::string& filename) +{ + cleanup(); + mALBuffer = alutCreateBufferFromFile(filename.c_str()); + if(mALBuffer == AL_NONE) + { + ALenum error = alutGetError(); + if (gDirUtilp->fileExists(filename)) + { + llwarns << + "LLAudioBufferOpenAL::loadWAV() Error loading " + << filename + << " " << alutGetErrorString(error) << llendl; + } + else + { + // It's common for the file to not actually exist. + lldebugs << + "LLAudioBufferOpenAL::loadWAV() Error loading " + << filename + << " " << alutGetErrorString(error) << llendl; + } + return false; + } + + return true; +} + +U32 LLAudioBufferOpenAL::getLength() +{ + if(mALBuffer == AL_NONE) + { + return 0; + } + ALint length; + alGetBufferi(mALBuffer, AL_SIZE, &length); + return length / 2; // convert size in bytes to size in (16-bit) samples +} + +// ------------ + +void LLAudioEngine_OpenAL::initWind() +{ + ALenum error; + llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl; + + mNumEmptyWindALBuffers = MAX_NUM_WIND_BUFFERS; + + alGetError(); /* clear error */ + + alGenSources(1,&mWindSource); + + if((error=alGetError()) != AL_NO_ERROR) + { + llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind sources: "<; + + mWindBufFreq = mWindGen->getInputSamplingRate(); + mWindBufSamples = llceil(mWindBufFreq * WIND_BUFFER_SIZE_SEC); + mWindBufBytes = mWindBufSamples * 2 /*stereo*/ * sizeof(WIND_SAMPLE_T); + + mWindBuf = new WIND_SAMPLE_T [mWindBufSamples * 2 /*stereo*/]; + + if(mWindBuf==NULL) + { + llerrs << "LLAudioEngine_OpenAL::initWind() Error creating wind memory buffer" << llendl; + mEnableWind=false; + } + + llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl; +} + +void LLAudioEngine_OpenAL::cleanupWind() +{ + llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl; + + if (mWindSource != AL_NONE) + { + // detach and delete all outstanding buffers on the wind source + alSourceStop(mWindSource); + ALint processed; + alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed); + while (processed--) + { + ALuint buffer = AL_NONE; + alSourceUnqueueBuffers(mWindSource, 1, &buffer); + alDeleteBuffers(1, &buffer); + } + + // delete the wind source itself + alDeleteSources(1, &mWindSource); + + mWindSource = AL_NONE; + } + + delete[] mWindBuf; + mWindBuf = NULL; + + delete mWindGen; + mWindGen = NULL; +} + +void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude) +{ + LLVector3 wind_pos; + F64 pitch; + F64 center_freq; + ALenum error; + + if (!mEnableWind) + return; + + if(!mWindBuf) + return; + + if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) + { + + // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) + // need to convert this to the conventional orientation DS3D and OpenAL use + // where +X = right, +Y = up, +Z = backwards + + wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); + + pitch = 1.0 + mapWindVecToPitch(wind_vec); + center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); + + mWindGen->mTargetFreq = (F32)center_freq; + mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; + mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); + + alSourcei(mWindSource, AL_LOOPING, AL_FALSE); + alSource3f(mWindSource, AL_POSITION, 0.0, 0.0, 0.0); + alSource3f(mWindSource, AL_VELOCITY, 0.0, 0.0, 0.0); + alSourcef(mWindSource, AL_ROLLOFF_FACTOR, 0.0); + alSourcei(mWindSource, AL_SOURCE_RELATIVE, AL_TRUE); + } + + // ok lets make a wind buffer now + + ALint processed, queued, unprocessed; + alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed); + alGetSourcei(mWindSource, AL_BUFFERS_QUEUED, &queued); + unprocessed = queued - processed; + + // ensure that there are always at least 3x as many filled buffers + // queued as we managed to empty since last time. + mNumEmptyWindALBuffers = llmin(mNumEmptyWindALBuffers + processed * 3 - unprocessed, MAX_NUM_WIND_BUFFERS-unprocessed); + mNumEmptyWindALBuffers = llmax(mNumEmptyWindALBuffers, 0); + + //llinfos << "mNumEmptyWindALBuffers: " << mNumEmptyWindALBuffers <<" (" << unprocessed << ":" << processed << ")" << llendl; + + while(processed--) // unqueue old buffers + { + ALuint buffer; + ALenum error; + alGetError(); /* clear error */ + alSourceUnqueueBuffers(mWindSource, 1, &buffer); + error = alGetError(); + if(error != AL_NO_ERROR) + { + llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << llendl; + } + else + { + alDeleteBuffers(1, &buffer); + } + } + + unprocessed += mNumEmptyWindALBuffers; + while (mNumEmptyWindALBuffers > 0) // fill+queue new buffers + { + ALuint buffer; + alGetError(); /* clear error */ + alGenBuffers(1,&buffer); + if((error=alGetError()) != AL_NO_ERROR) + { + llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind buffer: " << error << llendl; + break; + } + + alBufferData(buffer, + AL_FORMAT_STEREO16, + mWindGen->windGenerate(mWindBuf, + mWindBufSamples, 2), + mWindBufBytes, + mWindBufFreq); + error = alGetError(); + if(error != AL_NO_ERROR) + { + llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (bufferdata) buffers" << llendl; + } + + alSourceQueueBuffers(mWindSource, 1, &buffer); + error = alGetError(); + if(error != AL_NO_ERROR) + { + llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (queuing) buffers" << llendl; + } + + --mNumEmptyWindALBuffers; + } + + ALint playing; + alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing); + if(playing != AL_PLAYING) + { + alSourcePlay(mWindSource); + + lldebugs << "Wind had stopped - probably ran out of buffers - restarting: " << (unprocessed+mNumEmptyWindALBuffers) << " now queued." << llendl; + } +} + diff --git a/linden/indra/llaudio/llaudioengine_openal.h b/linden/indra/llaudio/llaudioengine_openal.h new file mode 100644 index 0000000..5aca03e --- /dev/null +++ b/linden/indra/llaudio/llaudioengine_openal.h @@ -0,0 +1,114 @@ +/** + * @file audioengine_openal.cpp + * @brief implementation of audio engine using OpenAL + * support as a OpenAL 3D implementation + * + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#ifndef LL_AUDIOENGINE_OPENAL_H +#define LL_AUDIOENGINE_OPENAL_H + +#include "llaudioengine.h" +#include "lllistener_openal.h" +#include "llwindgen.h" + +class LLAudioEngine_OpenAL : public LLAudioEngine +{ + public: + LLAudioEngine_OpenAL(); + virtual ~LLAudioEngine_OpenAL(); + + virtual bool init(const S32 num_channels, void *user_data); + virtual std::string getDriverName(bool verbose); + virtual void allocateListener(); + + virtual void shutdown(); + + void setInternalGain(F32 gain); + + LLAudioBuffer* createBuffer(); + LLAudioChannel* createChannel(); + + /*virtual*/ void initWind(); + /*virtual*/ void cleanupWind(); + /*virtual*/ void updateWind(LLVector3 direction, F32 camera_altitude); + + private: + void * windDSP(void *newbuffer, int length); + typedef S16 WIND_SAMPLE_T; + LLWindGen *mWindGen; + S16 *mWindBuf; + U32 mWindBufFreq; + U32 mWindBufSamples; + U32 mWindBufBytes; + ALuint mWindSource; + int mNumEmptyWindALBuffers; + + static const int MAX_NUM_WIND_BUFFERS = 80; + static const float WIND_BUFFER_SIZE_SEC = 0.05f; // 1/20th sec +}; + +class LLAudioChannelOpenAL : public LLAudioChannel +{ + public: + LLAudioChannelOpenAL(); + virtual ~LLAudioChannelOpenAL(); + protected: + /*virtual*/ void play(); + /*virtual*/ void playSynced(LLAudioChannel *channelp); + /*virtual*/ void cleanup(); + /*virtual*/ bool isPlaying(); + + /*virtual*/ bool updateBuffer(); + /*virtual*/ void update3DPosition(); + /*virtual*/ void updateLoop(); + + ALuint mALSource; + ALint mLastSamplePos; +}; + +class LLAudioBufferOpenAL : public LLAudioBuffer{ + public: + LLAudioBufferOpenAL(); + virtual ~LLAudioBufferOpenAL(); + + bool loadWAV(const std::string& filename); + U32 getLength(); + + friend class LLAudioChannelOpenAL; + protected: + void cleanup(); + ALuint getBuffer() {return mALBuffer;} + + ALuint mALBuffer; +}; + +#endif diff --git a/linden/indra/llaudio/lllistener.cpp b/linden/indra/llaudio/lllistener.cpp new file mode 100644 index 0000000..846c6bc --- /dev/null +++ b/linden/indra/llaudio/lllistener.cpp @@ -0,0 +1,142 @@ +/** + * @file listener.cpp + * @brief Implementation of LISTENER class abstracting the audio support + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lllistener.h" + +#define DEFAULT_AT 0.0f,0.0f,-1.0f +#define DEFAULT_UP 0.0f,1.0f,0.0f + +//----------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------- +LLListener::LLListener() +{ + init(); +} + +//----------------------------------------------------------------------- +LLListener::~LLListener() +{ +} + +//----------------------------------------------------------------------- +void LLListener::init(void) +{ + mPosition.zeroVec(); + mListenAt.setVec(DEFAULT_AT); + mListenUp.setVec(DEFAULT_UP); + mVelocity.zeroVec(); +} + +//----------------------------------------------------------------------- +void LLListener::translate(LLVector3 offset) +{ + mPosition += offset; +} + +//----------------------------------------------------------------------- +void LLListener::setPosition(LLVector3 pos) +{ + mPosition = pos; +} + +//----------------------------------------------------------------------- +LLVector3 LLListener::getPosition(void) +{ + return(mPosition); +} + +//----------------------------------------------------------------------- +LLVector3 LLListener::getAt(void) +{ + return(mListenAt); +} + +//----------------------------------------------------------------------- +LLVector3 LLListener::getUp(void) +{ + return(mListenUp); +} + +//----------------------------------------------------------------------- +void LLListener::setVelocity(LLVector3 vel) +{ + mVelocity = vel; +} + +//----------------------------------------------------------------------- +void LLListener::orient(LLVector3 up, LLVector3 at) +{ + mListenUp = up; + mListenAt = at; +} + +//----------------------------------------------------------------------- +void LLListener::set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at) +{ + mPosition = pos; + mVelocity = vel; + + setPosition(pos); + setVelocity(vel); + orient(up,at); +} + +//----------------------------------------------------------------------- +void LLListener::setDopplerFactor(F32 factor) +{ +} + +//----------------------------------------------------------------------- +F32 LLListener::getDopplerFactor() +{ + return (1.f); +} + +//----------------------------------------------------------------------- +void LLListener::setRolloffFactor(F32 factor) +{ +} + +//----------------------------------------------------------------------- +F32 LLListener::getRolloffFactor() +{ + return (1.f); +} + +//----------------------------------------------------------------------- +void LLListener::commitDeferredChanges() +{ +} + diff --git a/linden/indra/llaudio/lllistener.h b/linden/indra/llaudio/lllistener.h new file mode 100644 index 0000000..e94fbe8 --- /dev/null +++ b/linden/indra/llaudio/lllistener.h @@ -0,0 +1,78 @@ +/** + * @file listener.h + * @brief Description of LISTENER base class abstracting the audio support. + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LISTENER_H +#define LL_LISTENER_H + +#include "v3math.h" + +class LLListener +{ + private: + protected: + LLVector3 mPosition; + LLVector3 mVelocity; + LLVector3 mListenAt; + LLVector3 mListenUp; + + public: + + private: + protected: + public: + LLListener(); + virtual ~LLListener(); + virtual void init(); + + virtual void set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at); + + virtual void setPosition(LLVector3 pos); + virtual void setVelocity(LLVector3 vel); + + virtual void orient(LLVector3 up, LLVector3 at); + virtual void translate(LLVector3 offset); + + virtual void setDopplerFactor(F32 factor); + virtual void setRolloffFactor(F32 factor); + + virtual LLVector3 getPosition(); + virtual LLVector3 getAt(); + virtual LLVector3 getUp(); + + virtual F32 getDopplerFactor(); + virtual F32 getRolloffFactor(); + + virtual void commitDeferredChanges(); +}; + +#endif + diff --git a/linden/indra/llaudio/lllistener_ds3d.h b/linden/indra/llaudio/lllistener_ds3d.h new file mode 100644 index 0000000..1ff9c17 --- /dev/null +++ b/linden/indra/llaudio/lllistener_ds3d.h @@ -0,0 +1,74 @@ +/** + * @file listener_ds3d.h + * @brief Description of LISTENER class abstracting the audio support + * as a DirectSound 3D implementation (windows only) + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LISTENER_DS3D_H +#define LL_LISTENER_DS3D_H + +#include "lllistener.h" + +#include +#include +#include + +class LLListener_DS3D : public LLListener +{ + private: + protected: + IDirectSound3DListener8 *m3DListener; + public: + + private: + protected: + public: + LLListener_DS3D(); + virtual ~LLListener_DS3D(); + virtual void init(); + + virtual void setDS3DLPtr (IDirectSound3DListener8 *listener_p); + + virtual void translate(LLVector3 offset); + virtual void setPosition(LLVector3 pos); + virtual void setVelocity(LLVector3 vel); + virtual void orient(LLVector3 up, LLVector3 at); + + virtual void setDopplerFactor(F32 factor); + virtual F32 getDopplerFactor(); + virtual void setRolloffFactor(F32 factor); + virtual F32 getRolloffFactor(); + + virtual void commitDeferredChanges(); +}; + +#endif + + diff --git a/linden/indra/llaudio/lllistener_fmod.cpp b/linden/indra/llaudio/lllistener_fmod.cpp new file mode 100644 index 0000000..57ad461 --- /dev/null +++ b/linden/indra/llaudio/lllistener_fmod.cpp @@ -0,0 +1,131 @@ +/** + * @file listener_fmod.cpp + * @brief implementation of LISTENER class abstracting the audio + * support as a FMOD 3D implementation (windows only) + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llaudioengine.h" +#include "lllistener_fmod.h" +#include "fmod.h" + +//----------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------- +LLListener_FMOD::LLListener_FMOD() +{ + init(); +} + +//----------------------------------------------------------------------- +LLListener_FMOD::~LLListener_FMOD() +{ +} + +//----------------------------------------------------------------------- +void LLListener_FMOD::init(void) +{ + // do inherited + LLListener::init(); + mDopplerFactor = 1.0f; + mRolloffFactor = 1.0f; +} + +//----------------------------------------------------------------------- +void LLListener_FMOD::translate(LLVector3 offset) +{ + LLListener::translate(offset); + + FSOUND_3D_Listener_SetAttributes(mPosition.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); +} + +//----------------------------------------------------------------------- +void LLListener_FMOD::setPosition(LLVector3 pos) +{ + LLListener::setPosition(pos); + + FSOUND_3D_Listener_SetAttributes(pos.mV, NULL, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); +} + +//----------------------------------------------------------------------- +void LLListener_FMOD::setVelocity(LLVector3 vel) +{ + LLListener::setVelocity(vel); + + FSOUND_3D_Listener_SetAttributes(NULL, vel.mV, mListenAt.mV[0],mListenAt.mV[1],mListenAt.mV[2], mListenUp.mV[0],mListenUp.mV[1],mListenUp.mV[2]); +} + +//----------------------------------------------------------------------- +void LLListener_FMOD::orient(LLVector3 up, LLVector3 at) +{ + LLListener::orient(up, at); + + // Welcome to the transition between right and left + // (coordinate systems, that is) + // Leaving the at vector alone results in a L/R reversal + // since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed + at = -at; + + FSOUND_3D_Listener_SetAttributes(NULL, NULL, at.mV[0],at.mV[1],at.mV[2], up.mV[0],up.mV[1],up.mV[2]); +} + +//----------------------------------------------------------------------- +void LLListener_FMOD::commitDeferredChanges() +{ + FSOUND_Update(); +} + + +void LLListener_FMOD::setRolloffFactor(F32 factor) +{ + mRolloffFactor = factor; + FSOUND_3D_SetRolloffFactor(factor); +} + + +F32 LLListener_FMOD::getRolloffFactor() +{ + return mRolloffFactor; +} + + +void LLListener_FMOD::setDopplerFactor(F32 factor) +{ + mDopplerFactor = factor; + FSOUND_3D_SetDopplerFactor(factor); +} + + +F32 LLListener_FMOD::getDopplerFactor() +{ + return mDopplerFactor; +} + + diff --git a/linden/indra/llaudio/lllistener_fmod.h b/linden/indra/llaudio/lllistener_fmod.h new file mode 100644 index 0000000..5a48ec8 --- /dev/null +++ b/linden/indra/llaudio/lllistener_fmod.h @@ -0,0 +1,64 @@ +/** + * @file listener_fmod.h + * @brief Description of LISTENER class abstracting the audio support + * as an FMOD 3D implementation (windows and Linux) + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LISTENER_FMOD_H +#define LL_LISTENER_FMOD_H + +#include "lllistener.h" + +class LLListener_FMOD : public LLListener +{ + public: + LLListener_FMOD(); + virtual ~LLListener_FMOD(); + virtual void init(); + + virtual void translate(LLVector3 offset); + virtual void setPosition(LLVector3 pos); + virtual void setVelocity(LLVector3 vel); + virtual void orient(LLVector3 up, LLVector3 at); + virtual void commitDeferredChanges(); + + virtual void setDopplerFactor(F32 factor); + virtual F32 getDopplerFactor(); + virtual void setRolloffFactor(F32 factor); + virtual F32 getRolloffFactor(); + + protected: + F32 mDopplerFactor; + F32 mRolloffFactor; +}; + +#endif + + diff --git a/linden/indra/llaudio/lllistener_openal.cpp b/linden/indra/llaudio/lllistener_openal.cpp new file mode 100644 index 0000000..a96ebd5 --- /dev/null +++ b/linden/indra/llaudio/lllistener_openal.cpp @@ -0,0 +1,116 @@ +/** + * @file audioengine_openal.cpp + * @brief implementation of audio engine using OpenAL + * support as a OpenAL 3D implementation + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llaudioengine.h" + +#include "lllistener_openal.h" + +LLListener_OpenAL::LLListener_OpenAL() +{ + init(); +} + +LLListener_OpenAL::~LLListener_OpenAL() +{ +} + +void LLListener_OpenAL::translate(LLVector3 offset) +{ + //llinfos << "LLListener_OpenAL::translate() : " << offset << llendl; + LLListener::translate(offset); +} + +void LLListener_OpenAL::setPosition(LLVector3 pos) +{ + //llinfos << "LLListener_OpenAL::setPosition() : " << pos << llendl; + LLListener::setPosition(pos); +} + +void LLListener_OpenAL::setVelocity(LLVector3 vel) +{ + LLListener::setVelocity(vel); +} + +void LLListener_OpenAL::orient(LLVector3 up, LLVector3 at) +{ + //llinfos << "LLListener_OpenAL::orient() up: " << up << " at: " << at << llendl; + LLListener::orient(up, at); +} + +void LLListener_OpenAL::commitDeferredChanges() +{ + ALfloat orientation[6]; + orientation[0] = mListenAt.mV[0]; + orientation[1] = mListenAt.mV[1]; + orientation[2] = mListenAt.mV[2]; + orientation[3] = mListenUp.mV[0]; + orientation[4] = mListenUp.mV[1]; + orientation[5] = mListenUp.mV[2]; + + ALfloat velocity[3]; + velocity[0] = mVelocity.mV[0]; + velocity[1] = mVelocity.mV[1]; + velocity[2] = mVelocity.mV[2]; + + alListenerfv(AL_ORIENTATION, orientation); + alListenerfv(AL_POSITION, mPosition.mV); + alListenerfv(AL_VELOCITY, velocity); +} + +void LLListener_OpenAL::setDopplerFactor(F32 factor) +{ + //llinfos << "LLListener_OpenAL::setDopplerFactor() : " << factor << llendl; + alDopplerFactor(factor); +} + +F32 LLListener_OpenAL::getDopplerFactor() +{ + ALfloat factor; + factor = alGetFloat(AL_DOPPLER_FACTOR); + //llinfos << "LLListener_OpenAL::getDopplerFactor() : " << factor << llendl; + return factor; +} + + +void LLListener_OpenAL::setRolloffFactor(F32 factor) +{ + mRolloffFactor = factor; +} + +F32 LLListener_OpenAL::getRolloffFactor() +{ + return mRolloffFactor; +} + + diff --git a/linden/indra/llaudio/lllistener_openal.h b/linden/indra/llaudio/lllistener_openal.h new file mode 100644 index 0000000..0dfeea5 --- /dev/null +++ b/linden/indra/llaudio/lllistener_openal.h @@ -0,0 +1,64 @@ +/** + * @file listener_openal.h + * @brief Description of LISTENER class abstracting the audio support + * as an OpenAL implementation + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LISTENER_OPENAL_H +#define LL_LISTENER_OPENAL_H + +#include "lllistener.h" + +#include "AL/al.h" +#include "AL/alut.h" + +class LLListener_OpenAL : public LLListener +{ + public: + LLListener_OpenAL(); + virtual ~LLListener_OpenAL(); + + virtual void translate(LLVector3 offset); + virtual void setPosition(LLVector3 pos); + virtual void setVelocity(LLVector3 vel); + virtual void orient(LLVector3 up, LLVector3 at); + virtual void commitDeferredChanges(); + + virtual void setDopplerFactor(F32 factor); + virtual F32 getDopplerFactor(); + virtual void setRolloffFactor(F32 factor); + virtual F32 getRolloffFactor(); + + protected: + F32 mRolloffFactor; +}; + +#endif + diff --git a/linden/indra/llaudio/llstreamingaudio.h b/linden/indra/llaudio/llstreamingaudio.h new file mode 100644 index 0000000..aa89e6a --- /dev/null +++ b/linden/indra/llaudio/llstreamingaudio.h @@ -0,0 +1,56 @@ +/** + * @file streamingaudio.h + * @author Tofu Linden + * @brief Definition of LLStreamingAudioInterface base class abstracting the streaming audio interface + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_STREAMINGAUDIO_H +#define LL_STREAMINGAUDIO_H + +#include "stdtypes.h" // from llcommon + +// Entirely abstract. Based exactly on the historic API. +class LLStreamingAudioInterface +{ + public: + virtual ~LLStreamingAudioInterface() {} + + virtual void start(const std::string& url) = 0; + virtual void stop() = 0; + virtual void pause(int pause) = 0; + virtual void update() = 0; + virtual int isPlaying() = 0; + // use a value from 0.0 to 1.0, inclusive + virtual void setGain(F32 vol) = 0; + virtual F32 getGain() = 0; + virtual std::string getURL() = 0; +}; + +#endif // LL_STREAMINGAUDIO_H diff --git a/linden/indra/llaudio/llstreamingaudio_fmod.cpp b/linden/indra/llaudio/llstreamingaudio_fmod.cpp new file mode 100644 index 0000000..a71a872 --- /dev/null +++ b/linden/indra/llaudio/llstreamingaudio_fmod.cpp @@ -0,0 +1,362 @@ +/** + * @file streamingaudio_fmod.cpp + * @brief LLStreamingAudio_FMOD implementation + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llmath.h" + +#include "fmod.h" +#include "fmod_errors.h" + +#include "llstreamingaudio_fmod.h" + + +class LLAudioStreamManagerFMOD +{ +public: + LLAudioStreamManagerFMOD(const std::string& url); + int startStream(); + bool stopStream(); // Returns true if the stream was successfully stopped. + bool ready(); + + const std::string& getURL() { return mInternetStreamURL; } + + int getOpenState(); +protected: + FSOUND_STREAM* mInternetStream; + bool mReady; + + std::string mInternetStreamURL; +}; + + + +//--------------------------------------------------------------------------- +// Internet Streaming +//--------------------------------------------------------------------------- +LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() : + mCurrentInternetStreamp(NULL), + mFMODInternetStreamChannel(-1), + mGain(1.0f) +{ + // Number of milliseconds of audio to buffer for the audio card. + // Must be larger than the usual Second Life frame stutter time. + FSOUND_Stream_SetBufferSize(200); + + // Here's where we set the size of the network buffer and some buffering + // parameters. In this case we want a network buffer of 16k, we want it + // to prebuffer 40% of that when we first connect, and we want it + // to rebuffer 80% of that whenever we encounter a buffer underrun. + + // Leave the net buffer properties at the default. + //FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80); +} + + +LLStreamingAudio_FMOD::~LLStreamingAudio_FMOD() +{ + // nothing interesting/safe to do. +} + + +void LLStreamingAudio_FMOD::start(const std::string& url) +{ + //if (!mInited) + //{ + // llwarns << "startInternetStream before audio initialized" << llendl; + // return; + //} + + // "stop" stream but don't clear url, etc. in case url == mInternetStreamURL + stop(); + + if (!url.empty()) + { + llinfos << "Starting internet stream: " << url << llendl; + mCurrentInternetStreamp = new LLAudioStreamManagerFMOD(url); + mURL = url; + } + else + { + llinfos << "Set internet stream to null" << llendl; + mURL.clear(); + } +} + + +void LLStreamingAudio_FMOD::update() +{ + // Kill dead internet streams, if possible + std::list::iterator iter; + for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();) + { + LLAudioStreamManagerFMOD *streamp = *iter; + if (streamp->stopStream()) + { + llinfos << "Closed dead stream" << llendl; + delete streamp; + mDeadStreams.erase(iter++); + } + else + { + iter++; + } + } + + // Don't do anything if there are no streams playing + if (!mCurrentInternetStreamp) + { + return; + } + + int open_state = mCurrentInternetStreamp->getOpenState(); + + if (!open_state) + { + // Stream is live + + // start the stream if it's ready + if (mFMODInternetStreamChannel < 0) + { + mFMODInternetStreamChannel = mCurrentInternetStreamp->startStream(); + + if (mFMODInternetStreamChannel != -1) + { + // Reset volume to previously set volume + setGain(getGain()); + FSOUND_SetPaused(mFMODInternetStreamChannel, false); + } + } + } + + switch(open_state) + { + default: + case 0: + // success + break; + case -1: + // stream handle is invalid + llwarns << "InternetStream - invalid handle" << llendl; + stop(); + return; + case -2: + // opening + break; + case -3: + // failed to open, file not found, perhaps + llwarns << "InternetSteam - failed to open" << llendl; + stop(); + return; + case -4: + // connecting + break; + case -5: + // buffering + break; + } + +} + +void LLStreamingAudio_FMOD::stop() +{ + if (mFMODInternetStreamChannel != -1) + { + FSOUND_SetPaused(mFMODInternetStreamChannel, true); + FSOUND_SetPriority(mFMODInternetStreamChannel, 0); + mFMODInternetStreamChannel = -1; + } + + if (mCurrentInternetStreamp) + { + llinfos << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << llendl; + if (mCurrentInternetStreamp->stopStream()) + { + delete mCurrentInternetStreamp; + } + else + { + llwarns << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << llendl; + mDeadStreams.push_back(mCurrentInternetStreamp); + } + mCurrentInternetStreamp = NULL; + //mURL.clear(); + } +} + +void LLStreamingAudio_FMOD::pause(int pauseopt) +{ + if (pauseopt < 0) + { + pauseopt = mCurrentInternetStreamp ? 1 : 0; + } + + if (pauseopt) + { + if (mCurrentInternetStreamp) + { + stop(); + } + } + else + { + start(getURL()); + } +} + + +// A stream is "playing" if it has been requested to start. That +// doesn't necessarily mean audio is coming out of the speakers. +int LLStreamingAudio_FMOD::isPlaying() +{ + if (mCurrentInternetStreamp) + { + return 1; // Active and playing + } + else if (!mURL.empty()) + { + return 2; // "Paused" + } + else + { + return 0; + } +} + + +F32 LLStreamingAudio_FMOD::getGain() +{ + return mGain; +} + + +std::string LLStreamingAudio_FMOD::getURL() +{ + return mURL; +} + + +void LLStreamingAudio_FMOD::setGain(F32 vol) +{ + mGain = vol; + + if (mFMODInternetStreamChannel != -1) + { + vol = llclamp(vol, 0.f, 1.f); + int vol_int = llround(vol * 255.f); + FSOUND_SetVolumeAbsolute(mFMODInternetStreamChannel, vol_int); + } +} + + +/////////////////////////////////////////////////////// +// manager of possibly-multiple internet audio streams + +LLAudioStreamManagerFMOD::LLAudioStreamManagerFMOD(const std::string& url) : + mInternetStream(NULL), + mReady(false) +{ + mInternetStreamURL = url; + mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0); + if (!mInternetStream) + { + llwarns << "Couldn't open fmod stream, error " + << FMOD_ErrorString(FSOUND_GetError()) + << llendl; + mReady = false; + return; + } + + mReady = true; +} + +int LLAudioStreamManagerFMOD::startStream() +{ + // We need a live and opened stream before we try and play it. + if (!mInternetStream || getOpenState()) + { + llwarns << "No internet stream to start playing!" << llendl; + return -1; + } + + // Make sure the stream is set to 2D mode. + FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D); + + return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, true); +} + +bool LLAudioStreamManagerFMOD::stopStream() +{ + if (mInternetStream) + { + int read_percent = 0; + int status = 0; + int bitrate = 0; + unsigned int flags = 0x0; + FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags); + + bool close = true; + switch (status) + { + case FSOUND_STREAM_NET_CONNECTING: + close = false; + break; + case FSOUND_STREAM_NET_NOTCONNECTED: + case FSOUND_STREAM_NET_BUFFERING: + case FSOUND_STREAM_NET_READY: + case FSOUND_STREAM_NET_ERROR: + default: + close = true; + } + + if (close) + { + FSOUND_Stream_Close(mInternetStream); + mInternetStream = NULL; + return true; + } + else + { + return false; + } + } + else + { + return true; + } +} + +int LLAudioStreamManagerFMOD::getOpenState() +{ + int open_state = FSOUND_Stream_GetOpenState(mInternetStream); + return open_state; +} diff --git a/linden/indra/llaudio/llstreamingaudio_fmod.h b/linden/indra/llaudio/llstreamingaudio_fmod.h new file mode 100644 index 0000000..968ab53 --- /dev/null +++ b/linden/indra/llaudio/llstreamingaudio_fmod.h @@ -0,0 +1,68 @@ +/** + * @file streamingaudio_fmod.h + * @author Tofu Linden + * @brief Definition of LLStreamingAudio_FMOD implementation + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_STREAMINGAUDIO_FMOD_H +#define LL_STREAMINGAUDIO_FMOD_H + +#include "stdtypes.h" // from llcommon + +#include "llstreamingaudio.h" + +class LLAudioStreamManagerFMOD; + +class LLStreamingAudio_FMOD : public LLStreamingAudioInterface +{ + public: + LLStreamingAudio_FMOD(); + /*virtual*/ ~LLStreamingAudio_FMOD(); + + /*virtual*/ void start(const std::string& url); + /*virtual*/ void stop(); + /*virtual*/ void pause(int pause); + /*virtual*/ void update(); + /*virtual*/ int isPlaying(); + /*virtual*/ void setGain(F32 vol); + /*virtual*/ F32 getGain(); + /*virtual*/ std::string getURL(); + +private: + LLAudioStreamManagerFMOD *mCurrentInternetStreamp; + int mFMODInternetStreamChannel; + std::list mDeadStreams; + + std::string mURL; + F32 mGain; +}; + + +#endif // LL_STREAMINGAUDIO_FMOD_H diff --git a/linden/indra/llaudio/llvorbisdecode.cpp b/linden/indra/llaudio/llvorbisdecode.cpp new file mode 100644 index 0000000..4bf70f4 --- /dev/null +++ b/linden/indra/llaudio/llvorbisdecode.cpp @@ -0,0 +1,326 @@ +/** + * @file vorbisdecode.cpp + * @brief Vorbis decoding routine routine for Indra. + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "vorbis/codec.h" +#include "vorbis/vorbisfile.h" +#include "llerror.h" +#include "llmath.h" +#include "llvfile.h" + +#if 0 + +size_t vfs_read(void *ptr, size_t size, size_t nmemb, void *datasource) +{ + LLVFile *file = (LLVFile *)datasource; + + if (size > 0 && file->read((U8*)ptr, size * nmemb)) /*Flawfinder: ignore*/ + { + S32 read = file->getLastBytesRead(); + return read / size; /*Flawfinder: ignore*/ + } + else + { + return 0; + } +} + +int vfs_seek(void *datasource, ogg_int64_t offset, int whence) +{ + LLVFile *file = (LLVFile *)datasource; + + // vfs has 31-bit files + if (offset > S32_MAX) + { + return -1; + } + + S32 origin; + switch (whence) { + case SEEK_SET: + origin = 0; + break; + case SEEK_END: + origin = file->getSize(); + break; + case SEEK_CUR: + origin = -1; + break; + default: + llerrs << "Invalid whence argument to vfs_seek" << llendl; + return -1; + } + + if (file->seek((S32)offset, origin)) + { + return 0; + } + else + { + return -1; + } +} + +int vfs_close (void *datasource) +{ + LLVFile *file = (LLVFile *)datasource; + + delete file; + + return 0; +} + +long vfs_tell (void *datasource) +{ + LLVFile *file = (LLVFile *)datasource; + + return file->tell(); +} + + +BOOL decode_vorbis_file(LLVFS *vfs, const LLUUID &in_uuid, char *out_fname) +{ + ov_callbacks vfs_callbacks; + vfs_callbacks.read_func = vfs_read; + vfs_callbacks.seek_func = vfs_seek; + vfs_callbacks.close_func = vfs_close; + vfs_callbacks.tell_func = vfs_tell; + + char pcmout[4096]; /*Flawfinder: ignore*/ + + unsigned char temp[64]; /*Flawfinder: ignore*/ + + LLVFile *in_vfile; + + U32 data_length = 0; + + llinfos << "Vorbis decode from vfile: " << in_uuid << llendl; + + in_vfile = new LLVFile(vfs, in_uuid, LLAssetType::AT_SOUND); + if (! in_vfile->getSize()) + { + llwarning("unable to open vorbis source vfile for reading",0); + return(FALSE); + } + + //********************************** + LLAPRFile outfile ; + outfile.open(out_fname,LL_APR_WPB); + //********************************** + if (!outfile.getFileHandle()) + { + llwarning("unable to open vorbis destination file for writing",0); + return(FALSE); + } + else + { + // write the .wav format header + //"RIFF" + temp[0] = 0x52; + temp[1] = 0x49; + temp[2] = 0x46; + temp[3] = 0x46; + + // length = datalen + 36 (to be filled in later) + temp[4] = 0x00; + temp[5] = 0x00; + temp[6] = 0x00; + temp[7] = 0x00; + + //"WAVE" + temp[8] = 0x57; + temp[9] = 0x41; + temp[10] = 0x56; + temp[11] = 0x45; + + // "fmt " + temp[12] = 0x66; + temp[13] = 0x6D; + temp[14] = 0x74; + temp[15] = 0x20; + + // chunk size = 16 + temp[16] = 0x10; + temp[17] = 0x00; + temp[18] = 0x00; + temp[19] = 0x00; + + // format (1 = PCM) + temp[20] = 0x01; + temp[21] = 0x00; + + // number of channels + temp[22] = 0x01; + temp[23] = 0x00; + + // samples per second + temp[24] = 0x44; + temp[25] = 0xAC; + temp[26] = 0x00; + temp[27] = 0x00; + + // average bytes per second + temp[28] = 0x88; + temp[29] = 0x58; + temp[30] = 0x01; + temp[31] = 0x00; + + // bytes to output at a single time + temp[32] = 0x02; + temp[33] = 0x00; + + // 16 bits per sample + temp[34] = 0x10; + temp[35] = 0x00; + + // "data" + temp[36] = 0x64; + temp[37] = 0x61; + temp[38] = 0x74; + temp[39] = 0x61; + + + // these are the length of the data chunk, to be filled in later + temp[40] = 0x00; + temp[41] = 0x00; + temp[42] = 0x00; + temp[43] = 0x00; + + outfile.write(temp, 44); + } + + OggVorbis_File vf; + int eof=0; + int current_section; + + int r = ov_open_callbacks(in_vfile, &vf, NULL, 0, vfs_callbacks); + if(r < 0) + { + llwarns << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << in_uuid << llendl; + return(FALSE); + } + + { + char **ptr=ov_comment(&vf,-1)->user_comments; +// vorbis_info *vi=ov_info(&vf,-1); + while(*ptr){ + fprintf(stderr,"%s\n",*ptr); + ++ptr; + } +// fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate); +// fprintf(stderr,"\nDecoded length: %ld samples\n", (long)ov_pcm_total(&vf,-1)); +// fprintf(stderr,"Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor); + } + + while(!eof){ + long ret=ov_read(&vf,pcmout,sizeof(pcmout),0,2,1,¤t_section); + if (ret == 0) { + /* EOF */ + eof=1; +// llinfos << "Vorbis EOF" << llendl; + } else if (ret < 0) { + /* error in the stream. Not a problem, just reporting it in + case we (the app) cares. In this case, we don't. */ + llwarning("Error in vorbis stream",0); + break; + + } else { +// llinfos << "Vorbis read " << ret << "bytes" << llendl; + /* we don't bother dealing with sample rate changes, etc, but. + you'll have to*/ + data_length += outfile.write(pcmout, ret); + } + } + + ov_clear(&vf); + + // write "data" chunk length + outfile.seek(APR_SET,40); + outfile.write(&data_length,4); + + // write overall "RIFF" length + data_length += 36; + outfile.seek(APR_SET,4); + outfile.write(&data_length,1*4); + + // FUCK!!! Vorbis encode/decode messes up loop point transitions (pop) + // do a cheap-and-cheesy crossfade + + + S16 *samplep; + S32 i; + S32 fade_length; + + fade_length = llmin((S32)128,(S32)(data_length-36)/8); + + outfile.seek(APR_SET,44); + outfile.read(pcmout,2*fade_length); //read first 16 samples + + samplep = (S16 *)pcmout; + + for (i = 0 ;i < fade_length; i++) + { + *samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length)); + } + + outfile.seek(APR_SET,44); + outfile.write(pcmout,2*fade_length); //write back xfaded first 16 samples + + outfile.seek(APR_END,-fade_length*2); + outfile.read(pcmout,2*fade_length); //read last 16 samples + + samplep = (S16 *)pcmout; + + for (i = fade_length-1 ; i >= 0; i--) + { + *samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length)); + } + + outfile.seek(SEEK_END,-fade_length*2); + outfile.write(pcmout,2*fade_length); //write back xfaded last 16 samples + //******************* + outfile.close(); + //******************* + + if ((36 == data_length) || (!(eof))) + { + llwarning("BAD Vorbis DECODE!, removing .wav!",0); + LLFile::remove(out_fname); + return (FALSE); + } + +// fprintf(stderr,"Done.\n"); + + return(TRUE); +} +#endif diff --git a/linden/indra/llaudio/llvorbisdecode.h b/linden/indra/llaudio/llvorbisdecode.h new file mode 100644 index 0000000..cb67c99 --- /dev/null +++ b/linden/indra/llaudio/llvorbisdecode.h @@ -0,0 +1,42 @@ +/** + * @file vorbisdecode.h + * @brief Vorbis decoding routine routine for Indra. + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_VORBISDECODE_H +#define LL_VORBISDECODE_H + +class LLVFS; +class LLUUID; + +BOOL decode_vorbis_file(LLVFS *vfs, const LLUUID &in_uuid, char *out_fname); + +#endif + diff --git a/linden/indra/llaudio/llvorbisencode.cpp b/linden/indra/llaudio/llvorbisencode.cpp new file mode 100644 index 0000000..a24394d --- /dev/null +++ b/linden/indra/llaudio/llvorbisencode.cpp @@ -0,0 +1,505 @@ +/** + * @file vorbisencode.cpp + * @brief Vorbis encoding routine routine for Indra. + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "vorbis/vorbisenc.h" + +#include "llvorbisencode.h" +#include "llerror.h" +#include "llrand.h" +#include "llmath.h" +#include "llapr.h" + +//#if LL_DARWIN +// MBW -- XXX -- Getting rid of SecondLifeVorbis for now -- no fmod means no name collisions. +#if 0 +#include "VorbisFramework.h" + +#define vorbis_analysis mac_vorbis_analysis +#define vorbis_analysis_headerout mac_vorbis_analysis_headerout +#define vorbis_analysis_init mac_vorbis_analysis_init +#define vorbis_encode_ctl mac_vorbis_encode_ctl +#define vorbis_encode_setup_init mac_vorbis_encode_setup_init +#define vorbis_encode_setup_managed mac_vorbis_encode_setup_managed + +#define vorbis_info_init mac_vorbis_info_init +#define vorbis_info_clear mac_vorbis_info_clear +#define vorbis_comment_init mac_vorbis_comment_init +#define vorbis_comment_clear mac_vorbis_comment_clear +#define vorbis_block_init mac_vorbis_block_init +#define vorbis_block_clear mac_vorbis_block_clear +#define vorbis_dsp_clear mac_vorbis_dsp_clear +#define vorbis_analysis_buffer mac_vorbis_analysis_buffer +#define vorbis_analysis_wrote mac_vorbis_analysis_wrote +#define vorbis_analysis_blockout mac_vorbis_analysis_blockout + +#define ogg_stream_packetin mac_ogg_stream_packetin +#define ogg_stream_init mac_ogg_stream_init +#define ogg_stream_flush mac_ogg_stream_flush +#define ogg_stream_pageout mac_ogg_stream_pageout +#define ogg_page_eos mac_ogg_page_eos +#define ogg_stream_clear mac_ogg_stream_clear + +#endif + +S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg) +{ + U16 num_channels = 0; + U32 sample_rate = 0; + U32 bits_per_sample = 0; + U32 physical_file_size = 0; + U32 chunk_length = 0; + U32 raw_data_length = 0; + U32 bytes_per_sec = 0; + BOOL uncompressed_pcm = FALSE; + + unsigned char wav_header[44]; /*Flawfinder: ignore*/ + + error_msg.clear(); + + //******************************** + LLAPRFile infile ; + infile.open(in_fname,LL_APR_RB, LLAPRFile::global); + //******************************** + if (!infile.getFileHandle()) + { + error_msg = "CannotUploadSoundFile"; + return(LLVORBISENC_SOURCE_OPEN_ERR); + } + + infile.read(wav_header, 44); + physical_file_size = infile.seek(APR_END,0); + + if (strncmp((char *)&(wav_header[0]),"RIFF",4)) + { + error_msg = "SoundFileNotRIFF"; + return(LLVORBISENC_WAV_FORMAT_ERR); + } + + if (strncmp((char *)&(wav_header[8]),"WAVE",4)) + { + error_msg = "SoundFileNotRIFF"; + return(LLVORBISENC_WAV_FORMAT_ERR); + } + + // parse the chunks + + U32 file_pos = 12; // start at the first chunk (usually fmt but not always) + + while ((file_pos + 8)< physical_file_size) + { + infile.seek(APR_SET,file_pos); + infile.read(wav_header, 44); + + chunk_length = ((U32) wav_header[7] << 24) + + ((U32) wav_header[6] << 16) + + ((U32) wav_header[5] << 8) + + wav_header[4]; + +// llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl; + + if (!(strncmp((char *)&(wav_header[0]),"fmt ",4))) + { + if ((wav_header[8] == 0x01) && (wav_header[9] == 0x00)) + { + uncompressed_pcm = TRUE; + } + num_channels = ((U16) wav_header[11] << 8) + wav_header[10]; + sample_rate = ((U32) wav_header[15] << 24) + + ((U32) wav_header[14] << 16) + + ((U32) wav_header[13] << 8) + + wav_header[12]; + bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22]; + bytes_per_sec = ((U32) wav_header[19] << 24) + + ((U32) wav_header[18] << 16) + + ((U32) wav_header[17] << 8) + + wav_header[16]; + } + else if (!(strncmp((char *)&(wav_header[0]),"data",4))) + { + raw_data_length = chunk_length; + } + file_pos += (chunk_length + 8); + chunk_length = 0; + } + //**************** + infile.close(); + //**************** + + if (!uncompressed_pcm) + { + error_msg = "SoundFileNotPCM"; + return(LLVORBISENC_PCM_FORMAT_ERR); + } + + if ((num_channels < 1) || (num_channels > LLVORBIS_CLIP_MAX_CHANNELS)) + { + error_msg = "SoundFileInvalidChannelCount"; + return(LLVORBISENC_MULTICHANNEL_ERR); + } + + if (sample_rate != LLVORBIS_CLIP_SAMPLE_RATE) + { + error_msg = "SoundFileInvalidSampleRate"; + return(LLVORBISENC_UNSUPPORTED_SAMPLE_RATE); + } + + if ((bits_per_sample != 16) && (bits_per_sample != 8)) + { + error_msg = "SoundFileInvalidWordSize"; + return(LLVORBISENC_UNSUPPORTED_WORD_SIZE); + } + + if (!raw_data_length) + { + error_msg = "SoundFileInvalidHeader"; + return(LLVORBISENC_CLIP_TOO_LONG); + } + + F32 clip_length = (F32)raw_data_length/(F32)bytes_per_sec; + + if (clip_length > LLVORBIS_CLIP_MAX_TIME) + { + error_msg = "SoundFileInvalidTooLong"; + return(LLVORBISENC_CLIP_TOO_LONG); + } + + return(LLVORBISENC_NOERR); +} + +S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname) +{ +#define READ_BUFFER 1024 + unsigned char readbuffer[READ_BUFFER*4+44]; /* out of the data segment, not the stack */ /*Flawfinder: ignore*/ + + ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ + ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ + ogg_packet op; /* one raw packet of data for decode */ + + vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */ + vorbis_comment vc; /* struct that stores all the user comments */ + + vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ + vorbis_block vb; /* local working space for packet->PCM decode */ + + int eos=0; + int result; + + U16 num_channels = 0; + U32 sample_rate = 0; + U32 bits_per_sample = 0; + + S32 format_error = 0; + std::string error_msg; + if ((format_error = check_for_invalid_wav_formats(in_fname, error_msg))) + { + llwarns << error_msg << ": " << in_fname << llendl; + return(format_error); + } + +#if 1 + unsigned char wav_header[44]; /*Flawfinder: ignore*/ + + S32 data_left = 0; + + LLAPRFile infile ; + infile.open(in_fname,LL_APR_RB, LLAPRFile::global); + if (!infile.getFileHandle()) + { + llwarns << "Couldn't open temporary ogg file for writing: " << in_fname + << llendl; + return(LLVORBISENC_SOURCE_OPEN_ERR); + } + + LLAPRFile outfile ; + outfile.open(out_fname,LL_APR_WPB, LLAPRFile::global); + if (!outfile.getFileHandle()) + { + llwarns << "Couldn't open upload sound file for reading: " << in_fname + << llendl; + return(LLVORBISENC_DEST_OPEN_ERR); + } + + // parse the chunks + U32 chunk_length = 0; + U32 file_pos = 12; // start at the first chunk (usually fmt but not always) + + while (infile.eof() != APR_EOF) + { + infile.seek(APR_SET,file_pos); + infile.read(wav_header, 44); + + chunk_length = ((U32) wav_header[7] << 24) + + ((U32) wav_header[6] << 16) + + ((U32) wav_header[5] << 8) + + wav_header[4]; + +// llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl; + + if (!(strncmp((char *)&(wav_header[0]),"fmt ",4))) + { + num_channels = ((U16) wav_header[11] << 8) + wav_header[10]; + sample_rate = ((U32) wav_header[15] << 24) + + ((U32) wav_header[14] << 16) + + ((U32) wav_header[13] << 8) + + wav_header[12]; + bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22]; + } + else if (!(strncmp((char *)&(wav_header[0]),"data",4))) + { + infile.seek(APR_SET,file_pos+8); + // leave the file pointer at the beginning of the data chunk data + data_left = chunk_length; + break; + } + file_pos += (chunk_length + 8); + chunk_length = 0; + } + + + /********** Encode setup ************/ + + /* choose an encoding mode */ + /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */ + vorbis_info_init(&vi); + + // always encode to mono + + // SL-52913 & SL-53779 determined this quality level to be our 'good + // enough' general-purpose quality level with a nice low bitrate. + // Equivalent to oggenc -q0.5 + F32 quality = 0.05f; +// quality = (bitrate==128000 ? 0.4f : 0.1); + +// if (vorbis_encode_init(&vi, /* num_channels */ 1 ,sample_rate, -1, bitrate, -1)) + if (vorbis_encode_init_vbr(&vi, /* num_channels */ 1 ,sample_rate, quality)) +// if (vorbis_encode_setup_managed(&vi,1,sample_rate,-1,bitrate,-1) || +// vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE_AVG,NULL) || +// vorbis_encode_setup_init(&vi)) + { + llwarns << "unable to initialize vorbis codec at quality " << quality << llendl; + // llwarns << "unable to initialize vorbis codec at bitrate " << bitrate << llendl; + return(LLVORBISENC_DEST_OPEN_ERR); + } + + /* add a comment */ + vorbis_comment_init(&vc); +// vorbis_comment_add(&vc,"Linden"); + + /* set up the analysis state and auxiliary encoding storage */ + vorbis_analysis_init(&vd,&vi); + vorbis_block_init(&vd,&vb); + + /* set up our packet->stream encoder */ + /* pick a random serial number; that way we can more likely build + chained streams just by concatenation */ + ogg_stream_init(&os, ll_rand()); + + /* Vorbis streams begin with three headers; the initial header (with + most of the codec setup parameters) which is mandated by the Ogg + bitstream spec. The second header holds any comment fields. The + third header holds the bitstream codebook. We merely need to + make the headers, then pass them to libvorbis one at a time; + libvorbis handles the additional Ogg bitstream constraints */ + + { + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + + vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code); + ogg_stream_packetin(&os,&header); /* automatically placed in its own + page */ + ogg_stream_packetin(&os,&header_comm); + ogg_stream_packetin(&os,&header_code); + + /* We don't have to write out here, but doing so makes streaming + * much easier, so we do, flushing ALL pages. This ensures the actual + * audio data will start on a new page + */ + while(!eos){ + int result=ogg_stream_flush(&os,&og); + if(result==0)break; + outfile.write(og.header, og.header_len); + outfile.write(og.body, og.body_len); + } + + } + + + while(!eos) + { + long bytes_per_sample = bits_per_sample/8; + + long bytes=(long)infile.read(readbuffer,llclamp((S32)(READ_BUFFER*num_channels*bytes_per_sample),0,data_left)); /* stereo hardwired here */ + + if (bytes==0) + { + /* end of file. this can be done implicitly in the mainline, + but it's easier to see here in non-clever fashion. + Tell the library we're at end of stream so that it can handle + the last frame and mark end of stream in the output properly */ + + vorbis_analysis_wrote(&vd,0); +// eos = 1; + + } + else + { + long i; + long samples; + int temp; + + data_left -= bytes; + /* data to encode */ + + /* expose the buffer to submit data */ + float **buffer=vorbis_analysis_buffer(&vd,READ_BUFFER); + + i = 0; + samples = bytes / (num_channels * bytes_per_sample); + + if (num_channels == 2) + { + if (bytes_per_sample == 2) + { + /* uninterleave samples */ + for(i=0; i +class LLWindGen +{ +public: + LLWindGen() : + mTargetGain(0.f), + mTargetFreq(100.f), + mTargetPanGainR(0.5f), + mbuf0(0.0), + mbuf1(0.0), + mbuf2(0.0), + mbuf3(0.0), + mbuf4(0.0), + mbuf5(0.0), + mY0(0.0), + mY1(0.0), + mCurrentGain(0.f), + mCurrentFreq(100.f), + mCurrentPanGainR(0.5f) {}; + + static const U32 getInputSamplingRate() {return mInputSamplingRate;} + + // newbuffer = the buffer passed from the previous DSP unit. + // numsamples = length in samples-per-channel at this mix time. + // stride = number of bytes between start of each sample. + // NOTE: generates L/R interleaved stereo + MIXBUFFERFORMAT_T* windGenerate(MIXBUFFERFORMAT_T *newbuffer, int numsamples, int stride) + { + U8 *cursamplep = (U8*)newbuffer; + + double bandwidth = 50.0F; + double a0,b1,b2; + + // calculate resonant filter coeffs + b2 = exp(-(F_TWO_PI) * (bandwidth / mInputSamplingRate)); + + while (numsamples--) + { + mCurrentFreq = (float)((0.999 * mCurrentFreq) + (0.001 * mTargetFreq)); + mCurrentGain = (float)((0.999 * mCurrentGain) + (0.001 * mTargetGain)); + mCurrentPanGainR = (float)((0.999 * mCurrentPanGainR) + (0.001 * mTargetPanGainR)); + b1 = (-4.0 * b2) / (1.0 + b2) * cos(F_TWO_PI * (mCurrentFreq / mInputSamplingRate)); + a0 = (1.0 - b2) * sqrt(1.0 - (b1 * b1) / (4.0 * b2)); + double nextSample; + + // start with white noise + nextSample = ll_frand(2.0f) - 1.0f; + + // apply pinking filter + mbuf0 = 0.997f * mbuf0 + 0.0126502f * nextSample; + mbuf1 = 0.985f * mbuf1 + 0.0139083f * nextSample; + mbuf2 = 0.950f * mbuf2 + 0.0205439f * nextSample; + mbuf3 = 0.850f * mbuf3 + 0.0387225f * nextSample; + mbuf4 = 0.620f * mbuf4 + 0.0465932f * nextSample; + mbuf5 = 0.250f * mbuf5 + 0.1093477f * nextSample; + + nextSample = mbuf0 + mbuf1 + mbuf2 + mbuf3 + mbuf4 + mbuf5; + + // do a resonant filter on the noise + nextSample = (double)( a0 * nextSample - b1 * mY0 - b2 * mY1 ); + mY1 = mY0; + mY0 = nextSample; + + nextSample *= mCurrentGain; + + MIXBUFFERFORMAT_T sample; + + sample = llfloor(((F32)nextSample*32768.f*(1.0f - mCurrentPanGainR))+0.5f); + *(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767); + cursamplep += stride; + + sample = llfloor(((F32)nextSample*32768.f*mCurrentPanGainR)+0.5f); + *(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767); + cursamplep += stride; + } + + return newbuffer; + } + + F32 mTargetGain; + F32 mTargetFreq; + F32 mTargetPanGainR; + +private: + static const U32 mInputSamplingRate = 44100; + F64 mbuf0; + F64 mbuf1; + F64 mbuf2; + F64 mbuf3; + F64 mbuf4; + F64 mbuf5; + F64 mY0; + F64 mY1; + F32 mCurrentGain; + F32 mCurrentFreq; + F32 mCurrentPanGainR; +}; + +#endif diff --git a/linden/indra/llaudio/vorbisdecode.cpp b/linden/indra/llaudio/vorbisdecode.cpp deleted file mode 100644 index 4bf70f4..0000000 --- a/linden/indra/llaudio/vorbisdecode.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/** - * @file vorbisdecode.cpp - * @brief Vorbis decoding routine routine for Indra. - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "vorbis/codec.h" -#include "vorbis/vorbisfile.h" -#include "llerror.h" -#include "llmath.h" -#include "llvfile.h" - -#if 0 - -size_t vfs_read(void *ptr, size_t size, size_t nmemb, void *datasource) -{ - LLVFile *file = (LLVFile *)datasource; - - if (size > 0 && file->read((U8*)ptr, size * nmemb)) /*Flawfinder: ignore*/ - { - S32 read = file->getLastBytesRead(); - return read / size; /*Flawfinder: ignore*/ - } - else - { - return 0; - } -} - -int vfs_seek(void *datasource, ogg_int64_t offset, int whence) -{ - LLVFile *file = (LLVFile *)datasource; - - // vfs has 31-bit files - if (offset > S32_MAX) - { - return -1; - } - - S32 origin; - switch (whence) { - case SEEK_SET: - origin = 0; - break; - case SEEK_END: - origin = file->getSize(); - break; - case SEEK_CUR: - origin = -1; - break; - default: - llerrs << "Invalid whence argument to vfs_seek" << llendl; - return -1; - } - - if (file->seek((S32)offset, origin)) - { - return 0; - } - else - { - return -1; - } -} - -int vfs_close (void *datasource) -{ - LLVFile *file = (LLVFile *)datasource; - - delete file; - - return 0; -} - -long vfs_tell (void *datasource) -{ - LLVFile *file = (LLVFile *)datasource; - - return file->tell(); -} - - -BOOL decode_vorbis_file(LLVFS *vfs, const LLUUID &in_uuid, char *out_fname) -{ - ov_callbacks vfs_callbacks; - vfs_callbacks.read_func = vfs_read; - vfs_callbacks.seek_func = vfs_seek; - vfs_callbacks.close_func = vfs_close; - vfs_callbacks.tell_func = vfs_tell; - - char pcmout[4096]; /*Flawfinder: ignore*/ - - unsigned char temp[64]; /*Flawfinder: ignore*/ - - LLVFile *in_vfile; - - U32 data_length = 0; - - llinfos << "Vorbis decode from vfile: " << in_uuid << llendl; - - in_vfile = new LLVFile(vfs, in_uuid, LLAssetType::AT_SOUND); - if (! in_vfile->getSize()) - { - llwarning("unable to open vorbis source vfile for reading",0); - return(FALSE); - } - - //********************************** - LLAPRFile outfile ; - outfile.open(out_fname,LL_APR_WPB); - //********************************** - if (!outfile.getFileHandle()) - { - llwarning("unable to open vorbis destination file for writing",0); - return(FALSE); - } - else - { - // write the .wav format header - //"RIFF" - temp[0] = 0x52; - temp[1] = 0x49; - temp[2] = 0x46; - temp[3] = 0x46; - - // length = datalen + 36 (to be filled in later) - temp[4] = 0x00; - temp[5] = 0x00; - temp[6] = 0x00; - temp[7] = 0x00; - - //"WAVE" - temp[8] = 0x57; - temp[9] = 0x41; - temp[10] = 0x56; - temp[11] = 0x45; - - // "fmt " - temp[12] = 0x66; - temp[13] = 0x6D; - temp[14] = 0x74; - temp[15] = 0x20; - - // chunk size = 16 - temp[16] = 0x10; - temp[17] = 0x00; - temp[18] = 0x00; - temp[19] = 0x00; - - // format (1 = PCM) - temp[20] = 0x01; - temp[21] = 0x00; - - // number of channels - temp[22] = 0x01; - temp[23] = 0x00; - - // samples per second - temp[24] = 0x44; - temp[25] = 0xAC; - temp[26] = 0x00; - temp[27] = 0x00; - - // average bytes per second - temp[28] = 0x88; - temp[29] = 0x58; - temp[30] = 0x01; - temp[31] = 0x00; - - // bytes to output at a single time - temp[32] = 0x02; - temp[33] = 0x00; - - // 16 bits per sample - temp[34] = 0x10; - temp[35] = 0x00; - - // "data" - temp[36] = 0x64; - temp[37] = 0x61; - temp[38] = 0x74; - temp[39] = 0x61; - - - // these are the length of the data chunk, to be filled in later - temp[40] = 0x00; - temp[41] = 0x00; - temp[42] = 0x00; - temp[43] = 0x00; - - outfile.write(temp, 44); - } - - OggVorbis_File vf; - int eof=0; - int current_section; - - int r = ov_open_callbacks(in_vfile, &vf, NULL, 0, vfs_callbacks); - if(r < 0) - { - llwarns << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << in_uuid << llendl; - return(FALSE); - } - - { - char **ptr=ov_comment(&vf,-1)->user_comments; -// vorbis_info *vi=ov_info(&vf,-1); - while(*ptr){ - fprintf(stderr,"%s\n",*ptr); - ++ptr; - } -// fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate); -// fprintf(stderr,"\nDecoded length: %ld samples\n", (long)ov_pcm_total(&vf,-1)); -// fprintf(stderr,"Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor); - } - - while(!eof){ - long ret=ov_read(&vf,pcmout,sizeof(pcmout),0,2,1,¤t_section); - if (ret == 0) { - /* EOF */ - eof=1; -// llinfos << "Vorbis EOF" << llendl; - } else if (ret < 0) { - /* error in the stream. Not a problem, just reporting it in - case we (the app) cares. In this case, we don't. */ - llwarning("Error in vorbis stream",0); - break; - - } else { -// llinfos << "Vorbis read " << ret << "bytes" << llendl; - /* we don't bother dealing with sample rate changes, etc, but. - you'll have to*/ - data_length += outfile.write(pcmout, ret); - } - } - - ov_clear(&vf); - - // write "data" chunk length - outfile.seek(APR_SET,40); - outfile.write(&data_length,4); - - // write overall "RIFF" length - data_length += 36; - outfile.seek(APR_SET,4); - outfile.write(&data_length,1*4); - - // FUCK!!! Vorbis encode/decode messes up loop point transitions (pop) - // do a cheap-and-cheesy crossfade - - - S16 *samplep; - S32 i; - S32 fade_length; - - fade_length = llmin((S32)128,(S32)(data_length-36)/8); - - outfile.seek(APR_SET,44); - outfile.read(pcmout,2*fade_length); //read first 16 samples - - samplep = (S16 *)pcmout; - - for (i = 0 ;i < fade_length; i++) - { - *samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length)); - } - - outfile.seek(APR_SET,44); - outfile.write(pcmout,2*fade_length); //write back xfaded first 16 samples - - outfile.seek(APR_END,-fade_length*2); - outfile.read(pcmout,2*fade_length); //read last 16 samples - - samplep = (S16 *)pcmout; - - for (i = fade_length-1 ; i >= 0; i--) - { - *samplep++ = ((F32)*samplep * ((F32)i/(F32)fade_length)); - } - - outfile.seek(SEEK_END,-fade_length*2); - outfile.write(pcmout,2*fade_length); //write back xfaded last 16 samples - //******************* - outfile.close(); - //******************* - - if ((36 == data_length) || (!(eof))) - { - llwarning("BAD Vorbis DECODE!, removing .wav!",0); - LLFile::remove(out_fname); - return (FALSE); - } - -// fprintf(stderr,"Done.\n"); - - return(TRUE); -} -#endif diff --git a/linden/indra/llaudio/vorbisdecode.h b/linden/indra/llaudio/vorbisdecode.h deleted file mode 100644 index cb67c99..0000000 --- a/linden/indra/llaudio/vorbisdecode.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file vorbisdecode.h - * @brief Vorbis decoding routine routine for Indra. - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_VORBISDECODE_H -#define LL_VORBISDECODE_H - -class LLVFS; -class LLUUID; - -BOOL decode_vorbis_file(LLVFS *vfs, const LLUUID &in_uuid, char *out_fname); - -#endif - diff --git a/linden/indra/llaudio/vorbisencode.h b/linden/indra/llaudio/vorbisencode.h deleted file mode 100644 index ff5ce3a..0000000 --- a/linden/indra/llaudio/vorbisencode.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file vorbisencode.h - * @brief Vorbis encoding routine routine for Indra. - * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_VORBISENCODE_H -#define LL_VORBISENCODE_H - -const S32 LLVORBISENC_NOERR = 0; // no error -const S32 LLVORBISENC_SOURCE_OPEN_ERR = 1; // error opening source -const S32 LLVORBISENC_DEST_OPEN_ERR = 2; // error opening destination -const S32 LLVORBISENC_WAV_FORMAT_ERR = 3; // not a WAV -const S32 LLVORBISENC_PCM_FORMAT_ERR = 4; // not a PCM -const S32 LLVORBISENC_MONO_ERR = 5; // can't do mono -const S32 LLVORBISENC_STEREO_ERR = 6; // can't do stereo -const S32 LLVORBISENC_MULTICHANNEL_ERR = 7; // can't do stereo -const S32 LLVORBISENC_UNSUPPORTED_SAMPLE_RATE = 8; // unsupported sample rate -const S32 LLVORBISENC_UNSUPPORTED_WORD_SIZE = 9; // unsupported word size -const S32 LLVORBISENC_CLIP_TOO_LONG = 10; // source file is too long - - -S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg); -S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname); - -#endif - diff --git a/linden/indra/llaudio/windgen.h b/linden/indra/llaudio/windgen.h deleted file mode 100644 index 847bfa6..0000000 --- a/linden/indra/llaudio/windgen.h +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @file windgen.h - * @brief Templated wind noise generation - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ -#ifndef WINDGEN_H -#define WINDGEN_H - -#include "llcommon.h" -#include "llrand.h" - -template -class LLWindGen -{ -public: - LLWindGen() : - mTargetGain(0.f), - mTargetFreq(100.f), - mTargetPanGainR(0.5f), - mbuf0(0.0), - mbuf1(0.0), - mbuf2(0.0), - mbuf3(0.0), - mbuf4(0.0), - mbuf5(0.0), - mY0(0.0), - mY1(0.0), - mCurrentGain(0.f), - mCurrentFreq(100.f), - mCurrentPanGainR(0.5f) {}; - - static const U32 getInputSamplingRate() {return mInputSamplingRate;} - - // newbuffer = the buffer passed from the previous DSP unit. - // numsamples = length in samples-per-channel at this mix time. - // stride = number of bytes between start of each sample. - // NOTE: generates L/R interleaved stereo - MIXBUFFERFORMAT_T* windGenerate(MIXBUFFERFORMAT_T *newbuffer, int numsamples, int stride) - { - U8 *cursamplep = (U8*)newbuffer; - - double bandwidth = 50.0F; - double a0,b1,b2; - - // calculate resonant filter coeffs - b2 = exp(-(F_TWO_PI) * (bandwidth / mInputSamplingRate)); - - while (numsamples--) - { - mCurrentFreq = (float)((0.999 * mCurrentFreq) + (0.001 * mTargetFreq)); - mCurrentGain = (float)((0.999 * mCurrentGain) + (0.001 * mTargetGain)); - mCurrentPanGainR = (float)((0.999 * mCurrentPanGainR) + (0.001 * mTargetPanGainR)); - b1 = (-4.0 * b2) / (1.0 + b2) * cos(F_TWO_PI * (mCurrentFreq / mInputSamplingRate)); - a0 = (1.0 - b2) * sqrt(1.0 - (b1 * b1) / (4.0 * b2)); - double nextSample; - - // start with white noise - nextSample = ll_frand(2.0f) - 1.0f; - - // apply pinking filter - mbuf0 = 0.997f * mbuf0 + 0.0126502f * nextSample; - mbuf1 = 0.985f * mbuf1 + 0.0139083f * nextSample; - mbuf2 = 0.950f * mbuf2 + 0.0205439f * nextSample; - mbuf3 = 0.850f * mbuf3 + 0.0387225f * nextSample; - mbuf4 = 0.620f * mbuf4 + 0.0465932f * nextSample; - mbuf5 = 0.250f * mbuf5 + 0.1093477f * nextSample; - - nextSample = mbuf0 + mbuf1 + mbuf2 + mbuf3 + mbuf4 + mbuf5; - - // do a resonant filter on the noise - nextSample = (double)( a0 * nextSample - b1 * mY0 - b2 * mY1 ); - mY1 = mY0; - mY0 = nextSample; - - nextSample *= mCurrentGain; - - MIXBUFFERFORMAT_T sample; - - sample = llfloor(((F32)nextSample*32768.f*(1.0f - mCurrentPanGainR))+0.5f); - *(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767); - cursamplep += stride; - - sample = llfloor(((F32)nextSample*32768.f*mCurrentPanGainR)+0.5f); - *(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767); - cursamplep += stride; - } - - return newbuffer; - } - - F32 mTargetGain; - F32 mTargetFreq; - F32 mTargetPanGainR; - -private: - static const U32 mInputSamplingRate = 44100; - F64 mbuf0; - F64 mbuf1; - F64 mbuf2; - F64 mbuf3; - F64 mbuf4; - F64 mbuf5; - F64 mY0; - F64 mY1; - F32 mCurrentGain; - F32 mCurrentFreq; - F32 mCurrentPanGainR; -}; - -#endif diff --git a/linden/indra/llcommon/CMakeLists.txt b/linden/indra/llcommon/CMakeLists.txt index 3f14be6..1c12e55 100644 --- a/linden/indra/llcommon/CMakeLists.txt +++ b/linden/indra/llcommon/CMakeLists.txt @@ -42,6 +42,7 @@ set(llcommon_SOURCE_FILES llmetrics.cpp llmortician.cpp llprocessor.cpp + llprocesslauncher.cpp llqueuedthread.cpp llrand.cpp llrun.cpp @@ -136,6 +137,7 @@ set(llcommon_HEADER_FILES llnametable.h llpreprocessor.h llpriqueuemap.h + llprocesslauncher.h llprocessor.h llptrskiplist.h llptrskipmap.h diff --git a/linden/indra/llcommon/llerrorcontrol.h b/linden/indra/llcommon/llerrorcontrol.h index a55d706..fae7547 100644 --- a/linden/indra/llcommon/llerrorcontrol.h +++ b/linden/indra/llcommon/llerrorcontrol.h @@ -73,6 +73,7 @@ namespace LLError void setFunctionLevel(const std::string& function_name, LLError::ELevel); void setClassLevel(const std::string& class_name, LLError::ELevel); void setFileLevel(const std::string& file_name, LLError::ELevel); + void setTagLevel(const std::string& file_name, LLError::ELevel); void configure(const LLSD&); // the LLSD can configure all of the settings diff --git a/linden/indra/llcommon/llprocesslauncher.cpp b/linden/indra/llcommon/llprocesslauncher.cpp new file mode 100644 index 0000000..e27aaa3 --- /dev/null +++ b/linden/indra/llcommon/llprocesslauncher.cpp @@ -0,0 +1,346 @@ +/** + * @file llprocesslauncher.cpp + * @brief Utility class for launching, terminating, and tracking the state of processes. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llprocesslauncher.h" + +#include +#if LL_DARWIN || LL_LINUX +// not required or present on Win32 +#include +#endif + +LLProcessLauncher::LLProcessLauncher() +{ +#if LL_WINDOWS + mProcessHandle = 0; +#else + mProcessID = 0; +#endif +} + +LLProcessLauncher::~LLProcessLauncher() +{ + kill(); +} + +void LLProcessLauncher::setExecutable(const std::string &executable) +{ + mExecutable = executable; +} + +void LLProcessLauncher::setWorkingDirectory(const std::string &dir) +{ + mWorkingDir = dir; +} + +void LLProcessLauncher::clearArguments() +{ + mLaunchArguments.clear(); +} + +void LLProcessLauncher::addArgument(const std::string &arg) +{ + mLaunchArguments.push_back(arg); +} + +void LLProcessLauncher::addArgument(const char *arg) +{ + mLaunchArguments.push_back(std::string(arg)); +} + +#if LL_WINDOWS + +int LLProcessLauncher::launch(void) +{ + // If there was already a process associated with this object, kill it. + kill(); + orphan(); + + int result = 0; + + PROCESS_INFORMATION pinfo; + STARTUPINFOA sinfo; + memset(&sinfo, 0, sizeof(sinfo)); + + std::string args = "\"" + mExecutable + "\""; + for(int i = 0; i < (int)mLaunchArguments.size(); i++) + { + args += " "; + args += mLaunchArguments[i]; + } + LL_INFOS("Plugin") << "Executable: " << mExecutable << " arguments: " << args << LL_ENDL; + + // So retarded. Windows requires that the second parameter to CreateProcessA be a writable (non-const) string... + char *args2 = new char[args.size() + 1]; + strcpy(args2, args.c_str()); + + if( ! CreateProcessA( NULL, args2, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo ) ) + { + // TODO: do better than returning the OS-specific error code on failure... + result = GetLastError(); + if(result == 0) + { + // Make absolutely certain we return a non-zero value on failure. + result = -1; + } + } + else + { + // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on + // CloseHandle(pinfo.hProcess); // stops leaks - nothing else + mProcessHandle = pinfo.hProcess; + CloseHandle(pinfo.hThread); // stops leaks - nothing else + } + + delete[] args2; + + return result; +} + +bool LLProcessLauncher::isRunning(void) +{ + if(mProcessHandle != 0) + { + DWORD waitresult = WaitForSingleObject(mProcessHandle, 0); + if(waitresult == WAIT_OBJECT_0) + { + // the process has completed. + mProcessHandle = 0; + } + } + + return (mProcessHandle != 0); +} +bool LLProcessLauncher::kill(void) +{ + bool result = true; + + if(mProcessHandle != 0) + { + TerminateProcess(mProcessHandle,0); + + if(isRunning()) + { + result = false; + } + } + + return result; +} + +void LLProcessLauncher::orphan(void) +{ + // Forget about the process + mProcessHandle = 0; +} + +// static +void LLProcessLauncher::reap(void) +{ + // No actions necessary on Windows. +} + +#else // Mac and linux + +#include +#include +#include + +static std::list sZombies; + +// Attempt to reap a process ID -- returns true if the process has exited and been reaped, false otherwise. +static bool reap_pid(pid_t pid) +{ + bool result = false; + + pid_t wait_result = ::waitpid(pid, NULL, WNOHANG); + if(wait_result == pid) + { + result = true; + } + else if(wait_result == -1) + { + if(errno == ECHILD) + { + // No such process -- this may mean we're ignoring SIGCHILD. + result = true; + } + } + + return result; +} + +int LLProcessLauncher::launch(void) +{ + // If there was already a process associated with this object, kill it. + kill(); + orphan(); + + int result = 0; + int current_wd = -1; + + // create an argv vector for the child process + const char ** fake_argv = new const char *[mLaunchArguments.size() + 2]; // 1 for the executable path, 1 for the NULL terminator + + int i = 0; + + // add the executable path + fake_argv[i++] = mExecutable.c_str(); + + // and any arguments + for(int j=0; j < mLaunchArguments.size(); j++) + fake_argv[i++] = mLaunchArguments[j].c_str(); + + // terminate with a null pointer + fake_argv[i] = NULL; + + if(!mWorkingDir.empty()) + { + // save the current working directory + current_wd = ::open(".", O_RDONLY); + + // and change to the one the child will be executed in + if (::chdir(mWorkingDir.c_str())) + { + // chdir failed + } + } + + // flush all buffers before the child inherits them + ::fflush(NULL); + + pid_t id = vfork(); + if(id == 0) + { + // child process + + ::execv(mExecutable.c_str(), (char * const *)fake_argv); + + // If we reach this point, the exec failed. + // Use _exit() instead of exit() per the vfork man page. + _exit(0); + } + + // parent process + + if(current_wd >= 0) + { + // restore the previous working directory + if (::fchdir(current_wd)) + { + // chdir failed + } + ::close(current_wd); + } + + delete[] fake_argv; + + mProcessID = id; + + // At this point, the child process will have been created (since that's how vfork works -- the child borrowed our execution context until it forked) + // If the process doesn't exist at this point, the exec failed. + if(!isRunning()) + { + result = -1; + } + + return result; +} + +bool LLProcessLauncher::isRunning(void) +{ + if(mProcessID != 0) + { + // Check whether the process has exited, and reap it if it has. + if(reap_pid(mProcessID)) + { + // the process has exited. + mProcessID = 0; + } + } + + return (mProcessID != 0); +} + +bool LLProcessLauncher::kill(void) +{ + bool result = true; + + if(mProcessID != 0) + { + // Try to kill the process. We'll do approximately the same thing whether the kill returns an error or not, so we ignore the result. + (void)::kill(mProcessID, SIGTERM); + + // This will have the side-effect of reaping the zombie if the process has exited. + if(isRunning()) + { + result = false; + } + } + + return result; +} + +void LLProcessLauncher::orphan(void) +{ + // Disassociate the process from this object + if(mProcessID != 0) + { + // We may still need to reap the process's zombie eventually + sZombies.push_back(mProcessID); + + mProcessID = 0; + } +} + +// static +void LLProcessLauncher::reap(void) +{ + // Attempt to real all saved process ID's. + + std::list::iterator iter = sZombies.begin(); + while(iter != sZombies.end()) + { + if(reap_pid(*iter)) + { + iter = sZombies.erase(iter); + } + else + { + iter++; + } + } +} + +#endif diff --git a/linden/indra/llcommon/llprocesslauncher.h b/linden/indra/llcommon/llprocesslauncher.h new file mode 100644 index 0000000..036732f --- /dev/null +++ b/linden/indra/llcommon/llprocesslauncher.h @@ -0,0 +1,86 @@ +/** + * @file llprocesslauncher.h + * @brief Utility class for launching, terminating, and tracking the state of processes. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPROCESSLAUNCHER_H +#define LL_LLPROCESSLAUNCHER_H + +#if LL_WINDOWS +#include +#endif + + +/* + LLProcessLauncher handles launching external processes with specified command line arguments. + It also keeps track of whether the process is still running, and can kill it if required. +*/ + +class LLProcessLauncher +{ + LOG_CLASS(LLProcessLauncher); +public: + LLProcessLauncher(); + virtual ~LLProcessLauncher(); + + void setExecutable(const std::string &executable); + void setWorkingDirectory(const std::string &dir); + + void clearArguments(); + void addArgument(const std::string &arg); + void addArgument(const char *arg); + + int launch(void); + bool isRunning(void); + + // Attempt to kill the process -- returns true if the process is no longer running when it returns. + // Note that even if this returns false, the process may exit some time after it's called. + bool kill(void); + + // Use this if you want the external process to continue execution after the LLProcessLauncher instance controlling it is deleted. + // Normally, the destructor will attempt to kill the process and wait for termination. + // This should only be used if the viewer is about to exit -- otherwise, the child process will become a zombie after it exits. + void orphan(void); + + // This needs to be called periodically on Mac/Linux to clean up zombie processes. + static void reap(void); +private: + std::string mExecutable; + std::string mWorkingDir; + std::vector mLaunchArguments; + +#if LL_WINDOWS + HANDLE mProcessHandle; +#else + pid_t mProcessID; +#endif +}; + +#endif // LL_LLPROCESSLAUNCHER_H diff --git a/linden/indra/llinventory/llparcel.cpp b/linden/indra/llinventory/llparcel.cpp index 9c27476..547862f 100644 --- a/linden/indra/llinventory/llparcel.cpp +++ b/linden/indra/llinventory/llparcel.cpp @@ -199,6 +199,12 @@ void LLParcel::init(const LLUUID &owner_id, mObscureMusic = 1; mMediaWidth = 0; mMediaHeight = 0; + setMediaCurrentURL(LLStringUtil::null); + mMediaURLFilterEnable = FALSE; + mMediaURLFilterList = LLSD::emptyArray(); + mMediaAllowNavigate = TRUE; + mMediaURLTimeout = 0.0f; + mMediaPreventCameraZoom = FALSE; mGroupID.setNull(); @@ -314,6 +320,56 @@ void LLParcel::setMediaHeight(S32 height) { mMediaHeight = height; } + +void LLParcel::setMediaCurrentURL(const std::string& url) +{ + mMediaCurrentURL = url; + // The escaping here must match the escaping in the database + // abstraction layer if it's ever added. + // This should really filter the url in some way. Other than + // simply requiring non-printable. + LLStringFn::replace_nonprintable_in_ascii(mMediaCurrentURL, LL_UNKNOWN_CHAR); + +} + +void LLParcel::setMediaURLResetTimer(F32 time) +{ + mMediaResetTimer.start(); + mMediaResetTimer.setTimerExpirySec(time); +} + +void LLParcel::setMediaURLFilterList(LLSD list) +{ + // sanity check LLSD + // must be array of strings + if (!list.isArray()) + { + return; + } + + for (S32 i = 0; i < list.size(); i++) + { + if (!list[i].isString()) + return; + } + + // can't be too big + const S32 MAX_SIZE = 50; + if (list.size() > MAX_SIZE) + { + LLSD new_list = LLSD::emptyArray(); + + for (S32 i = 0; i < llmin(list.size(), MAX_SIZE); i++) + { + new_list.append(list[i]); + } + + list = new_list; + } + + mMediaURLFilterList = list; +} + // virtual void LLParcel::setLocalID(S32 local_id) { @@ -568,6 +624,34 @@ BOOL LLParcel::importAccessEntry(std::istream& input_stream, LLAccessEntry* entr return input_stream.good(); } +BOOL LLParcel::importMediaURLFilter(std::istream& input_stream, std::string& url) +{ + skip_to_end_of_next_keyword("{", input_stream); + + while(input_stream.good()) + { + skip_comments_and_emptyspace(input_stream); + std::string line, keyword, value; + get_line(line, input_stream, MAX_STRING); + get_keyword_and_value(keyword, value, line); + + if ("}" == keyword) + { + break; + } + else if ("url" == keyword) + { + url = value; + } + else + { + llwarns << "Unknown keyword in parcel media url filter section: <" + << keyword << ">" << llendl; + } + } + return input_stream.good(); +} + // Assumes we are in a block "ParcelData" void LLParcel::packMessage(LLMessageSystem* msg) { @@ -606,9 +690,15 @@ void LLParcel::packMessage(LLSD& msg) msg["media_height"] = getMediaHeight(); msg["auto_scale"] = getMediaAutoScale(); msg["media_loop"] = getMediaLoop(); + msg["media_current_url"] = getMediaCurrentURL(); msg["obscure_media"] = getObscureMedia(); msg["obscure_music"] = getObscureMusic(); msg["media_id"] = getMediaID(); + msg["media_allow_navigate"] = getMediaAllowNavigate(); + msg["media_prevent_camera_zoom"] = getMediaPreventCameraZoom(); + msg["media_url_timeout"] = getMediaURLTimeout(); + msg["media_url_filter_enable"] = getMediaURLFilterEnable(); + msg["media_url_filter_list"] = getMediaURLFilterList(); msg["group_id"] = getGroupID(); msg["pass_price"] = mPassPrice; msg["pass_hours"] = mPassHours; @@ -678,6 +768,21 @@ void LLParcel::unpackMessage(LLMessageSystem* msg) mObscureMedia = true; mObscureMusic = true; } + + if(msg->getNumberOfBlocks("MediaLinkSharing") > 0) + { + msg->getString("MediaLinkSharing", "MediaCurrentURL", buffer); + setMediaCurrentURL(buffer); + msg->getU8 ( "MediaLinkSharing", "MediaAllowNavigate", mMediaAllowNavigate ); + msg->getU8 ( "MediaLinkSharing", "MediaURLFilterEnable", mMediaURLFilterEnable ); + msg->getU8 ( "MediaLinkSharing", "MediaPreventCameraZoom", mMediaPreventCameraZoom ); + msg->getF32( "MediaLinkSharing", "MediaURLTimeout", mMediaURLTimeout); + } + else + { + setMediaCurrentURL(LLStringUtil::null); + } + } void LLParcel::packAccessEntries(LLMessageSystem* msg, @@ -994,6 +1099,20 @@ BOOL LLParcel::isSaleTimerExpired(const U64& time) return expired; } +BOOL LLParcel::isMediaResetTimerExpired(const U64& time) +{ + if (mMediaResetTimer.getStarted() == FALSE) + { + return FALSE; + } + BOOL expired = mMediaResetTimer.checkExpirationAndReset(0.0); + if (expired) + { + mMediaResetTimer.stop(); + } + return expired; +} + void LLParcel::startSale(const LLUUID& buyer_id, BOOL is_buyer_group) { @@ -1117,6 +1236,12 @@ void LLParcel::clearParcel() mObscureMusic = 1; mMediaWidth = 0; mMediaHeight = 0; + setMediaCurrentURL(LLStringUtil::null); + setMediaURLFilterList(LLSD::emptyArray()); + setMediaURLFilterEnable(FALSE); + setMediaAllowNavigate(TRUE); + setMediaPreventCameraZoom(FALSE); + setMediaURLTimeout(0.0f); setMusicURL(LLStringUtil::null); setInEscrow(FALSE); setAuthorizedBuyerID(LLUUID::null); diff --git a/linden/indra/llinventory/llparcel.h b/linden/indra/llinventory/llparcel.h index 6f5ae87..47571d0 100644 --- a/linden/indra/llinventory/llparcel.h +++ b/linden/indra/llinventory/llparcel.h @@ -247,6 +247,14 @@ public: void setObscureMusic( U8 flagIn ) { mObscureMusic = flagIn; } void setMediaWidth(S32 width); void setMediaHeight(S32 height); + void setMediaCurrentURL(const std::string& url); + void setMediaURLFilterEnable(U8 enable) { mMediaURLFilterEnable = enable; } + void setMediaURLFilterList(LLSD list); + void setMediaAllowNavigate(U8 enable) { mMediaAllowNavigate = enable; } + void setMediaURLTimeout(F32 timeout) { mMediaURLTimeout = timeout; } + void setMediaPreventCameraZoom(U8 enable) { mMediaPreventCameraZoom = enable; } + + void setMediaURLResetTimer(F32 time); virtual void setLocalID(S32 local_id); // blow away all the extra crap lurking in parcels, including urls, access lists, etc @@ -300,6 +308,7 @@ public: // BOOL importStream(std::istream& input_stream); BOOL importAccessEntry(std::istream& input_stream, LLAccessEntry* entry); // BOOL exportStream(std::ostream& output_stream); + BOOL importMediaURLFilter(std::istream& input_stream, std::string& url); void packMessage(LLMessageSystem* msg); void packMessage(LLSD& msg); @@ -341,8 +350,15 @@ public: S32 getMediaHeight() const { return mMediaHeight; } U8 getMediaAutoScale() const { return mMediaAutoScale; } U8 getMediaLoop() const { return mMediaLoop; } + const std::string& getMediaCurrentURL() const { return mMediaCurrentURL; } U8 getObscureMedia() const { return mObscureMedia; } U8 getObscureMusic() const { return mObscureMusic; } + U8 getMediaURLFilterEnable() const { return mMediaURLFilterEnable; } + LLSD getMediaURLFilterList() const { return mMediaURLFilterList; } + U8 getMediaAllowNavigate() const { return mMediaAllowNavigate; } + F32 getMediaURLTimeout() const { return mMediaURLTimeout; } + U8 getMediaPreventCameraZoom() const { return mMediaPreventCameraZoom; } + S32 getLocalID() const { return mLocalID; } const LLUUID& getOwnerID() const { return mOwnerID; } const LLUUID& getGroupID() const { return mGroupID; } @@ -418,6 +434,7 @@ public: BOOL getRecordTransaction() const { return mRecordTransaction; } void setRecordTransaction(BOOL record) { mRecordTransaction = record; } + BOOL isMediaResetTimerExpired(const U64& time); // more accessors U32 getParcelFlags() const { return mParcelFlags; } @@ -595,6 +612,8 @@ protected: LLVector3 mUserLookAt; ELandingType mLandingType; LLTimer mSaleTimerExpires; + LLTimer mMediaResetTimer; + S32 mGraceExtension; BOOL mRecordTransaction; @@ -624,9 +643,15 @@ protected: S32 mMediaHeight; U8 mMediaAutoScale; U8 mMediaLoop; + std::string mMediaCurrentURL; U8 mObscureMedia; U8 mObscureMusic; LLUUID mMediaID; + U8 mMediaURLFilterEnable; + LLSD mMediaURLFilterList; + U8 mMediaAllowNavigate; + U8 mMediaPreventCameraZoom; + F32 mMediaURLTimeout; S32 mPassPrice; F32 mPassHours; LLVector3 mAABBMin; diff --git a/linden/indra/llmath/CMakeLists.txt b/linden/indra/llmath/CMakeLists.txt index e5ec3e1..c05bf1d 100644 --- a/linden/indra/llmath/CMakeLists.txt +++ b/linden/indra/llmath/CMakeLists.txt @@ -83,3 +83,4 @@ set_source_files_properties(${llmath_HEADER_FILES} list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES}) add_library (llmath ${llmath_SOURCE_FILES}) +add_dependencies(llmath prepare) diff --git a/linden/indra/llmath/llmath.h b/linden/indra/llmath/llmath.h index 9f8e539..0de568c 100644 --- a/linden/indra/llmath/llmath.h +++ b/linden/indra/llmath/llmath.h @@ -35,6 +35,7 @@ #include #include +#include #include "lldefs.h" #include "llstl.h" // *TODO: Remove when LLString is gone #include "llstring.h" // *TODO: Remove when LLString is gone @@ -60,7 +61,9 @@ #endif // Single Precision Floating Point Routines -#if _MSC_VER < 1400 +#ifndef fsqrtf +#define fsqrtf(x) ((F32)sqrt((F64)(x))) +#endif #ifndef sqrtf #define sqrtf(x) ((F32)sqrt((F64)(x))) #endif @@ -81,11 +84,6 @@ #ifndef powf #define powf(x,y) ((F32)pow((F64)(x),(F64)(y))) #endif -#endif - -#ifndef fsqrtf -#define fsqrtf(x) sqrtf(x) -#endif const F32 GRAVITY = -9.8f; diff --git a/linden/indra/llmath/llvolume.cpp b/linden/indra/llmath/llvolume.cpp index 4c94a52..b0b8a94 100644 --- a/linden/indra/llmath/llvolume.cpp +++ b/linden/indra/llmath/llvolume.cpp @@ -3376,7 +3376,8 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, std::vector &segments, const LLVector3& obj_cam_vec, const LLMatrix4& mat, - const LLMatrix3& norm_mat) + const LLMatrix3& norm_mat, + S32 face_mask) { LLMemType m1(LLMemType::MTYPE_VOLUME); @@ -3384,12 +3385,17 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, normals.clear(); segments.clear(); + S32 cur_index = 0; //for each face for (face_list_t::iterator iter = mVolumeFaces.begin(); iter != mVolumeFaces.end(); ++iter) { const LLVolumeFace& face = *iter; + if (!(face_mask & (0x1 << cur_index++))) + { + continue; + } if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) { } diff --git a/linden/indra/llmath/llvolume.h b/linden/indra/llmath/llvolume.h index 2b1c60d..0b9002f 100644 --- a/linden/indra/llmath/llvolume.h +++ b/linden/indra/llmath/llvolume.h @@ -905,9 +905,13 @@ public: // returns number of triangle indeces required for path/profile mesh S32 getNumTriangleIndices() const; - void generateSilhouetteVertices(std::vector &vertices, std::vector &normals, std::vector &segments, const LLVector3& view_vec, - const LLMatrix4& mat, - const LLMatrix3& norm_mat); + void generateSilhouetteVertices(std::vector &vertices, + std::vector &normals, + std::vector &segments, + const LLVector3& view_vec, + const LLMatrix4& mat, + const LLMatrix3& norm_mat, + S32 face_index); //get the face index of the face that intersects with the given line segment at the point //closest to start. Moves end to the point of intersection. Returns -1 if no intersection. diff --git a/linden/indra/llmath/v3math.h b/linden/indra/llmath/v3math.h index 7f96800..8c65d93 100644 --- a/linden/indra/llmath/v3math.h +++ b/linden/indra/llmath/v3math.h @@ -411,8 +411,8 @@ inline bool operator<(const LLVector3 &a, const LLVector3 &b) return (a.mV[0] < b.mV[0] || (a.mV[0] == b.mV[0] && (a.mV[1] < b.mV[1] - || (a.mV[1] == b.mV[1]) - && a.mV[2] < b.mV[2]))); + || ((a.mV[1] == b.mV[1]) + && a.mV[2] < b.mV[2])))); } inline const LLVector3& operator+=(LLVector3 &a, const LLVector3 &b) diff --git a/linden/indra/llmedia/CMakeLists.txt b/linden/indra/llmedia/CMakeLists.txt deleted file mode 100644 index c7b5cd1..0000000 --- a/linden/indra/llmedia/CMakeLists.txt +++ /dev/null @@ -1,79 +0,0 @@ -# -*- cmake -*- - -project(llmedia) - -include(00-Common) -include(LLAudio) -include(LLCommon) -include(LLImage) -include(LLMath) -include(LLMedia) -include(LLMessage) -include(LLWindow) -include(Mozlib) - -include_directories( - ${GSTREAMER_INCLUDE_DIRS} - ${GSTREAMER_PLUGINS_BASE_INCLUDE_DIRS} - ${LLAUDIO_INCLUDE_DIRS} - ${LLCOMMON_INCLUDE_DIRS} - ${LLIMAGE_INCLUDE_DIRS} - ${LLMATH_INCLUDE_DIRS} - ${LLMESSAGE_INCLUDE_DIRS} - ${LLWINDOW_INCLUDE_DIRS} - ) - -set(llmedia_SOURCE_FILES - llmediaimplcommon.cpp - llmediaimplexample1.cpp - llmediaimplexample2.cpp - llmediaimplfactory.cpp - llmediamanager.cpp - llmediaimplgstreamer.cpp - llmediaimplgstreamervidplug.cpp - llgstplaythread.cpp - ) - -set(llmedia_HEADER_FILES - CMakeLists.txt - - llmediabase.h - llmediaemitter.h - llmediaimplcommon.h - llmediaimplexample1.h - llmediaimplexample2.h - llmediaimplfactory.h - llmediaimplregister.h - llmediamanager.h - llmediaobserver.h - llmediaimplgstreamer.h - llmediaimplgstreamervidplug.h - llgstplaythread.h - ) - - # Work around a bad interaction between broken gstreamer headers and - # g++ 4.3's increased strictness. - - if (${CXX_VERSION} MATCHES "4.[23]") - set_source_files_properties(llmediaimplgstreamervidplug.cpp PROPERTIES - COMPILE_FLAGS -Wno-error=write-strings) - endif (${CXX_VERSION} MATCHES "4.[23]") - -if (MOZLIB) - list(APPEND llmedia_SOURCE_FILES llmediaimplllmozlib.cpp) - - list(APPEND llmedia_HEADER_FILES llmediaimplllmozlib.h) -endif (MOZLIB) - -set_source_files_properties(${llmedia_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE) - -list(APPEND llmedia_SOURCE_FILES ${llmedia_HEADER_FILES}) - -add_library (llmedia ${llmedia_SOURCE_FILES}) -target_link_libraries( - llmedia - ${GSTREAMER_LIBRARIES} - ${GSTREAMER_PLUGINS_BASE_LIBRARIES} - ${QUICKTIME_LIBRARY} - ) diff --git a/linden/indra/llmedia/llgstplaythread.cpp b/linden/indra/llmedia/llgstplaythread.cpp deleted file mode 100644 index 152f9d9..0000000 --- a/linden/indra/llmedia/llgstplaythread.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @file llgstplaythread.cpp - * @author Jacek Antonelli - * @brief GStreamer playback management thread class - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2009, Jacek Antonelli - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * $/LicenseInfo$ - */ - -#include "llgstplaythread.h" -#include "llmediaimplgstreamer.h" - -LLGstPlayThread:: -LLGstPlayThread( LLMediaImplCommon *impl, - const std::string& name, apr_pool_t *poolp ): - LLThread( name, poolp ), - mMediaImpl( impl ) -{ -} - - -LLGstPlayThread::~LLGstPlayThread() -{ -} - - -// virtual -void LLGstPlayThread::run() -{ - ((LLMediaImplGStreamer *)mMediaImpl)->startPlay(); -} diff --git a/linden/indra/llmedia/llgstplaythread.h b/linden/indra/llmedia/llgstplaythread.h deleted file mode 100644 index c3c36a7..0000000 --- a/linden/indra/llmedia/llgstplaythread.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @file llgstplaythread.h - * @author Jacek Antonelli - * @brief GStreamer playback management thread class - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2009, Jacek Antonelli - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * $/LicenseInfo$ - */ - - -#ifndef LL_LLGSTPLAYTHREAD_H -#define LL_LLGSTPLAYTHREAD_H - -#include "linden_common.h" - -#include "llthread.h" -#include "llmediaimplcommon.h" - -class LLGstPlayThread: public LLThread -{ - public: - - LLGstPlayThread( LLMediaImplCommon *impl, - const std::string& name, apr_pool_t *poolp ); - - ~LLGstPlayThread(); - - virtual void run(); - - private: - - // Actually, this will really only be an LLMediaImplGStreamer. - // But we have to jump through some hoops to mutual pointer-holding. - // There may be a better way, but I don't have the motivation to find it. - LLMediaImplCommon *mMediaImpl; -}; - - -#endif // LL_LLGSTPLAYTHREAD_H diff --git a/linden/indra/llmedia/llmediabase.h b/linden/indra/llmedia/llmediabase.h deleted file mode 100644 index 3bcee4e..0000000 --- a/linden/indra/llmedia/llmediabase.h +++ /dev/null @@ -1,265 +0,0 @@ -/** - * @file llmediabase.h - * @author Callum Prentice - * @date 2007-10-22 00:00:00 - * @brief Abstract class that defines LLMedia public interface - * - * $LicenseInfo:firstyear=2005&license=viewergpl$ - * - * Copyright (c) 2005-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLMEDIABASE_H -#define LLMEDIABASE_H - -#if LL_LLMOZLIB_ENABLED && !defined ( MOZILLA_INTERNAL_API ) - // Without this, nsTAString.h errors out with: - // "Cannot use internal string classes without MOZILLA_INTERNAL_API defined. Use the frozen header nsStringAPI.h instead." - // It might be worth our while to figure out if we can use the frozen apis at some point... - #define MOZILLA_INTERNAL_API 1 -#endif - -#include - -class LLMediaObserver; -class LLMediaImplMakerBase; - -class LLMediaBase -{ - public: - LLMediaBase() {}; - virtual ~LLMediaBase() {}; - - //////////////////////////////////////////////////////////////////////////////// - // housekeeping - - // local initialization, called by the media manager when creating a source - virtual bool init() = 0; - - // undoes everything init() didm called by the media manager when destroying a source - virtual bool reset() = 0; - - - /* Mirrors GStreamer debug levels. */ - enum EDebugLevel { - DEBUG_LEVEL_NONE = 0, - DEBUG_LEVEL_ERROR, - DEBUG_LEVEL_WARNING, - DEBUG_LEVEL_INFO, - DEBUG_LEVEL_DEBUG, - DEBUG_LEVEL_LOG, - DEBUG_LEVEL_COUNT, - }; - - /* Set the debug verbosity level. Only implemented for GStreamer. */ - virtual bool setDebugLevel( EDebugLevel level ) = 0; - - // accessor for MIME type - virtual bool setMimeType( const std::string mime_type ) = 0; - virtual std::string getMimeType() const = 0; - - // accessor for intial URL. Note that this may have changed under the hood - // so pass back the original URL seeded to this impl - virtual std::string getMediaURL() const = 0; - - // ask impl for version string - virtual std::string getVersion() = 0; - - // set/clear URL to visit when a 404 page is reached - virtual bool set404RedirectUrl( std::string redirect_url ) = 0; - virtual bool clr404RedirectUrl() = 0; - - // sets the background color of the browser window - virtual bool setBackgroundColor( unsigned int red, unsigned int green, unsigned int blue ) const = 0; - - // sets the color of the caret in media impls that have one - virtual bool setCaretColor( unsigned int red, unsigned int green, unsigned int blue ) const = 0; - - //////////////////////////////////////////////////////////////////////////////// - // media management - - // needs to be called regularly to make media stream update itself - virtual bool updateMedia() = 0; - - // allows you to request a change in media width, height - may fail if media doesn't support size change - virtual bool setRequestedMediaSize( int media_width, int media_height ) = 0; - - // gets media width (may change throughout lifetime of media stream) - event emitted when media size changed too - virtual int getMediaWidth() const = 0; - - // gets media height (may change throughout lifetime of media stream) - event emitted when media size changed too - virtual int getMediaHeight() const = 0; - - // allows you to try to explicitly change media depth - may fail if media doesn't support depth change - virtual bool setMediaDepth( int media_depth ) = 0; - - // gets media depth (may change throughout lifetime of media stream) - event emitted when media depth changed too - virtual int getMediaDepth() const = 0; - - // gets size of media buffer for current frame (might NOT be the same as media width * height * depth) - virtual int getMediaBufferSize() const = 0; - - // returns pointer to raw media pixels - virtual unsigned char* getMediaData() = 0; - - // returns the size of the data, which may be different that the size of the media - virtual int getMediaDataWidth() const = 0; - virtual int getMediaDataHeight() const = 0; - - //////////////////////////////////////////////////////////////////////////////// - // texture management - - // gets internal format to use for OpenGL texture - virtual int getTextureFormatInternal() const = 0; - - // gets primary format to use for OpenGL texture - virtual int getTextureFormatPrimary() const = 0; - - // gets format type to use for OpenGL texture - virtual int getTextureFormatType() const = 0; - - - - - //////////////////////////////////////////////////////////////////////////////// - // audio - - // set/get control volume from media stream if present - virtual bool setVolume( float volume ) = 0; - virtual float getVolume() const = 0; - - - //////////////////////////////////////////////////////////////////////////////// - // transport control etc. - enum ECommand { - COMMAND_NONE = 0, - COMMAND_STOP = 1, - COMMAND_START = 2, - COMMAND_PAUSE = 4, - COMMAND_BACK = 5, - COMMAND_FORWARD = 6 - }; - enum EStatus { - STATUS_UNKNOWN = 0, - STATUS_INITIALIZING = 1, - STATUS_NAVIGATING = 2, - STATUS_STARTED = 3, - STATUS_STOPPED = 4, - STATUS_PAUSED = 6, - STATUS_RESETTING = 7, - STATUS_DEAD = 8 - }; - virtual bool addCommand( ECommand cmd ) = 0; - virtual bool clearCommand() = 0; - virtual bool updateCommand() = 0; - virtual EStatus getStatus() = 0; - virtual bool seek( double time ) = 0; - virtual bool setLooping( bool enable) = 0; - virtual bool isLooping() = 0; - - //////////////////////////////////////////////////////////////////////////////// - // scaling - - // autoscale means try to scale media to size of texture - may fail if media doesn't support size change - virtual bool setAutoScaled( bool auto_scaled ) = 0; - virtual bool isAutoScaled() const = 0; - - - //////////////////////////////////////////////////////////////////////////////// - // mouse and keyboard interaction - virtual bool mouseDown( int x_pos, int y_pos ) = 0; - virtual bool mouseUp( int x_pos, int y_pos ) = 0; - virtual bool mouseMove( int x_pos, int y_pos ) = 0; - virtual bool keyPress( int key_code ) = 0; - virtual bool scrollByLines( int lines ) = 0; - virtual bool focus( bool focus ) = 0; - virtual bool unicodeInput( unsigned long uni_char ) = 0; - virtual bool mouseLeftDoubleClick( int x_pos, int y_pos ) = 0; - - - //////////////////////////////////////////////////////////////////////////////// - // navigation - virtual bool navigateTo( const std::string url ) = 0; - virtual bool navigateForward() = 0; - virtual bool navigateBack() = 0; - virtual bool canNavigateForward() = 0; - virtual bool canNavigateBack() = 0; - - //////////////////////////////////////////////////////////////////////////////// - // caching/cookies - virtual bool enableCookies( bool enable ) = 0; - virtual bool clearCache() = 0; - virtual bool clearCookies() = 0; - - //////////////////////////////////////////////////////////////////////////////// - // proxy - virtual bool enableProxy(bool enable, std::string proxy_host_name, int proxy_port) = 0; - - //////////////////////////////////////////////////////////////////////////////// - // observer interface - virtual bool addObserver( LLMediaObserver* subject ) = 0; - virtual bool remObserver( LLMediaObserver* subject ) = 0; - - //////////////////////////////////////////////////////////////////////////////// - // factory interface - virtual void setImplMaker(LLMediaImplMakerBase* impl_maker) = 0; - - //////////////////////////////////////////////////////////////////////////////// - // type registry interface - virtual bool supportsMediaType(std::string scheme, std::string type) = 0; -}; - -////////////////////////////////////////////////////////////// -// media key codes - (mirroring mozilla's values) -const unsigned long LL_MEDIA_KEY_BACKSPACE = 0x08; -const unsigned long LL_MEDIA_KEY_TAB = 0x09; -const unsigned long LL_MEDIA_KEY_RETURN = 0x0D; -const unsigned long LL_MEDIA_KEY_PAD_RETURN = 0x0E; -const unsigned long LL_MEDIA_KEY_ESCAPE = 0x1B; -const unsigned long LL_MEDIA_KEY_PAGE_UP = 0x21; -const unsigned long LL_MEDIA_KEY_PAGE_DOWN = 0x22; -const unsigned long LL_MEDIA_KEY_END = 0x23; -const unsigned long LL_MEDIA_KEY_HOME = 0x24; -const unsigned long LL_MEDIA_KEY_LEFT = 0x25; -const unsigned long LL_MEDIA_KEY_UP = 0x26; -const unsigned long LL_MEDIA_KEY_RIGHT = 0x27; -const unsigned long LL_MEDIA_KEY_DOWN = 0x28; -const unsigned long LL_MEDIA_KEY_INSERT = 0x2D; -const unsigned long LL_MEDIA_KEY_DELETE = 0x2E; - -////////////////////////////////////////////////////////////// -// media frame buffer types - (mirroring GL values) -const int LL_MEDIA_UNSIGNED_BYTE = 0x1401; -const int LL_MEDIA_RGB = 0x1907; -const int LL_MEDIA_RGBA = 0x1908; -const int LL_MEDIA_RGB8 = 0x8051; -const int LL_MEDIA_UNSIGNED_INT_8_8_8_8 = 0x8035; -const int LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV = 0x8367; -const int LL_MEDIA_BGR = 0x80E0; -const int LL_MEDIA_BGRA = 0x80E1; - - -#endif // LLMEDIABASE_H diff --git a/linden/indra/llmedia/llmediaemitter.h b/linden/indra/llmedia/llmediaemitter.h deleted file mode 100644 index ef3caeb..0000000 --- a/linden/indra/llmedia/llmediaemitter.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @file llmediaemitter.h - * @author Callum Prentice - * @date 2007-10-22 00:00:00 - * @brief Manages and emits events to observers - * - * $LicenseInfo:firstyear=2005&license=viewergpl$ - * - * Copyright (c) 2005-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLMEDIAEMITTER_H -#define LLMEDIAEMITTER_H - -#include -#include -#include - -/////////////////////////////////////////////////////////////////////////////// -// -template< class T > -class LLMediaEmitter -{ - public: - LLMediaEmitter() { }; - ~LLMediaEmitter() { }; - - typedef typename T::EventType EventType; - typedef std::list< T* > ObserverContainer; - typedef void( T::*observerMethod )( const EventType& ); - - /////////////////////////////////////////////////////////////////////////////// - // - bool addObserver( T* observer_in ) - { - if ( ! observer_in ) - return false; - - if ( std::find( observers.begin(), observers.end(), observer_in) != observers.end() ) - return false; - - observers.push_back( observer_in ); - - return true; - }; - - /////////////////////////////////////////////////////////////////////////////// - // - bool remObserver( T* observer_in ) - { - if ( ! observer_in ) - return false; - - observers.remove( observer_in ); - observers.remove( observer_in ); - observers.remove( observer_in ); - - - - return true; - }; - - /////////////////////////////////////////////////////////////////////////////// - // - void update( observerMethod method, const EventType& msgIn ) - { - typename std::list< T* >::iterator iter = observers.begin(); - - while( iter != observers.end() ) - { - ( ( *iter )->*method )( msgIn ); - - ++iter; - }; - }; - - protected: - ObserverContainer observers; -}; - -#endif // LLMEDIAEMITTER_H diff --git a/linden/indra/llmedia/llmediaimplcommon.cpp b/linden/indra/llmedia/llmediaimplcommon.cpp deleted file mode 100644 index 166e86d..0000000 --- a/linden/indra/llmedia/llmediaimplcommon.cpp +++ /dev/null @@ -1,552 +0,0 @@ -/** - * @file llmediaimplcommon.cpp - * @brief Common impl functionality - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llmediaimplcommon.h" -#include "llmediaemitter.h" -#include "llmediaimplfactory.h" -#include "llmediaobserver.h" - -#ifdef WIN32 - // platform specific includes needed before OpenGL header - #include - #include -#elif defined(__APPLE__) - // framework-style include path when building on the Mac. - #include -#else // Assume this is linux - // Linux, MESA headers, but not necessarily assuming MESA runtime. - // quotes so we get libraries/.../GL/ version - #include "GL/gl.h" -#endif - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -LLMediaImplCommon::LLMediaImplCommon() : - mMimeType( std::string() ), - mInitialURL( std::string() ), - mImplMaker( NULL ), - mAutoScaled( false ), - mMediaWidth( 0 ), - mMediaPrevWidth( 0 ), - mMediaHeight( 0 ), - mMediaPrevHeight( 0 ), - mMediaDepth( 0 ), - mMediaPrevDepth( 0 ), - mMediaRowSpan( 0 ), - mMediaRequestedWidth( 0 ), - mMediaRequestedHeight( 0 ), - mCommand( LLMediaBase::COMMAND_NONE ), - mStatus( LLMediaBase::STATUS_UNKNOWN ), - mVolume( 0 ), - mLooping( false ), - mDebugLevel( LLMediaBase::DEBUG_LEVEL_NONE ) -{ -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -LLMediaImplCommon::~LLMediaImplCommon() -{ -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::init() -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::reset() -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::setDebugLevel( LLMediaBase::EDebugLevel level ) -{ - mDebugLevel = level; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::setMimeType( const std::string mime_type ) -{ - mMimeType = mime_type; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -std::string LLMediaImplCommon::getMimeType() const -{ - return mMimeType; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -std::string LLMediaImplCommon::getMediaURL() const -{ - return mInitialURL; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -std::string LLMediaImplCommon::getVersion() -{ - return std::string( "" ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::set404RedirectUrl( std::string redirect_url ) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::clr404RedirectUrl() -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::setBackgroundColor( unsigned int red, unsigned int green, unsigned int blue ) const -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::setCaretColor( unsigned int red, unsigned int green, unsigned int blue ) const -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::updateMedia() -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -unsigned char* LLMediaImplCommon::getMediaData() -{ - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -int LLMediaImplCommon::getMediaDataWidth() const -{ - return getMediaWidth(); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -int LLMediaImplCommon::getMediaDataHeight() const -{ - return getMediaHeight(); -} - - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::setMediaSize( int media_width, int media_height ) -{ - // if nothing changed, don't do anything - if ( ( mMediaWidth == media_width ) && - ( mMediaHeight == media_height ) ) - return false; - - // save old values so we can tell elsewhere if media size has changed - mMediaPrevWidth = mMediaWidth; - mMediaPrevHeight = mMediaHeight; - - mMediaWidth = media_width; - mMediaHeight = media_height; - - // only fire an event if the width changed - LLMediaEvent event( this ); - mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event ); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -int LLMediaImplCommon::getMediaWidth() const -{ - return mMediaWidth; -} - - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -int LLMediaImplCommon::getMediaHeight() const -{ - return mMediaHeight; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::setRequestedMediaSize(int width, int height) -{ - mMediaRequestedWidth = width; - mMediaRequestedHeight = height; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::setMediaDepth( int media_depth ) -{ - // if nothing changed, don't do anything - if ( mMediaDepth == media_depth ) - return false; - - // save old values so we can tell elsewhere if media size has changed - mMediaPrevDepth = mMediaDepth; - mMediaDepth = media_depth; - - // update value of rowspan too since it's based on media width & depth - mMediaRowSpan = mMediaWidth * mMediaDepth; - - // only fire an event if the depth changed - //LLMediaEvent event( this ); - //mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event ); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -int LLMediaImplCommon::getMediaDepth() const -{ - return mMediaDepth; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -int LLMediaImplCommon::getMediaBufferSize() const -{ - return mMediaRowSpan * mMediaHeight; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -int LLMediaImplCommon::getTextureFormatInternal() const -{ - return LL_MEDIA_RGB; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -int LLMediaImplCommon::getTextureFormatPrimary() const -{ - return LL_MEDIA_RGB; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -int LLMediaImplCommon::getTextureFormatType() const -{ - return LL_MEDIA_UNSIGNED_BYTE; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::setVolume( float volume ) -{ - mVolume = volume; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -float LLMediaImplCommon::getVolume() const -{ - return mVolume; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::addCommand( LLMediaBase::ECommand cmd ) -{ - // eventually will be a std::queue so you can add multiple commands - mCommand = cmd; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::clearCommand() -{ - // eventually will be a std::queue so you can add multiple commands - mCommand = LLMediaBase::COMMAND_NONE; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::updateCommand() -{ - if ( nextCommand() == LLMediaBase::COMMAND_START ) - { - setStatus( LLMediaBase::STATUS_STARTED ); - clearCommand(); - }; - - if ( nextCommand() == LLMediaBase::COMMAND_STOP ) - { - setStatus( LLMediaBase::STATUS_STOPPED ); - clearCommand(); - }; - - if ( nextCommand() == LLMediaBase::COMMAND_PAUSE ) - { - setStatus( LLMediaBase::STATUS_PAUSED ); - clearCommand(); - }; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// non-virtual (only impls use this) -LLMediaBase::ECommand LLMediaImplCommon::nextCommand() -{ - return mCommand; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -LLMediaBase::EStatus LLMediaImplCommon::getStatus() -{ - return mStatus; -} - -//////////////////////////////////////////////////////////////////////////////// -// non-virtual (only impls set this) -bool LLMediaImplCommon::setStatus( LLMediaBase::EStatus status ) -{ - mStatus = status; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::seek( double time ) -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::navigateTo( const std::string url ) -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::setAutoScaled( bool auto_scaled ) -{ - mAutoScaled = auto_scaled; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::isAutoScaled() const -{ - return mAutoScaled; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::mouseDown( int x_pos, int y_pos ) -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::mouseUp( int x_pos, int y_pos ) -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::mouseMove( int x_pos, int y_pos ) -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::keyPress( int key_code ) -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::scrollByLines( int lines ) -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::focus( bool focus ) -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::unicodeInput( unsigned long uni_char ) -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::mouseLeftDoubleClick( int x_pos, int y_pos ) -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::navigateForward() -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::navigateBack() -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::canNavigateForward() -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::canNavigateBack() -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::enableCookies( bool enable ) -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::clearCache() -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::clearCookies() -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual (derives from LLMediaBase) -bool LLMediaImplCommon::enableProxy(bool enable, std::string proxy_host_name, int proxy_port) -{ - return false; -} -//////////////////////////////////////////////////////////////////////////////// -// -bool LLMediaImplCommon::addObserver( LLMediaObserver* subject ) -{ - return mEventEmitter.addObserver( subject ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLMediaImplCommon::remObserver( LLMediaObserver* subject ) -{ - return mEventEmitter.remObserver( subject ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLMediaImplCommon::setImplMaker(LLMediaImplMakerBase* impl_maker) -{ - mImplMaker = impl_maker; -} -//////////////////////////////////////////////////////////////////////////////// -// -bool LLMediaImplCommon::supportsMediaType(std::string scheme, std::string type) -{ - int idx1 = type.find("/"); - int len = (idx1 == std::string::npos) ? 0 : idx1; - std::string category = type.substr(0,len); - - return mImplMaker->supportsScheme(scheme) || - mImplMaker->supportsMimeType(type) || - mImplMaker->supportsMimeTypeCategory(category); -} diff --git a/linden/indra/llmedia/llmediaimplcommon.h b/linden/indra/llmedia/llmediaimplcommon.h deleted file mode 100644 index 845429c..0000000 --- a/linden/indra/llmedia/llmediaimplcommon.h +++ /dev/null @@ -1,164 +0,0 @@ -/** - * @file llmediaimplcommon.h - * @brief Common impl functionality - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLMEDIAIMPLCOMMON_H -#define LLMEDIAIMPLCOMMON_H - -#include "llmediabase.h" -#include "llmediaemitter.h" -#include "llmediaobserver.h" - -#include - -class LLMediaImplMakerBase; - -class LLMediaImplCommon : - public LLMediaBase -{ - public: - LLMediaImplCommon(); - virtual ~LLMediaImplCommon(); - - //////////////////////////////////////////////////////////////////////////////// - // begin: default implementation of the abstract interface - // see llmediabase.h for documentation - - // housekeeping - virtual bool init(); - virtual bool reset(); - virtual bool setDebugLevel( LLMediaBase::EDebugLevel level ); - virtual bool setMimeType( const std::string url ); - virtual std::string getMimeType() const; - virtual std::string getMediaURL() const; - virtual std::string getVersion(); - virtual bool set404RedirectUrl( std::string redirect_url ); - virtual bool clr404RedirectUrl(); - virtual bool setBackgroundColor( unsigned int red, unsigned int green, unsigned int blue ) const; - virtual bool setCaretColor( unsigned int red, unsigned int green, unsigned int blue ) const; - - // media management - virtual bool updateMedia(); - virtual bool setRequestedMediaSize( int width, int height ); - virtual int getMediaWidth() const; - virtual int getMediaHeight() const; - virtual int getMediaDepth() const; - virtual int getMediaBufferSize() const; - virtual unsigned char* getMediaData(); - virtual int getMediaDataWidth() const; - virtual int getMediaDataHeight() const; - - // texture management - virtual int getTextureFormatInternal() const; - virtual int getTextureFormatPrimary() const; - virtual int getTextureFormatType() const; - - // audio - virtual bool setVolume( float volume ); - virtual float getVolume() const; - - // transport control - virtual bool addCommand( ECommand cmd ); - virtual bool clearCommand(); - virtual bool updateCommand(); - LLMediaBase::ECommand nextCommand(); - virtual LLMediaBase::EStatus getStatus(); - bool setStatus( LLMediaBase::EStatus status ); - - virtual bool seek( double time ); - virtual bool setLooping(bool enable) { mLooping = enable; return true; } - virtual bool isLooping() { return mLooping; } - virtual bool navigateTo( const std::string url ); - - // scaling - virtual bool setAutoScaled( bool auto_scaled ); - virtual bool isAutoScaled() const; - - // mouse and keyboard interaction - virtual bool mouseDown( int x_pos, int y_pos ); - virtual bool mouseUp( int x_pos, int y_pos ); - virtual bool mouseMove( int x_pos, int y_pos ); - virtual bool keyPress( int key_code ); - virtual bool scrollByLines( int lines ); - virtual bool focus( bool focus ); - virtual bool unicodeInput( unsigned long uni_char ); - virtual bool mouseLeftDoubleClick( int x_pos, int y_pos ); - - // navigation - virtual bool navigateForward(); - virtual bool navigateBack(); - virtual bool canNavigateForward(); - virtual bool canNavigateBack(); - - // caching/cookies - virtual bool enableCookies( bool enable ); - virtual bool clearCache(); - virtual bool clearCookies(); - - virtual bool enableProxy(bool enable, std::string proxy_host_name, int proxy_port); - - // observer interface - bool addObserver( LLMediaObserver* subject ); - bool remObserver( LLMediaObserver* subject ); - - // type registry interface - void setImplMaker(LLMediaImplMakerBase* impl_maker); - bool supportsMediaType(std::string scheme, std::string type); - - protected: - virtual bool setMediaSize( int width, int height ); - virtual bool setMediaDepth( int media_depth ); - - LLMediaEmitter< LLMediaObserver > mEventEmitter; - - // Back pointer to the construction object, which is used to discover types handled - // by the Impl, and meta data associated with the Impl. - LLMediaImplMakerBase* mImplMaker; - std::string mMimeType; - std::string mInitialURL; - bool mAutoScaled; - int mMediaWidth; - int mMediaPrevWidth; - int mMediaHeight; - int mMediaPrevHeight; - int mMediaDepth; - int mMediaPrevDepth; - int mMediaRowSpan; - int mMediaRequestedWidth; - int mMediaRequestedHeight; - float mVolume; - LLMediaBase::ECommand mCommand; - LLMediaBase::EStatus mStatus; - bool mLooping; - LLMediaBase::EDebugLevel mDebugLevel; -}; - -#endif // LLMEDIAIMPLCOMMON_H diff --git a/linden/indra/llmedia/llmediaimplexample1.cpp b/linden/indra/llmedia/llmediaimplexample1.cpp deleted file mode 100644 index fe7b7e2..0000000 --- a/linden/indra/llmedia/llmediaimplexample1.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/** - * @file llmediaimplexample1.cpp - * @brief Example 1 of a media impl concrete class - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llmediaimplexample1.h" -#include "llmediaimplregister.h" - -#include - -// register this impl with media manager factory -static LLMediaImplRegister sLLMediaImplExample1Reg( "LLMediaImplExample1", new LLMediaImplExample1Maker() ); - -#include - -#include - -/////////////////////////////////////////////////////////////////////////////// -// -LLMediaImplExample1Maker::LLMediaImplExample1Maker() -{ - // Register to handle the scheme - mSchema.push_back( "example1" ); -} - -/////////////////////////////////////////////////////////////////////////////// -// -LLMediaImplExample1::LLMediaImplExample1() : - mMediaPixels( 0 ) -{ - setRequestedMediaSize( 400, 200 ); - setMediaDepth( 3 ); - - srand( (unsigned int)(time( NULL )) ); -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) super-initialization - called once at application startup -bool LLMediaImplExample1::startup( LLMediaManagerData* init_data ) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) super-uninitialization - called once at application closedown -bool LLMediaImplExample1::closedown() -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplExample1::init() -{ - int buffer_size = getMediaBufferSize(); - - mMediaPixels = new unsigned char[ buffer_size ]; - - memset( mMediaPixels, 0xAA, buffer_size ); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplExample1::navigateTo( const std::string url ) -{ - std::cout << "LLMediaImplExample1::navigateTo" << std::endl; - - setStatus( LLMediaBase::STATUS_NAVIGATING ); - - // force a size change event for new URL - LLMediaEvent event( this ); - mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event ); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -std::string LLMediaImplExample1::getVersion() -{ - std::string version_string = "[" + sLLMediaImplExample1Reg.getImplName() + "] - " + "1.0.0.0"; - - return version_string; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplExample1::updateMedia() -{ - if ( mMediaPixels && getStatus() == LLMediaBase::STATUS_STARTED ) - { - // first time - make sure it's a few seconds back so first update happens immediately - static time_t t = time( 0 ) - 4; - - // selected time period elapsed (1 second) - if ( time( 0 ) - t > 1 ) - { - // display checkerboard - const int num_squares = rand() % 20 + 4; - int sqr1_r = rand() % 0x80; - int sqr1_g = rand() % 0x80; - int sqr1_b = rand() % 0x80; - int sqr2_r = rand() % 0x80; - int sqr2_g = rand() % 0x80; - int sqr2_b = rand() % 0x80; - - for ( int y1 = 0; y1 < num_squares; ++y1 ) - { - for ( int x1 = 0; x1 < num_squares; ++x1 ) - { - int px_start = getMediaWidth() * x1 / num_squares; - int px_end = ( getMediaWidth() * ( x1 + 1 ) ) / num_squares; - int py_start = getMediaHeight() * y1 / num_squares; - int py_end = ( getMediaHeight() * ( y1 + 1 ) ) / num_squares; - - for( int y2 = py_start; y2 < py_end; ++y2 ) - { - for( int x2 = px_start; x2 < px_end; ++x2 ) - { - int rowspan = getMediaWidth() * getMediaDepth(); - - if ( ( y1 % 2 ) ^ ( x1 % 2 ) ) - { - mMediaPixels[ y2 * rowspan + x2 * getMediaDepth() + 0 ] = sqr1_r; - mMediaPixels[ y2 * rowspan + x2 * getMediaDepth() + 1 ] = sqr1_g; - mMediaPixels[ y2 * rowspan + x2 * getMediaDepth() + 2 ] = sqr1_b; - } - else - { - mMediaPixels[ y2 * rowspan + x2 * getMediaDepth() + 0 ] = sqr2_r; - mMediaPixels[ y2 * rowspan + x2 * getMediaDepth() + 1 ] = sqr2_g; - mMediaPixels[ y2 * rowspan + x2 * getMediaDepth() + 2 ] = sqr2_b; - }; - }; - }; - }; - }; - - // emit an event to say that something in the media stream changed - LLMediaEvent event( this ); - mEventEmitter.update( &LLMediaObserver::onMediaContentsChange, event ); - - // reset time - t = time( 0 ); - - return true; - }; - }; - - // update the command (e.g. transport controls) state - updateCommand(); - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -unsigned char* LLMediaImplExample1::getMediaData() -{ - return mMediaPixels; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplExample1::reset() -{ - if ( mMediaPixels ) - { - delete [] mMediaPixels; - }; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplExample1::mouseMove( int x_pos, int y_pos ) -{ - if ( mMediaPixels && getStatus() == LLMediaBase::STATUS_STARTED ) - { - int base_pos = x_pos * getMediaDepth() + y_pos * getMediaDepth() * getMediaWidth(); - // example: write a bright pixel to the display when we move the mouse - mMediaPixels[ base_pos + 0 ] = rand() % 0x80 + 0x80; - mMediaPixels[ base_pos + 1 ] = rand() % 0x80 + 0x80; - mMediaPixels[ base_pos + 2 ] = rand() % 0x80 + 0x80; - - // emit an event to say that something in the media stream changed - LLMediaEvent event( this ); - mEventEmitter.update( &LLMediaObserver::onMediaContentsChange, event ); - }; - - return true; -} - - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplExample1::setRequestedMediaSize( int width, int height ) -{ - // we accept any size: - return setMediaSize(width, height); -} diff --git a/linden/indra/llmedia/llmediaimplexample1.h b/linden/indra/llmedia/llmediaimplexample1.h deleted file mode 100644 index 1b90e93..0000000 --- a/linden/indra/llmedia/llmediaimplexample1.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @file llmediaimplexample1.h - * @brief Example 1 of a media impl concrete class - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLMEDIAIMPLEXAMPLE1_H -#define LLMEDIAIMPLEXAMPLE1_H - -#include "llmediaimplcommon.h" -#include "llmediaimplfactory.h" - -class LLMediaManagerData; - -class LLMediaImplExample1 : - public LLMediaImplCommon -{ - public: - LLMediaImplExample1(); - - static bool startup( LLMediaManagerData* init_data ); - static bool closedown(); - - /* virtual */ bool init(); - /* virtual */ bool navigateTo( const std::string url ); - /* virtual */ bool updateMedia(); - /* virtual */ std::string getVersion(); - /* virtual */ unsigned char* getMediaData(); - /* virtual */ bool reset(); - /* virtual */ bool mouseMove( int x_pos, int y_pos ); - /* virtual */ bool setRequestedMediaSize( int width, int height ); - - private: - unsigned char* mMediaPixels; -}; - -class LLMediaImplExample1Maker : public LLMediaImplMaker -{ - public: - LLMediaImplExample1Maker(); - LLMediaImplExample1* create() - { - return new LLMediaImplExample1(); - } -}; - -#endif // LLMEDIAIMPLEXAMPLE1_H diff --git a/linden/indra/llmedia/llmediaimplexample2.cpp b/linden/indra/llmedia/llmediaimplexample2.cpp deleted file mode 100644 index 7590e19..0000000 --- a/linden/indra/llmedia/llmediaimplexample2.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/** - * @file llmediaimplexample2.cpp - * @brief Example 2 of a media impl concrete class - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llmediaimplexample2.h" -#include "llmediaimplregister.h" - -#include - -// register this impl with media manager factory -static LLMediaImplRegister sLLMediaImplExample2Reg( "LLMediaImplExample2", new LLMediaImplExample2Maker() ); - -#include -#include - -/////////////////////////////////////////////////////////////////////////////// -// -LLMediaImplExample2Maker::LLMediaImplExample2Maker() -{ - // Register to handle the scheme - mSchema.push_back( "example2." ); -} - -/////////////////////////////////////////////////////////////////////////////// -// -LLMediaImplExample2::LLMediaImplExample2() : - mMediaPixels( 0 ) -{ - setRequestedMediaSize( 500, 500 ); - setMediaDepth( 3 ); - - mXpos = ( getMediaWidth() / 2 ) + rand() % ( getMediaWidth() / 16 ) - ( getMediaWidth() / 32 ); - mYpos = ( getMediaHeight() / 2 ) + rand() % ( getMediaHeight() / 16 ) - ( getMediaHeight() / 32 ); - - srand( (unsigned int)(time( NULL )) ); -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) super-initialization - called once at application startup -bool LLMediaImplExample2::startup( LLMediaManagerData* init_data ) -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) super-uninitialization - called once at application closedown -bool LLMediaImplExample2::closedown() -{ - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplExample2::init() -{ - int buffer_size = getMediaBufferSize(); - - mMediaPixels = new unsigned char[ buffer_size ]; - - memset( mMediaPixels, 0x00, buffer_size ); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplExample2::navigateTo( const std::string url ) -{ - std::cout << "LLMediaImplExample2::navigateTo" << std::endl; - - setStatus( LLMediaBase::STATUS_NAVIGATING ); - - // force a size change event for new URL - LLMediaEvent event( this ); - mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event ); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -std::string LLMediaImplExample2::getVersion() -{ - std::string version_string = "[" + sLLMediaImplExample2Reg.getImplName() + "] - " + "1.0.0.0"; - - return version_string; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplExample2::updateMedia() -{ - if ( mMediaPixels && getStatus() == LLMediaBase::STATUS_STARTED ) - { - static int x_inc = rand() % 5 + 2; - static int y_inc = rand() % 5 + 2; - int block_size = 32; - - for( int y = 0; y < block_size; ++y ) - { - for( int x = 0; x < block_size; ++x ) - { - int rowspan = getMediaWidth() * getMediaDepth(); - mMediaPixels[ ( mXpos + x ) * getMediaDepth() + ( mYpos + y ) * rowspan + 0 ] = 0; - mMediaPixels[ ( mXpos + x ) * getMediaDepth() + ( mYpos + y ) * rowspan + 1 ] = 0; - mMediaPixels[ ( mXpos + x ) * getMediaDepth() + ( mYpos + y ) * rowspan + 2 ] = 0; - }; - }; - - if ( mXpos + x_inc < 0 || mXpos + x_inc >= getMediaWidth() - block_size ) - x_inc =- x_inc; - - if ( mYpos + y_inc < 0 || mYpos + y_inc >= getMediaHeight() - block_size ) - y_inc =- y_inc; - - mXpos += x_inc; - mYpos += y_inc; - - unsigned char col_r = rand() % 0xff; - unsigned char col_g = rand() % 0xff; - unsigned char col_b = rand() % 0xff; - - for( int y = 0; y < block_size; ++y ) - { - for( int x = 0; x < block_size; ++x ) - { - int rowspan = getMediaWidth() * getMediaDepth(); - mMediaPixels[ ( mXpos + x ) * getMediaDepth() + ( mYpos + y ) * rowspan + 0 ] = col_r; - mMediaPixels[ ( mXpos + x ) * getMediaDepth() + ( mYpos + y ) * rowspan + 1 ] = col_g; - mMediaPixels[ ( mXpos + x ) * getMediaDepth() + ( mYpos + y ) * rowspan + 2 ] = col_b; - }; - }; - - // emit an event to say that something in the media stream changed - LLMediaEvent event( this ); - mEventEmitter.update( &LLMediaObserver::onMediaContentsChange, event ); - }; - - // update the command (e.g. transport controls) state - updateCommand(); - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -unsigned char* LLMediaImplExample2::getMediaData() -{ - return mMediaPixels; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplExample2::reset() -{ - if ( mMediaPixels ) - { - delete [] mMediaPixels; - }; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplExample2::setRequestedMediaSize( int width, int height ) -{ - // we accept any size: - return setMediaSize(width, height); -} diff --git a/linden/indra/llmedia/llmediaimplexample2.h b/linden/indra/llmedia/llmediaimplexample2.h deleted file mode 100644 index 6a4f80b..0000000 --- a/linden/indra/llmedia/llmediaimplexample2.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file llmediaimplexample2.h - * @brief Example 2 of a media impl concrete class - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLMEDIAIMPLEXAMPLE2_H -#define LLMEDIAIMPLEXAMPLE2_H - -#include "llmediaimplcommon.h" -#include "llmediaimplfactory.h" - -class LLMediaManagerData; -class LLMediaImplMaker; - -class LLMediaImplExample2 : - public LLMediaImplCommon -{ - public: - LLMediaImplExample2(); - - static bool startup( LLMediaManagerData* init_data ); - static bool closedown(); - - /* virtual */ bool init(); - /* virtual */ bool navigateTo( const std::string url ); - /* virtual */ bool load( const std::string url ); - /* virtual */ std::string getVersion(); - /* virtual */ bool updateMedia(); - /* virtual */ unsigned char* getMediaData(); - /* virtual */ bool reset(); - /* virtual */ bool setRequestedMediaSize( int width, int height ); - - private: - unsigned char* mMediaPixels; - int mXpos; - int mYpos; -}; - -class LLMediaImplExample2Maker : public LLMediaImplMaker -{ - public: - LLMediaImplExample2Maker(); - LLMediaImplExample2* create() - { - return new LLMediaImplExample2(); - } -}; - -#endif // LLMEDIAIMPLEXAMPLE2_H diff --git a/linden/indra/llmedia/llmediaimplfactory.cpp b/linden/indra/llmedia/llmediaimplfactory.cpp deleted file mode 100644 index c5d098f..0000000 --- a/linden/indra/llmedia/llmediaimplfactory.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file llmediaimplfactory.cpp - * @brief Creates media impls that have registered themselves with LLMediaRegster - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llmediaimplfactory.h" - -#include - -LLMediaImplFactory* LLMediaImplFactory::sInstance = NULL; - -/////////////////////////////////////////////////////////////////////////////// -// static -LLMediaImplFactory* LLMediaImplFactory::getInstance() -{ - if ( ! sInstance ) - sInstance = new LLMediaImplFactory(); - - return sInstance; -} - -/////////////////////////////////////////////////////////////////////////////// -// -void LLMediaImplFactory::registerImpl( const std::string& impl_name, LLMediaImplMakerBase* impl_maker ) -{ - mNameImplMakerContainer.insert( name_impl_maker_container_t::value_type( impl_name, impl_maker ) ); -} - -/////////////////////////////////////////////////////////////////////////////// -// -LLMediaImplMakerBase* LLMediaImplFactory::getImplMaker( const std::string& scheme, const std::string& type ) -{ - name_impl_maker_container_t::const_iterator iter; - name_impl_maker_container_t::const_iterator begin = mNameImplMakerContainer.begin(); - name_impl_maker_container_t::const_iterator end = mNameImplMakerContainer.end(); - - for(iter = begin; iter != end; ++iter) - { - if(( *iter->second ).supportsScheme(scheme)) - { - return ( iter->second ); - } - } - - for(iter = begin; iter != end; ++iter) - { - if(( *iter->second ).supportsMimeType(type)) - { - return ( iter->second ); - } - } - int idx1 = type.find("/"); - int len = (idx1 == std::string::npos) ? 0 : idx1; - std::string category = type.substr(0,len); - for(iter = begin; iter != end; ++iter) - { - if(( *iter->second ).supportsMimeTypeCategory(category)) - { - return ( iter->second ); - } - } - - return NULL; -}; - -/////////////////////////////////////////////////////////////////////////////// -// -LLMediaImplMakerBase* LLMediaImplFactory::getImplMaker( const std::string& impl_name ) -{ - name_impl_maker_container_t::const_iterator found = mNameImplMakerContainer.find( impl_name ); - - if ( found == mNameImplMakerContainer.end() ) - { - return NULL; - }; - - return found->second; -} diff --git a/linden/indra/llmedia/llmediaimplfactory.h b/linden/indra/llmedia/llmediaimplfactory.h deleted file mode 100644 index 93a7cc1..0000000 --- a/linden/indra/llmedia/llmediaimplfactory.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file llmediaimplfactory.h - * @brief Creates media impls that have registered themselves with LLMediaRegster - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLMEDIAIMPLFACTORY_H -#define LLMEDIAIMPLFACTORY_H - -#include -#include -#include -#include - -#include "llmediabase.h" - -/////////////////////////////////////////////////////////////////////////////// -// -class LLMediaImplMakerBase -{ - public: - virtual bool supportsScheme(std::string scheme) = 0; - virtual bool supportsMimeType(std::string type) = 0; - virtual bool supportsMimeTypeCategory(std::string category) = 0; - virtual LLMediaBase* create() = 0; - virtual ~LLMediaImplMakerBase() {}; - - protected: - typedef std::vector vector_impl_registry_t; - vector_impl_registry_t mSchema; - vector_impl_registry_t mMimeTypes; - vector_impl_registry_t mMimeTypeCategories; -}; - -/////////////////////////////////////////////////////////////////////////////// -// -class LLMediaImplMaker : public LLMediaImplMakerBase -{ - public: - bool supportsScheme(std::string scheme) - { - vector_impl_registry_t::iterator found = std::find(mSchema.begin(), mSchema.end(), scheme); - return found != mSchema.end(); - } - bool supportsMimeType(std::string type) - { - vector_impl_registry_t::iterator found = std::find(mMimeTypes.begin(), mMimeTypes.end(), type); - return found != mMimeTypes.end(); - } - bool supportsMimeTypeCategory(std::string category) - { - vector_impl_registry_t::iterator found = std::find(mMimeTypeCategories.begin(), mMimeTypeCategories.end(), category); - return found != mMimeTypeCategories.end(); - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// -class LLMediaImplFactory -{ - public: - static LLMediaImplFactory* getInstance(); - void registerImpl( const std::string& impl_name, LLMediaImplMakerBase* impl_maker ); - LLMediaImplMakerBase* getImplMaker( const std::string& scheme, const std::string& type ); - LLMediaImplMakerBase* getImplMaker( const std::string& impl_name); - - private: - typedef std::map< std::string, LLMediaImplMakerBase* > name_impl_maker_container_t; - name_impl_maker_container_t mNameImplMakerContainer; - - static LLMediaImplFactory* sInstance; -}; - -#endif // LLMEDIAIMPLFACTORY_H diff --git a/linden/indra/llmedia/llmediaimplgstreamer.h b/linden/indra/llmedia/llmediaimplgstreamer.h deleted file mode 100644 index 8d2e756..0000000 --- a/linden/indra/llmedia/llmediaimplgstreamer.h +++ /dev/null @@ -1,164 +0,0 @@ -/** - * @file llmediaimplgstreamer.h - * @author Tofu Linden - * @brief implementation that supports media playback via GStreamer. - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -// header guard -#ifndef llmediaimplgstreamer_h -#define llmediaimplgstreamer_h - -#include "llmediaimplcommon.h" -#include "llmediaimplfactory.h" - -///#if LL_GSTREAMER_ENABLED - -extern "C" { -#include -} - -#include -#include "apr_pools.h" -#include "apr_dso.h" - - -#include "llmediaimplgstreamervidplug.h" -#include "llgstplaythread.h" - -class LLMediaManagerData; -class LLMediaImplMaker; - -/////////////////////////////////////////////////////////////////////////// -class LLMediaImplGStreamer: - public LLMediaImplCommon -{ - friend class LLGstPlayThread; - - public: - LLMediaImplGStreamer (); - virtual ~LLMediaImplGStreamer (); - - //////////////////////////////////////////////////////// - // implementation of the media public interface - - static bool startup( LLMediaManagerData* init_data ); - static bool closedown(); - - // Sets GST_PLUGIN_PATH env var for GStreamer. - static void set_gst_plugin_path(); - - /* virtual */ bool setDebugLevel( LLMediaBase::EDebugLevel level ); - - // Function given to GStreamer for handling debug messages - static void gstreamer_log(GstDebugCategory *category, - GstDebugLevel level, - const gchar *file, - const gchar *function, - gint line, - GObject *object, - GstDebugMessage *message, - gpointer data) -#if __GNUC__ - // recommended by the gstreamer docs - G_GNUC_NO_INSTRUMENT -#endif - ; - - /* virtual */ std::string getVersion(); - /* virtual */ bool navigateTo( const std::string url ); - /* virtual */ bool updateMedia(); - /* virtual */ unsigned char* getMediaData(); - /* virtual */ int getTextureFormatPrimary() const; - /* virtual */ int getTextureFormatType() const; - /* virtual */ int getTextureFormatInternal() const; - /* virtual */ bool seek( double time ); - /* virtual */ bool setVolume( float volume ); - - LLMediaEmitter< LLMediaObserver > getEventEmitter() const {return mEventEmitter;}; - - protected: - - void startPlay(); - - - private: - - // misc - bool unload(); - bool pause(); - bool stop(); - bool play(); - - static gboolean bus_callback (GstBus *bus, - GstMessage *message, - gpointer data); - - unsigned char* mediaData; - int mMediaRowbytes; - int mTextureFormatPrimary; - int mTextureFormatType; - - // GStreamer-specific - GMainLoop *mPump; // event pump for this media - GstElement *mPlaybin; - GstSLVideo *mVideoSink; - std::string mLastTitle; - GstState mState; - GstState getState() const { return mState; } - - LLGstPlayThread *mPlayThread; -}; - -class LLMediaImplGStreamerMaker : public LLMediaImplMaker -{ - public: - LLMediaImplGStreamerMaker(); - LLMediaImplGStreamer* create() - { - return new LLMediaImplGStreamer(); - } -}; - -///////////////////////////////////////////////////////////////////////// -// Debug/Info/Warning macros. -#define STDERRMSG(...) do{\ - fprintf(stderr, "%s:%d: ", __FUNCTION__, __LINE__);\ - fprintf(stderr, __VA_ARGS__);\ - fputc('\n',stderr);\ - }while(0) -#define NULLMSG(...) do{}while(0) - -#define DEBUGMSG NULLMSG -#define INFOMSG STDERRMSG -#define WARNMSG STDERRMSG -///////////////////////////////////////////////////////////////////////// - -///#endif // LL_GSTREAMER_ENABLED - -#endif // llmediaimplgstreamer_h diff --git a/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp b/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp deleted file mode 100644 index f2c0e88..0000000 --- a/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp +++ /dev/null @@ -1,448 +0,0 @@ -/** - * @file llmediaimplgstreamervidplug.h - * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -///#if LL_GSTREAMER_ENABLED - -#include "linden_common.h" - -#include -#include -#include - -#include "llthread.h" - -#include "llmediaimplgstreamervidplug.h" - -GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug); -#define GST_CAT_DEFAULT gst_slvideo_debug - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - ARG_0 -}; - -#define SLV_SIZECAPS ", width=(int){1,2,4,8,16,32,64,128,256,512,1024}, height=(int){1,2,4,8,16,32,64,128,256,512,1024} " -#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS ";" GST_VIDEO_CAPS_BGRx SLV_SIZECAPS - -static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ( - "sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (SLV_ALLCAPS) - ); - -GST_BOILERPLATE (GstSLVideo, gst_slvideo, GstVideoSink, - GST_TYPE_VIDEO_SINK); - -static void gst_slvideo_set_property (GObject * object, guint prop_id, - const GValue * value, - GParamSpec * pspec); -static void gst_slvideo_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static void -gst_slvideo_base_init (gpointer gclass) -{ - static GstElementDetails element_details = { - (gchar*)"PluginTemplate", - (gchar*)"Generic/PluginTemplate", - (gchar*)"Generic Template Element", - (gchar*)"Linden Lab" - }; - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_factory)); - gst_element_class_set_details (element_class, &element_details); -} - - -static void -gst_slvideo_finalize (GObject * object) -{ - GstSLVideo *slvideo; - slvideo = GST_SLVIDEO (object); - if (slvideo->caps) - { - gst_caps_unref(slvideo->caps); - } - - G_OBJECT_CLASS(parent_class)->finalize (object); -} - - -static GstFlowReturn -gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf) -{ - GstSLVideo *slvideo; - g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); - - slvideo = GST_SLVIDEO(bsink); - -#if 0 - fprintf(stderr, "\n\ntransferring a frame of %dx%d <- %p (%d)\n\n", - slvideo->width, slvideo->height, GST_BUFFER_DATA(buf), - slvideo->format); -#endif - if (GST_BUFFER_DATA(buf)) - { - // copy frame and frame info into neutral territory - GST_OBJECT_LOCK(slvideo); - slvideo->retained_frame_ready = TRUE; - slvideo->retained_frame_width = slvideo->width; - slvideo->retained_frame_height = slvideo->height; - slvideo->retained_frame_format = slvideo->format; - int rowbytes = - SLVPixelFormatBytes[slvideo->retained_frame_format] * - slvideo->retained_frame_width; - int needbytes = rowbytes * slvideo->retained_frame_width; - // resize retained frame hunk only if necessary - if (needbytes != slvideo->retained_frame_allocbytes) - { - delete[] slvideo->retained_frame_data; - slvideo->retained_frame_data = new unsigned char[needbytes]; - slvideo->retained_frame_allocbytes = needbytes; - - } - // copy the actual frame data to neutral territory - - // flipped, for GL reasons - for (int ypos=0; yposheight; ++ypos) - { - memcpy(&slvideo->retained_frame_data[(slvideo->height-1-ypos)*rowbytes], - &(((unsigned char*)GST_BUFFER_DATA(buf))[ypos*rowbytes]), - rowbytes); - } - // done with the shared data - GST_OBJECT_UNLOCK(slvideo); - } - - return GST_FLOW_OK; -} - - -static GstStateChangeReturn -gst_slvideo_change_state(GstElement * element, GstStateChange transition) -{ - GstSLVideo *slvideo; - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - - slvideo = GST_SLVIDEO (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - return ret; - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - slvideo->fps_n = 0; - slvideo->fps_d = 1; - GST_VIDEO_SINK_WIDTH(slvideo) = 0; - GST_VIDEO_SINK_HEIGHT(slvideo) = 0; - break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - - return ret; -} - - -static GstCaps * -gst_slvideo_get_caps (GstBaseSink * bsink) -{ - GstSLVideo *slvideo; - slvideo = GST_SLVIDEO(bsink); - - return gst_caps_ref (slvideo->caps); -} - - -/* this function handles the link with other elements */ -static gboolean -gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps) -{ - GstSLVideo *filter; - GstStructure *structure; - GstCaps *intersection; - - GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps); - - filter = GST_SLVIDEO(bsink); - - intersection = gst_caps_intersect (filter->caps, caps); - if (gst_caps_is_empty (intersection)) - { - // no overlap between our caps and requested caps - return FALSE; - } - gst_caps_unref(intersection); - - int width = 0; - int height = 0; - gboolean ret; - const GValue *fps; - const GValue *par; - structure = gst_caps_get_structure (caps, 0); - ret = gst_structure_get_int (structure, "width", &width); - ret = ret && gst_structure_get_int (structure, "height", &height); - fps = gst_structure_get_value (structure, "framerate"); - ret = ret && (fps != NULL); - par = gst_structure_get_value (structure, "pixel-aspect-ratio"); - if (!ret) - return FALSE; - - filter->width = width; - filter->height = height; - filter->fps_n = gst_value_get_fraction_numerator(fps); - filter->fps_d = gst_value_get_fraction_denominator(fps); - if (par) - { - filter->par_n = gst_value_get_fraction_numerator(par); - filter->par_d = gst_value_get_fraction_denominator(par); - } - else - { - filter->par_n = 1; - filter->par_d = 1; - } - GST_VIDEO_SINK_WIDTH(filter) = width; - GST_VIDEO_SINK_HEIGHT(filter) = height; - - filter->format = SLV_PF_UNKNOWN; - if (0 == strcmp(gst_structure_get_name(structure), - "video/x-raw-rgb")) - { - int red_mask; - int green_mask; - int blue_mask; - gst_structure_get_int(structure, "red_mask", &red_mask); - gst_structure_get_int(structure, "green_mask", &green_mask); - gst_structure_get_int(structure, "blue_mask", &blue_mask); - if ((unsigned int)red_mask == 0xFF000000 && - (unsigned int)green_mask == 0x00FF0000 && - (unsigned int)blue_mask == 0x0000FF00) - { - filter->format = SLV_PF_RGBX; - //fprintf(stderr, "\n\nPIXEL FORMAT RGB\n\n"); - } else if ((unsigned int)red_mask == 0x0000FF00 && - (unsigned int)green_mask == 0x00FF0000 && - (unsigned int)blue_mask == 0xFF000000) - { - filter->format = SLV_PF_BGRX; - //fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n"); - } - } - - return TRUE; -} - - -static gboolean -gst_slvideo_start (GstBaseSink * bsink) -{ - GstSLVideo *slvideo; - gboolean ret = TRUE; - - slvideo = GST_SLVIDEO(bsink); - - return ret; -} - -static gboolean -gst_slvideo_stop (GstBaseSink * bsink) -{ - GstSLVideo *slvideo; - slvideo = GST_SLVIDEO(bsink); - - // free-up retained frame buffer - GST_OBJECT_LOCK(slvideo); - slvideo->retained_frame_ready = FALSE; - delete[] slvideo->retained_frame_data; - slvideo->retained_frame_data = NULL; - slvideo->retained_frame_allocbytes = 0; - GST_OBJECT_UNLOCK(slvideo); - - return TRUE; -} - - -/* initialize the plugin's class */ -static void -gst_slvideo_class_init (GstSLVideoClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSinkClass *gstbasesink_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - - gobject_class->finalize = gst_slvideo_finalize; - gobject_class->set_property = gst_slvideo_set_property; - gobject_class->get_property = gst_slvideo_get_property; - - gstelement_class->change_state = gst_slvideo_change_state; - -#define LLGST_DEBUG_FUNCPTR(p) (p) - gstbasesink_class->get_caps = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_caps); - gstbasesink_class->set_caps = LLGST_DEBUG_FUNCPTR( gst_slvideo_set_caps); - //gstbasesink_class->buffer_alloc=LLGST_DEBUG_FUNCPTR(gst_slvideo_buffer_alloc); - //gstbasesink_class->get_times = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_times); - gstbasesink_class->preroll = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame); - gstbasesink_class->render = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame); - - gstbasesink_class->start = LLGST_DEBUG_FUNCPTR (gst_slvideo_start); - gstbasesink_class->stop = LLGST_DEBUG_FUNCPTR (gst_slvideo_stop); - - // gstbasesink_class->unlock = LLGST_DEBUG_FUNCPTR (gst_slvideo_unlock); -#undef LLGST_DEBUG_FUNCPTR -} - - -static void -gst_slvideo_update_caps (GstSLVideo * slvideo) -{ - GstCaps *caps; - - // GStreamer will automatically convert colourspace if necessary. - // GStreamer will automatically resize media to one of these enumerated - // powers-of-two that we ask for (yay GStreamer!) - caps = gst_caps_from_string (SLV_ALLCAPS); - - gst_caps_replace (&slvideo->caps, caps); -} - - -/* initialize the new element - * instantiate pads and add them to element - * set functions - * initialize structure - */ -static void -gst_slvideo_init (GstSLVideo * filter, - GstSLVideoClass * gclass) -{ - filter->width = -1; - filter->height = -1; - - // this is the info we share with the client app - GST_OBJECT_LOCK(filter); - filter->retained_frame_ready = FALSE; - filter->retained_frame_data = NULL; - filter->retained_frame_allocbytes = 0; - filter->retained_frame_width = filter->width; - filter->retained_frame_height = filter->height; - filter->retained_frame_format = SLV_PF_UNKNOWN; - GST_OBJECT_UNLOCK(filter); - - gst_slvideo_update_caps(filter); -} - -static void -gst_slvideo_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - g_return_if_fail (GST_IS_SLVIDEO (object)); - - if (prop_id) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -gst_slvideo_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - g_return_if_fail (GST_IS_SLVIDEO (object)); - - if (prop_id) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - - -/* entry point to initialize the plug-in - * initialize the plug-in itself - * register the element factories and pad templates - * register the features - */ -static gboolean -plugin_init (GstPlugin * plugin) -{ - //fprintf(stderr, "\n\n\nPLUGIN INIT\n\n\n"); - - GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin", - 0, (gchar*)"Second Life Video Sink"); - - return gst_element_register (plugin, "private-slvideo", - GST_RANK_NONE, GST_TYPE_SLVIDEO); -} - - -void gst_slvideo_init_class (void) -{ - gst_plugin_register_static( GST_VERSION_MAJOR, - GST_VERSION_MINOR, - (const gchar *)"private-slvideoplugin", - (gchar *)"SL Video sink plugin", - plugin_init, - (const gchar *)"0.1", - GST_LICENSE_UNKNOWN, - (const gchar *)"Second Life", - (const gchar *)"Second Life", - (const gchar *)"http://www.secondlife.com/" ); -} - -///#endif // LL_GSTREAMER_ENABLED diff --git a/linden/indra/llmedia/llmediaimplgstreamervidplug.h b/linden/indra/llmedia/llmediaimplgstreamervidplug.h deleted file mode 100644 index 3a984a9..0000000 --- a/linden/indra/llmedia/llmediaimplgstreamervidplug.h +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @file llmediaimplgstreamervidplug.h - * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef __GST_SLVIDEO_H__ -#define __GST_SLVIDEO_H__ - -///#if LL_GSTREAMER_ENABLED - -extern "C" { -#include -#include -#include -#include -} - -G_BEGIN_DECLS - -/* #defines don't like whitespacey bits */ -#define GST_TYPE_SLVIDEO \ - (gst_slvideo_get_type()) -#define GST_SLVIDEO(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SLVIDEO,GstSLVideo)) -#define GST_SLVIDEO_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SLVIDEO,GstSLVideoClass)) -#define GST_IS_SLVIDEO(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SLVIDEO)) -#define GST_IS_SLVIDEO_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SLVIDEO)) - -typedef struct _GstSLVideo GstSLVideo; -typedef struct _GstSLVideoClass GstSLVideoClass; - -typedef enum { - SLV_PF_UNKNOWN = 0, - SLV_PF_RGBX = 1, - SLV_PF_BGRX = 2, - SLV__END = 3 -} SLVPixelFormat; -const int SLVPixelFormatBytes[SLV__END] = {1, 4, 4}; - -struct _GstSLVideo -{ - GstVideoSink video_sink; - - GstCaps *caps; - - int fps_n, fps_d; - int par_n, par_d; - int height, width; - SLVPixelFormat format; - - // SHARED WITH APPLICATION: - // Access to the following should be protected by GST_OBJECT_LOCK() on - // the GstSLVideo object, and should be totally consistent upon UNLOCK - // (i.e. all written at once to reflect the current retained frame info - // when the retained frame is updated.) - bool retained_frame_ready; // new frame ready since flag last reset. (*TODO: could get the writer to wait on a semaphore instead of having the reader poll, potentially making dropped frames somewhat cheaper.) - unsigned char* retained_frame_data; - int retained_frame_allocbytes; - int retained_frame_width, retained_frame_height; - SLVPixelFormat retained_frame_format; -}; - -struct _GstSLVideoClass -{ - GstVideoSinkClass parent_class; -}; - -GType gst_slvideo_get_type (void); - -void gst_slvideo_init_class (void); - -G_END_DECLS - -///#endif // LL_GSTREAMER_ENABLED - -#endif /* __GST_SLVIDEO_H__ */ diff --git a/linden/indra/llmedia/llmediaimplllmozlib.cpp b/linden/indra/llmedia/llmediaimplllmozlib.cpp deleted file mode 100644 index 5b4b02e..0000000 --- a/linden/indra/llmedia/llmediaimplllmozlib.cpp +++ /dev/null @@ -1,624 +0,0 @@ -/** - * @file llmediaimplllmozlib.cpp - * @brief Example 2 of a media impl concrete class - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llmediaimplllmozlib.h" - -#if LL_LLMOZLIB_ENABLED - -#include "llmediaimplregister.h" -#include "llmediamanager.h" - -#ifdef WIN32 - // platform specific includes needed before OpenGL header - #include - #include -#elif defined(__APPLE__) - // framework-style include path when building on the Mac. - #include -#else // Assume this is linux - // Linux, MESA headers, but not necessarily assuming MESA runtime. - // quotes so we get libraries/.../GL/ version - #include "GL/gl.h" -#endif - - -#include - - -#include - -// register this impl with media manager factory -static LLMediaImplRegister sLLMediaImplLLMozLibReg( "LLMediaImplLLMozLib", new LLMediaImplLLMozLibMaker() ); - -/////////////////////////////////////////////////////////////////////////////// -// -LLMediaImplLLMozLibMaker::LLMediaImplLLMozLibMaker() -{ - // Register to handle the mime category - mMimeTypes.push_back( "image/svg+xml" ); - mMimeTypeCategories.push_back( "text" ); -#if !LL_QUICKTIME_ENABLED - mMimeTypeCategories.push_back( "image" ); -#endif -} - -/////////////////////////////////////////////////////////////////////////////// -// -LLMediaImplLLMozLib::LLMediaImplLLMozLib() : - mBrowserWindowWidth( 800 ), - mBrowserWindowHeight( 600 ), - mMediaDataWidth( 0 ), - mMediaDataHeight( 0 ), - mWindowId( 0 ), - mNeedsUpdate( false ) -{ - setRequestedMediaSize( mBrowserWindowWidth, mBrowserWindowHeight ); - - setMediaDepth( 4 ); -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) super-initialization - called once at application startup -bool LLMediaImplLLMozLib::startup( LLMediaManagerData* init_data ) -{ - - // Yuck, Mozilla's GTK callbacks play with the locale - push/pop - // the locale to protect it, as exotic/non-C locales - // causes our code lots of general critical weirdness - // and crashness. (SL-35450) - static std::string saved_locale; - saved_locale = setlocale(LC_ALL, NULL); - - - bool result = LLMozLib::getInstance()->init( init_data->getBrowserApplicationDir(), - init_data->getBrowserComponentDir(), - init_data->getBrowserProfileDir(), - init_data->getBrowserParentWindow() ); - - - setlocale(LC_ALL, saved_locale.c_str() ); - - - return result; -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) super-uninitialization - called once at application closedown -bool LLMediaImplLLMozLib::closedown() -{ - // name discrepancy - this reset actually shuts down LLMozLib - LLMozLib::getInstance()->reset(); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) -bool LLMediaImplLLMozLib::setBrowserUserAgent(std::string user_agent) -{ - // append special string to the embedded browser user agent string - LLMozLib::getInstance()->setBrowserAgentId(user_agent); - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::init() -{ - // if mWindowId is non-0, it's we already called init() and shouldn't call it again - // (::reset() will zero this value) - if ( mWindowId ) - return false; - -#if defined(LL_LINUX) || defined(WIN32) - static std::string saved_locale; - saved_locale = setlocale(LC_ALL, NULL); -#endif // defined(LL_LINUX) || defined(WIN32) - - mWindowId = LLMozLib::getInstance()->createBrowserWindow( mBrowserWindowWidth, mBrowserWindowHeight ); - - LLMozLib::getInstance()->setSize( mWindowId, mBrowserWindowWidth, mBrowserWindowHeight ); - - LLMozLib::getInstance()->setBackgroundColor( mWindowId, 0x00, 0x00, 0x00 ); - - LLMozLib::getInstance()->addObserver( mWindowId, this ); - - // plugins only work with some client-side hackery and they cause - // exception handling issues (DEV-10020) so we turn them off - LLMozLib::getInstance()->enablePlugins( false ); - - // second life client needs the bitmap flipped - LLMozLib::getInstance()->flipWindow( mWindowId, true ); - - // set media depth now we have created a browser window and know what it is - setMediaDepth( LLMozLib::getInstance()->getBrowserDepth( mWindowId ) ); - -#if defined(LL_LINUX) || defined(WIN32) - setlocale(LC_ALL, saved_locale.c_str() ); -#endif // defined(LL_LINUX) || defined(WIN32) - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -std::string LLMediaImplLLMozLib::getVersion() -{ - std::string version_string = "[" + sLLMediaImplLLMozLibReg.getImplName() + "] - " + LLMozLib::getInstance()->getVersion(); - - return version_string; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::set404RedirectUrl( std::string redirect_url ) -{ - return LLMozLib::getInstance()->set404RedirectUrl( mWindowId, redirect_url ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual - -bool LLMediaImplLLMozLib::clr404RedirectUrl() -{ - return LLMozLib::getInstance()->clr404RedirectUrl( mWindowId ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::setBackgroundColor( unsigned int red, unsigned int green, unsigned int blue ) const -{ - return LLMozLib::getInstance()->setBackgroundColor( mWindowId, red, green, blue ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::setCaretColor( unsigned int red, unsigned int green, unsigned int blue ) const -{ - return LLMozLib::getInstance()->setCaretColor( mWindowId, red, green, blue ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::navigateTo( const std::string url ) -{ - // pass url to llmozlib - LLMozLib::getInstance()->navigateTo( mWindowId, url ); - - // emit event with size change to kick things off - LLMediaEvent event( this ); - mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event ); - - // not that useful right now but maybe later - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::updateMedia() -{ - if ( getStatus() == LLMediaBase::STATUS_STARTED ) - { - // if flag set, the page changed and we need to update - if ( mNeedsUpdate ) - { - // snap browser pixels - LLMozLib::getInstance()->grabBrowserWindow( mWindowId ); - - // update media width - rendering the page can change it - mMediaDataWidth = LLMozLib::getInstance()->getBrowserRowSpan( mWindowId ) / getMediaDepth(); - mMediaDataHeight = LLMozLib::getInstance()->getBrowserHeight( mWindowId ); - - // emit an event to say that something in the media stream changed - LLMediaEvent event( this ); - mEventEmitter.update( &LLMediaObserver::onMediaContentsChange, event ); - - // flag that we've done the update and one isn't needed next frame - mNeedsUpdate = false; - }; - }; - - // update the state (e.g. transport controls) state - updateState(); - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLMediaImplLLMozLib::updateState() -{ - if ( nextCommand() == LLMediaBase::COMMAND_START ) - { - setStatus( LLMediaBase::STATUS_STARTED ); - clearCommand(); - }; - - if ( nextCommand() == LLMediaBase::COMMAND_STOP ) - { - setStatus( LLMediaBase::STATUS_STOPPED ); - clearCommand(); - }; - - if ( nextCommand() == LLMediaBase::COMMAND_BACK ) - { - setStatus( LLMediaBase::STATUS_STARTED ); - LLMozLib::getInstance()->navigateBack( mWindowId ); - clearCommand(); - }; - - if ( nextCommand() == LLMediaBase::COMMAND_FORWARD ) - { - setStatus( LLMediaBase::STATUS_STARTED ); - LLMozLib::getInstance()->navigateForward( mWindowId ); - clearCommand(); - }; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLMediaImplLLMozLib::onPageChanged( const EventType& eventIn ) -{ - // force an update when the contents of the page changes - mNeedsUpdate = true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLMediaImplLLMozLib::onClickLinkHref( const EventType& eventIn ) -{ - LLMediaEvent event( this, eventIn.getStringValue(), eventIn.getStringValue2() ); - mEventEmitter.update( &LLMediaObserver::onClickLinkHref, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLMediaImplLLMozLib::onClickLinkNoFollow( const EventType& eventIn ) -{ - LLMediaEvent event( this, eventIn.getStringValue() ); - mEventEmitter.update( &LLMediaObserver::onClickLinkNoFollow, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLMediaImplLLMozLib::onUpdateProgress( const EventType& eventIn ) -{ - LLMediaEvent event( this, eventIn.getIntValue() ); - mEventEmitter.update( &LLMediaObserver::onUpdateProgress, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLMediaImplLLMozLib::onStatusTextChange( const EventType& eventIn ) -{ - LLMediaEvent event( this, eventIn.getStringValue() ); - mEventEmitter.update( &LLMediaObserver::onStatusTextChange, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLMediaImplLLMozLib::onLocationChange( const EventType& eventIn ) -{ - LLMediaEvent event( this, eventIn.getEventUri() ); - mEventEmitter.update( &LLMediaObserver::onLocationChange, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLMediaImplLLMozLib::onNavigateBegin( const EventType& eventIn ) -{ - LLMediaEvent event( this, eventIn.getEventUri() ); - mEventEmitter.update( &LLMediaObserver::onNavigateBegin, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLMediaImplLLMozLib::onNavigateComplete( const EventType& eventIn ) -{ - // force an update when the page is finished - mNeedsUpdate = true; - - // pass in url and HTML response code (200/404 etc.) - LLMediaEvent event( this, eventIn.getEventUri(), eventIn.getIntValue() ); - mEventEmitter.update( &LLMediaObserver::onNavigateComplete, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -unsigned char* LLMediaImplLLMozLib::getMediaData() -{ - return (unsigned char*)LLMozLib::getInstance()->getBrowserWindowPixels( mWindowId ); -} - -// helper func to compute size of media data -bool LLMediaImplLLMozLib::recomputeSizes() -{ - int new_width = mMediaRequestedWidth; - int new_height = mMediaRequestedHeight; - - if (new_width < 0) - new_width = 512; - - if (new_height < 0) - new_height = 512; - - if (mAutoScaled) - { - new_width = LLMediaManager::textureWidthFromMediaWidth( new_width ); - new_height = LLMediaManager::textureHeightFromMediaHeight( new_height ); - } - - bool status = LLMozLib::getInstance()->setSize( mWindowId, new_width, new_height ); - - if (status) - setMediaSize(new_width, new_height); - - return status; -} - - -//////////////////////////////////////////////////////////////////////////////// -// virtual -int LLMediaImplLLMozLib::getMediaDataWidth() const -{ - return mMediaDataWidth; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -int LLMediaImplLLMozLib::getMediaDataHeight() const -{ - return mMediaDataHeight; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::setRequestedMediaSize(int width, int height) -{ - LLMediaImplCommon::setRequestedMediaSize(width, height); - - return recomputeSizes(); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::setAutoScaled( bool auto_scaled ) -{ - LLMediaImplCommon::setAutoScaled(auto_scaled); - - return recomputeSizes(); -} - - -//////////////////////////////////////////////////////////////////////////////// -// virtual -int LLMediaImplLLMozLib::getTextureFormatPrimary() const -{ -#if defined(__APPLE__) || defined(MACOSX) - return GL_BGRA_EXT; -#else - return LLMozLib::getInstance()->getBrowserDepth( mWindowId ) == 3 ? GL_BGR_EXT : GL_BGRA_EXT; -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -int LLMediaImplLLMozLib::getTextureFormatType() const -{ -#if defined(__APPLE__) || defined(MACOSX) - #ifdef __BIG_ENDIAN__ - return GL_UNSIGNED_INT_8_8_8_8_REV; - #else - return GL_UNSIGNED_INT_8_8_8_8; - #endif -#else - return GL_UNSIGNED_BYTE; -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::mouseDown( int x_pos, int y_pos ) -{ - return LLMozLib::getInstance()->mouseDown( mWindowId, x_pos, y_pos ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::mouseUp( int x_pos, int y_pos ) -{ - LLMozLib::getInstance()->mouseUp( mWindowId, x_pos, y_pos ); - - // this seems better than sending focus on mouse down (still need to improve this) - LLMozLib::getInstance()->focusBrowser( mWindowId, true ); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::mouseMove( int x_pos, int y_pos ) -{ - return LLMozLib::getInstance()->mouseMove( mWindowId, x_pos, y_pos ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::keyPress( int key_code ) -{ - // We don't have to deal with printable characters here - they should - // go through handleUnicodeChar(). This table could be more complete - // than it is, but I think this covers all of the important - // non-printables. - - unsigned long moz_key; - - switch(key_code) - { - case LL_MEDIA_KEY_BACKSPACE: - moz_key = LL_DOM_VK_BACK_SPACE; break; - case LL_MEDIA_KEY_TAB: - moz_key = LL_DOM_VK_TAB; break; - case LL_MEDIA_KEY_RETURN: - moz_key = LL_DOM_VK_RETURN; break; - case LL_MEDIA_KEY_PAD_RETURN: - moz_key = LL_DOM_VK_ENTER; break; - case LL_MEDIA_KEY_ESCAPE: - moz_key = LL_DOM_VK_ESCAPE; break; - case LL_MEDIA_KEY_PAGE_UP: - moz_key = LL_DOM_VK_PAGE_UP; break; - case LL_MEDIA_KEY_PAGE_DOWN: - moz_key = LL_DOM_VK_PAGE_DOWN; break; - case LL_MEDIA_KEY_END: - moz_key = LL_DOM_VK_END; break; - case LL_MEDIA_KEY_HOME: - moz_key = LL_DOM_VK_HOME; break; - case LL_MEDIA_KEY_LEFT: - moz_key = LL_DOM_VK_LEFT; break; - case LL_MEDIA_KEY_UP: - moz_key = LL_DOM_VK_UP; break; - case LL_MEDIA_KEY_RIGHT: - moz_key = LL_DOM_VK_RIGHT; break; - case LL_MEDIA_KEY_DOWN: - moz_key = LL_DOM_VK_DOWN; break; - case LL_MEDIA_KEY_INSERT: - moz_key = LL_DOM_VK_INSERT; break; - case LL_MEDIA_KEY_DELETE: - moz_key = LL_DOM_VK_DELETE; break; - - default: - return false; // don't know how to map this key. - } - - return LLMozLib::getInstance()->keyPress( mWindowId, moz_key ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::scrollByLines( int lines ) -{ - return LLMozLib::getInstance()->scrollByLines(mWindowId, lines); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::focus( bool focus ) -{ - return LLMozLib::getInstance()->focusBrowser(mWindowId, focus); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::unicodeInput( unsigned long uni_char ) -{ - return LLMozLib::getInstance()->unicodeInput(mWindowId, uni_char); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::mouseLeftDoubleClick( int x_pos, int y_pos ) -{ - return LLMozLib::getInstance()->mouseLeftDoubleClick( mWindowId, x_pos, y_pos ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::navigateForward() -{ - return LLMozLib::getInstance()->navigateForward(mWindowId); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::navigateBack() -{ - return LLMozLib::getInstance()->navigateBack(mWindowId); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::canNavigateForward() -{ - return LLMozLib::getInstance()->canNavigateForward(mWindowId); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::canNavigateBack() -{ - return LLMozLib::getInstance()->canNavigateBack(mWindowId); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::enableCookies(bool enable) -{ - return LLMozLib::getInstance()->enableCookies(enable); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::enableProxy(bool enable, std::string proxy_host_name, int proxy_port) -{ - return LLMozLib::getInstance()->enableProxy(enable, proxy_host_name, proxy_port); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::clearCache() -{ - return LLMozLib::getInstance()->clearCache(); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::clearCookies() -{ - return LLMozLib::getInstance()->clearAllCookies(); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplLLMozLib::reset() -{ - LLMozLib::getInstance()->remObserver( mWindowId, this ); - - LLMozLib::getInstance()->destroyBrowserWindow( mWindowId ); - - mWindowId = 0; - - return true; -} - -#endif // LL_LLMOZLIB_ENABLED diff --git a/linden/indra/llmedia/llmediaimplllmozlib.h b/linden/indra/llmedia/llmediaimplllmozlib.h deleted file mode 100644 index f71300e..0000000 --- a/linden/indra/llmedia/llmediaimplllmozlib.h +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @file llmediaimplllmozlib.cpp - * @brief Example 2 of a media impl concrete class - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLMEDIAIMPLLLMOZLIB_H -#define LLMEDIAIMPLLLMOZLIB_H - -#include "llmediaimplcommon.h" -#include "llmediaimplfactory.h" - -#if LL_LLMOZLIB_ENABLED - -#include "llmozlib2.h" - -class LLMediaManagerData; - -class LLMediaImplLLMozLib : - public LLMediaImplCommon, - public LLEmbeddedBrowserWindowObserver -{ - public: - LLMediaImplLLMozLib(); - - static bool startup( LLMediaManagerData* init_data ); - static bool closedown(); - - // Update the user-agent string reported when the browser requests - // web page, because we need to include the Second Life version - // and skin name (which can change without restarts). - // Must be called after startup(). - static bool setBrowserUserAgent(std::string user_agent); - - /* virtual */ bool init(); - /* virtual */ std::string getVersion(); - /* virtual */ bool set404RedirectUrl( std::string redirect_url ); - /* virtual */ bool clr404RedirectUrl(); - /* virtual */ bool setBackgroundColor( unsigned int red, unsigned int green, unsigned int blue ) const; - /* virtual */ bool setCaretColor( unsigned int red, unsigned int green, unsigned int blue ) const; - /* virtual */ bool navigateTo( const std::string url ); - /* virtual */ bool updateMedia(); - /* virtual */ unsigned char* getMediaData(); - /* virtual */ int getMediaDataWidth() const; - /* virtual */ int getMediaDataHeight() const; - /* virtual */ bool setRequestedMediaSize(int width, int height); - /* virtual */ bool setAutoScaled( bool auto_scaled ); - /* virtual */ int getTextureFormatPrimary() const; - /* virtual */ int getTextureFormatType() const; - /* virtual */ bool mouseDown( int x_pos, int y_pos ); - /* virtual */ bool mouseUp( int x_pos, int y_pos ); - /* virtual */ bool mouseMove( int x_pos, int y_pos ); - /* virtual */ bool keyPress( int key_code ); - /* virtual */ bool scrollByLines( int lines ); - /* virtual */ bool focus( bool focus ); - /* virtual */ bool unicodeInput( unsigned long uni_char ); - /* virtual */ bool mouseLeftDoubleClick( int x_pos, int y_pos ); - /* virtual */ bool navigateForward(); - /* virtual */ bool navigateBack(); - /* virtual */ bool canNavigateForward(); - /* virtual */ bool canNavigateBack(); - /* virtual */ bool enableCookies(bool enable); - /* virtual */ bool enableProxy(bool enable, std::string proxy_host_name, int proxy_port); - /* virtual */ bool clearCache(); - /* virtual */ bool clearCookies(); - /* virtual */ bool reset(); - - // LLMozLib observerables - virtual void onNavigateBegin( const EventType& eventIn ); - virtual void onNavigateComplete( const EventType& eventIn ); - virtual void onUpdateProgress( const EventType& eventIn ); - virtual void onPageChanged( const EventType& eventIn ); - virtual void onStatusTextChange( const EventType& eventIn ); - virtual void onLocationChange( const EventType& eventIn ); - virtual void onClickLinkHref( const EventType& eventIn ); - virtual void onClickLinkNoFollow( const EventType& eventIn ); - - private: - bool recomputeSizes(); - int mWindowId; - int mBrowserWindowWidth; - int mBrowserWindowHeight; - int mMediaDataWidth; - int mMediaDataHeight; - bool mNeedsUpdate; - bool updateState(); -}; - -// The maker class -class LLMediaImplLLMozLibMaker : public LLMediaImplMaker -{ - public: - LLMediaImplLLMozLibMaker(); - LLMediaImplLLMozLib* create() - { - return new LLMediaImplLLMozLib(); - } -}; -#endif // LL_LLMOZLIB_ENABLED - -#endif // LLMEDIAIMPLLLMOZLIB_H diff --git a/linden/indra/llmedia/llmediaimplquicktime.cpp b/linden/indra/llmedia/llmediaimplquicktime.cpp deleted file mode 100644 index 76cacee..0000000 --- a/linden/indra/llmedia/llmediaimplquicktime.cpp +++ /dev/null @@ -1,657 +0,0 @@ -/** - * @file llmediaimplquicktime.cpp - * @brief QuickTime media impl concrete class - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llmediaimplquicktime.h" - -#if LL_QUICKTIME_ENABLED - -#include "llmediamanager.h" -#include "llmediaimplregister.h" - -#if LL_WINDOWS -#include -#endif - -#include -#include - -// register this impl with media manager factory -static LLMediaImplRegister sLLMediaImplQuickTimeReg( "LLMediaImplQuickTime", new LLMediaImplQuickTimeMaker() ); - -/////////////////////////////////////////////////////////////////////////////// -// -LLMediaImplQuickTimeMaker::LLMediaImplQuickTimeMaker() -{ - // Register to handle the scheme - mSchema.push_back( "rtsp" ); - - // Register to handle the category - mMimeTypeCategories.push_back( "video" ); - mMimeTypeCategories.push_back( "audio" ); - mMimeTypeCategories.push_back( "image" ); -} - -/////////////////////////////////////////////////////////////////////////////// -// -LLMediaImplQuickTime::LLMediaImplQuickTime() : - mMovieHandle( 0 ), - mGWorldHandle( 0 ), - mMovieController( 0 ), - mMinWidth( 32 ), - mMaxWidth( 2048 ), - mMinHeight( 32 ), - mMaxHeight( 2048 ), - mCurVolume( 0 ) -{ -} - -/////////////////////////////////////////////////////////////////////////////// -// -LLMediaImplQuickTime::~LLMediaImplQuickTime() -{ - unload(); -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) super-initialization - called once at application startup -bool LLMediaImplQuickTime::startup( LLMediaManagerData* init_data ) -{ -#ifdef WIN32 - if ( InitializeQTML( 0L ) != noErr ) - { - return false; - }; -#endif - - EnterMovies(); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) super-uninitialization - called once at application closedown -bool LLMediaImplQuickTime::closedown() -{ - ExitMovies(); - -#ifdef WIN32 - TerminateQTML(); -#endif - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// private -bool LLMediaImplQuickTime::load( const std::string url ) -{ - if ( url.empty() ) - return false; - - //In case std::string::c_str() makes a copy of the url data, - //make sure there is memory to hold it before allocating memory for handle. - //if fails, NewHandleClear(...) should return NULL. - const char* url_string = url.c_str() ; - Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) ); - if ( NULL == handle ) - return false; - if(noErr != MemError() || NULL == *handle) - { - return false ; - } - - BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) ); - - //std::cout << "LLMediaImplQuickTime::load( " << url << " )" << std::endl; - - // TODO: supposed to use NewMovieFromDataParams now - OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType ); - DisposeHandle( handle ); - if ( noErr != err ) - return false; - - // do pre-roll actions (typically fired for streaming movies but not always) - PrePrerollMovie( mMovieHandle, 0, GetMoviePreferredRate( mMovieHandle ), moviePrePrerollCompleteCallback, ( void * )this ); - - // get movie rect (and check for min/max) - Rect movie_rect; - setMovieBoxEnhanced( &movie_rect ); - - // make a new movie controller - mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie ); - -#if defined(__APPLE__) || defined(MACOSX) - setMediaDepth( 4 ); -#else - setMediaDepth( 3 ); -#endif - - // tell manager about the media size - setMediaSize( movie_rect.right - movie_rect.left, movie_rect.bottom - movie_rect.top); - - // movie controller - MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this ); - - SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize ); - - // function that gets called when a frame is drawn - SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this ); - - // emit an event to say that a media source was loaded - LLMediaEvent event( this ); - mEventEmitter.update( &LLMediaObserver::onMediaLoaded, event ); - - // set up inital state - sizeChanged(); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -std::string LLMediaImplQuickTime::getVersion() -{ - long version; - Gestalt( gestaltQuickTimeVersion, &version ); - - std::ostringstream codec( "" ); - codec << "["; - codec << sLLMediaImplQuickTimeReg.getImplName(); - codec << "] - "; - codec << "QuickTime: " << std::hex << version; - - return codec.str(); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplQuickTime::navigateTo( const std::string url ) -{ - // tell engine what we're doing - setStatus( LLMediaBase::STATUS_NAVIGATING ); - - // remove the movie we were looking at - unload(); - - // load the new one (no real 'go to this url' function in QT) - load( url ); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplQuickTime::sizeChanged() -{ - if ( ! mMovieHandle ) - return false; - - // sanitize size of movie - Rect movie_rect; - setMovieBoxEnhanced( &movie_rect ); - - // we need this later - int width = ( movie_rect.right - movie_rect.left ); - int height = ( movie_rect.bottom - movie_rect.top ); - - std::cout << "LLMEDIA> size changed to " << width << " x " << height << std::endl; - - setMediaSize( width, height ); - - // media depth won't change - int depth_bits = getMediaDepth() * 8; - - GWorldPtr old_gworld_handle = mGWorldHandle; - - if (old_gworld_handle) - { - GWorldFlags result = UpdateGWorld( &mGWorldHandle, depth_bits, &movie_rect, NULL, NULL, 0 ); - if ( gwFlagErr == result ) - { - // TODO: unrecoverable?? throw exception? return something? - return false; - } - } - else - { - OSErr result = NewGWorld( &mGWorldHandle, depth_bits, &movie_rect, NULL, NULL, keepLocal | pixelsLocked ); - if ( noErr != result ) - { - // ATODO: unrecoverable?? throw exception? return something? - return false; - } - - // clear memory in GWorld to avoid random screen visual fuzz from uninitialized texture data - if ( mGWorldHandle ) - { - PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle ); - unsigned char* ptr = ( unsigned char* )GetPixBaseAddr( pix_map_handle ); - memset( ptr, 0x00, height * QTGetPixMapHandleRowBytes( pix_map_handle ) ); - } - } - - // point movie at GWorld if it's new - if ( mMovieHandle && ! old_gworld_handle ) - { - SetMovieGWorld( mMovieHandle, mGWorldHandle, GetGWorldDevice ( mGWorldHandle ) ); - } - - // update movie controller - if ( mMovieController ) - { - MCSetControllerPort( mMovieController, mGWorldHandle ); - MCPositionController( mMovieController, &movie_rect, &movie_rect, - mcTopLeftMovie | mcPositionDontInvalidate ); - MCMovieChanged( mMovieController, mMovieHandle ); - } - - // Emit event with size change so the calling app knows about it too - LLMediaEvent event( this ); - mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event ); - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// static -Boolean LLMediaImplQuickTime::mcActionFilterCallBack( MovieController mc, short action, void *params, long ref ) -{ - Boolean result = false; - - LLMediaImplQuickTime* self = ( LLMediaImplQuickTime* )ref; - - switch( action ) - { - // handle window resizing - case mcActionControllerSizeChanged: - self->sizeChanged(); - break; - - // Block any movie controller actions that open URLs. - case mcActionLinkToURL: - case mcActionGetNextURL: - case mcActionLinkToURLExtended: - // Prevent the movie controller from handling the message - result = true; - break; - - default: - break; - }; - - return result; -} - -//////////////////////////////////////////////////////////////////////////////// -// private -bool LLMediaImplQuickTime::unload() -{ - if ( mMovieHandle ) - { - StopMovie( mMovieHandle ); - if ( mMovieController ) - { - MCMovieChanged( mMovieController, mMovieHandle ); - }; - }; - - if ( mMovieController ) - { - MCSetActionFilterWithRefCon( mMovieController, NULL, (long)this ); - DisposeMovieController( mMovieController ); - mMovieController = NULL; - }; - - if ( mMovieHandle ) - { - SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, nil, ( long )this ); - DisposeMovie ( mMovieHandle ); - mMovieHandle = NULL; - }; - - if ( mGWorldHandle ) - { - DisposeGWorld( mGWorldHandle ); - mGWorldHandle = NULL; - }; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// static -OSErr LLMediaImplQuickTime::movieDrawingCompleteCallback( Movie call_back_movie, long ref ) -{ - LLMediaImplQuickTime* self = ( LLMediaImplQuickTime* )ref; - - // IMPORTANT: typically, a consumer who is observing this event will set a flag - // when this event is fired then render later. Be aware that the media stream - // can change during this period - dimensions, depth, format etc. - LLMediaEvent event( self ); - self->mEventEmitter.update( &LLMediaObserver::onMediaContentsChange, event ); - - return noErr; -} - -//////////////////////////////////////////////////////////////////////////////// -// static -void LLMediaImplQuickTime::moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref ) -{ - LLMediaImplQuickTime* self = ( LLMediaImplQuickTime* )ref; - - LLMediaEvent event( self ); - self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event ); -} - -/////////////////////////////////////////////////////////////////////////////// -// used for stop / loop -void LLMediaImplQuickTime::rewind() -{ - GoToBeginningOfMovie ( mMovieHandle ); - - MCMovieChanged( mMovieController, mMovieHandle ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLMediaImplQuickTime::processState() -{ - // start stream - if ( nextCommand() == LLMediaBase::COMMAND_START ) - { - // valid when we are in these states - if ( getStatus() == LLMediaBase::STATUS_NAVIGATING|| getStatus() == LLMediaBase::STATUS_STOPPED || getStatus() == LLMediaBase::STATUS_PAUSED ) - { - // it appears that the movie must be in a loaded state before we do this command - if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) - { - MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)GetMoviePreferredRate( mMovieHandle ) ); - - MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); - - setStatus( LLMediaBase::STATUS_STARTED ); - - clearCommand(); - } - } - } - else - if ( nextCommand() == LLMediaBase::COMMAND_STOP ) - { - // valid when we are in these states - if ( getStatus() == LLMediaBase::STATUS_NAVIGATING || getStatus() == LLMediaBase::STATUS_STARTED || getStatus() == LLMediaBase::STATUS_PAUSED ) - { - // it appears that the movie must be in a loaded state before we do this command - if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) - { - // stop playing - Fixed rate = X2Fix( 0.0 ); - MCDoAction( mMovieController, mcActionPlay, (void*)rate ); - - // go back to start - rewind(); - - setStatus( LLMediaBase::STATUS_STOPPED ); - clearCommand(); - }; - }; - } - else - if ( nextCommand() == LLMediaBase::COMMAND_PAUSE ) - { - // valid when we are in these states - if ( getStatus() == LLMediaBase::STATUS_NAVIGATING || getStatus() == LLMediaBase::STATUS_STARTED || getStatus() == LLMediaBase::STATUS_STOPPED ) - { - // it appears that the movie must be in a loaded state before we do this command - if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) - { - // stop playing - Fixed rate = X2Fix( 0.0 ); - MCDoAction( mMovieController, mcActionPlay, (void*)rate ); - - setStatus( LLMediaBase::STATUS_PAUSED ); - clearCommand(); - }; - }; - }; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplQuickTime::setMovieBoxEnhanced( Rect* rect ) -{ - // get movie rect - GetMovieNaturalBoundsRect( mMovieHandle, rect ); - - int natural_width = ( rect->right - rect->left ); - int natural_height = ( rect->bottom - rect->top ); - - int width = natural_width; - int height = natural_height; - - // if the user has requested a specific size, use it: - if ((mMediaRequestedWidth != 0) && (mMediaRequestedHeight != 0)) - { - width = mMediaRequestedWidth; - height = mMediaRequestedHeight; - } - - // if the user has requested, resize media to exactly fit texture - if (mAutoScaled) - { - width = LLMediaManager::textureWidthFromMediaWidth( width ); - height = LLMediaManager::textureHeightFromMediaHeight( height ); - } - - // make sure it falls in valid range - if ( width < mMinWidth ) - width = mMinWidth; - - if ( width > mMaxWidth ) - width = mMaxWidth; - - if ( height < mMinHeight ) - height = mMinHeight; - - if ( height > mMaxHeight ) - height = mMaxHeight; - - - // scale movie to fit rect and invert vertically to match opengl image format - MatrixRecord transform; - SetIdentityMatrix( &transform ); // transforms are additive so start from identify matrix - double scaleX = (double) width / natural_width; - double scaleY = -1.0 * (double) height / natural_height; - double centerX = width / 2.0; - double centerY = height / 2.0; - ScaleMatrix( &transform, X2Fix ( scaleX ), X2Fix ( scaleY ), X2Fix ( centerX ), X2Fix ( centerY ) ); - SetMovieMatrix( mMovieHandle, &transform ); - - // return the new rect - rect->right = width; - rect->bottom = height; - rect->left = 0; - rect->top = 0; - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplQuickTime::updateMedia() -{ - if ( ! mMovieHandle ) - return false; - - if ( ! mMovieController ) - return false; - - if ( ! mGWorldHandle ) - return false; - - // service QuickTime - MoviesTask( mMovieHandle, 0 ); - MCIdle( mMovieController ); - - // update state machine (deals with transport controls for example) - processState(); - - // special code for looping - need to rewind at the end of the movie - - if ( isLooping() ) - { - // QT call to see if we are at the end - can't do with controller - if ( IsMovieDone( mMovieHandle ) ) - { - // go back to start - rewind(); - - // kick off new play - MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)GetMoviePreferredRate( mMovieHandle ) ); - - // set the volume - MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); - } - } - - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -unsigned char* LLMediaImplQuickTime::getMediaData() -{ - unsigned char* ptr = NULL; - - if ( mGWorldHandle ) - { - PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle ); - - ptr = ( unsigned char* )GetPixBaseAddr( pix_map_handle ); - }; - - return ptr; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -int LLMediaImplQuickTime::getMediaDataWidth() const -{ - if ( mGWorldHandle ) - { - int depth = getMediaDepth(); - - if (depth < 1) - depth = 1; - - // ALWAYS use the row bytes from the PixMap if we have a GWorld because - // sometimes it's not the same as mMediaDepth * mMediaWidth ! - PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle ); - return QTGetPixMapHandleRowBytes( pix_map_handle ) / depth; - } - else - { - return LLMediaImplCommon::getMediaDataWidth(); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -int LLMediaImplQuickTime::getTextureFormatPrimary() const -{ -#if defined(__APPLE__) || defined(MACOSX) - return LL_MEDIA_BGRA; -#else - return LL_MEDIA_RGB; -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -int LLMediaImplQuickTime::getTextureFormatType() const -{ -#if defined(__APPLE__) || defined(MACOSX) - #ifdef __BIG_ENDIAN__ - return LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV; - #else - return LL_MEDIA_UNSIGNED_INT_8_8_8_8; - #endif -#else - return LL_MEDIA_UNSIGNED_BYTE; -#endif -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplQuickTime::seek( double time ) -{ - if ( mMovieController ) - { - TimeRecord when; - when.scale = GetMovieTimeScale( mMovieHandle ); - when.base = 0; - - // 'time' is in (floating point) seconds. The timebase time will be in 'units', where - // there are 'scale' units per second. - SInt64 raw_time = ( SInt64 )( time * (double)( when.scale ) ); - - when.value.hi = ( SInt32 )( raw_time >> 32 ); - when.value.lo = ( SInt32 )( ( raw_time & 0x00000000FFFFFFFF ) ); - - MCDoAction( mMovieController, mcActionGoToTime, &when ); - - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplQuickTime::setVolume( float volume ) -{ - mCurVolume = (short)(volume * ( double ) 0x100 ); - - if ( mMovieController ) - { - MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); - - return true; - } - - return false; -} - -#endif // _3DNOW_InstructionExtensions/ LL_QUICKTIME_ENABLED - diff --git a/linden/indra/llmedia/llmediaimplquicktime.h b/linden/indra/llmedia/llmediaimplquicktime.h deleted file mode 100644 index d4e1db8..0000000 --- a/linden/indra/llmedia/llmediaimplquicktime.h +++ /dev/null @@ -1,112 +0,0 @@ -/** - * @file llmediaimplquicktime.h - * @brief QuickTime media impl concrete class - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLMEDIAIMPLQUICKTIME_H -#define LLMEDIAIMPLQUICKTIME_H - -#include "llmediaimplcommon.h" -#include "llmediaimplfactory.h" - -#if LL_QUICKTIME_ENABLED - -#include - -// QuickTime includes -#if defined(__APPLE__) - #include -#elif defined(WIN32) - #include "MacTypes.h" - #include "QTML.h" - #include "Movies.h" - #include "QDoffscreen.h" - #include "FixMath.h" -#endif - -class LLMediaManagerData; - -class LLMediaImplQuickTime : - public LLMediaImplCommon -{ - public: - LLMediaImplQuickTime(); - virtual ~LLMediaImplQuickTime(); - - static bool startup( LLMediaManagerData* init_data ); - static bool closedown(); - - /* virtual */ std::string getVersion(); - /* virtual */ bool navigateTo( const std::string url ); - /* virtual */ bool updateMedia(); - /* virtual */ unsigned char* getMediaData(); - /* virtual */ int getMediaDataWidth() const; - /* virtual */ int getTextureFormatPrimary() const; - /* virtual */ int getTextureFormatType() const; - /* virtual */ bool seek( double time ); - /* virtual */ bool setVolume( float volume ); - - bool sizeChanged(); - - private: - static OSErr movieDrawingCompleteCallback( Movie call_back_movie, long ref ); - static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref ); - static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *refcon ); - - bool load( const std::string url ); - bool unload(); - void rewind(); - bool processState(); - bool setMovieBoxEnhanced( Rect* rect ); - - Movie mMovieHandle; - GWorldPtr mGWorldHandle; - ComponentInstance mMovieController; - const int mMinWidth; - const int mMaxWidth; - const int mMinHeight; - const int mMaxHeight; - int mCurVolume; -}; - -// The maker class -class LLMediaImplQuickTimeMaker : public LLMediaImplMaker -{ - public: - LLMediaImplQuickTimeMaker(); - LLMediaImplQuickTime* create() - { - return new LLMediaImplQuickTime(); - } -}; - -#endif // LL_QUICKTIME_ENABLED - -#endif // LLMEDIAIMPLQUICKTIME_H diff --git a/linden/indra/llmedia/llmediaimplregister.h b/linden/indra/llmedia/llmediaimplregister.h deleted file mode 100644 index 5191274..0000000 --- a/linden/indra/llmedia/llmediaimplregister.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file llmediaimplregister.h - * @brief Allow impls to register themselves with the impl factory - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLIMEDIAIMPLREGISTER_H -#define LLIMEDIAIMPLREGISTER_H - -#include - -#include "llmediaimplfactory.h" - -/////////////////////////////////////////////////////////////////////////////// -// -class LLMediaImplRegister -{ - public: - LLMediaImplRegister( std::string impl_name, LLMediaImplMaker* impl_maker ) : - mImplName( impl_name ) - { - LLMediaImplFactory::getInstance()->registerImpl( impl_name, impl_maker ); - }; - - std::string getImplName() - { - return mImplName; - }; - - private: - std::string mImplName; -}; - -#endif // LLIMEDIAIMPLREGISTER_H diff --git a/linden/indra/llmedia/llmediamanager.cpp b/linden/indra/llmedia/llmediamanager.cpp deleted file mode 100644 index 48da808..0000000 --- a/linden/indra/llmedia/llmediamanager.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/** - * @file llmediamanager.cpp - * @brief Manages instances of media impls - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llmediamanager.h" - -#if LL_WINDOWS - // GStreamer 0.10.22 - gstutils.h - conversion from 'guint64' to 'guint8'. - // This was an intentional change to make GStreamer more threadsafe, and - // is okay. Delete this bit if GStreamer ever gets more VS-friendly -- McCabe - #pragma warning(disable : 4244) -#endif -#include "llmediaimplgstreamer.h" -#if LL_WINDOWS - #pragma warning(default : 4244) -#endif - -#include "llmediaimplfactory.h" - -#include "llmediaimplexample1.h" -#include "llmediaimplexample2.h" -#include "llmediaimplquicktime.h" - -#if LL_LLMOZLIB_ENABLED -# include "llmediaimplllmozlib.h" -#endif - -#include "llerror.h" -LLMediaManager* LLMediaManager::sInstance = 0; - - -//////////////////////////////////////////////////////////////////////////////// -// (private) -LLMediaManager::LLMediaManager() -{ -} - -//////////////////////////////////////////////////////////////////////////////// -LLMediaManager::~LLMediaManager() -{ -} - -//////////////////////////////////////////////////////////////////////////////// -// Early initialization for web browser for the viewer, so we can show -// the login screen and defer initialization of QuickTime, etc. JC -// (static) -void LLMediaManager::initBrowser( LLMediaManagerData* init_data ) -{ - if ( ! sInstance ) - sInstance = new LLMediaManager(); - -#if LL_LLMOZLIB_ENABLED - LLMediaImplLLMozLib::startup( init_data ); -#endif // LL_LLMOZLIB_ENABLED -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) -void LLMediaManager::initClass( LLMediaManagerData* init_data ) -{ - if ( ! sInstance ) - sInstance = new LLMediaManager(); - - LL_DEBUGS("MediaManager") << "LLMediaManager::initClass" << LL_ENDL; - // Initialize impl classes here - this breaks the encapsulation model - // but some of the initialization takes a long time and we only want to - // do it once at app startup before any of the impls have been created - // Each impl provides a static startup method that does any initialization - // which takes a significant amount of time. - LLMediaImplExample1::startup( init_data ); - LLMediaImplExample2::startup( init_data ); - -#if LL_QUICKTIME_ENABLED - LL_DEBUGS("MediaManager") << "LLMediaManager::initClass: starting quicktime." << LL_ENDL; - LLMediaImplQuickTime::startup( init_data ); -#endif // LL_QUICKTIME_ENABLED - -///#if LL_GSTREAMER_ENABLED - LL_DEBUGS("MediaManager") << "LLMediaManager::initClass: starting gstreamer" << LL_ENDL; - LLMediaImplGStreamer::startup( init_data ); -///#endif // LL_GSTREAMER_ENABLED -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) -void LLMediaManager::updateClass() -{ - if (!sInstance) return; - - media_impl_container_t::iterator it - = sInstance->mMediaImplContainer.begin(); - media_impl_container_t::iterator end - = sInstance->mMediaImplContainer.end(); - for ( ; it != end; ++it ) - { - LLMediaBase* impl = *it; - impl->updateMedia(); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) -void LLMediaManager::cleanupClass() -{ - // Uninitialize impl classes here - this breaks the encapsulation model - // but some of the uninitialization takes a long time and we only want to - // do it once at app startup before any of the impls have been created. - // Each impl provides a static closedown method that does any uninitialization - // which takes a significant amount of time. - LLMediaImplExample1::closedown(); - LLMediaImplExample2::closedown(); - -#if LL_LLMOZLIB_ENABLED - LLMediaImplLLMozLib::closedown(); -#endif // LL_LLMOZLIB_ENABLED - -#if LL_QUICKTIME_ENABLED - LLMediaImplQuickTime::closedown(); -#endif // LL_QUICKTIME_ENABLED - -///#if LL_GSTREAMER_ENABLED - LLMediaImplGStreamer::closedown(); -///#endif // LL_QUICKTIME_ENABLED - - if ( sInstance ) - delete sInstance; - - sInstance = 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) -LLMediaManager* LLMediaManager::getInstance() -{ - return sInstance; -} - -//////////////////////////////////////////////////////////////////////////////// -// (static) -void LLMediaManager::setBrowserUserAgent(std::string user_agent) -{ -#if LL_LLMOZLIB_ENABLED - // *HACK: Breaks encapsulation model, as initClass does above. JC - LLMediaImplLLMozLib::setBrowserUserAgent(user_agent); -#endif // LL_LLMOZLIB_ENABLED -} - -//////////////////////////////////////////////////////////////////////////////// -// -LLMediaBase* LLMediaManager::createSourceFromMimeType( std::string scheme, std::string mime_type ) -{ - - LLMediaImplMakerBase* impl_maker = LLMediaImplFactory::getInstance()->getImplMaker( scheme, mime_type ); - - // If an impl maker is return it means this media type is supported - if ( impl_maker ) - { - LLMediaBase* media_impl = impl_maker->create(); - if( media_impl ) - { - media_impl->setImplMaker( impl_maker ); - std::pair< media_impl_container_t::iterator, bool > result = - mMediaImplContainer.insert( media_impl ); - - if ( result.second ) - { - media_impl->setMimeType( mime_type ); - - media_impl->init(); - - return media_impl; - }; - }; - }; - - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLMediaManager::destroySource( LLMediaBase* media_impl ) -{ - media_impl_container_t::iterator iter = - mMediaImplContainer.find( media_impl ); - - if ( iter != mMediaImplContainer.end() ) - { - if ( *iter ) - { - ( *iter)->reset(); - - delete ( *iter ); - - mMediaImplContainer.erase( iter ); - - return true; - }; - }; - - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLMediaManager::addMimeTypeImplNameMap( std::string mime_type, std::string impl_name ) -{ - std::pair< mime_type_impl_name_container_t::iterator, bool > result = - mMimeTypeImplNameContainer.insert( std::make_pair( mime_type, impl_name ) ); - - return result.second; -} - -//////////////////////////////////////////////////////////////////////////////// -// -std::string LLMediaManager::getImplNameFromMimeType( std::string mime_type ) -{ - mime_type_impl_name_container_t::iterator iter = - mMimeTypeImplNameContainer.find( mime_type ); - - if ( iter != mMimeTypeImplNameContainer.end() ) - { - return ( *iter ).second; - } - else - { - return std::string( "" ); - }; -} -//////////////////////////////////////////////////////////////////////////////// -// -bool LLMediaManager::supportsMediaType( const std::string& impl_name, const std::string& scheme, const std::string& mime_type ) -{ - LLMediaImplMakerBase* impl_maker = LLMediaImplFactory::getInstance()->getImplMaker( impl_name ); - if( impl_maker ) - { - int idx1 = mime_type.find("/"); - int len = (idx1 == std::string::npos) ? 0 : idx1; - std::string category = mime_type.substr(0,len); - - return impl_maker->supportsScheme(scheme) || - impl_maker->supportsMimeType(mime_type) || - impl_maker->supportsMimeTypeCategory(category); - } - return false; -} - -// static -int LLMediaManager::textureWidthFromMediaWidth( int media_width ) -{ - int texture_width = 1; - while ( texture_width < media_width ) - { - texture_width <<= 1; - }; - return texture_width; -} - -// static -int LLMediaManager::textureHeightFromMediaHeight( int media_height ) -{ - int texture_height = 1; - while ( texture_height < media_height ) - { - texture_height <<= 1; - }; - return texture_height; -} diff --git a/linden/indra/llmedia/llmediamanager.h b/linden/indra/llmedia/llmediamanager.h deleted file mode 100644 index dc832d5..0000000 --- a/linden/indra/llmedia/llmediamanager.h +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @file llmediamanager.h - * @brief Manages instances of media impls - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLMEDIAMANAGER_H -#define LLMEDIAMANAGER_H - -#include -#include - -#include "llmediaimplcommon.h" - -//////////////////////////////////////////////////////////////////////////////// -// -class LLMediaManagerData -{ - public: - LLMediaManagerData() : - mBrowserParentWindow( 0 ), - mBrowserProfileDir( "" ), - mBrowserProfileName ( "" ) - { }; - - void setBrowserApplicationDir( const std::string& browser_application_dir ) { mBrowserApplicationDir = browser_application_dir; }; - std::string& getBrowserApplicationDir() { return mBrowserApplicationDir; }; - - void setBrowserComponentDir( const std::string& browser_component_dir ) { mBrowserComponentDir = browser_component_dir; }; - std::string& getBrowserComponentDir() { return mBrowserComponentDir; }; - - void setBrowserParentWindow( void* browser_parent_window ) { mBrowserParentWindow = browser_parent_window; }; - void* getBrowserParentWindow() { return mBrowserParentWindow; }; - - void setBrowserProfileDir( const std::string& browser_profile_dir ) { mBrowserProfileDir = browser_profile_dir; }; - std::string& getBrowserProfileDir() { return mBrowserProfileDir; }; - - void setBrowserProfileName( const std::string& browser_profile_name ) { mBrowserProfileName = browser_profile_name; }; - std::string& getBrowserProfileName() { return mBrowserProfileName; }; - - private: - void* mBrowserParentWindow; - std::string mBrowserProfileDir; - std::string mBrowserProfileName; - std::string mBrowserApplicationDir; - std::string mBrowserComponentDir; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -class LLMediaManager -{ - public: - virtual ~LLMediaManager(); - - // Special case early init for just web browser component - // so we can show login screen. See .cpp file for details. JC - static void initBrowser( LLMediaManagerData* init_data ); - - static void initClass( LLMediaManagerData* init_data ); - static void cleanupClass(); - static LLMediaManager* getInstance(); - - // We append the skin name to the browser user agent string, so - // we need to change it while the app is running, not just at - // init time. - // Must be called after initClass() above. - // *HACK: Breaks encapsulation model. JC - static void setBrowserUserAgent(std::string user_agent); - - // Calls update on all media sources - static void updateClass(); - - // Given an URL and mime_type, construct/destroy a playback engine for - // it (a "media impl"). - LLMediaBase* createSourceFromMimeType( std::string scheme, std::string mime_type ); - bool destroySource( LLMediaBase* media_impl ); - - // mime type to impl mapping functions - bool addMimeTypeImplNameMap( std::string mime_type, std::string impl_name ); - std::string getImplNameFromMimeType( std::string mime_type ); - - // Name accessor for querying type support - bool supportsMediaType( const std::string& impl_name, const std::string& scheme, const std::string& mime_type ); - - // convenience functions for getting suggested texture sizes to hold various size media - static int textureWidthFromMediaWidth( int media_width ); - static int textureHeightFromMediaHeight( int media_height ); - - private: - LLMediaManager(); - static LLMediaManager* sInstance; - - typedef std::set< LLMediaBase* > media_impl_container_t; - media_impl_container_t mMediaImplContainer; - - typedef std::map< std::string, std::string > mime_type_impl_name_container_t; - mime_type_impl_name_container_t mMimeTypeImplNameContainer; -}; - -#endif // LLMEDIAMANAGER_H diff --git a/linden/indra/llmedia/llmediaobserver.h b/linden/indra/llmedia/llmediaobserver.h deleted file mode 100644 index ab8d755..0000000 --- a/linden/indra/llmedia/llmediaobserver.h +++ /dev/null @@ -1,116 +0,0 @@ -/** - * @file llmediaobserver.h - * @brief Derrive from this class and override methods to observe events from emitter class - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LLMEDIAEOBSERVER_H -#define LLMEDIAEOBSERVER_H - -class LLMediaBase; - -class LLMediaEvent -{ - public: - LLMediaEvent( LLMediaBase* subject ) : - mSubject( subject ), mIntValue(-1) - { - }; - - LLMediaEvent( LLMediaBase* subject, std::string in ) : - mSubject( subject ), mIntValue(-1), mStringValue(in) - { - }; - - LLMediaEvent( LLMediaBase* subject, std::string string_in, std::string string_ex_in ) : - mSubject( subject ), mIntValue(-1), mStringValue(string_in), mStringValueEx(string_ex_in) - { - }; - - LLMediaEvent( LLMediaBase* subject, std::string string_in, int int_in ) : - mSubject( subject ), mIntValue(int_in), mStringValue(string_in) - { - }; - - LLMediaEvent( LLMediaBase* subject, int in ) : - mSubject( subject ), mIntValue(in) - { - }; - - virtual ~LLMediaEvent() { } - - LLMediaBase* getSubject() const - { - return mSubject; - }; - - int getIntValue() const - { - return mIntValue; - } - - std::string getStringValue() const - { - return mStringValue; - } - - std::string getStringValueEx() const - { - return mStringValueEx; - } - - private: - LLMediaBase* mSubject; - int mIntValue; - std::string mStringValue; - std::string mStringValueEx; -}; - -class LLMediaObserver -{ - public: - virtual ~LLMediaObserver() {} - - typedef LLMediaEvent EventType; - virtual void onMediaPreroll( const EventType& event_in ) { } - virtual void onMediaLoaded( const EventType& event_in ) { } - virtual void onMediaSizeChange( const EventType& event_in ) { } - virtual void onMediaContentsChange( const EventType& event_in ) { } - virtual void onMediaStatusTextChange( const EventType& event_in ) { } - virtual void onMediaTitleChange( const EventType &event_in ) { } - virtual void onNavigateBegin( const EventType& event_in ) { } - virtual void onNavigateComplete( const EventType& event_in ) { } - virtual void onUpdateProgress( const EventType& event_in ) { } - virtual void onStatusTextChange( const EventType& event_in ) { } - virtual void onLocationChange( const EventType& event_in ) { } - virtual void onClickLinkHref( const EventType& event_in ) { } - virtual void onClickLinkNoFollow( const EventType& event_in ) { } -}; - -#endif // LLMEDIAEOBSERVER_H diff --git a/linden/indra/llmessage/tests/commtest.h b/linden/indra/llmessage/tests/commtest.h new file mode 100644 index 0000000..cf1461e --- /dev/null +++ b/linden/indra/llmessage/tests/commtest.h @@ -0,0 +1,83 @@ +/** + * @file commtest.h + * @author Nat Goodspeed + * @date 2009-01-09 + * @brief + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if ! defined(LL_COMMTEST_H) +#define LL_COMMTEST_H + +#include "networkio.h" +#include "llevents.h" +#include "llsd.h" +#include "llhost.h" +#include "stringize.h" +#include + +/** + * This struct is shared by a couple of standalone comm tests (ADD_COMM_BUILD_TEST). + */ +struct commtest_data +{ + NetworkIO& netio; + LLEventPumps& pumps; + LLEventStream replyPump, errorPump; + LLSD result; + bool success; + LLHost host; + std::string server; + + commtest_data(): + netio(NetworkIO::instance()), + pumps(LLEventPumps::instance()), + replyPump("reply"), + errorPump("error"), + success(false), + host("127.0.0.1", 8000), + server(STRINGIZE("http://" << host.getString() << "/")) + { + replyPump.listen("self", boost::bind(&commtest_data::outcome, this, _1, true)); + errorPump.listen("self", boost::bind(&commtest_data::outcome, this, _1, false)); + } + + bool outcome(const LLSD& _result, bool _success) + { +// std::cout << "commtest_data::outcome(" << _result << ", " << _success << ")\n"; + result = _result; + success = _success; + // Break the wait loop in NetworkIO::pump(), otherwise devs get + // irritated at making the big monolithic test executable take longer + pumps.obtain("done").post(success); + return false; + } +}; + +#endif /* ! defined(LL_COMMTEST_H) */ diff --git a/linden/indra/llmessage/tests/llcurl_stub.cpp b/linden/indra/llmessage/tests/llcurl_stub.cpp new file mode 100644 index 0000000..c73a565 --- /dev/null +++ b/linden/indra/llmessage/tests/llcurl_stub.cpp @@ -0,0 +1,100 @@ +/** + * @file llcurl_stub.cpp + * @brief stub class to allow unit testing + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llcurl.h" + +LLCurl::Responder::Responder() : mReferenceCount(0) +{ +} + +void LLCurl::Responder::completed(U32 status, std::basic_string, std::allocator > const &reason, + LLSD const& mContent) +{ + if (isGoodStatus(status)) + { + result(mContent); + } + else + { + error(status, reason, mContent); + } +} + +void LLCurl::Responder::completedHeader(unsigned, + std::basic_string, std::allocator > const&, + LLSD const&) +{ +} + +void LLCurl::Responder::completedRaw(unsigned, + std::basic_string, std::allocator > const&, + LLChannelDescriptors const&, + boost::shared_ptr const&) +{ +} + +void LLCurl::Responder::error(unsigned, + std::basic_string, std::allocator > const&, + LLSD const&) +{ +} + +LLCurl::Responder::~Responder () +{ +} + +void LLCurl::Responder::error(unsigned, + std::basic_string, std::allocator > const&) +{ +} + +void LLCurl::Responder::result(LLSD const&) +{ +} + +namespace boost +{ + void intrusive_ptr_add_ref(LLCurl::Responder* p) + { + ++p->mReferenceCount; + } + + void intrusive_ptr_release(LLCurl::Responder* p) + { + if(p && 0 == --p->mReferenceCount) + { + delete p; + } + } +}; + diff --git a/linden/indra/llmessage/tests/llhttpclientadapter_test.cpp b/linden/indra/llmessage/tests/llhttpclientadapter_test.cpp new file mode 100644 index 0000000..7065c9d --- /dev/null +++ b/linden/indra/llmessage/tests/llhttpclientadapter_test.cpp @@ -0,0 +1,170 @@ +/** + * @file + * @brief + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llhttpclientadapter.h" + +#include "../test/lltut.h" +#include "llhttpclient.h" +#include "llcurl_stub.cpp" + +float const HTTP_REQUEST_EXPIRY_SECS = 1.0F; + +std::vector get_urls; +std::vector > get_responders; +void LLHTTPClient::get(const std::string& url, boost::intrusive_ptr responder, const LLSD& headers, const F32 timeout) +{ + get_urls.push_back(url); + get_responders.push_back(responder); +} + +std::vector put_urls; +std::vector put_body; +std::vector > put_responders; + +void LLHTTPClient::put(const std::string& url, const LLSD& body, boost::intrusive_ptr responder, const LLSD& headers, const F32 timeout) +{ + put_urls.push_back(url); + put_responders.push_back(responder); + put_body.push_back(body); + +} + + +namespace tut +{ + struct LLHTTPClientAdapterData + { + LLHTTPClientAdapterData() + { + get_urls.clear(); + get_responders.clear(); + put_urls.clear(); + put_responders.clear(); + put_body.clear(); + } + }; + + typedef test_group factory; + typedef factory::object object; +} + +namespace +{ + tut::factory tf("LLHTTPClientAdapterData test"); +} + +namespace tut +{ + // Ensure we can create the object + template<> template<> + void object::test<1>() + { + LLHTTPClientAdapter adapter; + } + + // Does the get pass the appropriate arguments to the LLHTTPClient + template<> template<> + void object::test<2>() + { + LLHTTPClientAdapter adapter; + + boost::intrusive_ptr responder = new LLCurl::Responder(); + + adapter.get("Made up URL", responder); + ensure_equals(get_urls.size(), 1); + ensure_equals(get_urls[0], "Made up URL"); + } + + // Ensure the responder matches the one passed to get + template<> template<> + void object::test<3>() + { + LLHTTPClientAdapter adapter; + boost::intrusive_ptr responder = new LLCurl::Responder(); + + adapter.get("Made up URL", responder); + + ensure_equals(get_responders.size(), 1); + ensure_equals(get_responders[0].get(), responder.get()); + } + + // Ensure the correct url is used in the put + template<> template<> + void object::test<4>() + { + LLHTTPClientAdapter adapter; + + boost::intrusive_ptr responder = new LLCurl::Responder(); + + LLSD body; + body["TestBody"] = "Foobar"; + + adapter.put("Made up URL", body, responder); + ensure_equals(put_urls.size(), 1); + ensure_equals(put_urls[0], "Made up URL"); + } + + // Ensure the correct responder is used by put + template<> template<> + void object::test<5>() + { + LLHTTPClientAdapter adapter; + + boost::intrusive_ptr responder = new LLCurl::Responder(); + + LLSD body; + body["TestBody"] = "Foobar"; + + adapter.put("Made up URL", body, responder); + + ensure_equals(put_responders.size(), 1); + ensure_equals(put_responders[0].get(), responder.get()); + } + + // Ensure the message body is passed through the put properly + template<> template<> + void object::test<6>() + { + LLHTTPClientAdapter adapter; + + boost::intrusive_ptr responder = new LLCurl::Responder(); + + LLSD body; + body["TestBody"] = "Foobar"; + + adapter.put("Made up URL", body, responder); + + ensure_equals(put_body.size(), 1); + ensure_equals(put_body[0]["TestBody"].asString(), "Foobar"); + } +} + diff --git a/linden/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp b/linden/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp new file mode 100644 index 0000000..d57f17f --- /dev/null +++ b/linden/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp @@ -0,0 +1,165 @@ +/** + * @file lltrustedmessageservice_test.cpp + * @brief LLTrustedMessageService unit tests + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "lltemplatemessagedispatcher.h" +#include "lltut.h" + +#include "llhttpnode.h" +#include "llhost.h" +#include "message.h" +#include "llsd.h" + +#include "llhost.cpp" // Needed for copy operator +#include "net.cpp" // Needed by LLHost. + +LLMessageSystem * gMessageSystem = NULL; + +// sensor test doubles +bool gClearRecvWasCalled = false; +void LLMessageSystem::clearReceiveState(void) +{ + gClearRecvWasCalled = true; +} + +char gUdpDispatchedData[MAX_BUFFER_SIZE]; +bool gUdpDispatchWasCalled = false; +BOOL LLTemplateMessageReader::readMessage(const U8* data,class LLHost const &) +{ + gUdpDispatchWasCalled = true; + strcpy(gUdpDispatchedData, reinterpret_cast(data)); + return true; +} + +BOOL gValidateMessage = FALSE; +BOOL LLTemplateMessageReader::validateMessage(const U8*, S32 buffer_size, LLHost const &sender, bool trusted) +{ + return gValidateMessage; +} + +LLHost host; +const LLHost& LLMessageSystem::getSender() const +{ + return host; +} + +const char* gBinaryTemplateData = "BINARYTEMPLATEDATA"; +void fillVector(std::vector& vector_data, const char* data) +{ + vector_data.resize(strlen(data) + 1); + strcpy(reinterpret_cast(&vector_data[0]), data); +} + +namespace tut +{ + static LLTemplateMessageReader::message_template_number_map_t numberMap; + + struct LLTemplateMessageDispatcherData + { + LLTemplateMessageDispatcherData() + { + mMessageName = "MessageName"; + gUdpDispatchWasCalled = false; + gClearRecvWasCalled = false; + gValidateMessage = FALSE; + mMessage["body"]["binary-template-data"] = std::vector(); + } + + LLSD mMessage; + LLHTTPNode::ResponsePtr mResponsePtr; + std::string mMessageName; + }; + + typedef test_group factory; + typedef factory::object object; +} + +namespace +{ + tut::factory tf("LLTemplateMessageDispatcher test"); +} + +namespace tut +{ + // does an empty message stop processing? + template<> template<> + void object::test<1>() + { + LLTemplateMessageReader* pReader = NULL; + LLTemplateMessageDispatcher t(*pReader); + t.dispatch(mMessageName, mMessage, mResponsePtr); + ensure(! gUdpDispatchWasCalled); + ensure(! gClearRecvWasCalled); + } + + // does the disaptch invoke the udp send method? + template<> template<> + void object::test<2>() + { + LLTemplateMessageReader* pReader = NULL; + LLTemplateMessageDispatcher t(*pReader); + gValidateMessage = TRUE; + std::vector vector_data; + fillVector(vector_data, gBinaryTemplateData); + mMessage["body"]["binary-template-data"] = vector_data; + t.dispatch(mMessageName, mMessage, mResponsePtr); + ensure("udp dispatch was called", gUdpDispatchWasCalled); + } + + // what if the message wasn't valid? We would hope the message gets cleared! + template<> template<> + void object::test<3>() + { + LLTemplateMessageReader* pReader = NULL; + LLTemplateMessageDispatcher t(*pReader); + std::vector vector_data; + fillVector(vector_data, gBinaryTemplateData); + mMessage["body"]["binary-template-data"] = vector_data; + gValidateMessage = FALSE; + t.dispatch(mMessageName, mMessage, mResponsePtr); + ensure("clear received message was called", gClearRecvWasCalled); + } + + // is the binary data passed through correctly? + template<> template<> + void object::test<4>() + { + LLTemplateMessageReader* pReader = NULL; + LLTemplateMessageDispatcher t(*pReader); + gValidateMessage = TRUE; + std::vector vector_data; + fillVector(vector_data, gBinaryTemplateData); + mMessage["body"]["binary-template-data"] = vector_data; + t.dispatch(mMessageName, mMessage, mResponsePtr); + ensure("data couriered correctly", strcmp(gBinaryTemplateData, gUdpDispatchedData) == 0); + } +} + diff --git a/linden/indra/llmessage/tests/lltesthttpclientadapter.cpp b/linden/indra/llmessage/tests/lltesthttpclientadapter.cpp new file mode 100644 index 0000000..6361f1c --- /dev/null +++ b/linden/indra/llmessage/tests/lltesthttpclientadapter.cpp @@ -0,0 +1,67 @@ +/** + * @file + * @brief + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "lltesthttpclientadapter.h" + +LLTestHTTPClientAdapter::LLTestHTTPClientAdapter() +{ +} + +LLTestHTTPClientAdapter::~LLTestHTTPClientAdapter() +{ +} + +void LLTestHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder) +{ + mGetUrl.push_back(url); + mGetResponder.push_back(responder); +} + +void LLTestHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder) +{ + mPutUrl.push_back(url); + mPutBody.push_back(body); + mPutResponder.push_back(responder); +} + +U32 LLTestHTTPClientAdapter::putCalls() const +{ + return mPutUrl.size(); +} + +void LLTestHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) +{ + mGetUrl.push_back(url); + mGetHeaders.push_back(headers); + mGetResponder.push_back(responder); +} + + diff --git a/linden/indra/llmessage/tests/lltesthttpclientadapter.h b/linden/indra/llmessage/tests/lltesthttpclientadapter.h new file mode 100644 index 0000000..ac2afa8 --- /dev/null +++ b/linden/indra/llmessage/tests/lltesthttpclientadapter.h @@ -0,0 +1,63 @@ +/** + * @file + * @brief + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +/* Macro Definitions */ +#ifndef LL_LLTESTHTTPCLIENTADAPTER_H +#define LL_LLTESTHTTPCLIENTADAPTER_H + + +#include "linden_common.h" +#include "llhttpclientinterface.h" + +class LLTestHTTPClientAdapter : public LLHTTPClientInterface +{ +public: + LLTestHTTPClientAdapter(); + virtual ~LLTestHTTPClientAdapter(); + virtual void get(const std::string& url, LLCurl::ResponderPtr responder); + virtual void get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers); + + virtual void put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder); + U32 putCalls() const; + + std::vector mPutBody; + std::vector mGetHeaders; + std::vector mPutUrl; + std::vector mGetUrl; + std::vector mPutResponder; + std::vector mGetResponder; +}; + + + +#endif //LL_LLSIMULATORPRESENCESENDER_H + diff --git a/linden/indra/llmessage/tests/lltestmessagesender.cpp b/linden/indra/llmessage/tests/lltestmessagesender.cpp new file mode 100644 index 0000000..5e8a87f --- /dev/null +++ b/linden/indra/llmessage/tests/lltestmessagesender.cpp @@ -0,0 +1,44 @@ +/** + * @file + * @brief + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "lltestmessagesender.h" + +LLTestMessageSender::~LLTestMessageSender() +{ +} + + +S32 LLTestMessageSender::sendMessage(const LLHost& host, LLStoredMessagePtr message) +{ + mSendHosts.push_back(host); + mSendMessages.push_back(message); + return 0; +} diff --git a/linden/indra/llmessage/tests/lltestmessagesender.h b/linden/indra/llmessage/tests/lltestmessagesender.h new file mode 100644 index 0000000..f57210e --- /dev/null +++ b/linden/indra/llmessage/tests/lltestmessagesender.h @@ -0,0 +1,57 @@ +/** + * @file + * @brief + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +/* Macro Definitions */ +#ifndef LL_LLTESTMESSAGESENDER_H +#define LL_LLTESTMESSAGESENDER_H + + +#include "linden_common.h" +#include "llmessagesenderinterface.h" +#include + + + +class LLTestMessageSender : public LLMessageSenderInterface +{ +public: + virtual ~LLTestMessageSender(); + virtual S32 sendMessage(const LLHost& host, LLStoredMessagePtr message); + + std::vector mSendHosts; + std::vector mSendMessages; +}; + + + +#endif //LL_LLTESTMESSAGESENDER_H + diff --git a/linden/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/linden/indra/llmessage/tests/lltrustedmessageservice_test.cpp new file mode 100644 index 0000000..0a3da4b --- /dev/null +++ b/linden/indra/llmessage/tests/lltrustedmessageservice_test.cpp @@ -0,0 +1,146 @@ +/** + * @file lltrustedmessageservice_test.cpp + * @brief LLTrustedMessageService unit tests + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "lltrustedmessageservice.h" +#include "../test/lltut.h" + +#include "llhost.cpp" // LLHost is a value type for test purposes. +#include "net.cpp" // Needed by LLHost. + +#include "message.h" +#include "llmessageconfig.h" + +LLMessageSystem* gMessageSystem = NULL; + +LLMessageConfig::SenderTrust +LLMessageConfig::getSenderTrustedness(const std::string& msg_name) +{ + return LLMessageConfig::NOT_SET; +} + +void LLMessageSystem::receivedMessageFromTrustedSender() +{ +} + +bool LLMessageSystem::isTrustedSender(const LLHost& host) const +{ + return false; +} + +bool LLMessageSystem::isTrustedMessage(const std::string& name) const +{ + return false; +} + +bool messageDispatched = false; +bool messageDispatchedAsBinary = false; +LLSD lastLLSD; +std::string lastMessageName; + +void LLMessageSystem::dispatch(const std::string& msg_name, + const LLSD& message, + LLHTTPNode::ResponsePtr responsep) +{ + messageDispatched = true; + lastLLSD = message; + lastMessageName = msg_name; +} + +void LLMessageSystem::dispatchTemplate(const std::string& msg_name, + const LLSD& message, + LLHTTPNode::ResponsePtr responsep) +{ + lastLLSD = message; + lastMessageName = msg_name; + messageDispatchedAsBinary = true; +} + +namespace tut +{ + struct LLTrustedMessageServiceData + { + LLTrustedMessageServiceData() + { + LLSD emptyLLSD; + lastLLSD = emptyLLSD; + lastMessageName = "uninitialised message name"; + messageDispatched = false; + messageDispatchedAsBinary = false; + } + }; + + typedef test_group factory; + typedef factory::object object; +} + +namespace +{ + tut::factory tf("LLTrustedMessageServiceData test"); +} + +namespace tut +{ + // characterisation tests + + // 1) test that messages get forwarded with names etc. as current behaviour (something like LLMessageSystem::dispatch(name, data...) + + // test llsd messages are sent as normal using LLMessageSystem::dispatch() (eventually) + template<> template<> + void object::test<1>() + { + LLHTTPNode::ResponsePtr response; + LLSD input; + LLSD context; + LLTrustedMessageService adapter; + adapter.post(response, context, input); + // test original ting got called wit nowt, ya get me blood? + ensure_equals(messageDispatched, true); + ensure(lastLLSD.has("body")); + } + + // test that llsd wrapped binary-template-data messages are + // sent via LLMessageSystem::binaryDispatch() or similar + template<> template<> + void object::test<2>() + { + LLHTTPNode::ResponsePtr response; + LLSD input; + input["binary-template-data"] = "10001010110"; //make me a message here. + LLSD context; + LLTrustedMessageService adapter; + + adapter.post(response, context, input); + ensure("check template-binary-data message was dispatched as binary", messageDispatchedAsBinary); + ensure_equals(lastLLSD["body"]["binary-template-data"].asString(), "10001010110"); + // test somit got called with "10001010110" (something like LLMessageSystem::dispatchTemplate(blah)) + } +} diff --git a/linden/indra/llmessage/tests/networkio.h b/linden/indra/llmessage/tests/networkio.h new file mode 100644 index 0000000..0ebe369 --- /dev/null +++ b/linden/indra/llmessage/tests/networkio.h @@ -0,0 +1,116 @@ +/** + * @file networkio.h + * @author Nat Goodspeed + * @date 2009-01-09 + * @brief + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if ! defined(LL_NETWORKIO_H) +#define LL_NETWORKIO_H + +#include "llmemory.h" // LLSingleton +#include "llapr.h" +#include "llares.h" +#include "llpumpio.h" +#include "llhttpclient.h" + +/***************************************************************************** +* NetworkIO +*****************************************************************************/ +// Doing this initialization in a class constructor makes sense. But we don't +// want to redo it for each different test. Nor do we want to do it at static- +// init time. Use the lazy, on-demand initialization we get from LLSingleton. +class NetworkIO: public LLSingleton +{ +public: + NetworkIO(): + mServicePump(NULL), + mDone(false) + { + ll_init_apr(); + if (! gAPRPoolp) + { + throw std::runtime_error("Can't initialize APR"); + } + + // Create IO Pump to use for HTTP Requests. + mServicePump = new LLPumpIO(gAPRPoolp); + LLHTTPClient::setPump(*mServicePump); + if (ll_init_ares() == NULL || !gAres->isInitialized()) + { + throw std::runtime_error("Can't start DNS resolver"); + } + + // You can interrupt pump() without waiting the full timeout duration + // by posting an event to the LLEventPump named "done". + LLEventPumps::instance().obtain("done").listen("self", + boost::bind(&NetworkIO::done, this, _1)); + } + + bool pump(F32 timeout=10) + { + // Reset the done flag so we don't pop out prematurely + mDone = false; + // Evidently the IO structures underlying LLHTTPClient need to be + // "pumped". Do some stuff normally performed in the viewer's main + // loop. + LLTimer timer; + while (timer.getElapsedTimeF32() < timeout) + { + if (mDone) + { +// std::cout << "NetworkIO::pump(" << timeout << "): breaking loop after " +// << timer.getElapsedTimeF32() << " seconds\n"; + return true; + } + pumpOnce(); + } + return false; + } + + void pumpOnce() + { + gAres->process(); + mServicePump->pump(); + mServicePump->callback(); + } + + bool done(const LLSD&) + { + mDone = true; + return false; + } + +private: + LLPumpIO* mServicePump; + bool mDone; +}; + +#endif /* ! defined(LL_NETWORKIO_H) */ diff --git a/linden/indra/llmessage/tests/test_llsdmessage_peer.py b/linden/indra/llmessage/tests/test_llsdmessage_peer.py new file mode 100644 index 0000000..655169d --- /dev/null +++ b/linden/indra/llmessage/tests/test_llsdmessage_peer.py @@ -0,0 +1,153 @@ +#!/usr/bin/python +"""\ +@file test_llsdmessage_peer.py +@author Nat Goodspeed +@date 2008-10-09 +@brief This script asynchronously runs the executable (with args) specified on + the command line, returning its result code. While that executable is + running, we provide dummy local services for use by C++ tests. + +$LicenseInfo:firstyear=2008&license=viewergpl$ + +Copyright (c) 2008-2009, Linden Research, Inc. + +Second Life Viewer Source Code +The source code in this file ("Source Code") is provided by Linden Lab +to you under the terms of the GNU General Public License, version 2.0 +("GPL"), unless you have obtained a separate licensing agreement +("Other License"), formally executed by you and Linden Lab. Terms of +the GPL can be found in doc/GPL-license.txt in this distribution, or +online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + +There are special exceptions to the terms and conditions of the GPL as +it is applied to this Source Code. View the full text of the exception +in the file doc/FLOSS-exception.txt in this software distribution, or +online at +http://secondlifegrid.net/programs/open_source/licensing/flossexception + +By copying, modifying or distributing this software, you acknowledge +that you have read and understood your obligations described above, +and agree to abide by those obligations. + +ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +COMPLETENESS OR PERFORMANCE. +$/LicenseInfo$ +""" + +import os +import sys +from threading import Thread +from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler +mydir = os.path.dirname(__file__) # expected to be .../indra/llmessage/tests/ +sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python")) +from indra.util.fastest_elementtree import parse as xml_parse +from indra.base import llsd + +def debug(*args): + sys.stdout.writelines(args) + sys.stdout.flush() +# comment out the line below to enable debug output +debug = lambda *args: None + +class TestHTTPRequestHandler(BaseHTTPRequestHandler): + """This subclass of BaseHTTPRequestHandler is to receive and echo + LLSD-flavored messages sent by the C++ LLHTTPClient. + """ + def read(self): + # The following logic is adapted from the library module + # SimpleXMLRPCServer.py. + # Get arguments by reading body of request. + # We read this in chunks to avoid straining + # socket.read(); around the 10 or 15Mb mark, some platforms + # begin to have problems (bug #792570). + try: + size_remaining = int(self.headers["content-length"]) + except (KeyError, ValueError): + return "" + max_chunk_size = 10*1024*1024 + L = [] + while size_remaining: + chunk_size = min(size_remaining, max_chunk_size) + chunk = self.rfile.read(chunk_size) + L.append(chunk) + size_remaining -= len(chunk) + return ''.join(L) + # end of swiped read() logic + + def read_xml(self): + # This approach reads the entire POST data into memory first + return llsd.parse(self.read()) +## # This approach attempts to stream in the LLSD XML from self.rfile, +## # assuming that the underlying XML parser reads its input file +## # incrementally. Unfortunately I haven't been able to make it work. +## tree = xml_parse(self.rfile) +## debug("Finished raw parse\n") +## debug("parsed XML tree %s\n" % tree) +## debug("parsed root node %s\n" % tree.getroot()) +## debug("root node tag %s\n" % tree.getroot().tag) +## return llsd.to_python(tree.getroot()) + + def do_GET(self): + # Of course, don't attempt to read data. + self.answer(dict(reply="success", status=500, + reason="Your GET operation requested failure")) + + def do_POST(self): + # Read the provided POST data. + self.answer(self.read_xml()) + + def answer(self, data): + if "fail" not in self.path: + response = llsd.format_xml(data.get("reply", llsd.LLSD("success"))) + self.send_response(200) + self.send_header("Content-type", "application/llsd+xml") + self.send_header("Content-Length", str(len(response))) + self.end_headers() + self.wfile.write(response) + else: # fail requested + status = data.get("status", 500) + reason = data.get("reason", + self.responses.get(status, + ("fail requested", + "Your request specified failure status %s " + "without providing a reason" % status))[1]) + self.send_error(status, reason) + + def log_request(self, code, size=None): + # For present purposes, we don't want the request splattered onto + # stderr, as it would upset devs watching the test run + pass + + def log_error(self, format, *args): + # Suppress error output as well + pass + +class TestHTTPServer(Thread): + def run(self): + httpd = HTTPServer(('127.0.0.1', 8000), TestHTTPRequestHandler) + debug("Starting HTTP server...\n") + httpd.serve_forever() + +def main(*args): + # Start HTTP server thread. Note that this and all other comm server + # threads should be daemon threads: we'll let them run "forever," + # confident that the whole process will terminate when the main thread + # terminates, which will be when the test executable child process + # terminates. + httpThread = TestHTTPServer(name="httpd") + httpThread.setDaemon(True) + httpThread.start() + # choice of os.spawnv(): + # - [v vs. l] pass a list of args vs. individual arguments, + # - [no p] don't use the PATH because we specifically want to invoke the + # executable passed as our first arg, + # - [no e] child should inherit this process's environment. + debug("Running %s...\n" % (" ".join(args))) + sys.stdout.flush() + rc = os.spawnv(os.P_WAIT, args[0], args) + debug("%s returned %s\n" % (args[0], rc)) + return rc + +if __name__ == "__main__": + sys.exit(main(*sys.argv[1:])) diff --git a/linden/indra/llplugin/CMakeLists.txt b/linden/indra/llplugin/CMakeLists.txt new file mode 100644 index 0000000..6706775 --- /dev/null +++ b/linden/indra/llplugin/CMakeLists.txt @@ -0,0 +1,55 @@ +# -*- cmake -*- + +project(llplugin) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLMath) +include(LLMessage) +include(LLRender) +include(LLXML) +include(LLWindow) + +include_directories( + ${LLCOMMON_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLMESSAGE_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLXML_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} + ) + +set(llplugin_SOURCE_FILES + llpluginclassmedia.cpp + llplugininstance.cpp + llpluginmessage.cpp + llpluginmessagepipe.cpp + llpluginprocesschild.cpp + llpluginprocessparent.cpp + llpluginsharedmemory.cpp + ) + +set(llplugin_HEADER_FILES + CMakeLists.txt + + llpluginclassmedia.h + llpluginclassmediaowner.h + llplugininstance.h + llpluginmessage.h + llpluginmessageclasses.h + llpluginmessagepipe.h + llpluginprocesschild.h + llpluginprocessparent.h + llpluginsharedmemory.h + ) + +set_source_files_properties(${llplugin_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES}) + +add_library (llplugin ${llplugin_SOURCE_FILES}) + +add_subdirectory(slplugin) diff --git a/linden/indra/llplugin/llpluginclassmedia.cpp b/linden/indra/llplugin/llpluginclassmedia.cpp new file mode 100644 index 0000000..a6f6f30 --- /dev/null +++ b/linden/indra/llplugin/llpluginclassmedia.cpp @@ -0,0 +1,1162 @@ +/** + * @file llpluginclassmedia.cpp + * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "indra_constants.h" + +#include "llpluginclassmedia.h" +#include "llpluginmessageclasses.h" + +static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256; + +static int nextPowerOf2( int value ) +{ + int next_power_of_2 = 1; + while ( next_power_of_2 < value ) + { + next_power_of_2 <<= 1; + } + + return next_power_of_2; +} + +LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner) +{ + mOwner = owner; + mPlugin = NULL; + reset(); +} + + +LLPluginClassMedia::~LLPluginClassMedia() +{ + reset(); +} + +bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug, const std::string &user_data_path) +{ + LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL; + LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL; + LL_DEBUGS("Plugin") << "user_data_path: " << user_data_path << LL_ENDL; + + mPlugin = new LLPluginProcessParent(this); + mPlugin->setSleepTime(mSleepTime); + mPlugin->init(launcher_filename, plugin_filename, debug, user_data_path); + + return true; +} + + +void LLPluginClassMedia::reset() +{ + if(mPlugin != NULL) + { + delete mPlugin; + mPlugin = NULL; + } + + mTextureParamsReceived = false; + mRequestedTextureDepth = 0; + mRequestedTextureInternalFormat = 0; + mRequestedTextureFormat = 0; + mRequestedTextureType = 0; + mRequestedTextureSwapBytes = false; + mRequestedTextureCoordsOpenGL = false; + mTextureSharedMemorySize = 0; + mTextureSharedMemoryName.clear(); + mDefaultMediaWidth = 0; + mDefaultMediaHeight = 0; + mNaturalMediaWidth = 0; + mNaturalMediaHeight = 0; + mSetMediaWidth = -1; + mSetMediaHeight = -1; + mRequestedMediaWidth = 0; + mRequestedMediaHeight = 0; + mFullMediaWidth = 0; + mFullMediaHeight = 0; + mTextureWidth = 0; + mTextureHeight = 0; + mMediaWidth = 0; + mMediaHeight = 0; + mDirtyRect = LLRect::null; + mAutoScaleMedia = false; + mRequestedVolume = 1.0f; + mPriority = PRIORITY_NORMAL; + mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT; + mAllowDownsample = false; + mPadding = 0; + mLastMouseX = 0; + mLastMouseY = 0; + mStatus = LLPluginClassMediaOwner::MEDIA_NONE; + mSleepTime = 1.0f / 100.0f; + mCanCut = false; + mCanCopy = false; + mCanPaste = false; + mMediaName.clear(); + mMediaDescription.clear(); + + // media_browser class + mNavigateURI.clear(); + mNavigateResultCode = -1; + mNavigateResultString.clear(); + mHistoryBackAvailable = false; + mHistoryForwardAvailable = false; + mStatusText.clear(); + mProgressPercent = 0; + + // media_time class + mCurrentTime = 0.0f; + mDuration = 0.0f; + mCurrentRate = 0.0f; + mLoadedDuration = 0.0f; +} + +void LLPluginClassMedia::idle(void) +{ + if(mPlugin) + { + mPlugin->idle(); + } + + if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL)) + { + // Can't process a size change at this time + } + else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight)) + { + // Calculate the correct size for the media texture + mRequestedTextureHeight = mRequestedMediaHeight; + if(mPadding < 0) + { + // negative values indicate the plugin wants a power of 2 + mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth); + } + else + { + mRequestedTextureWidth = mRequestedMediaWidth; + + if(mPadding > 1) + { + // Pad up to a multiple of the specified number of bytes per row + int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth; + int pad = rowbytes % mPadding; + if(pad != 0) + { + rowbytes += mPadding - pad; + } + + if(rowbytes % mRequestedTextureDepth == 0) + { + mRequestedTextureWidth = rowbytes / mRequestedTextureDepth; + } + else + { + LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL; + } + } + } + + + // Size change has been requested but not initiated yet. + size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth; + + // Add an extra line for padding, just in case. + newsize += mRequestedTextureWidth * mRequestedTextureDepth; + + if(newsize != mTextureSharedMemorySize) + { + if(!mTextureSharedMemoryName.empty()) + { + // Tell the plugin to remove the old memory segment + mPlugin->removeSharedMemory(mTextureSharedMemoryName); + mTextureSharedMemoryName.clear(); + } + + mTextureSharedMemorySize = newsize; + mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize); + if(!mTextureSharedMemoryName.empty()) + { + void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName); + + // clear texture memory to avoid random screen visual fuzz from uninitialized texture data + memset( addr, 0x00, newsize ); + + // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin, + // so it may not be worthwhile. + // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight); + } + } + + // This is our local indicator that a change is in progress. + mTextureWidth = -1; + mTextureHeight = -1; + mMediaWidth = -1; + mMediaHeight = -1; + + // This invalidates any existing dirty rect. + resetDirty(); + + // Send a size change message to the plugin + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change"); + message.setValue("name", mTextureSharedMemoryName); + message.setValueS32("width", mRequestedMediaWidth); + message.setValueS32("height", mRequestedMediaHeight); + message.setValueS32("texture_width", mRequestedTextureWidth); + message.setValueS32("texture_height", mRequestedTextureHeight); + mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue. + + LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL; + } + } + + if(mPlugin && mPlugin->isRunning()) + { + // Send queued messages + while(!mSendQueue.empty()) + { + LLPluginMessage message = mSendQueue.front(); + mSendQueue.pop(); + mPlugin->sendMessage(message); + } + } +} + +int LLPluginClassMedia::getTextureWidth() const +{ + return nextPowerOf2(mTextureWidth); +} + +int LLPluginClassMedia::getTextureHeight() const +{ + return nextPowerOf2(mTextureHeight); +} + +unsigned char* LLPluginClassMedia::getBitsData() +{ + unsigned char *result = NULL; + if((mPlugin != NULL) && !mTextureSharedMemoryName.empty()) + { + result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName); + } + return result; +} + +void LLPluginClassMedia::setSize(int width, int height) +{ + if((width > 0) && (height > 0)) + { + mSetMediaWidth = width; + mSetMediaHeight = height; + } + else + { + mSetMediaWidth = -1; + mSetMediaHeight = -1; + } + + setSizeInternal(); +} + +void LLPluginClassMedia::setSizeInternal(void) +{ + if((mSetMediaWidth > 0) && (mSetMediaHeight > 0)) + { + mRequestedMediaWidth = mSetMediaWidth; + mRequestedMediaHeight = mSetMediaHeight; + } + else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0)) + { + mRequestedMediaWidth = mNaturalMediaWidth; + mRequestedMediaHeight = mNaturalMediaHeight; + } + else + { + mRequestedMediaWidth = mDefaultMediaWidth; + mRequestedMediaHeight = mDefaultMediaHeight; + } + + // Save these for size/interest calculations + mFullMediaWidth = mRequestedMediaWidth; + mFullMediaHeight = mRequestedMediaHeight; + + if(mAllowDownsample) + { + switch(mPriority) + { + case PRIORITY_SLIDESHOW: + case PRIORITY_LOW: + // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit + while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit)) + { + mRequestedMediaWidth /= 2; + mRequestedMediaHeight /= 2; + } + break; + + default: + // Don't adjust texture size + break; + } + } + + if(mAutoScaleMedia) + { + mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth); + mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight); + } + + if(mRequestedMediaWidth > 2048) + mRequestedMediaWidth = 2048; + + if(mRequestedMediaHeight > 2048) + mRequestedMediaHeight = 2048; +} + +void LLPluginClassMedia::setAutoScale(bool auto_scale) +{ + if(auto_scale != mAutoScaleMedia) + { + mAutoScaleMedia = auto_scale; + setSizeInternal(); + } +} + +bool LLPluginClassMedia::textureValid(void) +{ + if( + !mTextureParamsReceived || + mTextureWidth <= 0 || + mTextureHeight <= 0 || + mMediaWidth <= 0 || + mMediaHeight <= 0 || + mRequestedMediaWidth != mMediaWidth || + mRequestedMediaHeight != mMediaHeight || + getBitsData() == NULL + ) + return false; + + return true; +} + +bool LLPluginClassMedia::getDirty(LLRect *dirty_rect) +{ + bool result = !mDirtyRect.isNull(); + + if(dirty_rect != NULL) + { + *dirty_rect = mDirtyRect; + } + + return result; +} + +void LLPluginClassMedia::resetDirty(void) +{ + mDirtyRect = LLRect::null; +} + +std::string LLPluginClassMedia::translateModifiers(MASK modifiers) +{ + std::string result; + + + if(modifiers & MASK_CONTROL) + { + result += "control|"; + } + + if(modifiers & MASK_ALT) + { + result += "alt|"; + } + + if(modifiers & MASK_SHIFT) + { + result += "shift|"; + } + + // TODO: should I deal with platform differences here or in callers? + // TODO: how do we deal with the Mac "command" key? +/* + if(modifiers & MASK_SOMETHING) + { + result += "meta|"; + } +*/ + return result; +} + +void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers) +{ + if(type == MOUSE_EVENT_MOVE) + { + if((x == mLastMouseX) && (y == mLastMouseY)) + { + // Don't spam unnecessary mouse move events. + return; + } + + mLastMouseX = x; + mLastMouseY = y; + } + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event"); + std::string temp; + switch(type) + { + case MOUSE_EVENT_DOWN: temp = "down"; break; + case MOUSE_EVENT_UP: temp = "up"; break; + case MOUSE_EVENT_MOVE: temp = "move"; break; + case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click"; break; + } + message.setValue("event", temp); + + message.setValueS32("button", button); + + message.setValueS32("x", x); + + // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it. + if(!mRequestedTextureCoordsOpenGL) + { + // TODO: Should I use mMediaHeight or mRequestedMediaHeight here? + y = mMediaHeight - y; + } + message.setValueS32("y", y); + + message.setValue("modifiers", translateModifiers(modifiers)); + + sendMessage(message); +} + +bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers) +{ + bool result = true; + + // FIXME: + // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode. + // For now, return false for the ones the webkit plugin won't handle properly. + + switch(key_code) + { + case KEY_BACKSPACE: + case KEY_TAB: + case KEY_RETURN: + case KEY_PAD_RETURN: + case KEY_SHIFT: + case KEY_CONTROL: + case KEY_ALT: + case KEY_CAPSLOCK: + case KEY_ESCAPE: + case KEY_PAGE_UP: + case KEY_PAGE_DOWN: + case KEY_END: + case KEY_HOME: + case KEY_LEFT: + case KEY_UP: + case KEY_RIGHT: + case KEY_DOWN: + case KEY_INSERT: + case KEY_DELETE: + // These will be handled + break; + + default: + // regular ASCII characters will also be handled + if(key_code >= KEY_SPECIAL) + { + // Other "special" codes will not work properly. + result = false; + } + break; + } + + if(result) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event"); + std::string temp; + switch(type) + { + case KEY_EVENT_DOWN: temp = "down"; break; + case KEY_EVENT_UP: temp = "up"; break; + case KEY_EVENT_REPEAT: temp = "repeat"; break; + } + message.setValue("event", temp); + + message.setValueS32("key", key_code); + + message.setValue("modifiers", translateModifiers(modifiers)); + + sendMessage(message); + } + + return result; +} + +void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event"); + + message.setValueS32("x", x); + message.setValueS32("y", y); + message.setValue("modifiers", translateModifiers(modifiers)); + + sendMessage(message); +} + +bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event"); + + message.setValue("text", text); + message.setValue("modifiers", translateModifiers(modifiers)); + + sendMessage(message); + + return true; +} + +void LLPluginClassMedia::loadURI(const std::string &uri) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri"); + + message.setValue("uri", uri); + + sendMessage(message); +} + +const char* LLPluginClassMedia::priorityToString(EPriority priority) +{ + const char* result = "UNKNOWN"; + switch(priority) + { + case PRIORITY_UNLOADED: result = "unloaded"; break; + case PRIORITY_STOPPED: result = "stopped"; break; + case PRIORITY_HIDDEN: result = "hidden"; break; + case PRIORITY_SLIDESHOW: result = "slideshow"; break; + case PRIORITY_LOW: result = "low"; break; + case PRIORITY_NORMAL: result = "normal"; break; + case PRIORITY_HIGH: result = "high"; break; + } + + return result; +} + +void LLPluginClassMedia::setPriority(EPriority priority) +{ + if(mPriority != priority) + { + mPriority = priority; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority"); + + std::string priority_string = priorityToString(priority); + switch(priority) + { + case PRIORITY_UNLOADED: + mSleepTime = 1.0f; + break; + case PRIORITY_STOPPED: + mSleepTime = 1.0f; + break; + case PRIORITY_HIDDEN: + mSleepTime = 1.0f; + break; + case PRIORITY_SLIDESHOW: + mSleepTime = 1.0f; + break; + case PRIORITY_LOW: + mSleepTime = 1.0f / 25.0f; + break; + case PRIORITY_NORMAL: + mSleepTime = 1.0f / 50.0f; + break; + case PRIORITY_HIGH: + mSleepTime = 1.0f / 100.0f; + break; + } + + message.setValue("priority", priority_string); + + sendMessage(message); + + if(mPlugin) + { + mPlugin->setSleepTime(mSleepTime); + } + + LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL; + + // This may affect the calculated size, so recalculate it here. + setSizeInternal(); + } +} + +void LLPluginClassMedia::setLowPrioritySizeLimit(int size) +{ + int power = nextPowerOf2(size); + if(mLowPrioritySizeLimit != power) + { + mLowPrioritySizeLimit = power; + + // This may affect the calculated size, so recalculate it here. + setSizeInternal(); + } +} + +F64 LLPluginClassMedia::getCPUUsage() +{ + F64 result = 0.0f; + + if(mPlugin) + { + result = mPlugin->getCPUUsage(); + } + + return result; +} + +void LLPluginClassMedia::cut() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut"); + sendMessage(message); +} + +void LLPluginClassMedia::copy() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy"); + sendMessage(message); +} + +void LLPluginClassMedia::paste() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste"); + sendMessage(message); +} + +/* virtual */ +void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) +{ + std::string message_class = message.getClass(); + + if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + std::string message_name = message.getName(); + if(message_name == "texture_params") + { + mRequestedTextureDepth = message.getValueS32("depth"); + mRequestedTextureInternalFormat = message.getValueU32("internalformat"); + mRequestedTextureFormat = message.getValueU32("format"); + mRequestedTextureType = message.getValueU32("type"); + mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes"); + mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl"); + + // These two are optional, and will default to 0 if they're not specified. + mDefaultMediaWidth = message.getValueS32("default_width"); + mDefaultMediaHeight = message.getValueS32("default_height"); + + mAllowDownsample = message.getValueBoolean("allow_downsample"); + mPadding = message.getValueS32("padding"); + + setSizeInternal(); + + mTextureParamsReceived = true; + } + else if(message_name == "updated") + { + if(message.hasValue("left")) + { + LLRect newDirtyRect; + newDirtyRect.mLeft = message.getValueS32("left"); + newDirtyRect.mTop = message.getValueS32("top"); + newDirtyRect.mRight = message.getValueS32("right"); + newDirtyRect.mBottom = message.getValueS32("bottom"); + + // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion. + // If they're backwards, swap them. + if(newDirtyRect.mTop < newDirtyRect.mBottom) + { + S32 temp = newDirtyRect.mTop; + newDirtyRect.mTop = newDirtyRect.mBottom; + newDirtyRect.mBottom = temp; + } + + if(mDirtyRect.isNull()) + { + mDirtyRect = newDirtyRect; + } + else + { + mDirtyRect.unionWith(newDirtyRect); + } + + LL_DEBUGS("Plugin") << "adjusted incoming rect is: (" + << newDirtyRect.mLeft << ", " + << newDirtyRect.mTop << ", " + << newDirtyRect.mRight << ", " + << newDirtyRect.mBottom << "), new dirty rect is: (" + << mDirtyRect.mLeft << ", " + << mDirtyRect.mTop << ", " + << mDirtyRect.mRight << ", " + << mDirtyRect.mBottom << ")" + << LL_ENDL; + + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED); + } + + + bool time_duration_updated = false; + int previous_percent = mProgressPercent; + + if(message.hasValue("current_time")) + { + mCurrentTime = message.getValueReal("current_time"); + time_duration_updated = true; + } + if(message.hasValue("duration")) + { + mDuration = message.getValueReal("duration"); + time_duration_updated = true; + } + + if(message.hasValue("current_rate")) + { + mCurrentRate = message.getValueReal("current_rate"); + } + + if(message.hasValue("loaded_duration")) + { + mLoadedDuration = message.getValueReal("loaded_duration"); + time_duration_updated = true; + } + else + { + // If the message doesn't contain a loaded_duration param, assume it's equal to duration + mLoadedDuration = mDuration; + } + + // Calculate a percentage based on the loaded duration and total duration. + if(mDuration != 0.0f) // Don't divide by zero. + { + mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration); + } + + if(time_duration_updated) + { + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED); + } + + if(previous_percent != mProgressPercent) + { + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED); + } + } + else if(message_name == "media_status") + { + std::string status = message.getValue("status"); + + LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL; + + if(status == "loading") + { + mStatus = LLPluginClassMediaOwner::MEDIA_LOADING; + } + else if(status == "loaded") + { + mStatus = LLPluginClassMediaOwner::MEDIA_LOADED; + } + else if(status == "error") + { + mStatus = LLPluginClassMediaOwner::MEDIA_ERROR; + } + else if(status == "playing") + { + mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING; + } + else if(status == "paused") + { + mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED; + } + else if(status == "done") + { + mStatus = LLPluginClassMediaOwner::MEDIA_DONE; + } + else + { + // empty string or any unknown string + mStatus = LLPluginClassMediaOwner::MEDIA_NONE; + } + } + else if(message_name == "size_change_request") + { + S32 width = message.getValueS32("width"); + S32 height = message.getValueS32("height"); + std::string name = message.getValue("name"); + + // TODO: check that name matches? + mNaturalMediaWidth = width; + mNaturalMediaHeight = height; + + setSizeInternal(); + } + else if(message_name == "size_change_response") + { + std::string name = message.getValue("name"); + + // TODO: check that name matches? + + mTextureWidth = message.getValueS32("texture_width"); + mTextureHeight = message.getValueS32("texture_height"); + mMediaWidth = message.getValueS32("width"); + mMediaHeight = message.getValueS32("height"); + + // This invalidates any existing dirty rect. + resetDirty(); + + // TODO: should we verify that the plugin sent back the right values? + // Two size changes in a row may cause them to not match, due to queueing, etc. + + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED); + } + else if(message_name == "cursor_changed") + { + mCursorName = message.getValue("name"); + + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED); + } + else if(message_name == "edit_state") + { + if(message.hasValue("cut")) + { + mCanCut = message.getValueBoolean("cut"); + } + if(message.hasValue("copy")) + { + mCanCopy = message.getValueBoolean("copy"); + } + if(message.hasValue("paste")) + { + mCanPaste = message.getValueBoolean("paste"); + } + } + else if(message_name == "name_text") + { + mMediaName = message.getValue("name"); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED); + } + else + { + LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) + { + std::string message_name = message.getName(); + if(message_name == "navigate_begin") + { + mNavigateURI = message.getValue("uri"); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN); + } + else if(message_name == "navigate_complete") + { + mNavigateURI = message.getValue("uri"); + mNavigateResultCode = message.getValueS32("result_code"); + mNavigateResultString = message.getValue("result_string"); + mHistoryBackAvailable = message.getValueBoolean("history_back_available"); + mHistoryForwardAvailable = message.getValueBoolean("history_forward_available"); + + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE); + } + else if(message_name == "progress") + { + mProgressPercent = message.getValueS32("percent"); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED); + } + else if(message_name == "status_text") + { + mStatusText = message.getValue("status"); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED); + } + else if(message_name == "location_changed") + { + mLocation = message.getValue("uri"); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED); + } + else if(message_name == "click_href") + { + mClickURL = message.getValue("uri"); + mClickTarget = message.getValue("target"); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF); + } + else if(message_name == "click_nofollow") + { + mClickURL = message.getValue("uri"); + mClickTarget.clear(); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW); + } + else + { + LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) + { + std::string message_name = message.getName(); + + // This class hasn't defined any incoming messages yet. +// if(message_name == "message_name") +// { +// } +// else + { + LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; + } + } + +} + +/* virtual */ +void LLPluginClassMedia::pluginLaunchFailed() +{ + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH); +} + +/* virtual */ +void LLPluginClassMedia::pluginDied() +{ + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED); +} + +void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event) +{ + if(mOwner) + { + mOwner->handleMediaEvent(this, event); + } +} + +void LLPluginClassMedia::sendMessage(const LLPluginMessage &message) +{ + if(mPlugin && mPlugin->isRunning()) + { + mPlugin->sendMessage(message); + } + else + { + // The plugin isn't set up yet -- queue this message to be sent after initialization. + mSendQueue.push(message); + } +} + +//////////////////////////////////////////////////////////// +// MARK: media_browser class functions +bool LLPluginClassMedia::pluginSupportsMediaBrowser(void) +{ + std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER); + return !version.empty(); +} + +void LLPluginClassMedia::focus(bool focused) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus"); + + message.setValueBoolean("focused", focused); + + sendMessage(message); +} + +void LLPluginClassMedia::clear_cache() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache"); + sendMessage(message); +} + +void LLPluginClassMedia::clear_cookies() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies"); + sendMessage(message); +} + +void LLPluginClassMedia::enable_cookies(bool enable) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies"); + sendMessage(message); +} + +void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup"); + + message.setValueBoolean("enable", enable); + message.setValue("host", host); + message.setValueS32("port", port); + + sendMessage(message); +} + +void LLPluginClassMedia::browse_stop() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop"); + sendMessage(message); +} + +void LLPluginClassMedia::browse_reload(bool ignore_cache) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload"); + + message.setValueBoolean("ignore_cache", ignore_cache); + + sendMessage(message); +} + +void LLPluginClassMedia::browse_forward() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward"); + sendMessage(message); +} + +void LLPluginClassMedia::browse_back() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back"); + sendMessage(message); +} + +void LLPluginClassMedia::set_status_redirect(int code, const std::string &url) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_status_redirect"); + + message.setValueS32("code", code); + message.setValue("url", url); + + sendMessage(message); +} + +void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent"); + + message.setValue("user_agent", user_agent); + + sendMessage(message); +} + +void LLPluginClassMedia::crashPlugin() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash"); + + sendMessage(message); +} + +void LLPluginClassMedia::hangPlugin() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang"); + + sendMessage(message); +} + + +//////////////////////////////////////////////////////////// +// MARK: media_time class functions +bool LLPluginClassMedia::pluginSupportsMediaTime(void) +{ + std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME); + return !version.empty(); +} + +void LLPluginClassMedia::stop() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop"); + sendMessage(message); +} + +void LLPluginClassMedia::start(float rate) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start"); + + message.setValueReal("rate", rate); + + sendMessage(message); +} + +void LLPluginClassMedia::pause() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause"); + sendMessage(message); +} + +void LLPluginClassMedia::seek(float time) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek"); + + message.setValueReal("time", time); + + sendMessage(message); +} + +void LLPluginClassMedia::setLoop(bool loop) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop"); + + message.setValueBoolean("loop", loop); + + sendMessage(message); +} + +void LLPluginClassMedia::setVolume(float volume) +{ + if(volume != mRequestedVolume) + { + mRequestedVolume = volume; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume"); + + message.setValueReal("volume", volume); + + sendMessage(message); + } +} + +float LLPluginClassMedia::getVolume() +{ + return mRequestedVolume; +} + +void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history) +{ + // Send URL history to plugin + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history"); + message.setValueLLSD("history", url_history); + sendMessage(message); + + LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL; +} + diff --git a/linden/indra/llplugin/llpluginclassmedia.h b/linden/indra/llplugin/llpluginclassmedia.h new file mode 100644 index 0000000..c45010e --- /dev/null +++ b/linden/indra/llplugin/llpluginclassmedia.h @@ -0,0 +1,352 @@ +/** + * @file llpluginclassmedia.h + * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPLUGINCLASSMEDIA_H +#define LL_LLPLUGINCLASSMEDIA_H + +#include "llgltypes.h" +#include "llpluginprocessparent.h" +#include "llrect.h" +#include "llpluginclassmediaowner.h" +#include + + +class LLPluginClassMedia : public LLPluginProcessParentOwner +{ + LOG_CLASS(LLPluginClassMedia); +public: + LLPluginClassMedia(LLPluginClassMediaOwner *owner); + virtual ~LLPluginClassMedia(); + + // local initialization, called by the media manager when creating a source + virtual bool init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug, const std::string &user_data_path); + + // undoes everything init() didm called by the media manager when destroying a source + virtual void reset(); + + void idle(void); + + // All of these may return 0 or an actual valid value. + // Callers need to check the return for 0, and not use the values in that case. + int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; }; + int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; }; + int getNaturalWidth() const { return mNaturalMediaWidth; }; + int getNaturalHeight() const { return mNaturalMediaHeight; }; + int getSetWidth() const { return mSetMediaWidth; }; + int getSetHeight() const { return mSetMediaHeight; }; + int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; }; + int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; }; + int getTextureWidth() const; + int getTextureHeight() const; + int getFullWidth() const { return mFullMediaWidth; }; + int getFullHeight() const { return mFullMediaHeight; }; + + // This may return NULL. Callers need to check for and handle this case. + unsigned char* getBitsData(); + + // gets the format details of the texture data + // These may return 0 if they haven't been set up yet. The caller needs to detect this case. + int getTextureDepth() const { return mRequestedTextureDepth; }; + int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; }; + int getTextureFormatPrimary() const { return mRequestedTextureFormat; }; + int getTextureFormatType() const { return mRequestedTextureType; }; + bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; }; + bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; }; + + void setSize(int width, int height); + void setAutoScale(bool auto_scale); + + // Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent. + // This will initially be false, and will also be false for some time after setSize while the resize is processed. + // Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values + // until you call idle() again. + bool textureValid(void); + + bool getDirty(LLRect *dirty_rect = NULL); + void resetDirty(void); + + typedef enum + { + MOUSE_EVENT_DOWN, + MOUSE_EVENT_UP, + MOUSE_EVENT_MOVE, + MOUSE_EVENT_DOUBLE_CLICK + }EMouseEventType; + + void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers); + + typedef enum + { + KEY_EVENT_DOWN, + KEY_EVENT_UP, + KEY_EVENT_REPEAT + }EKeyEventType; + + bool keyEvent(EKeyEventType type, int key_code, MASK modifiers); + + void scrollEvent(int x, int y, MASK modifiers); + + // Text may be unicode (utf8 encoded) + bool textInput(const std::string &text, MASK modifiers); + + void loadURI(const std::string &uri); + + // "Loading" means uninitialized or any state prior to fully running (processing commands) + bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; }; + + // "Running" means the steady state -- i.e. processing messages + bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; }; + + // "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally) + bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; }; + + std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); }; + + bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; }; + void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); }; + + // Inherited from LLPluginProcessParentOwner + /* virtual */ void receivePluginMessage(const LLPluginMessage &message); + /* virtual */ void pluginLaunchFailed(); + /* virtual */ void pluginDied(); + + + typedef enum + { + PRIORITY_UNLOADED, // media plugin isn't even loaded. + PRIORITY_STOPPED, // media is not playing, shouldn't need to update at all. + PRIORITY_HIDDEN, // media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc. + PRIORITY_SLIDESHOW, // media is in the far distance, updates very infrequently + PRIORITY_LOW, // media is in the distance, may be rendered at reduced size + PRIORITY_NORMAL, // normal (default) priority + PRIORITY_HIGH // media has user focus and/or is taking up most of the screen + }EPriority; + + static const char* priorityToString(EPriority priority); + void setPriority(EPriority priority); + void setLowPrioritySizeLimit(int size); + + F64 getCPUUsage(); + + // Valid after a MEDIA_EVENT_CURSOR_CHANGED event + std::string getCursorName() const { return mCursorName; }; + + LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; } + + void cut(); + bool canCut() const { return mCanCut; }; + + void copy(); + bool canCopy() const { return mCanCopy; }; + + void paste(); + bool canPaste() const { return mCanPaste; }; + + /////////////////////////////////// + // media browser class functions + bool pluginSupportsMediaBrowser(void); + + void focus(bool focused); + void clear_cache(); + void clear_cookies(); + void enable_cookies(bool enable); + void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0); + void browse_stop(); + void browse_reload(bool ignore_cache = false); + void browse_forward(); + void browse_back(); + void set_status_redirect(int code, const std::string &url); + void setBrowserUserAgent(const std::string& user_agent); + + // This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE + std::string getNavigateURI() const { return mNavigateURI; }; + + // These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE + S32 getNavigateResultCode() const { return mNavigateResultCode; }; + std::string getNavigateResultString() const { return mNavigateResultString; }; + bool getHistoryBackAvailable() const { return mHistoryBackAvailable; }; + bool getHistoryForwardAvailable() const { return mHistoryForwardAvailable; }; + + // This is valid after MEDIA_EVENT_PROGRESS_UPDATED + int getProgressPercent() const { return mProgressPercent; }; + + // This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED + std::string getStatusText() const { return mStatusText; }; + + // This is valid after MEDIA_EVENT_LOCATION_CHANGED + std::string getLocation() const { return mLocation; }; + + // This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW + std::string getClickURL() const { return mClickURL; }; + + // This is valid after MEDIA_EVENT_CLICK_LINK_HREF + std::string getClickTarget() const { return mClickTarget; }; + + std::string getMediaName() const { return mMediaName; }; + std::string getMediaDescription() const { return mMediaDescription; }; + + // Crash the plugin. If you use this outside of a testbed, you will be punished. + void crashPlugin(); + + // Hang the plugin. If you use this outside of a testbed, you will be punished. + void hangPlugin(); + + /////////////////////////////////// + // media time class functions + bool pluginSupportsMediaTime(void); + void stop(); + void start(float rate = 0.0f); + void pause(); + void seek(float time); + void setLoop(bool loop); + void setVolume(float volume); + float getVolume(); + + F64 getCurrentTime(void) const { return mCurrentTime; }; + F64 getDuration(void) const { return mDuration; }; + F64 getCurrentPlayRate(void) { return mCurrentRate; }; + F64 getLoadedDuration(void) const { return mLoadedDuration; }; + + // Initialize the URL history of the plugin by sending + // "init_history" message + void initializeUrlHistory(const LLSD& url_history); + +protected: + + LLPluginClassMediaOwner *mOwner; + + // Notify this object's owner that an event has occurred. + void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event); + + void sendMessage(const LLPluginMessage &message); // Send message internally, either queueing or sending directly. + std::queue mSendQueue; // Used to queue messages while the plugin initializes. + + void setSizeInternal(void); + + bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true + S32 mRequestedTextureDepth; + LLGLenum mRequestedTextureInternalFormat; + LLGLenum mRequestedTextureFormat; + LLGLenum mRequestedTextureType; + bool mRequestedTextureSwapBytes; + bool mRequestedTextureCoordsOpenGL; + + std::string mTextureSharedMemoryName; + size_t mTextureSharedMemorySize; + + // True to scale requested media up to the full size of the texture (i.e. next power of two) + bool mAutoScaleMedia; + + // default media size for the plugin, from the texture_params message. + int mDefaultMediaWidth; + int mDefaultMediaHeight; + + // Size that has been requested by the plugin itself + int mNaturalMediaWidth; + int mNaturalMediaHeight; + + // Size that has been requested with setSize() + int mSetMediaWidth; + int mSetMediaHeight; + + // Full calculated media size (before auto-scale and downsample calculations) + int mFullMediaWidth; + int mFullMediaHeight; + + // Actual media size being set (after auto-scale) + int mRequestedMediaWidth; + int mRequestedMediaHeight; + + // Texture size calculated from actual media size + int mRequestedTextureWidth; + int mRequestedTextureHeight; + + // Size that the plugin has acknowledged + int mTextureWidth; + int mTextureHeight; + int mMediaWidth; + int mMediaHeight; + + float mRequestedVolume; + + // Priority of this media stream + EPriority mPriority; + int mLowPrioritySizeLimit; + + bool mAllowDownsample; + int mPadding; + + + LLPluginProcessParent *mPlugin; + + LLRect mDirtyRect; + + std::string translateModifiers(MASK modifiers); + + std::string mCursorName; + int mLastMouseX; + int mLastMouseY; + + LLPluginClassMediaOwner::EMediaStatus mStatus; + + F64 mSleepTime; + + bool mCanCut; + bool mCanCopy; + bool mCanPaste; + + std::string mMediaName; + std::string mMediaDescription; + + ///////////////////////////////////////// + // media_browser class + std::string mNavigateURI; + S32 mNavigateResultCode; + std::string mNavigateResultString; + bool mHistoryBackAvailable; + bool mHistoryForwardAvailable; + std::string mStatusText; + int mProgressPercent; + std::string mLocation; + std::string mClickURL; + std::string mClickTarget; + + ///////////////////////////////////////// + // media_time class + F64 mCurrentTime; + F64 mDuration; + F64 mCurrentRate; + F64 mLoadedDuration; + +}; + +#endif // LL_LLPLUGINCLASSMEDIA_H diff --git a/linden/indra/llplugin/llpluginclassmediaowner.h b/linden/indra/llplugin/llpluginclassmediaowner.h new file mode 100644 index 0000000..182eb92 --- /dev/null +++ b/linden/indra/llplugin/llpluginclassmediaowner.h @@ -0,0 +1,82 @@ +/** + * @file llpluginclassmediaowner.h + * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPLUGINCLASSMEDIAOWNER_H +#define LL_LLPLUGINCLASSMEDIAOWNER_H + +#include "llpluginprocessparent.h" +#include "llrect.h" +#include + +class LLPluginClassMedia; + +class LLPluginClassMediaOwner +{ +public: + typedef enum + { + MEDIA_EVENT_CONTENT_UPDATED, // contents/dirty rect have updated + MEDIA_EVENT_TIME_DURATION_UPDATED, // current time and/or duration have updated + MEDIA_EVENT_SIZE_CHANGED, // media size has changed + MEDIA_EVENT_CURSOR_CHANGED, // plugin has requested a cursor change + + MEDIA_EVENT_NAVIGATE_BEGIN, // browser has begun navigation + MEDIA_EVENT_NAVIGATE_COMPLETE, // browser has finished navigation + MEDIA_EVENT_PROGRESS_UPDATED, // browser has updated loading progress + MEDIA_EVENT_STATUS_TEXT_CHANGED, // browser has updated the status text + MEDIA_EVENT_NAME_CHANGED, // browser has updated the name of the media (typically tag) + MEDIA_EVENT_LOCATION_CHANGED, // browser location (URL) has changed (maybe due to internal navagation/frames/etc) + MEDIA_EVENT_CLICK_LINK_HREF, // I'm not entirely sure what the semantics of these two are + MEDIA_EVENT_CLICK_LINK_NOFOLLOW, + + MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch + MEDIA_EVENT_PLUGIN_FAILED // The plugin died unexpectedly + + } EMediaEvent; + + typedef enum + { + MEDIA_NONE, // Uninitialized -- no useful state + MEDIA_LOADING, // loading or navigating + MEDIA_LOADED, // navigation/preroll complete + MEDIA_ERROR, // navigation/preroll failed + MEDIA_PLAYING, // playing (only for time-based media) + MEDIA_PAUSED, // paused (only for time-based media) + MEDIA_DONE // finished playing (only for time-based media) + + } EMediaStatus; + + virtual ~LLPluginClassMediaOwner() {}; + virtual void handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent /*event*/) {}; +}; + +#endif // LL_LLPLUGINCLASSMEDIAOWNER_H diff --git a/linden/indra/llplugin/llplugininstance.cpp b/linden/indra/llplugin/llplugininstance.cpp new file mode 100644 index 0000000..5185b36 --- /dev/null +++ b/linden/indra/llplugin/llplugininstance.cpp @@ -0,0 +1,172 @@ +/** + * @file llplugininstance.cpp + * @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llplugininstance.h" + +#include "llapr.h" + +/** Virtual destructor. */ +LLPluginInstanceMessageListener::~LLPluginInstanceMessageListener() +{ +} + +/** + * TODO:DOC describe how it's used + */ +const char *LLPluginInstance::PLUGIN_INIT_FUNCTION_NAME = "LLPluginInitEntryPoint"; + +/** + * Constructor. + * + * @param[in] owner Plugin instance. TODO:DOC is this a good description of what "owner" is? + */ +LLPluginInstance::LLPluginInstance(LLPluginInstanceMessageListener *owner) : + mDSOHandle(NULL), + mPluginUserData(NULL), + mPluginSendMessageFunction(NULL) +{ + mOwner = owner; +} + +/** + * Destructor. + */ +LLPluginInstance::~LLPluginInstance() +{ + if(mDSOHandle != NULL) + { + apr_dso_unload(mDSOHandle); + mDSOHandle = NULL; + } +} + +/** + * Dynamically loads the plugin and runs the plugin's init function. + * + * @param[in] plugin_file Name of plugin dll/dylib/so. TODO:DOC is this correct? see .h + * @return 0 if successful, APR error code or error code from the plugin's init function on failure. + */ +int LLPluginInstance::load(std::string &plugin_file) +{ + pluginInitFunction init_function = NULL; + + int result = apr_dso_load(&mDSOHandle, + plugin_file.c_str(), + gAPRPoolp); + if(result != APR_SUCCESS) + { + char buf[1024]; + apr_dso_error(mDSOHandle, buf, sizeof(buf)); + + LL_WARNS("Plugin") << "apr_dso_load of " << plugin_file << " failed with error " << result << " , additional info string: " << buf << LL_ENDL; + + } + + if(result == APR_SUCCESS) + { + result = apr_dso_sym((apr_dso_handle_sym_t*)&init_function, + mDSOHandle, + PLUGIN_INIT_FUNCTION_NAME); + + if(result != APR_SUCCESS) + { + LL_WARNS("Plugin") << "apr_dso_sym failed with error " << result << LL_ENDL; + } + } + + if(result == APR_SUCCESS) + { + result = init_function(staticReceiveMessage, (void*)this, &mPluginSendMessageFunction, &mPluginUserData); + + if(result != APR_SUCCESS) + { + LL_WARNS("Plugin") << "call to init function failed with error " << result << LL_ENDL; + } + } + + return (int)result; +} + +/** + * Sends a message to the plugin. + * + * @param[in] message Message + */ +void LLPluginInstance::sendMessage(const std::string &message) +{ + if(mPluginSendMessageFunction) + { + LL_DEBUGS("Plugin") << "sending message to plugin: \"" << message << "\"" << LL_ENDL; + mPluginSendMessageFunction(message.c_str(), &mPluginUserData); + } + else + { + LL_WARNS("Plugin") << "dropping message: \"" << message << "\"" << LL_ENDL; + } +} + +/** + * Idle. TODO:DOC what's the purpose of this? + * + */ +void LLPluginInstance::idle(void) +{ +} + +// static +void LLPluginInstance::staticReceiveMessage(const char *message_string, void **user_data) +{ + // TODO: validate that the user_data argument is still a valid LLPluginInstance pointer + // we could also use a key that's looked up in a map (instead of a direct pointer) for safety, but that's probably overkill + LLPluginInstance *self = (LLPluginInstance*)*user_data; + self->receiveMessage(message_string); +} + +/** + * Plugin receives message from plugin loader shell. + * + * @param[in] message_string Message + */ +void LLPluginInstance::receiveMessage(const char *message_string) +{ + if(mOwner) + { + LL_DEBUGS("Plugin") << "processing incoming message: \"" << message_string << "\"" << LL_ENDL; + mOwner->receivePluginMessage(message_string); + } + else + { + LL_WARNS("Plugin") << "dropping incoming message: \"" << message_string << "\"" << LL_ENDL; + } +} diff --git a/linden/indra/llplugin/llplugininstance.h b/linden/indra/llplugin/llplugininstance.h new file mode 100644 index 0000000..0b53b5f --- /dev/null +++ b/linden/indra/llplugin/llplugininstance.h @@ -0,0 +1,104 @@ +/** + * @file llplugininstance.h + * @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPLUGININSTANCE_H +#define LL_LLPLUGININSTANCE_H + +#include "llstring.h" +#include "llapr.h" + +#include "apr_dso.h" + +/** + * @brief LLPluginInstanceMessageListener receives messages sent from the plugin loader shell to the plugin. + */ +class LLPluginInstanceMessageListener +{ +public: + virtual ~LLPluginInstanceMessageListener(); + /** Plugin receives message from plugin loader shell. */ + virtual void receivePluginMessage(const std::string &message) = 0; +}; + +/** + * @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing. + */ +class LLPluginInstance +{ + LOG_CLASS(LLPluginInstance); +public: + LLPluginInstance(LLPluginInstanceMessageListener *owner); + virtual ~LLPluginInstance(); + + // Load a plugin dll/dylib/so + // Returns 0 if successful, APR error code or error code returned from the plugin's init function on failure. + int load(std::string &plugin_file); + + // Sends a message to the plugin. + void sendMessage(const std::string &message); + + // TODO:DOC is this comment obsolete? can't find "send_count" anywhere in indra tree. + // send_count is the maximum number of message to process from the send queue. If negative, it will drain the queue completely. + // The receive queue is always drained completely. + // Returns the total number of messages processed from both queues. + void idle(void); + + /** The signature of the function for sending a message from plugin to plugin loader shell. + * + * @param[in] message_string Null-terminated C string + * @param[in] user_data The opaque reference that the callee supplied during setup. + */ + typedef void (*sendMessageFunction) (const char *message_string, void **user_data); + + /** The signature of the plugin init function. TODO:DOC check direction (pluging loader shell to plugin?) + * + * @param[in] host_user_data Data from plugin loader shell. + * @param[in] plugin_send_function Function for sending from the plugin loader shell to plugin. + */ + typedef int (*pluginInitFunction) (sendMessageFunction host_send_func, void *host_user_data, sendMessageFunction *plugin_send_func, void **plugin_user_data); + + /** Name of plugin init function */ + static const char *PLUGIN_INIT_FUNCTION_NAME; + +private: + static void staticReceiveMessage(const char *message_string, void **user_data); + void receiveMessage(const char *message_string); + + apr_dso_handle_t *mDSOHandle; + + void *mPluginUserData; + sendMessageFunction mPluginSendMessageFunction; + + LLPluginInstanceMessageListener *mOwner; +}; + +#endif // LL_LLPLUGININSTANCE_H diff --git a/linden/indra/llplugin/llpluginmessage.cpp b/linden/indra/llplugin/llpluginmessage.cpp new file mode 100644 index 0000000..67ac995 --- /dev/null +++ b/linden/indra/llplugin/llpluginmessage.cpp @@ -0,0 +1,442 @@ +/** + * @file llpluginmessage.cpp + * @brief LLPluginMessage encapsulates the serialization/deserialization of messages passed to and from plugins. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llpluginmessage.h" +#include "llsdserialize.h" +#include "u64.h" + +/** + * Constructor. + */ +LLPluginMessage::LLPluginMessage() +{ +} + +/** + * Constructor. + * + * @param[in] p Existing message + */ +LLPluginMessage::LLPluginMessage(const LLPluginMessage &p) +{ + mMessage = p.mMessage; +} + +/** + * Constructor. + * + * @param[in] message_class Message class + * @param[in] message_name Message name + */ +LLPluginMessage::LLPluginMessage(const std::string &message_class, const std::string &message_name) +{ + setMessage(message_class, message_name); +} + + +/** + * Destructor. + */ +LLPluginMessage::~LLPluginMessage() +{ +} + +/** + * Reset all internal state. + */ +void LLPluginMessage::clear() +{ + mMessage = LLSD::emptyMap(); + mMessage["params"] = LLSD::emptyMap(); +} + +/** + * Sets the message class and name. Also has the side-effect of clearing any key-value pairs in the message. + * + * @param[in] message_class Message class + * @param[in] message_name Message name + */ +void LLPluginMessage::setMessage(const std::string &message_class, const std::string &message_name) +{ + clear(); + mMessage["class"] = message_class; + mMessage["name"] = message_name; +} + +/** + * Sets a key/value pair in the message, where the value is a string. + * + * @param[in] key Key + * @param[in] value String value + */ +void LLPluginMessage::setValue(const std::string &key, const std::string &value) +{ + mMessage["params"][key] = value; +} + +/** + * Sets a key/value pair in the message, where the value is LLSD. + * + * @param[in] key Key + * @param[in] value LLSD value + */ +void LLPluginMessage::setValueLLSD(const std::string &key, const LLSD &value) +{ + mMessage["params"][key] = value; +} + +/** + * Sets a key/value pair in the message, where the value is signed 32-bit. + * + * @param[in] key Key + * @param[in] value 32-bit signed value + */ +void LLPluginMessage::setValueS32(const std::string &key, S32 value) +{ + mMessage["params"][key] = value; +} + +/** + * Sets a key/value pair in the message, where the value is unsigned 32-bit. The value is stored as a string beginning with "0x". + * + * @param[in] key Key + * @param[in] value 32-bit unsigned value + */ +void LLPluginMessage::setValueU32(const std::string &key, U32 value) +{ + std::stringstream temp; + temp << "0x" << std::hex << value; + setValue(key, temp.str()); +} + +/** + * Sets a key/value pair in the message, where the value is a bool. + * + * @param[in] key Key + * @param[in] value Boolean value + */ +void LLPluginMessage::setValueBoolean(const std::string &key, bool value) +{ + mMessage["params"][key] = value; +} + +/** + * Sets a key/value pair in the message, where the value is a double. + * + * @param[in] key Key + * @param[in] value Boolean value + */ +void LLPluginMessage::setValueReal(const std::string &key, F64 value) +{ + mMessage["params"][key] = value; +} + +/** + * Sets a key/value pair in the message, where the value is a pointer. The pointer is stored as a string. + * + * @param[in] key Key + * @param[in] value Pointer value + */ +void LLPluginMessage::setValuePointer(const std::string &key, void* value) +{ + std::stringstream temp; + // iostreams should output pointer values in hex with an initial 0x by default. + temp << value; + setValue(key, temp.str()); +} + +/** + * Gets the message class. + * + * @return Message class + */ +std::string LLPluginMessage::getClass(void) const +{ + return mMessage["class"]; +} + +/** + * Gets the message name. + * + * @return Message name + */ +std::string LLPluginMessage::getName(void) const +{ + return mMessage["name"]; +} + +/** + * Returns true if the specified key exists in this message (useful for optional parameters). + * + * @param[in] key Key + * + * @return True if key exists, false otherwise. + */ +bool LLPluginMessage::hasValue(const std::string &key) const +{ + bool result = false; + + if(mMessage["params"].has(key)) + { + result = true; + } + + return result; +} + +/** + * Gets the value of a key as a string. If the key does not exist, an empty string will be returned. + * + * @param[in] key Key + * + * @return String value of key if key exists, empty string if key does not exist. + */ +std::string LLPluginMessage::getValue(const std::string &key) const +{ + std::string result; + + if(mMessage["params"].has(key)) + { + result = mMessage["params"][key].asString(); + } + + return result; +} + +/** + * Gets the value of a key as LLSD. If the key does not exist, a null LLSD will be returned. + * + * @param[in] key Key + * + * @return LLSD value of key if key exists, null LLSD if key does not exist. + */ +LLSD LLPluginMessage::getValueLLSD(const std::string &key) const +{ + LLSD result; + + if(mMessage["params"].has(key)) + { + result = mMessage["params"][key]; + } + + return result; +} + +/** + * Gets the value of a key as signed 32-bit int. If the key does not exist, 0 will be returned. + * + * @param[in] key Key + * + * @return Signed 32-bit int value of key if key exists, 0 if key does not exist. + */ +S32 LLPluginMessage::getValueS32(const std::string &key) const +{ + S32 result = 0; + + if(mMessage["params"].has(key)) + { + result = mMessage["params"][key].asInteger(); + } + + return result; +} + +/** + * Gets the value of a key as unsigned 32-bit int. If the key does not exist, 0 will be returned. + * + * @param[in] key Key + * + * @return Unsigned 32-bit int value of key if key exists, 0 if key does not exist. + */ +U32 LLPluginMessage::getValueU32(const std::string &key) const +{ + U32 result = 0; + + if(mMessage["params"].has(key)) + { + std::string value = mMessage["params"][key].asString(); + + result = (U32)strtoul(value.c_str(), NULL, 16); + } + + return result; +} + +/** + * Gets the value of a key as a bool. If the key does not exist, false will be returned. + * + * @param[in] key Key + * + * @return Boolean value of key if it exists, false otherwise. + */ +bool LLPluginMessage::getValueBoolean(const std::string &key) const +{ + bool result = false; + + if(mMessage["params"].has(key)) + { + result = mMessage["params"][key].asBoolean(); + } + + return result; +} + +/** + * Gets the value of a key as a double. If the key does not exist, 0 will be returned. + * + * @param[in] key Key + * + * @return Value as a double if key exists, 0 otherwise. + */ +F64 LLPluginMessage::getValueReal(const std::string &key) const +{ + F64 result = 0.0f; + + if(mMessage["params"].has(key)) + { + result = mMessage["params"][key].asReal(); + } + + return result; +} + +/** + * Gets the value of a key as a pointer. If the key does not exist, NULL will be returned. + * + * @param[in] key Key + * + * @return Pointer value if key exists, NULL otherwise. + */ +void* LLPluginMessage::getValuePointer(const std::string &key) const +{ + void* result = NULL; + + if(mMessage["params"].has(key)) + { + std::string value = mMessage["params"][key].asString(); + + result = (void*)llstrtou64(value.c_str(), NULL, 16); + } + + return result; +} + +/** + * Flatten the message into a string. + * + * @return Message as a string. + */ +std::string LLPluginMessage::generate(void) const +{ + std::ostringstream result; + + // Pretty XML may be slightly easier to deal with while debugging... +// LLSDSerialize::toXML(mMessage, result); + LLSDSerialize::toPrettyXML(mMessage, result); + + return result.str(); +} + +/** + * Parse an incoming message into component parts. Clears all existing state before starting the parse. + * + * @return Returns -1 on failure, otherwise returns the number of key/value pairs in the incoming message. + */ +int LLPluginMessage::parse(const std::string &message) +{ + // clear any previous state + clear(); + + std::istringstream input(message); + + S32 parse_result = LLSDSerialize::fromXML(mMessage, input); + + return (int)parse_result; +} + + +/** + * Destructor + */ +LLPluginMessageListener::~LLPluginMessageListener() +{ + // TODO: should listeners have a way to ensure they're removed from dispatcher lists when deleted? +} + + +/** + * Destructor + */ +LLPluginMessageDispatcher::~LLPluginMessageDispatcher() +{ + +} + +/** + * Add a message listener. TODO:DOC need more info on what uses this. when are multiple listeners needed? + * + * @param[in] listener Message listener + */ +void LLPluginMessageDispatcher::addPluginMessageListener(LLPluginMessageListener *listener) +{ + mListeners.insert(listener); +} + +/** + * Remove a message listener. + * + * @param[in] listener Message listener + */ +void LLPluginMessageDispatcher::removePluginMessageListener(LLPluginMessageListener *listener) +{ + mListeners.erase(listener); +} + +/** + * Distribute a message to all message listeners. + * + * @param[in] message Message + */ +void LLPluginMessageDispatcher::dispatchPluginMessage(const LLPluginMessage &message) +{ + for (listener_set_t::iterator it = mListeners.begin(); + it != mListeners.end(); + ) + { + LLPluginMessageListener* listener = *it; + listener->receivePluginMessage(message); + // In case something deleted an entry. + it = mListeners.upper_bound(listener); + } +} diff --git a/linden/indra/llplugin/llpluginmessage.h b/linden/indra/llplugin/llpluginmessage.h new file mode 100644 index 0000000..8bcb896 --- /dev/null +++ b/linden/indra/llplugin/llpluginmessage.h @@ -0,0 +1,142 @@ +/** + * @file llpluginmessage.h + * @brief LLPluginMessage encapsulates the serialization/deserialization of messages passed to and from plugins. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPLUGINMESSAGE_H +#define LL_LLPLUGINMESSAGE_H + +#include "llsd.h" + +/** + * @brief LLPluginMessage encapsulates the serialization/deserialization of messages passed to and from plugins. + */ +class LLPluginMessage +{ + LOG_CLASS(LLPluginMessage); +public: + LLPluginMessage(); + LLPluginMessage(const LLPluginMessage &p); + LLPluginMessage(const std::string &message_class, const std::string &message_name); + ~LLPluginMessage(); + + // reset all internal state + void clear(void); + + // Sets the message class and name + // Also has the side-effect of clearing any key/value pairs in the message. + void setMessage(const std::string &message_class, const std::string &message_name); + + // Sets a key/value pair in the message + void setValue(const std::string &key, const std::string &value); + void setValueLLSD(const std::string &key, const LLSD &value); + void setValueS32(const std::string &key, S32 value); + void setValueU32(const std::string &key, U32 value); + void setValueBoolean(const std::string &key, bool value); + void setValueReal(const std::string &key, F64 value); + void setValuePointer(const std::string &key, void *value); + + std::string getClass(void) const; + std::string getName(void) const; + + // Returns true if the specified key exists in this message (useful for optional parameters) + bool hasValue(const std::string &key) const; + + // get the value of a particular key as a string. If the key doesn't exist in the message, an empty string will be returned. + std::string getValue(const std::string &key) const; + + // get the value of a particular key as LLSD. If the key doesn't exist in the message, a null LLSD will be returned. + LLSD getValueLLSD(const std::string &key) const; + + // get the value of a key as a S32. If the value wasn't set as a S32, behavior is undefined. + S32 getValueS32(const std::string &key) const; + + // get the value of a key as a U32. Since there isn't an LLSD type for this, we use a hexadecimal string instead. + U32 getValueU32(const std::string &key) const; + + // get the value of a key as a Boolean. + bool getValueBoolean(const std::string &key) const; + + // get the value of a key as a float. + F64 getValueReal(const std::string &key) const; + + // get the value of a key as a pointer. + void* getValuePointer(const std::string &key) const; + + // Flatten the message into a string + std::string generate(void) const; + + // Parse an incoming message into component parts + // (this clears out all existing state before starting the parse) + // Returns -1 on failure, otherwise returns the number of key/value pairs in the message. + int parse(const std::string &message); + + +private: + + LLSD mMessage; + +}; + +/** + * @brief Listener for plugin messages. + */ +class LLPluginMessageListener +{ +public: + virtual ~LLPluginMessageListener(); + /** Plugin receives message from plugin loader shell. */ + virtual void receivePluginMessage(const LLPluginMessage &message) = 0; + +}; + +/** + * @brief Dispatcher for plugin messages. + * + * Manages the set of plugin message listeners and distributes messages to plugin message listeners. + */ +class LLPluginMessageDispatcher +{ +public: + virtual ~LLPluginMessageDispatcher(); + + void addPluginMessageListener(LLPluginMessageListener *); + void removePluginMessageListener(LLPluginMessageListener *); +protected: + void dispatchPluginMessage(const LLPluginMessage &message); + + /** A set of message listeners. */ + typedef std::set<LLPluginMessageListener*> listener_set_t; + /** The set of message listeners. */ + listener_set_t mListeners; +}; + + +#endif // LL_LLPLUGINMESSAGE_H diff --git a/linden/indra/llplugin/llpluginmessageclasses.h b/linden/indra/llplugin/llpluginmessageclasses.h new file mode 100644 index 0000000..1f60d5e --- /dev/null +++ b/linden/indra/llplugin/llpluginmessageclasses.h @@ -0,0 +1,57 @@ +/** + * @file llpluginmessageclasses.h + * @brief This file defines the versions of existing message classes for LLPluginMessage. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPLUGINMESSAGECLASSES_H +#define LL_LLPLUGINMESSAGECLASSES_H + +// Version strings for each plugin message class. +// Backwards-compatible changes (i.e. changes which only add new messges) should increment the minor version (i.e. "1.0" -> "1.1"). +// Non-backwards-compatible changes (which delete messages or change their semantics) should increment the major version (i.e. "1.1" -> "2.0"). +// Plugins will supply the set of message classes they understand, with version numbers, as part of their init_response message. +// The contents and semantics of the base:init message must NEVER change in a non-backwards-compatible way, as a special case. + +#define LLPLUGIN_MESSAGE_CLASS_INTERNAL "internal" +#define LLPLUGIN_MESSAGE_CLASS_INTERNAL_VERSION "1.0" + +#define LLPLUGIN_MESSAGE_CLASS_BASE "base" +#define LLPLUGIN_MESSAGE_CLASS_BASE_VERSION "1.0" + +#define LLPLUGIN_MESSAGE_CLASS_MEDIA "media" +#define LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION "1.0" + +#define LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER "media_browser" +#define LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION "1.0" + +#define LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME "media_time" +#define LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION "1.0" + +#endif // LL_LLPLUGINMESSAGECLASSES_H diff --git a/linden/indra/llplugin/llpluginmessagepipe.cpp b/linden/indra/llplugin/llpluginmessagepipe.cpp new file mode 100644 index 0000000..209f49f --- /dev/null +++ b/linden/indra/llplugin/llpluginmessagepipe.cpp @@ -0,0 +1,316 @@ +/** + * @file llpluginmessagepipe.cpp + * @brief Classes that implement connections from the plugin system to pipes/pumps. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llpluginmessagepipe.h" +#include "llbufferstream.h" + +#include "llapr.h" + +static const char MESSAGE_DELIMITER = '\0'; + +LLPluginMessagePipeOwner::LLPluginMessagePipeOwner() : + mMessagePipe(NULL), + mSocketError(APR_SUCCESS) +{ +} + +// virtual +LLPluginMessagePipeOwner::~LLPluginMessagePipeOwner() +{ + killMessagePipe(); +} + +// virtual +apr_status_t LLPluginMessagePipeOwner::socketError(apr_status_t error) +{ + mSocketError = error; + return error; +}; + +//virtual +void LLPluginMessagePipeOwner::setMessagePipe(LLPluginMessagePipe *read_pipe) +{ + // Save a reference to this pipe + mMessagePipe = read_pipe; +} + +bool LLPluginMessagePipeOwner::canSendMessage(void) +{ + return (mMessagePipe != NULL); +} + +bool LLPluginMessagePipeOwner::writeMessageRaw(const std::string &message) +{ + bool result = true; + if(mMessagePipe != NULL) + { + result = mMessagePipe->addMessage(message); + } + else + { + LL_WARNS("Plugin") << "dropping message: " << message << LL_ENDL; + result = false; + } + + return result; +} + +void LLPluginMessagePipeOwner::killMessagePipe(void) +{ + if(mMessagePipe != NULL) + { + delete mMessagePipe; + mMessagePipe = NULL; + } +} + +LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket) +{ + mOwner = owner; + mOwner->setMessagePipe(this); + mSocket = socket; +} + +LLPluginMessagePipe::~LLPluginMessagePipe() +{ + if(mOwner != NULL) + { + mOwner->setMessagePipe(NULL); + } +} + +bool LLPluginMessagePipe::addMessage(const std::string &message) +{ + // queue the message for later output + mOutput += message; + mOutput += MESSAGE_DELIMITER; // message separator + + return true; +} + +void LLPluginMessagePipe::clearOwner(void) +{ + // The owner is done with this pipe. The next call to process_impl should send any remaining data and exit. + mOwner = NULL; +} + +void LLPluginMessagePipe::setSocketTimeout(apr_interval_time_t timeout_usec) +{ + // We never want to sleep forever, so force negative timeouts to become non-blocking. + + // according to this page: http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-13.html + // blocking/non-blocking with apr sockets is somewhat non-portable. + + if(timeout_usec <= 0) + { + // Make the socket non-blocking + apr_socket_opt_set(mSocket->getSocket(), APR_SO_NONBLOCK, 1); + apr_socket_timeout_set(mSocket->getSocket(), 0); + } + else + { + // Make the socket blocking-with-timeout + apr_socket_opt_set(mSocket->getSocket(), APR_SO_NONBLOCK, 1); + apr_socket_timeout_set(mSocket->getSocket(), timeout_usec); + } +} + +bool LLPluginMessagePipe::pump(F64 timeout) +{ + bool result = true; + + if(mSocket) + { + apr_status_t status; + apr_size_t size; + + if(!mOutput.empty()) + { + // write any outgoing messages + size = (apr_size_t)mOutput.size(); + + setSocketTimeout(0); + +// LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL; + + status = apr_socket_send( + mSocket->getSocket(), + (const char*)mOutput.data(), + &size); + +// LL_INFOS("Plugin") << "after apr_socket_send, size = " << size << LL_ENDL; + + if(status == APR_SUCCESS) + { + // success + mOutput = mOutput.substr(size); + } + else if(APR_STATUS_IS_EAGAIN(status)) + { + // Socket buffer is full... + // remove the written part from the buffer and try again later. + mOutput = mOutput.substr(size); + } + else + { + // some other error + // Treat this as fatal. + ll_apr_warn_status(status); + + if(mOwner) + { + mOwner->socketError(status); + } + result = false; + } + } + + // FIXME: For some reason, the apr timeout stuff isn't working properly on windows. + // Until such time as we figure out why, don't try to use the socket timeout -- just sleep here instead. +#if LL_WINDOWS + if(result) + { + if(timeout != 0.0f) + { + ms_sleep((int)(timeout * 1000.0f)); + timeout = 0.0f; + } + } +#endif + + // Check for incoming messages + if(result) + { + char input_buf[1024]; + apr_size_t request_size; + + // Start out by reading one byte, so that any data received will wake us up. + request_size = 1; + + // and use the timeout so we'll sleep if no data is available. + setSocketTimeout((apr_interval_time_t)(timeout * 1000000)); + + while(1) + { + size = request_size; + +// LL_INFOS("Plugin") << "before apr_socket_recv, size = " << size << LL_ENDL; + + status = apr_socket_recv( + mSocket->getSocket(), + input_buf, + &size); + +// LL_INFOS("Plugin") << "after apr_socket_recv, size = " << size << LL_ENDL; + + if(size > 0) + mInput.append(input_buf, size); + + if(status == APR_SUCCESS) + { +// llinfos << "success, read " << size << llendl; + + if(size != request_size) + { + // This was a short read, so we're done. + break; + } + } + else if(APR_STATUS_IS_TIMEUP(status)) + { +// llinfos << "TIMEUP, read " << size << llendl; + + // Timeout was hit. Since the initial read is 1 byte, this should never be a partial read. + break; + } + else if(APR_STATUS_IS_EAGAIN(status)) + { +// llinfos << "EAGAIN, read " << size << llendl; + + // We've been doing partial reads, and we're done now. + break; + } + else + { + // some other error + // Treat this as fatal. + ll_apr_warn_status(status); + + if(mOwner) + { + mOwner->socketError(status); + } + result = false; + break; + } + + // Second and subsequent reads should not use the timeout + setSocketTimeout(0); + // and should try to fill the input buffer + request_size = sizeof(input_buf); + } + + processInput(); + } + } + + if(!result) + { + // If we got an error, we're done. + LL_INFOS("Plugin") << "Error from socket, cleaning up." << LL_ENDL; + delete this; + } + + return result; +} + +void LLPluginMessagePipe::processInput(void) +{ + // Look for input delimiter(s) in the input buffer. + int start = 0; + int delim; + while((delim = mInput.find(MESSAGE_DELIMITER, start)) != std::string::npos) + { + // Let the owner process this message + mOwner->receiveMessageRaw(mInput.substr(start, delim - start)); + + start = delim + 1; + } + + // Remove delivered messages from the input buffer. + if(start != 0) + mInput = mInput.substr(start); + +} + diff --git a/linden/indra/llplugin/llpluginmessagepipe.h b/linden/indra/llplugin/llpluginmessagepipe.h new file mode 100644 index 0000000..9bf1781 --- /dev/null +++ b/linden/indra/llplugin/llpluginmessagepipe.h @@ -0,0 +1,92 @@ +/** + * @file llpluginmessagepipe.h + * @brief Classes that implement connections from the plugin system to pipes/pumps. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPLUGINMESSAGEPIPE_H +#define LL_LLPLUGINMESSAGEPIPE_H + +#include "lliosocket.h" + +class LLPluginMessagePipe; + +// Inherit from this to be able to receive messages from the LLPluginMessagePipe +class LLPluginMessagePipeOwner +{ + LOG_CLASS(LLPluginMessagePipeOwner); +public: + LLPluginMessagePipeOwner(); + virtual ~LLPluginMessagePipeOwner(); + // called with incoming messages + virtual void receiveMessageRaw(const std::string &message) = 0; + // called when the socket has an error + virtual apr_status_t socketError(apr_status_t error); + + // called from LLPluginMessagePipe to manage the connection with LLPluginMessagePipeOwner -- do not use! + virtual void setMessagePipe(LLPluginMessagePipe *message_pipe) ; + +protected: + // returns false if writeMessageRaw() would drop the message + bool canSendMessage(void); + // call this to send a message over the pipe + bool writeMessageRaw(const std::string &message); + // call this to close the pipe + void killMessagePipe(void); + + LLPluginMessagePipe *mMessagePipe; + apr_status_t mSocketError; +}; + +class LLPluginMessagePipe +{ + LOG_CLASS(LLPluginMessagePipe); +public: + LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket); + virtual ~LLPluginMessagePipe(); + + bool addMessage(const std::string &message); + void clearOwner(void); + + bool pump(F64 timeout = 0.0f); + +protected: + void processInput(void); + + // used internally by pump() + void setSocketTimeout(apr_interval_time_t timeout_usec); + + std::string mInput; + std::string mOutput; + + LLPluginMessagePipeOwner *mOwner; + LLSocket::ptr_t mSocket; +}; + +#endif // LL_LLPLUGINMESSAGE_H diff --git a/linden/indra/llplugin/llpluginprocesschild.cpp b/linden/indra/llplugin/llpluginprocesschild.cpp new file mode 100644 index 0000000..9b5eafc --- /dev/null +++ b/linden/indra/llplugin/llpluginprocesschild.cpp @@ -0,0 +1,490 @@ +/** + * @file llpluginprocesschild.cpp + * @brief LLPluginProcessChild handles the child side of the external-process plugin API. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llpluginprocesschild.h" +#include "llplugininstance.h" +#include "llpluginmessagepipe.h" +#include "llpluginmessageclasses.h" + +static const F32 HEARTBEAT_SECONDS = 1.0f; +static const F32 PLUGIN_IDLE_SECONDS = 1.0f / 100.0f; // Each call to idle will give the plugin this much time. + +LLPluginProcessChild::LLPluginProcessChild() +{ + mInstance = NULL; + mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); + mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz + mCPUElapsed = 0.0f; +} + +LLPluginProcessChild::~LLPluginProcessChild() +{ + if(mInstance != NULL) + { + sendMessageToPlugin(LLPluginMessage("base", "cleanup")); + delete mInstance; + mInstance = NULL; + } +} + +void LLPluginProcessChild::killSockets(void) +{ + killMessagePipe(); + mSocket.reset(); +} + +void LLPluginProcessChild::init(U32 launcher_port) +{ + mLauncherHost = LLHost("127.0.0.1", launcher_port); + setState(STATE_INITIALIZED); +} + +void LLPluginProcessChild::idle(void) +{ + bool idle_again; + do + { + if(mSocketError != APR_SUCCESS) + { + LL_INFOS("Plugin") << "message pipe is in error state, moving to STATE_ERROR"<< LL_ENDL; + setState(STATE_ERROR); + } + + if((mState > STATE_INITIALIZED) && (mMessagePipe == NULL)) + { + // The pipe has been closed -- we're done. + // TODO: This could be slightly more subtle, but I'm not sure it needs to be. + LL_INFOS("Plugin") << "message pipe went away, moving to STATE_ERROR"<< LL_ENDL; + setState(STATE_ERROR); + } + + // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState(). + // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return. + // When in doubt, don't do it. + idle_again = false; + + if(mInstance != NULL) + { + // Provide some time to the plugin + mInstance->idle(); + } + + switch(mState) + { + case STATE_UNINITIALIZED: + break; + + case STATE_INITIALIZED: + if(mSocket->blockingConnect(mLauncherHost)) + { + // This automatically sets mMessagePipe + new LLPluginMessagePipe(this, mSocket); + + setState(STATE_CONNECTED); + } + else + { + // connect failed + setState(STATE_ERROR); + } + break; + + case STATE_CONNECTED: + sendMessageToParent(LLPluginMessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hello")); + setState(STATE_PLUGIN_LOADING); + break; + + case STATE_PLUGIN_LOADING: + if(!mPluginFile.empty()) + { + mInstance = new LLPluginInstance(this); + if(mInstance->load(mPluginFile) == 0) + { + mHeartbeat.start(); + mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS); + mCPUElapsed = 0.0f; + setState(STATE_PLUGIN_LOADED); + } + else + { + setState(STATE_ERROR); + } + } + break; + + case STATE_PLUGIN_LOADED: + { + setState(STATE_PLUGIN_INITIALIZING); + LLPluginMessage message("base", "init"); + message.setValue("user_data_path", mUserDataPath); + sendMessageToPlugin(message); + } + break; + + case STATE_PLUGIN_INITIALIZING: + // waiting for init_response... + break; + + case STATE_RUNNING: + if(mInstance != NULL) + { + // Provide some time to the plugin + LLPluginMessage message("base", "idle"); + message.setValueReal("time", PLUGIN_IDLE_SECONDS); + sendMessageToPlugin(message); + + mInstance->idle(); + + if(mHeartbeat.hasExpired()) + { + + // This just proves that we're not stuck down inside the plugin code. + LLPluginMessage heartbeat(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "heartbeat"); + + // Calculate the approximage CPU usage fraction (floating point value between 0 and 1) used by the plugin this heartbeat cycle. + // Note that this will not take into account any threads or additional processes the plugin spawns, but it's a first approximation. + // If we could write OS-specific functions to query the actual CPU usage of this process, that would be a better approximation. + heartbeat.setValueReal("cpu_usage", mCPUElapsed / mHeartbeat.getElapsedTimeF64()); + + sendMessageToParent(heartbeat); + + mHeartbeat.reset(); + mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS); + mCPUElapsed = 0.0f; + } + } + // receivePluginMessage will transition to STATE_UNLOADING + break; + + case STATE_UNLOADING: + if(mInstance != NULL) + { + sendMessageToPlugin(LLPluginMessage("base", "cleanup")); + delete mInstance; + mInstance = NULL; + } + setState(STATE_UNLOADED); + break; + + case STATE_UNLOADED: + killSockets(); + setState(STATE_DONE); + break; + + case STATE_ERROR: + // Close the socket to the launcher + killSockets(); + // TODO: Where do we go from here? Just exit()? + setState(STATE_DONE); + break; + + case STATE_DONE: + // just sit here. + break; + } + + } while (idle_again); +} + +void LLPluginProcessChild::sleep(F64 seconds) +{ + if(mMessagePipe) + { + mMessagePipe->pump(seconds); + } + else + { + ms_sleep((int)(seconds * 1000.0f)); + } +} + +void LLPluginProcessChild::pump(void) +{ + if(mMessagePipe) + { + mMessagePipe->pump(0.0f); + } + else + { + // Should we warn here? + } +} + + +bool LLPluginProcessChild::isRunning(void) +{ + bool result = false; + + if(mState == STATE_RUNNING) + result = true; + + return result; +} + +bool LLPluginProcessChild::isDone(void) +{ + bool result = false; + + switch(mState) + { + case STATE_DONE: + result = true; + break; + default: + break; + } + + return result; +} + +void LLPluginProcessChild::sendMessageToPlugin(const LLPluginMessage &message) +{ + std::string buffer = message.generate(); + + LL_DEBUGS("Plugin") << "Sending to plugin: " << buffer << LL_ENDL; + LLTimer elapsed; + + mInstance->sendMessage(buffer); + + mCPUElapsed += elapsed.getElapsedTimeF64(); +} + +void LLPluginProcessChild::sendMessageToParent(const LLPluginMessage &message) +{ + std::string buffer = message.generate(); + + LL_DEBUGS("Plugin") << "Sending to parent: " << buffer << LL_ENDL; + + writeMessageRaw(buffer); +} + +void LLPluginProcessChild::receiveMessageRaw(const std::string &message) +{ + // Incoming message from the TCP Socket + + LL_DEBUGS("Plugin") << "Received from parent: " << message << LL_ENDL; + + bool passMessage = true; + + // FIXME: how should we handle queueing here? + + { + // Decode this message + LLPluginMessage parsed; + parsed.parse(message); + + std::string message_class = parsed.getClass(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) + { + passMessage = false; + + std::string message_name = parsed.getName(); + if(message_name == "load_plugin") + { + mPluginFile = parsed.getValue("file"); + mUserDataPath = parsed.getValue("user_data_path"); + } + else if(message_name == "shm_add") + { + std::string name = parsed.getValue("name"); + size_t size = (size_t)parsed.getValueS32("size"); + + sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); + if(iter != mSharedMemoryRegions.end()) + { + // Need to remove the old region first + LL_WARNS("Plugin") << "Adding a duplicate shared memory segment!" << LL_ENDL; + } + else + { + // This is a new region + LLPluginSharedMemory *region = new LLPluginSharedMemory; + if(region->attach(name, size)) + { + mSharedMemoryRegions.insert(sharedMemoryRegionsType::value_type(name, region)); + + std::stringstream addr; + addr << region->getMappedAddress(); + + // Send the add notification to the plugin + LLPluginMessage message("base", "shm_added"); + message.setValue("name", name); + message.setValueS32("size", (S32)size); + message.setValuePointer("address", region->getMappedAddress()); + sendMessageToPlugin(message); + + // and send the response to the parent + message.setMessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_add_response"); + message.setValue("name", name); + sendMessageToParent(message); + } + else + { + LL_WARNS("Plugin") << "Couldn't create a shared memory segment!" << LL_ENDL; + } + } + + } + else if(message_name == "shm_remove") + { + std::string name = parsed.getValue("name"); + sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); + if(iter != mSharedMemoryRegions.end()) + { + // forward the remove request to the plugin -- its response will trigger us to detach the segment. + LLPluginMessage message("base", "shm_remove"); + message.setValue("name", name); + sendMessageToPlugin(message); + } + else + { + LL_WARNS("Plugin") << "shm_remove for unknown memory segment!" << LL_ENDL; + } + } + else if(message_name == "sleep_time") + { + mSleepTime = parsed.getValueReal("time"); + } + else if(message_name == "crash") + { + // Crash the plugin + LL_ERRS("Plugin") << "Plugin crash requested." << LL_ENDL; + } + else if(message_name == "hang") + { + // Hang the plugin + LL_WARNS("Plugin") << "Plugin hang requested." << LL_ENDL; + while(1) + { + // wheeeeeeeee...... + } + } + else + { + LL_WARNS("Plugin") << "Unknown internal message from parent: " << message_name << LL_ENDL; + } + } + } + + if(passMessage && mInstance != NULL) + { + LLTimer elapsed; + + mInstance->sendMessage(message); + + mCPUElapsed += elapsed.getElapsedTimeF64(); + } +} + +/* virtual */ +void LLPluginProcessChild::receivePluginMessage(const std::string &message) +{ + LL_DEBUGS("Plugin") << "Received from plugin: " << message << LL_ENDL; + + // Incoming message from the plugin instance + bool passMessage = true; + + // FIXME: how should we handle queueing here? + + // Intercept certain base messages (responses to ones sent by this class) + { + // Decode this message + LLPluginMessage parsed; + parsed.parse(message); + std::string message_class = parsed.getClass(); + if(message_class == "base") + { + std::string message_name = parsed.getName(); + if(message_name == "init_response") + { + // The plugin has finished initializing. + setState(STATE_RUNNING); + + // Don't pass this message up to the parent + passMessage = false; + + LLPluginMessage new_message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin_response"); + LLSD versions = parsed.getValueLLSD("versions"); + new_message.setValueLLSD("versions", versions); + + if(parsed.hasValue("plugin_version")) + { + std::string plugin_version = parsed.getValue("plugin_version"); + new_message.setValueLLSD("plugin_version", plugin_version); + } + + // Let the parent know it's loaded and initialized. + sendMessageToParent(new_message); + } + else if(message_name == "shm_remove_response") + { + // Don't pass this message up to the parent + passMessage = false; + + std::string name = parsed.getValue("name"); + sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); + if(iter != mSharedMemoryRegions.end()) + { + // detach the shared memory region + iter->second->detach(); + + // and remove it from our map + mSharedMemoryRegions.erase(iter); + + // Finally, send the response to the parent. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove_response"); + message.setValue("name", name); + sendMessageToParent(message); + } + else + { + LL_WARNS("Plugin") << "shm_remove_response for unknown memory segment!" << LL_ENDL; + } + } + } + } + + if(passMessage) + { + LL_DEBUGS("Plugin") << "Passing through to parent: " << message << LL_ENDL; + writeMessageRaw(message); + } +} + + +void LLPluginProcessChild::setState(EState state) +{ + LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL; + mState = state; +}; diff --git a/linden/indra/llplugin/llpluginprocesschild.h b/linden/indra/llplugin/llpluginprocesschild.h new file mode 100644 index 0000000..16a1ae8 --- /dev/null +++ b/linden/indra/llplugin/llpluginprocesschild.h @@ -0,0 +1,112 @@ +/** + * @file llpluginprocesschild.h + * @brief LLPluginProcessChild handles the child side of the external-process plugin API. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPLUGINPROCESSCHILD_H +#define LL_LLPLUGINPROCESSCHILD_H + +#include "llpluginmessage.h" +#include "llpluginmessagepipe.h" +#include "llplugininstance.h" +#include "llhost.h" +#include "llpluginsharedmemory.h" + +class LLPluginInstance; + +class LLPluginProcessChild: public LLPluginMessagePipeOwner, public LLPluginInstanceMessageListener +{ + LOG_CLASS(LLPluginProcessChild); +public: + LLPluginProcessChild(); + ~LLPluginProcessChild(); + + void init(U32 launcher_port); + void idle(void); + void sleep(F64 seconds); + void pump(); + + // returns true if the plugin is in the steady state (processing messages) + bool isRunning(void); + + // returns true if the plugin is unloaded or we're in an unrecoverable error state. + bool isDone(void); + + void killSockets(void); + + F64 getSleepTime(void) const { return mSleepTime; }; + + void sendMessageToPlugin(const LLPluginMessage &message); + void sendMessageToParent(const LLPluginMessage &message); + + // Inherited from LLPluginMessagePipeOwner + /* virtual */ void receiveMessageRaw(const std::string &message); + + // Inherited from LLPluginInstanceMessageListener + /* virtual */ void receivePluginMessage(const std::string &message); + +private: + + enum EState + { + STATE_UNINITIALIZED, + STATE_INITIALIZED, // init() has been called + STATE_CONNECTED, // connected back to launcher + STATE_PLUGIN_LOADING, // plugin library needs to be loaded + STATE_PLUGIN_LOADED, // plugin library has been loaded + STATE_PLUGIN_INITIALIZING, // plugin is processing init message + STATE_RUNNING, // steady state (processing messages) + STATE_UNLOADING, // plugin has sent shutdown_response and needs to be unloaded + STATE_UNLOADED, // plugin has been unloaded + STATE_ERROR, // generic bailout state + STATE_DONE // state machine will sit in this state after either error or normal termination. + }; + EState mState; + void setState(EState state); + + LLHost mLauncherHost; + LLSocket::ptr_t mSocket; + + std::string mPluginFile; + + std::string mUserDataPath; + + LLPluginInstance *mInstance; + + typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType; + sharedMemoryRegionsType mSharedMemoryRegions; + + LLTimer mHeartbeat; + F64 mSleepTime; + F64 mCPUElapsed; + +}; + +#endif // LL_LLPLUGINPROCESSCHILD_H diff --git a/linden/indra/llplugin/llpluginprocessparent.cpp b/linden/indra/llplugin/llpluginprocessparent.cpp new file mode 100644 index 0000000..bd36d11 --- /dev/null +++ b/linden/indra/llplugin/llpluginprocessparent.cpp @@ -0,0 +1,714 @@ +/** + * @file llpluginprocessparent.cpp + * @brief LLPluginProcessParent handles the parent side of the external-process plugin API. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llpluginprocessparent.h" +#include "llpluginmessagepipe.h" +#include "llpluginmessageclasses.h" + +#include "llapr.h" + +//virtual +LLPluginProcessParentOwner::~LLPluginProcessParentOwner() +{ + +} + +LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner) +{ + mOwner = owner; + mBoundPort = 0; + mState = STATE_UNINITIALIZED; + mDisableTimeout = false; + mDebug = false; + + mPluginLaunchTimeout = 60.0f; + mPluginLockupTimeout = 30.0f; + + // Don't start the timer here -- start it when we actually launch the plugin process. + mHeartbeat.stop(); +} + +LLPluginProcessParent::~LLPluginProcessParent() +{ + LL_DEBUGS("Plugin") << "destructor" << LL_ENDL; + + // Destroy any remaining shared memory regions + sharedMemoryRegionsType::iterator iter; + while((iter = mSharedMemoryRegions.begin()) != mSharedMemoryRegions.end()) + { + // destroy the shared memory region + iter->second->destroy(); + + // and remove it from our map + mSharedMemoryRegions.erase(iter); + } + + // orphaning the process means it won't be killed when the LLProcessLauncher is destructed. + // This is what we want -- it should exit cleanly once it notices the sockets have been closed. + mProcess.orphan(); + killSockets(); +} + +void LLPluginProcessParent::killSockets(void) +{ + killMessagePipe(); + mListenSocket.reset(); + mSocket.reset(); +} + +void LLPluginProcessParent::errorState(void) +{ + if(mState < STATE_RUNNING) + setState(STATE_LAUNCH_FAILURE); + else + setState(STATE_ERROR); +} + +void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug, const std::string &user_data_path) +{ + mProcess.setExecutable(launcher_filename); + mPluginFile = plugin_filename; + mCPUUsage = 0.0f; + mDebug = debug; + mUserDataPath = user_data_path; + + setState(STATE_INITIALIZED); +} + +bool LLPluginProcessParent::accept() +{ + bool result = false; + + apr_status_t status = APR_EGENERAL; + apr_socket_t *new_socket = NULL; + + status = apr_socket_accept( + &new_socket, + mListenSocket->getSocket(), + gAPRPoolp); + + + if(status == APR_SUCCESS) + { +// llinfos << "SUCCESS" << llendl; + // Success. Create a message pipe on the new socket + + // we MUST create a new pool for the LLSocket, since it will take ownership of it and delete it in its destructor! + apr_pool_t* new_pool = NULL; + status = apr_pool_create(&new_pool, gAPRPoolp); + + mSocket = LLSocket::create(new_socket, new_pool); + new LLPluginMessagePipe(this, mSocket); + + result = true; + } + else if(APR_STATUS_IS_EAGAIN(status)) + { +// llinfos << "EAGAIN" << llendl; + + // No incoming connections. This is not an error. + status = APR_SUCCESS; + } + else + { +// llinfos << "Error:" << llendl; + ll_apr_warn_status(status); + + // Some other error. + errorState(); + } + + return result; +} + +void LLPluginProcessParent::idle(void) +{ + bool idle_again; + + do + { + // Give time to network processing + if(mMessagePipe) + { + if(!mMessagePipe->pump()) + { +// LL_WARNS("Plugin") << "Message pipe hit an error state" << LL_ENDL; + errorState(); + } + } + + if((mSocketError != APR_SUCCESS) && (mState <= STATE_RUNNING)) + { + // The socket is in an error state -- the plugin is gone. + LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL; + errorState(); + } + + // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState(). + // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return. + // When in doubt, don't do it. + idle_again = false; + switch(mState) + { + case STATE_UNINITIALIZED: + break; + + case STATE_INITIALIZED: + { + + apr_status_t status = APR_SUCCESS; + apr_sockaddr_t* addr = NULL; + mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); + mBoundPort = 0; + + // This code is based on parts of LLSocket::create() in lliosocket.cpp. + + status = apr_sockaddr_info_get( + &addr, + "127.0.0.1", + APR_INET, + 0, // port 0 = ephemeral ("find me a port") + 0, + gAPRPoolp); + + if(ll_apr_warn_status(status)) + { + killSockets(); + errorState(); + break; + } + + // This allows us to reuse the address on quick down/up. This is unlikely to create problems. + ll_apr_warn_status(apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_REUSEADDR, 1)); + + status = apr_socket_bind(mListenSocket->getSocket(), addr); + if(ll_apr_warn_status(status)) + { + killSockets(); + errorState(); + break; + } + + // Get the actual port the socket was bound to + { + apr_sockaddr_t* bound_addr = NULL; + if(ll_apr_warn_status(apr_socket_addr_get(&bound_addr, APR_LOCAL, mListenSocket->getSocket()))) + { + killSockets(); + errorState(); + break; + } + mBoundPort = bound_addr->port; + + if(mBoundPort == 0) + { + LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL; + + killSockets(); + errorState(); + break; + } + } + + LL_DEBUGS("Plugin") << "Bound tcp socket to port: " << addr->port << LL_ENDL; + + // Make the listen socket non-blocking + status = apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_NONBLOCK, 1); + if(ll_apr_warn_status(status)) + { + killSockets(); + errorState(); + break; + } + + apr_socket_timeout_set(mListenSocket->getSocket(), 0); + if(ll_apr_warn_status(status)) + { + killSockets(); + errorState(); + break; + } + + // If it's a stream based socket, we need to tell the OS + // to keep a queue of incoming connections for ACCEPT. + status = apr_socket_listen( + mListenSocket->getSocket(), + 10); // FIXME: Magic number for queue size + + if(ll_apr_warn_status(status)) + { + killSockets(); + errorState(); + break; + } + + // If we got here, we're listening. + setState(STATE_LISTENING); + } + break; + + case STATE_LISTENING: + { + // Launch the plugin process. + + // Only argument to the launcher is the port number we're listening on + std::stringstream stream; + stream << mBoundPort; + mProcess.addArgument(stream.str()); + if(mProcess.launch() != 0) + { + errorState(); + } + else + { + if(mDebug) + { + #if LL_DARWIN + // If we're set to debug, start up a gdb instance in a new terminal window and have it attach to the plugin process and continue. + + // The command we're constructing would look like this on the command line: + // osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell' + + std::stringstream cmd; + + mDebugger.setExecutable("/usr/bin/osascript"); + mDebugger.addArgument("-e"); + mDebugger.addArgument("tell application \"Terminal\""); + mDebugger.addArgument("-e"); + cmd << "set win to do script \"gdb -pid " << mProcess.getProcessID() << "\""; + mDebugger.addArgument(cmd.str()); + mDebugger.addArgument("-e"); + mDebugger.addArgument("do script \"continue\" in win"); + mDebugger.addArgument("-e"); + mDebugger.addArgument("end tell"); + mDebugger.launch(); + + #endif + } + + // This will allow us to time out if the process never starts. + mHeartbeat.start(); + mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout); + setState(STATE_LAUNCHED); + } + } + break; + + case STATE_LAUNCHED: + // waiting for the plugin to connect + if(pluginLockedUpOrQuit()) + { + errorState(); + } + else + { + // Check for the incoming connection. + if(accept()) + { + // Stop listening on the server port + mListenSocket.reset(); + setState(STATE_CONNECTED); + } + } + break; + + case STATE_CONNECTED: + // waiting for hello message from the plugin + + if(pluginLockedUpOrQuit()) + { + errorState(); + } + break; + + case STATE_HELLO: + LL_DEBUGS("Plugin") << "received hello message" << llendl; + + // Send the message to load the plugin + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin"); + message.setValue("file", mPluginFile); + message.setValue("user_data_path", mUserDataPath); + sendMessage(message); + } + + setState(STATE_LOADING); + break; + + case STATE_LOADING: + // The load_plugin_response message will kick us from here into STATE_RUNNING + if(pluginLockedUpOrQuit()) + { + errorState(); + } + break; + + case STATE_RUNNING: + if(pluginLockedUpOrQuit()) + { + errorState(); + } + break; + + case STATE_EXITING: + if(!mProcess.isRunning()) + { + setState(STATE_CLEANUP); + } + else if(pluginLockedUp()) + { + LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << llendl; + errorState(); + } + break; + + case STATE_LAUNCH_FAILURE: + if(mOwner != NULL) + { + mOwner->pluginLaunchFailed(); + } + setState(STATE_CLEANUP); + break; + + case STATE_ERROR: + if(mOwner != NULL) + { + mOwner->pluginDied(); + } + setState(STATE_CLEANUP); + break; + + case STATE_CLEANUP: + // Don't do a kill here anymore -- closing the sockets is the new 'kill'. + mProcess.orphan(); + killSockets(); + setState(STATE_DONE); + break; + + + case STATE_DONE: + // just sit here. + break; + + } + + } while (idle_again); +} + +bool LLPluginProcessParent::isLoading(void) +{ + bool result = false; + + if(mState <= STATE_LOADING) + result = true; + + return result; +} + +bool LLPluginProcessParent::isRunning(void) +{ + bool result = false; + + if(mState == STATE_RUNNING) + result = true; + + return result; +} + +bool LLPluginProcessParent::isDone(void) +{ + bool result = false; + + if(mState == STATE_DONE) + result = true; + + return result; +} + +void LLPluginProcessParent::setSleepTime(F64 sleep_time, bool force_send) +{ + if(force_send || (sleep_time != mSleepTime)) + { + // Cache the time locally + mSleepTime = sleep_time; + + if(canSendMessage()) + { + // and send to the plugin. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "sleep_time"); + message.setValueReal("time", mSleepTime); + sendMessage(message); + } + else + { + // Too early to send -- the load_plugin_response message will trigger us to send mSleepTime later. + } + } +} + +void LLPluginProcessParent::sendMessage(const LLPluginMessage &message) +{ + + std::string buffer = message.generate(); + LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL; + writeMessageRaw(buffer); +} + + +void LLPluginProcessParent::receiveMessageRaw(const std::string &message) +{ + LL_DEBUGS("Plugin") << "Received: " << message << LL_ENDL; + + // FIXME: should this go into a queue instead? + + LLPluginMessage parsed; + if(parsed.parse(message) != -1) + { + receiveMessage(parsed); + } +} + +void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message) +{ + std::string message_class = message.getClass(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) + { + // internal messages should be handled here + std::string message_name = message.getName(); + if(message_name == "hello") + { + if(mState == STATE_CONNECTED) + { + // Plugin host has launched. Tell it which plugin to load. + setState(STATE_HELLO); + } + else + { + LL_WARNS("Plugin") << "received hello message in wrong state -- bailing out" << LL_ENDL; + errorState(); + } + + } + else if(message_name == "load_plugin_response") + { + if(mState == STATE_LOADING) + { + // Plugin has been loaded. + + mPluginVersionString = message.getValue("plugin_version"); + LL_INFOS("Plugin") << "plugin version string: " << mPluginVersionString << LL_ENDL; + + // Check which message classes/versions the plugin supports. + // TODO: check against current versions + // TODO: kill plugin on major mismatches? + mMessageClassVersions = message.getValueLLSD("versions"); + LLSD::map_iterator iter; + for(iter = mMessageClassVersions.beginMap(); iter != mMessageClassVersions.endMap(); iter++) + { + LL_INFOS("Plugin") << "message class: " << iter->first << " -> version: " << iter->second.asString() << LL_ENDL; + } + + // Send initial sleep time + setSleepTime(mSleepTime, true); + + setState(STATE_RUNNING); + } + else + { + LL_WARNS("Plugin") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL; + errorState(); + } + } + else if(message_name == "heartbeat") + { + // this resets our timer. + mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); + + mCPUUsage = message.getValueReal("cpu_usage"); + + LL_DEBUGS("Plugin") << "cpu usage reported as " << mCPUUsage << LL_ENDL; + + } + else if(message_name == "shm_add_response") + { + // Nothing to do here. + } + else if(message_name == "shm_remove_response") + { + std::string name = message.getValue("name"); + sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); + + if(iter != mSharedMemoryRegions.end()) + { + // destroy the shared memory region + iter->second->destroy(); + + // and remove it from our map + mSharedMemoryRegions.erase(iter); + } + } + else + { + LL_WARNS("Plugin") << "Unknown internal message from child: " << message_name << LL_ENDL; + } + } + else + { + if(mOwner != NULL) + { + mOwner->receivePluginMessage(message); + } + } +} + +std::string LLPluginProcessParent::addSharedMemory(size_t size) +{ + std::string name; + + LLPluginSharedMemory *region = new LLPluginSharedMemory; + + // This is a new region + if(region->create(size)) + { + name = region->getName(); + + mSharedMemoryRegions.insert(sharedMemoryRegionsType::value_type(name, region)); + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_add"); + message.setValue("name", name); + message.setValueS32("size", (S32)size); + sendMessage(message); + } + else + { + LL_WARNS("Plugin") << "Couldn't create a shared memory segment!" << LL_ENDL; + + // Don't leak + delete region; + } + + return name; +} + +void LLPluginProcessParent::removeSharedMemory(const std::string &name) +{ + sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); + + if(iter != mSharedMemoryRegions.end()) + { + // This segment exists. Send the message to the child to unmap it. The response will cause the parent to unmap our end. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove"); + message.setValue("name", name); + sendMessage(message); + } + else + { + LL_WARNS("Plugin") << "Request to remove an unknown shared memory segment." << LL_ENDL; + } +} +size_t LLPluginProcessParent::getSharedMemorySize(const std::string &name) +{ + size_t result = 0; + + sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); + if(iter != mSharedMemoryRegions.end()) + { + result = iter->second->getSize(); + } + + return result; +} +void *LLPluginProcessParent::getSharedMemoryAddress(const std::string &name) +{ + void *result = NULL; + + sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); + if(iter != mSharedMemoryRegions.end()) + { + result = iter->second->getMappedAddress(); + } + + return result; +} + +std::string LLPluginProcessParent::getMessageClassVersion(const std::string &message_class) +{ + std::string result; + + if(mMessageClassVersions.has(message_class)) + { + result = mMessageClassVersions[message_class].asString(); + } + + return result; +} + +std::string LLPluginProcessParent::getPluginVersion(void) +{ + return mPluginVersionString; +} + +void LLPluginProcessParent::setState(EState state) +{ + LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL; + mState = state; +}; + +bool LLPluginProcessParent::pluginLockedUpOrQuit() +{ + bool result = false; + + if(!mDisableTimeout && !mDebug) + { + if(!mProcess.isRunning()) + { + LL_WARNS("Plugin") << "child exited" << llendl; + result = true; + } + else if(pluginLockedUp()) + { + LL_WARNS("Plugin") << "timeout" << llendl; + result = true; + } + } + + return result; +} + +bool LLPluginProcessParent::pluginLockedUp() +{ + // If the timer is running and has expired, the plugin has locked up. + return (mHeartbeat.getStarted() && mHeartbeat.hasExpired()); +} + diff --git a/linden/indra/llplugin/llpluginprocessparent.h b/linden/indra/llplugin/llpluginprocessparent.h new file mode 100644 index 0000000..00c60b5 --- /dev/null +++ b/linden/indra/llplugin/llpluginprocessparent.h @@ -0,0 +1,169 @@ +/** + * @file llpluginprocessparent.h + * @brief LLPluginProcessParent handles the parent side of the external-process plugin API. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPLUGINPROCESSPARENT_H +#define LL_LLPLUGINPROCESSPARENT_H + +#include "llapr.h" +#include "llprocesslauncher.h" +#include "llpluginmessage.h" +#include "llpluginmessagepipe.h" +#include "llpluginsharedmemory.h" + +#include "lliosocket.h" + +class LLPluginProcessParentOwner +{ +public: + virtual ~LLPluginProcessParentOwner(); + virtual void receivePluginMessage(const LLPluginMessage &message) = 0; + // This will only be called when the plugin has died unexpectedly + virtual void pluginLaunchFailed() {}; + virtual void pluginDied() {}; +}; + +class LLPluginProcessParent : public LLPluginMessagePipeOwner +{ + LOG_CLASS(LLPluginProcessParent); +public: + LLPluginProcessParent(LLPluginProcessParentOwner *owner); + ~LLPluginProcessParent(); + + void init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug, const std::string &user_data_path); + void idle(void); + + // returns true if the plugin is on its way to steady state + bool isLoading(void); + + // returns true if the plugin is in the steady state (processing messages) + bool isRunning(void); + + // returns true if the process has exited or we've had a fatal error + bool isDone(void); + + void killSockets(void); + + // Go to the proper error state + void errorState(void); + + void setSleepTime(F64 sleep_time, bool force_send = false); + F64 getSleepTime(void) const { return mSleepTime; }; + + void sendMessage(const LLPluginMessage &message); + + void receiveMessage(const LLPluginMessage &message); + + // Inherited from LLPluginMessagePipeOwner + void receiveMessageRaw(const std::string &message); + + // This adds a memory segment shared with the client, generating a name for the segment. The name generated is guaranteed to be unique on the host. + // The caller must call removeSharedMemory first (and wait until getSharedMemorySize returns 0 for the indicated name) before re-adding a segment with the same name. + std::string addSharedMemory(size_t size); + // Negotiates for the removal of a shared memory segment. It is the caller's responsibility to ensure that nothing touches the memory + // after this has been called, since the segment will be unmapped shortly thereafter. + void removeSharedMemory(const std::string &name); + size_t getSharedMemorySize(const std::string &name); + void *getSharedMemoryAddress(const std::string &name); + + // Returns the version string the plugin indicated for the message class, or an empty string if that class wasn't in the list. + std::string getMessageClassVersion(const std::string &message_class); + + std::string getPluginVersion(void); + + bool getDisableTimeout() { return mDisableTimeout; }; + void setDisableTimeout(bool disable) { mDisableTimeout = disable; }; + + void setLaunchTimeout(F32 timeout) { mPluginLaunchTimeout = timeout; }; + void setLockupTimeout(F32 timeout) { mPluginLockupTimeout = timeout; }; + + F64 getCPUUsage() { return mCPUUsage; }; + +private: + + enum EState + { + STATE_UNINITIALIZED, + STATE_INITIALIZED, // init() has been called + STATE_LISTENING, // listening for incoming connection + STATE_LAUNCHED, // process has been launched + STATE_CONNECTED, // process has connected + STATE_HELLO, // first message from the plugin process has been received + STATE_LOADING, // process has been asked to load the plugin + STATE_RUNNING, // + STATE_LAUNCH_FAILURE, // Failure before plugin loaded + STATE_ERROR, // generic bailout state + STATE_CLEANUP, // clean everything up + STATE_EXITING, // Tried to kill process, waiting for it to exit + STATE_DONE // + + }; + EState mState; + void setState(EState state); + + bool pluginLockedUp(); + bool pluginLockedUpOrQuit(); + + bool accept(); + + LLSocket::ptr_t mListenSocket; + LLSocket::ptr_t mSocket; + U32 mBoundPort; + + LLProcessLauncher mProcess; + + std::string mPluginFile; + + std::string mUserDataPath; + + LLPluginProcessParentOwner *mOwner; + + typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType; + sharedMemoryRegionsType mSharedMemoryRegions; + + LLSD mMessageClassVersions; + std::string mPluginVersionString; + + LLTimer mHeartbeat; + F64 mSleepTime; + F64 mCPUUsage; + + bool mDisableTimeout; + bool mDebug; + + LLProcessLauncher mDebugger; + + F32 mPluginLaunchTimeout; // Somewhat longer timeout for initial launch. + F32 mPluginLockupTimeout; // If we don't receive a heartbeat in this many seconds, we declare the plugin locked up. + +}; + +#endif // LL_LLPLUGINPROCESSPARENT_H diff --git a/linden/indra/llplugin/llpluginsharedmemory.cpp b/linden/indra/llplugin/llpluginsharedmemory.cpp new file mode 100644 index 0000000..2be4648 --- /dev/null +++ b/linden/indra/llplugin/llpluginsharedmemory.cpp @@ -0,0 +1,506 @@ +/** + * @file llpluginsharedmemory.cpp + * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llpluginsharedmemory.h" + +// on Mac and Linux, we use the native shm_open/mmap interface by using +// #define USE_SHM_OPEN_SHARED_MEMORY 1 +// in the appropriate sections below. + +// For Windows, use: +// #define USE_WIN32_SHARED_MEMORY 1 + +// If we ever want to fall back to the apr implementation for a platform, use: +// #define USE_APR_SHARED_MEMORY 1 + +#if LL_WINDOWS +// #define USE_APR_SHARED_MEMORY 1 + #define USE_WIN32_SHARED_MEMORY 1 +#elif LL_DARWIN + #define USE_SHM_OPEN_SHARED_MEMORY 1 +#elif LL_LINUX + #define USE_SHM_OPEN_SHARED_MEMORY 1 +#endif + + +// FIXME: This path thing is evil and unacceptable. +#if LL_WINDOWS + #define APR_SHARED_MEMORY_PREFIX_STRING "C:\\LLPlugin_" + // Apparnently using the "Global\\" prefix here only works from administrative accounts under Vista. + // Other options I've seen referenced are "Local\\" and "Session\\". + #define WIN32_SHARED_MEMORY_PREFIX_STRING "Local\\LL_" +#else + // mac and linux + #define APR_SHARED_MEMORY_PREFIX_STRING "/tmp/LLPlugin_" + #define SHM_OPEN_SHARED_MEMORY_PREFIX_STRING "/LL" +#endif + +#if USE_APR_SHARED_MEMORY + #include "llapr.h" + #include "apr_shm.h" +#elif USE_SHM_OPEN_SHARED_MEMORY + #include <sys/fcntl.h> + #include <sys/mman.h> + #include <errno.h> +#elif USE_WIN32_SHARED_MEMORY +#include <windows.h> +#endif // USE_APR_SHARED_MEMORY + + +int LLPluginSharedMemory::sSegmentNumber = 0; + +std::string LLPluginSharedMemory::createName(void) +{ + std::stringstream newname; + +#if LL_WINDOWS + newname << GetCurrentProcessId(); +#else // LL_WINDOWS + newname << getpid(); +#endif // LL_WINDOWS + + newname << "_" << sSegmentNumber++; + + return newname.str(); +} + +/** + * @brief LLPluginSharedMemoryImpl is the platform-dependent implementation of LLPluginSharedMemory. TODO:DOC is this necessary/sufficient? kinda obvious. + * + */ +class LLPluginSharedMemoryPlatformImpl +{ +public: + LLPluginSharedMemoryPlatformImpl(); + ~LLPluginSharedMemoryPlatformImpl(); + +#if USE_APR_SHARED_MEMORY + apr_shm_t* mAprSharedMemory; +#elif USE_SHM_OPEN_SHARED_MEMORY + int mSharedMemoryFD; +#elif USE_WIN32_SHARED_MEMORY + HANDLE mMapFile; +#endif + +}; + +/** + * Constructor. Creates a shared memory segment. + */ +LLPluginSharedMemory::LLPluginSharedMemory() +{ + mSize = 0; + mMappedAddress = NULL; + mNeedsDestroy = false; + + mImpl = new LLPluginSharedMemoryPlatformImpl; +} + +/** + * Destructor. Uses destroy() and detach() to ensure shared memory segment is cleaned up. + */ +LLPluginSharedMemory::~LLPluginSharedMemory() +{ + if(mNeedsDestroy) + destroy(); + else + detach(); + + unlink(); + + delete mImpl; +} + +#if USE_APR_SHARED_MEMORY +// MARK: apr implementation + +LLPluginSharedMemoryPlatformImpl::LLPluginSharedMemoryPlatformImpl() +{ + mAprSharedMemory = NULL; +} + +LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl() +{ + +} + +bool LLPluginSharedMemory::map(void) +{ + mMappedAddress = apr_shm_baseaddr_get(mImpl->mAprSharedMemory); + if(mMappedAddress == NULL) + { + return false; + } + + return true; +} + +bool LLPluginSharedMemory::unmap(void) +{ + // This is a no-op under apr. + return true; +} + +bool LLPluginSharedMemory::close(void) +{ + // This is a no-op under apr. + return true; +} + +bool LLPluginSharedMemory::unlink(void) +{ + // This is a no-op under apr. + return true; +} + + +bool LLPluginSharedMemory::create(size_t size) +{ + mName = APR_SHARED_MEMORY_PREFIX_STRING; + mName += createName(); + mSize = size; + + apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), gAPRPoolp ); + + if(ll_apr_warn_status(status)) + { + return false; + } + + mNeedsDestroy = true; + + return map(); +} + +bool LLPluginSharedMemory::destroy(void) +{ + if(mImpl->mAprSharedMemory) + { + apr_status_t status = apr_shm_destroy(mImpl->mAprSharedMemory); + if(ll_apr_warn_status(status)) + { + // TODO: Is this a fatal error? I think not... + } + mImpl->mAprSharedMemory = NULL; + } + + return true; +} + +bool LLPluginSharedMemory::attach(const std::string &name, size_t size) +{ + mName = name; + mSize = size; + + apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), gAPRPoolp ); + + if(ll_apr_warn_status(status)) + { + return false; + } + + return map(); +} + + +bool LLPluginSharedMemory::detach(void) +{ + if(mImpl->mAprSharedMemory) + { + apr_status_t status = apr_shm_detach(mImpl->mAprSharedMemory); + if(ll_apr_warn_status(status)) + { + // TODO: Is this a fatal error? I think not... + } + mImpl->mAprSharedMemory = NULL; + } + + return true; +} + + +#elif USE_SHM_OPEN_SHARED_MEMORY +// MARK: shm_open/mmap implementation + +LLPluginSharedMemoryPlatformImpl::LLPluginSharedMemoryPlatformImpl() +{ + mSharedMemoryFD = -1; +} + +LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl() +{ +} + +bool LLPluginSharedMemory::map(void) +{ + mMappedAddress = ::mmap(NULL, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, mImpl->mSharedMemoryFD, 0); + if(mMappedAddress == NULL) + { + return false; + } + + LL_DEBUGS("Plugin") << "memory mapped at " << mMappedAddress << LL_ENDL; + + return true; +} + +bool LLPluginSharedMemory::unmap(void) +{ + if(mMappedAddress != NULL) + { + LL_DEBUGS("Plugin") << "calling munmap(" << mMappedAddress << ", " << mSize << ")" << LL_ENDL; + if(::munmap(mMappedAddress, mSize) == -1) + { + // TODO: Is this a fatal error? I think not... + } + + mMappedAddress = NULL; + } + + return true; +} + +bool LLPluginSharedMemory::close(void) +{ + if(mImpl->mSharedMemoryFD != -1) + { + LL_DEBUGS("Plugin") << "calling close(" << mImpl->mSharedMemoryFD << ")" << LL_ENDL; + if(::close(mImpl->mSharedMemoryFD) == -1) + { + // TODO: Is this a fatal error? I think not... + } + + mImpl->mSharedMemoryFD = -1; + } + return true; +} + +bool LLPluginSharedMemory::unlink(void) +{ + if(!mName.empty()) + { + if(::shm_unlink(mName.c_str()) == -1) + { + return false; + } + } + + return true; +} + + +bool LLPluginSharedMemory::create(size_t size) +{ + mName = SHM_OPEN_SHARED_MEMORY_PREFIX_STRING; + mName += createName(); + mSize = size; + + // Preemptive unlink, just in case something didn't get cleaned up. + unlink(); + + mImpl->mSharedMemoryFD = ::shm_open(mName.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if(mImpl->mSharedMemoryFD == -1) + { + return false; + } + + mNeedsDestroy = true; + + if(::ftruncate(mImpl->mSharedMemoryFD, mSize) == -1) + { + return false; + } + + + return map(); +} + +bool LLPluginSharedMemory::destroy(void) +{ + unmap(); + close(); + + return true; +} + + +bool LLPluginSharedMemory::attach(const std::string &name, size_t size) +{ + mName = name; + mSize = size; + + mImpl->mSharedMemoryFD = ::shm_open(mName.c_str(), O_RDWR, S_IRUSR | S_IWUSR); + if(mImpl->mSharedMemoryFD == -1) + { + return false; + } + + // unlink here so the segment will be cleaned up automatically after the last close. + unlink(); + + return map(); +} + +bool LLPluginSharedMemory::detach(void) +{ + unmap(); + close(); + return true; +} + +#elif USE_WIN32_SHARED_MEMORY +// MARK: Win32 CreateFileMapping-based implementation + +// Reference: http://msdn.microsoft.com/en-us/library/aa366551(VS.85).aspx + +LLPluginSharedMemoryPlatformImpl::LLPluginSharedMemoryPlatformImpl() +{ + mMapFile = NULL; +} + +LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl() +{ + +} + +bool LLPluginSharedMemory::map(void) +{ + mMappedAddress = MapViewOfFile( + mImpl->mMapFile, // handle to map object + FILE_MAP_ALL_ACCESS, // read/write permission + 0, + 0, + mSize); + + if(mMappedAddress == NULL) + { + LL_WARNS("Plugin") << "MapViewOfFile failed: " << GetLastError() << LL_ENDL; + return false; + } + + LL_DEBUGS("Plugin") << "memory mapped at " << mMappedAddress << LL_ENDL; + + return true; +} + +bool LLPluginSharedMemory::unmap(void) +{ + if(mMappedAddress != NULL) + { + UnmapViewOfFile(mMappedAddress); + mMappedAddress = NULL; + } + + return true; +} + +bool LLPluginSharedMemory::close(void) +{ + if(mImpl->mMapFile != NULL) + { + CloseHandle(mImpl->mMapFile); + mImpl->mMapFile = NULL; + } + + return true; +} + +bool LLPluginSharedMemory::unlink(void) +{ + // This is a no-op on Windows. + return true; +} + + +bool LLPluginSharedMemory::create(size_t size) +{ + mName = WIN32_SHARED_MEMORY_PREFIX_STRING; + mName += createName(); + mSize = size; + + mImpl->mMapFile = CreateFileMappingA( + INVALID_HANDLE_VALUE, // use paging file + NULL, // default security + PAGE_READWRITE, // read/write access + 0, // max. object size + mSize, // buffer size + mName.c_str()); // name of mapping object + + if(mImpl->mMapFile == NULL) + { + LL_WARNS("Plugin") << "CreateFileMapping failed: " << GetLastError() << LL_ENDL; + return false; + } + + mNeedsDestroy = true; + + return map(); +} + +bool LLPluginSharedMemory::destroy(void) +{ + unmap(); + close(); + return true; +} + +bool LLPluginSharedMemory::attach(const std::string &name, size_t size) +{ + mName = name; + mSize = size; + + mImpl->mMapFile = OpenFileMappingA( + FILE_MAP_ALL_ACCESS, // read/write access + FALSE, // do not inherit the name + mName.c_str()); // name of mapping object + + if(mImpl->mMapFile == NULL) + { + LL_WARNS("Plugin") << "OpenFileMapping failed: " << GetLastError() << LL_ENDL; + return false; + } + + return map(); +} + +bool LLPluginSharedMemory::detach(void) +{ + unmap(); + close(); + return true; +} + + + +#endif diff --git a/linden/indra/llplugin/llpluginsharedmemory.h b/linden/indra/llplugin/llpluginsharedmemory.h new file mode 100644 index 0000000..2dc550e --- /dev/null +++ b/linden/indra/llplugin/llpluginsharedmemory.h @@ -0,0 +1,130 @@ +/** + * @file llpluginsharedmemory.h + * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPLUGINSHAREDMEMORY_H +#define LL_LLPLUGINSHAREDMEMORY_H + +class LLPluginSharedMemoryPlatformImpl; + +/** + * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API. + * + */ +class LLPluginSharedMemory +{ + LOG_CLASS(LLPluginSharedMemory); +public: + LLPluginSharedMemory(); + ~LLPluginSharedMemory(); + + // Parent will use create/destroy, child will use attach/detach. + // Message transactions will ensure child attaches after parent creates and detaches before parent destroys. + + /** + * Creates a shared memory segment, with a name which is guaranteed to be unique on the host at the current time. Used by parent. + * Message transactions will (? TODO:DOC - should? must?) ensure child attaches after parent creates and detaches before parent destroys. + * + * @param[in] size Shared memory size in TODO:DOC units = bytes?. + * + * @return False for failure, true for success. + */ + bool create(size_t size); + /** + * Destroys a shared memory segment. Used by parent. + * Message transactions will (? TODO:DOC - should? must?) ensure child attaches after parent creates and detaches before parent destroys. + * + * @return True. TODO:DOC - always returns true. Is this the intended behavior? + */ + bool destroy(void); + + /** + * Creates and attaches a name to a shared memory segment. TODO:DOC what's the difference between attach() and create()? + * + * @param[in] name Name to attach to memory segment + * @param[in] size Size of memory segment TODO:DOC in bytes? + * + * @return False on failure, true otherwise. + */ + bool attach(const std::string &name, size_t size); + /** + * Detaches shared memory segment. + * + * @return False on failure, true otherwise. + */ + bool detach(void); + + /** + * Checks if shared memory is mapped to a non-null address. + * + * @return True if memory address is non-null, false otherwise. + */ + bool isMapped(void) const { return (mMappedAddress != NULL); }; + /** + * Get pointer to shared memory. + * + * @return Pointer to shared memory. + */ + void *getMappedAddress(void) const { return mMappedAddress; }; + /** + * Get size of shared memory. + * + * @return Size of shared memory in bytes. TODO:DOC are bytes the correct unit? + */ + size_t getSize(void) const { return mSize; }; + /** + * Get name of shared memory. + * + * @return Name of shared memory. + */ + std::string getName() const { return mName; }; + +private: + bool map(void); + bool unmap(void); + bool close(void); + bool unlink(void); + + std::string mName; + size_t mSize; + void *mMappedAddress; + bool mNeedsDestroy; + + LLPluginSharedMemoryPlatformImpl *mImpl; + + static int sSegmentNumber; + static std::string createName(); + +}; + + + +#endif // LL_LLPLUGINSHAREDMEMORY_H diff --git a/linden/indra/llplugin/slplugin/CMakeLists.txt b/linden/indra/llplugin/slplugin/CMakeLists.txt new file mode 100644 index 0000000..4a7d670 --- /dev/null +++ b/linden/indra/llplugin/slplugin/CMakeLists.txt @@ -0,0 +1,55 @@ +project(SLPlugin) + +include(00-Common) +include(LLCommon) +include(LLPlugin) +include(Linking) +include(PluginAPI) +include(LLMessage) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${LLMESSAGE_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} +) + +if (DARWIN) + include(CMakeFindFrameworks) + find_library(CARBON_LIBRARY Carbon) +endif (DARWIN) + + +### SLPlugin + +set(SLPlugin_SOURCE_FILES + slplugin.cpp + ) + +add_executable(SLPlugin + WIN32 + ${SLPlugin_SOURCE_FILES} +) + +target_link_libraries(SLPlugin + ${LLPLUGIN_LIBRARIES} + ${LLMESSAGE_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${PLUGIN_API_WINDOWS_LIBRARIES} +) + +add_dependencies(SLPlugin + ${LLPLUGIN_LIBRARIES} + ${LLMESSAGE_LIBRARIES} + ${LLCOMMON_LIBRARIES} +) + +if (DARWIN) + # Mac version needs to link against carbon, and also needs an embedded plist (to set LSBackgroundOnly) + target_link_libraries(SLPlugin ${CARBON_LIBRARY}) + set_target_properties( + SLPlugin + PROPERTIES + LINK_FLAGS "-Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/slplugin_info.plist" + ) +endif (DARWIN) + diff --git a/linden/indra/llplugin/slplugin/slplugin.cpp b/linden/indra/llplugin/slplugin/slplugin.cpp new file mode 100644 index 0000000..fa3924b --- /dev/null +++ b/linden/indra/llplugin/slplugin/slplugin.cpp @@ -0,0 +1,288 @@ +/** + * @file slplugin.cpp + * @brief Loader shell for plugins, intended to be launched by the plugin host application, which directly loads a plugin dynamic library. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#include "linden_common.h" + +#include "llpluginprocesschild.h" +#include "llpluginmessage.h" +#include "llerrorcontrol.h" +#include "llapr.h" +#include "llstring.h" + +#if LL_DARWIN + #include <Carbon/Carbon.h> +#endif + +#if LL_DARWIN || LL_LINUX + #include <signal.h> +#endif + +/* + On Mac OS, since we call WaitNextEvent, this process will show up in the dock unless we set the LSBackgroundOnly flag in the Info.plist. + + Normally non-bundled binaries don't have an info.plist file, but it's possible to embed one in the binary by adding this to the linker flags: + + -sectcreate __TEXT __info_plist /path/to/slplugin_info.plist + + which means adding this to the gcc flags: + + -Wl,-sectcreate,__TEXT,__info_plist,/path/to/slplugin_info.plist + +*/ + +#if LL_DARWIN || LL_LINUX +// Signal handlers to make crashes not show an OS dialog... +static void crash_handler(int sig) +{ + // Just exit cleanly. + // TODO: add our own crash reporting + _exit(1); +} +#endif + +#if LL_WINDOWS +#include <windows.h> +//////////////////////////////////////////////////////////////////////////////// +// Our exception handler - will probably just exit and the host application +// will miss the heartbeat and log the error in the usual fashion. +LONG WINAPI myWin32ExceptionHandler( struct _EXCEPTION_POINTERS* exception_infop ) +{ + //std::cerr << "This plugin (" << __FILE__ << ") - "; + //std::cerr << "intercepted an unhandled exception and will exit immediately." << std::endl; + + // TODO: replace exception handler before we exit? + return EXCEPTION_EXECUTE_HANDLER; +} + +// Taken from : http://blog.kalmbachnet.de/?postid=75 +// The MSVC 2005 CRT forces the call of the default-debugger (normally Dr.Watson) +// even with the other exception handling code. This (terrifying) piece of code +// patches things so that doesn't happen. +LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter( + LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter ) +{ + return NULL; +} + +BOOL PreventSetUnhandledExceptionFilter() +{ +// WARNING: This won't work on 64-bit Windows systems so we turn it off it. +// It should work for any flavor of 32-bit Windows we care about. +// If it's off, sometimes you will see an OS message when a plugin crashes +#ifndef _WIN64 + HMODULE hKernel32 = LoadLibraryA( "kernel32.dll" ); + if ( NULL == hKernel32 ) + return FALSE; + + void *pOrgEntry = GetProcAddress( hKernel32, "SetUnhandledExceptionFilter" ); + if( NULL == pOrgEntry ) + return FALSE; + + unsigned char newJump[ 100 ]; + DWORD dwOrgEntryAddr = (DWORD)pOrgEntry; + dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far + void *pNewFunc = &MyDummySetUnhandledExceptionFilter; + DWORD dwNewEntryAddr = (DWORD) pNewFunc; + DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr; + + newJump[ 0 ] = 0xE9; // JMP absolute + memcpy( &newJump[ 1 ], &dwRelativeAddr, sizeof( pNewFunc ) ); + SIZE_T bytesWritten; + BOOL bRet = WriteProcessMemory( GetCurrentProcess(), pOrgEntry, newJump, sizeof( pNewFunc ) + 1, &bytesWritten ); + return bRet; +#else + return FALSE; +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// Hook our exception handler and replace the system one +void initExceptionHandler() +{ + LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; + + // save old exception handler in case we need to restore it at the end + prev_filter = SetUnhandledExceptionFilter( myWin32ExceptionHandler ); + PreventSetUnhandledExceptionFilter(); +} + +bool checkExceptionHandler() +{ + bool ok = true; + LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; + prev_filter = SetUnhandledExceptionFilter(myWin32ExceptionHandler); + + PreventSetUnhandledExceptionFilter(); + + if (prev_filter != myWin32ExceptionHandler) + { + LL_WARNS("AppInit") << "Our exception handler (" << (void *)myWin32ExceptionHandler << ") replaced with " << prev_filter << "!" << LL_ENDL; + ok = false; + } + + if (prev_filter == NULL) + { + ok = FALSE; + if (myWin32ExceptionHandler == NULL) + { + LL_WARNS("AppInit") << "Exception handler uninitialized." << LL_ENDL; + } + else + { + LL_WARNS("AppInit") << "Our exception handler (" << (void *)myWin32ExceptionHandler << ") replaced with NULL!" << LL_ENDL; + } + } + + return ok; +} +#endif + +// If this application on Windows platform is a console application, a console is always +// created which is bad. Making it a Windows "application" via CMake settings but not +// adding any code to explicitly create windows does the right thing. +#if LL_WINDOWS +int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) +#else +int main(int argc, char **argv) +#endif +{ + ll_init_apr(); + + // Set up llerror logging + { + LLError::initForApplication("."); + LLError::setDefaultLevel(LLError::LEVEL_INFO); +// LLError::setTagLevel("Plugin", LLError::LEVEL_DEBUG); +// LLError::logToFile("slplugin.log"); + } + +#if LL_WINDOWS + if( strlen( lpCmdLine ) == 0 ) + { + LL_ERRS("slplugin") << "usage: " << "SLPlugin" << " launcher_port" << LL_ENDL; + }; + + U32 port = 0; + if(!LLStringUtil::convertToU32(lpCmdLine, port)) + { + LL_ERRS("slplugin") << "port number must be numeric" << LL_ENDL; + }; + + // Insert our exception handler into the system so this plugin doesn't + // display a crash message if something bad happens. The host app will + // see the missing heartbeat and log appropriately. + initExceptionHandler(); +#elif LL_DARWIN || LL_LINUX + if(argc < 2) + { + LL_ERRS("slplugin") << "usage: " << argv[0] << " launcher_port" << LL_ENDL; + } + + U32 port = 0; + if(!LLStringUtil::convertToU32(argv[1], port)) + { + LL_ERRS("slplugin") << "port number must be numeric" << LL_ENDL; + } + + // Catch signals that most kinds of crashes will generate, and exit cleanly so the system crash dialog isn't shown. + signal(SIGILL, &crash_handler); // illegal instruction +# if LL_DARWIN + signal(SIGEMT, &crash_handler); // emulate instruction executed +# endif // LL_DARWIN + signal(SIGFPE, &crash_handler); // floating-point exception + signal(SIGBUS, &crash_handler); // bus error + signal(SIGSEGV, &crash_handler); // segmentation violation + signal(SIGSYS, &crash_handler); // non-existent system call invoked +#endif + + LLPluginProcessChild *plugin = new LLPluginProcessChild(); + + plugin->init(port); + + LLTimer timer; + timer.start(); + +#if LL_WINDOWS + checkExceptionHandler(); +#endif + + while(!plugin->isDone()) + { + timer.reset(); + plugin->idle(); +#if LL_DARWIN + { + // Some plugins (webkit at least) will want an event loop. This qualifies. + EventRecord evt; + WaitNextEvent(0, &evt, 0, NULL); + } +#endif + F64 elapsed = timer.getElapsedTimeF64(); + F64 remaining = plugin->getSleepTime() - elapsed; + + if(remaining <= 0.0f) + { + // We've already used our full allotment. +// LL_INFOS("slplugin") << "elapsed = " << elapsed * 1000.0f << " ms, remaining = " << remaining * 1000.0f << " ms, not sleeping" << LL_ENDL; + + // Still need to service the network... + plugin->pump(); + } + else + { + +// LL_INFOS("slplugin") << "elapsed = " << elapsed * 1000.0f << " ms, remaining = " << remaining * 1000.0f << " ms, sleeping for " << remaining * 1000.0f << " ms" << LL_ENDL; +// timer.reset(); + + // This also services the network as needed. + plugin->sleep(remaining); + +// LL_INFOS("slplugin") << "slept for "<< timer.getElapsedTimeF64() * 1000.0f << " ms" << LL_ENDL; + } + +#if LL_WINDOWS + // More agressive checking of interfering exception handlers. + // Doesn't appear to be required so far - even for plugins + // that do crash with a single call to the intercept + // exception handler such as QuickTime. + //checkExceptionHandler(); +#endif + } + + delete plugin; + + ll_cleanup_apr(); + + return 0; +} + diff --git a/linden/indra/llplugin/slplugin/slplugin_info.plist b/linden/indra/llplugin/slplugin/slplugin_info.plist new file mode 100644 index 0000000..b1daf87 --- /dev/null +++ b/linden/indra/llplugin/slplugin/slplugin_info.plist @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>LSBackgroundOnly</key> + <true/> +</dict> +</plist> diff --git a/linden/indra/llui/CMakeLists.txt b/linden/indra/llui/CMakeLists.txt index a0f80b4..e6b3b63 100644 --- a/linden/indra/llui/CMakeLists.txt +++ b/linden/indra/llui/CMakeLists.txt @@ -3,11 +3,9 @@ project(llui) include(00-Common) -include(LLAudio) include(LLCommon) include(LLImage) include(LLMath) -include(LLMedia) include(LLMessage) include(LLRender) include(LLWindow) @@ -15,11 +13,9 @@ include(LLVFS) include(LLXML) include_directories( - ${LLAUDIO_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} - ${LLMEDIA_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} @@ -141,3 +137,14 @@ set_source_files_properties(${llui_HEADER_FILES} list(APPEND llui_SOURCE_FILES ${llui_HEADER_FILES}) add_library (llui ${llui_SOURCE_FILES}) +# Libraries on which this library depends, needed for Linux builds +# Sort by high-level to low-level +target_link_libraries(llui + llrender + llwindow + llimage + llvfs # ugh, just for LLDir + llxml + llcommon # must be after llimage, llwindow, llrender + llmath + ) diff --git a/linden/indra/llui/llbutton.cpp b/linden/indra/llui/llbutton.cpp index 1a6c705..702e34e 100644 --- a/linden/indra/llui/llbutton.cpp +++ b/linden/indra/llui/llbutton.cpp @@ -840,6 +840,11 @@ void LLButton::setColor(const LLColor4& color) setImageColor(color); } +void LLButton::setAlpha(F32 alpha) +{ + mImageColor.setAlpha(alpha); + mDisabledImageColor.setAlpha(alpha * 0.5f); +} void LLButton::setImageDisabled(LLPointer<LLUIImage> image) { diff --git a/linden/indra/llui/llbutton.h b/linden/indra/llui/llbutton.h index 724b775..2174d95 100644 --- a/linden/indra/llui/llbutton.h +++ b/linden/indra/llui/llbutton.h @@ -136,7 +136,8 @@ public: void setImageColor(const std::string& color_control); void setImageColor(const LLColor4& c); - virtual void setColor(const LLColor4& c); + /*virtual*/ void setColor(const LLColor4& c); + /*virtual*/ void setAlpha(F32 alpha); void setImages(const std::string &image_name, const std::string &selected_name); void setDisabledImages(const std::string &image_name, const std::string &selected_name); diff --git a/linden/indra/llui/llfloater.cpp b/linden/indra/llui/llfloater.cpp index f6451a1..bb42ca3 100644 --- a/linden/indra/llui/llfloater.cpp +++ b/linden/indra/llui/llfloater.cpp @@ -1459,9 +1459,9 @@ void LLFloater::draw() { if (hasFocus() && getDefaultButton()->getEnabled()) { - LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); + LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus(); // is this button a direct descendent and not a nested widget (e.g. checkbox)? - BOOL focus_is_child_button = dynamic_cast<LLButton*>(focus_ctrl) != NULL && focus_ctrl->getParent() == this; + BOOL focus_is_child_button = dynamic_cast<LLButton*>(focus_ctrl) != NULL && dynamic_cast<LLButton*>(focus_ctrl)->getParent() == this; // only enable default button when current focus is not a button getDefaultButton()->setBorderEnabled(!focus_is_child_button); } @@ -1481,7 +1481,7 @@ void LLFloater::draw() else { // draw children - LLView* focused_child = gFocusMgr.getKeyboardFocus(); + LLView* focused_child = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus()); BOOL focused_child_visible = FALSE; if (focused_child && focused_child->getParent() == this) { @@ -2239,7 +2239,7 @@ BOOL LLFloaterView::allChildrenClosed() LLView* viewp = *it; LLFloater* floaterp = (LLFloater*)viewp; - if (floaterp->getVisible() && !floaterp->isDead() && floaterp->canClose()) + if (floaterp->getVisible() && !floaterp->isDead() && floaterp->isCloseable()) { return false; } diff --git a/linden/indra/llui/llfocusmgr.cpp b/linden/indra/llui/llfocusmgr.cpp index 661ffdd..96b01b9 100644 --- a/linden/indra/llui/llfocusmgr.cpp +++ b/linden/indra/llui/llfocusmgr.cpp @@ -38,6 +38,68 @@ const F32 FOCUS_FADE_TIME = 0.3f; +// NOTE: the LLFocusableElement implementation has been here from lluictrl.cpp. + +LLFocusableElement::LLFocusableElement() +: mFocusLostCallback(NULL), + mFocusReceivedCallback(NULL), + mFocusChangedCallback(NULL), + mFocusCallbackUserData(NULL) +{ +} + +// virtual +BOOL LLFocusableElement::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ + return FALSE; +} + +// virtual +BOOL LLFocusableElement::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) +{ + return FALSE; +} + +// virtual +LLFocusableElement::~LLFocusableElement() +{ +} + +void LLFocusableElement::onFocusReceived() +{ + if( mFocusReceivedCallback ) + { + mFocusReceivedCallback( this, mFocusCallbackUserData ); + } + if( mFocusChangedCallback ) + { + mFocusChangedCallback( this, mFocusCallbackUserData ); + } +} + +void LLFocusableElement::onFocusLost() +{ + if( mFocusLostCallback ) + { + mFocusLostCallback( this, mFocusCallbackUserData ); + } + + if( mFocusChangedCallback ) + { + mFocusChangedCallback( this, mFocusCallbackUserData ); + } +} + +BOOL LLFocusableElement::hasFocus() const +{ + return gFocusMgr.getKeyboardFocus() == this; +} + +void LLFocusableElement::setFocus(BOOL b) +{ +} + + LLFocusMgr gFocusMgr; LLFocusMgr::LLFocusMgr() @@ -87,11 +149,13 @@ void LLFocusMgr::releaseFocusIfNeeded( const LLView* view ) } -void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystrokes_only) +void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL keystrokes_only) { if (mLockedView && (new_focus == NULL || - (new_focus != mLockedView && !new_focus->hasAncestor(mLockedView)))) + (new_focus != mLockedView + && dynamic_cast<LLView*>(new_focus) + && !dynamic_cast<LLView*>(new_focus)->hasAncestor(mLockedView)))) { // don't allow focus to go to anything that is not the locked focus // or one of its descendants @@ -121,7 +185,8 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystroke mFocusTimer.reset(); #ifdef _DEBUG - mKeyboardFocusName = new_focus ? new_focus->getName() : std::string("none"); + LLUICtrl* focus_ctrl = dynamic_cast<LLUICtrl*>(new_focus); + mKeyboardFocusName = focus_ctrl ? focus_ctrl->getName() : std::string("none"); #endif // If we've got a default keyboard focus, and the caller is @@ -131,8 +196,8 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystroke mDefaultKeyboardFocus->setFocus(TRUE); } - LLView* focus_subtree = mKeyboardFocus; - LLView* viewp = mKeyboardFocus; + LLView* focus_subtree = dynamic_cast<LLView*>(mKeyboardFocus); + LLView* viewp = dynamic_cast<LLView*>(mKeyboardFocus); // find root-most focus root while(viewp) { @@ -146,7 +211,8 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystroke if (focus_subtree) { - mFocusHistory[focus_subtree->getHandle()] = mKeyboardFocus ? mKeyboardFocus->getHandle() : LLHandle<LLView>(); + LLView* focused_view = dynamic_cast<LLView*>(mKeyboardFocus); + mFocusHistory[focus_subtree->getHandle()] = focused_view ? focused_view->getHandle() : LLHandle<LLView>(); } } @@ -160,7 +226,7 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, BOOL lock, BOOL keystroke // Returns TRUE is parent or any descedent of parent has keyboard focus. BOOL LLFocusMgr::childHasKeyboardFocus(const LLView* parent ) const { - LLView* focus_view = mKeyboardFocus; + LLView* focus_view = dynamic_cast<LLView*>(mKeyboardFocus); while( focus_view ) { if( focus_view == parent ) @@ -190,7 +256,7 @@ BOOL LLFocusMgr::childHasMouseCapture( const LLView* parent ) const return FALSE; } -void LLFocusMgr::removeKeyboardFocusWithoutCallback( const LLView* focus ) +void LLFocusMgr::removeKeyboardFocusWithoutCallback( const LLFocusableElement* focus ) { // should be ok to unlock here, as you have to know the locked view // in order to unlock it @@ -313,7 +379,7 @@ void LLFocusMgr::removeTopCtrlWithoutCallback( const LLUICtrl* top_view ) void LLFocusMgr::lockFocus() { - mLockedView = mKeyboardFocus; + mLockedView = dynamic_cast<LLUICtrl*>(mKeyboardFocus); } void LLFocusMgr::unlockFocus() diff --git a/linden/indra/llui/llfocusmgr.h b/linden/indra/llui/llfocusmgr.h index aaeb25a..88ede1a 100644 --- a/linden/indra/llui/llfocusmgr.h +++ b/linden/indra/llui/llfocusmgr.h @@ -37,10 +37,39 @@ #include "llstring.h" #include "llframetimer.h" -#include "llview.h" +#include "llui.h" class LLUICtrl; class LLMouseHandler; +class LLView; + +class LLFocusableElement +{ + friend class LLFocusMgr; // allow access to focus change handlers +public: + LLFocusableElement(); + virtual ~LLFocusableElement(); + + virtual void setFocus( BOOL b ); + virtual BOOL hasFocus() const; + + void setFocusLostCallback(void (*cb)(LLFocusableElement* caller, void*), void* user_data = NULL) { mFocusLostCallback = cb; mFocusCallbackUserData = user_data; } + void setFocusReceivedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL) { mFocusReceivedCallback = cb; mFocusCallbackUserData = user_data; } + void setFocusChangedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL ) { mFocusChangedCallback = cb; mFocusCallbackUserData = user_data; } + + // These were brought up the hierarchy from LLView so that we don't have to use dynamic_cast when dealing with keyboard focus. + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); + +protected: + virtual void onFocusReceived(); + virtual void onFocusLost(); + void (*mFocusLostCallback)( LLFocusableElement* caller, void* userdata ); + void (*mFocusReceivedCallback)( LLFocusableElement* ctrl, void* userdata ); + void (*mFocusChangedCallback)( LLFocusableElement* ctrl, void* userdata ); + void* mFocusCallbackUserData; +}; + class LLFocusMgr { @@ -55,11 +84,11 @@ public: BOOL childHasMouseCapture( const LLView* parent ) const; // Keyboard Focus - void setKeyboardFocus(LLUICtrl* new_focus, BOOL lock = FALSE, BOOL keystrokes_only = FALSE); // new_focus = NULL to release the focus. - LLUICtrl* getKeyboardFocus() const { return mKeyboardFocus; } - LLUICtrl* getLastKeyboardFocus() const { return mLastKeyboardFocus; } + void setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock = FALSE, BOOL keystrokes_only = FALSE); // new_focus = NULL to release the focus. + LLFocusableElement* getKeyboardFocus() const { return mKeyboardFocus; } + LLFocusableElement* getLastKeyboardFocus() const { return mLastKeyboardFocus; } BOOL childHasKeyboardFocus( const LLView* parent ) const; - void removeKeyboardFocusWithoutCallback( const LLView* focus ); + void removeKeyboardFocusWithoutCallback( const LLFocusableElement* focus ); BOOL getKeystrokesOnly() { return mKeystrokesOnly; } void setKeystrokesOnly(BOOL keystrokes_only) { mKeystrokesOnly = keystrokes_only; } @@ -75,8 +104,8 @@ public: // If setKeyboardFocus(NULL) is called, and there is a non-NULL default // keyboard focus view, focus goes there. JC - void setDefaultKeyboardFocus(LLUICtrl* default_focus) { mDefaultKeyboardFocus = default_focus; } - LLUICtrl* getDefaultKeyboardFocus() const { return mDefaultKeyboardFocus; } + void setDefaultKeyboardFocus(LLFocusableElement* default_focus) { mDefaultKeyboardFocus = default_focus; } + LLFocusableElement* getDefaultKeyboardFocus() const { return mDefaultKeyboardFocus; } // Top View @@ -98,9 +127,9 @@ private: LLMouseHandler* mMouseCaptor; // Mouse events are premptively routed to this object // Keyboard Focus - LLUICtrl* mKeyboardFocus; // Keyboard events are preemptively routed to this object - LLUICtrl* mLastKeyboardFocus; // who last had focus - LLUICtrl* mDefaultKeyboardFocus; + LLFocusableElement* mKeyboardFocus; // Keyboard events are preemptively routed to this object + LLFocusableElement* mLastKeyboardFocus; // who last had focus + LLFocusableElement* mDefaultKeyboardFocus; BOOL mKeystrokesOnly; // Top View diff --git a/linden/indra/llui/lliconctrl.cpp b/linden/indra/llui/lliconctrl.cpp index e73c8fe..0df960e 100644 --- a/linden/indra/llui/lliconctrl.cpp +++ b/linden/indra/llui/lliconctrl.cpp @@ -112,6 +112,12 @@ void LLIconCtrl::draw() LLUICtrl::draw(); } +// virtual +void LLIconCtrl::setAlpha(F32 alpha) +{ + mColor.setAlpha(alpha); +} + // virtual void LLIconCtrl::setValue(const LLSD& value ) { diff --git a/linden/indra/llui/lliconctrl.h b/linden/indra/llui/lliconctrl.h index 50778cf..2506fb2 100644 --- a/linden/indra/llui/lliconctrl.h +++ b/linden/indra/llui/lliconctrl.h @@ -65,6 +65,8 @@ public: virtual void setValue(const LLSD& value ); virtual LLSD getValue() const; + /*virtual*/ void setAlpha(F32 alpha); + void setColor(const LLColor4& color) { mColor = color; } virtual LLXMLNodePtr getXML(bool save_children = true) const; diff --git a/linden/indra/llui/llmultisliderctrl.cpp b/linden/indra/llui/llmultisliderctrl.cpp index b76c2f6..f9ec6d5 100644 --- a/linden/indra/llui/llmultisliderctrl.cpp +++ b/linden/indra/llui/llmultisliderctrl.cpp @@ -34,9 +34,6 @@ #include "llmultisliderctrl.h" -#include "audioengine.h" -#include "sound_ids.h" - #include "llmath.h" #include "llfontgl.h" #include "llgl.h" diff --git a/linden/indra/llui/llpanel.cpp b/linden/indra/llui/llpanel.cpp index 709342b..26137d7 100644 --- a/linden/indra/llui/llpanel.cpp +++ b/linden/indra/llui/llpanel.cpp @@ -203,6 +203,12 @@ void LLPanel::draw() LLView::draw(); } +/*virtual*/ +void LLPanel::setAlpha(F32 alpha) +{ + mBgColorOpaque.setAlpha(alpha); +} + void LLPanel::updateDefaultBtn() { // This method does not call LLView::draw() so callers will need @@ -213,8 +219,7 @@ void LLPanel::updateDefaultBtn() { if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled()) { - LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); - LLButton* buttonp = dynamic_cast<LLButton*>(focus_ctrl); + LLButton* buttonp = dynamic_cast<LLButton*>(gFocusMgr.getKeyboardFocus()); BOOL focus_is_child_button = buttonp && buttonp->getCommitOnReturn(); // only enable default button when current focus is not a return-capturing button mDefaultBtn->setBorderEnabled(!focus_is_child_button); @@ -276,7 +281,7 @@ BOOL LLPanel::handleKeyHere( KEY key, MASK mask ) { BOOL handled = FALSE; - LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus(); + LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); // handle user hitting ESC to defocus if (key == KEY_ESCAPE) @@ -800,6 +805,14 @@ void LLPanel::childSetColor(const std::string& id, const LLColor4& color) child->setColor(color); } } +void LLPanel::childSetAlpha(const std::string& id, F32 alpha) +{ + LLUICtrl* child = getChild<LLUICtrl>(id, true); + if (child) + { + child->setAlpha(alpha); + } +} LLCtrlSelectionInterface* LLPanel::childGetSelectionInterface(const std::string& id) const { diff --git a/linden/indra/llui/llpanel.h b/linden/indra/llui/llpanel.h index 756d02e..378b357 100644 --- a/linden/indra/llui/llpanel.h +++ b/linden/indra/llui/llpanel.h @@ -82,6 +82,8 @@ public: // From LLFocusableElement /*virtual*/ void setFocus( BOOL b ); + virtual void setAlpha(F32 alpha); + // New virtuals virtual void refresh(); // called in setFocus() @@ -174,6 +176,7 @@ public: void childSetUserData(const std::string& id, void* userdata); void childSetColor(const std::string& id, const LLColor4& color); + void childSetAlpha(const std::string& id, F32 alpha); LLCtrlSelectionInterface* childGetSelectionInterface(const std::string& id) const; LLCtrlListInterface* childGetListInterface(const std::string& id) const; diff --git a/linden/indra/llui/llsliderctrl.cpp b/linden/indra/llui/llsliderctrl.cpp index 8a13ed4..51d43fb 100644 --- a/linden/indra/llui/llsliderctrl.cpp +++ b/linden/indra/llui/llsliderctrl.cpp @@ -34,8 +34,6 @@ #include "llsliderctrl.h" -#include "audioengine.h" - #include "llmath.h" #include "llfontgl.h" #include "llgl.h" diff --git a/linden/indra/llui/llspinctrl.cpp b/linden/indra/llui/llspinctrl.cpp index 7eccaca..e66b20e 100644 --- a/linden/indra/llui/llspinctrl.cpp +++ b/linden/indra/llui/llspinctrl.cpp @@ -45,7 +45,6 @@ #include "lltextbox.h" #include "llkeyboard.h" #include "llmath.h" -#include "audioengine.h" #include "llcontrol.h" #include "llfocusmgr.h" #include "llresmgr.h" diff --git a/linden/indra/llui/lltextparser.cpp b/linden/indra/llui/lltextparser.cpp index 925b118..707dd0a 100644 --- a/linden/indra/llui/lltextparser.cpp +++ b/linden/indra/llui/lltextparser.cpp @@ -1,6 +1,5 @@ /** - * @file lltexteditor.cpp - * @brief LLTextEditor base class + * @file lltextparser.cpp * * $LicenseInfo:firstyear=2001&license=viewergpl$ * @@ -32,6 +31,8 @@ #include "linden_common.h" +#include "lltextparser.h" + #include "llsd.h" #include "llsdserialize.h" #include "llerror.h" @@ -40,23 +41,13 @@ #include "message.h" #include "llmath.h" #include "v4color.h" -#include "audioengine.h" -#include "llwindow.h" #include "lldir.h" -#include "lltextparser.h" -//#include "lltexttospeech.h" - // Routines used for parsing text for TextParsers and html LLTextParser* LLTextParser::sInstance = NULL; // -// Constants -// -const F32 SOUND_GAIN = 1.0f; - -// // Member Functions // @@ -76,38 +67,7 @@ LLTextParser* LLTextParser::getInstance() return sInstance; } -void LLTextParser::triggerAlerts(LLUUID agent_id, LLVector3d position, std::string text, LLWindow* viewer_window) -{ -// bool spoken=FALSE; - for (S32 i=0;i<mHighlights.size();i++) - { - if (findPattern(text,mHighlights[i]) >= 0 ) - { - if(gAudiop) - { - if ((std::string)mHighlights[i]["sound_lluuid"] != LLUUID::null.asString()) - { - gAudiop->triggerSound(mHighlights[i]["sound_lluuid"].asUUID(), agent_id, SOUND_GAIN, LLAudioEngine::AUDIO_TYPE_UI, position); - } -/* - if (!spoken) - { - LLTextToSpeech* text_to_speech = NULL; - text_to_speech = LLTextToSpeech::getInstance(); - spoken = text_to_speech->speak((LLString)mHighlights[i]["voice"],text); - } - */ - } - if (mHighlights[i]["flash"]) - { - if (viewer_window && viewer_window->getMinimized()) - { - viewer_window->flashIcon(5.f); - } - } - } - } -} +// Moved triggerAlerts() to llfloaterchat.cpp to break llui/llaudio library dependency. S32 LLTextParser::findPattern(const std::string &text, LLSD highlight) { diff --git a/linden/indra/llui/lltextparser.h b/linden/indra/llui/lltextparser.h index d69e3a2..32343a2 100644 --- a/linden/indra/llui/lltextparser.h +++ b/linden/indra/llui/lltextparser.h @@ -34,12 +34,8 @@ #ifndef LL_LLTEXTPARSER_H #define LL_LLTEXTPARSER_H -#include <vector> -#include "linden_common.h" +#include "llsd.h" -#include "lltextparser.h" - -class LLSD; class LLUUID; class LLVector3d; class LLColor4; @@ -59,7 +55,6 @@ public: S32 findPattern(const std::string &text, LLSD highlight); LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color,S32 part=WHOLE, S32 index=0); bool parseFullLineHighlights(const std::string &text, LLColor4 *color); - void triggerAlerts(LLUUID agent_id, LLVector3d position, std::string text, LLWindow* viewer_window); std::string getFileName(); LLSD loadFromDisk(); diff --git a/linden/indra/llui/llui.cpp b/linden/indra/llui/llui.cpp index 57ce13c..75a4467 100644 --- a/linden/indra/llui/llui.cpp +++ b/linden/indra/llui/llui.cpp @@ -38,7 +38,6 @@ #include <map> // Linden library includes -#include "audioengine.h" #include "v2math.h" #include "v4color.h" #include "llrender.h" diff --git a/linden/indra/llui/lluictrl.cpp b/linden/indra/llui/lluictrl.cpp index 9d97312..3f4ab5e 100644 --- a/linden/indra/llui/lluictrl.cpp +++ b/linden/indra/llui/lluictrl.cpp @@ -39,54 +39,7 @@ static LLRegisterWidget<LLUICtrl> r("ui_ctrl"); -LLFocusableElement::LLFocusableElement() -: mFocusLostCallback(NULL), - mFocusReceivedCallback(NULL), - mFocusChangedCallback(NULL), - mFocusCallbackUserData(NULL) -{ -} - -//virtual -LLFocusableElement::~LLFocusableElement() -{ -} - -void LLFocusableElement::onFocusReceived() -{ - if( mFocusReceivedCallback ) - { - mFocusReceivedCallback( this, mFocusCallbackUserData ); - } - if( mFocusChangedCallback ) - { - mFocusChangedCallback( this, mFocusCallbackUserData ); - } -} - -void LLFocusableElement::onFocusLost() -{ - if( mFocusLostCallback ) - { - mFocusLostCallback( this, mFocusCallbackUserData ); - } - - if( mFocusChangedCallback ) - { - mFocusChangedCallback( this, mFocusCallbackUserData ); - } -} - -BOOL LLFocusableElement::hasFocus() const -{ - return FALSE; -} - -void LLFocusableElement::setFocus(BOOL b) -{ -} - - +// NOTE: the LLFocusableElement implementation has been moved to llfocusmgr.cpp, to mirror the header where the class is defined. LLUICtrl::LLUICtrl() : mCommitCallback(NULL), @@ -212,7 +165,7 @@ void LLUICtrl::onFocusReceived() // find first view in hierarchy above new focus that is a LLUICtrl LLView* viewp = getParent(); - LLUICtrl* last_focus = gFocusMgr.getLastKeyboardFocus(); + LLUICtrl* last_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getLastKeyboardFocus()); while (viewp && !viewp->isCtrl()) { @@ -590,6 +543,10 @@ void LLUICtrl::setDoubleClickCallback( void (*cb)(void*) ) // virtual void LLUICtrl::setColor(const LLColor4& color) { } +// virtual + +void LLUICtrl::setAlpha(F32 alpha) +{ } // virtual void LLUICtrl::setMinValue(LLSD min_value) diff --git a/linden/indra/llui/lluictrl.h b/linden/indra/llui/lluictrl.h index db41af8..be8e863 100644 --- a/linden/indra/llui/lluictrl.h +++ b/linden/indra/llui/lluictrl.h @@ -39,31 +39,8 @@ #include "llsd.h" -class LLFocusableElement -{ - friend class LLFocusMgr; // allow access to focus change handlers -public: - LLFocusableElement(); - virtual ~LLFocusableElement(); - - virtual void setFocus( BOOL b ); - virtual BOOL hasFocus() const; - - void setFocusLostCallback(void (*cb)(LLFocusableElement* caller, void*), void* user_data = NULL) { mFocusLostCallback = cb; mFocusCallbackUserData = user_data; } - void setFocusReceivedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL) { mFocusReceivedCallback = cb; mFocusCallbackUserData = user_data; } - void setFocusChangedCallback( void (*cb)(LLFocusableElement*, void*), void* user_data = NULL ) { mFocusChangedCallback = cb; mFocusCallbackUserData = user_data; } - -protected: - virtual void onFocusReceived(); - virtual void onFocusLost(); - void (*mFocusLostCallback)( LLFocusableElement* caller, void* userdata ); - void (*mFocusReceivedCallback)( LLFocusableElement* ctrl, void* userdata ); - void (*mFocusChangedCallback)( LLFocusableElement* ctrl, void* userdata ); - void* mFocusCallbackUserData; -}; - class LLUICtrl -: public LLView, public LLFocusableElement +: public LLView { public: typedef void (*LLUICtrlCallback)(LLUICtrl* ctrl, void* userdata); @@ -117,6 +94,7 @@ public: virtual void clear(); virtual void setDoubleClickCallback( void (*cb)(void*) ); virtual void setColor(const LLColor4& color); + virtual void setAlpha(F32 alpha); virtual void setMinValue(LLSD min_value); virtual void setMaxValue(LLSD max_value); diff --git a/linden/indra/llui/llview.cpp b/linden/indra/llui/llview.cpp index 8de376f..1f76696 100644 --- a/linden/indra/llui/llview.cpp +++ b/linden/indra/llui/llview.cpp @@ -136,11 +136,6 @@ LLView::~LLView() { //llinfos << "Deleting view " << mName << ":" << (void*) this << llendl; // llassert(LLView::sIsDrawing == FALSE); - if( gFocusMgr.getKeyboardFocus() == this ) - { - llwarns << "View holding keyboard focus deleted: " << getName() << ". Keyboard focus removed." << llendl; - gFocusMgr.removeKeyboardFocusWithoutCallback( this ); - } if( hasMouseCapture() ) { @@ -1327,7 +1322,7 @@ void LLView::draw() LLRect screenRect; // draw focused control on top of everything else - LLView* focus_view = gFocusMgr.getKeyboardFocus(); + LLUICtrl* focus_view = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); if (focus_view && focus_view->getParent() != this) { focus_view = NULL; diff --git a/linden/indra/llui/llview.h b/linden/indra/llui/llview.h index 7e09dfa..1c8ab31 100644 --- a/linden/indra/llui/llview.h +++ b/linden/indra/llui/llview.h @@ -53,6 +53,7 @@ #include "stdenums.h" #include "lluistring.h" #include "llcursortypes.h" +#include "llfocusmgr.h" const U32 FOLLOWS_NONE = 0x00; const U32 FOLLOWS_LEFT = 0x01; @@ -207,7 +208,7 @@ public: } }; -class LLView : public LLMouseHandler, public LLMortician +class LLView : public LLMouseHandler, public LLMortician, public LLFocusableElement { public: @@ -398,9 +399,11 @@ public: virtual BOOL canSnapTo(const LLView* other_view); virtual void snappedTo(const LLView* snap_view); + + // inherited from LLFocusableElement + /* virtual */ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + /* virtual */ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); - virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); - virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, @@ -421,8 +424,9 @@ public: BOOL getSaveToXML() const { return mSaveToXML; } void setSaveToXML(BOOL b) { mSaveToXML = b; } - virtual void onFocusLost(); - virtual void onFocusReceived(); + // inherited from LLFocusableElement + /* virtual */ void onFocusLost(); + /* virtual */ void onFocusReceived(); typedef enum e_hit_test_type { diff --git a/linden/indra/llvfs/CMakeLists.txt b/linden/indra/llvfs/CMakeLists.txt index cc0297e..d6a0bbc 100644 --- a/linden/indra/llvfs/CMakeLists.txt +++ b/linden/indra/llvfs/CMakeLists.txt @@ -4,7 +4,6 @@ project(llvfs) include(00-Common) include(LLCommon) -include(UnixInstall) include_directories( ${LLCOMMON_INCLUDE_DIRS} @@ -58,6 +57,7 @@ set_source_files_properties(${llvfs_HEADER_FILES} list(APPEND llvfs_SOURCE_FILES ${llvfs_HEADER_FILES}) add_library (llvfs ${llvfs_SOURCE_FILES}) +add_dependencies(llvfs prepare) if (DARWIN) include(CMakeFindFrameworks) diff --git a/linden/indra/llvfs/lldir.cpp b/linden/indra/llvfs/lldir.cpp index af55593..5567fdd 100644 --- a/linden/indra/llvfs/lldir.cpp +++ b/linden/indra/llvfs/lldir.cpp @@ -294,6 +294,10 @@ const std::string LLDir::getSkinBaseDir() const return dir; } +const std::string &LLDir::getLLPluginDir() const +{ + return mLLPluginDir; +} std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const { @@ -465,6 +469,8 @@ std::string LLDir::getDirName(const std::string& filepath) const std::string LLDir::getExtension(const std::string& filepath) const { + if (filepath.empty()) + return std::string(); std::string basename = getBaseFileName(filepath, false); std::size_t offset = basename.find_last_of('.'); std::string exten = (offset == std::string::npos || offset == 0) ? "" : basename.substr(offset+1); diff --git a/linden/indra/llvfs/lldir.h b/linden/indra/llvfs/lldir.h index 21dcf5b..55574d6 100644 --- a/linden/indra/llvfs/lldir.h +++ b/linden/indra/llvfs/lldir.h @@ -80,6 +80,10 @@ class LLDir virtual BOOL fileExists(const std::string &filename) const = 0; const std::string findFile(const std::string &filename, const std::string searchPath1 = "", const std::string searchPath2 = "", const std::string searchPath3 = "") const; + + virtual std::string getLLPluginLauncher() = 0; // full path and name for the plugin shell + virtual std::string getLLPluginFilename(std::string base_name) = 0; // full path and name to the plugin DSO for this base_name (i.e. 'FOO' -> '/bar/baz/libFOO.so') + const std::string &getExecutablePathAndName() const; // Full pathname of the executable const std::string &getAppName() const; // install directory under progams/ ie "SecondLife" const std::string &getExecutableDir() const; // Directory where the executable is located @@ -100,6 +104,7 @@ class LLDir const std::string &getUserSkinDir() const; // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin const std::string &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default const std::string getSkinBaseDir() const; // folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins + const std::string &getLLPluginDir() const; // Directory containing plugins and plugin shell // Expanded filename std::string getExpandedFilename(ELLPath location, const std::string &filename) const; @@ -156,6 +161,7 @@ protected: std::string mSkinDir; // Location for current skin info. std::string mDefaultSkinDir; // Location for default skin info. std::string mUserSkinDir; // Location for user-modified skin info. + std::string mLLPluginDir; // Location for plugins and plugin shell }; void dir_exists_or_crash(const std::string &dir_name); diff --git a/linden/indra/llvfs/lldir_linux.cpp b/linden/indra/llvfs/lldir_linux.cpp index 8ff8c5d..ec0a4f4 100644 --- a/linden/indra/llvfs/lldir_linux.cpp +++ b/linden/indra/llvfs/lldir_linux.cpp @@ -94,11 +94,7 @@ LLDir_Linux::LLDir_Linux() mExecutablePathAndName = ""; mExecutableDir = tmp_str; mWorkingDir = tmp_str; -#ifdef APP_RO_DATA_DIR - mAppRODataDir = APP_RO_DATA_DIR; -#else mAppRODataDir = tmp_str; -#endif mOSUserDir = getCurrentUserHome(tmp_str); mOSUserAppDir = ""; mLindenUserDir = tmp_str; @@ -128,6 +124,33 @@ LLDir_Linux::LLDir_Linux() } } + mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin"; + +#ifdef APP_RO_DATA_DIR + const char* appRODataDir = APP_RO_DATA_DIR; + if(appRODataDir[0] == '/') + { + // We have a full path to the data directory. + mAppRODataDir = appRODataDir; + } + else if(appRODataDir[0] != '\0') + { + // We have a relative path to the data directory. Search + // for it in each potential install prefix containing the + // executable. + for(std::string prefix = getDirName(mExecutableDir); + !prefix.empty(); prefix = getDirName(prefix)) + { + std::string dir = prefix + "/" + appRODataDir; + if(fileExists(dir + "/app_settings")) + { + mAppRODataDir = dir; + break; + } + } + } +#endif + // *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something. mTempDir = "/tmp"; } @@ -370,3 +393,15 @@ BOOL LLDir_Linux::fileExists(const std::string &filename) const } } + +/*virtual*/ std::string LLDir_Linux::getLLPluginLauncher() +{ + return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() + + "SLPlugin"; +} + +/*virtual*/ std::string LLDir_Linux::getLLPluginFilename(std::string base_name) +{ + return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + + "lib" + base_name + ".so"; +} diff --git a/linden/indra/llvfs/lldir_linux.h b/linden/indra/llvfs/lldir_linux.h index 20b408f..8e94fb1 100644 --- a/linden/indra/llvfs/lldir_linux.h +++ b/linden/indra/llvfs/lldir_linux.h @@ -52,6 +52,9 @@ public: virtual void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname); /*virtual*/ BOOL fileExists(const std::string &filename) const; + /*virtual*/ std::string getLLPluginLauncher(); + /*virtual*/ std::string getLLPluginFilename(std::string base_name); + private: DIR *mDirp; int mCurrentDirIndex; diff --git a/linden/indra/llvfs/lldir_mac.cpp b/linden/indra/llvfs/lldir_mac.cpp index 6d5dcf3..a45c1ed 100644 --- a/linden/indra/llvfs/lldir_mac.cpp +++ b/linden/indra/llvfs/lldir_mac.cpp @@ -190,6 +190,8 @@ LLDir_Mac::LLDir_Mac() } mWorkingDir = getCurPath(); + + mLLPluginDir = mAppRODataDir + mDirDelimiter + "llplugin"; CFRelease(executableURLRef); executableURLRef = NULL; @@ -388,4 +390,17 @@ BOOL LLDir_Mac::fileExists(const std::string &filename) const } +/*virtual*/ std::string LLDir_Mac::getLLPluginLauncher() +{ + return gDirUtilp->getAppRODataDir() + gDirUtilp->getDirDelimiter() + + "SLPlugin"; +} + +/*virtual*/ std::string LLDir_Mac::getLLPluginFilename(std::string base_name) +{ + return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + + base_name + ".dylib"; +} + + #endif // LL_DARWIN diff --git a/linden/indra/llvfs/lldir_mac.h b/linden/indra/llvfs/lldir_mac.h index 28d48a0..8be5d03 100644 --- a/linden/indra/llvfs/lldir_mac.h +++ b/linden/indra/llvfs/lldir_mac.h @@ -52,6 +52,9 @@ public: virtual void getRandomFileInDir(const std::string &dirname, const std::string &ask, std::string &fname); virtual BOOL fileExists(const std::string &filename) const; + /*virtual*/ std::string getLLPluginLauncher(); + /*virtual*/ std::string getLLPluginFilename(std::string base_name); + private: int mCurrentDirIndex; int mCurrentDirCount; diff --git a/linden/indra/llvfs/lldir_solaris.cpp b/linden/indra/llvfs/lldir_solaris.cpp index 9553d92..c647e2b 100644 --- a/linden/indra/llvfs/lldir_solaris.cpp +++ b/linden/indra/llvfs/lldir_solaris.cpp @@ -161,6 +161,8 @@ LLDir_Solaris::LLDir_Solaris() } } + mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin"; + // *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something. mTempDir = "/tmp"; } diff --git a/linden/indra/llvfs/lldir_win32.cpp b/linden/indra/llvfs/lldir_win32.cpp index 19b9bcc..9d4c5ec 100644 --- a/linden/indra/llvfs/lldir_win32.cpp +++ b/linden/indra/llvfs/lldir_win32.cpp @@ -143,6 +143,8 @@ LLDir_Win32::LLDir_Win32() llwarns << "Couldn't create LL_PATH_CACHE dir " << mDefaultCacheDir << llendl; } } + + mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin"; } LLDir_Win32::~LLDir_Win32() @@ -378,6 +380,19 @@ BOOL LLDir_Win32::fileExists(const std::string &filename) const } +/*virtual*/ std::string LLDir_Win32::getLLPluginLauncher() +{ + return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() + + "SLPlugin.exe"; +} + +/*virtual*/ std::string LLDir_Win32::getLLPluginFilename(std::string base_name) +{ + return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() + + base_name + ".dll"; +} + + #if 0 // Utility function to get version number of a DLL diff --git a/linden/indra/llvfs/lldir_win32.h b/linden/indra/llvfs/lldir_win32.h index 8710ca5..9ef4d30 100644 --- a/linden/indra/llvfs/lldir_win32.h +++ b/linden/indra/llvfs/lldir_win32.h @@ -49,6 +49,9 @@ public: /*virtual*/ void getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname); /*virtual*/ BOOL fileExists(const std::string &filename) const; + /*virtual*/ std::string getLLPluginLauncher(); + /*virtual*/ std::string getLLPluginFilename(std::string base_name); + private: BOOL LLDir_Win32::getNextFileInDir(const llutf16string &dirname, const std::string &mask, std::string &fname, BOOL wrap); diff --git a/linden/indra/llwindow/CMakeLists.txt b/linden/indra/llwindow/CMakeLists.txt index afce0c0..5224163 100644 --- a/linden/indra/llwindow/CMakeLists.txt +++ b/linden/indra/llwindow/CMakeLists.txt @@ -19,7 +19,6 @@ include(LLRender) include(LLVFS) include(LLWindow) include(LLXML) -include(Mozlib) include(UI) include_directories( @@ -55,6 +54,13 @@ set(viewer_HEADER_FILES llmousehandler.h ) +# Libraries on which this library depends, needed for Linux builds +# Sort by high-level to low-level +set(llwindow_LINK_LIBRARIES + ${UI_LIBRARIES} # for GTK + ${SDL_LIBRARY} + ) + if (DARWIN) list(APPEND llwindow_SOURCE_FILES llkeyboardmacosx.cpp @@ -98,6 +104,9 @@ if (WINDOWS) lldxhardware.h llkeyboardwin32.h ) + list(APPEND llwindow_LINK_LIBRARIES + comdlg32 # Common Dialogs for ChooseColor + ) endif (WINDOWS) if (SOLARIS) @@ -134,6 +143,7 @@ if (SERVER AND NOT WINDOWS AND NOT DARWIN) ${server_SOURCE_FILES} ) endif (SERVER AND NOT WINDOWS AND NOT DARWIN) + # *TODO: This should probably have target_link_libraries if (llwindow_HEADER_FILES) list(APPEND llwindow_SOURCE_FILES ${llwindow_HEADER_FILES}) @@ -145,4 +155,6 @@ if (VIEWER) ${llwindow_SOURCE_FILES} ${viewer_SOURCE_FILES} ) + target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES}) endif (VIEWER) + diff --git a/linden/indra/media_plugins/CMakeLists.txt b/linden/indra/media_plugins/CMakeLists.txt new file mode 100644 index 0000000..d35afd8 --- /dev/null +++ b/linden/indra/media_plugins/CMakeLists.txt @@ -0,0 +1,11 @@ +# -*- cmake -*- + +add_subdirectory(base) + +add_subdirectory(webkit) + +add_subdirectory(gstreamer010) + +if (WINDOWS OR DARWIN) + add_subdirectory(quicktime) +endif (WINDOWS OR DARWIN) diff --git a/linden/indra/media_plugins/base/CMakeLists.txt b/linden/indra/media_plugins/base/CMakeLists.txt new file mode 100644 index 0000000..f8d2dab --- /dev/null +++ b/linden/indra/media_plugins/base/CMakeLists.txt @@ -0,0 +1,41 @@ +# -*- cmake -*- + +project(media_plugin_base) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLPlugin) +include(LLMath) +include(LLRender) +include(LLWindow) +include(Linking) +include(PluginAPI) +include(FindOpenGL) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} +) + + +### media_plugin_base + +set(media_plugin_base_SOURCE_FILES + media_plugin_base.cpp +) + +set(media_plugin_base_HEADER_FILES + CMakeLists.txt + + media_plugin_base.h +) + +add_library(media_plugin_base + ${media_plugin_base_SOURCE_FILES} +) + diff --git a/linden/indra/media_plugins/base/media_plugin_base.cpp b/linden/indra/media_plugins/base/media_plugin_base.cpp new file mode 100644 index 0000000..1919419 --- /dev/null +++ b/linden/indra/media_plugins/base/media_plugin_base.cpp @@ -0,0 +1,155 @@ +/** + * @file media_plugin_base.cpp + * @brief Media plugin base class for LLMedia API plugin system + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "media_plugin_base.h" + + +// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint +//////////////////////////////////////////////////////////////////////////////// +// + +MediaPluginBase::MediaPluginBase( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) +{ + mHostSendFunction = host_send_func; + mHostUserData = host_user_data; + mDeleteMe = false; + mPixels = 0; + mWidth = 0; + mHeight = 0; + mTextureWidth = 0; + mTextureHeight = 0; + mDepth = 0; + mStatus = STATUS_NONE; +} + +std::string MediaPluginBase::statusString() +{ + std::string result; + + switch(mStatus) + { + case STATUS_LOADING: result = "loading"; break; + case STATUS_LOADED: result = "loaded"; break; + case STATUS_ERROR: result = "error"; break; + case STATUS_PLAYING: result = "playing"; break; + case STATUS_PAUSED: result = "paused"; break; + default: + // keep the empty string + break; + } + + return result; +} + +void MediaPluginBase::setStatus(EStatus status) +{ + if(mStatus != status) + { + mStatus = status; + sendStatus(); + } +} + + +void MediaPluginBase::staticReceiveMessage(const char *message_string, void **user_data) +{ + MediaPluginBase *self = (MediaPluginBase*)*user_data; + + if(self != NULL) + { + self->receiveMessage(message_string); + + // If the plugin has processed the delete message, delete it. + if(self->mDeleteMe) + { + delete self; + *user_data = NULL; + } + } +} + +void MediaPluginBase::sendMessage(const LLPluginMessage &message) +{ + std::string output = message.generate(); + mHostSendFunction(output.c_str(), &mHostUserData); +} + +void MediaPluginBase::setDirty(int left, int top, int right, int bottom) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); + + message.setValueS32("left", left); + message.setValueS32("top", top); + message.setValueS32("right", right); + message.setValueS32("bottom", bottom); + + sendMessage(message); +} + +void MediaPluginBase::sendStatus() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "media_status"); + + message.setValue("status", statusString()); + + sendMessage(message); +} + + +#if LL_WINDOWS +# define LLSYMEXPORT __declspec(dllexport) +#elif LL_LINUX +# define LLSYMEXPORT __attribute__ ((visibility("default"))) +#else +# define LLSYMEXPORT /**/ +#endif + +extern "C" +{ + LLSYMEXPORT int LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data); +} + +LLSYMEXPORT int +LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + return init_media_plugin(host_send_func, host_user_data, plugin_send_func, plugin_user_data); +} + +#ifdef WIN32 +int WINAPI DllEntryPoint( HINSTANCE hInstance, unsigned long reason, void* params ) +{ + return 1; +} +#endif diff --git a/linden/indra/media_plugins/base/media_plugin_base.exp b/linden/indra/media_plugins/base/media_plugin_base.exp new file mode 100644 index 0000000..1e27d1f --- /dev/null +++ b/linden/indra/media_plugins/base/media_plugin_base.exp @@ -0,0 +1 @@ +_LLPluginInitEntryPoint diff --git a/linden/indra/media_plugins/base/media_plugin_base.h b/linden/indra/media_plugins/base/media_plugin_base.h new file mode 100644 index 0000000..4872706 --- /dev/null +++ b/linden/indra/media_plugins/base/media_plugin_base.h @@ -0,0 +1,112 @@ +/** + * @file media_plugin_base.h + * @brief Media plugin base class for LLMedia API plugin system + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" + + +class MediaPluginBase +{ +public: + MediaPluginBase(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + virtual ~MediaPluginBase() {} + + virtual void receiveMessage(const char *message_string) = 0; + + static void staticReceiveMessage(const char *message_string, void **user_data); + +protected: + + typedef enum + { + STATUS_NONE, + STATUS_LOADING, + STATUS_LOADED, + STATUS_ERROR, + STATUS_PLAYING, + STATUS_PAUSED, + } EStatus; + + class SharedSegmentInfo + { + public: + void *mAddress; + size_t mSize; + }; + + void sendMessage(const LLPluginMessage &message); + void sendStatus(); + std::string statusString(); + void setStatus(EStatus status); + + // The quicktime plugin overrides this to add current time and duration to the message... + virtual void setDirty(int left, int top, int right, int bottom); + + typedef std::map<std::string, SharedSegmentInfo> SharedSegmentMap; + + + LLPluginInstance::sendMessageFunction mHostSendFunction; + void *mHostUserData; + bool mDeleteMe; + unsigned char* mPixels; + std::string mTextureSegmentName; + int mWidth; + int mHeight; + int mTextureWidth; + int mTextureHeight; + int mDepth; + EStatus mStatus; + SharedSegmentMap mSharedSegments; + +}; + +// The plugin must define this function to create its instance. +int init_media_plugin( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data); + +// It should look something like this: +/* +{ + MediaPluginFoo *self = new MediaPluginFoo(host_send_func, host_user_data); + *plugin_send_func = MediaPluginFoo::staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; +} +*/ + diff --git a/linden/indra/media_plugins/example/CMakeLists.txt b/linden/indra/media_plugins/example/CMakeLists.txt new file mode 100644 index 0000000..4d82f27 --- /dev/null +++ b/linden/indra/media_plugins/example/CMakeLists.txt @@ -0,0 +1,74 @@ +# -*- cmake -*- + +project(media_plugin_example) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLPlugin) +include(LLMath) +include(LLRender) +include(LLWindow) +include(Linking) +include(PluginAPI) +include(MediaPluginBase) +include(FindOpenGL) + +include(ExamplePlugin) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} +) + + +### media_plugin_example + +set(media_plugin_example_SOURCE_FILES + media_plugin_example.cpp + ) + +add_library(media_plugin_example + SHARED + ${media_plugin_example_SOURCE_FILES} +) + +target_link_libraries(media_plugin_example + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${EXAMPLE_PLUGIN_LIBRARIES} + ${PLUGIN_API_WINDOWS_LIBRARIES} +) + +add_dependencies(media_plugin_example + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} +) + +if (WINDOWS) + set_target_properties( + media_plugin_example + PROPERTIES + LINK_FLAGS "/MANIFEST:NO" + ) +endif (WINDOWS) + +if (DARWIN) + # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name + set_target_properties( + media_plugin_example + PROPERTIES + PREFIX "" + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path" + LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" + ) + +endif (DARWIN) \ No newline at end of file diff --git a/linden/indra/media_plugins/example/media_plugin_example.cpp b/linden/indra/media_plugins/example/media_plugin_example.cpp new file mode 100644 index 0000000..99e0199 --- /dev/null +++ b/linden/indra/media_plugins/example/media_plugin_example.cpp @@ -0,0 +1,488 @@ +/** + * @file media_plugin_example.cpp + * @brief Example plugin for LLMedia API plugin system + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llgl.h" +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#include <time.h> + +//////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginExample : + public MediaPluginBase +{ + public: + MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ); + ~MediaPluginExample(); + + /*virtual*/ void receiveMessage( const char* message_string ); + + private: + bool init(); + void update( F64 milliseconds ); + void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ); + bool mFirstTime; + + time_t mLastUpdateTime; + enum Constants { ENumObjects = 10 }; + unsigned char* mBackgroundPixels; + int mColorR[ ENumObjects ]; + int mColorG[ ENumObjects ]; + int mColorB[ ENumObjects ]; + int mXpos[ ENumObjects ]; + int mYpos[ ENumObjects ]; + int mXInc[ ENumObjects ]; + int mYInc[ ENumObjects ]; + int mBlockSize[ ENumObjects ]; + bool mMouseButtonDown; + bool mStopAction; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginExample::MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) : + MediaPluginBase( host_send_func, host_user_data ) +{ + mFirstTime = true; + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; + mMouseButtonDown = false; + mStopAction = false; + mLastUpdateTime = 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// +MediaPluginExample::~MediaPluginExample() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginExample::receiveMessage( const char* message_string ) +{ + LLPluginMessage message_in; + + if ( message_in.parse( message_string ) >= 0 ) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + + if ( message_class == LLPLUGIN_MESSAGE_CLASS_BASE ) + { + if ( message_name == "init" ) + { + LLPluginMessage message( "base", "init_response" ); + LLSD versions = LLSD::emptyMap(); + versions[ LLPLUGIN_MESSAGE_CLASS_BASE ] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + message.setValueLLSD( "versions", versions ); + + std::string plugin_version = "Example media plugin, Example Version 1.0.0.0"; + message.setValue( "plugin_version", plugin_version ); + sendMessage( message ); + + // Plugin gets to decide the texture parameters to use. + message.setMessage( LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params" ); + message.setValueS32( "default_width", mWidth ); + message.setValueS32( "default_height", mHeight ); + message.setValueS32( "depth", mDepth ); + message.setValueU32( "internalformat", GL_RGBA ); + message.setValueU32( "format", GL_RGBA ); + message.setValueU32( "type", GL_UNSIGNED_BYTE ); + message.setValueBoolean( "coords_opengl", false ); + sendMessage( message ); + } + else + if ( message_name == "idle" ) + { + // no response is necessary here. + F64 time = message_in.getValueReal( "time" ); + + // Convert time to milliseconds for update() + update( time ); + } + else + if ( message_name == "cleanup" ) + { + // clean up here + } + else + if ( message_name == "shm_added" ) + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer( "address" ); + info.mSize = ( size_t )message_in.getValueS32( "size" ); + std::string name = message_in.getValue( "name" ); + + mSharedSegments.insert( SharedSegmentMap::value_type( name, info ) ); + + } + else + if ( message_name == "shm_remove" ) + { + std::string name = message_in.getValue( "name" ); + + SharedSegmentMap::iterator iter = mSharedSegments.find( name ); + if( iter != mSharedSegments.end() ) + { + if ( mPixels == iter->second.mAddress ) + { + // This is the currently active pixel buffer. + // Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + }; + mSharedSegments.erase( iter ); + } + else + { + //std::cerr << "MediaPluginExample::receiveMessage: unknown shared memory region!" << std::endl; + }; + + // Send the response so it can be cleaned up. + LLPluginMessage message( "base", "shm_remove_response" ); + message.setValue( "name", name ); + sendMessage( message ); + } + else + { + //std::cerr << "MediaPluginExample::receiveMessage: unknown base message: " << message_name << std::endl; + }; + } + else + if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA ) + { + if ( message_name == "size_change" ) + { + std::string name = message_in.getValue( "name" ); + S32 width = message_in.getValueS32( "width" ); + S32 height = message_in.getValueS32( "height" ); + S32 texture_width = message_in.getValueS32( "texture_width" ); + S32 texture_height = message_in.getValueS32( "texture_height" ); + + if ( ! name.empty() ) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find( name ); + if ( iter != mSharedSegments.end() ) + { + mPixels = ( unsigned char* )iter->second.mAddress; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + + init(); + }; + }; + + LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response" ); + message.setValue( "name", name ); + message.setValueS32( "width", width ); + message.setValueS32( "height", height ); + message.setValueS32( "texture_width", texture_width ); + message.setValueS32( "texture_height", texture_height ); + sendMessage( message ); + } + else + if ( message_name == "load_uri" ) + { + std::string uri = message_in.getValue( "uri" ); + if ( ! uri.empty() ) + { + }; + } + else + if ( message_name == "mouse_event" ) + { + std::string event = message_in.getValue( "event" ); + S32 button = message_in.getValueS32( "button" ); + + // left mouse button + if ( button == 0 ) + { + int mouse_x = message_in.getValueS32( "x" ); + int mouse_y = message_in.getValueS32( "y" ); + std::string modifiers = message_in.getValue( "modifiers" ); + + if ( event == "move" ) + { + if ( mMouseButtonDown ) + write_pixel( mouse_x, mouse_y, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80 ); + } + else + if ( event == "down" ) + { + mMouseButtonDown = true; + } + else + if ( event == "up" ) + { + mMouseButtonDown = false; + } + else + if ( event == "double_click" ) + { + }; + }; + } + else + if ( message_name == "key_event" ) + { + std::string event = message_in.getValue( "event" ); + S32 key = message_in.getValueS32( "key" ); + std::string modifiers = message_in.getValue( "modifiers" ); + + if ( event == "down" ) + { + if ( key == ' ') + { + mLastUpdateTime = 0; + update( 0.0f ); + }; + }; + } + else + { + //std::cerr << "MediaPluginExample::receiveMessage: unknown media message: " << message_string << std::endl; + }; + } + else + if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER ) + { + if ( message_name == "browse_reload" ) + { + mLastUpdateTime = 0; + mFirstTime = true; + mStopAction = false; + update( 0.0f ); + } + else + if ( message_name == "browse_stop" ) + { + for( int n = 0; n < ENumObjects; ++n ) + mXInc[ n ] = mYInc[ n ] = 0; + + mStopAction = true; + update( 0.0f ); + } + else + { + //std::cerr << "MediaPluginExample::receiveMessage: unknown media_browser message: " << message_string << std::endl; + }; + } + else + { + //std::cerr << "MediaPluginExample::receiveMessage: unknown message class: " << message_class << std::endl; + }; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginExample::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ) +{ + // make sure we don't write outside the buffer + if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) ) + return; + + if ( mBackgroundPixels != NULL ) + { + unsigned char *pixel = mBackgroundPixels; + pixel += y * mWidth * mDepth; + pixel += ( x * mDepth ); + pixel[ 0 ] = b; + pixel[ 1 ] = g; + pixel[ 2 ] = r; + + setDirty( x, y, x + 1, y + 1 ); + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginExample::update( F64 milliseconds ) +{ + if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 ) + return; + + if ( mPixels == 0 ) + return; + + if ( mFirstTime ) + { + for( int n = 0; n < ENumObjects; ++n ) + { + mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 ); + mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 ); + + mColorR[ n ] = rand() % 0x60 + 0x60; + mColorG[ n ] = rand() % 0x60 + 0x60; + mColorB[ n ] = rand() % 0x60 + 0x60; + + mXInc[ n ] = 0; + while ( mXInc[ n ] == 0 ) + mXInc[ n ] = rand() % 7 - 3; + + mYInc[ n ] = 0; + while ( mYInc[ n ] == 0 ) + mYInc[ n ] = rand() % 9 - 4; + + mBlockSize[ n ] = rand() % 0x30 + 0x10; + }; + + delete [] mBackgroundPixels; + + mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ]; + + mFirstTime = false; + }; + + if ( mStopAction ) + return; + + if ( time( NULL ) > mLastUpdateTime + 3 ) + { + const int num_squares = rand() % 20 + 4; + int sqr1_r = rand() % 0x80 + 0x20; + int sqr1_g = rand() % 0x80 + 0x20; + int sqr1_b = rand() % 0x80 + 0x20; + int sqr2_r = rand() % 0x80 + 0x20; + int sqr2_g = rand() % 0x80 + 0x20; + int sqr2_b = rand() % 0x80 + 0x20; + + for ( int y1 = 0; y1 < num_squares; ++y1 ) + { + for ( int x1 = 0; x1 < num_squares; ++x1 ) + { + int px_start = mWidth * x1 / num_squares; + int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares; + int py_start = mHeight * y1 / num_squares; + int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares; + + for( int y2 = py_start; y2 < py_end; ++y2 ) + { + for( int x2 = px_start; x2 < px_end; ++x2 ) + { + int rowspan = mWidth * mDepth; + + if ( ( y1 % 2 ) ^ ( x1 % 2 ) ) + { + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b; + } + else + { + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b; + }; + }; + }; + }; + }; + + time( &mLastUpdateTime ); + }; + + memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth ); + + for( int n = 0; n < ENumObjects; ++n ) + { + if ( rand() % 50 == 0 ) + { + mXInc[ n ] = 0; + while ( mXInc[ n ] == 0 ) + mXInc[ n ] = rand() % 7 - 3; + + mYInc[ n ] = 0; + while ( mYInc[ n ] == 0 ) + mYInc[ n ] = rand() % 9 - 4; + }; + + if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] ) + mXInc[ n ] =- mXInc[ n ]; + + if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] ) + mYInc[ n ] =- mYInc[ n ]; + + mXpos[ n ] += mXInc[ n ]; + mYpos[ n ] += mYInc[ n ]; + + for( int y = 0; y < mBlockSize[ n ]; ++y ) + { + for( int x = 0; x < mBlockSize[ n ]; ++x ) + { + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ]; + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ]; + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ]; + }; + }; + }; + + setDirty( 0, 0, mWidth, mHeight ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +bool MediaPluginExample::init() +{ + LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" ); + message.setValue( "name", "Example Plugin" ); + sendMessage( message ); + + return true; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func, + void* host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data ) +{ + MediaPluginExample* self = new MediaPluginExample( host_send_func, host_user_data ); + *plugin_send_func = MediaPluginExample::staticReceiveMessage; + *plugin_user_data = ( void* )self; + + return 0; +} diff --git a/linden/indra/media_plugins/gstreamer010/CMakeLists.txt b/linden/indra/media_plugins/gstreamer010/CMakeLists.txt new file mode 100644 index 0000000..a3a32d8 --- /dev/null +++ b/linden/indra/media_plugins/gstreamer010/CMakeLists.txt @@ -0,0 +1,71 @@ +# -*- cmake -*- + +project(media_plugin_gstreamer010) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLPlugin) +include(LLMath) +include(LLRender) +include(LLWindow) +include(Linking) +include(PluginAPI) +include(MediaPluginBase) +include(FindOpenGL) + +include(GStreamer010Plugin) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} + ${GSTREAMER010_INCLUDE_DIRS} + ${GSTREAMER010_PLUGINS_BASE_INCLUDE_DIRS} +) + +### media_plugin_gstreamer010 + +set(media_plugin_gstreamer010_SOURCE_FILES + media_plugin_gstreamer010.cpp + llmediaimplgstreamer_syms.cpp + llmediaimplgstreamervidplug.cpp + ) + +set(media_plugin_gstreamer010_HEADER_FILES + llmediaimplgstreamervidplug.h + llmediaimplgstreamer_syms.h + llmediaimplgstreamertriviallogging.h + ) + +#awfixme if (${CXX_VERSION_NUMBER} MATCHES "4[23].") + # Work around a bad interaction between broken gstreamer headers and + # g++ 4.3's increased strictness. + set_source_files_properties(llmediaimplgstreamervidplug.cpp PROPERTIES + COMPILE_FLAGS -Wno-write-strings) +#awfixme endif (${CXX_VERSION_NUMBER} MATCHES "4[23].") + +add_library(media_plugin_gstreamer010 + SHARED + ${media_plugin_gstreamer010_SOURCE_FILES} +) + +target_link_libraries(media_plugin_gstreamer010 + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${PLUGIN_API_WINDOWS_LIBRARIES} + ${GSTREAMER010_LIBRARIES} +) + +add_dependencies(media_plugin_gstreamer010 + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} +) + + diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h new file mode 100644 index 0000000..ef41736 --- /dev/null +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h @@ -0,0 +1,57 @@ +/** + * @file llmediaimplgstreamer.h + * @author Tofu Linden + * @brief implementation that supports media playback via GStreamer. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// header guard +#ifndef llmediaimplgstreamer_h +#define llmediaimplgstreamer_h + +#if LL_GSTREAMER010_ENABLED + +extern "C" { +#include <stdio.h> +#include <gst/gst.h> + +#include "apr_pools.h" +#include "apr_dso.h" +} + + +extern "C" { +gboolean llmediaimplgstreamer_bus_callback (GstBus *bus, + GstMessage *message, + gpointer data); +} + +#endif // LL_GSTREAMER010_ENABLED + +#endif // llmediaimplgstreamer_h diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp new file mode 100644 index 0000000..cc52232 --- /dev/null +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp @@ -0,0 +1,171 @@ +/** + * @file llmediaimplgstreamer_syms.cpp + * @brief dynamic GStreamer symbol-grabbing code + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if LL_GSTREAMER010_ENABLED + +#include <string> + +extern "C" { +#include <gst/gst.h> + +#include "apr_pools.h" +#include "apr_dso.h" +} + +#include "llmediaimplgstreamertriviallogging.h" + +#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL +#include "llmediaimplgstreamer_syms_raw.inc" +#include "llmediaimplgstreamer_syms_rawv.inc" +#undef LL_GST_SYM + +// a couple of stubs for disgusting reasons +GstDebugCategory* +ll_gst_debug_category_new(gchar *name, guint color, gchar *description) +{ + static GstDebugCategory dummy; + return &dummy; +} +void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname) +{ +} + +static bool sSymsGrabbed = false; +static apr_pool_t *sSymGSTDSOMemoryPool = NULL; +static apr_dso_handle_t *sSymGSTDSOHandleG = NULL; +static apr_dso_handle_t *sSymGSTDSOHandleV = NULL; + + +bool grab_gst_syms(std::string gst_dso_name, + std::string gst_dso_name_vid) +{ + if (sSymsGrabbed) + { + // already have grabbed good syms + return TRUE; + } + + bool sym_error = false; + bool rtn = false; + apr_status_t rv; + apr_dso_handle_t *sSymGSTDSOHandle = NULL; + +#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##GSTSYM, sSymGSTDSOHandle, #GSTSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #GSTSYM); if (REQ) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #GSTSYM, (void*)ll##GSTSYM);}while(0) + + //attempt to load the shared libraries + apr_pool_create(&sSymGSTDSOMemoryPool, NULL); + + if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle, + gst_dso_name.c_str(), + sSymGSTDSOMemoryPool) )) + { + INFOMSG("Found DSO: %s", gst_dso_name.c_str()); +#include "llmediaimplgstreamer_syms_raw.inc" + + if ( sSymGSTDSOHandle ) + { + sSymGSTDSOHandleG = sSymGSTDSOHandle; + sSymGSTDSOHandle = NULL; + } + + if ( APR_SUCCESS == + (rv = apr_dso_load(&sSymGSTDSOHandle, + gst_dso_name_vid.c_str(), + sSymGSTDSOMemoryPool) )) + { + INFOMSG("Found DSO: %s", gst_dso_name_vid.c_str()); +#include "llmediaimplgstreamer_syms_rawv.inc" + rtn = !sym_error; + } + else + { + INFOMSG("Couldn't load DSO: %s", gst_dso_name_vid.c_str()); + rtn = false; // failure + } + } + else + { + INFOMSG("Couldn't load DSO: %s", gst_dso_name.c_str()); + rtn = false; // failure + } + + if (sym_error) + { + WARNMSG("Failed to find necessary symbols in GStreamer libraries."); + } + + if ( sSymGSTDSOHandle ) + { + sSymGSTDSOHandleV = sSymGSTDSOHandle; + sSymGSTDSOHandle = NULL; + } +#undef LL_GST_SYM + + sSymsGrabbed = !!rtn; + return rtn; +} + + +void ungrab_gst_syms() +{ + // should be safe to call regardless of whether we've + // actually grabbed syms. + + if ( sSymGSTDSOHandleG ) + { + apr_dso_unload(sSymGSTDSOHandleG); + sSymGSTDSOHandleG = NULL; + } + + if ( sSymGSTDSOHandleV ) + { + apr_dso_unload(sSymGSTDSOHandleV); + sSymGSTDSOHandleV = NULL; + } + + if ( sSymGSTDSOMemoryPool ) + { + apr_pool_destroy(sSymGSTDSOMemoryPool); + sSymGSTDSOMemoryPool = NULL; + } + + // NULL-out all of the symbols we'd grabbed +#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{ll##GSTSYM = NULL;}while(0) +#include "llmediaimplgstreamer_syms_raw.inc" +#include "llmediaimplgstreamer_syms_rawv.inc" +#undef LL_GST_SYM + + sSymsGrabbed = false; +} + + +#endif // LL_GSTREAMER010_ENABLED diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h new file mode 100644 index 0000000..ee7473d --- /dev/null +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h @@ -0,0 +1,78 @@ +/** + * @file llmediaimplgstreamer_syms.h + * @brief dynamic GStreamer symbol-grabbing code + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#if LL_GSTREAMER010_ENABLED + +extern "C" { +#include <gst/gst.h> +} + +bool grab_gst_syms(std::string gst_dso_name, + std::string gst_dso_name_vid); +void ungrab_gst_syms(); + +#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__) +#include "llmediaimplgstreamer_syms_raw.inc" +#include "llmediaimplgstreamer_syms_rawv.inc" +#undef LL_GST_SYM + +// regrettable hacks to give us better runtime compatibility with older systems +#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0) +#define llg_return_val_if_fail(COND,V) do{if (!(COND)) return V;}while(0) + +// regrettable hacks because GStreamer was not designed for runtime loading +#undef GST_TYPE_MESSAGE +#define GST_TYPE_MESSAGE (llgst_message_get_type()) +#undef GST_TYPE_OBJECT +#define GST_TYPE_OBJECT (llgst_object_get_type()) +#undef GST_TYPE_PIPELINE +#define GST_TYPE_PIPELINE (llgst_pipeline_get_type()) +#undef GST_TYPE_ELEMENT +#define GST_TYPE_ELEMENT (llgst_element_get_type()) +#undef GST_TYPE_VIDEO_SINK +#define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type()) +// more regrettable hacks to stub-out these .h-exposed GStreamer internals +void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname); +#undef _gst_debug_register_funcptr +#define _gst_debug_register_funcptr ll_gst_debug_register_funcptr +GstDebugCategory* ll_gst_debug_category_new(gchar *name, guint color, gchar *description); +#undef _gst_debug_category_new +#define _gst_debug_category_new ll_gst_debug_category_new +#undef __gst_debug_enabled +#define __gst_debug_enabled (0) + +// more hacks +#define LLGST_MESSAGE_TYPE_NAME(M) (llgst_message_type_get_name(GST_MESSAGE_TYPE(M))) + +#endif // LL_GSTREAMER010_ENABLED diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc new file mode 100644 index 0000000..b33e593 --- /dev/null +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc @@ -0,0 +1,51 @@ + +// required symbols to grab +LL_GST_SYM(true, gst_pad_peer_accept_caps, gboolean, GstPad *pad, GstCaps *caps); +LL_GST_SYM(true, gst_buffer_new, GstBuffer*, void); +LL_GST_SYM(true, gst_buffer_set_caps, void, GstBuffer*, GstCaps *); +LL_GST_SYM(true, gst_structure_set_value, void, GstStructure *, const gchar *, const GValue*); +LL_GST_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err); +LL_GST_SYM(true, gst_message_get_type, GType, void); +LL_GST_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type); +LL_GST_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug); +LL_GST_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug); +LL_GST_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending); +LL_GST_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state); +LL_GST_SYM(true, gst_object_unref, void, gpointer object); +LL_GST_SYM(true, gst_object_get_type, GType, void); +LL_GST_SYM(true, gst_pipeline_get_type, GType, void); +LL_GST_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline); +LL_GST_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data); +LL_GST_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name); +LL_GST_SYM(true, gst_element_get_type, GType, void); +LL_GST_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template); +LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp); +LL_GST_SYM(true, gst_element_class_set_details, void, GstElementClass *klass, const GstElementDetails *details); +LL_GST_SYM(true, gst_caps_unref, void, GstCaps* caps); +LL_GST_SYM(true, gst_caps_ref, GstCaps *, GstCaps* caps); +//LL_GST_SYM(true, gst_caps_is_empty, gboolean, const GstCaps *caps); +LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string); +LL_GST_SYM(true, gst_caps_replace, void, GstCaps **caps, GstCaps *newcaps); +LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index); +LL_GST_SYM(true, gst_caps_copy, GstCaps *, const GstCaps * caps); +//LL_GST_SYM(true, gst_caps_intersect, GstCaps *, const GstCaps *caps1, const GstCaps *caps2); +LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type); +LL_GST_SYM(true, _gst_plugin_register_static, void, GstPluginDesc *desc); +LL_GST_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value); +LL_GST_SYM(true, gst_structure_get_value, G_CONST_RETURN GValue *, const GstStructure *structure, const gchar *fieldname); +LL_GST_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value); +LL_GST_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value); +LL_GST_SYM(true, gst_structure_get_name, G_CONST_RETURN gchar *, const GstStructure *structure); +LL_GST_SYM(true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64); + +// optional symbols to grab +LL_GST_SYM(false, gst_registry_fork_set_enabled, void, gboolean enabled); +LL_GST_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled); +LL_GST_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent); +LL_GST_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug); +LL_GST_SYM(false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur); +LL_GST_SYM(false, gst_version, void, guint *major, guint *minor, guint *micro, guint *nano); + +// GStreamer 'internal' symbols which may not be visible in some runtimes but are still used in expanded GStreamer header macros - yuck! We'll substitute our own stubs for these. +//LL_GST_SYM(true, _gst_debug_register_funcptr, void, GstDebugFuncPtr func, gchar* ptrname); +//LL_GST_SYM(true, _gst_debug_category_new, GstDebugCategory *, gchar *name, guint color, gchar *description); diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc new file mode 100644 index 0000000..14fbcb4 --- /dev/null +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc @@ -0,0 +1,5 @@ + +// required symbols to grab +LL_GST_SYM(true, gst_video_sink_get_type, GType, void); + +// optional symbols to grab diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h new file mode 100644 index 0000000..e31d4a3 --- /dev/null +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h @@ -0,0 +1,53 @@ +/** + * @file llmediaimplgstreamertriviallogging.h + * @brief minimal logging utilities. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ +#define __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ + +#include <cstdio> + +///////////////////////////////////////////////////////////////////////// +// Debug/Info/Warning macros. +#define MSGMODULEFOO "(media plugin)" +#define STDERRMSG(...) do{\ + fprintf(stderr, MSGMODULEFOO " %s:%d: ", __FUNCTION__, __LINE__);\ + fprintf(stderr, __VA_ARGS__);\ + fputc('\n',stderr);\ + }while(0) +#define NULLMSG(...) do{}while(0) + +#define DEBUGMSG NULLMSG +#define INFOMSG STDERRMSG +#define WARNMSG STDERRMSG +///////////////////////////////////////////////////////////////////////// + +#endif /* __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ */ diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp new file mode 100644 index 0000000..25e96d4 --- /dev/null +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp @@ -0,0 +1,532 @@ +/** + * @file llmediaimplgstreamervidplug.cpp + * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if LL_GSTREAMER010_ENABLED + +#include "linden_common.h" + +#include <gst/gst.h> +#include <gst/video/video.h> +#include <gst/video/gstvideosink.h> + +#include "llmediaimplgstreamer_syms.h" +#include "llmediaimplgstreamertriviallogging.h" + +#include "llmediaimplgstreamervidplug.h" + + +GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug); +#define GST_CAT_DEFAULT gst_slvideo_debug + + +#define SLV_SIZECAPS ", width=(int)[1,2048], height=(int)[1,2048] " +#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS + +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ( + (gchar*)"sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (SLV_ALLCAPS) + ); + +GST_BOILERPLATE (GstSLVideo, gst_slvideo, GstVideoSink, + GST_TYPE_VIDEO_SINK); + +static void gst_slvideo_set_property (GObject * object, guint prop_id, + const GValue * value, + GParamSpec * pspec); +static void gst_slvideo_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static void +gst_slvideo_base_init (gpointer gclass) +{ + static GstElementDetails element_details = { + (gchar*)"PluginTemplate", + (gchar*)"Generic/PluginTemplate", + (gchar*)"Generic Template Element", + (gchar*)"Linden Lab" + }; + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + llgst_element_class_add_pad_template (element_class, + llgst_static_pad_template_get (&sink_factory)); + llgst_element_class_set_details (element_class, &element_details); +} + + +static void +gst_slvideo_finalize (GObject * object) +{ + GstSLVideo *slvideo; + slvideo = GST_SLVIDEO (object); + if (slvideo->caps) + { + llgst_caps_unref(slvideo->caps); + } + + G_OBJECT_CLASS(parent_class)->finalize (object); +} + + +static GstFlowReturn +gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf) +{ + GstSLVideo *slvideo; + llg_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); + + slvideo = GST_SLVIDEO(bsink); + +#if 0 + fprintf(stderr, "\n\ntransferring a frame of %dx%d <- %p (%d)\n\n", + slvideo->width, slvideo->height, GST_BUFFER_DATA(buf), + slvideo->format); +#endif + if (GST_BUFFER_DATA(buf)) + { + // copy frame and frame info into neutral territory + GST_OBJECT_LOCK(slvideo); + slvideo->retained_frame_ready = TRUE; + slvideo->retained_frame_width = slvideo->width; + slvideo->retained_frame_height = slvideo->height; + slvideo->retained_frame_format = slvideo->format; + int rowbytes = + SLVPixelFormatBytes[slvideo->retained_frame_format] * + slvideo->retained_frame_width; + int needbytes = rowbytes * slvideo->retained_frame_width; + // resize retained frame hunk only if necessary + if (needbytes != slvideo->retained_frame_allocbytes) + { + delete[] slvideo->retained_frame_data; + slvideo->retained_frame_data = new unsigned char[needbytes]; + slvideo->retained_frame_allocbytes = needbytes; + + } + // copy the actual frame data to neutral territory - + // flipped, for GL reasons + for (int ypos=0; ypos<slvideo->height; ++ypos) + { + memcpy(&slvideo->retained_frame_data[(slvideo->height-1-ypos)*rowbytes], + &(((unsigned char*)GST_BUFFER_DATA(buf))[ypos*rowbytes]), + rowbytes); + } + // done with the shared data + GST_OBJECT_UNLOCK(slvideo); + } + + return GST_FLOW_OK; +} + + +static GstStateChangeReturn +gst_slvideo_change_state(GstElement * element, GstStateChange transition) +{ + GstSLVideo *slvideo; + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + + slvideo = GST_SLVIDEO (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + slvideo->fps_n = 0; + slvideo->fps_d = 1; + GST_VIDEO_SINK_WIDTH(slvideo) = 0; + GST_VIDEO_SINK_HEIGHT(slvideo) = 0; + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} + + +static GstCaps * +gst_slvideo_get_caps (GstBaseSink * bsink) +{ + GstSLVideo *slvideo; + slvideo = GST_SLVIDEO(bsink); + + return llgst_caps_ref (slvideo->caps); +} + + +/* this function handles the link with other elements */ +static gboolean +gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps) +{ + GstSLVideo *filter; + GstStructure *structure; + + GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps); + + filter = GST_SLVIDEO(bsink); + + int width, height; + gboolean ret; + const GValue *fps; + const GValue *par; + structure = llgst_caps_get_structure (caps, 0); + ret = llgst_structure_get_int (structure, "width", &width); + ret = ret && llgst_structure_get_int (structure, "height", &height); + fps = llgst_structure_get_value (structure, "framerate"); + ret = ret && (fps != NULL); + par = llgst_structure_get_value (structure, "pixel-aspect-ratio"); + if (!ret) + return FALSE; + + INFOMSG("** filter caps set with width=%d, height=%d", width, height); + + GST_OBJECT_LOCK(filter); + + filter->width = width; + filter->height = height; + + filter->fps_n = llgst_value_get_fraction_numerator(fps); + filter->fps_d = llgst_value_get_fraction_denominator(fps); + if (par) + { + filter->par_n = llgst_value_get_fraction_numerator(par); + filter->par_d = llgst_value_get_fraction_denominator(par); + } + else + { + filter->par_n = 1; + filter->par_d = 1; + } + GST_VIDEO_SINK_WIDTH(filter) = width; + GST_VIDEO_SINK_HEIGHT(filter) = height; + + // crufty lump - we *always* accept *only* RGBX now. + /* + filter->format = SLV_PF_UNKNOWN; + if (0 == strcmp(llgst_structure_get_name(structure), + "video/x-raw-rgb")) + { + int red_mask; + int green_mask; + int blue_mask; + llgst_structure_get_int(structure, "red_mask", &red_mask); + llgst_structure_get_int(structure, "green_mask", &green_mask); + llgst_structure_get_int(structure, "blue_mask", &blue_mask); + if ((unsigned int)red_mask == 0xFF000000 && + (unsigned int)green_mask == 0x00FF0000 && + (unsigned int)blue_mask == 0x0000FF00) + { + filter->format = SLV_PF_RGBX; + //fprintf(stderr, "\n\nPIXEL FORMAT RGB\n\n"); + } else if ((unsigned int)red_mask == 0x0000FF00 && + (unsigned int)green_mask == 0x00FF0000 && + (unsigned int)blue_mask == 0xFF000000) + { + filter->format = SLV_PF_BGRX; + //fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n"); + } + }*/ + + filter->format = SLV_PF_RGBX; + + GST_OBJECT_UNLOCK(filter); + + return TRUE; +} + + +static gboolean +gst_slvideo_start (GstBaseSink * bsink) +{ + GstSLVideo *slvideo; + gboolean ret = TRUE; + + slvideo = GST_SLVIDEO(bsink); + + return ret; +} + +static gboolean +gst_slvideo_stop (GstBaseSink * bsink) +{ + GstSLVideo *slvideo; + slvideo = GST_SLVIDEO(bsink); + + // free-up retained frame buffer + GST_OBJECT_LOCK(slvideo); + slvideo->retained_frame_ready = FALSE; + delete[] slvideo->retained_frame_data; + slvideo->retained_frame_data = NULL; + slvideo->retained_frame_allocbytes = 0; + GST_OBJECT_UNLOCK(slvideo); + + return TRUE; +} + + +static GstFlowReturn +gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, + GstCaps * caps, GstBuffer ** buf) +{ + gint width, height; + GstStructure *structure = NULL; + GstSLVideo *slvideo; + slvideo = GST_SLVIDEO(bsink); + + // caps == requested caps + // we can ignore these and reverse-negotiate our preferred dimensions with + // the peer if we like - we need to do this to obey dynamic resize requests + // flowing in from the app. + structure = llgst_caps_get_structure (caps, 0); + if (!llgst_structure_get_int(structure, "width", &width) || + !llgst_structure_get_int(structure, "height", &height)) + { + GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps); + return GST_FLOW_NOT_NEGOTIATED; + } + + GstBuffer *newbuf = llgst_buffer_new(); + bool made_bufferdata_ptr = false; +#define MAXDEPTHHACK 4 + + GST_OBJECT_LOCK(slvideo); + if (slvideo->resize_forced) + { + gint slwantwidth, slwantheight; + slwantwidth = slvideo->resize_try_width; + slwantheight = slvideo->resize_try_height; + + if (slwantwidth != width || + slwantheight != height) + { + // don't like requested caps, we will issue our own suggestion - copy + // the requested caps but substitute our own width and height and see + // if our peer is happy with that. + + GstCaps *desired_caps; + GstStructure *desired_struct; + desired_caps = llgst_caps_copy (caps); + desired_struct = llgst_caps_get_structure (desired_caps, 0); + + GValue value = {0}; + g_value_init(&value, G_TYPE_INT); + g_value_set_int(&value, slwantwidth); + llgst_structure_set_value (desired_struct, "width", &value); + g_value_unset(&value); + g_value_init(&value, G_TYPE_INT); + g_value_set_int(&value, slwantheight); + llgst_structure_set_value (desired_struct, "height", &value); + + if (llgst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo), + desired_caps)) + { + // todo: re-use buffers from a pool? + // todo: set MALLOCDATA to null, set DATA to point straight to shm? + + // peer likes our cap suggestion + DEBUGMSG("peer loves us :)"); + GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK; + GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf)); + GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf); + llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps); + + made_bufferdata_ptr = true; + } else { + // peer hates our cap suggestion + INFOMSG("peer hates us :("); + llgst_caps_unref(desired_caps); + } + } + } + + if (!made_bufferdata_ptr) // need to fallback to malloc at original size + { + GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK; + GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf)); + GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf); + llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps); + } + + GST_OBJECT_UNLOCK(slvideo); + + *buf = GST_BUFFER_CAST(newbuf); + + return GST_FLOW_OK; +} + + +/* initialize the plugin's class */ +static void +gst_slvideo_class_init (GstSLVideoClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSinkClass *gstbasesink_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasesink_class = (GstBaseSinkClass *) klass; + + gobject_class->finalize = gst_slvideo_finalize; + gobject_class->set_property = gst_slvideo_set_property; + gobject_class->get_property = gst_slvideo_get_property; + + gstelement_class->change_state = gst_slvideo_change_state; + +#define LLGST_DEBUG_FUNCPTR(p) (p) + gstbasesink_class->get_caps = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_caps); + gstbasesink_class->set_caps = LLGST_DEBUG_FUNCPTR( gst_slvideo_set_caps); + gstbasesink_class->buffer_alloc=LLGST_DEBUG_FUNCPTR(gst_slvideo_buffer_alloc); + //gstbasesink_class->get_times = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_times); + gstbasesink_class->preroll = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame); + gstbasesink_class->render = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame); + + gstbasesink_class->start = LLGST_DEBUG_FUNCPTR (gst_slvideo_start); + gstbasesink_class->stop = LLGST_DEBUG_FUNCPTR (gst_slvideo_stop); + + // gstbasesink_class->unlock = LLGST_DEBUG_FUNCPTR (gst_slvideo_unlock); +#undef LLGST_DEBUG_FUNCPTR +} + + +/* initialize the new element + * instantiate pads and add them to element + * set functions + * initialize structure + */ +static void +gst_slvideo_init (GstSLVideo * filter, + GstSLVideoClass * gclass) +{ + filter->caps = NULL; + filter->width = -1; + filter->height = -1; + + // this is the info we share with the client app + GST_OBJECT_LOCK(filter); + filter->retained_frame_ready = FALSE; + filter->retained_frame_data = NULL; + filter->retained_frame_allocbytes = 0; + filter->retained_frame_width = filter->width; + filter->retained_frame_height = filter->height; + filter->retained_frame_format = SLV_PF_UNKNOWN; + GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS); + llgst_caps_replace (&filter->caps, caps); + filter->resize_forced = false; + filter->resize_try_width = -1; + filter->resize_try_height = -1; + GST_OBJECT_UNLOCK(filter); +} + +static void +gst_slvideo_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + llg_return_if_fail (GST_IS_SLVIDEO (object)); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_slvideo_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + llg_return_if_fail (GST_IS_SLVIDEO (object)); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +/* entry point to initialize the plug-in + * initialize the plug-in itself + * register the element factories and pad templates + * register the features + */ +static gboolean +plugin_init (GstPlugin * plugin) +{ + DEBUGMSG("\n\n\nPLUGIN INIT\n\n\n"); + + GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin", + 0, (gchar*)"Second Life Video Sink"); + + return llgst_element_register (plugin, (gchar*)"private-slvideo", + GST_RANK_NONE, GST_TYPE_SLVIDEO); +} + +/* this is the structure that gstreamer looks for to register plugins + */ +/* NOTE: Can't rely upon GST_PLUGIN_DEFINE_STATIC to self-register, since + some g++ versions buggily avoid __attribute__((constructor)) functions - + so we provide an explicit plugin init function. + */ +void gst_slvideo_init_class (void) +{ +#define PACKAGE "packagehack" + // this macro quietly refers to PACKAGE internally + static GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + (gchar*)"private-slvideoplugin", + (gchar*)"SL Video sink plugin", + plugin_init, (gchar*)"0.1", (gchar*)GST_LICENSE_UNKNOWN, + (gchar*)"Second Life", + (gchar*)"http://www.secondlife.com/"); +#undef PACKAGE + ll_gst_plugin_register_static (&gst_plugin_desc); + DEBUGMSG(stderr, "\n\n\nCLASS INIT\n\n\n"); +} + +#endif // LL_GSTREAMER010_ENABLED diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h new file mode 100644 index 0000000..f6d55b8 --- /dev/null +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h @@ -0,0 +1,109 @@ +/** + * @file llmediaimplgstreamervidplug.h + * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef __GST_SLVIDEO_H__ +#define __GST_SLVIDEO_H__ + +#if LL_GSTREAMER010_ENABLED + +extern "C" { +#include <gst/gst.h> +#include <gst/video/video.h> +#include <gst/video/gstvideosink.h> +} + +G_BEGIN_DECLS + +/* #defines don't like whitespacey bits */ +#define GST_TYPE_SLVIDEO \ + (gst_slvideo_get_type()) +#define GST_SLVIDEO(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SLVIDEO,GstSLVideo)) +#define GST_SLVIDEO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SLVIDEO,GstSLVideoClass)) +#define GST_IS_SLVIDEO(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SLVIDEO)) +#define GST_IS_SLVIDEO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SLVIDEO)) + +typedef struct _GstSLVideo GstSLVideo; +typedef struct _GstSLVideoClass GstSLVideoClass; + +typedef enum { + SLV_PF_UNKNOWN = 0, + SLV_PF_RGBX = 1, + SLV_PF_BGRX = 2, + SLV__END = 3 +} SLVPixelFormat; +const int SLVPixelFormatBytes[SLV__END] = {1, 4, 4}; + +struct _GstSLVideo +{ + GstVideoSink video_sink; + + GstCaps *caps; + + int fps_n, fps_d; + int par_n, par_d; + int height, width; + SLVPixelFormat format; + + // SHARED WITH APPLICATION: + // Access to the following should be protected by GST_OBJECT_LOCK() on + // the GstSLVideo object, and should be totally consistent upon UNLOCK + // (i.e. all written at once to reflect the current retained frame info + // when the retained frame is updated.) + bool retained_frame_ready; // new frame ready since flag last reset. (*TODO: could get the writer to wait on a semaphore instead of having the reader poll, potentially making dropped frames somewhat cheaper.) + unsigned char* retained_frame_data; + int retained_frame_allocbytes; + int retained_frame_width, retained_frame_height; + SLVPixelFormat retained_frame_format; + // sticky resize info + bool resize_forced; + int resize_try_width; + int resize_try_height; +}; + +struct _GstSLVideoClass +{ + GstVideoSinkClass parent_class; +}; + +GType gst_slvideo_get_type (void); + +void gst_slvideo_init_class (void); + +G_END_DECLS + +#endif // LL_GSTREAMER010_ENABLED + +#endif /* __GST_SLVIDEO_H__ */ diff --git a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp new file mode 100644 index 0000000..77b7c13 --- /dev/null +++ b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp @@ -0,0 +1,1202 @@ +/** + * @file media_plugin_gstreamer010.cpp + * @brief GStreamer-0.10 plugin for LLMedia API plugin system + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llgl.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#if LL_GSTREAMER010_ENABLED + +extern "C" { +#include <gst/gst.h> +} + +#include "llmediaimplgstreamer.h" +#include "llmediaimplgstreamertriviallogging.h" + +#include "llmediaimplgstreamervidplug.h" + +#include "llmediaimplgstreamer_syms.h" + +////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginGStreamer010 : public MediaPluginBase +{ +public: + MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginGStreamer010(); + + /* virtual */ void receiveMessage(const char *message_string); + + static bool startup(); + static bool closedown(); + + gboolean processGSTEvents(GstBus *bus, + GstMessage *message); + +private: + std::string getVersion(); + bool navigateTo( const std::string urlIn ); + bool seek( double time_sec ); + bool setVolume( float volume ); + + // misc + bool pause(); + bool stop(); + bool play(double rate); + bool getTimePos(double &sec_out); + + static const double MIN_LOOP_SEC = 1.0F; + + bool mIsLooping; + + enum ECommand { + COMMAND_NONE, + COMMAND_STOP, + COMMAND_PLAY, + COMMAND_FAST_FORWARD, + COMMAND_FAST_REWIND, + COMMAND_PAUSE, + COMMAND_SEEK, + }; + ECommand mCommand; + +private: + bool unload(); + bool load(); + + bool update(int milliseconds); + void mouseDown( int x, int y ); + void mouseUp( int x, int y ); + void mouseMove( int x, int y ); + + bool sizeChanged(); + + static bool mDoneInit; + + guint mBusWatchID; + + float mVolume; + + int mDepth; + + // media natural size + int mNaturalWidth; + int mNaturalHeight; + int mNaturalRowbytes; + // previous media natural size so we can detect changes + int mPreviousNaturalWidth; + int mPreviousNaturalHeight; + // desired render size from host + int mWidth; + int mHeight; + // padded texture size we need to write into + int mTextureWidth; + int mTextureHeight; + + int mTextureFormatPrimary; + int mTextureFormatType; + + bool mSeekWanted; + double mSeekDestination; + + // Very GStreamer-specific + GMainLoop *mPump; // event pump for this media + GstElement *mPlaybin; + GstSLVideo *mVideoSink; +}; + +//static +bool MediaPluginGStreamer010::mDoneInit = false; + +MediaPluginGStreamer010::MediaPluginGStreamer010( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) : + MediaPluginBase(host_send_func, host_user_data), + mBusWatchID ( 0 ), + mNaturalRowbytes ( 4 ), + mTextureFormatPrimary ( GL_RGBA ), + mTextureFormatType ( GL_UNSIGNED_INT_8_8_8_8_REV ), + mSeekWanted(false), + mSeekDestination(0.0), + mPump ( NULL ), + mPlaybin ( NULL ), + mVideoSink ( NULL ), + mCommand ( COMMAND_NONE ) +{ + std::ostringstream str; + INFOMSG("MediaPluginGStreamer010 constructor - my PID=%u", U32(getpid())); +} + +/////////////////////////////////////////////////////////////////////////////// +// +//#define LL_GST_REPORT_STATE_CHANGES +#ifdef LL_GST_REPORT_STATE_CHANGES +static char* get_gst_state_name(GstState state) +{ + switch (state) { + case GST_STATE_VOID_PENDING: return "VOID_PENDING"; + case GST_STATE_NULL: return "NULL"; + case GST_STATE_READY: return "READY"; + case GST_STATE_PAUSED: return "PAUSED"; + case GST_STATE_PLAYING: return "PLAYING"; + } + return "(unknown)"; +} +#endif // LL_GST_REPORT_STATE_CHANGES + +gboolean +MediaPluginGStreamer010::processGSTEvents(GstBus *bus, + GstMessage *message) +{ + if (!message) + return TRUE; // shield against GStreamer bug + + if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED && + GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING) + { + DEBUGMSG("Got GST message type: %s", + LLGST_MESSAGE_TYPE_NAME (message)); + } + else + { + DEBUGMSG("Got GST message type: %s", + LLGST_MESSAGE_TYPE_NAME (message)); + } + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_BUFFERING: { + // NEEDS GST 0.10.11+ + if (llgst_message_parse_buffering) + { + gint percent = 0; + llgst_message_parse_buffering(message, &percent); + DEBUGMSG("GST buffering: %d%%", percent); + } + break; + } + case GST_MESSAGE_STATE_CHANGED: { + GstState old_state; + GstState new_state; + GstState pending_state; + llgst_message_parse_state_changed(message, + &old_state, + &new_state, + &pending_state); +#ifdef LL_GST_REPORT_STATE_CHANGES + // not generally very useful, and rather spammy. + DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s", + get_gst_state_name(old_state), + get_gst_state_name(new_state), + get_gst_state_name(pending_state)); +#endif // LL_GST_REPORT_STATE_CHANGES + + switch (new_state) { + case GST_STATE_VOID_PENDING: + break; + case GST_STATE_NULL: + break; + case GST_STATE_READY: + setStatus(STATUS_LOADED); + break; + case GST_STATE_PAUSED: + setStatus(STATUS_PAUSED); + break; + case GST_STATE_PLAYING: + setStatus(STATUS_PLAYING); + break; + } + break; + } + case GST_MESSAGE_ERROR: { + GError *err = NULL; + gchar *debug = NULL; + + llgst_message_parse_error (message, &err, &debug); + WARNMSG("GST error: %s", err?err->message:"(unknown)"); + if (err) + g_error_free (err); + g_free (debug); + + mCommand = COMMAND_STOP; + + setStatus(STATUS_ERROR); + + break; + } + case GST_MESSAGE_INFO: { + if (llgst_message_parse_info) + { + GError *err = NULL; + gchar *debug = NULL; + + llgst_message_parse_info (message, &err, &debug); + INFOMSG("GST info: %s", err?err->message:"(unknown)"); + if (err) + g_error_free (err); + g_free (debug); + } + break; + } + case GST_MESSAGE_WARNING: { + GError *err = NULL; + gchar *debug = NULL; + + llgst_message_parse_warning (message, &err, &debug); + WARNMSG("GST warning: %s", err?err->message:"(unknown)"); + if (err) + g_error_free (err); + g_free (debug); + + break; + } + case GST_MESSAGE_EOS: + /* end-of-stream */ + DEBUGMSG("GST end-of-stream."); + if (mIsLooping) + { + DEBUGMSG("looping media..."); + double eos_pos_sec = 0.0F; + bool got_eos_position = getTimePos(eos_pos_sec); + + if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC) + { + // if we know that the movie is really short, don't + // loop it else it can easily become a time-hog + // because of GStreamer spin-up overhead + DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec); + // inject a COMMAND_PAUSE + mCommand = COMMAND_PAUSE; + } + else + { +#undef LLGST_LOOP_BY_SEEKING +// loop with a stop-start instead of a seek, because it actually seems rather +// faster than seeking on remote streams. +#ifdef LLGST_LOOP_BY_SEEKING + // first, try looping by an explicit rewind + bool seeksuccess = seek(0.0); + if (seeksuccess) + { + play(1.0); + } + else +#endif // LLGST_LOOP_BY_SEEKING + { // use clumsy stop-start to loop + DEBUGMSG("didn't loop by rewinding - stopping and starting instead..."); + stop(); + play(1.0); + } + } + } + else // not a looping media + { + // inject a COMMAND_STOP + mCommand = COMMAND_STOP; + } + break; + default: + /* unhandled message */ + break; + } + + /* we want to be notified again the next time there is a message + * on the bus, so return true (false means we want to stop watching + * for messages on the bus and our callback should not be called again) + */ + return TRUE; +} + +extern "C" { +gboolean +llmediaimplgstreamer_bus_callback (GstBus *bus, + GstMessage *message, + gpointer data) +{ + MediaPluginGStreamer010 *impl = (MediaPluginGStreamer010*)data; + return impl->processGSTEvents(bus, message); +} +} // extern "C" + + + +bool +MediaPluginGStreamer010::navigateTo ( const std::string urlIn ) +{ + if (!mDoneInit) + return false; // error + + setStatus(STATUS_LOADING); + + DEBUGMSG("Setting media URI: %s", urlIn.c_str()); + + mSeekWanted = false; + + if (NULL == mPump || + NULL == mPlaybin) + { + setStatus(STATUS_ERROR); + return false; // error + } + + // set URI + g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL); + //g_object_set (G_OBJECT (mPlaybin), "uri", "file:///tmp/movie", NULL); + + // navigateTo implicitly plays, too. + play(1.0); + + return true; +} + + +bool +MediaPluginGStreamer010::update(int milliseconds) +{ + if (!mDoneInit) + return false; // error + + DEBUGMSG("updating media..."); + + // sanity check + if (NULL == mPump || + NULL == mPlaybin) + { + DEBUGMSG("dead media..."); + return false; + } + + // see if there's an outstanding seek wanted + if (mSeekWanted && + // bleh, GST has to be happy that the movie is really truly playing + // or it may quietly ignore the seek (with rtsp:// at least). + (GST_STATE(mPlaybin) == GST_STATE_PLAYING)) + { + seek(mSeekDestination); + mSeekWanted = false; + } + + // *TODO: time-limit - but there isn't a lot we can do here, most + // time is spent in gstreamer's own opaque worker-threads. maybe + // we can do something sneaky like only unlock the video object + // for 'milliseconds' and otherwise hold the lock. + while (g_main_context_pending(g_main_loop_get_context(mPump))) + { + g_main_context_iteration(g_main_loop_get_context(mPump), FALSE); + } + + // check for availability of a new frame + + if (mVideoSink) + { + GST_OBJECT_LOCK(mVideoSink); + if (mVideoSink->retained_frame_ready) + { + DEBUGMSG("NEW FRAME READY"); + + if (mVideoSink->retained_frame_width != mNaturalWidth || + mVideoSink->retained_frame_height != mNaturalHeight) + // *TODO: also check for change in format + { + // just resize container, don't consume frame + int neww = mVideoSink->retained_frame_width; + int newh = mVideoSink->retained_frame_height; + + int newd = 4; + mTextureFormatPrimary = GL_RGBA; + mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; + + /* + int newd = SLVPixelFormatBytes[mVideoSink->retained_frame_format]; + if (SLV_PF_BGRX == mVideoSink->retained_frame_format) + { + mTextureFormatPrimary = GL_BGRA; + mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; + } + else + { + mTextureFormatPrimary = GL_RGBA; + mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; + } + */ + + GST_OBJECT_UNLOCK(mVideoSink); + + mNaturalRowbytes = neww * newd; + DEBUGMSG("video container resized to %dx%d", + neww, newh); + + mDepth = newd; + mNaturalWidth = neww; + mNaturalHeight = newh; + sizeChanged(); + return true; + } + + if (mPixels && + mNaturalHeight <= mHeight && + mNaturalWidth <= mWidth && + !mTextureSegmentName.empty()) + { + + // we're gonna totally consume this frame - reset 'ready' flag + mVideoSink->retained_frame_ready = FALSE; + int destination_rowbytes = mWidth * mDepth; + for (int row=0; row<mNaturalHeight; ++row) + { + memcpy(&mPixels + [destination_rowbytes * row], + &mVideoSink->retained_frame_data + [mNaturalRowbytes * row], + mNaturalRowbytes); + } + + GST_OBJECT_UNLOCK(mVideoSink); + DEBUGMSG("NEW FRAME REALLY TRULY CONSUMED, TELLING HOST"); + + setDirty(0,0,mNaturalWidth,mNaturalHeight); + } + else + { + // new frame ready, but we're not ready to + // consume it. + + GST_OBJECT_UNLOCK(mVideoSink); + + DEBUGMSG("NEW FRAME not consumed, still waiting for a shm segment and/or shm resize"); + } + + return true; + } + else + { + // nothing to do yet. + GST_OBJECT_UNLOCK(mVideoSink); + return true; + } + } + + return true; +} + + +void +MediaPluginGStreamer010::mouseDown( int x, int y ) +{ + // do nothing +} + +void +MediaPluginGStreamer010::mouseUp( int x, int y ) +{ + // do nothing +} + +void +MediaPluginGStreamer010::mouseMove( int x, int y ) +{ + // do nothing +} + + +bool +MediaPluginGStreamer010::pause() +{ + DEBUGMSG("pausing media..."); + // todo: error-check this? + llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); + return true; +} + +bool +MediaPluginGStreamer010::stop() +{ + DEBUGMSG("stopping media..."); + // todo: error-check this? + llgst_element_set_state(mPlaybin, GST_STATE_READY); + return true; +} + +bool +MediaPluginGStreamer010::play(double rate) +{ + // NOTE: we don't actually support non-natural rate. + + DEBUGMSG("playing media... rate=%f", rate); + // todo: error-check this? + llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); + return true; +} + +bool +MediaPluginGStreamer010::setVolume( float volume ) +{ + // we try to only update volume as conservatively as + // possible, as many gst-plugins-base versions up to at least + // November 2008 have critical race-conditions in setting volume - sigh + if (mVolume == volume) + return true; // nothing to do, everything's fine + + mVolume = volume; + if (mDoneInit && mPlaybin) + { + g_object_set(mPlaybin, "volume", mVolume, NULL); + return true; + } + + return false; +} + +bool +MediaPluginGStreamer010::seek(double time_sec) +{ + bool success = false; + if (mDoneInit && mPlaybin) + { + success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME, + GstSeekFlags(GST_SEEK_FLAG_FLUSH | + GST_SEEK_FLAG_KEY_UNIT), + GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND), + GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); + } + DEBUGMSG("MEDIA SEEK REQUEST to %fsec result was %d", + float(time_sec), int(success)); + return success; +} + +bool +MediaPluginGStreamer010::getTimePos(double &sec_out) +{ + bool got_position = false; + if (mPlaybin) + { + gint64 pos; + GstFormat timefmt = GST_FORMAT_TIME; + got_position = + llgst_element_query_position && + llgst_element_query_position(mPlaybin, + &timefmt, + &pos); + got_position = got_position + && (timefmt == GST_FORMAT_TIME); + // GStreamer may have other ideas, but we consider the current position + // undefined if not PLAYING or PAUSED + got_position = got_position && + (GST_STATE(mPlaybin) == GST_STATE_PLAYING || + GST_STATE(mPlaybin) == GST_STATE_PAUSED); + if (got_position && !GST_CLOCK_TIME_IS_VALID(pos)) + { + if (GST_STATE(mPlaybin) == GST_STATE_PLAYING) + { + // if we're playing then we treat an invalid clock time + // as 0, for complicated reasons (insert reason here) + pos = 0; + } + else + { + got_position = false; + } + + } + // If all the preconditions succeeded... we can trust the result. + if (got_position) + { + sec_out = double(pos) / double(GST_SECOND); // gst to sec + } + } + return got_position; +} + +bool +MediaPluginGStreamer010::load() +{ + if (!mDoneInit) + return false; // error + + setStatus(STATUS_LOADING); + + DEBUGMSG("setting up media..."); + + mIsLooping = false; + mVolume = 0.1234567; // minor hack to force an initial volume update + + // Create a pumpable main-loop for this media + mPump = g_main_loop_new (NULL, FALSE); + if (!mPump) + { + setStatus(STATUS_ERROR); + return false; // error + } + + // instantiate a playbin element to do the hard work + mPlaybin = llgst_element_factory_make ("playbin", "play"); + if (!mPlaybin) + { + setStatus(STATUS_ERROR); + return false; // error + } + + // get playbin's bus + GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin)); + if (!bus) + { + setStatus(STATUS_ERROR); + return false; // error + } + mBusWatchID = llgst_bus_add_watch (bus, + llmediaimplgstreamer_bus_callback, + this); + llgst_object_unref (bus); + + if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) { + // instantiate a custom video sink + mVideoSink = + GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo")); + if (!mVideoSink) + { + WARNMSG("Could not instantiate private-slvideo element."); + // todo: cleanup. + setStatus(STATUS_ERROR); + return false; // error + } + + // connect the pieces + g_object_set(mPlaybin, "video-sink", mVideoSink, NULL); + } + + return true; +} + +bool +MediaPluginGStreamer010::unload () +{ + if (!mDoneInit) + return false; // error + + DEBUGMSG("unloading media..."); + + // stop getting callbacks for this bus + g_source_remove(mBusWatchID); + mBusWatchID = 0; + + if (mPlaybin) + { + llgst_element_set_state (mPlaybin, GST_STATE_NULL); + llgst_object_unref (GST_OBJECT (mPlaybin)); + mPlaybin = NULL; + } + + if (mPump) + { + g_main_loop_quit(mPump); + mPump = NULL; + } + + mVideoSink = NULL; + + setStatus(STATUS_NONE); + + return true; +} + + +//static +bool +MediaPluginGStreamer010::startup() +{ + // first - check if GStreamer is explicitly disabled + if (NULL != getenv("LL_DISABLE_GSTREAMER")) + return false; + + // only do global GStreamer initialization once. + if (!mDoneInit) + { + g_thread_init(NULL); + + // Init the glib type system - we need it. + g_type_init(); + + // Get symbols! +#if LL_DARWIN + if (! grab_gst_syms("libgstreamer-0.10.dylib", + "libgstvideo-0.10.dylib") ) +#elseif LL_WINDOWS + if (! grab_gst_syms("libgstreamer-0.10.dll", + "libgstvideo-0.10.dll") ) +#else // linux or other ELFy unixoid + if (! grab_gst_syms("libgstreamer-0.10.so.0", + "libgstvideo-0.10.so.0") ) +#endif + { + WARNMSG("Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled."); + return false; + } + + if (llgst_segtrap_set_enabled) + { + llgst_segtrap_set_enabled(FALSE); + } + else + { + WARNMSG("gst_segtrap_set_enabled() is not available; plugin crashes won't be caught."); + } + +#if LL_LINUX + // Gstreamer tries a fork during init, waitpid-ing on it, + // which conflicts with any installed SIGCHLD handler... + struct sigaction tmpact, oldact; + if (llgst_registry_fork_set_enabled) { + // if we can disable SIGCHLD-using forking behaviour, + // do it. + llgst_registry_fork_set_enabled(false); + } + else { + // else temporarily install default SIGCHLD handler + // while GStreamer initialises + tmpact.sa_handler = SIG_DFL; + sigemptyset( &tmpact.sa_mask ); + tmpact.sa_flags = SA_SIGINFO; + sigaction(SIGCHLD, &tmpact, &oldact); + } +#endif // LL_LINUX + + // Protect against GStreamer resetting the locale, yuck. + static std::string saved_locale; + saved_locale = setlocale(LC_ALL, NULL); + + // finally, try to initialize GStreamer! + GError *err = NULL; + gboolean init_gst_success = llgst_init_check(NULL, NULL, &err); + + // restore old locale + setlocale(LC_ALL, saved_locale.c_str() ); + +#if LL_LINUX + // restore old SIGCHLD handler + if (!llgst_registry_fork_set_enabled) + sigaction(SIGCHLD, &oldact, NULL); +#endif // LL_LINUX + + if (!init_gst_success) // fail + { + if (err) + { + WARNMSG("GST init failed: %s", err->message); + g_error_free(err); + } + else + { + WARNMSG("GST init failed for unspecified reason."); + } + return false; + } + + // Init our custom plugins - only really need do this once. + gst_slvideo_init_class(); + + mDoneInit = true; + } + + return true; +} + + +bool +MediaPluginGStreamer010::sizeChanged() +{ + // the shared writing space has possibly changed size/location/whatever + + // Check to see whether the movie's natural size has updated + if (mNaturalWidth != mPreviousNaturalWidth || + mNaturalHeight != mPreviousNaturalHeight) + { + mPreviousNaturalWidth = mNaturalWidth; + mPreviousNaturalHeight = mNaturalHeight; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); + message.setValue("name", mTextureSegmentName); + message.setValueS32("width", mNaturalWidth); + message.setValueS32("height", mNaturalHeight); + DEBUGMSG("<--- Sending size change request to application with name: '%s' - size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight); + sendMessage(message); + } + + return true; +} + + + +//static +bool +MediaPluginGStreamer010::closedown() +{ + if (!mDoneInit) + return false; // error + + ungrab_gst_syms(); + + mDoneInit = false; + + return true; +} + +MediaPluginGStreamer010::~MediaPluginGStreamer010() +{ + DEBUGMSG("MediaPluginGStreamer010 destructor"); + + closedown(); + + DEBUGMSG("GStreamer010 closing down"); +} + + +std::string +MediaPluginGStreamer010::getVersion() +{ + std::string plugin_version = "GStreamer010 media plugin, GStreamer version "; + if (mDoneInit && + llgst_version) + { + guint major, minor, micro, nano; + llgst_version(&major, &minor, µ, &nano); + plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor, (unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR, (unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO); + } + else + { + plugin_version += "(unknown)"; + } + return plugin_version; +} + +void MediaPluginGStreamer010::receiveMessage(const char *message_string) +{ + //std::cerr << "MediaPluginGStreamer010::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if(message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; + message.setValueLLSD("versions", versions); + + if ( load() ) + { + DEBUGMSG("GStreamer010 media instance set up"); + } + else + { + WARNMSG("GStreamer010 media instance failed to set up"); + } + + message.setValue("plugin_version", getVersion()); + sendMessage(message); + + // Plugin gets to decide the texture parameters to use. + message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + // lame to have to decide this now, it depends on the movie. Oh well. + mDepth = 4; + + mNaturalWidth = 1; + mNaturalHeight = 1; + mPreviousNaturalWidth = 1; + mPreviousNaturalHeight = 1; + mWidth = 1; + mHeight = 1; + mTextureWidth = 1; + mTextureHeight = 1; + + message.setValueU32("format", GL_RGBA); + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV); + + message.setValueS32("depth", mDepth); + message.setValueS32("default_width", mWidth); + message.setValueS32("default_height", mHeight); + message.setValueU32("internalformat", GL_RGBA8); + message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. + message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. + double time = message_in.getValueReal("time"); + + // Convert time to milliseconds for update() + update((int)(time * 1000.0f)); + } + else if(message_name == "cleanup") + { + unload(); + closedown(); + } + else if(message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + std::ostringstream str; + INFOMSG("MediaPluginGStreamer010::receiveMessage: shared memory added, name: %s, size: %d, address: %p", name.c_str(), int(info.mSize), info.mAddress); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if(message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + DEBUGMSG("MediaPluginGStreamer010::receiveMessage: shared memory remove, name = %s", name.c_str()); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + if(mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + + // Make sure the movie decoder is no longer pointed at the shared segment. + sizeChanged(); + } + mSharedSegments.erase(iter); + } + else + { + WARNMSG("MediaPluginGStreamer010::receiveMessage: unknown shared memory region!"); + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { + std::ostringstream str; + INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown base message: %s", message_name.c_str()); + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if(message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + std::ostringstream str; + INFOMSG("---->Got size change instruction from application with shm name: %s - size is %d x %d", name.c_str(), width, height); + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + if(!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + INFOMSG("*** Got size change with matching shm, new size is %d x %d", width, height); + INFOMSG("*** Got size change with matching shm, texture size size is %d x %d", texture_width, texture_height); + + mPixels = (unsigned char*)iter->second.mAddress; + mTextureSegmentName = name; + mWidth = width; + mHeight = height; + + if (texture_width > 1 || + texture_height > 1) // not a dummy size from the app, a real explicit forced size + { + INFOMSG("**** = REAL RESIZE REQUEST FROM APP"); + + GST_OBJECT_LOCK(mVideoSink); + mVideoSink->resize_forced = true; + mVideoSink->resize_try_width = texture_width; + mVideoSink->resize_try_height = texture_height; + GST_OBJECT_UNLOCK(mVideoSink); + } + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + } + } + } + else if(message_name == "load_uri") + { + std::string uri = message_in.getValue("uri"); + navigateTo( uri ); + sendStatus(); + } + else if(message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); + + if(event == "down") + { + mouseDown(x, y); + } + else if(event == "up") + { + mouseUp(x, y); + } + else if(event == "move") + { + mouseMove(x, y); + }; + }; + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) + { + if(message_name == "stop") + { + stop(); + } + else if(message_name == "start") + { + double rate = 0.0; + if(message_in.hasValue("rate")) + { + rate = message_in.getValueReal("rate"); + } + // NOTE: we don't actually support rate. + play(rate); + } + else if(message_name == "pause") + { + pause(); + } + else if(message_name == "seek") + { + double time = message_in.getValueReal("time"); + // defer the actual seek in case we haven't + // really truly started yet in which case there + // is nothing to seek upon + mSeekWanted = true; + mSeekDestination = time; + } + else if(message_name == "set_loop") + { + bool loop = message_in.getValueBoolean("loop"); + mIsLooping = loop; + } + else if(message_name == "set_volume") + { + double volume = message_in.getValueReal("volume"); + setVolume(volume); + } + } + else + { + INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown message class: %s", message_class.c_str()); + } + } +} + +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + if (MediaPluginGStreamer010::startup()) + { + MediaPluginGStreamer010 *self = new MediaPluginGStreamer010(host_send_func, host_user_data); + *plugin_send_func = MediaPluginGStreamer010::staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; // okay + } + else + { + return -1; // failed to init + } +} + +#else // LL_GSTREAMER010_ENABLED + +// Stubbed-out class with constructor/destructor (necessary or windows linker +// will just think its dead code and optimize it all out) +class MediaPluginGStreamer010 : public MediaPluginBase +{ +public: + MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginGStreamer010(); + /* virtual */ void receiveMessage(const char *message_string); +}; + +MediaPluginGStreamer010::MediaPluginGStreamer010( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) : + MediaPluginBase(host_send_func, host_user_data) +{ + // no-op +} + +MediaPluginGStreamer010::~MediaPluginGStreamer010() +{ + // no-op +} + +void MediaPluginGStreamer010::receiveMessage(const char *message_string) +{ + // no-op +} + +// We're building without GStreamer enabled. Just refuse to initialize. +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + return -1; +} + +#endif // LL_GSTREAMER010_ENABLED diff --git a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp~ b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp~ new file mode 100755 index 0000000..7d34a1e --- /dev/null +++ b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp~ @@ -0,0 +1,1219 @@ +/** + * @file media_plugin_gstreamer010.cpp + * @brief GStreamer-0.10 plugin for LLMedia API plugin system + * + * @cond + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#include "linden_common.h" + +#include "llgl.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#if LL_GSTREAMER010_ENABLED + +extern "C" { +#include <gst/gst.h> +} + +#include "llmediaimplgstreamer.h" +#include "llmediaimplgstreamertriviallogging.h" + +#include "llmediaimplgstreamervidplug.h" + +#include "llmediaimplgstreamer_syms.h" + +////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginGStreamer010 : public MediaPluginBase +{ +public: + MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginGStreamer010(); + + /* virtual */ void receiveMessage(const char *message_string); + + static bool startup(); + static bool closedown(); + + gboolean processGSTEvents(GstBus *bus, + GstMessage *message); + +private: + std::string getVersion(); + bool navigateTo( const std::string urlIn ); + bool seek( double time_sec ); + bool setVolume( float volume ); + + // misc + bool pause(); + bool stop(); + bool play(double rate); + bool getTimePos(double &sec_out); + + static const double MIN_LOOP_SEC = 1.0F; + + bool mIsLooping; + + enum ECommand { + COMMAND_NONE, + COMMAND_STOP, + COMMAND_PLAY, + COMMAND_FAST_FORWARD, + COMMAND_FAST_REWIND, + COMMAND_PAUSE, + COMMAND_SEEK, + }; + ECommand mCommand; + +private: + bool unload(); + bool load(); + + bool update(int milliseconds); + void mouseDown( int x, int y ); + void mouseUp( int x, int y ); + void mouseMove( int x, int y ); + + void sizeChanged(); + + static bool mDoneInit; + + guint mBusWatchID; + + float mVolume; + + int mDepth; + + // media NATURAL size + int mNaturalWidth; + int mNaturalHeight; + // media current size + int mCurrentWidth; + int mCurrentHeight; + int mCurrentRowbytes; + // previous media size so we can detect changes + int mPreviousWidth; + int mPreviousHeight; + // desired render size from host + int mWidth; + int mHeight; + // padded texture size we need to write into + int mTextureWidth; + int mTextureHeight; + + int mTextureFormatPrimary; + int mTextureFormatType; + + bool mSeekWanted; + double mSeekDestination; + + // Very GStreamer-specific + GMainLoop *mPump; // event pump for this media + GstElement *mPlaybin; + GstSLVideo *mVideoSink; +}; + +//static +bool MediaPluginGStreamer010::mDoneInit = false; + +MediaPluginGStreamer010::MediaPluginGStreamer010( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) : + MediaPluginBase(host_send_func, host_user_data), + mBusWatchID ( 0 ), + mCurrentRowbytes ( 4 ), + mTextureFormatPrimary ( GL_RGBA ), + mTextureFormatType ( GL_UNSIGNED_INT_8_8_8_8_REV ), + mSeekWanted(false), + mSeekDestination(0.0), + mPump ( NULL ), + mPlaybin ( NULL ), + mVideoSink ( NULL ), + mCommand ( COMMAND_NONE ) +{ + std::ostringstream str; + INFOMSG("MediaPluginGStreamer010 constructor - my PID=%u", U32(getpid())); +} + +/////////////////////////////////////////////////////////////////////////////// +// +//#define LL_GST_REPORT_STATE_CHANGES +#ifdef LL_GST_REPORT_STATE_CHANGES +static char* get_gst_state_name(GstState state) +{ + switch (state) { + case GST_STATE_VOID_PENDING: return "VOID_PENDING"; + case GST_STATE_NULL: return "NULL"; + case GST_STATE_READY: return "READY"; + case GST_STATE_PAUSED: return "PAUSED"; + case GST_STATE_PLAYING: return "PLAYING"; + } + return "(unknown)"; +} +#endif // LL_GST_REPORT_STATE_CHANGES + +gboolean +MediaPluginGStreamer010::processGSTEvents(GstBus *bus, + GstMessage *message) +{ + if (!message) + return TRUE; // shield against GStreamer bug + + if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED && + GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING) + { + DEBUGMSG("Got GST message type: %s", + LLGST_MESSAGE_TYPE_NAME (message)); + } + else + { + // TODO: grok 'duration' message type + DEBUGMSG("Got GST message type: %s", + LLGST_MESSAGE_TYPE_NAME (message)); + } + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_BUFFERING: { + // NEEDS GST 0.10.11+ + if (llgst_message_parse_buffering) + { + gint percent = 0; + llgst_message_parse_buffering(message, &percent); + DEBUGMSG("GST buffering: %d%%", percent); + } + break; + } + case GST_MESSAGE_STATE_CHANGED: { + GstState old_state; + GstState new_state; + GstState pending_state; + llgst_message_parse_state_changed(message, + &old_state, + &new_state, + &pending_state); +#ifdef LL_GST_REPORT_STATE_CHANGES + // not generally very useful, and rather spammy. + DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s", + get_gst_state_name(old_state), + get_gst_state_name(new_state), + get_gst_state_name(pending_state)); +#endif // LL_GST_REPORT_STATE_CHANGES + + switch (new_state) { + case GST_STATE_VOID_PENDING: + break; + case GST_STATE_NULL: + break; + case GST_STATE_READY: + setStatus(STATUS_LOADED); + break; + case GST_STATE_PAUSED: + setStatus(STATUS_PAUSED); + break; + case GST_STATE_PLAYING: + setStatus(STATUS_PLAYING); + break; + } + break; + } + case GST_MESSAGE_ERROR: { + GError *err = NULL; + gchar *debug = NULL; + + llgst_message_parse_error (message, &err, &debug); + WARNMSG("GST error: %s", err?err->message:"(unknown)"); + if (err) + g_error_free (err); + g_free (debug); + + mCommand = COMMAND_STOP; + + setStatus(STATUS_ERROR); + + break; + } + case GST_MESSAGE_INFO: { + if (llgst_message_parse_info) + { + GError *err = NULL; + gchar *debug = NULL; + + llgst_message_parse_info (message, &err, &debug); + INFOMSG("GST info: %s", err?err->message:"(unknown)"); + if (err) + g_error_free (err); + g_free (debug); + } + break; + } + case GST_MESSAGE_WARNING: { + GError *err = NULL; + gchar *debug = NULL; + + llgst_message_parse_warning (message, &err, &debug); + WARNMSG("GST warning: %s", err?err->message:"(unknown)"); + if (err) + g_error_free (err); + g_free (debug); + + break; + } + case GST_MESSAGE_EOS: + /* end-of-stream */ + DEBUGMSG("GST end-of-stream."); + if (mIsLooping) + { + DEBUGMSG("looping media..."); + double eos_pos_sec = 0.0F; + bool got_eos_position = getTimePos(eos_pos_sec); + + if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC) + { + // if we know that the movie is really short, don't + // loop it else it can easily become a time-hog + // because of GStreamer spin-up overhead + DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec); + // inject a COMMAND_PAUSE + mCommand = COMMAND_PAUSE; + } + else + { +#undef LLGST_LOOP_BY_SEEKING +// loop with a stop-start instead of a seek, because it actually seems rather +// faster than seeking on remote streams. +#ifdef LLGST_LOOP_BY_SEEKING + // first, try looping by an explicit rewind + bool seeksuccess = seek(0.0); + if (seeksuccess) + { + play(1.0); + } + else +#endif // LLGST_LOOP_BY_SEEKING + { // use clumsy stop-start to loop + DEBUGMSG("didn't loop by rewinding - stopping and starting instead..."); + stop(); + play(1.0); + } + } + } + else // not a looping media + { + // inject a COMMAND_STOP + mCommand = COMMAND_STOP; + } + break; + default: + /* unhandled message */ + break; + } + + /* we want to be notified again the next time there is a message + * on the bus, so return true (false means we want to stop watching + * for messages on the bus and our callback should not be called again) + */ + return TRUE; +} + +extern "C" { +gboolean +llmediaimplgstreamer_bus_callback (GstBus *bus, + GstMessage *message, + gpointer data) +{ + MediaPluginGStreamer010 *impl = (MediaPluginGStreamer010*)data; + return impl->processGSTEvents(bus, message); +} +} // extern "C" + + + +bool +MediaPluginGStreamer010::navigateTo ( const std::string urlIn ) +{ + if (!mDoneInit) + return false; // error + + setStatus(STATUS_LOADING); + + DEBUGMSG("Setting media URI: %s", urlIn.c_str()); + + mSeekWanted = false; + + if (NULL == mPump || + NULL == mPlaybin) + { + setStatus(STATUS_ERROR); + return false; // error + } + + // set URI + g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL); + //g_object_set (G_OBJECT (mPlaybin), "uri", "file:///tmp/movie", NULL); + + // navigateTo implicitly plays, too. + play(1.0); + + return true; +} + + +bool +MediaPluginGStreamer010::update(int milliseconds) +{ + if (!mDoneInit) + return false; // error + + DEBUGMSG("updating media..."); + + // sanity check + if (NULL == mPump || + NULL == mPlaybin) + { + DEBUGMSG("dead media..."); + return false; + } + + // see if there's an outstanding seek wanted + if (mSeekWanted && + // bleh, GST has to be happy that the movie is really truly playing + // or it may quietly ignore the seek (with rtsp:// at least). + (GST_STATE(mPlaybin) == GST_STATE_PLAYING)) + { + seek(mSeekDestination); + mSeekWanted = false; + } + + // *TODO: time-limit - but there isn't a lot we can do here, most + // time is spent in gstreamer's own opaque worker-threads. maybe + // we can do something sneaky like only unlock the video object + // for 'milliseconds' and otherwise hold the lock. + while (g_main_context_pending(g_main_loop_get_context(mPump))) + { + g_main_context_iteration(g_main_loop_get_context(mPump), FALSE); + } + + // check for availability of a new frame + + if (mVideoSink) + { + GST_OBJECT_LOCK(mVideoSink); + if (mVideoSink->retained_frame_ready) + { + DEBUGMSG("NEW FRAME READY"); + + if (mVideoSink->retained_frame_width != mCurrentWidth || + mVideoSink->retained_frame_height != mCurrentHeight) + // *TODO: also check for change in format + { + // just resize container, don't consume frame + int neww = mVideoSink->retained_frame_width; + int newh = mVideoSink->retained_frame_height; + + int newd = 4; + mTextureFormatPrimary = GL_RGBA; + mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; + + /* + int newd = SLVPixelFormatBytes[mVideoSink->retained_frame_format]; + if (SLV_PF_BGRX == mVideoSink->retained_frame_format) + { + mTextureFormatPrimary = GL_BGRA; + mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; + } + else + { + mTextureFormatPrimary = GL_RGBA; + mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; + } + */ + + GST_OBJECT_UNLOCK(mVideoSink); + + mCurrentRowbytes = neww * newd; + DEBUGMSG("video container resized to %dx%d", + neww, newh); + + mDepth = newd; + mCurrentWidth = neww; + mCurrentHeight = newh; + sizeChanged(); + return true; + } + + if (mPixels && + mCurrentHeight <= mHeight && + mCurrentWidth <= mWidth && + !mTextureSegmentName.empty()) + { + // we're gonna totally consume this frame - reset 'ready' flag + mVideoSink->retained_frame_ready = FALSE; + int destination_rowbytes = mWidth * mDepth; + for (int row=0; row<mCurrentHeight; ++row) + { + memcpy(&mPixels + [destination_rowbytes * row], + &mVideoSink->retained_frame_data + [mCurrentRowbytes * row], + mCurrentRowbytes); + } + + GST_OBJECT_UNLOCK(mVideoSink); + DEBUGMSG("NEW FRAME REALLY TRULY CONSUMED, TELLING HOST"); + + setDirty(0,0,mCurrentWidth,mCurrentHeight); + } + else + { + // new frame ready, but we're not ready to + // consume it. + + GST_OBJECT_UNLOCK(mVideoSink); + + DEBUGMSG("NEW FRAME not consumed, still waiting for a shm segment and/or shm resize"); + } + + return true; + } + else + { + // nothing to do yet. + GST_OBJECT_UNLOCK(mVideoSink); + return true; + } + } + + return true; +} + + +void +MediaPluginGStreamer010::mouseDown( int x, int y ) +{ + // do nothing +} + +void +MediaPluginGStreamer010::mouseUp( int x, int y ) +{ + // do nothing +} + +void +MediaPluginGStreamer010::mouseMove( int x, int y ) +{ + // do nothing +} + + +bool +MediaPluginGStreamer010::pause() +{ + DEBUGMSG("pausing media..."); + // todo: error-check this? + llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); + return true; +} + +bool +MediaPluginGStreamer010::stop() +{ + DEBUGMSG("stopping media..."); + // todo: error-check this? + llgst_element_set_state(mPlaybin, GST_STATE_READY); + return true; +} + +bool +MediaPluginGStreamer010::play(double rate) +{ + // NOTE: we don't actually support non-natural rate. + + DEBUGMSG("playing media... rate=%f", rate); + // todo: error-check this? + llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); + return true; +} + +bool +MediaPluginGStreamer010::setVolume( float volume ) +{ + // we try to only update volume as conservatively as + // possible, as many gst-plugins-base versions up to at least + // November 2008 have critical race-conditions in setting volume - sigh + if (mVolume == volume) + return true; // nothing to do, everything's fine + + mVolume = volume; + if (mDoneInit && mPlaybin) + { + g_object_set(mPlaybin, "volume", mVolume, NULL); + return true; + } + + return false; +} + +bool +MediaPluginGStreamer010::seek(double time_sec) +{ + bool success = false; + if (mDoneInit && mPlaybin) + { + success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME, + GstSeekFlags(GST_SEEK_FLAG_FLUSH | + GST_SEEK_FLAG_KEY_UNIT), + GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND), + GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); + } + DEBUGMSG("MEDIA SEEK REQUEST to %fsec result was %d", + float(time_sec), int(success)); + return success; +} + +bool +MediaPluginGStreamer010::getTimePos(double &sec_out) +{ + bool got_position = false; + if (mPlaybin) + { + gint64 pos; + GstFormat timefmt = GST_FORMAT_TIME; + got_position = + llgst_element_query_position && + llgst_element_query_position(mPlaybin, + &timefmt, + &pos); + got_position = got_position + && (timefmt == GST_FORMAT_TIME); + // GStreamer may have other ideas, but we consider the current position + // undefined if not PLAYING or PAUSED + got_position = got_position && + (GST_STATE(mPlaybin) == GST_STATE_PLAYING || + GST_STATE(mPlaybin) == GST_STATE_PAUSED); + if (got_position && !GST_CLOCK_TIME_IS_VALID(pos)) + { + if (GST_STATE(mPlaybin) == GST_STATE_PLAYING) + { + // if we're playing then we treat an invalid clock time + // as 0, for complicated reasons (insert reason here) + pos = 0; + } + else + { + got_position = false; + } + + } + // If all the preconditions succeeded... we can trust the result. + if (got_position) + { + sec_out = double(pos) / double(GST_SECOND); // gst to sec + } + } + return got_position; +} + +bool +MediaPluginGStreamer010::load() +{ + if (!mDoneInit) + return false; // error + + setStatus(STATUS_LOADING); + + DEBUGMSG("setting up media..."); + + mIsLooping = false; + mVolume = 0.1234567; // minor hack to force an initial volume update + + // Create a pumpable main-loop for this media + mPump = g_main_loop_new (NULL, FALSE); + if (!mPump) + { + setStatus(STATUS_ERROR); + return false; // error + } + + // instantiate a playbin element to do the hard work + mPlaybin = llgst_element_factory_make ("playbin", "play"); + if (!mPlaybin) + { + setStatus(STATUS_ERROR); + return false; // error + } + + // get playbin's bus + GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin)); + if (!bus) + { + setStatus(STATUS_ERROR); + return false; // error + } + mBusWatchID = llgst_bus_add_watch (bus, + llmediaimplgstreamer_bus_callback, + this); + llgst_object_unref (bus); + + if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) { + // instantiate a custom video sink + mVideoSink = + GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo")); + if (!mVideoSink) + { + WARNMSG("Could not instantiate private-slvideo element."); + // todo: cleanup. + setStatus(STATUS_ERROR); + return false; // error + } + + // connect the pieces + g_object_set(mPlaybin, "video-sink", mVideoSink, NULL); + } + + return true; +} + +bool +MediaPluginGStreamer010::unload () +{ + if (!mDoneInit) + return false; // error + + DEBUGMSG("unloading media..."); + + // stop getting callbacks for this bus + g_source_remove(mBusWatchID); + mBusWatchID = 0; + + if (mPlaybin) + { + llgst_element_set_state (mPlaybin, GST_STATE_NULL); + llgst_object_unref (GST_OBJECT (mPlaybin)); + mPlaybin = NULL; + } + + if (mPump) + { + g_main_loop_quit(mPump); + mPump = NULL; + } + + mVideoSink = NULL; + + setStatus(STATUS_NONE); + + return true; +} + + +//static +bool +MediaPluginGStreamer010::startup() +{ + // first - check if GStreamer is explicitly disabled + if (NULL != getenv("LL_DISABLE_GSTREAMER")) + return false; + + // only do global GStreamer initialization once. + if (!mDoneInit) + { + g_thread_init(NULL); + + // Init the glib type system - we need it. + g_type_init(); + + // Get symbols! +#if LL_DARWIN + if (! grab_gst_syms("libgstreamer-0.10.dylib", + "libgstvideo-0.10.dylib") ) +#elseif LL_WINDOWS + if (! grab_gst_syms("libgstreamer-0.10.dll", + "libgstvideo-0.10.dll") ) +#else // linux or other ELFy unixoid + if (! grab_gst_syms("libgstreamer-0.10.so.0", + "libgstvideo-0.10.so.0") ) +#endif + { + WARNMSG("Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled."); + return false; + } + + if (llgst_segtrap_set_enabled) + { + llgst_segtrap_set_enabled(FALSE); + } + else + { + WARNMSG("gst_segtrap_set_enabled() is not available; plugin crashes won't be caught."); + } + +#if LL_LINUX + // Gstreamer tries a fork during init, waitpid-ing on it, + // which conflicts with any installed SIGCHLD handler... + struct sigaction tmpact, oldact; + if (llgst_registry_fork_set_enabled) { + // if we can disable SIGCHLD-using forking behaviour, + // do it. + llgst_registry_fork_set_enabled(false); + } + else { + // else temporarily install default SIGCHLD handler + // while GStreamer initialises + tmpact.sa_handler = SIG_DFL; + sigemptyset( &tmpact.sa_mask ); + tmpact.sa_flags = SA_SIGINFO; + sigaction(SIGCHLD, &tmpact, &oldact); + } +#endif // LL_LINUX + + // Protect against GStreamer resetting the locale, yuck. + static std::string saved_locale; + saved_locale = setlocale(LC_ALL, NULL); + + // finally, try to initialize GStreamer! + GError *err = NULL; + gboolean init_gst_success = llgst_init_check(NULL, NULL, &err); + + // restore old locale + setlocale(LC_ALL, saved_locale.c_str() ); + +#if LL_LINUX + // restore old SIGCHLD handler + if (!llgst_registry_fork_set_enabled) + sigaction(SIGCHLD, &oldact, NULL); +#endif // LL_LINUX + + if (!init_gst_success) // fail + { + if (err) + { + WARNMSG("GST init failed: %s", err->message); + g_error_free(err); + } + else + { + WARNMSG("GST init failed for unspecified reason."); + } + return false; + } + + // Init our custom plugins - only really need do this once. + gst_slvideo_init_class(); + + mDoneInit = true; + } + + return true; +} + + +void +MediaPluginGStreamer010::sizeChanged() +{ + // the shared writing space has possibly changed size/location/whatever + + // Check to see whether the movie's NATURAL size has been set yet + if (1 == mNaturalWidth && + 1 == mNaturalHeight) + { + mNaturalWidth = mCurrentWidth; + mNaturalHeight = mCurrentHeight; + DEBUGMSG("Media NATURAL size better detected as %dx%d", + mNaturalWidth, mNaturalHeight); + } + + // if the size has changed then the shm has changed and the app needs telling + if (mCurrentWidth != mPreviousWidth || + mCurrentHeight != mPreviousHeight) + { + mPreviousWidth = mCurrentWidth; + mPreviousHeight = mCurrentHeight; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); + message.setValue("name", mTextureSegmentName); + message.setValueS32("width", mNaturalWidth); + message.setValueS32("height", mNaturalHeight); + DEBUGMSG("<--- Sending size change request to application with name: '%s' - natural size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight); + sendMessage(message); + } +} + + + +//static +bool +MediaPluginGStreamer010::closedown() +{ + if (!mDoneInit) + return false; // error + + ungrab_gst_syms(); + + mDoneInit = false; + + return true; +} + +MediaPluginGStreamer010::~MediaPluginGStreamer010() +{ + DEBUGMSG("MediaPluginGStreamer010 destructor"); + + closedown(); + + DEBUGMSG("GStreamer010 closing down"); +} + + +std::string +MediaPluginGStreamer010::getVersion() +{ + std::string plugin_version = "GStreamer010 media plugin, GStreamer version "; + if (mDoneInit && + llgst_version) + { + guint major, minor, micro, nano; + llgst_version(&major, &minor, µ, &nano); + plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor, (unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR, (unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO); + } + else + { + plugin_version += "(unknown)"; + } + return plugin_version; +} + +void MediaPluginGStreamer010::receiveMessage(const char *message_string) +{ + //std::cerr << "MediaPluginGStreamer010::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if(message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; + message.setValueLLSD("versions", versions); + + if ( load() ) + { + DEBUGMSG("GStreamer010 media instance set up"); + } + else + { + WARNMSG("GStreamer010 media instance failed to set up"); + } + + message.setValue("plugin_version", getVersion()); + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. + double time = message_in.getValueReal("time"); + + // Convert time to milliseconds for update() + update((int)(time * 1000.0f)); + } + else if(message_name == "cleanup") + { + unload(); + closedown(); + } + else if(message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + std::ostringstream str; + INFOMSG("MediaPluginGStreamer010::receiveMessage: shared memory added, name: %s, size: %d, address: %p", name.c_str(), int(info.mSize), info.mAddress); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + } + else if(message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + DEBUGMSG("MediaPluginGStreamer010::receiveMessage: shared memory remove, name = %s", name.c_str()); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + if(mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + + // Make sure the movie decoder is no longer pointed at the shared segment. + sizeChanged(); + } + mSharedSegments.erase(iter); + } + else + { + WARNMSG("MediaPluginGStreamer010::receiveMessage: unknown shared memory region!"); + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { + std::ostringstream str; + INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown base message: %s", message_name.c_str()); + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if(message_name == "init") + { + // Plugin gets to decide the texture parameters to use. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + // lame to have to decide this now, it depends on the movie. Oh well. + mDepth = 4; + + mCurrentWidth = 1; + mCurrentHeight = 1; + mPreviousWidth = 1; + mPreviousHeight = 1; + mNaturalWidth = 1; + mNaturalHeight = 1; + mWidth = 1; + mHeight = 1; + mTextureWidth = 1; + mTextureHeight = 1; + + message.setValueU32("format", GL_RGBA); + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV); + + message.setValueS32("depth", mDepth); + message.setValueS32("default_width", mWidth); + message.setValueS32("default_height", mHeight); + message.setValueU32("internalformat", GL_RGBA8); + message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. + message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale + sendMessage(message); + } + else if(message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + std::ostringstream str; + INFOMSG("---->Got size change instruction from application with shm name: %s - size is %d x %d", name.c_str(), width, height); + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + if(!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + INFOMSG("*** Got size change with matching shm, new size is %d x %d", width, height); + INFOMSG("*** Got size change with matching shm, texture size size is %d x %d", texture_width, texture_height); + + mPixels = (unsigned char*)iter->second.mAddress; + mTextureSegmentName = name; + mWidth = width; + mHeight = height; + + if (texture_width > 1 || + texture_height > 1) // not a dummy size from the app, a real explicit forced size + { + INFOMSG("**** = REAL RESIZE REQUEST FROM APP"); + + GST_OBJECT_LOCK(mVideoSink); + mVideoSink->resize_forced_always = true; + mVideoSink->resize_try_width = texture_width; + mVideoSink->resize_try_height = texture_height; + GST_OBJECT_UNLOCK(mVideoSink); + } + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + } + } + } + else if(message_name == "load_uri") + { + std::string uri = message_in.getValue("uri"); + navigateTo( uri ); + sendStatus(); + } + else if(message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); + + if(event == "down") + { + mouseDown(x, y); + } + else if(event == "up") + { + mouseUp(x, y); + } + else if(event == "move") + { + mouseMove(x, y); + }; + }; + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) + { + if(message_name == "stop") + { + stop(); + } + else if(message_name == "start") + { + double rate = 0.0; + if(message_in.hasValue("rate")) + { + rate = message_in.getValueReal("rate"); + } + // NOTE: we don't actually support rate. + play(rate); + } + else if(message_name == "pause") + { + pause(); + } + else if(message_name == "seek") + { + double time = message_in.getValueReal("time"); + // defer the actual seek in case we haven't + // really truly started yet in which case there + // is nothing to seek upon + mSeekWanted = true; + mSeekDestination = time; + } + else if(message_name == "set_loop") + { + bool loop = message_in.getValueBoolean("loop"); + mIsLooping = loop; + } + else if(message_name == "set_volume") + { + double volume = message_in.getValueReal("volume"); + setVolume(volume); + } + } + else + { + INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown message class: %s", message_class.c_str()); + } + } +} + +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + if (MediaPluginGStreamer010::startup()) + { + MediaPluginGStreamer010 *self = new MediaPluginGStreamer010(host_send_func, host_user_data); + *plugin_send_func = MediaPluginGStreamer010::staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; // okay + } + else + { + return -1; // failed to init + } +} + +#else // LL_GSTREAMER010_ENABLED + +// Stubbed-out class with constructor/destructor (necessary or windows linker +// will just think its dead code and optimize it all out) +class MediaPluginGStreamer010 : public MediaPluginBase +{ +public: + MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginGStreamer010(); + /* virtual */ void receiveMessage(const char *message_string); +}; + +MediaPluginGStreamer010::MediaPluginGStreamer010( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) : + MediaPluginBase(host_send_func, host_user_data) +{ + // no-op +} + +MediaPluginGStreamer010::~MediaPluginGStreamer010() +{ + // no-op +} + +void MediaPluginGStreamer010::receiveMessage(const char *message_string) +{ + // no-op +} + +// We're building without GStreamer enabled. Just refuse to initialize. +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + return -1; +} + +#endif // LL_GSTREAMER010_ENABLED diff --git a/linden/indra/media_plugins/quicktime/CMakeLists.txt b/linden/indra/media_plugins/quicktime/CMakeLists.txt new file mode 100644 index 0000000..db11c9a --- /dev/null +++ b/linden/indra/media_plugins/quicktime/CMakeLists.txt @@ -0,0 +1,83 @@ +# -*- cmake -*- + +project(media_plugin_quicktime) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLPlugin) +include(LLMath) +include(LLRender) +include(LLWindow) +include(Linking) +include(PluginAPI) +include(MediaPluginBase) +include(FindOpenGL) +include(QuickTimePlugin) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} +) + +if (DARWIN) + include(CMakeFindFrameworks) + find_library(CARBON_LIBRARY Carbon) +endif (DARWIN) + + +### media_plugin_quicktime + +set(media_plugin_quicktime_SOURCE_FILES + media_plugin_quicktime.cpp + ) + +add_library(media_plugin_quicktime + SHARED + ${media_plugin_quicktime_SOURCE_FILES} +) + +target_link_libraries(media_plugin_quicktime + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${QUICKTIME_LIBRARY} + ${PLUGIN_API_WINDOWS_LIBRARIES} +) + +add_dependencies(media_plugin_quicktime + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} +) + +if (QUICKTIME) + + add_definitions(-DLL_QUICKTIME_ENABLED=1) + + if (DARWIN) + # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name + set_target_properties( + media_plugin_quicktime + PROPERTIES + PREFIX "" + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path" + LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" + ) + +# We use a bunch of deprecated system APIs. + set_source_files_properties( + media_plugin_quicktime.cpp PROPERTIES + COMPILE_FLAGS -Wno-deprecated-declarations + ) + find_library(CARBON_LIBRARY Carbon) + target_link_libraries(media_plugin_quicktime ${CARBON_LIBRARY}) + endif (DARWIN) +endif (QUICKTIME) + diff --git a/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp new file mode 100644 index 0000000..51cc8dd --- /dev/null +++ b/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -0,0 +1,985 @@ +/** + * @file media_plugin_quicktime.cpp + * @brief QuickTime plugin for LLMedia API plugin system + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llgl.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#if LL_QUICKTIME_ENABLED + +#if defined(LL_DARWIN) + #include <QuickTime/QuickTime.h> +#elif defined(LL_WINDOWS) + #include "MacTypes.h" + #include "QTML.h" + #include "Movies.h" + #include "QDoffscreen.h" + #include "FixMath.h" +#endif + +// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint +//////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginQuickTime : public MediaPluginBase +{ +public: + MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginQuickTime(); + + /* virtual */ void receiveMessage(const char *message_string); + +private: + + int mNaturalWidth; + int mNaturalHeight; + Movie mMovieHandle; + GWorldPtr mGWorldHandle; + ComponentInstance mMovieController; + int mCurVolume; + bool mMediaSizeChanging; + bool mIsLooping; + const int mMinWidth; + const int mMaxWidth; + const int mMinHeight; + const int mMaxHeight; + F64 mPlayRate; + + enum ECommand { + COMMAND_NONE, + COMMAND_STOP, + COMMAND_PLAY, + COMMAND_FAST_FORWARD, + COMMAND_FAST_REWIND, + COMMAND_PAUSE, + COMMAND_SEEK, + }; + ECommand mCommand; + + // Override this to add current time and duration to the message + /*virtual*/ void setDirty(int left, int top, int right, int bottom) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); + + message.setValueS32("left", left); + message.setValueS32("top", top); + message.setValueS32("right", right); + message.setValueS32("bottom", bottom); + + if(mMovieHandle) + { + message.setValueReal("current_time", getCurrentTime()); + message.setValueReal("duration", getDuration()); + message.setValueReal("current_rate", Fix2X(GetMovieRate(mMovieHandle))); + } + + sendMessage(message); + } + + + static Rect rectFromSize(int width, int height) + { + Rect result; + + + result.left = 0; + result.top = 0; + result.right = width; + result.bottom = height; + + return result; + } + + Fixed getPlayRate(void) + { + Fixed result; + if(mPlayRate == 0.0f) + { + // Default to the movie's preferred rate + result = GetMoviePreferredRate(mMovieHandle); + if(result == 0) + { + // Don't return a 0 play rate, ever. + std::cerr << "Movie's preferred rate is 0, forcing to 1.0." << std::endl; + result = X2Fix(1.0f); + } + } + else + { + result = X2Fix(mPlayRate); + } + + return result; + } + + void load( const std::string url ) + { + if ( url.empty() ) + return; + + // Stop and unload any existing movie before starting another one. + unload(); + + setStatus(STATUS_LOADING); + + //In case std::string::c_str() makes a copy of the url data, + //make sure there is memory to hold it before allocating memory for handle. + //if fails, NewHandleClear(...) should return NULL. + const char* url_string = url.c_str() ; + Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) ); + if ( NULL == handle || noErr != MemError() || NULL == *handle ) + { + setStatus(STATUS_ERROR); + return; + } + + BlockMove( url_string, *handle, ( Size )( url.length() + 1 ) ); + + OSErr err = NewMovieFromDataRef( &mMovieHandle, newMovieActive | newMovieDontInteractWithUser | newMovieAsyncOK | newMovieIdleImportOK, nil, handle, URLDataHandlerSubType ); + DisposeHandle( handle ); + if ( noErr != err ) + { + setStatus(STATUS_ERROR); + return; + }; + + // do pre-roll actions (typically fired for streaming movies but not always) + PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this ); + + Rect movie_rect = rectFromSize(mWidth, mHeight); + + // make a new movie controller + mMovieController = NewMovieController( mMovieHandle, &movie_rect, mcNotVisible | mcTopLeftMovie ); + + // movie controller + MCSetActionFilterWithRefCon( mMovieController, mcActionFilterCallBack, ( long )this ); + + SetMoviePlayHints( mMovieHandle, hintsAllowDynamicResize, hintsAllowDynamicResize ); + + // function that gets called when a frame is drawn + SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this ); + + setStatus(STATUS_LOADED); + + sizeChanged(); + }; + + bool unload() + { + if ( mMovieHandle ) + { + StopMovie( mMovieHandle ); + if ( mMovieController ) + { + MCMovieChanged( mMovieController, mMovieHandle ); + }; + }; + + if ( mMovieController ) + { + MCSetActionFilterWithRefCon( mMovieController, NULL, (long)this ); + DisposeMovieController( mMovieController ); + mMovieController = NULL; + }; + + if ( mMovieHandle ) + { + SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, nil, ( long )this ); + DisposeMovie( mMovieHandle ); + mMovieHandle = NULL; + }; + + if ( mGWorldHandle ) + { + DisposeGWorld( mGWorldHandle ); + mGWorldHandle = NULL; + }; + + setStatus(STATUS_NONE); + + return true; + } + + bool navigateTo( const std::string url ) + { + unload(); + load( url ); + + return true; + }; + + bool sizeChanged() + { + if ( ! mMovieHandle ) + return false; + + // Check to see whether the movie's natural size has updated + { + int width, height; + getMovieNaturalSize(&width, &height); + if((width != 0) && (height != 0) && ((width != mNaturalWidth) || (height != mNaturalHeight))) + { + mNaturalWidth = width; + mNaturalHeight = height; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); + message.setValue("name", mTextureSegmentName); + message.setValueS32("width", width); + message.setValueS32("height", height); + sendMessage(message); + //std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl; + } + } + + // sanitize destination size + Rect dest_rect = rectFromSize(mWidth, mHeight); + + // media depth won't change + int depth_bits = mDepth * 8; + long rowbytes = mDepth * mTextureWidth; + + GWorldPtr old_gworld_handle = mGWorldHandle; + + if(mPixels != NULL) + { + // We have pixels. Set up a GWorld pointing at the texture. + OSErr result = NewGWorldFromPtr( &mGWorldHandle, depth_bits, &dest_rect, NULL, NULL, 0, (Ptr)mPixels, rowbytes); + if ( noErr != result ) + { + // TODO: unrecoverable?? throw exception? return something? + return false; + } + } + else + { + // We don't have pixels. Create a fake GWorld we can point the movie at when it's not safe to render normally. + Rect tempRect = rectFromSize(1, 1); + OSErr result = NewGWorld( &mGWorldHandle, depth_bits, &tempRect, NULL, NULL, 0); + if ( noErr != result ) + { + // TODO: unrecoverable?? throw exception? return something? + return false; + } + } + + SetMovieGWorld( mMovieHandle, mGWorldHandle, GetGWorldDevice( mGWorldHandle ) ); + + // If the GWorld was already set up, delete it. + if(old_gworld_handle != NULL) + { + DisposeGWorld( old_gworld_handle ); + } + + // Set up the movie display matrix + { + // scale movie to fit rect and invert vertically to match opengl image format + MatrixRecord transform; + SetIdentityMatrix( &transform ); // transforms are additive so start from identify matrix + double scaleX = (double) mWidth / mNaturalWidth; + double scaleY = -1.0 * (double) mHeight / mNaturalHeight; + double centerX = mWidth / 2.0; + double centerY = mHeight / 2.0; + ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) ); + SetMovieMatrix( mMovieHandle, &transform ); + } + + // update movie controller + if ( mMovieController ) + { + MCSetControllerPort( mMovieController, mGWorldHandle ); + MCPositionController( mMovieController, &dest_rect, &dest_rect, + mcTopLeftMovie | mcPositionDontInvalidate ); + MCMovieChanged( mMovieController, mMovieHandle ); + } + + + // Emit event with size change so the calling app knows about it too + // TODO: + //LLMediaEvent event( this ); + //mEventEmitter.update( &LLMediaObserver::onMediaSizeChange, event ); + + return true; + } + + static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref ) + { + Boolean result = false; + + MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; + + switch( action ) + { + // handle window resizing + case mcActionControllerSizeChanged: + // Ensure that the movie draws correctly at the new size + self->sizeChanged(); + break; + + // Block any movie controller actions that open URLs. + case mcActionLinkToURL: + case mcActionGetNextURL: + case mcActionLinkToURLExtended: + // Prevent the movie controller from handling the message + result = true; + break; + + default: + break; + }; + + return result; + }; + + static OSErr movieDrawingCompleteCallback( Movie call_back_movie, long ref ) + { + MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; + + // IMPORTANT: typically, a consumer who is observing this event will set a flag + // when this event is fired then render later. Be aware that the media stream + // can change during this period - dimensions, depth, format etc. + //LLMediaEvent event( self ); +// self->updateQuickTime(); + // TODO ^^^ + + if ( self->mWidth > 0 && self->mHeight > 0 ) + self->setDirty( 0, 0, self->mWidth, self->mHeight ); + + return noErr; + }; + + static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref ) + { + //MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; + + // TODO: + //LLMediaEvent event( self ); + //self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event ); + }; + + + void rewind() + { + GoToBeginningOfMovie( mMovieHandle ); + MCMovieChanged( mMovieController, mMovieHandle ); + }; + + bool processState() + { + if ( mCommand == COMMAND_PLAY ) + { + if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING ) + { + long state = GetMovieLoadState( mMovieHandle ); + + if ( state >= kMovieLoadStatePlaythroughOK ) + { + // if the movie is at the end (generally because it reached it naturally) + // and we play is requested, jump back to the start of the movie. + // note: this is different from having loop flag set. + if ( IsMovieDone( mMovieHandle ) ) + { + Fixed rate = X2Fix( 0.0 ); + MCDoAction( mMovieController, mcActionPlay, (void*)rate ); + rewind(); + }; + + MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() ); + MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); + setStatus(STATUS_PLAYING); + mCommand = COMMAND_NONE; + }; + }; + } + else + if ( mCommand == COMMAND_STOP ) + { + if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED ) + { + if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) + { + Fixed rate = X2Fix( 0.0 ); + MCDoAction( mMovieController, mcActionPlay, (void*)rate ); + rewind(); + + setStatus(STATUS_LOADED); + mCommand = COMMAND_NONE; + }; + }; + } + else + if ( mCommand == COMMAND_PAUSE ) + { + if ( mStatus == STATUS_PLAYING ) + { + if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) + { + Fixed rate = X2Fix( 0.0 ); + MCDoAction( mMovieController, mcActionPlay, (void*)rate ); + setStatus(STATUS_PAUSED); + mCommand = COMMAND_NONE; + }; + }; + }; + + return true; + }; + + void play(F64 rate) + { + mPlayRate = rate; + mCommand = COMMAND_PLAY; + }; + + void stop() + { + mCommand = COMMAND_STOP; + }; + + void pause() + { + mCommand = COMMAND_PAUSE; + }; + + void getMovieNaturalSize(int *movie_width, int *movie_height) + { + Rect rect; + + GetMovieNaturalBoundsRect( mMovieHandle, &rect ); + + int width = ( rect.right - rect.left ); + int height = ( rect.bottom - rect.top ); + + // make sure width and height fall in valid range + if ( width < mMinWidth ) + width = mMinWidth; + + if ( width > mMaxWidth ) + width = mMaxWidth; + + if ( height < mMinHeight ) + height = mMinHeight; + + if ( height > mMaxHeight ) + height = mMaxHeight; + + // return the new rect + *movie_width = width; + *movie_height = height; + } + + void updateQuickTime(int milliseconds) + { + if ( ! mMovieHandle ) + return; + + if ( ! mMovieController ) + return; + + // service QuickTime + // Calling it this way doesn't have good behavior on Windows... +// MoviesTask( mMovieHandle, milliseconds ); + // This was the original, but I think using both MoviesTask and MCIdle is redundant. Trying with only MCIdle. +// MoviesTask( mMovieHandle, 0 ); + + MCIdle( mMovieController ); + + if ( ! mGWorldHandle ) + return; + + if ( mMediaSizeChanging ) + return; + + // update state machine + processState(); + + // special code for looping - need to rewind at the end of the movie + if ( mIsLooping ) + { + // QT call to see if we are at the end - can't do with controller + if ( IsMovieDone( mMovieHandle ) ) + { + // go back to start + rewind(); + + if ( mMovieController ) + { + // kick off new play + MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() ); + + // set the volume + MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); + }; + }; + }; + }; + + int getDataWidth() const + { + if ( mGWorldHandle ) + { + int depth = mDepth; + + if (depth < 1) + depth = 1; + + // ALWAYS use the row bytes from the PixMap if we have a GWorld because + // sometimes it's not the same as mMediaDepth * mMediaWidth ! + PixMapHandle pix_map_handle = GetGWorldPixMap( mGWorldHandle ); + return QTGetPixMapHandleRowBytes( pix_map_handle ) / depth; + } + else + { + // TODO : return LLMediaImplCommon::getaDataWidth(); + return 0; + } + }; + + void seek( F64 time ) + { + if ( mMovieController ) + { + TimeRecord when; + when.scale = GetMovieTimeScale( mMovieHandle ); + when.base = 0; + + // 'time' is in (floating point) seconds. The timebase time will be in 'units', where + // there are 'scale' units per second. + SInt64 raw_time = ( SInt64 )( time * (double)( when.scale ) ); + + when.value.hi = ( SInt32 )( raw_time >> 32 ); + when.value.lo = ( SInt32 )( ( raw_time & 0x00000000FFFFFFFF ) ); + + MCDoAction( mMovieController, mcActionGoToTime, &when ); + }; + }; + + F64 getDuration() + { + TimeValue duration = GetMovieDuration( mMovieHandle ); + TimeValue scale = GetMovieTimeScale( mMovieHandle ); + + return (F64)duration / (F64)scale; + }; + + F64 getCurrentTime() + { + TimeValue curr_time = GetMovieTime( mMovieHandle, 0 ); + TimeValue scale = GetMovieTimeScale( mMovieHandle ); + + return (F64)curr_time / (F64)scale; + }; + + void setVolume( F64 volume ) + { + mCurVolume = (short)(volume * ( double ) 0x100 ); + + if ( mMovieController ) + { + MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void update(int milliseconds = 0) + { + updateQuickTime(milliseconds); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseDown( int x, int y ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseUp( int x, int y ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseMove( int x, int y ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void keyPress( unsigned char key ) + { + }; + +}; + +MediaPluginQuickTime::MediaPluginQuickTime( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) : + MediaPluginBase(host_send_func, host_user_data), + mMinWidth( 0 ), + mMaxWidth( 2048 ), + mMinHeight( 0 ), + mMaxHeight( 2048 ) +{ +// std::cerr << "MediaPluginQuickTime constructor" << std::endl; + + mNaturalWidth = -1; + mNaturalHeight = -1; + mMovieHandle = 0; + mGWorldHandle = 0; + mMovieController = 0; + mCurVolume = 0x99; + mMediaSizeChanging = false; + mIsLooping = false; + mCommand = COMMAND_NONE; + mPlayRate = 0.0f; + mStatus = STATUS_NONE; +} + +MediaPluginQuickTime::~MediaPluginQuickTime() +{ +// std::cerr << "MediaPluginQuickTime destructor" << std::endl; + + ExitMovies(); + +#ifdef LL_WINDOWS + TerminateQTML(); +// std::cerr << "QuickTime closing down" << std::endl; +#endif +} + + +void MediaPluginQuickTime::receiveMessage(const char *message_string) +{ +// std::cerr << "MediaPluginQuickTime::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if(message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + // Normally a plugin would only specify one of these two subclasses, but this is a demo... +// versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; + message.setValueLLSD("versions", versions); + + #ifdef LL_WINDOWS + if ( InitializeQTML( 0L ) != noErr ) + { + //TODO: If no QT on Windows, this fails - respond accordingly. + //return false; + } + else + { +// std::cerr << "QuickTime initialized" << std::endl; + }; + #endif + + EnterMovies(); + + std::string plugin_version = "QuickTime media plugin, QuickTime version "; + + long version = 0; + Gestalt( gestaltQuickTimeVersion, &version ); + std::ostringstream codec( "" ); + codec << std::hex << version << std::dec; + plugin_version += codec.str(); + message.setValue("plugin_version", plugin_version); + sendMessage(message); + + // Plugin gets to decide the texture parameters to use. + message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + #if defined(LL_WINDOWS) + // Values for Windows + mDepth = 3; + message.setValueU32("format", GL_RGB); + message.setValueU32("type", GL_UNSIGNED_BYTE); + + // We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even. + // Padding to a multiple of 3*32 guarantees it'll divide out properly. + message.setValueU32("padding", 32 * 3); + #else + // Values for Mac + mDepth = 4; + message.setValueU32("format", GL_BGRA_EXT); + #ifdef __BIG_ENDIAN__ + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV ); + #else + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8); + #endif + + // Pad texture width to a multiple of 32 bytes, to line up with cache lines. + message.setValueU32("padding", 32); + #endif + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. + message.setValueBoolean("allow_downsample", true); + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. + F64 time = message_in.getValueReal("time"); + + // Convert time to milliseconds for update() + update((int)(time * 1000.0f)); + } + else if(message_name == "cleanup") + { + // TODO: clean up here + } + else if(message_name == "shm_added") + { + SharedSegmentInfo info; + U64 address_lo = message_in.getValueU32("address"); + U64 address_hi = message_in.hasValue("address_1") ? message_in.getValueU32("address_1") : 0; + info.mAddress = (void*)((address_lo) | + (address_hi * (U64(1)<<31))); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + +// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory added, name: " << name +// << ", size: " << info.mSize +// << ", address: " << info.mAddress +// << std::endl; + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if(message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + +// std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory remove, name = " << name << std::endl; + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + if(mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + + // Make sure the movie GWorld is no longer pointed at the shared segment. + sizeChanged(); + } + mSharedSegments.erase(iter); + } + else + { +// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown shared memory region!" << std::endl; + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { +// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if(message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + //std::cerr << "---->Got size change instruction from application with name: " << name << " - size is " << width << " x " << height << std::endl; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + if(!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { +// std::cerr << "%%% Got size change, new size is " << width << " by " << height << std::endl; +// std::cerr << "%%%% texture size is " << texture_width << " by " << texture_height << std::endl; + + mPixels = (unsigned char*)iter->second.mAddress; + mTextureSegmentName = name; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + + mMediaSizeChanging = false; + + sizeChanged(); + + update(); + }; + }; + } + else if(message_name == "load_uri") + { + std::string uri = message_in.getValue("uri"); + load( uri ); + sendStatus(); + } + else if(message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); + + if(event == "down") + { + mouseDown(x, y); + } + else if(event == "up") + { + mouseUp(x, y); + } + else if(event == "move") + { + mouseMove(x, y); + }; + }; + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) + { + if(message_name == "stop") + { + stop(); + } + else if(message_name == "start") + { + F64 rate = 0.0; + if(message_in.hasValue("rate")) + { + rate = message_in.getValueReal("rate"); + } + play(rate); + } + else if(message_name == "pause") + { + pause(); + } + else if(message_name == "seek") + { + F64 time = message_in.getValueReal("time"); + seek(time); + } + else if(message_name == "set_loop") + { + bool loop = message_in.getValueBoolean("loop"); + mIsLooping = loop; + } + else if(message_name == "set_volume") + { + F64 volume = message_in.getValueReal("volume"); + setVolume(volume); + } + } + else + { +// std::cerr << "MediaPluginQuickTime::receiveMessage: unknown message class: " << message_class << std::endl; + }; + }; +} + +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + MediaPluginQuickTime *self = new MediaPluginQuickTime(host_send_func, host_user_data); + *plugin_send_func = MediaPluginQuickTime::staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; +} + +#else // LL_QUICKTIME_ENABLED + +// Stubbed-out class with constructor/destructor (necessary or windows linker +// will just think its dead code and optimize it all out) +class MediaPluginQuickTime : public MediaPluginBase +{ +public: + MediaPluginQuickTime(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginQuickTime(); + /* virtual */ void receiveMessage(const char *message_string); +}; + +MediaPluginQuickTime::MediaPluginQuickTime( + LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) : + MediaPluginBase(host_send_func, host_user_data) +{ + // no-op +} + +MediaPluginQuickTime::~MediaPluginQuickTime() +{ + // no-op +} + +void MediaPluginQuickTime::receiveMessage(const char *message_string) +{ + // no-op +} + +// We're building without quicktime enabled. Just refuse to initialize. +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + return -1; +} + +#endif // LL_QUICKTIME_ENABLED diff --git a/linden/indra/media_plugins/webkit/CMakeLists.txt b/linden/indra/media_plugins/webkit/CMakeLists.txt new file mode 100644 index 0000000..5bccd58 --- /dev/null +++ b/linden/indra/media_plugins/webkit/CMakeLists.txt @@ -0,0 +1,82 @@ +# -*- cmake -*- + +project(media_plugin_webkit) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLPlugin) +include(LLMath) +include(LLRender) +include(LLWindow) +include(Linking) +include(PluginAPI) +include(MediaPluginBase) +include(FindOpenGL) + +include(WebKitLibPlugin) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} +) + + +### media_plugin_webkit + +set(media_plugin_webkit_SOURCE_FILES + media_plugin_webkit.cpp + ) + +add_library(media_plugin_webkit + SHARED + ${media_plugin_webkit_SOURCE_FILES} +) + +target_link_libraries(media_plugin_webkit + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${WEBKIT_PLUGIN_LIBRARIES} + ${PLUGIN_API_WINDOWS_LIBRARIES} +) + +add_dependencies(media_plugin_webkit + ${LLPLUGIN_LIBRARIES} + ${MEDIA_PLUGIN_BASE_LIBRARIES} + ${LLCOMMON_LIBRARIES} +) + +if (WINDOWS) + set_target_properties( + media_plugin_webkit + PROPERTIES + LINK_FLAGS "/MANIFEST:NO" + ) +endif (WINDOWS) + +if (DARWIN) + # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name + set_target_properties( + media_plugin_webkit + PROPERTIES + PREFIX "" + BUILD_WITH_INSTALL_RPATH 1 + INSTALL_NAME_DIR "@executable_path" + LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" + ) + + # copy the webkit dylib to the build directory + add_custom_command( + TARGET media_plugin_webkit POST_BUILD +# OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/libllqtwebkit.dylib + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/ + DEPENDS media_plugin_webkit ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib + ) + +endif (DARWIN) \ No newline at end of file diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp new file mode 100644 index 0000000..f115c28 --- /dev/null +++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -0,0 +1,932 @@ +/** + * @file media_plugin_webkit.cpp + * @brief Webkit plugin for LLMedia API plugin system + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llqtwebkit.h" + +#include "linden_common.h" +#include "indra_constants.h" // for indra keyboard codes + +#include "llgl.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#if LL_WINDOWS +#include <direct.h> +#else +#include <unistd.h> +#include <stdlib.h> +#endif + +#if LL_WINDOWS + // NOTE - This captures the module handle of the dll. This is used below + // to get the path to this dll for webkit initialization. + // I don't know how/if this can be done with apr... + namespace { HMODULE gModuleHandle;}; + BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) + { + gModuleHandle = (HMODULE) hinstDLL; + return TRUE; + } +#endif + +//////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginWebKit : + public MediaPluginBase, + public LLEmbeddedBrowserWindowObserver +{ +public: + MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginWebKit(); + + /*virtual*/ void receiveMessage(const char *message_string); + +private: + + enum + { + INIT_STATE_UNINITIALIZED, // Browser instance hasn't been set up yet + INIT_STATE_NAVIGATING, // Browser instance has been set up and initial navigate to about:blank has been issued + INIT_STATE_NAVIGATE_COMPLETE, // initial navigate to about:blank has completed + INIT_STATE_WAIT_REDRAW, // First real navigate begin has been received, waiting for page changed event to start handling redraws + INIT_STATE_RUNNING // All initialization gymnastics are complete. + }; + int mBrowserWindowId; + int mInitState; + std::string mInitialNavigateURL; + bool mNeedsUpdate; + + bool mCanCut; + bool mCanCopy; + bool mCanPaste; + int mLastMouseX; + int mLastMouseY; + bool mFirstFocus; + + //////////////////////////////////////////////////////////////////////////////// + // + void update(int milliseconds) + { + LLQtWebKit::getInstance()->pump( milliseconds ); + + checkEditState(); + + if(mInitState == INIT_STATE_NAVIGATE_COMPLETE) + { + if(!mInitialNavigateURL.empty()) + { + // We already have the initial navigate URL -- kick off the navigate. + LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, mInitialNavigateURL ); + mInitialNavigateURL.clear(); + } + } + + if ( (mInitState == INIT_STATE_RUNNING) && mNeedsUpdate ) + { + const unsigned char* browser_pixels = LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId ); + + unsigned int buffer_size = LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId ) * LLQtWebKit::getInstance()->getBrowserHeight( mBrowserWindowId ); + +// std::cerr << "webkit plugin: updating" << std::endl; + + // TODO: should get rid of this memcpy if possible + if ( mPixels && browser_pixels ) + { +// std::cerr << " memcopy of " << buffer_size << " bytes" << std::endl; + memcpy( mPixels, browser_pixels, buffer_size ); + } + + if ( mWidth > 0 && mHeight > 0 ) + { +// std::cerr << "Setting dirty, " << mWidth << " x " << mHeight << std::endl; + setDirty( 0, 0, mWidth, mHeight ); + } + + mNeedsUpdate = false; + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + bool initBrowser() + { + // already initialized + if ( mInitState > INIT_STATE_UNINITIALIZED ) + return true; + + // not enough information to initialize the browser yet. + if ( mWidth < 0 || mHeight < 0 || mDepth < 0 || + mTextureWidth < 0 || mTextureHeight < 0 ) + { + return false; + }; + + // set up directories + char cwd[ FILENAME_MAX ]; // I *think* this is defined on all platforms we use + if (NULL == getcwd( cwd, FILENAME_MAX - 1 )) + { + llwarns << "Couldn't get cwd - probably too long - failing to init." << llendl; + return false; + } + std::string application_dir = std::string( cwd ); + +#if LL_WINDOWS + // NOTE - On windows, at least, the component path is the + // location of this dll's image file. + std::string component_dir; + char dll_path[_MAX_PATH]; + DWORD len = GetModuleFileNameA(gModuleHandle, (LPCH)&dll_path, _MAX_PATH); + while(len && dll_path[ len ] != ('\\') ) + { + len--; + } + if(len >= 0) + { + dll_path[len] = 0; + component_dir = dll_path; + } + else + { + // NOTE - This case should be a rare exception. + // GetModuleFileNameA should always give you a full path. + component_dir = application_dir; + } +#else + std::string component_dir = application_dir; +#endif + std::string profileDir = application_dir + "/" + "browser_profile"; // cross platform? + + // window handle - needed on Windows and must be app window. +#if LL_WINDOWS + char window_title[ MAX_PATH ]; + GetConsoleTitleA( window_title, MAX_PATH ); + void* native_window_handle = (void*)FindWindowA( NULL, window_title ); +#else + void* native_window_handle = 0; +#endif + + // main browser initialization + bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, profileDir, native_window_handle ); + if ( result ) + { + // create single browser window + mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight ); + +#if LL_WINDOWS + // Enable plugins + LLQtWebKit::getInstance()->enablePlugins(true); +#elif LL_DARWIN + // Disable plugins + LLQtWebKit::getInstance()->enablePlugins(false); +#elif LL_LINUX + // Disable plugins + LLQtWebKit::getInstance()->enablePlugins(false); +#endif + + // tell LLQtWebKit about the size of the browser window + LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); + + // observer events that LLQtWebKit emits + LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this ); + + // append details to agent string + LLQtWebKit::getInstance()->setBrowserAgentId( "LLPluginMedia Web Browser" ); + + // don't flip bitmap + LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true ); + + // Set the background color to black - mostly for initial login page + LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, 0x00, 0x00, 0x00 ); + + // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns. + mInitState = INIT_STATE_NAVIGATING; + + // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance. + // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially + // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date. + LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" ); + + return true; + }; + + return false; + }; + + //////////////////////////////////////////////////////////////////////////////// + // virtual + void onCursorChanged(const EventType& event) + { + LLQtWebKit::ECursor llqt_cursor = (LLQtWebKit::ECursor)event.getIntValue(); + std::string name; + + switch(llqt_cursor) + { + case LLQtWebKit::C_ARROW: + name = "arrow"; + break; + case LLQtWebKit::C_IBEAM: + name = "ibeam"; + break; + case LLQtWebKit::C_SPLITV: + name = "splitv"; + break; + case LLQtWebKit::C_SPLITH: + name = "splith"; + break; + case LLQtWebKit::C_POINTINGHAND: + name = "hand"; + break; + + default: + llwarns << "Unknown cursor ID: " << (int)llqt_cursor << llendl; + break; + } + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "cursor_changed"); + message.setValue("name", name); + sendMessage(message); + } + + //////////////////////////////////////////////////////////////////////////////// + // virtual + void onPageChanged( const EventType& event ) + { + if(mInitState == INIT_STATE_WAIT_REDRAW) + { + mInitState = INIT_STATE_RUNNING; + } + + // flag that an update is required + mNeedsUpdate = true; + }; + + //////////////////////////////////////////////////////////////////////////////// + // virtual + void onNavigateBegin(const EventType& event) + { + if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); + message.setValue("uri", event.getEventUri()); + sendMessage(message); + + setStatus(STATUS_LOADING); + } + + if(mInitState == INIT_STATE_NAVIGATE_COMPLETE) + { + mInitState = INIT_STATE_WAIT_REDRAW; + } + + } + + //////////////////////////////////////////////////////////////////////////////// + // virtual + void onNavigateComplete(const EventType& event) + { + if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); + message.setValue("uri", event.getEventUri()); + message.setValueS32("result_code", event.getIntValue()); + message.setValue("result_string", event.getStringValue()); + message.setValueBoolean("history_back_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK)); + message.setValueBoolean("history_forward_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD)); + sendMessage(message); + + setStatus(STATUS_LOADED); + } + else if(mInitState == INIT_STATE_NAVIGATING) + { + mInitState = INIT_STATE_NAVIGATE_COMPLETE; + } + + } + + //////////////////////////////////////////////////////////////////////////////// + // virtual + void onUpdateProgress(const EventType& event) + { + if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "progress"); + message.setValueS32("percent", event.getIntValue()); + sendMessage(message); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // virtual + void onStatusTextChange(const EventType& event) + { + if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "status_text"); + message.setValue("status", event.getStringValue()); + sendMessage(message); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // virtual + void onTitleChange(const EventType& event) + { + if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", event.getStringValue()); + sendMessage(message); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // virtual + void onLocationChange(const EventType& event) + { + if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed"); + message.setValue("uri", event.getEventUri()); + sendMessage(message); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // virtual + void onClickLinkHref(const EventType& event) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href"); + message.setValue("uri", event.getStringValue()); + message.setValue("target", event.getStringValue2()); + sendMessage(message); + } + + //////////////////////////////////////////////////////////////////////////////// + // virtual + void onClickLinkNoFollow(const EventType& event) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); + message.setValue("uri", event.getStringValue()); + sendMessage(message); + } + + LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers) + { + int result = 0; + + if(modifiers.find("shift") != std::string::npos) + result |= LLQtWebKit::KM_MODIFIER_SHIFT; + + if(modifiers.find("alt") != std::string::npos) + result |= LLQtWebKit::KM_MODIFIER_ALT; + + if(modifiers.find("control") != std::string::npos) + result |= LLQtWebKit::KM_MODIFIER_CONTROL; + + if(modifiers.find("meta") != std::string::npos) + result |= LLQtWebKit::KM_MODIFIER_META; + + return (LLQtWebKit::EKeyboardModifier)result; + } + + + //////////////////////////////////////////////////////////////////////////////// + // + void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers) + { + int llqt_key; + + // The incoming values for 'key' will be the ones from indra_constants.h + // the outgoing values are the ones from llqtwebkit.h + + switch((KEY)key) + { + // This is the list that the llqtwebkit implementation actually maps into Qt keys. +// case KEY_XXX: llqt_key = LL_DOM_VK_CANCEL; break; +// case KEY_XXX: llqt_key = LL_DOM_VK_HELP; break; + case KEY_BACKSPACE: llqt_key = LL_DOM_VK_BACK_SPACE; break; + case KEY_TAB: llqt_key = LL_DOM_VK_TAB; break; +// case KEY_XXX: llqt_key = LL_DOM_VK_CLEAR; break; + case KEY_RETURN: llqt_key = LL_DOM_VK_RETURN; break; + case KEY_PAD_RETURN: llqt_key = LL_DOM_VK_ENTER; break; + case KEY_SHIFT: llqt_key = LL_DOM_VK_SHIFT; break; + case KEY_CONTROL: llqt_key = LL_DOM_VK_CONTROL; break; + case KEY_ALT: llqt_key = LL_DOM_VK_ALT; break; +// case KEY_XXX: llqt_key = LL_DOM_VK_PAUSE; break; + case KEY_CAPSLOCK: llqt_key = LL_DOM_VK_CAPS_LOCK; break; + case KEY_ESCAPE: llqt_key = LL_DOM_VK_ESCAPE; break; + case KEY_PAGE_UP: llqt_key = LL_DOM_VK_PAGE_UP; break; + case KEY_PAGE_DOWN: llqt_key = LL_DOM_VK_PAGE_DOWN; break; + case KEY_END: llqt_key = LL_DOM_VK_END; break; + case KEY_HOME: llqt_key = LL_DOM_VK_HOME; break; + case KEY_LEFT: llqt_key = LL_DOM_VK_LEFT; break; + case KEY_UP: llqt_key = LL_DOM_VK_UP; break; + case KEY_RIGHT: llqt_key = LL_DOM_VK_RIGHT; break; + case KEY_DOWN: llqt_key = LL_DOM_VK_DOWN; break; +// case KEY_XXX: llqt_key = LL_DOM_VK_PRINTSCREEN; break; + case KEY_INSERT: llqt_key = LL_DOM_VK_INSERT; break; + case KEY_DELETE: llqt_key = LL_DOM_VK_DELETE; break; +// case KEY_XXX: llqt_key = LL_DOM_VK_CONTEXT_MENU; break; + + default: + if(key < KEY_SPECIAL) + { + // Pass the incoming key through -- it should be regular ASCII, which should be correct for webkit. + llqt_key = key; + } + else + { + // Don't pass through untranslated special keys -- they'll be all wrong. + llqt_key = 0; + } + break; + } + +// std::cerr << "keypress, original code = 0x" << std::hex << key << ", converted code = 0x" << std::hex << llqt_key << std::dec << std::endl; + + if(llqt_key != 0) + { + LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, key_event, llqt_key, modifiers); + } + + checkEditState(); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers) + { + LLWString wstr = utf8str_to_wstring(utf8str); + + unsigned int i; + for(i=0; i < wstr.size(); i++) + { +// std::cerr << "unicode input, code = 0x" << std::hex << (unsigned long)(wstr[i]) << std::dec << std::endl; + + LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, wstr[i], modifiers); + } + + checkEditState(); + }; + + void checkEditState(void) + { + bool can_cut = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT); + bool can_copy = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY); + bool can_paste = LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE); + + if((can_cut != mCanCut) || (can_copy != mCanCopy) || (can_paste != mCanPaste)) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_state"); + + if(can_cut != mCanCut) + { + mCanCut = can_cut; + message.setValueBoolean("cut", can_cut); + } + + if(can_copy != mCanCopy) + { + mCanCopy = can_copy; + message.setValueBoolean("copy", can_copy); + } + + if(can_paste != mCanPaste) + { + mCanPaste = can_paste; + message.setValueBoolean("paste", can_paste); + } + + sendMessage(message); + + } + } + +}; + +MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) : + MediaPluginBase(host_send_func, host_user_data) +{ +// std::cerr << "MediaPluginWebKit constructor" << std::endl; + + mBrowserWindowId = 0; + mInitState = INIT_STATE_UNINITIALIZED; + mNeedsUpdate = true; + mCanCut = false; + mCanCopy = false; + mCanPaste = false; + mLastMouseX = 0; + mLastMouseY = 0; + mFirstFocus = true; +} + +MediaPluginWebKit::~MediaPluginWebKit() +{ + // unhook observer + LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this ); + + // clean up + LLQtWebKit::getInstance()->reset(); + +// std::cerr << "MediaPluginWebKit destructor" << std::endl; +} + +void MediaPluginWebKit::receiveMessage(const char *message_string) +{ +// std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if(message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + message.setValueLLSD("versions", versions); + + std::string plugin_version = "Webkit media plugin, Webkit version "; + plugin_version += LLQtWebKit::getInstance()->getVersion(); + message.setValue("plugin_version", plugin_version); + sendMessage(message); + + // Plugin gets to decide the texture parameters to use. + mDepth = 4; + + message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("default_width", 1024); + message.setValueS32("default_height", 1024); + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGBA); + message.setValueU32("format", GL_RGBA); + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", true); + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. + F64 time = message_in.getValueReal("time"); + + // Convert time to milliseconds for update() + update((int)(time * 1000.0f)); + } + else if(message_name == "cleanup") + { + // TODO: clean up here + } + else if(message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + +// std::cerr << "MediaPluginWebKit::receiveMessage: shared memory added, name: " << name +// << ", size: " << info.mSize +// << ", address: " << info.mAddress +// << std::endl; + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if(message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + +// std::cerr << "MediaPluginWebKit::receiveMessage: shared memory remove, name = " << name << std::endl; + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + if(mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + } + mSharedSegments.erase(iter); + } + else + { +// std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { +// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if(message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + if(!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + mPixels = (unsigned char*)iter->second.mAddress; + mWidth = width; + mHeight = height; + + // initialize (only gets called once) + initBrowser(); + + // size changed so tell the browser + LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); + +// std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight +// << ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl; + + S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId); + + // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response. + if(real_width <= texture_width) + { + texture_width = real_width; + } + else + { + // This won't work -- it'll be bigger than the allocated memory. This is a fatal error. +// std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl; + mDeleteMe = true; + return; + } + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + + }; + }; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + } + else if(message_name == "load_uri") + { + std::string uri = message_in.getValue("uri"); + +// std::cout << "loading URI: " << uri << std::endl; + + if(!uri.empty()) + { + if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) + { + LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, uri ); + } + else + { + mInitialNavigateURL = uri; + } + } + } + else if(message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + S32 button = message_in.getValueS32("button"); + mLastMouseX = message_in.getValueS32("x"); + mLastMouseY = message_in.getValueS32("y"); + std::string modifiers = message_in.getValue("modifiers"); + + // Treat unknown mouse events as mouse-moves. + LLQtWebKit::EMouseEvent mouse_event = LLQtWebKit::ME_MOUSE_MOVE; + if(event == "down") + { + mouse_event = LLQtWebKit::ME_MOUSE_DOWN; + } + else if(event == "up") + { + mouse_event = LLQtWebKit::ME_MOUSE_UP; + } + else if(event == "double_click") + { + mouse_event = LLQtWebKit::ME_MOUSE_DOUBLE_CLICK; + } + + LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, mouse_event, button, mLastMouseX, mLastMouseY, decodeModifiers(modifiers)); + checkEditState(); + } + else if(message_name == "scroll_event") + { + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); + std::string modifiers = message_in.getValue("modifiers"); + + // Incoming scroll events are adjusted so that 1 detent is approximately 1 unit. + // Qt expects 1 detent to be 120 units. + // It also seems that our y scroll direction is inverted vs. what Qt expects. + + x *= 120; + y *= -120; + + LLQtWebKit::getInstance()->scrollWheelEvent(mBrowserWindowId, mLastMouseX, mLastMouseY, x, y, decodeModifiers(modifiers)); + } + else if(message_name == "key_event") + { + std::string event = message_in.getValue("event"); + S32 key = message_in.getValueS32("key"); + std::string modifiers = message_in.getValue("modifiers"); + + // Treat unknown events as key-up for safety. + LLQtWebKit::EKeyEvent key_event = LLQtWebKit::KE_KEY_UP; + if(event == "down") + { + key_event = LLQtWebKit::KE_KEY_DOWN; + } + else if(event == "repeat") + { + key_event = LLQtWebKit::KE_KEY_REPEAT; + } + + keyEvent(key_event, key, decodeModifiers(modifiers)); + } + else if(message_name == "text_event") + { + std::string text = message_in.getValue("text"); + std::string modifiers = message_in.getValue("modifiers"); + + unicodeInput(text, decodeModifiers(modifiers)); + } + if(message_name == "edit_cut") + { + LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT ); + checkEditState(); + } + if(message_name == "edit_copy") + { + LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY ); + checkEditState(); + } + if(message_name == "edit_paste") + { + LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE ); + checkEditState(); + } + else + { +// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media message: " << message_string << std::endl; + }; + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) + { + if(message_name == "focus") + { + bool val = message_in.getValueBoolean("focused"); + LLQtWebKit::getInstance()->focusBrowser( mBrowserWindowId, val ); + + if(mFirstFocus && val) + { + // On the first focus, post a tab key event. This fixes a problem with initial focus. + std::string empty; + keyEvent(LLQtWebKit::KE_KEY_DOWN, KEY_TAB, decodeModifiers(empty)); + keyEvent(LLQtWebKit::KE_KEY_UP, KEY_TAB, decodeModifiers(empty)); + mFirstFocus = false; + } + } + else if(message_name == "clear_cache") + { + LLQtWebKit::getInstance()->clearCache(); + } + else if(message_name == "clear_cookies") + { + LLQtWebKit::getInstance()->clearAllCookies(); + } + else if(message_name == "enable_cookies") + { + bool val = message_in.getValueBoolean("enable"); + LLQtWebKit::getInstance()->enableCookies( val ); + } + else if(message_name == "proxy_setup") + { + bool val = message_in.getValueBoolean("enable"); + std::string host = message_in.getValue("host"); + int port = message_in.getValueS32("port"); + LLQtWebKit::getInstance()->enableProxy( val, host, port ); + } + else if(message_name == "browse_stop") + { + LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_STOP ); + } + else if(message_name == "browse_reload") + { + // foo = message_in.getValueBoolean("ignore_cache"); + LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_RELOAD ); + } + else if(message_name == "browse_forward") + { + LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD ); + } + else if(message_name == "browse_back") + { + LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK ); + } + else if(message_name == "set_status_redirect") + { + int code = message_in.getValueS32("code"); + std::string url = message_in.getValue("url"); + if ( 404 == code ) // browser lib only supports 404 right now + { + LLQtWebKit::getInstance()->set404RedirectUrl( mBrowserWindowId, url ); + }; + } + else if(message_name == "set_user_agent") + { + std::string user_agent = message_in.getValue("user_agent"); + LLQtWebKit::getInstance()->setBrowserAgentId( user_agent ); + } + else if(message_name == "init_history") + { + // Initialize browser history + LLSD history = message_in.getValueLLSD("history"); + // First, clear the URL history + LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId); + // Then, add the history items in order + LLSD::array_iterator iter_history = history.beginArray(); + LLSD::array_iterator end_history = history.endArray(); + for(; iter_history != end_history; ++iter_history) + { + std::string url = (*iter_history).asString(); + if(! url.empty()) { + LLQtWebKit::getInstance()->prependHistoryUrl(mBrowserWindowId, url); + } + } + } + else + { +// std::cerr << "MediaPluginWebKit::receiveMessage: unknown media_browser message: " << message_string << std::endl; + }; + } + else + { +// std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; + }; + } +} + +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + MediaPluginWebKit *self = new MediaPluginWebKit(host_send_func, host_user_data); + *plugin_send_func = MediaPluginWebKit::staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; +} + diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index 1691095..15561d0 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt @@ -21,8 +21,8 @@ include(LLImage) include(LLImageJ2COJ) include(LLInventory) include(LLMath) -include(LLMedia) include(LLMessage) +include(LLPlugin) include(LLPrimitive) include(LLRender) include(LLUI) @@ -31,7 +31,6 @@ include(LLWindow) include(LLXML) include(LScript) include(Linking) -include(Mozlib) include(NDOF) include(GooglePerfTools) include(TemplateCheck) @@ -55,8 +54,8 @@ include_directories( ${LLIMAGE_INCLUDE_DIRS} ${LLINVENTORY_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} - ${LLMEDIA_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} + ${LLPLUGIN_INCLUDE_DIRS} ${LLPRIMITIVE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} ${LLUI_INCLUDE_DIRS} @@ -65,7 +64,6 @@ include_directories( ${LLXML_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS}/lscript_compile - ${GSTREAMER_INCLUDE_DIRS} ) set(viewer_SOURCE_FILES @@ -185,9 +183,8 @@ set(viewer_SOURCE_FILES llfloatergroups.cpp llfloaterhandler.cpp llfloaterhardwaresettings.cpp - llfloaterhtml.cpp llfloaterhtmlcurrency.cpp - llfloaterhtmlhelp.cpp + llfloatermediabrowser.cpp llfloaterhtmlsimple.cpp llfloaterhud.cpp llfloaterimagepreview.cpp @@ -312,10 +309,12 @@ set(viewer_SOURCE_FILES llpanelinput.cpp llpanelinventory.cpp llpanelland.cpp + llpanellandaudio.cpp llpanellandmedia.cpp llpanellandobjects.cpp llpanellandoptions.cpp llpanellogin.cpp + llpanelmediahud.cpp llpanelmsgs.cpp llpanelnetwork.cpp llpanelobject.cpp @@ -421,6 +420,8 @@ set(viewer_SOURCE_FILES llviewerkeyboard.cpp llviewerlayer.cpp llviewermedia.cpp + llviewermediafocus.cpp + llviewermedia_streamingaudio.cpp llviewermenu.cpp llviewermenufile.cpp llviewermessage.cpp @@ -467,7 +468,7 @@ set(viewer_SOURCE_FILES llwearable.cpp llwearablelist.cpp llweb.cpp - llwebbrowserctrl.cpp + llmediactrl.cpp llwindlightremotectrl.cpp llwind.cpp llwlanimator.cpp @@ -630,9 +631,8 @@ set(viewer_HEADER_FILES llfloatergroups.h llfloaterhandler.h llfloaterhardwaresettings.h - llfloaterhtml.h llfloaterhtmlcurrency.h - llfloaterhtmlhelp.h + llfloatermediabrowser.h llfloaterhtmlsimple.h llfloaterhud.h llfloaterimagepreview.h @@ -756,11 +756,13 @@ set(viewer_HEADER_FILES llpanelinput.h llpanelinventory.h llpanelland.h + llpanellandaudio.h llpanellandmedia.h llpanellandobjects.h llpanellandoptions.h llpanelLCD.h llpanellogin.h + llpanelmediahud.h llpanelmsgs.h llpanelnetwork.h llpanelobject.h @@ -867,6 +869,8 @@ set(viewer_HEADER_FILES llviewerkeyboard.h llviewerlayer.h llviewermedia.h + llviewermediaobserver.h + llviewermediafocus.h llviewermenu.h llviewermenufile.h llviewermessage.h @@ -915,7 +919,7 @@ set(viewer_HEADER_FILES llwearable.h llwearablelist.h llweb.h - llwebbrowserctrl.h + llmediactrl.h llwind.h llwindebug.h llwindlightremotectrl.h @@ -1118,6 +1122,7 @@ if (WINDOWS) if (INTEL_MEMOPS_LIBRARY) list(APPEND viewer_LIBRARIES ${INTEL_MEMOPS_LIBRARY}) endif (INTEL_MEMOPS_LIBRARY) + use_prebuilt_binary(dbghelp) endif (WINDOWS) # Add the xui files. This is handy for searching for xui elements @@ -1134,6 +1139,8 @@ set(viewer_XUI_FILES ) +list(APPEND viewer_XUI_FILES ${viewer_XUI_FILE_GLOB_LIST}) +list(SORT viewer_XUI_FILES) list(APPEND viewer_XUI_FILES ${viewer_XUI_FILE_GLOB_LIST}) list(SORT viewer_XUI_FILES) @@ -1169,6 +1176,7 @@ set(viewer_APPSETTINGS_FILES ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg ) + source_group("App Settings" FILES ${viewer_APPSETTINGS_FILES}) set_source_files_properties(${viewer_APPSETTINGS_FILES} @@ -1326,6 +1334,9 @@ if (WINDOWS) --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/touched.bat DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) + + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) + if (PACKAGE) add_custom_target(package ALL DEPENDS ${CMAKE_CFG_INTDIR}/touched.bat) add_dependencies(package windows-updater windows-crash-logger) @@ -1338,8 +1349,8 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLIMAGE_LIBRARIES} ${LLIMAGEJ2COJ_LIBRARIES} ${LLINVENTORY_LIBRARIES} - ${LLMEDIA_LIBRARIES} ${LLMESSAGE_LIBRARIES} + ${LLPLUGIN_LIBRARIES} ${LLPRIMITIVE_LIBRARIES} ${LLRENDER_LIBRARIES} ${FREETYPE_LIBRARIES} @@ -1361,7 +1372,6 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${OPENGL_LIBRARIES} ${FMODWRAPPER_LIBRARY} ${OPENGL_LIBRARIES} - ${MOZLIB_LIBRARIES} ${JSONCPP_LIBRARIES} ${SDL_LIBRARY} ${SMARTHEAP_LIBRARY} @@ -1443,6 +1453,8 @@ if (DARWIN) DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer010 media_plugin_webkit) + if (PACKAGE) add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME}) add_dependencies(package mac-updater mac-crash-logger) @@ -1461,6 +1473,8 @@ if (DARWIN) --build=${CMAKE_CURRENT_BINARY_DIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched + + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) @@ -1492,3 +1506,65 @@ if (INSTALL) endif (INSTALL) ADD_VIEWER_BUILD_TEST(llagentaccess viewer) + +# Don't do these for DARWIN or LINUX here -- they're taken care of by viewer_manifest.py +if (WINDOWS) + get_target_property(BUILT_SLPLUGIN SLPlugin LOCATION) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_if_different + ${BUILT_SLPLUGIN} + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} + COMMENT "Copying SLPlugin executable to the runtime folder." + ) + + get_target_property(BUILT_WEBKIT_PLUGIN media_plugin_webkit LOCATION) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_if_different + ${BUILT_WEBKIT_PLUGIN} + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin + COMMENT "Copying WebKit Plugin to the runtime folder." + ) + + get_target_property(BUILT_QUICKTIME_PLUGIN media_plugin_quicktime LOCATION) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_if_different + ${BUILT_QUICKTIME_PLUGIN} + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin + COMMENT "Copying Quicktime Plugin to the runtime folder." + ) + + # Copying the mime_types.xml file to app_settings + set(mime_types_source "${CMAKE_SOURCE_DIR}/newview/skins/default/xui/en-us") + set(mime_types_dest "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings") + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_if_different + ${mime_types_source}/mime_types_windows.xml + ${mime_types_dest}/mime_types.xml + COMMENT "Copying mime_types_windows.xml to mime_types.xml." + ) + +endif (WINDOWS) + +if (DARWIN) +# Don't do this here -- it's taken care of by viewer_manifest.py +# add_custom_command(TARGET ${VIEWER_BINARY_NAME} POST_BUILD +# COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin/ +# DEPENDS ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib +# ) +endif (DARWIN) diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml index 0a27aa2..4d80845 100644 --- a/linden/indra/newview/app_settings/settings.xml +++ b/linden/indra/newview/app_settings/settings.xml @@ -7624,7 +7624,40 @@ <key>Value</key> <integer>0</integer> </map> - <key>MemoryLogFrequency</key> + <key>MediaControlFadeTime</key> + <map> + <key>Comment</key> + <string>Amount of time (in seconds) that the media control fades</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.5</real> + </map> + <key>MediaControlTimeout</key> + <map> + <key>Comment</key> + <string>Amount of time (in seconds) for media controls to fade with no mouse activity</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>3.0</real> + </map> + <key>MediaOnAPrimUI</key> + <map> + <key>Comment</key> + <string>Whether or not to show the "link sharing" UI</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>MemoryLogFrequency</key> <map> <key>Comment</key> <string>Seconds between display of Memory in log (0 for never)</string> diff --git a/linden/indra/newview/chatbar_as_cmdline.cpp b/linden/indra/newview/chatbar_as_cmdline.cpp index 59804c0..d90bcd8 100644 --- a/linden/indra/newview/chatbar_as_cmdline.cpp +++ b/linden/indra/newview/chatbar_as_cmdline.cpp @@ -16,7 +16,7 @@ * may be used to endorse or promote products derived from this * software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY MODULAR SYSTEMS AND CONTRIBUTORS “AS IS” + * THIS SOFTWARE IS PROVIDED BY MODULAR SYSTEMS AND CONTRIBUTORS �AS IS� * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MODULAR SYSTEMS OR CONTRIBUTORS @@ -69,7 +69,7 @@ #include "llviewerparcelmgr.h" #include "llviewerparcelmedia.h" #include "llparcel.h" -#include "audioengine.h" +#include "llaudioengine.h" #include "llviewerparcelmediaautoplay.h" #include "lloverlaybar.h" #include "lggautocorrectfloater.h" diff --git a/linden/indra/newview/floatervoicelicense.cpp b/linden/indra/newview/floatervoicelicense.cpp index 4004290..74d16c3 100644 --- a/linden/indra/newview/floatervoicelicense.cpp +++ b/linden/indra/newview/floatervoicelicense.cpp @@ -27,7 +27,7 @@ * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ - +/* #include "llviewerprecompiledheaders.h" #include "floatervoicelicense.h" @@ -234,4 +234,4 @@ void FloaterVoiceLicense::onNavigateComplete( const EventType& eventIn ) LLCheckBoxCtrl * license_agreement = getChild<LLCheckBoxCtrl>("agree_chk"); license_agreement->setEnabled( true ); } -} +}*/ diff --git a/linden/indra/newview/floatervoicelicense.h b/linden/indra/newview/floatervoicelicense.h index 4130d22..9d2012d 100644 --- a/linden/indra/newview/floatervoicelicense.h +++ b/linden/indra/newview/floatervoicelicense.h @@ -35,8 +35,8 @@ #include "llmodaldialog.h" #include "llassetstorage.h" -#include "llwebbrowserctrl.h" - +//imprudence fixme: removed for media plugins #include "llwebbrowserctrl.h" +/* class LLButton; class LLRadioGroup; class LLVFS; @@ -45,7 +45,7 @@ class LLUUID; class FloaterVoiceLicense : public LLModalDialog, - public LLWebBrowserCtrlObserver, + public LLViewerMediaObserver public LLFloaterSingleton<FloaterVoiceLicense> { public: @@ -67,6 +67,6 @@ public: private: int mWebBrowserWindowId; int mLoadCompleteCount; -}; +};*/ #endif // FLOATERVOICELICENSE_H diff --git a/linden/indra/newview/llagent.cpp b/linden/indra/newview/llagent.cpp index 51b6c53..5bcffdb 100644 --- a/linden/indra/newview/llagent.cpp +++ b/linden/indra/newview/llagent.cpp @@ -77,6 +77,7 @@ #include "llfloaterdirectory.h" #include "llfloatergroupinfo.h" #include "llfloatergroups.h" +#include "llfloaterland.h" #include "llfloatermap.h" #include "llfloatermute.h" #include "llfloatersnapshot.h" @@ -113,6 +114,7 @@ #include "llurldispatcher.h" #include "llviewercamera.h" #include "llviewerinventory.h" +#include "llviewermediafocus.h" #include "llviewermenu.h" #include "llviewernetwork.h" #include "llviewerobjectlist.h" @@ -6061,7 +6063,11 @@ bool LLAgent::teleportCore(bool is_local) LLFloaterWorldMap::hide(NULL); LLFloaterDirectory::hide(NULL); + // hide land floater too - it'll be out of date + LLFloaterLand::hideInstance(); + LLViewerParcelMgr::getInstance()->deselectLand(); + LLViewerMediaFocus::getInstance()->setFocusFace(false, NULL, 0, NULL); // Close all pie menus, deselect land, etc. // Don't change the camera until we know teleport succeeded. JC diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp index b3f3e59..86c83b9 100644 --- a/linden/indra/newview/llappviewer.cpp +++ b/linden/indra/newview/llappviewer.cpp @@ -61,8 +61,8 @@ #include "llviewerwindow.h" #include "llviewerdisplay.h" #include "llviewermedia.h" - - +#include "llviewerparcelmedia.h" +#include "llviewermediafocus.h" #include "llviewermessage.h" #include "llviewerobjectlist.h" #include "llworldmap.h" @@ -103,7 +103,8 @@ #include "llassetstorage.h" #include "llpolymesh.h" #include "llcachename.h" -#include "audioengine.h" +#include "llaudioengine.h" +#include "llstreamingaudio.h" #include "llviewermenu.h" #include "llselectmgr.h" #include "lltrans.h" @@ -1257,6 +1258,14 @@ bool LLAppViewer::cleanup() if (gAudiop) { + // shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem. + + LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl(); + delete sai; + gAudiop->setStreamingAudioImpl(NULL); + + // shut down the audio subsystem + bool want_longname = false; if (gAudiop->getDriverName(want_longname) == "FMOD") { @@ -1483,7 +1492,9 @@ bool LLAppViewer::cleanup() //Note: //LLViewerMedia::cleanupClass() has to be put before gImageList.shutdown() //because some new image might be generated during cleaning up media. --bao + LLViewerMediaFocus::cleanupClass(); LLViewerMedia::cleanupClass(); + LLViewerParcelMedia::cleanupClass(); gImageList.shutdown(); // shutdown again in case a callback added something LLUIImageList::getInstance()->cleanUp(); @@ -3671,6 +3682,9 @@ void LLAppViewer::idle() gAgent.updateCamera(); } + // update media focus + LLViewerMediaFocus::getInstance()->update(); + // objects and camera should be in sync, do LOD calculations now { LLFastTimer t(LLFastTimer::FTM_LOD_UPDATE); diff --git a/linden/indra/newview/llappviewerlinux.cpp b/linden/indra/newview/llappviewerlinux.cpp index bfad899..307f925 100644 --- a/linden/indra/newview/llappviewerlinux.cpp +++ b/linden/indra/newview/llappviewerlinux.cpp @@ -437,7 +437,7 @@ gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **succ llinfos << "Was asked to go to slurl: " << slurl << llendl; std::string url = slurl; - LLWebBrowserCtrl* web = NULL; + LLMediaCtrl* web = NULL; const bool trusted_browser = false; if (LLURLDispatcher::dispatch(url, web, trusted_browser)) { diff --git a/linden/indra/newview/llappviewermacosx.cpp b/linden/indra/newview/llappviewermacosx.cpp index 3cd0836..3a993eb 100644 --- a/linden/indra/newview/llappviewermacosx.cpp +++ b/linden/indra/newview/llappviewermacosx.cpp @@ -1,6 +1,6 @@ /** * @file llappviewermacosx.cpp - * @brief The LLAppViewerWin32 class definitions + * @brief The LLAppViewerMacOSX class definitions * * $LicenseInfo:firstyear=2007&license=viewergpl$ * @@ -476,7 +476,7 @@ OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn) url.replace(0, prefix.length(), "secondlife:///app/"); } - LLWebBrowserCtrl* web = NULL; + LLMediaCtrl* web = NULL; const bool trusted_browser = false; LLURLDispatcher::dispatch(url, web, trusted_browser); } diff --git a/linden/indra/newview/llassetuploadresponders.cpp b/linden/indra/newview/llassetuploadresponders.cpp index aff1fb8..b9ec9a0 100644 --- a/linden/indra/newview/llassetuploadresponders.cpp +++ b/linden/indra/newview/llassetuploadresponders.cpp @@ -287,7 +287,8 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) LLInventoryView* view = LLInventoryView::getActiveInventory(); if(view) { - LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); + LLFocusableElement* focus = gFocusMgr.getKeyboardFocus(); + view->getPanel()->setSelection(content["new_inventory_item"].asUUID(), TAKE_FOCUS_NO); if((LLAssetType::AT_TEXTURE == asset_type || LLAssetType::AT_SOUND == asset_type) && LLFilePicker::instance().getFileCount() <= FILE_COUNT_DISPLAY_THRESHOLD) @@ -296,7 +297,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) } //LLInventoryView::dumpSelectionInformation((void*)view); // restore keyboard focus - gFocusMgr.setKeyboardFocus(focus_ctrl); + gFocusMgr.setKeyboardFocus(focus); } } else diff --git a/linden/indra/newview/llaudiosourcevo.h b/linden/indra/newview/llaudiosourcevo.h index e7bb283..4b70f8b 100644 --- a/linden/indra/newview/llaudiosourcevo.h +++ b/linden/indra/newview/llaudiosourcevo.h @@ -34,7 +34,7 @@ #ifndef LL_LLAUDIOSOURCEVO_H #define LL_LLAUDIOSOURCEVO_H -#include "audioengine.h" +#include "llaudioengine.h" #include "llviewerobject.h" class LLViewerObject; diff --git a/linden/indra/newview/llchatbar.cpp b/linden/indra/newview/llchatbar.cpp index 0a4ca34..99a2a22 100644 --- a/linden/indra/newview/llchatbar.cpp +++ b/linden/indra/newview/llchatbar.cpp @@ -955,7 +955,7 @@ public: // Your code here bool handle(const LLSD& tokens, const LLSD& query_map, - LLWebBrowserCtrl* web) + LLMediaCtrl* web) { if (tokens.size() < 2) return false; S32 channel = tokens[0].asInteger(); diff --git a/linden/indra/newview/llcommandhandler.cpp b/linden/indra/newview/llcommandhandler.cpp index 422c94a..a04182a 100644 --- a/linden/indra/newview/llcommandhandler.cpp +++ b/linden/indra/newview/llcommandhandler.cpp @@ -55,7 +55,7 @@ public: bool dispatch(const std::string& cmd, const LLSD& params, const LLSD& query_map, - LLWebBrowserCtrl* web, + LLMediaCtrl* web, bool trusted_browser); private: @@ -84,7 +84,7 @@ void LLCommandHandlerRegistry::add(const char* cmd, bool require_trusted_browser bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, const LLSD& params, const LLSD& query_map, - LLWebBrowserCtrl* web, + LLMediaCtrl* web, bool trusted_browser) { std::map<std::string, LLCommandHandlerInfo>::iterator it = mMap.find(cmd); @@ -126,7 +126,7 @@ LLCommandHandler::~LLCommandHandler() bool LLCommandDispatcher::dispatch(const std::string& cmd, const LLSD& params, const LLSD& query_map, - LLWebBrowserCtrl* web, + LLMediaCtrl* web, bool trusted_browser) { return LLCommandHandlerRegistry::instance().dispatch( diff --git a/linden/indra/newview/llcommandhandler.h b/linden/indra/newview/llcommandhandler.h index ab4c2cc..5cb3ee7 100644 --- a/linden/indra/newview/llcommandhandler.h +++ b/linden/indra/newview/llcommandhandler.h @@ -47,7 +47,7 @@ public: // Your code here bool handle(const LLSD& tokens, const LLSD& query_map, - LLWebBrowserCtrl* web) + LLMediaCtrl* web) { if (tokens.size() < 1) return false; LLUUID id( tokens[0] ); @@ -60,7 +60,7 @@ LLFooHandler gFooHandler; */ -class LLWebBrowserCtrl; +class LLMediaCtrl; class LLCommandHandler { @@ -68,14 +68,14 @@ public: LLCommandHandler(const char* command, bool allow_from_untrusted_browser); // Automatically registers object to get called when // command is executed. All commands can be processed - // in links from LLWebBrowserCtrl, but some (like teleport) + // in links from LLMediaCtrl, but some (like teleport) // should not be allowed from outside the app. virtual ~LLCommandHandler(); virtual bool handle(const LLSD& params, const LLSD& query_map, - LLWebBrowserCtrl* web) = 0; + LLMediaCtrl* web) = 0; // For URL secondlife:///app/foo/bar/baz?cat=1&dog=2 // @params - array of "bar", "baz", possibly empty // @query_map - map of "cat" -> 1, "dog" -> 2, possibly empty @@ -91,7 +91,7 @@ public: static bool dispatch(const std::string& cmd, const LLSD& params, const LLSD& query_map, - LLWebBrowserCtrl* web, + LLMediaCtrl* web, bool trusted_browser); // Execute a command registered via the above mechanism, // passing string parameters. diff --git a/linden/indra/newview/llfirstuse.cpp b/linden/indra/newview/llfirstuse.cpp index e82aa96..ca8614c 100644 --- a/linden/indra/newview/llfirstuse.cpp +++ b/linden/indra/newview/llfirstuse.cpp @@ -397,8 +397,8 @@ void LLFirstUse::voiceLicenseAgreement() { gSavedSettings.setWarning("FirstVoiceLicense", FALSE); - FloaterVoiceLicense::getInstance()->open(); - FloaterVoiceLicense::getInstance()->center(); +// imprudence fixme FloaterVoiceLicense::getInstance()->open(); +// FloaterVoiceLicense::getInstance()->center(); } else // currently in STATE_LOGIN_VOICE_LICENSE when arriving here { diff --git a/linden/indra/newview/llfloaterabout.cpp b/linden/indra/newview/llfloaterabout.cpp index 1945df4..d2d1250 100644 --- a/linden/indra/newview/llfloaterabout.cpp +++ b/linden/indra/newview/llfloaterabout.cpp @@ -42,7 +42,7 @@ #include "llcurl.h" #include "llimagej2c.h" -#include "audioengine.h" +#include "llaudioengine.h" #include "hippoGridManager.h" #include "llviewertexteditor.h" @@ -57,7 +57,6 @@ #include "lltrans.h" #include "llappviewer.h" #include "llglheaders.h" -#include "llmediamanager.h" #include "llwindow.h" #include "viewerversion.h" @@ -244,26 +243,10 @@ LLFloaterAbout::LLFloaterAbout() support.append("\n"); - LLMediaManager *mgr = LLMediaManager::getInstance(); - if (mgr) - { - LLMediaBase *gstreamer = mgr->createSourceFromMimeType("http", "audio/mpeg"); - if (gstreamer) - { - support.append("GStreamer Version: "); - support.append( gstreamer->getVersion() ); - support.append("\n"); - } - - LLMediaBase *media_source = mgr->createSourceFromMimeType("http", "text/html"); - if (media_source) - { - support.append("LLMozLib Version: "); - support.append(media_source->getVersion()); - support.append("\n"); - mgr->destroySource(media_source); - } - } + // TODO: Implement media plugin version query + + support.append("Qt Webkit Version: 4.5.2 "); + support.append("\n"); if (gPacketsIn > 0) { diff --git a/linden/indra/newview/llfloateravatarinfo.cpp b/linden/indra/newview/llfloateravatarinfo.cpp index 21f160e..0618875 100644 --- a/linden/indra/newview/llfloateravatarinfo.cpp +++ b/linden/indra/newview/llfloateravatarinfo.cpp @@ -63,7 +63,7 @@ public: LLAgentHandler() : LLCommandHandler("agent", true) { } bool handle(const LLSD& params, const LLSD& query_map, - LLWebBrowserCtrl* web) + LLMediaCtrl* web) { if (params.size() < 2) return false; LLUUID agent_id; diff --git a/linden/indra/newview/llfloaterchat.cpp b/linden/indra/newview/llfloaterchat.cpp index 59f4d70..2daa5aa 100644 --- a/linden/indra/newview/llfloaterchat.cpp +++ b/linden/indra/newview/llfloaterchat.cpp @@ -190,6 +190,15 @@ void LLFloaterChat::setMinimized(BOOL minimized) updateConsoleVisibility(); } +// linden library includes +#include "llaudioengine.h" +#include "llchat.h" +#include "llfontgl.h" +#include "llrect.h" +#include "llerror.h" +#include "llstring.h" +#include "llwindow.h" +#include "message.h" void LLFloaterChat::updateConsoleVisibility() { @@ -583,13 +592,54 @@ void LLFloaterChat::addChat(const LLChat& chat, if(from_instant_message && gSavedSettings.getBOOL("IMInChatHistory")) addChatHistory(chat,false); - LLTextParser* highlight = LLTextParser::getInstance(); - highlight->triggerAlerts(gAgent.getID(), gAgent.getPositionGlobal(), chat.mText, gViewerWindow->getWindow()); + triggerAlerts(chat.mText); if(!from_instant_message) addChatHistory(chat); } +// Moved from lltextparser.cpp to break llui/llaudio library dependency. +//static +void LLFloaterChat::triggerAlerts(const std::string& text) +{ + LLTextParser* parser = LLTextParser::getInstance(); +// bool spoken=FALSE; + for (S32 i=0;i<parser->mHighlights.size();i++) + { + LLSD& highlight = parser->mHighlights[i]; + if (parser->findPattern(text,highlight) >= 0 ) + { + if(gAudiop) + { + if ((std::string)highlight["sound_lluuid"] != LLUUID::null.asString()) + { + gAudiop->triggerSound(highlight["sound_lluuid"].asUUID(), + gAgent.getID(), + 1.f, + LLAudioEngine::AUDIO_TYPE_UI, + gAgent.getPositionGlobal() ); + } +/* + if (!spoken) + { + LLTextToSpeech* text_to_speech = NULL; + text_to_speech = LLTextToSpeech::getInstance(); + spoken = text_to_speech->speak((LLString)highlight["voice"],text); + } + */ + } + if (highlight["flash"]) + { + LLWindow* viewer_window = gViewerWindow->getWindow(); + if (viewer_window && viewer_window->getMinimized()) + { + viewer_window->flashIcon(5.f); + } + } + } + } +} + LLColor4 get_text_color(const LLChat& chat) { LLColor4 text_color; diff --git a/linden/indra/newview/llfloaterchat.h b/linden/indra/newview/llfloaterchat.h index 5a26567..f8683b9 100644 --- a/linden/indra/newview/llfloaterchat.h +++ b/linden/indra/newview/llfloaterchat.h @@ -78,6 +78,8 @@ public: // Add chat to history alone. static void addChatHistory(const LLChat& chat, bool log_to_file = true); + static void triggerAlerts(const std::string& text); + static void onClickMute(void *data); static void onClickToggleShowMute(LLUICtrl* caller, void *data); static void onClickToggleTranslateChat(LLUICtrl* caller, void *data); diff --git a/linden/indra/newview/llfloaterclassified.cpp b/linden/indra/newview/llfloaterclassified.cpp index d426e04..0760303 100644 --- a/linden/indra/newview/llfloaterclassified.cpp +++ b/linden/indra/newview/llfloaterclassified.cpp @@ -57,7 +57,7 @@ public: // requires trusted browser to trigger LLClassifiedHandler() : LLCommandHandler("classified", true) { } bool handle(const LLSD& tokens, const LLSD& query_map, - LLWebBrowserCtrl* web) + LLMediaCtrl* web) { if (tokens.size() < 2) { diff --git a/linden/indra/newview/llfloaterevent.cpp b/linden/indra/newview/llfloaterevent.cpp index 485c13c..0ec2a76 100644 --- a/linden/indra/newview/llfloaterevent.cpp +++ b/linden/indra/newview/llfloaterevent.cpp @@ -58,7 +58,7 @@ public: // requires trusted browser to trigger LLEventHandler() : LLCommandHandler("event", true) { } bool handle(const LLSD& tokens, const LLSD& query_map, - LLWebBrowserCtrl* web) + LLMediaCtrl* web) { if (tokens.size() < 2) { diff --git a/linden/indra/newview/llfloatergroupinfo.cpp b/linden/indra/newview/llfloatergroupinfo.cpp index 6fbd5e1..3ae7d5a 100644 --- a/linden/indra/newview/llfloatergroupinfo.cpp +++ b/linden/indra/newview/llfloatergroupinfo.cpp @@ -60,7 +60,7 @@ public: // requires trusted browser to trigger LLGroupHandler() : LLCommandHandler("group", true) { } bool handle(const LLSD& tokens, const LLSD& query_map, - LLWebBrowserCtrl* web) + LLMediaCtrl* web) { if (tokens.size() < 1) { diff --git a/linden/indra/newview/llfloaterhandler.cpp b/linden/indra/newview/llfloaterhandler.cpp index f4c7e43..7cf7156 100644 --- a/linden/indra/newview/llfloaterhandler.cpp +++ b/linden/indra/newview/llfloaterhandler.cpp @@ -31,7 +31,7 @@ #include "llfloaterhandler.h" #include "llfloater.h" -#include "llwebbrowserctrl.h" +#include "llmediactrl.h" // register with dispatch via global object LLFloaterHandler gFloaterHandler; @@ -54,7 +54,7 @@ LLFloater* get_parent_floater(LLView* view) } -bool LLFloaterHandler::handle(const LLSD ¶ms, const LLSD &query_map, LLWebBrowserCtrl *web) +bool LLFloaterHandler::handle(const LLSD ¶ms, const LLSD &query_map, LLMediaCtrl *web) { if (params.size() < 2) return false; LLFloater* floater = NULL; diff --git a/linden/indra/newview/llfloaterhandler.h b/linden/indra/newview/llfloaterhandler.h index b08f1f3..31ea80c 100644 --- a/linden/indra/newview/llfloaterhandler.h +++ b/linden/indra/newview/llfloaterhandler.h @@ -39,7 +39,7 @@ class LLFloaterHandler { public: LLFloaterHandler() : LLCommandHandler("floater", true) { } - bool handle(const LLSD& params, const LLSD& query_map, LLWebBrowserCtrl* web); + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web); }; #endif diff --git a/linden/indra/newview/llfloaterhtmlhelp.h b/linden/indra/newview/llfloaterhtmlhelp.h deleted file mode 100644 index 83f15cd..0000000 --- a/linden/indra/newview/llfloaterhtmlhelp.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file llfloaterhtmlhelp.h - * @brief HTML Help floater - uses embedded web browser control - * - * $LicenseInfo:firstyear=2006&license=viewergpl$ - * - * Copyright (c) 2006-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLFLOATERHTMLHELP_H -#define LL_LLFLOATERHTMLHELP_H - -#include "llhtmlhelp.h" -#include "llfloater.h" -#include "llwebbrowserctrl.h" - -class LLViewerHtmlHelp : public LLHtmlHelp -{ -public: - LLViewerHtmlHelp(); - virtual ~LLViewerHtmlHelp(); - - /*virtual*/ void show(); - /*virtual*/ void show(std::string start_url); -}; - -class LLComboBox; -class LLWebBrowserCtrl; - -class LLFloaterMediaBrowser : public LLFloater, public LLFloaterSingleton<LLFloaterMediaBrowser>, public LLWebBrowserCtrlObserver -{ -public: - LLFloaterMediaBrowser(const LLSD& media_data); - - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onClose(bool app_quitting); - /*virtual*/ void onLocationChange( const EventType& eventIn ); - - /*virtual*/ void draw(); - - void openMedia(const std::string& media_url); - void buildURLHistory(); - - static void helpF1(); - -private: - static void onEnterAddress(LLUICtrl* ctrl, void* user_data); - static void onClickRefresh(void* user_data); - static void onClickBack(void* user_data); - static void onClickForward(void* user_data); - static void onClickGo(void* user_data); - static void onClickClose(void* user_data); - static void onClickOpenWebBrowser(void* user_data); - static void onClickAssign(void* user_data); - static void onClickHome(void* user_data); - static void onClickSetHome(void* user_data); - static bool onClickF1HelpLoadURL(const LLSD& notification, const LLSD& response); - - LLWebBrowserCtrl* mBrowser; - LLComboBox* mAddressCombo; - std::string mCurrentURL; -}; - -extern LLViewerHtmlHelp gViewerHtmlHelp; - -#endif // LL_LLFLOATERHTMLHELP_H - diff --git a/linden/indra/newview/llfloaterhtmlsimple.cpp b/linden/indra/newview/llfloaterhtmlsimple.cpp index 7dfc4f6..8091c1e 100644 --- a/linden/indra/newview/llfloaterhtmlsimple.cpp +++ b/linden/indra/newview/llfloaterhtmlsimple.cpp @@ -35,7 +35,7 @@ #include "llfloaterhtmlsimple.h" #include "lluictrlfactory.h" -#include "llwebbrowserctrl.h" +#include "llmediactrl.h" LLFloaterHtmlSimple::LLFloaterHtmlSimple(const LLSD &initial_url) @@ -56,12 +56,12 @@ LLFloaterHtmlSimple::~LLFloaterHtmlSimple() void LLFloaterHtmlSimple::navigateTo(const std::string &url) { - LLWebBrowserCtrl* web = getChild<LLWebBrowserCtrl>("browser"); + LLMediaCtrl* web = getChild<LLMediaCtrl>("browser"); web->navigateTo(url); } void LLFloaterHtmlSimple::setTrusted(bool trusted) { - LLWebBrowserCtrl* web = getChild<LLWebBrowserCtrl>("browser"); + LLMediaCtrl* web = getChild<LLMediaCtrl>("browser"); web->setTrusted(trusted); } diff --git a/linden/indra/newview/llfloaterhud.cpp b/linden/indra/newview/llfloaterhud.cpp index 9810bf1..6324b56 100644 --- a/linden/indra/newview/llfloaterhud.cpp +++ b/linden/indra/newview/llfloaterhud.cpp @@ -36,7 +36,7 @@ // Viewer libs #include "llviewercontrol.h" -#include "llwebbrowserctrl.h" +#include "llmediactrl.h" #include "llalertdialog.h" // Linden libs @@ -74,7 +74,7 @@ LLFloaterHUD::LLFloaterHUD() reshape(saved_position_rect.getWidth(), saved_position_rect.getHeight(), FALSE); setRect(saved_position_rect); - mWebBrowser = getChild<LLWebBrowserCtrl>("floater_hud_browser" ); + mWebBrowser = getChild<LLMediaCtrl>("floater_hud_browser" ); if (mWebBrowser) { // Open links in internal browser diff --git a/linden/indra/newview/llfloaterhud.h b/linden/indra/newview/llfloaterhud.h index 2d58685..919ffef 100644 --- a/linden/indra/newview/llfloaterhud.h +++ b/linden/indra/newview/llfloaterhud.h @@ -35,7 +35,7 @@ #include "llfloater.h" -class LLWebBrowserCtrl; +class LLMediaCtrl; class LLFloaterHUD : public LLFloater { @@ -53,7 +53,7 @@ private: /*virtual*/ ~LLFloaterHUD(); private: - LLWebBrowserCtrl* mWebBrowser; ///< the actual web browser control + LLMediaCtrl* mWebBrowser; ///< the actual web browser control static LLFloaterHUD* sInstance; }; diff --git a/linden/indra/newview/llfloaterland.cpp b/linden/indra/newview/llfloaterland.cpp index 066b739..39de55f 100644 --- a/linden/indra/newview/llfloaterland.cpp +++ b/linden/indra/newview/llfloaterland.cpp @@ -56,6 +56,7 @@ #include "lllineeditor.h" #include "llnamelistctrl.h" #include "llnotify.h" +#include "llpanellandaudio.h" #include "llpanellandmedia.h" #include "llradiogroup.h" #include "llscrolllistctrl.h" @@ -204,6 +205,7 @@ LLFloaterLand::LLFloaterLand(const LLSD& seed) factory_map["land_covenant_panel"] = LLCallbackMap(createPanelLandCovenant, this); factory_map["land_objects_panel"] = LLCallbackMap(createPanelLandObjects, this); factory_map["land_options_panel"] = LLCallbackMap(createPanelLandOptions, this); +// factory_map["land_audio_panel"] = LLCallbackMap(createPanelLandAudio, this); factory_map["land_media_panel"] = LLCallbackMap(createPanelLandMedia, this); factory_map["land_access_panel"] = LLCallbackMap(createPanelLandAccess, this); @@ -239,6 +241,7 @@ void LLFloaterLand::refresh() mPanelGeneral->refresh(); mPanelObjects->refresh(); mPanelOptions->refresh(); +// mPanelAudio->refresh(); mPanelMedia->refresh(); mPanelAccess->refresh(); } @@ -277,6 +280,15 @@ void* LLFloaterLand::createPanelLandOptions(void* data) return self->mPanelOptions; } +/* +// static +void* LLFloaterLand::createPanelLandAudio(void* data) +{ + LLFloaterLand* self = (LLFloaterLand*)data; + self->mPanelAudio = new LLPanelLandAudio(self->mParcel); + return self->mPanelAudio; +} +*/ // static void* LLFloaterLand::createPanelLandMedia(void* data) { diff --git a/linden/indra/newview/llfloaterland.h b/linden/indra/newview/llfloaterland.h index 113b679..4105f44 100644 --- a/linden/indra/newview/llfloaterland.h +++ b/linden/indra/newview/llfloaterland.h @@ -64,6 +64,7 @@ class LLParcelSelection; class LLPanelLandGeneral; class LLPanelLandObjects; class LLPanelLandOptions; +class LLPanelLandAudio; class LLPanelLandMedia; class LLPanelLandAccess; class LLPanelLandBan; @@ -102,6 +103,7 @@ protected: static void* createPanelLandCovenant(void* data); static void* createPanelLandObjects(void* data); static void* createPanelLandOptions(void* data); + static void* createPanelLandAudio(void* data); static void* createPanelLandMedia(void* data); static void* createPanelLandAccess(void* data); static void* createPanelLandBan(void* data); @@ -115,6 +117,7 @@ protected: LLPanelLandGeneral* mPanelGeneral; LLPanelLandObjects* mPanelObjects; LLPanelLandOptions* mPanelOptions; +// LLPanelLandAudio* mPanelAudio; LLPanelLandMedia* mPanelMedia; LLPanelLandAccess* mPanelAccess; LLPanelLandCovenant* mPanelCovenant; diff --git a/linden/indra/newview/llfloatermediabrowser.cpp b/linden/indra/newview/llfloatermediabrowser.cpp new file mode 100644 index 0000000..def0159 --- /dev/null +++ b/linden/indra/newview/llfloatermediabrowser.cpp @@ -0,0 +1,398 @@ +/** + * @file llfloaterhtmlhelp.cpp + * @brief HTML Help floater - uses embedded web browser control + * + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatermediabrowser.h" +#include "llfloaterhtml.h" + +#include "llparcel.h" +#include "llpluginclassmedia.h" +#include "lluictrlfactory.h" +#include "llmediactrl.h" +#include "llviewerwindow.h" +#include "llviewercontrol.h" +#include "llviewerparcelmgr.h" +#include "llweb.h" +#include "llui.h" +#include "roles_constants.h" + +#include "llurlhistory.h" +#include "llmediactrl.h" +#include "llviewermedia.h" +#include "llviewerparcelmedia.h" +#include "llcombobox.h" + + +// TEMP +#include "llsdutil.h" + +LLFloaterMediaBrowser::LLFloaterMediaBrowser(const LLSD& media_data) +{ + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_media_browser.xml"); + +} + +void LLFloaterMediaBrowser::draw() +{ + childSetEnabled("go", !mAddressCombo->getValue().asString().empty()); + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if(parcel) + { + childSetVisible("parcel_owner_controls", LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_CHANGE_MEDIA)); + childSetEnabled("assign", !mAddressCombo->getValue().asString().empty()); + } + bool show_time_controls = false; + bool media_playing = false; + if(mBrowser) + { + LLPluginClassMedia* media_plugin = mBrowser->getMediaPlugin(); + if(media_plugin) + { + show_time_controls = media_plugin->pluginSupportsMediaTime(); + media_playing = media_plugin->getStatus() == LLPluginClassMediaOwner::MEDIA_PLAYING; + } + } + childSetVisible("rewind", show_time_controls); + childSetVisible("play", show_time_controls && ! media_playing); + childSetVisible("pause", show_time_controls && media_playing); + childSetVisible("stop", show_time_controls); + childSetVisible("seek", show_time_controls); + + childSetEnabled("play", ! media_playing); + childSetEnabled("stop", media_playing); + + childSetEnabled("back", mBrowser->canNavigateBack()); + childSetEnabled("forward", mBrowser->canNavigateForward()); + + LLFloater::draw(); +} + +BOOL LLFloaterMediaBrowser::postBuild() +{ + mBrowser = getChild<LLMediaCtrl>("browser"); + mBrowser->addObserver(this); + + mAddressCombo = getChild<LLComboBox>("address"); + mAddressCombo->setCommitCallback(onEnterAddress); + mAddressCombo->setCallbackUserData(this); + + childSetAction("back", onClickBack, this); + childSetAction("forward", onClickForward, this); + childSetAction("reload", onClickRefresh, this); + childSetAction("rewind", onClickRewind, this); + childSetAction("play", onClickPlay, this); + childSetAction("stop", onClickStop, this); + childSetAction("pause", onClickPlay, this); + childSetAction("seek", onClickSeek, this); + childSetAction("go", onClickGo, this); + childSetAction("close", onClickClose, this); + childSetAction("open_browser", onClickOpenWebBrowser, this); + childSetAction("assign", onClickAssign, this); + + buildURLHistory(); + return TRUE; +} + +void LLFloaterMediaBrowser::buildURLHistory() +{ + LLCtrlListInterface* url_list = childGetListInterface("address"); + if (url_list) + { + url_list->operateOnAll(LLCtrlListInterface::OP_DELETE); + } + + // Get all of the entries in the "browser" collection + LLSD browser_history = LLURLHistory::getURLHistory("browser"); + + LLSD::array_iterator iter_history = + browser_history.beginArray(); + LLSD::array_iterator end_history = + browser_history.endArray(); + for(; iter_history != end_history; ++iter_history) + { + std::string url = (*iter_history).asString(); + if(! url.empty()) + url_list->addSimpleElement(url); + } + + // initialize URL history in the plugin + mBrowser->getMediaPlugin()->initializeUrlHistory(browser_history); +} + +std::string LLFloaterMediaBrowser::getSupportURL() +{ + return getString("support_page_url"); +} +void LLFloaterMediaBrowser::onClose(bool app_quitting) +{ + //setVisible(FALSE); + destroy(); +} + +void LLFloaterMediaBrowser::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ + if(event == MEDIA_EVENT_LOCATION_CHANGED) + { + setCurrentURL(self->getLocation()); + } + else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) + { + // This is the event these flags are sent with. + childSetEnabled("back", self->getHistoryBackAvailable()); + childSetEnabled("forward", self->getHistoryForwardAvailable()); + } +} +void LLFloaterMediaBrowser::setCurrentURL(const std::string& url) +{ + mCurrentURL = url; + + // redirects will navigate momentarily to about:blank, don't add to history + if (mCurrentURL != "about:blank") + { + mAddressCombo->remove(mCurrentURL); + mAddressCombo->add(mCurrentURL, ADD_SORTED); + mAddressCombo->selectByValue(mCurrentURL); + + // Serialize url history + LLURLHistory::removeURL("browser", mCurrentURL); + LLURLHistory::addURL("browser", mCurrentURL); + } + childSetEnabled("back", mBrowser->canNavigateBack()); + childSetEnabled("forward", mBrowser->canNavigateForward()); + childSetEnabled("reload", TRUE); +} + +LLFloaterMediaBrowser* LLFloaterMediaBrowser::showInstance(const LLSD& media_url) +{ + LLFloaterMediaBrowser* floaterp = LLUISingleton<LLFloaterMediaBrowser, VisibilityPolicy<LLFloater> >::showInstance(media_url); + + floaterp->openMedia(media_url.asString()); + return floaterp; +} + +//static +void LLFloaterMediaBrowser::onEnterAddress(LLUICtrl* ctrl, void* user_data) +{ + LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data; + self->mBrowser->navigateTo(self->mAddressCombo->getValue().asString()); +} + +//static +void LLFloaterMediaBrowser::onClickRefresh(void* user_data) +{ + LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data; + + self->mAddressCombo->remove(0); + self->mBrowser->navigateTo(self->mCurrentURL); +} + +//static +void LLFloaterMediaBrowser::onClickForward(void* user_data) +{ + LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data; + + self->mBrowser->navigateForward(); +} + +//static +void LLFloaterMediaBrowser::onClickBack(void* user_data) +{ + LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data; + + self->mBrowser->navigateBack(); +} + +//static +void LLFloaterMediaBrowser::onClickGo(void* user_data) +{ + LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data; + + self->mBrowser->navigateTo(self->mAddressCombo->getValue().asString()); +} + +//static +void LLFloaterMediaBrowser::onClickClose(void* user_data) +{ + LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data; + + self->close(); +} + +//static +void LLFloaterMediaBrowser::onClickOpenWebBrowser(void* user_data) +{ + LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data; + + std::string url = self->mCurrentURL.empty() ? + self->mBrowser->getHomePageUrl() : + self->mCurrentURL; + LLWeb::loadURLExternal(url); +} + +void LLFloaterMediaBrowser::onClickAssign(void* user_data) +{ + LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data; + + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!parcel) + { + return; + } + std::string media_url = self->mAddressCombo->getValue().asString(); + LLStringUtil::trim(media_url); + + if(parcel->getMediaType() != "text/html") + { + parcel->setMediaURL(media_url); + parcel->setMediaCurrentURL(media_url); + parcel->setMediaType(std::string("text/html")); + LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel, true ); + LLViewerParcelMedia::sendMediaNavigateMessage(media_url); + LLViewerParcelMedia::stop(); + // LLViewerParcelMedia::update( parcel ); + } + LLViewerParcelMedia::sendMediaNavigateMessage(media_url); +} +//static +void LLFloaterMediaBrowser::onClickRewind(void* user_data) +{ + LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data; + + if(self->mBrowser->getMediaPlugin()) + self->mBrowser->getMediaPlugin()->start(-2.0f); +} +//static +void LLFloaterMediaBrowser::onClickPlay(void* user_data) +{ + LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data; + + LLPluginClassMedia* plugin = self->mBrowser->getMediaPlugin(); + if(plugin) + { + if(plugin->getStatus() == LLPluginClassMediaOwner::MEDIA_PLAYING) + { + plugin->pause(); + } + else + { + plugin->start(); + } + } +} +//static +void LLFloaterMediaBrowser::onClickStop(void* user_data) +{ + LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data; + + if(self->mBrowser->getMediaPlugin()) + self->mBrowser->getMediaPlugin()->stop(); +} +//static +void LLFloaterMediaBrowser::onClickSeek(void* user_data) +{ + LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data; + + if(self->mBrowser->getMediaPlugin()) + self->mBrowser->getMediaPlugin()->start(2.0f); +} +void LLFloaterMediaBrowser::openMedia(const std::string& media_url) +{ + mBrowser->setHomePageUrl(media_url); + mBrowser->navigateTo(media_url); + setCurrentURL(media_url); +} +//////////////////////////////////////////////////////////////////////////////// +// + +LLViewerHtmlHelp gViewerHtmlHelp; + + +//////////////////////////////////////////////////////////////////////////////// +// +LLViewerHtmlHelp::LLViewerHtmlHelp() +{ + + LLUI::setHtmlHelp(this); +} + +LLViewerHtmlHelp::~LLViewerHtmlHelp() +{ + + LLUI::setHtmlHelp(NULL); +} + +void LLViewerHtmlHelp::show() +{ + show(""); +} + +void LLViewerHtmlHelp::show(std::string url) +{ + LLFloaterMediaBrowser* floater_html = LLFloaterMediaBrowser::getInstance(); + floater_html->setVisible(FALSE); + + if (url.empty()) + { + url = floater_html->getSupportURL(); + } + + if (gSavedSettings.getBOOL("UseExternalBrowser")) + { + LLSD notificationData; + notificationData["url"] = url; + + LLNotifications::instance().add("ClickOpenF1Help", notificationData, LLSD(), onClickF1HelpLoadURL); + floater_html->close(); + } + else + { + // don't wait, just do it + floater_html->setVisible(TRUE); + floater_html->openMedia(url); + } +} +// static +bool LLViewerHtmlHelp::onClickF1HelpLoadURL(const LLSD& notification, const LLSD& response) +{ + LLFloaterMediaBrowser* floater_html = LLFloaterMediaBrowser::getInstance(); + floater_html->setVisible(FALSE); + std::string url = floater_html->getSupportURL(); + S32 option = LLNotification::getSelectedOption(notification, response); + if (option == 0) + { + LLWeb::loadURL(url); + } + floater_html->close(); + return false; +} + diff --git a/linden/indra/newview/llfloatermediabrowser.h b/linden/indra/newview/llfloatermediabrowser.h new file mode 100644 index 0000000..8a78df8 --- /dev/null +++ b/linden/indra/newview/llfloatermediabrowser.h @@ -0,0 +1,102 @@ +/** + * @file llfloaterhtmlhelp.h + * @brief HTML Help floater - uses embedded web browser control + * + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERHTMLHELP_H +#define LL_LLFLOATERHTMLHELP_H + +#include "llhtmlhelp.h" +#include "llfloater.h" +#include "llmediactrl.h" + +class LLViewerHtmlHelp : public LLHtmlHelp +{ +public: + LLViewerHtmlHelp(); + virtual ~LLViewerHtmlHelp(); + + /*virtual*/ void show(); + /*virtual*/ void show(std::string start_url); + void show(std::string start_url, std::string title); + + static bool onClickF1HelpLoadURL(const LLSD& notification, const LLSD& response); + +}; + +class LLComboBox; +class LLMediaCtrl; + +class LLFloaterMediaBrowser : + public LLFloater, + public LLUISingleton<LLFloaterMediaBrowser, + VisibilityPolicy<LLFloater> >, + public LLViewerMediaObserver +{ +public: + LLFloaterMediaBrowser(const LLSD& media_data); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onClose(bool app_quitting); + /*virtual*/ void draw(); + + // inherited from LLViewerMediaObserver + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + + void openMedia(const std::string& media_url); + void buildURLHistory(); + std::string getSupportURL(); + void setCurrentURL(const std::string& url); + + + static LLFloaterMediaBrowser* showInstance(const LLSD& id); + static void onEnterAddress(LLUICtrl* ctrl, void* user_data); + static void onClickRefresh(void* user_data); + static void onClickBack(void* user_data); + static void onClickForward(void* user_data); + static void onClickGo(void* user_data); + static void onClickClose(void* user_data); + static void onClickOpenWebBrowser(void* user_data); + static void onClickAssign(void* user_data); + static void onClickRewind(void* user_data); + static void onClickPlay(void* user_data); + static void onClickStop(void* user_data); + static void onClickSeek(void* user_data); + +private: + LLMediaCtrl* mBrowser; + LLComboBox* mAddressCombo; + std::string mCurrentURL; +}; + +extern LLViewerHtmlHelp gViewerHtmlHelp; + +#endif // LL_LLFLOATERHTMLHELP_H + diff --git a/linden/indra/newview/llfloaterobjectiminfo.cpp b/linden/indra/newview/llfloaterobjectiminfo.cpp index fa7964c..f933a85 100644 --- a/linden/indra/newview/llfloaterobjectiminfo.cpp +++ b/linden/indra/newview/llfloaterobjectiminfo.cpp @@ -137,7 +137,7 @@ void LLFloaterObjectIMInfo::onClickMap(void* data) std::ostringstream link; link << "secondlife://" << self->mSlurl; - class LLWebBrowserCtrl* web = NULL; + class LLMediaCtrl* web = NULL; LLURLDispatcher::dispatch(link.str(), web, true); } @@ -213,14 +213,14 @@ public: LLObjectIMInfoHandler() : LLCommandHandler("objectim", true) { } bool handle(const LLSD& tokens, const LLSD& query_map, - LLWebBrowserCtrl* web); + LLMediaCtrl* web); }; // Creating the object registers with the dispatcher. LLObjectIMInfoHandler gObjectIMHandler; // ex. secondlife:///app/objectim/9426adfc-9c17-8765-5f09-fdf19957d003?owner=a112d245-9095-4e9c-ace4-ffa31717f934&groupowned=true&slurl=ahern/123/123/123&name=Object -bool LLObjectIMInfoHandler::handle(const LLSD &tokens, const LLSD &query_map, LLWebBrowserCtrl* web) +bool LLObjectIMInfoHandler::handle(const LLSD &tokens, const LLSD &query_map, LLMediaCtrl* web) { LLUUID task_id = tokens[0].asUUID(); std::string name = query_map["name"].asString(); diff --git a/linden/indra/newview/llfloaterparcel.cpp b/linden/indra/newview/llfloaterparcel.cpp index 4213150..a61f3b9 100644 --- a/linden/indra/newview/llfloaterparcel.cpp +++ b/linden/indra/newview/llfloaterparcel.cpp @@ -55,7 +55,7 @@ public: // requires trusted browser to trigger LLParcelHandler() : LLCommandHandler("parcel", true) { } bool handle(const LLSD& params, const LLSD& query_map, - LLWebBrowserCtrl* web) + LLMediaCtrl* web) { if (params.size() < 2) { diff --git a/linden/indra/newview/llfloaterpreference.cpp b/linden/indra/newview/llfloaterpreference.cpp index 09336cb..a94f7cf 100644 --- a/linden/indra/newview/llfloaterpreference.cpp +++ b/linden/indra/newview/llfloaterpreference.cpp @@ -94,7 +94,7 @@ public: // requires trusted browser LLPreferencesHandler() : LLCommandHandler("preferences", true) { } bool handle(const LLSD& tokens, const LLSD& query_map, - LLWebBrowserCtrl* web) + LLMediaCtrl* web) { LLFloaterPreference::show(NULL); return true; @@ -445,7 +445,7 @@ void LLFloaterPreference::onBtnOK( void* userdata ) // commit any outstanding text entry if (fp->hasFocus()) { - LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus(); + LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); if (cur_focus->acceptsTextInput()) { cur_focus->onCommit(); @@ -479,7 +479,7 @@ void LLFloaterPreference::onBtnApply( void* userdata ) LLFloaterPreference *fp =(LLFloaterPreference *)userdata; if (fp->hasFocus()) { - LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus(); + LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); if (cur_focus->acceptsTextInput()) { cur_focus->onCommit(); @@ -505,7 +505,7 @@ void LLFloaterPreference::onBtnCancel( void* userdata ) LLFloaterPreference *fp =(LLFloaterPreference *)userdata; if (fp->hasFocus()) { - LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus(); + LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); if (cur_focus->acceptsTextInput()) { cur_focus->onCommit(); diff --git a/linden/indra/newview/llfloatertos.cpp b/linden/indra/newview/llfloatertos.cpp index 6a392e0..2dedc79 100644 --- a/linden/indra/newview/llfloatertos.cpp +++ b/linden/indra/newview/llfloatertos.cpp @@ -161,12 +161,10 @@ BOOL LLFloaterTOS::postBuild() LLTextEditor *editor = getChild<LLTextEditor>("tos_text"); editor->setVisible( FALSE ); - LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("tos_html"); + LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("tos_html"); if ( web_browser ) { - // start to observe it so we see navigate complete events - web_browser->addObserver( this ); - + web_browser->addObserver(this); gResponsePtr = LLIamHere::build( this ); LLHTTPClient::get( getString( "real_url" ), gResponsePtr ); } @@ -179,7 +177,7 @@ void LLFloaterTOS::setSiteIsAlive( bool alive ) // only do this for TOS pages if ( mType == TOS_TOS ) { - LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("tos_html"); + LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("tos_html"); // if the contents of the site was retrieved if ( alive ) { @@ -201,12 +199,6 @@ void LLFloaterTOS::setSiteIsAlive( bool alive ) LLFloaterTOS::~LLFloaterTOS() { - // stop obsaerving events - LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("tos_html"); - if ( web_browser ) - { - web_browser->remObserver( this ); - }; // tell the responder we're not here anymore if ( gResponsePtr ) @@ -269,14 +261,17 @@ void LLFloaterTOS::onCancel( void* userdata ) } //virtual -void LLFloaterTOS::onNavigateComplete( const EventType& eventIn ) +void LLFloaterTOS::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent event) { - // skip past the loading screen navigate complete - if ( ++mLoadCompleteCount == 2 ) + if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) { - llinfos << "NAVIGATE COMPLETE" << llendl; - // enable Agree to TOS radio button now that page has loaded - LLCheckBoxCtrl * tos_agreement = getChild<LLCheckBoxCtrl>("agree_chk"); - tos_agreement->setEnabled( true ); - }; + // skip past the loading screen navigate complete + if ( ++mLoadCompleteCount == 2 ) + { + llinfos << "NAVIGATE COMPLETE" << llendl; + // enable Agree to TOS radio button now that page has loaded + LLCheckBoxCtrl * tos_agreement = getChild<LLCheckBoxCtrl>("agree_chk"); + tos_agreement->setEnabled( true ); + } + } } diff --git a/linden/indra/newview/llfloatertos.h b/linden/indra/newview/llfloatertos.h index dbec3ff..c5d5878 100644 --- a/linden/indra/newview/llfloatertos.h +++ b/linden/indra/newview/llfloatertos.h @@ -35,7 +35,7 @@ #include "llmodaldialog.h" #include "llassetstorage.h" -#include "llwebbrowserctrl.h" +#include "llmediactrl.h" class LLButton; class LLRadioGroup; @@ -45,7 +45,7 @@ class LLUUID; class LLFloaterTOS : public LLModalDialog, - public LLWebBrowserCtrlObserver + public LLViewerMediaObserver { public: virtual ~LLFloaterTOS(); @@ -70,7 +70,8 @@ public: void setSiteIsAlive( bool alive ); - virtual void onNavigateComplete( const EventType& eventIn ); + // inherited from LLViewerMediaObserver + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); private: // Asset_id is overwritten with LLUUID::null when agree is clicked. diff --git a/linden/indra/newview/llfloaterurlentry.cpp b/linden/indra/newview/llfloaterurlentry.cpp index 9d91aa9..8d483e5 100644 --- a/linden/indra/newview/llfloaterurlentry.cpp +++ b/linden/indra/newview/llfloaterurlentry.cpp @@ -227,7 +227,7 @@ void LLFloaterURLEntry::onBtnOK( void* userdata ) } // Discover the MIME type only for "http" scheme. - if(scheme == "http") + if(scheme == "http" || scheme == "https") { LLHTTPClient::getHeaderOnly( media_url, new LLMediaTypeResponder(self->getHandle())); diff --git a/linden/indra/newview/llhoverview.cpp b/linden/indra/newview/llhoverview.cpp index 6367380..109eece 100644 --- a/linden/indra/newview/llhoverview.cpp +++ b/linden/indra/newview/llhoverview.cpp @@ -154,12 +154,13 @@ void LLHoverView::updateHover(LLTool* current_tool) void LLHoverView::pickCallback(const LLPickInfo& pick_info) { + gHoverView->mLastPickInfo = pick_info; LLViewerObject* hit_obj = pick_info.getObject(); if (hit_obj) { gHoverView->setHoverActive(TRUE); - LLSelectMgr::getInstance()->setHoverObject(hit_obj); + LLSelectMgr::getInstance()->setHoverObject(hit_obj, pick_info.mObjectFace); gHoverView->mLastHoverObject = hit_obj; gHoverView->mHoverOffset = pick_info.mObjectOffset; } diff --git a/linden/indra/newview/llhoverview.h b/linden/indra/newview/llhoverview.h index 0891118..d0bb28d 100644 --- a/linden/indra/newview/llhoverview.h +++ b/linden/indra/newview/llhoverview.h @@ -42,6 +42,7 @@ #include "v3dmath.h" #include "lldarray.h" +#include "llviewerwindow.h" #include "llviewerobject.h" class LLTool; @@ -79,6 +80,7 @@ public: BOOL isHoveringLand() const; LLViewerObject* getLastHoverObject() const; + LLPickInfo getPickInfo() { return mLastPickInfo; } static void pickCallback(const LLPickInfo& info); @@ -103,6 +105,7 @@ protected: // If not null and not dead, we're over an object. LLPointer<LLViewerObject> mLastHoverObject; + LLPickInfo mLastPickInfo; // If not LLVector3d::ZERO, we're over land. LLVector3d mHoverLandGlobal; diff --git a/linden/indra/newview/llhudview.cpp b/linden/indra/newview/llhudview.cpp index 198514c..afcdd73 100644 --- a/linden/indra/newview/llhudview.cpp +++ b/linden/indra/newview/llhudview.cpp @@ -48,14 +48,19 @@ #include "lltracker.h" #include "llviewercamera.h" #include "llui.h" +#include "lluictrlfactory.h" LLHUDView *gHUDView = NULL; const S32 HUD_ARROW_SIZE = 32; -LLHUDView::LLHUDView() -: LLPanel() -{ } + + +LLHUDView::LLHUDView(const LLRect& r) +{ + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_hud.xml"); + userSetShape(r); +} LLHUDView::~LLHUDView() { } @@ -64,6 +69,7 @@ LLHUDView::~LLHUDView() void LLHUDView::draw() { LLTracker::drawHUDArrow(); + LLView::draw(); } @@ -89,4 +95,3 @@ BOOL LLHUDView::handleMouseDown(S32 x, S32 y, MASK mask) } return LLView::handleMouseDown(x, y, mask); } - diff --git a/linden/indra/newview/llhudview.h b/linden/indra/newview/llhudview.h index 7859e7f..05ff9c8 100644 --- a/linden/indra/newview/llhudview.h +++ b/linden/indra/newview/llhudview.h @@ -42,7 +42,7 @@ class LLHUDView : public LLPanel { public: - LLHUDView(); + LLHUDView(const LLRect& rect); virtual ~LLHUDView(); virtual void draw(); diff --git a/linden/indra/newview/llimpanel.cpp b/linden/indra/newview/llimpanel.cpp index 808a2c9..cc7a35d 100644 --- a/linden/indra/newview/llimpanel.cpp +++ b/linden/indra/newview/llimpanel.cpp @@ -2198,8 +2198,8 @@ void LLFloaterIMPanel::sendMsg() LLViewerStats::getInstance()->incStat(LLViewerStats::ST_IM_COUNT); + mInputEditor->setText(LLStringUtil::null); } - mInputEditor->setText(LLStringUtil::null); // Don't need to actually send the typing stop message, the other // client will infer it from receiving the message. diff --git a/linden/indra/newview/llloginhandler.cpp b/linden/indra/newview/llloginhandler.cpp index 6366398..30b05ef 100644 --- a/linden/indra/newview/llloginhandler.cpp +++ b/linden/indra/newview/llloginhandler.cpp @@ -111,7 +111,7 @@ void LLLoginHandler::parse(const LLSD& queryMap) bool LLLoginHandler::handle(const LLSD& tokens, const LLSD& query_map, - LLWebBrowserCtrl* web) + LLMediaCtrl* web) { parse(query_map); diff --git a/linden/indra/newview/llloginhandler.h b/linden/indra/newview/llloginhandler.h index c76d7e8..0844b80 100644 --- a/linden/indra/newview/llloginhandler.h +++ b/linden/indra/newview/llloginhandler.h @@ -40,7 +40,7 @@ class LLLoginHandler : public LLCommandHandler public: // allow from external browsers LLLoginHandler() : LLCommandHandler("login", false) { } - /*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, LLWebBrowserCtrl* web); + /*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web); // Fill in our internal fields from a SLURL like // secondlife:///app/login?first=Bob&last=Dobbs diff --git a/linden/indra/newview/llmediactrl.cpp b/linden/indra/newview/llmediactrl.cpp new file mode 100644 index 0000000..1530598 --- /dev/null +++ b/linden/indra/newview/llmediactrl.cpp @@ -0,0 +1,1201 @@ +/** + * @file LLMediaCtrl.cpp + * @brief Web browser UI control + * + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + + +#include "llmediactrl.h" + +// viewer includes +#include "llfloaterhtml.h" +#include "llfloaterworldmap.h" +#include "lluictrlfactory.h" +#include "llurldispatcher.h" +#include "llurlsimstring.h" +#include "llviewborder.h" +#include "llviewercontrol.h" +#include "llviewermedia.h" +#include "llviewerwindow.h" +#include "llnotifications.h" +#include "llweb.h" +#include "llrender.h" +#include "llpluginclassmedia.h" + +// linden library includes +#include "llfocusmgr.h" + +extern BOOL gRestoreGL; + +// Setting the mozilla buffer width to 2048 exactly doesn't work, since it pads its rowbytes a bit, pushing the texture width over 2048. +// 2000 should give enough headroom for any amount of padding it cares to add. +const S32 MAX_DIMENSION = 2000; +const S32 MAX_TEXTURE_DIMENSION = 2048; + +static LLRegisterWidget<LLMediaCtrl> r("web_browser"); + +LLMediaCtrl::LLMediaCtrl( const std::string& name, const LLRect& rect ) : + LLUICtrl( name, rect, FALSE, NULL, NULL ), + mTextureDepthBytes( 4 ), + mWebBrowserImage( 0 ), + mBorder(NULL), + mFrequentUpdates( true ), + mForceUpdate( false ), + mOpenLinksInExternalBrowser( false ), + mOpenLinksInInternalBrowser( false ), + mTrusted( false ), + mHomePageUrl( "" ), + mIgnoreUIScale( true ), + mAlwaysRefresh( false ), + mExternalUrl( "" ), + mMediaSource( 0 ), + mTakeFocusOnClick( true ), + mCurrentNavUrl( "about:blank" ), + mLastSetCursor( UI_CURSOR_ARROW ), + mStretchToFill( true ), + mMaintainAspectRatio ( true ), + mHideLoading (false) +{ + S32 screen_width = mIgnoreUIScale ? + llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]) : getRect().getWidth(); + S32 screen_height = mIgnoreUIScale ? + llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight(); + + mMediaSource = LLViewerMedia::newMediaImpl(mHomePageUrl, LLUUID::null, screen_width, screen_height, false, false, "text/html"); + if ( !mMediaSource ) + { + llwarns << "media source create failed " << llendl; + // return; + } + else + { + // create a new texture (based on LLDynamic texture) that will be used to display the output + mWebBrowserImage = new LLWebBrowserTexture( screen_width, screen_height, this, mMediaSource ); + } + + mMediaSource->setVisible( getVisible() ); + + mMediaSource->addObserver( this ); + + LLRect border_rect( 0, getRect().getHeight() + 2, getRect().getWidth() + 2, 0 ); + mBorder = new LLViewBorder( std::string("web control border"), border_rect, LLViewBorder::BEVEL_IN ); + addChild( mBorder ); +} + +//////////////////////////////////////////////////////////////////////////////// +// note: this is now a singleton and destruction happens via initClass() now +LLMediaCtrl::~LLMediaCtrl() +{ + + if (mMediaSource) + { + mMediaSource->remObserver( this ); + mMediaSource = NULL; + } + + if ( mWebBrowserImage ) + { + delete mWebBrowserImage; + mWebBrowserImage = NULL; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::setBorderVisible( BOOL border_visible ) +{ + if ( mBorder ) + { + mBorder->setVisible( border_visible ); + }; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::setTakeFocusOnClick( bool take_focus ) +{ + mTakeFocusOnClick = take_focus; +} + +//////////////////////////////////////////////////////////////////////////////// +// set flag that forces the embedded browser to open links in the external system browser +void LLMediaCtrl::setOpenInExternalBrowser( bool valIn ) +{ + mOpenLinksInExternalBrowser = valIn; +}; + +//////////////////////////////////////////////////////////////////////////////// +// set flag that forces the embedded browser to open links in the internal browser floater +void LLMediaCtrl::setOpenInInternalBrowser( bool valIn ) +{ + mOpenLinksInInternalBrowser = valIn; +}; + +//////////////////////////////////////////////////////////////////////////////// +void LLMediaCtrl::setTrusted( bool valIn ) +{ + mTrusted = valIn; +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask ) +{ + convertInputCoords(x, y); + + if (mMediaSource) + mMediaSource->mouseMove(x, y); + + gViewerWindow->setCursor(mLastSetCursor); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks ) +{ + if (mMediaSource && mMediaSource->hasMedia()) + mMediaSource->getMediaPlugin()->scrollEvent(0, clicks, MASK_NONE); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) +{ + convertInputCoords(x, y); + + if (mMediaSource) + { + mMediaSource->mouseUp(x, y); + + // *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup, + // in addition to the onFocusReceived() call below. Undo this. JC + if (!mTakeFocusOnClick) + { + mMediaSource->focus(false); + gViewerWindow->focusClient(); + } + } + + gFocusMgr.setMouseCapture( NULL ); + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLMediaCtrl::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + convertInputCoords(x, y); + + if (mMediaSource) + mMediaSource->mouseDown(x, y); + + gFocusMgr.setMouseCapture( this ); + + if (mTakeFocusOnClick) + { + setFocus( TRUE ); + } + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLMediaCtrl::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + convertInputCoords(x, y); + + if (mMediaSource) + mMediaSource->mouseLeftDoubleClick( x, y ); + + gFocusMgr.setMouseCapture( this ); + + if (mTakeFocusOnClick) + { + setFocus( TRUE ); + } + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::onFocusReceived() +{ + if (mMediaSource) + { + mMediaSource->focus(true); + + // Set focus for edit menu items + LLEditMenuHandler::gEditMenuHandler = mMediaSource; + } + + LLUICtrl::onFocusReceived(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::onFocusLost() +{ + if (mMediaSource) + { + mMediaSource->focus(false); + + if( LLEditMenuHandler::gEditMenuHandler == mMediaSource ) + { + // Clear focus for edit menu items + LLEditMenuHandler::gEditMenuHandler = NULL; + } + } + + gViewerWindow->focusClient(); + + LLUICtrl::onFocusLost(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask ) +{ + BOOL result = FALSE; + + // FIXME: THIS IS SO WRONG. + // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... + + if (mMediaSource) + { + if( MASK_CONTROL & mask ) + { + if( 'C' == key ) + { + mMediaSource->copy(); + result = TRUE; + } + else + if( 'V' == key ) + { + mMediaSource->paste(); + result = TRUE; + } + else + if( 'X' == key ) + { + mMediaSource->cut(); + result = TRUE; + } + } + + if(!result) + { + result = mMediaSource->handleKeyHere(key, mask); + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::handleVisibilityChange ( BOOL new_visibility ) +{ + llinfos << "visibility changed to " << (new_visibility?"true":"false") << llendl; + if(mMediaSource) + { + mMediaSource->setVisible( new_visibility ); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char) +{ + BOOL result = FALSE; + + // only accept 'printable' characters, sigh... + if (uni_char >= 32 // discard 'control' characters + && uni_char != 127) // SDL thinks this is 'delete' - yuck. + { + if (mMediaSource) + result = mMediaSource->handleUnicodeCharHere(uni_char); + } + + return result; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::onVisibilityChange ( BOOL new_visibility ) +{ + // set state of frequent updates automatically if visibility changes + if ( new_visibility ) + { + mFrequentUpdates = true; + } + else + { + mFrequentUpdates = false; + } + LLUICtrl::onVisibilityChange(new_visibility); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::reshape( S32 width, S32 height, BOOL called_from_parent ) +{ + S32 screen_width = mIgnoreUIScale ? llround((F32)width * LLUI::sGLScaleFactor.mV[VX]) : width; + S32 screen_height = mIgnoreUIScale ? llround((F32)height * LLUI::sGLScaleFactor.mV[VY]) : height; + +// llinfos << "reshape called with width = " << width << ", height = " << height << llendl; + + // when floater is minimized, these sizes are negative + if ( mWebBrowserImage && screen_height > 0 && screen_width > 0 ) + { + mWebBrowserImage->resize( screen_width, screen_height ); + mForceUpdate = true; + } + + LLUICtrl::reshape( width, height, called_from_parent ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::navigateBack() +{ + if (mMediaSource && mMediaSource->hasMedia()) + { + mMediaSource->getMediaPlugin()->browse_back(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::navigateForward() +{ + if (mMediaSource && mMediaSource->hasMedia()) + { + mMediaSource->getMediaPlugin()->browse_forward(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +bool LLMediaCtrl::canNavigateBack() +{ + if (mMediaSource) + return mMediaSource->canNavigateBack(); + else + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// +bool LLMediaCtrl::canNavigateForward() +{ + if (mMediaSource) + return mMediaSource->canNavigateForward(); + else + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::set404RedirectUrl( std::string redirect_url ) +{ + if(mMediaSource && mMediaSource->hasMedia()) + mMediaSource->getMediaPlugin()->set_status_redirect( 404, redirect_url ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::clr404RedirectUrl() +{ + if(mMediaSource && mMediaSource->hasMedia()) + mMediaSource->getMediaPlugin()->set_status_redirect(404, ""); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) +{ + // don't browse to anything that starts with secondlife:// or sl:// + const std::string protocol1 = "secondlife://"; + const std::string protocol2 = "sl://"; + if ((LLStringUtil::compareInsensitive(url_in.substr(0, protocol1.length()), protocol1) == 0) || + (LLStringUtil::compareInsensitive(url_in.substr(0, protocol2.length()), protocol2) == 0)) + { + // TODO: Print out/log this attempt? + // llinfos << "Rejecting attempt to load restricted website :" << urlIn << llendl; + return; + } + + if (mMediaSource) + { + mCurrentNavUrl = url_in; + mMediaSource->navigateTo(url_in, mime_type, mime_type.empty()); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::string& filename_in ) +{ + std::string language = LLUI::getLanguage(); + std::string delim = gDirUtilp->getDirDelimiter(); + std::string filename; + + filename += subdir; + filename += delim; + filename += filename_in; + + std::string expanded_filename = gDirUtilp->findSkinnedFilename("html", language, filename); + + if (! gDirUtilp->fileExists(expanded_filename)) + { + if (language != "en-us") + { + expanded_filename = gDirUtilp->findSkinnedFilename("html", "en-us", filename); + if (! gDirUtilp->fileExists(expanded_filename)) + { + llwarns << "File " << subdir << delim << filename_in << "not found" << llendl; + return; + } + } + else + { + llwarns << "File " << subdir << delim << filename_in << "not found" << llendl; + return; + } + } + if (mMediaSource) + { + mCurrentNavUrl = expanded_filename; + mMediaSource->navigateTo(expanded_filename, "text/html", false); + } + +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::navigateHome() +{ + if( mHomePageUrl.length() ) + { + if (mMediaSource) + mMediaSource->navigateTo(mHomePageUrl); + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::setHomePageUrl( const std::string urlIn ) +{ + mHomePageUrl = urlIn; +} + +//////////////////////////////////////////////////////////////////////////////// +// +bool LLMediaCtrl::setCaretColor(unsigned int red, unsigned int green, unsigned int blue) +{ + //NOOP + return false; +} +//////////////////////////////////////////////////////////////////////////////// +// +std::string LLMediaCtrl::getHomePageUrl() +{ + return mHomePageUrl; +} + +//////////////////////////////////////////////////////////////////////////////// +// +LLPluginClassMedia* LLMediaCtrl::getMediaPlugin() +{ + return mMediaSource.isNull() ? NULL : mMediaSource->getMediaPlugin(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::draw() +{ + if ( ! mWebBrowserImage ) + return; + + if ( gRestoreGL == 1 ) + { + LLRect r = getRect(); + reshape( r.getWidth(), r.getHeight(), FALSE ); + return; + }; + + // NOTE: optimization needed here - probably only need to do this once + // unless tearoffs change the parent which they probably do. + const LLUICtrl* ptr = findRootMostFocusRoot(); + if ( ptr && ptr->hasFocus() ) + { + setFrequentUpdates( true ); + } + else + { + setFrequentUpdates( false ); + }; + + // alpha off for this + LLGLSUIDefault gls_ui; + LLGLDisable gls_alphaTest( GL_ALPHA_TEST ); + + gGL.pushMatrix(); + { + if (mIgnoreUIScale) + { + glLoadIdentity(); + // font system stores true screen origin, need to scale this by UI scale factor + // to get render origin for this view (with unit scale) + gGL.translatef(floorf(LLFontGL::sCurOrigin.mX * LLUI::sGLScaleFactor.mV[VX]), + floorf(LLFontGL::sCurOrigin.mY * LLUI::sGLScaleFactor.mV[VY]), + LLFontGL::sCurOrigin.mZ); + } + + // scale texture to fit the space using texture coords + gGL.getTexUnit(0)->bind(mWebBrowserImage->getTexture()); + gGL.color4fv( LLColor4::white.mV ); + F32 max_u = ( F32 )mWebBrowserImage->getMediaWidth() / ( F32 )mWebBrowserImage->getWidth(); + F32 max_v = ( F32 )mWebBrowserImage->getMediaHeight() / ( F32 )mWebBrowserImage->getHeight(); + + LLRect r = getRect(); + S32 width, height; + S32 x_offset = 0; + S32 y_offset = 0; + + if(mStretchToFill) + { + if(mMaintainAspectRatio) + { + F32 media_aspect = (F32)(mWebBrowserImage->getMediaWidth()) / (F32)(mWebBrowserImage->getMediaHeight()); + F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight()); + if(media_aspect > view_aspect) + { + // max width, adjusted height + width = r.getWidth(); + height = llmin(llmax(S32(width / media_aspect), 0), r.getHeight()); + } + else + { + // max height, adjusted width + height = r.getHeight(); + width = llmin(llmax(S32(height * media_aspect), 0), r.getWidth()); + } + } + else + { + width = r.getWidth(); + height = r.getHeight(); + } + } + else + { + width = llmin(mWebBrowserImage->getMediaWidth(), r.getWidth()); + height = llmin(mWebBrowserImage->getMediaHeight(), r.getHeight()); + } + + x_offset = (r.getWidth() - width) / 2; + y_offset = (r.getHeight() - height) / 2; + + if (mIgnoreUIScale) + { + width = llround((F32)width * LLUI::sGLScaleFactor.mV[VX]); + height = llround((F32)height * LLUI::sGLScaleFactor.mV[VY]); + x_offset = llround((F32)x_offset * LLUI::sGLScaleFactor.mV[VX]); + y_offset = llround((F32)y_offset * LLUI::sGLScaleFactor.mV[VY]); + } + + // draw the browser + gGL.setSceneBlendType(LLRender::BT_REPLACE); + gGL.begin( LLRender::QUADS ); + if (! mWebBrowserImage->getTextureCoordsOpenGL()) + { + // render using web browser reported width and height, instead of trying to invert GL scale + gGL.texCoord2f( max_u, 0.f ); + gGL.vertex2i( x_offset + width, y_offset + height ); + + gGL.texCoord2f( 0.f, 0.f ); + gGL.vertex2i( x_offset, y_offset + height ); + + gGL.texCoord2f( 0.f, max_v ); + gGL.vertex2i( x_offset, y_offset ); + + gGL.texCoord2f( max_u, max_v ); + gGL.vertex2i( x_offset + width, y_offset ); + } + else + { + // render using web browser reported width and height, instead of trying to invert GL scale + gGL.texCoord2f( max_u, max_v ); + gGL.vertex2i( x_offset + width, y_offset + height ); + + gGL.texCoord2f( 0.f, max_v ); + gGL.vertex2i( x_offset, y_offset + height ); + + gGL.texCoord2f( 0.f, 0.f ); + gGL.vertex2i( x_offset, y_offset ); + + gGL.texCoord2f( max_u, 0.f ); + gGL.vertex2i( x_offset + width, y_offset ); + } + gGL.end(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } + gGL.popMatrix(); + + // highlight if keyboard focus here. (TODO: this needs some work) + if ( mBorder->getVisible() ) + mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) ); + + + LLUICtrl::draw(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::convertInputCoords(S32& x, S32& y) +{ + x = mIgnoreUIScale ? llround((F32)x * LLUI::sGLScaleFactor.mV[VX]) : x; + if ( ! mWebBrowserImage->getTextureCoordsOpenGL() ) + { + y = mIgnoreUIScale ? llround((F32)(y) * LLUI::sGLScaleFactor.mV[VY]) : y; + } + else + { + y = mIgnoreUIScale ? llround((F32)(getRect().getHeight() - y) * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight() - y; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// static +bool LLMediaCtrl::onClickLinkExternalTarget(const LLSD& notification, const LLSD& response ) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + if ( 0 == option ) + { + // open in external browser because we don't support + // creation of our own secondary browser windows + LLWeb::loadURLExternal( notification["payload"]["external_url"].asString() ); + } + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// inherited from LLViewerMediaObserver +//virtual +void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ + switch(event) + { + case MEDIA_EVENT_CONTENT_UPDATED: + { + // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL; + }; + break; + + case MEDIA_EVENT_TIME_DURATION_UPDATED: + { + // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << LL_ENDL; + }; + break; + + case MEDIA_EVENT_SIZE_CHANGED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_SIZE_CHANGED " << LL_ENDL; + LLRect r = getRect(); + reshape( r.getWidth(), r.getHeight(), FALSE ); + }; + break; + + case MEDIA_EVENT_CURSOR_CHANGED: + { + LL_INFOS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL; + + std::string cursor = self->getCursorName(); + + if(cursor == "arrow") + mLastSetCursor = UI_CURSOR_ARROW; + else if(cursor == "ibeam") + mLastSetCursor = UI_CURSOR_IBEAM; + else if(cursor == "splith") + mLastSetCursor = UI_CURSOR_SIZEWE; + else if(cursor == "splitv") + mLastSetCursor = UI_CURSOR_SIZENS; + else if(cursor == "hand") + mLastSetCursor = UI_CURSOR_HAND; + else // for anything else, default to the arrow + mLastSetCursor = UI_CURSOR_ARROW; + }; + break; + + case MEDIA_EVENT_NAVIGATE_BEGIN: + { + LL_INFOS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN, url is " << self->getNavigateURI() << LL_ENDL; + if(mMediaSource && mHideLoading) + { + mMediaSource->suspendUpdates(true); + } + }; + break; + + case MEDIA_EVENT_NAVIGATE_COMPLETE: + { + LL_INFOS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL; + if(mMediaSource && mHideLoading) + { + mMediaSource->suspendUpdates(false); + } + }; + break; + + case MEDIA_EVENT_PROGRESS_UPDATED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << LL_ENDL; + }; + break; + + case MEDIA_EVENT_STATUS_TEXT_CHANGED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << LL_ENDL; + }; + break; + + case MEDIA_EVENT_LOCATION_CHANGED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << LL_ENDL; + }; + break; + + case MEDIA_EVENT_CLICK_LINK_HREF: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL; + onClickLinkHref(self); + }; + break; + + case MEDIA_EVENT_CLICK_LINK_NOFOLLOW: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL; + onClickLinkNoFollow(self); + }; + break; + + case MEDIA_EVENT_PLUGIN_FAILED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL; + }; + break; + + case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL; + }; + break; + + case MEDIA_EVENT_NAME_CHANGED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAME_CHANGED" << LL_ENDL; + }; + break; + }; + + // chain all events to any potential observers of this object. + emitEvent(self, event); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::onClickLinkHref( LLPluginClassMedia* self ) +{ + // retrieve the event parameters + std::string target = self->getClickTarget(); + std::string url = self->getClickURL(); + + // if there is a value for the target + if ( !target.empty() ) + { + if ( target == "_external" ) + { + mExternalUrl = url; + LLSD payload; + payload["external_url"] = mExternalUrl; + LLNotifications::instance().add( "WebLaunchExternalTarget", LLSD(), payload, onClickLinkExternalTarget); + return; + } + } + + const std::string protocol1( "http://" ); + const std::string protocol2( "https://" ); + if( mOpenLinksInExternalBrowser ) + { + if ( !url.empty() ) + { + if ( LLStringUtil::compareInsensitive( url.substr( 0, protocol1.length() ), protocol1 ) == 0 || + LLStringUtil::compareInsensitive( url.substr( 0, protocol2.length() ), protocol2 ) == 0 ) + { + LLWeb::loadURLExternal( url ); + } + } + } + else + if( mOpenLinksInInternalBrowser ) + { + if ( !url.empty() ) + { + if ( LLStringUtil::compareInsensitive( url.substr( 0, protocol1.length() ), protocol1 ) == 0 || + LLStringUtil::compareInsensitive( url.substr( 0, protocol2.length() ), protocol2 ) == 0 ) + { + // If we spawn a new LLFloaterHTML, assume we want it to + // follow this LLMediaCtrl's trust for whether or + // not to open secondlife:///app/ links. JC. +// const bool open_links_externally = false; +// LLFloaterHtml::getInstance()->show( +// event_in.mStringPayload, +// "Second Life Browser", +// open_links_externally, +// mTrusted); + } + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::onClickLinkNoFollow( LLPluginClassMedia* self ) +{ + std::string url = self->getClickURL(); + if (LLURLDispatcher::isSLURLCommand(url) + && !mTrusted) + { + // block handling of this secondlife:///app/ URL + LLNotifications::instance().add("UnableToOpenCommandURL"); + return; + } + + LLURLDispatcher::dispatch(url, this, mTrusted); +} + +//////////////////////////////////////////////////////////////////////////////// +// +LLWebBrowserTexture::LLWebBrowserTexture( S32 width, S32 height, LLMediaCtrl* browserCtrl, viewer_media_t media_source ) : + LLDynamicTexture( 512, 512, 4, ORDER_FIRST, TRUE ), + mNeedsUpdate( true ), + mNeedsResize( false ), + mTextureCoordsOpenGL( true ), + mWebBrowserCtrl( browserCtrl ), + mMediaSource(media_source) +{ + mElapsedTime.start(); + + resize( width, height ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +LLWebBrowserTexture::~LLWebBrowserTexture() +{ + mElapsedTime.stop(); + mMediaSource = NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLWebBrowserTexture::needsRender() +{ + bool texture_dirty = false; + + if ( mWebBrowserCtrl->getFrequentUpdates() || + mWebBrowserCtrl->getAlwaysRefresh() || + mWebBrowserCtrl->getForceUpdate() ) + { + // All of these force an update + return TRUE; + } + + // If the texture needs updating, render needs to be called. + if (mMediaSource && mMediaSource->hasMedia()) + { + LLPluginClassMedia* media = mMediaSource->getMediaPlugin(); + + if(media->textureValid() && media->getDirty()) + { + texture_dirty = true; + } + } + + + return texture_dirty; +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLWebBrowserTexture::render() +{ + if(updateBrowserTexture()) + { + // updateBrowserTexture already verified that the media plugin is there and the texture is valid. + LLPluginClassMedia* media_plugin = mMediaSource->getMediaPlugin(); + LLRect dirty_rect; + + if(mNeedsUpdate) + { + // If we need an update, use the whole rect instead of the dirty rect. + dirty_rect.mLeft = 0; + dirty_rect.mBottom = 0; + dirty_rect.mRight = media_plugin->getWidth(); + dirty_rect.mTop = media_plugin->getHeight(); + } + else + { + mNeedsUpdate = media_plugin->getDirty(&dirty_rect); + } + + if ( mNeedsUpdate ) + { + mNeedsUpdate = false; + mWebBrowserCtrl->setForceUpdate(false); + + // Constrain the dirty rect to be inside the texture + S32 x_pos = llmax(dirty_rect.mLeft, 0); + S32 y_pos = llmax(dirty_rect.mBottom, 0); + S32 width = llmin(dirty_rect.mRight, getWidth()) - x_pos; + S32 height = llmin(dirty_rect.mTop, getHeight()) - y_pos; + + if(width > 0 && height > 0) + { + U8* data = media_plugin->getBitsData(); + + // Offset the pixels pointer to match x_pos and y_pos + data += ( x_pos * media_plugin->getTextureDepth() * media_plugin->getBitsWidth() ); + data += ( y_pos * media_plugin->getTextureDepth() ); + + mTexture->setSubImage( + data, + media_plugin->getBitsWidth(), + media_plugin->getBitsHeight(), + x_pos, + y_pos, + width, + height, + TRUE); // force a fast update (i.e. don't call analyzeAlpha, etc.) + } + + media_plugin->resetDirty(); + + return TRUE; + }; + }; + + return FALSE; +} + +//////////////////////////////////////////////////////////////////////////////// +// +S32 LLWebBrowserTexture::getMediaWidth() +{ + return mMediaWidth; +} + +//////////////////////////////////////////////////////////////////////////////// +// +S32 LLWebBrowserTexture::getMediaHeight() +{ + return mMediaHeight; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLWebBrowserTexture::setNeedsUpdate() +{ + mNeedsUpdate = true; +} + +//////////////////////////////////////////////////////////////////////////////// +// +bool LLWebBrowserTexture::getNeedsUpdate() +{ + return mNeedsUpdate; +} + +//////////////////////////////////////////////////////////////////////////////// +// +bool LLWebBrowserTexture::getTextureCoordsOpenGL() +{ + return mTextureCoordsOpenGL; +} + + +//////////////////////////////////////////////////////////////////////////////// +// +void LLWebBrowserTexture::resize( S32 new_width, S32 new_height ) +{ + F32 scale_ratio = 1.f; + if (new_width > MAX_DIMENSION) + { + scale_ratio = (F32)MAX_DIMENSION / (F32)new_width; + } + if (new_height > MAX_DIMENSION) + { + scale_ratio = llmin(scale_ratio, (F32)MAX_DIMENSION / (F32)new_height); + } + + mMediaWidth = llround(scale_ratio * (F32)new_width); + mMediaHeight = llround(scale_ratio * (F32)new_height); + + adjustSize(); +} + +bool LLWebBrowserTexture::adjustSize() +{ + if (mMediaSource && mMediaSource->hasMedia()) + { + int natural_width = mMediaSource->getMediaPlugin()->getNaturalWidth(); + int natural_height = mMediaSource->getMediaPlugin()->getNaturalHeight(); + + if(natural_width != 0) + { + // If the media has a "natural size", use it. + mMediaWidth = natural_width; + mMediaHeight = natural_height; + } + + mMediaSource->setSize(mMediaWidth, mMediaHeight); + mNeedsResize = false; + + return true; + } + else + { + // The media isn't fully initialized yet, delay the resize until later. + mNeedsResize = true; + } + + return false; +} + +bool LLWebBrowserTexture::updateBrowserTexture() +{ + if (!adjustSize()) + return false; + + LLPluginClassMedia* media = mMediaSource->getMediaPlugin(); + + if(!media->textureValid()) + return false; + + if(mMediaSource->mNeedsNewTexture + || media->getTextureWidth() != mWidth + || media->getTextureHeight() != mHeight ) + { + releaseGLTexture(); + + mWidth = media->getTextureWidth(); + mHeight = media->getTextureHeight(); + mTextureCoordsOpenGL = media->getTextureCoordsOpenGL(); + + // will create mWidth * mHeight sized texture, using the texture params specified by the media. + LLDynamicTexture::generateGLTexture( + media->getTextureFormatInternal(), + media->getTextureFormatPrimary(), + media->getTextureFormatType(), + media->getTextureFormatSwapBytes()); + + + mMediaSource->mNeedsNewTexture = false; + } + + return true; +} +// virtual +LLXMLNodePtr LLMediaCtrl::getXML(bool save_children) const +{ + LLXMLNodePtr node = LLUICtrl::getXML(); + + node->setName(LL_WEB_BROWSER_CTRL_TAG); + + return node; +} + +LLView* LLMediaCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) +{ + std::string name("web_browser"); + node->getAttributeString("name", name); + + std::string start_url(""); + node->getAttributeString("start_url", start_url ); + + BOOL border_visible = true; + node->getAttributeBOOL("border_visible", border_visible); + + LLRect rect; + createRect(node, rect, parent, LLRect()); + + LLMediaCtrl* web_browser = new LLMediaCtrl( name, rect ); + + if(node->hasAttribute("caret_color")) + { + LLColor4 color; + LLUICtrlFactory::getAttributeColor(node, "caret_color", color); + LLColor4U colorU = LLColor4U(color); + web_browser->setCaretColor( colorU.mV[0], colorU.mV[1], colorU.mV[2] ); + } + + BOOL ignore_ui_scale = web_browser->getIgnoreUIScale(); + node->getAttributeBOOL("ignore_ui_scale", ignore_ui_scale); + web_browser->setIgnoreUIScale((bool)ignore_ui_scale); + + web_browser->initFromXML(node, parent); + + web_browser->setHomePageUrl( start_url ); + + web_browser->setBorderVisible( border_visible ); + + if(! start_url.empty()) + { + web_browser->navigateHome(); + } + + return web_browser; +} + +std::string LLMediaCtrl::getCurrentNavUrl() +{ + return mCurrentNavUrl; +} + diff --git a/linden/indra/newview/llmediactrl.h b/linden/indra/newview/llmediactrl.h new file mode 100644 index 0000000..77f59c7 --- /dev/null +++ b/linden/indra/newview/llmediactrl.h @@ -0,0 +1,201 @@ +/** + * @file llmediactrl.h + * @brief Web browser UI control + * + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLMediaCtrl_H +#define LL_LLMediaCtrl_H + +#include "llviewermedia.h" + +#include "lluictrl.h" +#include "llframetimer.h" +#include "lldynamictexture.h" + +class LLViewBorder; +class LLWebBrowserTexture; +class LLUICtrlFactory; + +//////////////////////////////////////////////////////////////////////////////// +// +class LLMediaCtrl : + public LLUICtrl, + public LLViewerMediaObserver, + public LLViewerMediaEventEmitter +{ + public: + LLMediaCtrl( const std::string& name, const LLRect& rect ); + virtual ~LLMediaCtrl(); + + void setBorderVisible( BOOL border_visible ); + + // For the tutorial window, we don't want to take focus on clicks, + // as the examples include how to move around with the arrow + // keys. Thus we keep focus on the app by setting this false. + // Defaults to true. + void setTakeFocusOnClick( bool take_focus ); + + virtual LLXMLNodePtr getXML(bool save_children = true) const; + static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); + + // handle mouse related methods + virtual BOOL handleHover( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); + virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); + virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); + + // navigation + void navigateTo( std::string url_in, std::string mime_type = ""); + void navigateBack(); + void navigateHome(); + void navigateForward(); + void navigateToLocalPage( const std::string& subdir, const std::string& filename_in ); + bool canNavigateBack(); + bool canNavigateForward(); + void setOpenInExternalBrowser( bool valIn ); + void setOpenInInternalBrowser( bool valIn ); + std::string getCurrentNavUrl(); + + // By default, we do not handle "secondlife:///app/" SLURLs, because + // those can cause teleports, open windows, etc. We cannot be sure + // that each "click" is actually due to a user action, versus + // Javascript or some other mechanism. However, we need the search + // floater and login page to handle these URLs. Those are safe + // because we control the page content. See DEV-9530. JC. + void setTrusted( bool valIn ); + + void setHomePageUrl( const std::string urlIn ); + std::string getHomePageUrl(); + + // set/clear URL to visit when a 404 page is reached + void set404RedirectUrl( std::string redirect_url ); + void clr404RedirectUrl(); + + // accessor/mutator for flag that indicates if frequent updates to texture happen + bool getFrequentUpdates() { return mFrequentUpdates; }; + void setFrequentUpdates( bool frequentUpdatesIn ) { mFrequentUpdates = frequentUpdatesIn; }; + + void setIgnoreUIScale(bool ignore) { mIgnoreUIScale = ignore; } + bool getIgnoreUIScale() { return mIgnoreUIScale; } + + void setAlwaysRefresh(bool refresh) { mAlwaysRefresh = refresh; } + bool getAlwaysRefresh() { return mAlwaysRefresh; } + + void setForceUpdate(bool force_update) { mForceUpdate = force_update; } + bool getForceUpdate() { return mForceUpdate; } + + LLPluginClassMedia* getMediaPlugin(); + + bool setCaretColor( unsigned int red, unsigned int green, unsigned int blue ); + + + // over-rides + virtual BOOL handleKeyHere( KEY key, MASK mask); + virtual void handleVisibilityChange ( BOOL new_visibility ); + virtual BOOL handleUnicodeCharHere(llwchar uni_char); + virtual void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE); + virtual void draw(); + virtual void onVisibilityChange ( BOOL curVisibilityIn ); + + // focus overrides + void onFocusLost(); + void onFocusReceived(); + + // Incoming media event dispatcher + virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + + // handlers for individual events (could be done inside the switch in handleMediaEvent, they're just individual functions for clarity) + void onClickLinkHref( LLPluginClassMedia* self ); + void onClickLinkNoFollow( LLPluginClassMedia* self ); + + protected: + void convertInputCoords(S32& x, S32& y); + + private: + static bool onClickLinkExternalTarget( const LLSD&, const LLSD& ); + + const S32 mTextureDepthBytes; + LLWebBrowserTexture* mWebBrowserImage; + LLViewBorder* mBorder; + bool mFrequentUpdates; + bool mForceUpdate; + bool mOpenLinksInExternalBrowser; + bool mOpenLinksInInternalBrowser; + bool mTrusted; + std::string mHomePageUrl; + std::string mExternalUrl; + std::string mCurrentNavUrl; + bool mIgnoreUIScale; + bool mAlwaysRefresh; + viewer_media_t mMediaSource; + bool mTakeFocusOnClick; + ECursorType mLastSetCursor; + bool mStretchToFill; + bool mMaintainAspectRatio; + bool mHideLoading; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +class LLWebBrowserTexture : public LLDynamicTexture +{ +LOG_CLASS(LLWebBrowserTexture); + public: + LLWebBrowserTexture( S32 width, S32 height, LLMediaCtrl* browserCtrl, viewer_media_t media_source ); + virtual ~LLWebBrowserTexture(); + + virtual BOOL needsRender(); + virtual void preRender( BOOL clear_depth = TRUE ) {}; + virtual void postRender( BOOL success ) {}; + virtual BOOL render(); + + bool adjustSize(); + S32 getMediaWidth(); + S32 getMediaHeight(); + bool getNeedsUpdate(); + void setNeedsUpdate(); + bool getTextureCoordsOpenGL(); + + void resize( S32 new_width, S32 new_height ); + bool updateBrowserTexture(); + + protected: + S32 mMediaWidth; + S32 mMediaHeight; + bool mNeedsUpdate; + bool mNeedsResize; + bool mTextureCoordsOpenGL; + LLFrameTimer mElapsedTime; + LLMediaCtrl* mWebBrowserCtrl; + viewer_media_t mMediaSource; +}; + +#endif // LL_LLMediaCtrl_H diff --git a/linden/indra/newview/llmediaremotectrl.cpp b/linden/indra/newview/llmediaremotectrl.cpp index f2ec414..a62973a 100644 --- a/linden/indra/newview/llmediaremotectrl.cpp +++ b/linden/indra/newview/llmediaremotectrl.cpp @@ -34,7 +34,7 @@ #include "llmediaremotectrl.h" -#include "audioengine.h" +#include "llaudioengine.h" #include "lliconctrl.h" #include "llmimetypes.h" #include "lloverlaybar.h" @@ -86,6 +86,7 @@ BOOL LLMediaRemoteCtrl::postBuild() childSetAction("media_stop",LLOverlayBar::mediaStop,this); childSetAction("music_stop",LLOverlayBar::toggleMusicPlay,this); childSetAction("media_pause",LLOverlayBar::toggleMediaPlay,this); + childSetAction("music_pause",LLOverlayBar::toggleMusicPlay,this); childSetAction("expand", onClickExpandBtn, this); return TRUE; @@ -135,9 +136,11 @@ void* LLMediaRemoteCtrl::createVolumePanel(void* data) // Virtual void LLMediaRemoteCtrl::setToolTip(const std::string& msg) { - std::string mime_type = LLMIMETypes::translate(LLViewerMedia::getMimeType()); - std::string tool_tip = LLMIMETypes::findToolTip(LLViewerMedia::getMimeType()); - std::string play_tip = LLMIMETypes::findPlayTip(LLViewerMedia::getMimeType()); + // TODO: this gets removed for Media on a Prim + + const std::string mime_type = LLViewerParcelMedia::getMimeType(); + std::string tool_tip = LLMIMETypes::findToolTip(mime_type); + std::string play_tip = LLMIMETypes::findPlayTip(mime_type); // childSetToolTip("media_stop", mControls->getString("stop_label") + "\n" + tool_tip); childSetToolTip("media_icon", tool_tip); childSetToolTip("media_play", play_tip); @@ -150,6 +153,7 @@ void LLMediaRemoteCtrl::enableMediaButtons() bool stop_media_enabled = false; bool play_music_enabled = false; bool stop_music_enabled = false; + bool music_show_pause = false; bool media_show_pause = false; LLColor4 music_icon_color = LLUI::sColorsGroup->getColor( "IconDisabledColor" ); LLColor4 media_icon_color = LLUI::sColorsGroup->getColor( "IconDisabledColor" ); @@ -161,7 +165,7 @@ void LLMediaRemoteCtrl::enableMediaButtons() if (gSavedSettings.getBOOL("AudioStreamingVideo")) { - if ( parcel && parcel->getMediaURL()[0]) + if ( parcel && !parcel->getMediaURL().empty()) { // Set the tooltip // Put this text into xui file @@ -171,23 +175,22 @@ void LLMediaRemoteCtrl::enableMediaButtons() play_media_enabled = true; media_icon_color = LLUI::sColorsGroup->getColor( "IconEnabledColor" ); - LLMediaBase::EStatus status = LLViewerParcelMedia::getStatus(); + LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus(); switch(status) { - case LLMediaBase::STATUS_STOPPED: - case LLMediaBase::STATUS_UNKNOWN: + case LLViewerMediaImpl::MEDIA_NONE: media_show_pause = false; stop_media_enabled = false; break; - case LLMediaBase::STATUS_STARTED: - case LLMediaBase::STATUS_NAVIGATING: - case LLMediaBase::STATUS_RESETTING: + case LLViewerMediaImpl::MEDIA_LOADING: + case LLViewerMediaImpl::MEDIA_LOADED: + case LLViewerMediaImpl::MEDIA_PLAYING: // HACK: only show the pause button for movie types media_show_pause = LLMIMETypes::widgetType(parcel->getMediaType()) == "movie" ? true : false; stop_media_enabled = true; play_media_enabled = false; break; - case LLMediaBase::STATUS_PAUSED: + case LLViewerMediaImpl::MEDIA_PAUSED: media_show_pause = false; stop_media_enabled = true; break; @@ -197,46 +200,42 @@ void LLMediaRemoteCtrl::enableMediaButtons() } } } + if (gSavedSettings.getBOOL("AudioStreamingMusic") && gAudiop) { - - if ( parcel && parcel->getMusicURL()[0]) + if ( parcel && !parcel->getMusicURL().empty()) { + play_music_enabled = true; music_icon_color = LLUI::sColorsGroup->getColor( "IconEnabledColor" ); if (gOverlayBar->musicPlaying()) { - play_music_enabled = false; + music_show_pause = true; stop_music_enabled = true; } else { - play_music_enabled = true; + music_show_pause = false; stop_music_enabled = false; } } - // if no mime type has been set disable play - if( LLViewerMedia::getMimeType().empty() - || LLViewerMedia::getMimeType() == "none/none") - { - play_media_enabled = false; - stop_media_enabled = false; - } + // Don't test the mime-type: this is not updated in a consistent basis. The existence of a valid gAudiop is enough guarantee. } const std::string media_icon_name = LLMIMETypes::findIcon(media_type); - LLButton* music_play_btn = getChild<LLButton>("music_play"); LLButton* music_stop_btn = getChild<LLButton>("music_stop"); - - music_play_btn->setEnabled(play_music_enabled); - music_stop_btn->setEnabled(stop_music_enabled); - childSetColor("music_icon", music_icon_color); - + LLButton* music_pause_btn = getChild<LLButton>("music_pause"); LLButton* media_play_btn = getChild<LLButton>("media_play"); LLButton* media_stop_btn = getChild<LLButton>("media_stop"); LLButton* media_pause_btn = getChild<LLButton>("media_pause"); LLIconCtrl* media_icon = getChild<LLIconCtrl>("media_icon"); + music_play_btn->setEnabled(play_music_enabled); + music_stop_btn->setEnabled(stop_music_enabled); + music_pause_btn->setEnabled(music_show_pause); + music_pause_btn->setVisible(music_show_pause); + music_play_btn->setVisible(! music_show_pause); + childSetColor("music_icon", music_icon_color); if(!media_icon_name.empty()) { media_icon->setImage(media_icon_name); diff --git a/linden/indra/newview/llmimetypes.cpp b/linden/indra/newview/llmimetypes.cpp index bfbc81a..525e89c 100644 --- a/linden/indra/newview/llmimetypes.cpp +++ b/linden/indra/newview/llmimetypes.cpp @@ -46,6 +46,8 @@ std::string sDefaultWidgetType; // Returned when we don't know what widget set to use std::string sDefaultImpl; // Returned when we don't know what impl to use +std::string sXMLFilename; + // Squirrel away XML filename so we know how to reset ///////////////////////////////////////////////////////////////////////////// @@ -146,6 +148,8 @@ bool LLMIMETypes::parseMIMETypes(const std::string& xml_filename) sWidgetMap[set_name] = info; } } + + sXMLFilename = xml_filename; return true; } @@ -267,3 +271,23 @@ bool LLMIMETypes::findAllowLooping(const std::string& mime_type) } return allow_looping; } + +// static +bool LLMIMETypes::isTypeHandled(const std::string& mime_type) +{ + mime_info_map_t::const_iterator it = sMap.find(mime_type); + if (it != sMap.end()) + { + return true; + } + return false; +} + +// static +void LLMIMETypes::reload(void*) +{ + sMap.clear(); + sWidgetMap.clear(); + (void)LLMIMETypes::parseMIMETypes(sXMLFilename); +} + diff --git a/linden/indra/newview/llmimetypes.h b/linden/indra/newview/llmimetypes.h index 7a50c29..b217ce7 100644 --- a/linden/indra/newview/llmimetypes.h +++ b/linden/indra/newview/llmimetypes.h @@ -72,6 +72,12 @@ public: static bool findAllowLooping(const std::string& mime_type); // accessor for flag to enable/disable media looping checkbox + static bool isTypeHandled(const std::string& mime_type); + // determines if the specific mime type is handled by the media system + + static void reload(void*); + // re-loads the MIME types file from the file path last passed into parseMIMETypes + public: struct LLMIMEInfo { diff --git a/linden/indra/newview/lloverlaybar.cpp b/linden/indra/newview/lloverlaybar.cpp index 6191a01..db4422d 100644 --- a/linden/indra/newview/lloverlaybar.cpp +++ b/linden/indra/newview/lloverlaybar.cpp @@ -38,7 +38,7 @@ #include "lloverlaybar.h" #include "aoremotectrl.h" -#include "audioengine.h" +#include "llaudioengine.h" #include "llrender.h" #include "llagent.h" #include "llbutton.h" @@ -63,7 +63,7 @@ #include "llvoiceclient.h" #include "llvoavatar.h" #include "llvoiceremotectrl.h" -#include "llwebbrowserctrl.h" +#include "llmediactrl.h" #include "llwindlightremotectrl.h" #include "llselectmgr.h" @@ -75,13 +75,14 @@ LLOverlayBar *gOverlayBar = NULL; extern S32 MENU_BAR_HEIGHT; - +//awfixme +/* class LLTitleObserver : public LLMediaObserver { public: void init(std::string url); - /*virtual*/ void onMediaTitleChange(const EventType& event_in); + *//*virtual*//* void onMediaTitleChange(const EventType& event_in); private: LLMediaBase* mMediaSource; }; @@ -120,7 +121,7 @@ void LLTitleObserver::onMediaTitleChange(const EventType& event_in) chat.mText = playing_msg; LLFloaterChat::addChat(chat, FALSE, FALSE); } - +*/ // // Functions @@ -445,11 +446,11 @@ void LLOverlayBar::toggleMediaPlay(void*) } - if (LLViewerMedia::isMediaPaused()) + if (LLViewerParcelMedia::getStatus() == LLViewerMediaImpl::MEDIA_PAUSED) { LLViewerParcelMedia::start(); } - else if(LLViewerMedia::isMediaPlaying()) + else if(LLViewerParcelMedia::getStatus() == LLViewerMediaImpl::MEDIA_PLAYING) { LLViewerParcelMedia::pause(); } @@ -490,7 +491,7 @@ void LLOverlayBar::toggleMusicPlay(void*) // if ( gAudiop->isInternetStreamPlaying() == 0 ) { gAudiop->startInternetStream(parcel->getMusicURL()); - sTitleObserver.init(parcel->getMusicURL()); +//awfixme sTitleObserver.init(parcel->getMusicURL()); } } } diff --git a/linden/indra/newview/llpanelaudioprefs.cpp b/linden/indra/newview/llpanelaudioprefs.cpp index 2bb3ab4..d4c8e9f 100644 --- a/linden/indra/newview/llpanelaudioprefs.cpp +++ b/linden/indra/newview/llpanelaudioprefs.cpp @@ -42,7 +42,7 @@ #include "llfontgl.h" // project includes -#include "audioengine.h" +#include "llaudioengine.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" @@ -105,7 +105,6 @@ void LLPanelAudioPrefs::refreshValues() mPreviousMusicVolume = gSavedSettings.getF32("AudioLevelMusic"); mPreviousMediaVolume = gSavedSettings.getF32("AudioLevelMedia"); mPreviousDoppler = gSavedSettings.getF32("AudioLevelDoppler"); - mPreviousDistance = gSavedSettings.getF32("AudioLevelDistance"); mPreviousRolloff = gSavedSettings.getF32("AudioLevelRolloff"); mPreviousMoneyThreshold = gSavedSettings.getF32("UISndMoneyChangeThreshold"); @@ -134,7 +133,6 @@ void LLPanelAudioPrefs::cancel() gSavedSettings.setF32("AudioLevelMusic", mPreviousMusicVolume); gSavedSettings.setF32("AudioLevelMedia", mPreviousMediaVolume); gSavedSettings.setF32("AudioLevelDoppler", mPreviousDoppler ); - gSavedSettings.setF32("AudioLevelDistance", mPreviousDistance ); gSavedSettings.setF32("AudioLevelRolloff", mPreviousRolloff ); gSavedSettings.setF32("UISndMoneyChangeThreshold", mPreviousMoneyThreshold ); diff --git a/linden/indra/newview/llpanelavatar.cpp b/linden/indra/newview/llpanelavatar.cpp index 33f4cd6..288dbcd 100644 --- a/linden/indra/newview/llpanelavatar.cpp +++ b/linden/indra/newview/llpanelavatar.cpp @@ -64,6 +64,7 @@ #include "llmutelist.h" #include "llpanelclassified.h" #include "llpanelpick.h" +#include "llpluginclassmedia.h" #include "llscrolllistctrl.h" #include "llstatusbar.h" #include "lltabcontainer.h" @@ -410,14 +411,12 @@ BOOL LLPanelAvatarWeb::postBuild(void) childSetControlName("auto_load","AutoLoadWebProfiles"); - mWebBrowser = getChild<LLWebBrowserCtrl>("profile_html"); + mWebBrowser = getChild<LLMediaCtrl>("profile_html"); + mWebBrowser->addObserver(this); // links open in internally mWebBrowser->setOpenInExternalBrowser( false ); - // observe browser events - mWebBrowser->addObserver( this ); - return TRUE; } @@ -476,18 +475,22 @@ LLPanelAvatarWeb::LLPanelAvatarWeb(const std::string& name, const LLRect& rect, LLPanelAvatarWeb::~LLPanelAvatarWeb() { - // stop observing browser events - if ( mWebBrowser ) +} + +void LLPanelAvatarWeb::refresh() +{ + if (mNavigateTo != "") { - mWebBrowser->remObserver( this ); - }; + llinfos << "Loading " << mNavigateTo << llendl; + mWebBrowser->navigateTo( mNavigateTo ); + mNavigateTo = ""; + } } + void LLPanelAvatarWeb::enableControls(BOOL self) { childSetEnabled("url_edit",self); - childSetVisible("status_text",!self && !mHome.empty()); - childSetText("status_text", LLStringUtil::null); } void LLPanelAvatarWeb::setWebURL(std::string url) @@ -511,11 +514,8 @@ void LLPanelAvatarWeb::setWebURL(std::string url) else { childSetVisible("profile_html",false); + childSetVisible("status_text", false); } - - BOOL own_avatar = (getPanelAvatar()->getAvatarID() == gAgent.getID() ); - childSetVisible("status_text",!own_avatar && !mHome.empty()); - } // static @@ -538,13 +538,15 @@ void LLPanelAvatarWeb::load(std::string url) { bool have_url = (!url.empty()); + + childSetVisible("profile_html", have_url); + childSetVisible("status_text", have_url); + childSetText("status_text", LLStringUtil::null); + if (have_url) { - llinfos << "Loading " << url << llendl; - mWebBrowser->navigateTo( url ); + mNavigateTo = url; } - - childSetVisible("profile_html", have_url); } //static @@ -586,14 +588,22 @@ void LLPanelAvatarWeb::onCommitLoad(LLUICtrl* ctrl, void* data) } } -void LLPanelAvatarWeb::onStatusTextChange( const EventType& eventIn ) -{ - childSetText("status_text", eventIn.getStringValue() ); -} - -void LLPanelAvatarWeb::onLocationChange( const EventType& eventIn ) +void LLPanelAvatarWeb::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) { - childSetText("url_edit", eventIn.getStringValue() ); + switch(event) + { + case MEDIA_EVENT_STATUS_TEXT_CHANGED: + childSetText("status_text", self->getStatusText() ); + break; + + case MEDIA_EVENT_LOCATION_CHANGED: + childSetText("url_edit", self->getLocation() ); + break; + + default: + // Having a default case makes the compiler happy. + break; + } } diff --git a/linden/indra/newview/llpanelavatar.h b/linden/indra/newview/llpanelavatar.h index 72a47f5..b687cd8 100644 --- a/linden/indra/newview/llpanelavatar.h +++ b/linden/indra/newview/llpanelavatar.h @@ -36,7 +36,7 @@ #include "llpanel.h" #include "v3dmath.h" #include "lluuid.h" -#include "llwebbrowserctrl.h" +#include "llmediactrl.h" class LLButton; class LLCheckBoxCtrl; @@ -55,7 +55,7 @@ class LLViewerImage; class LLViewerObject; class LLMessageSystem; class LLIconCtrl; -class LLWebBrowserCtrl; +class LLMediaCtrl; enum EOnlineStatus { @@ -137,13 +137,15 @@ private: // WARNING! The order of the inheritance here matters!! Do not change. - KLW class LLPanelAvatarWeb : public LLPanelAvatarTab - , public LLWebBrowserCtrlObserver + , public LLViewerMediaObserver { public: LLPanelAvatarWeb(const std::string& name, const LLRect& rect, LLPanelAvatar* panel_avatar); /*virtual*/ ~LLPanelAvatarWeb(); /*virtual*/ BOOL postBuild(void); + /*virtual*/ void refresh(); + void enableControls(BOOL own_avatar); void setWebURL(std::string url); @@ -154,13 +156,13 @@ public: static void onCommitURL(LLUICtrl* ctrl, void* data); static void onClickWebProfileHelp(void *); - // browser observer impls - virtual void onStatusTextChange( const EventType& eventIn ); - virtual void onLocationChange( const EventType& eventIn ); + // inherited from LLViewerMediaObserver + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); private: std::string mHome; - LLWebBrowserCtrl* mWebBrowser; + std::string mNavigateTo; + LLMediaCtrl* mWebBrowser; }; diff --git a/linden/indra/newview/llpanelclassified.cpp b/linden/indra/newview/llpanelclassified.cpp index 36fc86d..2250012 100644 --- a/linden/indra/newview/llpanelclassified.cpp +++ b/linden/indra/newview/llpanelclassified.cpp @@ -142,7 +142,7 @@ public: const bool from_search = true; LLPanelClassified::sendClassifiedClickMessage(classified_id, "teleport", from_search); // Invoke teleport - LLWebBrowserCtrl* web = NULL; + LLMediaCtrl* web = NULL; const bool trusted_browser = true; return LLURLDispatcher::dispatch(url, web, trusted_browser); } diff --git a/linden/indra/newview/llpaneldebug.cpp b/linden/indra/newview/llpaneldebug.cpp index c804fce..745daf5 100644 --- a/linden/indra/newview/llpaneldebug.cpp +++ b/linden/indra/newview/llpaneldebug.cpp @@ -42,7 +42,7 @@ #include "llfontgl.h" // project includes -#include "audioengine.h" +#include "llaudioengine.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcolorswatch.h" diff --git a/linden/indra/newview/llpaneldirfind.cpp b/linden/indra/newview/llpaneldirfind.cpp index 609f5cc..14c4a90 100644 --- a/linden/indra/newview/llpaneldirfind.cpp +++ b/linden/indra/newview/llpaneldirfind.cpp @@ -50,6 +50,7 @@ #include "llviewercontrol.h" #include "llmenucommands.h" #include "llmenugl.h" +#include "llpluginclassmedia.h" #include "lltextbox.h" #include "lluiconstants.h" #include "llviewerimagelist.h" @@ -143,9 +144,11 @@ BOOL LLPanelDirFind::postBuild() } - mWebBrowser = getChild<LLWebBrowserCtrl>(mBrowserName); + mWebBrowser = getChild<LLMediaCtrl>(mBrowserName); if (mWebBrowser) { + mWebBrowser->addObserver(this); + // new pages appear in same window as the results page now mWebBrowser->setOpenInInternalBrowser( false ); mWebBrowser->setOpenInExternalBrowser( false ); @@ -156,9 +159,6 @@ BOOL LLPanelDirFind::postBuild() // redirect 404 pages from S3 somewhere else mWebBrowser->set404RedirectUrl( getString("redirect_404_url") ); - // Track updates for progress display. - mWebBrowser->addObserver(this); - navigateToDefaultPage(); } @@ -167,8 +167,6 @@ BOOL LLPanelDirFind::postBuild() LLPanelDirFind::~LLPanelDirFind() { - if (mWebBrowser) - mWebBrowser->remObserver(this); } // virtual @@ -485,19 +483,27 @@ void LLPanelDirFind::onClickSearch(void* data) LLFloaterDirectory::sNewSearchCount++; } -void LLPanelDirFind::onNavigateBegin( const EventType& eventIn ) -{ - childSetText("status_text", getString("loading_text")); -} - -void LLPanelDirFind::onNavigateComplete( const EventType& eventIn ) +void LLPanelDirFind::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) { - childSetText("status_text", getString("done_text")); -} - -void LLPanelDirFind::onLocationChange( const EventType& eventIn ) -{ - llinfos << eventIn.getStringValue() << llendl; + switch(event) + { + case MEDIA_EVENT_NAVIGATE_BEGIN: + childSetText("status_text", getString("loading_text")); + break; + + case MEDIA_EVENT_NAVIGATE_COMPLETE: + childSetText("status_text", getString("done_text")); + break; + + case MEDIA_EVENT_LOCATION_CHANGED: + // Debugging info to console + llinfos << self->getLocation() << llendl; + break; + + default: + // Having a default case makes the compiler happy. + break; + } } //--------------------------------------------------------------------------- diff --git a/linden/indra/newview/llpaneldirfind.h b/linden/indra/newview/llpaneldirfind.h index 1a97f4b..d3dda6e 100644 --- a/linden/indra/newview/llpaneldirfind.h +++ b/linden/indra/newview/llpaneldirfind.h @@ -34,19 +34,18 @@ #define LL_LLPANELDIRFIND_H #include "llpaneldirbrowser.h" -#include "llwebbrowserctrl.h" +#include "llmediactrl.h" class LLUICtrl; class LLLineEditor; class LLPanelDirFindAll; class LLFloaterDirectory; -class LLWebBrowserCtrlObserver; // This class in an abstract base class for all new style search widgets. It contains a pointer to a web browser control // class LLPanelDirFind : public LLPanelDirBrowser, - public LLWebBrowserCtrlObserver + public LLViewerMediaObserver { public: LLPanelDirFind(const std::string& name, LLFloaterDirectory* floater, const std::string& browser_name); @@ -73,15 +72,11 @@ private: static void onCommitSearch(LLUICtrl*, void* data); static void onClickHelp( void* data ); - /*virtual*/ void onNavigateBegin( const EventType& eventIn ); - /*virtual*/ void onNavigateComplete( const EventType& eventIn ); - - // Used to update progress indicator - /*virtual*/ void onLocationChange( const EventType& eventIn ); - // Debugging info to console + // inherited from LLViewerMediaObserver + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); protected: - LLWebBrowserCtrl* mWebBrowser; + LLMediaCtrl* mWebBrowser; std::string mBrowserName; }; diff --git a/linden/indra/newview/llpaneldirgroups.cpp b/linden/indra/newview/llpaneldirgroups.cpp index 1aa2e86..4119514 100644 --- a/linden/indra/newview/llpaneldirgroups.cpp +++ b/linden/indra/newview/llpaneldirgroups.cpp @@ -41,6 +41,7 @@ #include "llqueryflags.h" #include "llviewercontrol.h" #include "llviewerwindow.h" +#include "llmediactrl.h" LLPanelDirGroups::LLPanelDirGroups(const std::string& name, LLFloaterDirectory* floater) : LLPanelDirBrowser(name, floater) diff --git a/linden/indra/newview/llpanelface.cpp b/linden/indra/newview/llpanelface.cpp index 68e603e..b9a40da 100644 --- a/linden/indra/newview/llpanelface.cpp +++ b/linden/indra/newview/llpanelface.cpp @@ -66,6 +66,7 @@ #include "llviewerstats.h" #include "llviewerwindow.h" #include "lluictrlfactory.h" +#include "llpluginclassmedia.h" // // Methods @@ -77,7 +78,6 @@ BOOL LLPanelFace::postBuild() LLTextureCtrl* mTextureCtrl; LLColorSwatchCtrl* mColorSwatch; - LLTextBox* mLabelTexGen; LLComboBox* mComboTexGen; LLCheckBoxCtrl *mCheckFullbright; @@ -85,7 +85,6 @@ BOOL LLPanelFace::postBuild() LLTextBox* mLabelColorTransp; LLSpinCtrl* mCtrlColorTransp; // transparency = 1 - alpha - LLTextBox* mLabelGlow; LLSpinCtrl* mCtrlGlow; setMouseOpaque(FALSE); @@ -156,7 +155,7 @@ BOOL LLPanelFace::postBuild() mCheckFullbright->setCommitCallback(LLPanelFace::onCommitFullbright); mCheckFullbright->setCallbackUserData( this ); } - mLabelTexGen = getChild<LLTextBox>("tex gen"); + mComboTexGen = getChild<LLComboBox>("combobox texgen"); if(mComboTexGen) { @@ -165,7 +164,6 @@ BOOL LLPanelFace::postBuild() mComboTexGen->setCallbackUserData( this ); } - mLabelGlow = getChild<LLTextBox>("glow label"); mCtrlGlow = getChild<LLSpinCtrl>("glow"); if(mCtrlGlow) { @@ -507,11 +505,6 @@ void LLPanelFace::getState() childSetEnabled("button align",FALSE); //mBtnAutoFix->setEnabled ( FALSE ); - if(LLViewerMedia::hasMedia()) - { - childSetEnabled("textbox autofix",editable); - childSetEnabled("button align",editable); - } //if ( LLMediaEngine::getInstance()->getMediaRenderer () ) // if ( LLMediaEngine::getInstance()->getMediaRenderer ()->isLoaded () ) // { @@ -568,7 +561,15 @@ void LLPanelFace::getState() } } } + + if(LLViewerMedia::textureHasMedia(id)) + { + childSetEnabled("textbox autofix",editable); + childSetEnabled("button align",editable); + } + } + LLAggregatePermissions texture_perms; if(texture_ctrl) @@ -1117,14 +1118,18 @@ struct LLPanelFaceSetMediaFunctor : public LLSelectedTEFunctor { virtual bool apply(LLViewerObject* object, S32 te) { + // TODO: the media impl pointer should actually be stored by the texture + viewer_media_t pMediaImpl = LLViewerMedia::getMediaImplFromTextureID(object->getTE ( te )->getID()); // only do this if it's a media texture - if ( object->getTE ( te )->getID() == LLViewerMedia::getMediaTextureID() ) + if ( pMediaImpl.notNull()) { - S32 media_width, media_height; - S32 texture_width, texture_height; - if ( LLViewerMedia::getMediaSize( &media_width, &media_height ) - && LLViewerMedia::getTextureSize( &texture_width, &texture_height ) ) + LLPluginClassMedia *media = pMediaImpl->getMediaPlugin(); + if(media) { + S32 media_width = media->getWidth(); + S32 media_height = media->getHeight(); + S32 texture_width = media->getTextureWidth(); + S32 texture_height = media->getTextureHeight(); F32 scale_s = (F32)media_width / (F32)texture_width; F32 scale_t = (F32)media_height / (F32)texture_height; diff --git a/linden/indra/newview/llpanellandaudio.cpp b/linden/indra/newview/llpanellandaudio.cpp new file mode 100644 index 0000000..0247009 --- /dev/null +++ b/linden/indra/newview/llpanellandaudio.cpp @@ -0,0 +1,195 @@ +/** + * @file llpanellandaudio.cpp + * @brief Allows configuration of "media" for a land parcel, + * for example movies, web pages, and audio. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanellandaudio.h" + +// viewer includes +#include "llmimetypes.h" +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" +#include "lluictrlfactory.h" + +// library includes +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llfloaterurlentry.h" +#include "llfocusmgr.h" +#include "lllineeditor.h" +#include "llparcel.h" +#include "lltextbox.h" +#include "llradiogroup.h" +#include "llspinctrl.h" +#include "llsdutil.h" +#include "lltexturectrl.h" +#include "roles_constants.h" +#include "llscrolllistctrl.h" + +// Values for the parcel voice settings radio group +enum +{ + kRadioVoiceChatEstate = 0, + kRadioVoiceChatPrivate = 1, + kRadioVoiceChatDisable = 2 +}; + +//--------------------------------------------------------------------------- +// LLPanelLandAudio +//--------------------------------------------------------------------------- + +LLPanelLandAudio::LLPanelLandAudio(LLParcelSelectionHandle& parcel) +: LLPanel(std::string("land_media_panel")), mParcel(parcel) +{ +} + + +// virtual +LLPanelLandAudio::~LLPanelLandAudio() +{ +} + + +BOOL LLPanelLandAudio::postBuild() +{ + mCheckSoundLocal = getChild<LLCheckBoxCtrl>("check_sound_local"); + childSetCommitCallback("check_sound_local", onCommitAny, this); + + mRadioVoiceChat = getChild<LLRadioGroup>("parcel_voice_channel"); + childSetCommitCallback("parcel_voice_channel", onCommitAny, this); + + mMusicURLEdit = getChild<LLLineEditor>("music_url"); + childSetCommitCallback("music_url", onCommitAny, this); + + mMusicUrlCheck = getChild<LLCheckBoxCtrl>("hide_music_url"); + childSetCommitCallback("hide_music_url", onCommitAny, this); + + return TRUE; +} + + +// public +void LLPanelLandAudio::refresh() +{ + LLParcel *parcel = mParcel->getParcel(); + + if (!parcel) + { + clearCtrls(); + } + else + { + // something selected, hooray! + + // Display options + BOOL can_change_media = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_CHANGE_MEDIA); + + mMusicURLEdit->setText(parcel->getMusicURL()); + mMusicURLEdit->setEnabled( can_change_media ); + + mMusicUrlCheck->set( parcel->getObscureMusic() ); + mMusicUrlCheck->setEnabled( can_change_media ); + + mCheckSoundLocal->set( parcel->getSoundLocal() ); + mCheckSoundLocal->setEnabled( can_change_media ); + + if(parcel->getParcelFlagAllowVoice()) + { + if(parcel->getParcelFlagUseEstateVoiceChannel()) + mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatEstate); + else + mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatPrivate); + } + else + { + mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatDisable); + } + + LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + mRadioVoiceChat->setEnabled( region && region->isVoiceEnabled() && can_change_media ); + } +} +// static +void LLPanelLandAudio::onCommitAny(LLUICtrl*, void *userdata) +{ + LLPanelLandAudio *self = (LLPanelLandAudio *)userdata; + + LLParcel* parcel = self->mParcel->getParcel(); + if (!parcel) + { + return; + } + + // Extract data from UI + BOOL sound_local = self->mCheckSoundLocal->get(); + int voice_setting = self->mRadioVoiceChat->getSelectedIndex(); + std::string music_url = self->mMusicURLEdit->getText(); + U8 obscure_music = self->mMusicUrlCheck->get(); + + + BOOL voice_enabled; + BOOL voice_estate_chan; + + switch(voice_setting) + { + default: + case kRadioVoiceChatEstate: + voice_enabled = TRUE; + voice_estate_chan = TRUE; + break; + case kRadioVoiceChatPrivate: + voice_enabled = TRUE; + voice_estate_chan = FALSE; + break; + case kRadioVoiceChatDisable: + voice_enabled = FALSE; + voice_estate_chan = FALSE; + break; + } + + // Remove leading/trailing whitespace (common when copying/pasting) + LLStringUtil::trim(music_url); + + // Push data into current parcel + parcel->setParcelFlag(PF_ALLOW_VOICE_CHAT, voice_enabled); + parcel->setParcelFlag(PF_USE_ESTATE_VOICE_CHAN, voice_estate_chan); + parcel->setParcelFlag(PF_SOUND_LOCAL, sound_local); + parcel->setMusicURL(music_url); + parcel->setObscureMusic(obscure_music); + + // Send current parcel data upstream to server + LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); + + // Might have changed properties, so let's redraw! + self->refresh(); +} diff --git a/linden/indra/newview/llpanellandaudio.h b/linden/indra/newview/llpanellandaudio.h new file mode 100644 index 0000000..3d5d633 --- /dev/null +++ b/linden/indra/newview/llpanellandaudio.h @@ -0,0 +1,63 @@ +/** + * @file llpanellandaudio.h + * @brief Allows configuration of "audio" for a land parcel. + * + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LLPANELLANDAUDIO_H +#define LLPANELLANDAUDIO_H + +#include "lllineeditor.h" +#include "llpanel.h" +#include "llparcelselection.h" +#include "lluifwd.h" // widget pointer types + +class LLPanelLandAudio + : public LLPanel +{ +public: + LLPanelLandAudio(LLSafeHandle<LLParcelSelection>& parcelp); + /*virtual*/ ~LLPanelLandAudio(); + /*virtual*/ BOOL postBuild(); + void refresh(); + +private: + static void onCommitAny(LLUICtrl* ctrl, void *userdata); + +private: + LLCheckBoxCtrl* mCheckSoundLocal; + LLRadioGroup* mRadioVoiceChat; + LLLineEditor* mMusicURLEdit; + LLCheckBoxCtrl* mMusicUrlCheck; + + LLSafeHandle<LLParcelSelection>& mParcel; +}; + +#endif diff --git a/linden/indra/newview/llpanellandmedia.cpp b/linden/indra/newview/llpanellandmedia.cpp index bebd69e..a8e7c4a 100644 --- a/linden/indra/newview/llpanellandmedia.cpp +++ b/linden/indra/newview/llpanellandmedia.cpp @@ -39,6 +39,8 @@ #include "llmimetypes.h" #include "llviewerparcelmgr.h" #include "llviewerregion.h" +#include "llviewermedia.h" +#include "llviewerparcelmedia.h" #include "lluictrlfactory.h" // library includes @@ -54,6 +56,7 @@ #include "llsdutil.h" #include "lltexturectrl.h" #include "roles_constants.h" +#include "llscrolllistctrl.h" #include "hippoGridManager.h" @@ -62,15 +65,8 @@ //--------------------------------------------------------------------------- LLPanelLandMedia::LLPanelLandMedia(LLParcelSelectionHandle& parcel) -: LLPanel(std::string("land_media_panel")), - +: LLPanel(), mParcel(parcel), - mCheckSoundLocal(NULL), - mSoundHelpButton(NULL), - mCheckEnableVoiceChat(NULL), - mCheckEnableVoiceChatIsEstateDisabled(NULL), - mCheckEnableVoiceChatParcel(NULL), - mMusicURLEdit(NULL), mMediaURLEdit(NULL), mMediaDescEdit(NULL), mMediaTypeCombo(NULL), @@ -81,8 +77,7 @@ LLPanelLandMedia::LLPanelLandMedia(LLParcelSelectionHandle& parcel) mMediaTextureCtrl(NULL), mMediaAutoScaleCheck(NULL), mMediaLoopCheck(NULL), - mMediaUrlCheck(NULL), - mMusicUrlCheck(NULL) + mMediaUrlCheck(NULL) { } @@ -90,34 +85,10 @@ LLPanelLandMedia::LLPanelLandMedia(LLParcelSelectionHandle& parcel) // virtual LLPanelLandMedia::~LLPanelLandMedia() { - // close LLFloaterURLEntry? -} - - -// static -void LLPanelLandMedia::onClickSoundHelp(void*) -{ - LLNotifications::instance().add("ClickSoundHelpLand"); } - BOOL LLPanelLandMedia::postBuild() { - mCheckSoundLocal = getChild<LLCheckBoxCtrl>("check sound local"); - childSetCommitCallback("check sound local", onCommitAny, this); - - mSoundHelpButton = getChild<LLButton>("?"); - mSoundHelpButton->setClickedCallback(onClickSoundHelp, this); - - mCheckEnableVoiceChat = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel"); - childSetCommitCallback("parcel_enable_voice_channel", onCommitAny, this); - mCheckEnableVoiceChatIsEstateDisabled = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel_is_estate_disabled"); - childSetCommitCallback("parcel_enable_voice_channel_is_estate_disabled", onCommitAny, this); - mCheckEnableVoiceChatParcel = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel_parcel"); - childSetCommitCallback("parcel_enable_voice_channel_parcel", onCommitAny, this); - - mMusicURLEdit = getChild<LLLineEditor>("music_url"); - childSetCommitCallback("music_url", onCommitAny, this); mMediaTextureCtrl = getChild<LLTextureCtrl>("media texture"); mMediaTextureCtrl->setCommitCallback( onCommitAny ); @@ -130,16 +101,13 @@ BOOL LLPanelLandMedia::postBuild() childSetCommitCallback("media_auto_scale", onCommitAny, this); mMediaLoopCheck = getChild<LLCheckBoxCtrl>("media_loop"); - childSetCommitCallback("media_loop", onCommitAny, this); + childSetCommitCallback("media_loop", onCommitAny, this ); mMediaUrlCheck = getChild<LLCheckBoxCtrl>("hide_media_url"); - childSetCommitCallback("hide_media_url", onCommitAny, this); - - mMusicUrlCheck = getChild<LLCheckBoxCtrl>("hide_music_url"); - childSetCommitCallback("hide_music_url", onCommitAny, this); + childSetCommitCallback("hide_media_url", onCommitAny, this ); mMediaURLEdit = getChild<LLLineEditor>("media_url"); - childSetCommitCallback("media_url", onCommitAny, this); + childSetCommitCallback("media_url", onCommitAny, this ); mMediaDescEdit = getChild<LLLineEditor>("url_description"); childSetCommitCallback("url_description", onCommitAny, this); @@ -148,15 +116,41 @@ BOOL LLPanelLandMedia::postBuild() childSetCommitCallback("media type", onCommitType, this); populateMIMECombo(); + mMediaResetCtrl = getChild<LLSpinCtrl>("media_reset_time"); + childSetCommitCallback("media_reset_time", onCommitAny, this); + mMediaResetCtrlLabel = getChild<LLTextBox>("media_reset"); + mMediaWidthCtrl = getChild<LLSpinCtrl>("media_size_width"); childSetCommitCallback("media_size_width", onCommitAny, this); mMediaHeightCtrl = getChild<LLSpinCtrl>("media_size_height"); childSetCommitCallback("media_size_height", onCommitAny, this); mMediaSizeCtrlLabel = getChild<LLTextBox>("media_size"); + mMediaNavigateAllowCheck = getChild<LLCheckBoxCtrl>("check navigate allow"); + childSetCommitCallback("check navigate allow", onCommitAny, this); + mMediaURLFilterCheck = getChild<LLCheckBoxCtrl>("check navigate filter"); + childSetCommitCallback("check navigate filter", onCommitAny, this); + mSetURLButton = getChild<LLButton>("set_media_url"); childSetAction("set_media_url", onSetBtn, this); + mResetURLButton = getChild<LLButton>("reset_media_url"); + childSetAction("reset_media_url", onResetBtn, this); + + mURLFilterList = getChild<LLScrollListCtrl>("filter_list"); + + mMediaURLFilterDomainEdit = getChild<LLLineEditor>("navigate_filter_domain"); + + mMediaURLFilterAddButton = getChild<LLButton>("add_navigate_filter"); + childSetAction("add_navigate_filter", onClickAddURLFilter, this); + + mMediaURLFilterRemoveButton = getChild<LLButton>("remove_navigate_filter"); + childSetAction("remove_navigate_filter", onClickRemoveURLFilter, this); + + mRadioNavigateControl = getChild<LLRadioGroup>("radio_navigate_allow"); + childSetCommitCallback("radio_navigate_allow", onCommitAny, this); + + return TRUE; } @@ -177,8 +171,8 @@ void LLPanelLandMedia::refresh() // Display options BOOL can_change_media = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_CHANGE_MEDIA); - mCheckSoundLocal->set( parcel->getSoundLocal() ); - mCheckSoundLocal->setEnabled( can_change_media ); +//imprudence fixme mCheckSoundLocal->set( parcel->getSoundLocal() ); +//imprudence fixme mCheckSoundLocal->setEnabled( can_change_media ); LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); if (!region) @@ -194,42 +188,43 @@ void LLPanelLandMedia::refresh() { if (region && region->isVoiceEnabled()) // estate-wide voice-disable overrides all { - mCheckEnableVoiceChatIsEstateDisabled->setVisible(false); +//imprudence fixme mCheckEnableVoiceChatIsEstateDisabled->setVisible(false); - mCheckEnableVoiceChat->setVisible(true); - mCheckEnableVoiceChat->setEnabled( can_change_media ); - mCheckEnableVoiceChat->set(allow_voice); +//imprudence fixme mCheckEnableVoiceChat->setVisible(true); +//imprudence fixme mCheckEnableVoiceChat->setEnabled( can_change_media ); +//imprudence fixme mCheckEnableVoiceChat->set(allow_voice); - mCheckEnableVoiceChatParcel->setEnabled( can_change_media && allow_voice ); +//imprudence fixme mCheckEnableVoiceChatParcel->setEnabled( can_change_media && allow_voice ); } else // disabled at region level { - mCheckEnableVoiceChatIsEstateDisabled->setVisible(true); // always disabled - mCheckEnableVoiceChat->setVisible(false); - mCheckEnableVoiceChat->setEnabled(false); - mCheckEnableVoiceChat->set(false); +//imprudence fixme mCheckEnableVoiceChatIsEstateDisabled->setVisible(true); // always disabled +//imprudence fixme mCheckEnableVoiceChat->setVisible(false); +//imprudence fixme mCheckEnableVoiceChat->setEnabled(false); +//imprudence fixme mCheckEnableVoiceChat->set(false); - mCheckEnableVoiceChatParcel->setEnabled(false); +//imprudence fixme mCheckEnableVoiceChatParcel->setEnabled(false); } } else { - mCheckEnableVoiceChatIsEstateDisabled->setVisible(true); +//imprudence fixme mCheckEnableVoiceChatIsEstateDisabled->setVisible(true); - mCheckEnableVoiceChat->setVisible(true); - mCheckEnableVoiceChat->setEnabled( can_change_media ); - mCheckEnableVoiceChat->set(allow_voice); +//imprudence fixme mCheckEnableVoiceChat->setVisible(true); +//imprudence fixme mCheckEnableVoiceChat->setEnabled( can_change_media ); +//imprudence fixme mCheckEnableVoiceChat->set(allow_voice); - mCheckEnableVoiceChatParcel->setEnabled( can_change_media && allow_voice ); +//imprudence fixme mCheckEnableVoiceChatParcel->setEnabled( can_change_media && allow_voice ); } - mCheckEnableVoiceChatParcel->set(!parcel->getParcelFlagUseEstateVoiceChannel()); +//imprudence fixme mCheckEnableVoiceChatParcel->set(!parcel->getParcelFlagUseEstateVoiceChannel()); + +//imprudence fixme mMusicURLEdit->setText(parcel->getMusicURL()); +//imprudence fixme mMusicURLEdit->setEnabled( can_change_media ); + - mMusicURLEdit->setText(parcel->getMusicURL()); - mMusicURLEdit->setEnabled( can_change_media ); - mMediaURLEdit->setText(parcel->getMediaURL()); - mMediaURLEdit->setEnabled( FALSE ); + childSetText("current_url", parcel->getMediaCurrentURL()); mMediaDescEdit->setText(parcel->getMediaDesc()); mMediaDescEdit->setEnabled( can_change_media ); @@ -246,15 +241,11 @@ void LLPanelLandMedia::refresh() mMediaUrlCheck->set( parcel->getObscureMedia() ); mMediaUrlCheck->setEnabled( can_change_media ); - mMusicUrlCheck->set( parcel->getObscureMusic() ); - mMusicUrlCheck->setEnabled( can_change_media ); - // don't display urls if you're not able to change it // much requested change in forums so people can't 'steal' urls // NOTE: bug#2009 means this is still vunerable - however, bug // should be closed since this bug opens up major security issues elsewhere. bool obscure_media = ! can_change_media && parcel->getObscureMedia(); - bool obscure_music = ! can_change_media && parcel->getObscureMusic(); // Special code to disable asterixes for html type if(mime_type == "text/html") @@ -264,7 +255,6 @@ void LLPanelLandMedia::refresh() mMediaUrlCheck->setEnabled( false ); } - mMusicURLEdit->setDrawAsterixes( obscure_music ); mMediaURLEdit->setDrawAsterixes( obscure_media ); mMediaAutoScaleCheck->set( parcel->getMediaAutoScale () ); @@ -278,6 +268,10 @@ void LLPanelLandMedia::refresh() else mMediaLoopCheck->set( false ); mMediaLoopCheck->setEnabled ( can_change_media && allow_looping ); + + mMediaResetCtrl->set( parcel->getMediaURLTimeout() ); + mMediaResetCtrl->setEnabled( can_change_media ); + mMediaResetCtrlLabel->setEnabled( can_change_media ); // disallow media size change for mime types that don't allow it bool allow_resize = LLMIMETypes::findAllowResize( mime_type ); @@ -301,28 +295,45 @@ void LLPanelLandMedia::refresh() mMediaTextureCtrl->setEnabled( can_change_media ); mSetURLButton->setEnabled( can_change_media ); + mResetURLButton->setEnabled( can_change_media ); - #if 0 - // there is a media url and a media texture selected - if ( ( ! ( std::string ( parcel->getMediaURL() ).empty () ) ) && ( ! ( parcel->getMediaID ().isNull () ) ) ) - { - // turn on transport controls if allowed for this parcel - mMediaStopButton->setEnabled ( editable ); - mMediaStartButton->setEnabled ( editable ); - } - else - { - // no media url or no media texture - mMediaStopButton->setEnabled ( FALSE ); - mMediaStartButton->setEnabled ( FALSE ); - }; - #endif + mMediaURLFilterCheck->set( parcel->getMediaURLFilterEnable() ); + mMediaURLFilterCheck->setEnabled( can_change_media ); LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mURLEntryFloater.get(); if (floater_url_entry) { floater_url_entry->updateFromLandMediaPanel(); } + + // This radial control is really just an inverse mapping to the boolean allow_navigate value. + // It is set as a radial merely for user readability. + mRadioNavigateControl->setSelectedIndex(! parcel->getMediaAllowNavigate()); + mRadioNavigateControl->setEnabled( can_change_media ); + + mMediaURLFilterDomainEdit->setEnabled( can_change_media ); + mMediaURLFilterAddButton->setEnabled( can_change_media ); + mMediaURLFilterRemoveButton->setEnabled( can_change_media ); + + if (mURLFilterList) + { + mURLFilterList->setEnabled( can_change_media ); + + mURLFilterList->deleteAllItems(); + + LLSD list = parcel->getMediaURLFilterList(); + + for (LLSD::array_iterator i = list.beginArray(); i != list.endArray(); ++i) + { + std::string domain = (*i).asString(); + + LLSD element; + element["id"] = domain; + element["columns"][0]["value"] = domain; + + mURLFilterList->addElement(element); + } + } } } @@ -364,12 +375,19 @@ void LLPanelLandMedia::setMediaType(const std::string& mime_type) void LLPanelLandMedia::setMediaURL(const std::string& media_url) { mMediaURLEdit->setText(media_url); + LLParcel *parcel = mParcel->getParcel(); + if(parcel) + parcel->setMediaCurrentURL(media_url); + // LLViewerMedia::navigateHome(); + + mMediaURLEdit->onCommit(); + // LLViewerParcelMedia::sendMediaNavigateMessage(media_url); + childSetText("current_url", media_url); } - std::string LLPanelLandMedia::getMediaURL() { - return mMediaURLEdit->getText(); + return mMediaURLEdit->getText(); } // static @@ -398,33 +416,26 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata) } // Extract data from UI - BOOL sound_local = self->mCheckSoundLocal->get(); - std::string music_url = self->mMusicURLEdit->getText(); std::string media_url = self->mMediaURLEdit->getText(); std::string media_desc = self->mMediaDescEdit->getText(); std::string mime_type = self->childGetText("mime_type"); U8 media_auto_scale = self->mMediaAutoScaleCheck->get(); U8 media_loop = self->mMediaLoopCheck->get(); U8 obscure_media = self->mMediaUrlCheck->get(); - U8 obscure_music = self->mMusicUrlCheck->get(); + F32 media_reset_time = (F32)self->mMediaResetCtrl->get(); S32 media_width = (S32)self->mMediaWidthCtrl->get(); S32 media_height = (S32)self->mMediaHeightCtrl->get(); LLUUID media_id = self->mMediaTextureCtrl->getImageAssetID(); + U8 navigate_allow = ! self->mRadioNavigateControl->getSelectedIndex(); + U8 navigate_filter = self->mMediaURLFilterCheck->get(); - BOOL voice_enabled = self->mCheckEnableVoiceChat->get(); - BOOL voice_estate_chan = ! self->mCheckEnableVoiceChatParcel->get(); self->childSetText("mime_type", mime_type); // Remove leading/trailing whitespace (common when copying/pasting) - LLStringUtil::trim(music_url); LLStringUtil::trim(media_url); // Push data into current parcel - parcel->setParcelFlag(PF_ALLOW_VOICE_CHAT, voice_enabled); - parcel->setParcelFlag(PF_USE_ESTATE_VOICE_CHAN, voice_estate_chan); - parcel->setParcelFlag(PF_SOUND_LOCAL, sound_local); - parcel->setMusicURL(music_url); parcel->setMediaURL(media_url); parcel->setMediaType(mime_type); parcel->setMediaDesc(media_desc); @@ -434,7 +445,10 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata) parcel->setMediaAutoScale ( media_auto_scale ); parcel->setMediaLoop ( media_loop ); parcel->setObscureMedia( obscure_media ); - parcel->setObscureMusic( obscure_music ); + parcel->setMediaURLFilterEnable(navigate_filter); + parcel->setMediaAllowNavigate(navigate_allow); + parcel->setMediaURLTimeout(media_reset_time); + // Send current parcel data upstream to server LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); @@ -453,3 +467,91 @@ void LLPanelLandMedia::onSetBtn(void *userdata) parent_floater->addDependentFloater(self->mURLEntryFloater.get()); } } + +// static +void LLPanelLandMedia::onResetBtn(void *userdata) +{ + LLPanelLandMedia *self = (LLPanelLandMedia *)userdata; + LLParcel* parcel = self->mParcel->getParcel(); + // LLViewerMedia::navigateHome(); + self->refresh(); + self->childSetText("current_url", parcel->getMediaURL()); + // LLViewerParcelMedia::sendMediaNavigateMessage(parcel->getMediaURL()); + +} +// static +void LLPanelLandMedia::onClickAddURLFilter(void *userdata) +{ + LLPanelLandMedia *panelp = (LLPanelLandMedia *)userdata; + LLParcel* parcel = panelp->mParcel->getParcel(); + + LLSD list = parcel->getMediaURLFilterList(); + + std::string domain = panelp->mMediaURLFilterDomainEdit->getText(); + LLStringUtil::trim(domain); + + BOOL add = TRUE; + if (domain == "") + { + add = FALSE; + } + + // check for dupes + for(S32 i = 0; i < list.size(); i++) + { + if (list[i].asString() == domain) + { + add = FALSE; + break; + } + } + + if (add) + { + list.append(domain); + parcel->setMediaURLFilterList(list); + + LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); + + panelp->mMediaURLFilterDomainEdit->setText(std::string("")); + + panelp->refresh(); + } + +} + +// static +void LLPanelLandMedia::onClickRemoveURLFilter(void *data) +{ + LLPanelLandMedia* panelp = (LLPanelLandMedia*)data; + if (panelp && panelp->mURLFilterList) + { + LLParcel* parcel = panelp->mParcel->getParcel(); + if (parcel) + { + LLSD list = parcel->getMediaURLFilterList(); + + std::vector<LLScrollListItem*> domains = panelp->mURLFilterList->getAllSelected(); + for (std::vector<LLScrollListItem*>::iterator iter = domains.begin(); iter != domains.end(); iter++) + { + LLScrollListItem* item = *iter; + const std::string domain = item->getValue().asString(); + + for(S32 i = 0; i < list.size(); i++) + { + if (list[i].asString() == domain) + { + list.erase(i); + break; + } + } + } + + parcel->setMediaURLFilterList(list); + LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); + + panelp->refresh(); + } + } + +} diff --git a/linden/indra/newview/llpanellandmedia.h b/linden/indra/newview/llpanellandmedia.h index 6a53dd4..c883d98 100644 --- a/linden/indra/newview/llpanellandmedia.h +++ b/linden/indra/newview/llpanellandmedia.h @@ -56,29 +56,36 @@ private: static void onCommitAny(LLUICtrl* ctrl, void *userdata); static void onCommitType(LLUICtrl* ctrl, void *userdata); static void onSetBtn(void* userdata); - static void onClickSoundHelp(void*); - + static void onResetBtn(void* userdata); + static void onClickAddURLFilter(void *userdata); + static void onClickRemoveURLFilter(void *userdata); + private: - LLCheckBoxCtrl* mCheckSoundLocal; - LLButton* mSoundHelpButton; - LLCheckBoxCtrl* mCheckEnableVoiceChat; - LLCheckBoxCtrl* mCheckEnableVoiceChatIsEstateDisabled; - LLCheckBoxCtrl* mCheckEnableVoiceChatParcel; - LLLineEditor* mMusicURLEdit; LLLineEditor* mMediaURLEdit; LLLineEditor* mMediaDescEdit; LLComboBox* mMediaTypeCombo; LLButton* mSetURLButton; + LLButton* mResetURLButton; + LLSpinCtrl* mMediaResetCtrl; LLSpinCtrl* mMediaHeightCtrl; LLSpinCtrl* mMediaWidthCtrl; + LLTextBox* mMediaResetCtrlLabel; LLTextBox* mMediaSizeCtrlLabel; LLTextureCtrl* mMediaTextureCtrl; LLCheckBoxCtrl* mMediaAutoScaleCheck; LLCheckBoxCtrl* mMediaLoopCheck; LLCheckBoxCtrl* mMediaUrlCheck; - LLCheckBoxCtrl* mMusicUrlCheck; LLHandle<LLFloater> mURLEntryFloater; + LLCheckBoxCtrl* mMediaNavigateAllowCheck; + LLCheckBoxCtrl* mMediaURLFilterCheck; + LLLineEditor* mMediaURLFilterDomainEdit; + LLButton* mMediaURLFilterAddButton; + LLButton* mMediaURLFilterRemoveButton; + LLScrollListCtrl* mURLFilterList; + LLRadioGroup* mRadioNavigateControl; + + LLSafeHandle<LLParcelSelection>& mParcel; }; diff --git a/linden/indra/newview/llpanellogin.cpp b/linden/indra/newview/llpanellogin.cpp index 23b7785..a8b7106 100644 --- a/linden/indra/newview/llpanellogin.cpp +++ b/linden/indra/newview/llpanellogin.cpp @@ -73,12 +73,10 @@ #include "lluictrlfactory.h" #include "llhttpclient.h" #include "llweb.h" -#include "llwebbrowserctrl.h" #include "viewerversion.h" +#include "llmediactrl.h" -#include "llfloaterhtml.h" - -#include "llfloaterhtmlhelp.h" +#include "llfloatermediabrowser.h" #include "llfloatertos.h" #include "llglheaders.h" @@ -101,7 +99,7 @@ class LLLoginRefreshHandler : public LLCommandHandler public: // don't allow from external browsers LLLoginRefreshHandler() : LLCommandHandler("login_refresh", true) { } - bool handle(const LLSD& tokens, const LLSD& query_map, LLWebBrowserCtrl* web) + bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP) { @@ -291,16 +289,15 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, #endif // get the web browser control - LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("login_html"); + LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html"); + web_browser->addObserver(this); + // Need to handle login secondlife:///app/ URLs web_browser->setTrusted( true ); - // observe browser events - web_browser->addObserver( this ); - // don't make it a tab stop until SL-27594 is fixed web_browser->setTabStop(FALSE); - web_browser->navigateToLocalPage( "loading", "loading.html" ); + // web_browser->navigateToLocalPage( "loading", "loading.html" ); // make links open in external browser web_browser->setOpenInExternalBrowser( true ); @@ -335,7 +332,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, void LLPanelLogin::setSiteIsAlive( bool alive ) { - LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("login_html"); + LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html"); // if the contents of the site was retrieved if ( alive ) { @@ -398,6 +395,11 @@ LLPanelLogin::~LLPanelLogin() //// We know we're done with the image, so be rid of it. //gImageList.deleteImage( mLogoImage ); + + if ( gFocusMgr.getDefaultKeyboardFocus() == this ) + { + gFocusMgr.setDefaultKeyboardFocus(NULL); + } } // virtual @@ -779,7 +781,7 @@ void LLPanelLogin::setAlwaysRefresh(bool refresh) { if (LLStartUp::getStartupState() >= STATE_LOGIN_CLEANUP) return; - LLWebBrowserCtrl* web_browser = sInstance->getChild<LLWebBrowserCtrl>("login_html"); + LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html"); if (web_browser) { @@ -952,25 +954,28 @@ void LLPanelLogin::loadLoginPage() #endif #endif - LLWebBrowserCtrl* web_browser = sInstance->getChild<LLWebBrowserCtrl>("login_html"); + LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html"); // navigate to the "real" page - web_browser->navigateTo( oStr.str() ); + web_browser->navigateTo( oStr.str(), "text/html" ); } -void LLPanelLogin::onNavigateComplete( const EventType& eventIn ) +void LLPanelLogin::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent event) { - LLWebBrowserCtrl* web_browser = sInstance->getChild<LLWebBrowserCtrl>("login_html"); - if (web_browser) + if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) { - // *HACK HACK HACK HACK! - /* Stuff a Tab key into the browser now so that the first field will - ** get the focus! The embedded javascript on the page that properly - ** sets the initial focus in a real web browser is not working inside - ** the viewer, so this is an UGLY HACK WORKAROUND for now. - */ - // Commented out as it's not reliable - //web_browser->handleKey(KEY_TAB, MASK_NONE, false); + LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html"); + if (web_browser) + { + // *HACK HACK HACK HACK! + /* Stuff a Tab key into the browser now so that the first field will + ** get the focus! The embedded javascript on the page that properly + ** sets the initial focus in a real web browser is not working inside + ** the viewer, so this is an UGLY HACK WORKAROUND for now. + */ + // Commented out as it's not reliable + //web_browser->handleKey(KEY_TAB, MASK_NONE, false); + } } } diff --git a/linden/indra/newview/llpanellogin.h b/linden/indra/newview/llpanellogin.h index 15c2d28..c99fa30 100644 --- a/linden/indra/newview/llpanellogin.h +++ b/linden/indra/newview/llpanellogin.h @@ -35,14 +35,14 @@ #include "llpanel.h" #include "llmemory.h" // LLPointer<> -#include "llwebbrowserctrl.h" // LLWebBrowserCtrlObserver +#include "llmediactrl.h" // LLMediaCtrlObserver class LLUIImage; class LLPanelLogin: public LLPanel, - public LLWebBrowserCtrlObserver + public LLViewerMediaObserver { LOG_CLASS(LLPanelLogin); public: @@ -84,6 +84,9 @@ public: static void setAlwaysRefresh(bool refresh); static void mungePassword(LLUICtrl* caller, void* user_data); + // inherited from LLViewerMediaObserver + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + private: static void onClickConnect(void*); static void onClickGrid(void*); @@ -91,7 +94,6 @@ private: static bool newAccountAlertCallback(const LLSD& notification, const LLSD& response); static void onClickQuit(void*); static void onClickVersion(void*); - virtual void onNavigateComplete( const EventType& eventIn ); static void onClickForgotPassword(void*); static void onPassKey(LLLineEditor* caller, void* user_data); static void onSelectServer(LLUICtrl*, void*); diff --git a/linden/indra/newview/llpanelmediahud.cpp b/linden/indra/newview/llpanelmediahud.cpp new file mode 100644 index 0000000..39c4b63 --- /dev/null +++ b/linden/indra/newview/llpanelmediahud.cpp @@ -0,0 +1,667 @@ +/** + * @file llpanelmsgs.cpp + * @brief Message popup preferences panel + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +//LLPanelMediaHUD +#include "llagent.h" +#include "llparcel.h" +#include "llpanel.h" +#include "llselectmgr.h" +#include "llrender.h" +#include "lldrawable.h" +#include "llviewerwindow.h" +#include "lluictrlfactory.h" +#include "llbutton.h" +#include "llface.h" +#include "llhudview.h" +#include "lliconctrl.h" +#include "lltoolpie.h" +#include "llviewercamera.h" +#include "llpanelmediahud.h" +#include "llpluginclassmedia.h" +#include "llviewercontrol.h" +#include "llviewerparcelmgr.h" +#include "llviewermedia.h" +#include "llviewermediafocus.h" +#include "llvovolume.h" +#include "llweb.h" + +glh::matrix4f glh_get_current_modelview(); +glh::matrix4f glh_get_current_projection(); + +const F32 ZOOM_NEAR_PADDING = 1.0f; +const F32 ZOOM_MEDIUM_PADDING = 1.2f; +const F32 ZOOM_FAR_PADDING = 1.5f; + +// +// LLPanelMediaHUD +// + +LLPanelMediaHUD::LLPanelMediaHUD(viewer_media_t media_impl) + : mMediaImpl(media_impl) +{ + mMediaFocus = false; + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_hud.xml"); + mMouseMoveTimer.reset(); + mFadeTimer.stop(); + mCurrentZoom = ZOOM_NONE; + mScrollState = SCROLL_NONE; + + mPanelHandle.bind(this); +} +LLPanelMediaHUD::~LLPanelMediaHUD() +{ + mMediaImpl = NULL; +} + +BOOL LLPanelMediaHUD::postBuild() +{ + LLButton* close_btn = getChild<LLButton>("close"); + close_btn->setClickedCallback(onClickClose, this); + + LLButton* back_btn = getChild<LLButton>("back"); + back_btn->setClickedCallback(onClickBack, this); + + LLButton* fwd_btn = getChild<LLButton>("fwd"); + fwd_btn->setClickedCallback(onClickForward, this); + + LLButton* home_btn = getChild<LLButton>("home"); + home_btn->setClickedCallback(onClickHome, this); + + LLButton* stop_btn = getChild<LLButton>("stop"); + stop_btn->setClickedCallback(onClickStop, this); + + LLButton* media_stop_btn = getChild<LLButton>("media_stop"); + media_stop_btn->setClickedCallback(onClickStop, this); + + LLButton* reload_btn = getChild<LLButton>("reload"); + reload_btn->setClickedCallback(onClickReload, this); + + LLButton* play_btn = getChild<LLButton>("play"); + play_btn->setClickedCallback(onClickPlay, this); + + LLButton* pause_btn = getChild<LLButton>("pause"); + pause_btn->setClickedCallback(onClickPause, this); + + LLButton* open_btn = getChild<LLButton>("new_window"); + open_btn->setClickedCallback(onClickOpen, this); + + LLButton* zoom_btn = getChild<LLButton>("zoom_frame"); + zoom_btn->setClickedCallback(onClickZoom, this); + + LLButton* open_btn_h = getChild<LLButton>("new_window_hover"); + open_btn_h->setClickedCallback(onClickOpen, this); + + LLButton* zoom_btn_h = getChild<LLButton>("zoom_frame_hover"); + zoom_btn_h->setClickedCallback(onClickZoom, this); + + LLButton* scroll_up_btn = getChild<LLButton>("scrollup"); + scroll_up_btn->setClickedCallback(onScrollUp, this); + scroll_up_btn->setHeldDownCallback(onScrollUpHeld); + scroll_up_btn->setMouseUpCallback(onScrollStop); + LLButton* scroll_left_btn = getChild<LLButton>("scrollleft"); + scroll_left_btn->setClickedCallback(onScrollLeft, this); + scroll_left_btn->setHeldDownCallback(onScrollLeftHeld); + scroll_left_btn->setMouseUpCallback(onScrollStop); + LLButton* scroll_right_btn = getChild<LLButton>("scrollright"); + scroll_right_btn->setClickedCallback(onScrollRight, this); + scroll_right_btn->setHeldDownCallback(onScrollLeftHeld); + scroll_right_btn->setMouseUpCallback(onScrollStop); + LLButton* scroll_down_btn = getChild<LLButton>("scrolldown"); + scroll_down_btn->setClickedCallback(onScrollDown, this); + scroll_down_btn->setHeldDownCallback(onScrollDownHeld); + scroll_down_btn->setMouseUpCallback(onScrollStop); + + mMouseInactiveTime = gSavedSettings.getF32("MediaControlTimeout"); + mControlFadeTime = gSavedSettings.getF32("MediaControlFadeTime"); + + mCurrentZoom = ZOOM_NONE; + // clicks on HUD buttons do not remove keyboard focus from media + setIsChrome(TRUE); + return TRUE; +} + +void LLPanelMediaHUD::updateShape() +{ + const S32 MIN_HUD_WIDTH=200; + const S32 MIN_HUD_HEIGHT=120; + + LLPluginClassMedia* media_plugin = NULL; + if(mMediaImpl.notNull() && mMediaImpl->hasMedia()) + { + media_plugin = mMediaImpl->getMediaPlugin(); + } + + // Early out for no media plugin + if(media_plugin == NULL) + { + setVisible(FALSE); + return; + } + + LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + + bool can_navigate = parcel->getMediaAllowNavigate(); + + // LLObjectSelectionHandle selection = LLViewerMediaFocus::getInstance()->getSelection(); + + LLSelectNode* nodep = mMediaFocus ? LLSelectMgr::getInstance()->getSelection()->getFirstNode() : LLSelectMgr::getInstance()->getHoverNode(); + if(! nodep) + { + return; + } + setVisible(FALSE); + LLViewerObject* objectp = nodep->getObject(); + + if (objectp) + { + + // Set the state of the buttons + LLButton* back_btn = getChild<LLButton>("back"); + LLButton* fwd_btn = getChild<LLButton>("fwd"); + LLButton* reload_btn = getChild<LLButton>("reload"); + LLButton* play_btn = getChild<LLButton>("play"); + LLButton* pause_btn = getChild<LLButton>("pause"); + LLButton* stop_btn = getChild<LLButton>("stop"); + LLButton* media_stop_btn = getChild<LLButton>("media_stop"); + LLButton* home_btn = getChild<LLButton>("home"); + LLButton* close_btn = getChild<LLButton>("close"); + LLButton* open_btn = getChild<LLButton>("new_window"); + LLPanel* media_focused_panel = getChild<LLPanel>("media_focused_controls"); + LLPanel* media_hover_panel = getChild<LLPanel>("media_hover_controls"); + back_btn->setVisible(true); + fwd_btn->setVisible(true); + reload_btn->setVisible(true); + stop_btn->setVisible(false); + home_btn->setVisible(true); + close_btn->setVisible(true); + open_btn->setVisible(true); + + + if(mMediaFocus) + { + back_btn->setEnabled(mMediaImpl->canNavigateBack() && can_navigate); + fwd_btn->setEnabled(mMediaImpl->canNavigateForward() && can_navigate); + stop_btn->setEnabled(can_navigate); + home_btn->setEnabled(can_navigate); + LLPluginClassMediaOwner::EMediaStatus result = media_plugin->getStatus(); + + if(media_plugin->pluginSupportsMediaTime()) + { + reload_btn->setEnabled(FALSE); + reload_btn->setVisible(FALSE); + media_stop_btn->setVisible(TRUE); + home_btn->setVisible(FALSE); + back_btn->setEnabled(TRUE); + fwd_btn->setEnabled(TRUE); + switch(result) + { + case LLPluginClassMediaOwner::MEDIA_PLAYING: + play_btn->setEnabled(FALSE); + play_btn->setVisible(FALSE); + pause_btn->setEnabled(TRUE); + pause_btn->setVisible(TRUE); + media_stop_btn->setEnabled(TRUE); + break; + case LLPluginClassMediaOwner::MEDIA_PAUSED: + default: + pause_btn->setEnabled(FALSE); + pause_btn->setVisible(FALSE); + play_btn->setEnabled(TRUE); + play_btn->setVisible(TRUE); + media_stop_btn->setEnabled(FALSE); + break; + } + } + else + { + play_btn->setVisible(FALSE); + pause_btn->setVisible(FALSE); + media_stop_btn->setVisible(FALSE); + if(result == LLPluginClassMediaOwner::MEDIA_LOADING) + { + reload_btn->setEnabled(FALSE); + reload_btn->setVisible(FALSE); + stop_btn->setEnabled(TRUE); + stop_btn->setVisible(TRUE); + } + else + { + reload_btn->setEnabled(TRUE); + reload_btn->setVisible(TRUE); + stop_btn->setEnabled(FALSE); + stop_btn->setVisible(FALSE); + } + } + } + media_focused_panel->setVisible(mMediaFocus); + media_hover_panel->setVisible(!mMediaFocus); + + if(media_plugin == NULL) + // Handle Scrolling + switch (mScrollState) + { + case SCROLL_UP: + media_plugin->scrollEvent(0, -1, MASK_NONE); + break; + case SCROLL_DOWN: + media_plugin->scrollEvent(0, 1, MASK_NONE); + break; + case SCROLL_LEFT: + mMediaImpl->handleKeyHere(KEY_LEFT, MASK_NONE); + break; + case SCROLL_RIGHT: + mMediaImpl->handleKeyHere(KEY_RIGHT, MASK_NONE); + break; + case SCROLL_NONE: + default: + break; + } + LLBBox screen_bbox; + setVisible(TRUE); + glh::matrix4f mat = glh_get_current_projection()*glh_get_current_modelview(); + std::vector<LLVector3>::iterator vert_it; + std::vector<LLVector3>::iterator vert_end; + std::vector<LLVector3> vect_face; + + LLVolume* volume = objectp->getVolume(); + + if (volume) + { + const LLVolumeFace& vf = volume->getVolumeFace(nodep->getLastSelectedTE()); + + const LLVector3* ext = vf.mExtents; + + LLVector3 center = (ext[0]+ext[1])*0.5f; + LLVector3 size = (ext[1]-ext[0])*0.5f; + LLVector3 vert[] = + { + center + size.scaledVec(LLVector3(1,1,1)), + center + size.scaledVec(LLVector3(-1,1,1)), + center + size.scaledVec(LLVector3(1,-1,1)), + center + size.scaledVec(LLVector3(-1,-1,1)), + center + size.scaledVec(LLVector3(1,1,-1)), + center + size.scaledVec(LLVector3(-1,1,-1)), + center + size.scaledVec(LLVector3(1,-1,-1)), + center + size.scaledVec(LLVector3(-1,-1,-1)), + }; + + LLVOVolume* vo = (LLVOVolume*) objectp; + + for (U32 i = 0; i < 8; i++) + { + vect_face.push_back(vo->volumePositionToAgent(vert[i])); + } + } + vert_it = vect_face.begin(); + vert_end = vect_face.end(); + + LLVector3 min = LLVector3(1,1,1); + LLVector3 max = LLVector3(-1,-1,-1); + for(; vert_it != vert_end; ++vert_it) + { + // project silhouette vertices into screen space + glh::vec3f screen_vert = glh::vec3f(vert_it->mV); + mat.mult_matrix_vec(screen_vert); + + // add to screenspace bounding box + update_min_max(min, max, LLVector3(screen_vert.v)); + } + + LLCoordGL screen_min; + screen_min.mX = llround((F32)gViewerWindow->getWindowWidth() * (min.mV[VX] + 1.f) * 0.5f); + screen_min.mY = llround((F32)gViewerWindow->getWindowHeight() * (min.mV[VY] + 1.f) * 0.5f); + + LLCoordGL screen_max; + screen_max.mX = llround((F32)gViewerWindow->getWindowWidth() * (max.mV[VX] + 1.f) * 0.5f); + screen_max.mY = llround((F32)gViewerWindow->getWindowHeight() * (max.mV[VY] + 1.f) * 0.5f); + + // grow panel so that screenspace bounding box fits inside "media_region" element of HUD + LLRect media_hud_rect; + getParent()->screenRectToLocal(LLRect(screen_min.mX, screen_max.mY, screen_max.mX, screen_min.mY), &media_hud_rect); + LLView* media_region = getChild<LLView>("media_region"); + media_hud_rect.mLeft -= media_region->getRect().mLeft; + media_hud_rect.mBottom -= media_region->getRect().mBottom; + media_hud_rect.mTop += getRect().getHeight() - media_region->getRect().mTop; + media_hud_rect.mRight += getRect().getWidth() - media_region->getRect().mRight; + + + LLRect old_hud_rect = media_hud_rect; + // keep all parts of HUD on-screen + media_hud_rect.intersectWith(getParent()->getLocalRect()); + + // If we had to clip the rect, don't display the border + childSetVisible("bg_image", false); + + // clamp to minimum size, keeping centered + media_hud_rect.setCenterAndSize(media_hud_rect.getCenterX(), media_hud_rect.getCenterY(), + llmax(MIN_HUD_WIDTH, media_hud_rect.getWidth()), llmax(MIN_HUD_HEIGHT, media_hud_rect.getHeight())); + + userSetShape(media_hud_rect); + + // Test mouse position to see if the cursor is stationary + LLCoordWindow cursor_pos_window; + getWindow()->getCursorPosition(&cursor_pos_window); + + // If last pos is not equal to current pos, the mouse has moved + // We need to reset the timer, and make sure the panel is visible + if(cursor_pos_window.mX != mLastCursorPos.mX || + cursor_pos_window.mY != mLastCursorPos.mY || + mScrollState != SCROLL_NONE) + { + mMouseMoveTimer.start(); + mLastCursorPos = cursor_pos_window; + } + + // Mouse has been stationary, but not for long enough to fade the UI + if(mMouseMoveTimer.getElapsedTimeF32() < mMouseInactiveTime) + { + // If we have started fading, reset the alpha values + if(mFadeTimer.getStarted()) + { + F32 alpha = 1.0f; + setAlpha(alpha); + mFadeTimer.stop(); + } + } + // If we need to start fading the UI (and we have not already started) + else if(! mFadeTimer.getStarted()) + { + mFadeTimer.reset(); + mFadeTimer.start(); + } + } +} +/*virtual*/ +void LLPanelMediaHUD::draw() +{ + if(mFadeTimer.getStarted()) + { + if(mFadeTimer.getElapsedTimeF32() >= mControlFadeTime) + { + setVisible(FALSE); + } + else + { + F32 time = mFadeTimer.getElapsedTimeF32(); + F32 alpha = llmax(lerp(1.0, 0.0, time / mControlFadeTime), 0.0f); + setAlpha(alpha); + } + } + LLPanel::draw(); +} +void LLPanelMediaHUD::setAlpha(F32 alpha) +{ + LLViewQuery query; + + LLView* query_view = mMediaFocus ? getChildView("media_focused_controls") : getChildView("media_hover_controls"); + child_list_t children = query(query_view); + for (child_list_iter_t child_iter = children.begin(); + child_iter != children.end(); ++child_iter) + { + LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(*child_iter); + if (ctrl) + ctrl->setAlpha(alpha); + } + + LLPanel::setAlpha(alpha); +} +BOOL LLPanelMediaHUD::handleScrollWheel(S32 x, S32 y, S32 clicks) +{ + return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks); +} +bool LLPanelMediaHUD::isMouseOver() +{ + if( ! getVisible() ) + { + return false; + } + LLRect screen_rect; + LLCoordWindow cursor_pos_window; + getWindow()->getCursorPosition(&cursor_pos_window); + + localRectToScreen(getLocalRect(), &screen_rect); + // screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y); + + if(screen_rect.pointInRect(cursor_pos_window.mX, cursor_pos_window.mY)) + { + return true; + } + return false; +} + +//static +void LLPanelMediaHUD::onClickClose(void* user_data) +{ + LLViewerMediaFocus::getInstance()->setFocusFace(FALSE, NULL, 0, NULL); + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + if(this_panel->mCurrentZoom != ZOOM_NONE) + { + // gAgent.setFocusOnAvatar(TRUE, ANIMATE); + this_panel->mCurrentZoom = ZOOM_NONE; + } + this_panel->setVisible(FALSE); + +} + +//static +void LLPanelMediaHUD::onClickBack(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + if(this_panel->mMediaImpl->getMediaPlugin()->pluginSupportsMediaTime()) + { + this_panel->mMediaImpl->getMediaPlugin()->start(-2.0); + } + else + { + this_panel->mMediaImpl->getMediaPlugin()->browse_back(); + } + + } +} +//static +void LLPanelMediaHUD::onClickForward(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + if(this_panel->mMediaImpl->getMediaPlugin()->pluginSupportsMediaTime()) + { + this_panel->mMediaImpl->getMediaPlugin()->start(2.0); + } + else + { + this_panel->mMediaImpl->getMediaPlugin()->browse_forward(); + } + } +} +//static +void LLPanelMediaHUD::onClickHome(void* user_data) +{ + //LLViewerMedia::navigateHome(); + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + if(this_panel->mMediaImpl.notNull()) + { + this_panel->mMediaImpl->navigateHome(); + } +} +//static +void LLPanelMediaHUD::onClickOpen(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + if(this_panel->mMediaImpl.notNull()) + { + LLWeb::loadURL(this_panel->mMediaImpl->getMediaURL()); + } +} +//static +void LLPanelMediaHUD::onClickReload(void* user_data) +{ + //LLViewerMedia::navigateHome(); + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + if(objectp && this_panel->mMediaImpl.notNull()) + { + this_panel->mMediaImpl->navigateTo(objectp->getMediaURL()); + } +} +//static +void LLPanelMediaHUD::onClickPlay(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + this_panel->mMediaImpl->getMediaPlugin()->start(); + } +} +//static +void LLPanelMediaHUD::onClickPause(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + this_panel->mMediaImpl->getMediaPlugin()->pause(); + } +} +//static +void LLPanelMediaHUD::onClickStop(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + if (this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + if(this_panel->mMediaImpl->getMediaPlugin()->pluginSupportsMediaTime()) + { + this_panel->mMediaImpl->getMediaPlugin()->stop(); + } + else + { + this_panel->mMediaImpl->getMediaPlugin()->browse_stop(); + } + } +} +//static +void LLPanelMediaHUD::onClickZoom(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + this_panel->nextZoomLevel(); +} +void LLPanelMediaHUD::nextZoomLevel() +{ + F32 zoom_padding = 0.0f; + S32 last_zoom_level = (S32)mCurrentZoom; + mCurrentZoom = (EZoomLevel)((last_zoom_level + 1) % (S32)ZOOM_END); + + switch (mCurrentZoom) + { + case ZOOM_NONE: + { + gAgent.setFocusOnAvatar(TRUE, ANIMATE); + break; + } + case ZOOM_MEDIUM: + { + zoom_padding = ZOOM_MEDIUM_PADDING; + break; + } + default: + { + gAgent.setFocusOnAvatar(TRUE, ANIMATE); + break; + } + } + + if (zoom_padding > 0.0f) + LLViewerMediaFocus::getInstance()->setCameraZoom(zoom_padding); +} +void LLPanelMediaHUD::onScrollUp(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + if(this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + this_panel->mMediaImpl->getMediaPlugin()->scrollEvent(0, -1, MASK_NONE); + } +} +void LLPanelMediaHUD::onScrollUpHeld(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + this_panel->mScrollState = SCROLL_UP; +} +void LLPanelMediaHUD::onScrollRight(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + if(this_panel->mMediaImpl.notNull()) + { + this_panel->mMediaImpl->handleKeyHere(KEY_RIGHT, MASK_NONE); + } +} +void LLPanelMediaHUD::onScrollRightHeld(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + this_panel->mScrollState = SCROLL_RIGHT; +} + +void LLPanelMediaHUD::onScrollLeft(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + if(this_panel->mMediaImpl.notNull()) + { + this_panel->mMediaImpl->handleKeyHere(KEY_LEFT, MASK_NONE); + } +} +void LLPanelMediaHUD::onScrollLeftHeld(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + this_panel->mScrollState = SCROLL_LEFT; +} + +void LLPanelMediaHUD::onScrollDown(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + if(this_panel->mMediaImpl.notNull() && this_panel->mMediaImpl->hasMedia()) + { + this_panel->mMediaImpl->getMediaPlugin()->scrollEvent(0, 1, MASK_NONE); + } +} +void LLPanelMediaHUD::onScrollDownHeld(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + this_panel->mScrollState = SCROLL_DOWN; +} + +void LLPanelMediaHUD::onScrollStop(void* user_data) +{ + LLPanelMediaHUD* this_panel = static_cast<LLPanelMediaHUD*> (user_data); + this_panel->mScrollState = SCROLL_NONE; +} diff --git a/linden/indra/newview/llpanelmediahud.h b/linden/indra/newview/llpanelmediahud.h new file mode 100644 index 0000000..5f12ebc --- /dev/null +++ b/linden/indra/newview/llpanelmediahud.h @@ -0,0 +1,110 @@ +/** + * @file llpanelmediahud.h + * @brief Media hud panel + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_PANELMEDIAHUD_H +#define LL_PANELMEDIAHUD_H + +#include "llpanel.h" +#include "llviewermedia.h" + +class LLCoordWindow; +class LLViewerMediaImpl; + +class LLPanelMediaHUD : public LLPanel +{ +public: + LLPanelMediaHUD(viewer_media_t media_impl); + virtual ~LLPanelMediaHUD(); + /*virtual*/ BOOL postBuild(); + virtual void draw(); + virtual void setAlpha(F32 alpha); + virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); + void updateShape(); + bool isMouseOver(); + void setMediaFocus(bool b) { mMediaFocus = b; } + void nextZoomLevel(); + void resetZoomLevel() { mCurrentZoom = ZOOM_NONE; } + + LLHandle<LLPanelMediaHUD> getHandle() const { return mPanelHandle; } + void setMediaImpl(viewer_media_t media_impl) { mMediaImpl = media_impl; } + + + enum EZoomLevel + { + ZOOM_NONE = 0, + ZOOM_MEDIUM = 1, + ZOOM_END + }; + enum EScrollDir + { + SCROLL_UP = 0, + SCROLL_DOWN, + SCROLL_LEFT, + SCROLL_RIGHT, + SCROLL_NONE + }; + +private: + static void onClickClose(void* user_data); + static void onClickBack(void* user_data); + static void onClickForward(void* user_data); + static void onClickHome(void* user_data); + static void onClickOpen(void* user_data); + static void onClickReload(void* user_data); + static void onClickPlay(void* user_data); + static void onClickPause(void* user_data); + static void onClickStop(void* user_data); + static void onClickZoom(void* user_data); + static void onScrollUp(void* user_data); + static void onScrollUpHeld(void* user_data); + static void onScrollLeft(void* user_data); + static void onScrollLeftHeld(void* user_data); + static void onScrollRight(void* user_data); + static void onScrollRightHeld(void* user_data); + static void onScrollDown(void* user_data); + static void onScrollDownHeld(void* user_data); + static void onScrollStop(void* user_data); + + bool mMediaFocus; + LLMatrix4 mLastCameraMat; + EZoomLevel mCurrentZoom; + EScrollDir mScrollState; + LLCoordWindow mLastCursorPos; + LLFrameTimer mMouseMoveTimer; + LLFrameTimer mFadeTimer; + F32 mMouseInactiveTime; + F32 mControlFadeTime; + viewer_media_t mMediaImpl; + LLRootHandle<LLPanelMediaHUD> mPanelHandle; +}; + +#endif // LL_PANELMEDIAHUD_H diff --git a/linden/indra/newview/llpanelpermissions.cpp b/linden/indra/newview/llpanelpermissions.cpp index fc05744..6b318e0 100644 --- a/linden/indra/newview/llpanelpermissions.cpp +++ b/linden/indra/newview/llpanelpermissions.cpp @@ -277,7 +277,7 @@ void LLPanelPermissions::refresh() BOOL is_perm_modify = (LLSelectMgr::getInstance()->getSelection()->getFirstRootNode() && LLSelectMgr::getInstance()->selectGetRootsModify()) || LLSelectMgr::getInstance()->selectGetModify(); - const LLView* keyboard_focus_view = gFocusMgr.getKeyboardFocus(); + const LLFocusableElement* keyboard_focus_view = gFocusMgr.getKeyboardFocus(); S32 string_index = 0; std::string MODIFY_INFO_STRINGS[] = { diff --git a/linden/indra/newview/llpanelweb.cpp b/linden/indra/newview/llpanelweb.cpp index 38bb2d7..e2933f0 100644 --- a/linden/indra/newview/llpanelweb.cpp +++ b/linden/indra/newview/llpanelweb.cpp @@ -38,50 +38,23 @@ // project includes #include "llcheckboxctrl.h" #include "hippoGridManager.h" -#include "llmediamanager.h" #include "lluictrlfactory.h" #include "llviewercontrol.h" +#include "llviewermedia.h" #include "llviewerwindow.h" +#include "llpluginclassmedia.h" // helper functions for getting/freeing the web browser media // if creating/destroying these is too slow, we'll need to create // a static member and update all our static callbacks -LLMediaBase *get_web_media() +viewer_media_t get_web_media() { - LLMediaBase *media_source; - LLMediaManager *mgr = LLMediaManager::getInstance(); - - if (!mgr) - { - llwarns << "cannot get media manager" << llendl; - return NULL; - } - media_source = mgr->createSourceFromMimeType("http", "text/html" ); - if ( !media_source ) - { - llwarns << "media source create failed " << llendl; - return NULL; - } + viewer_media_t media_source = LLViewerMedia::newMediaImpl("", LLUUID::null, 0, 0, 0, 0, "text/html"); return media_source; } -void free_web_media(LLMediaBase *media_source) -{ - if (!media_source) - return; - - LLMediaManager *mgr = LLMediaManager::getInstance(); - if (!mgr) - { - llwarns << "cannot get media manager" << llendl; - return; - } - - mgr->destroySource(media_source); -} - LLPanelWeb::LLPanelWeb() { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_web.xml"); @@ -144,17 +117,16 @@ void LLPanelWeb::apply() bool value = childGetValue("use_external_browser").asString() == "external" ? true : false; gSavedSettings.setBOOL("UseExternalBrowser", value); - LLMediaBase *media_source = get_web_media(); - if (media_source) + viewer_media_t media_source = get_web_media(); + if (media_source && media_source->hasMedia()) { - media_source->enableCookies(childGetValue("cookies_enabled")); + media_source->getMediaPlugin()->enable_cookies(childGetValue("cookies_enabled")); bool proxy_enable = childGetValue("web_proxy_enabled"); std::string proxy_address = childGetValue("web_proxy_editor"); int proxy_port = childGetValue("web_proxy_port"); - media_source->enableProxy(proxy_enable, proxy_address, proxy_port); + media_source->getMediaPlugin()->proxy_setup(proxy_enable, proxy_address, proxy_port); } - free_web_media(media_source); } void LLPanelWeb::cancel() @@ -173,10 +145,9 @@ bool LLPanelWeb::callback_clear_browser_cache(const LLSD& notification, const LL S32 option = LLNotification::getSelectedOption(notification, response); if ( option == 0 ) // YES { - LLMediaBase *media_source = get_web_media(); - if (media_source) - media_source->clearCache(); - free_web_media(media_source); + viewer_media_t media_source = get_web_media(); + if (media_source && media_source->hasMedia()) + media_source->getMediaPlugin()->clear_cache(); } return false; } @@ -193,10 +164,9 @@ bool LLPanelWeb::callback_clear_cookies(const LLSD& notification, const LLSD& re S32 option = LLNotification::getSelectedOption(notification, response); if ( option == 0 ) // YES { - LLMediaBase *media_source = get_web_media(); - if (media_source) - media_source->clearCookies(); - free_web_media(media_source); + viewer_media_t media_source = get_web_media(); + if (media_source && media_source->hasMedia()) + media_source->getMediaPlugin()->clear_cookies(); } return false; } @@ -209,10 +179,9 @@ void LLPanelWeb::onCommitCookies(LLUICtrl* ctrl, void* data) if (!self || !check) return; - LLMediaBase *media_source = get_web_media(); - if (media_source) - media_source->enableCookies(check->get()); - free_web_media(media_source); + viewer_media_t media_source = get_web_media(); + if (media_source && media_source->hasMedia()) + media_source->getMediaPlugin()->enable_cookies(check->get()); } // static void LLPanelWeb::onCommitWebProxyEnabled(LLUICtrl* ctrl, void* data) diff --git a/linden/indra/newview/llprefsvoice.cpp b/linden/indra/newview/llprefsvoice.cpp index fe5446b..609d30a 100644 --- a/linden/indra/newview/llprefsvoice.cpp +++ b/linden/indra/newview/llprefsvoice.cpp @@ -153,8 +153,8 @@ void LLPrefsVoice::apply() if (enable_voice && !gSavedSettings.getBOOL("VivoxLicenseAccepted")) { // This window enables voice chat if license is accepted - FloaterVoiceLicense::getInstance()->open(); - FloaterVoiceLicense::getInstance()->center(); +//imprudence fixme FloaterVoiceLicense::getInstance()->open(); +//imprudence fixme FloaterVoiceLicense::getInstance()->center(); } else { diff --git a/linden/indra/newview/llpreviewscript.cpp b/linden/indra/newview/llpreviewscript.cpp index d8c3aa9..737d712 100644 --- a/linden/indra/newview/llpreviewscript.cpp +++ b/linden/indra/newview/llpreviewscript.cpp @@ -81,7 +81,7 @@ #include "llviewertexteditor.h" #include "llviewerwindow.h" #include "lluictrlfactory.h" -#include "llwebbrowserctrl.h" +#include "llmediactrl.h" #include "lluictrlfactory.h" #include "llviewercontrol.h" @@ -360,7 +360,7 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate) // update back and forward buttons LLButton* fwd_button = help_floater->getChild<LLButton>("fwd_btn"); LLButton* back_button = help_floater->getChild<LLButton>("back_btn"); - LLWebBrowserCtrl* browser = help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html"); + LLMediaCtrl* browser = help_floater->getChild<LLMediaCtrl>("lsl_guide_html"); back_button->setEnabled(browser->canNavigateBack()); fwd_button->setEnabled(browser->canNavigateForward()); @@ -419,7 +419,7 @@ void LLScriptEdCore::setHelpPage(const std::string& help_string) LLFloater* help_floater = mLiveHelpHandle.get(); if (!help_floater) return; - LLWebBrowserCtrl* web_browser = help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html"); + LLMediaCtrl* web_browser = help_floater->getChild<LLMediaCtrl>("lsl_guide_html"); if (!web_browser) return; LLComboBox* history_combo = help_floater->getChild<LLComboBox>("history_combo"); @@ -592,7 +592,7 @@ void LLScriptEdCore::onBtnDynamicHelp(void* userdata) live_help_floater->childSetAction("back_btn", onClickBack, userdata); live_help_floater->childSetAction("fwd_btn", onClickForward, userdata); - LLWebBrowserCtrl* browser = live_help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html"); + LLMediaCtrl* browser = live_help_floater->getChild<LLMediaCtrl>("lsl_guide_html"); browser->setAlwaysRefresh(TRUE); LLComboBox* help_combo = live_help_floater->getChild<LLComboBox>("history_combo"); @@ -621,7 +621,7 @@ void LLScriptEdCore::onClickBack(void* userdata) LLFloater* live_help_floater = corep->mLiveHelpHandle.get(); if (live_help_floater) { - LLWebBrowserCtrl* browserp = live_help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html"); + LLMediaCtrl* browserp = live_help_floater->getChild<LLMediaCtrl>("lsl_guide_html"); if (browserp) { browserp->navigateBack(); @@ -636,7 +636,7 @@ void LLScriptEdCore::onClickForward(void* userdata) LLFloater* live_help_floater = corep->mLiveHelpHandle.get(); if (live_help_floater) { - LLWebBrowserCtrl* browserp = live_help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html"); + LLMediaCtrl* browserp = live_help_floater->getChild<LLMediaCtrl>("lsl_guide_html"); if (browserp) { browserp->navigateForward(); @@ -678,7 +678,7 @@ void LLScriptEdCore::onHelpComboCommit(LLUICtrl* ctrl, void* userdata) corep->addHelpItemToHistory(help_string); - LLWebBrowserCtrl* web_browser = live_help_floater->getChild<LLWebBrowserCtrl>("lsl_guide_html"); + LLMediaCtrl* web_browser = live_help_floater->getChild<LLMediaCtrl>("lsl_guide_html"); LLUIString url_string = gSavedSettings.getString("LSLHelpURL"); url_string.setArg("[APP_DIRECTORY]", gDirUtilp->getWorkingDir()); url_string.setArg("[LSL_STRING]", help_string); diff --git a/linden/indra/newview/llpreviewsound.cpp b/linden/indra/newview/llpreviewsound.cpp index 26d8da5..0dd65ab 100644 --- a/linden/indra/newview/llpreviewsound.cpp +++ b/linden/indra/newview/llpreviewsound.cpp @@ -32,7 +32,7 @@ #include "llviewerprecompiledheaders.h" -#include "audioengine.h" +#include "llaudioengine.h" #include "llagent.h" // gAgent #include "llbutton.h" #include "llinventory.h" diff --git a/linden/indra/newview/llselectmgr.cpp b/linden/indra/newview/llselectmgr.cpp index 83abcf4..558d278 100644 --- a/linden/indra/newview/llselectmgr.cpp +++ b/linden/indra/newview/llselectmgr.cpp @@ -59,6 +59,7 @@ #include "llfloaterreporter.h" #include "llfloatertools.h" #include "llframetimer.h" +#include "llfocusmgr.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" #include "llinventorymodel.h" @@ -74,6 +75,8 @@ #include "llviewercamera.h" #include "llviewercontrol.h" #include "llviewerimagelist.h" +#include "llviewermedia.h" +#include "llviewermediafocus.h" #include "llviewermenu.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" @@ -4875,7 +4878,7 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) if (mSelectedObjects->getNumNodes()) { LLUUID inspect_item_id = LLFloaterInspect::getSelectedUUID(); - + LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getSelectedUUID(); for (S32 pass = 0; pass < 2; pass++) { for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); @@ -4889,7 +4892,11 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) { continue; } - if(objectp->getID() == inspect_item_id) + if (objectp->getID() == focus_item_id) + { + node->renderOneSilhouette(gFocusMgr.getFocusColor()); + } + else if(objectp->getID() == inspect_item_id) { node->renderOneSilhouette(sHighlightInspectColor); } diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index 4fd4daa..87d48c8 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp @@ -40,14 +40,15 @@ # include <sys/stat.h> // mkdir() #endif -#include "audioengine.h" +#include "llviewermedia_streamingaudio.h" +#include "llaudioengine.h" #ifdef LL_FMOD -# include "audioengine_fmod.h" +# include "llaudioengine_fmod.h" #endif #ifdef LL_OPENAL -#include "audioengine_openal.h" +#include "llaudioengine_openal.h" #endif #include "llares.h" @@ -100,6 +101,7 @@ #include "llfloatergesture.h" #include "llfloaterhud.h" #include "llfloaterland.h" +#include "llfloaterteleporthistory.h" #include "llfloatertopobjects.h" #include "llfloatertos.h" #include "llfloaterworldmap.h" @@ -191,12 +193,6 @@ #include "jcfloater_animation_list.h" #include "jcfloaterareasearch.h" -#include "llfloaterteleporthistory.h" - -#if LL_LIBXUL_ENABLED -#include "llmozlib.h" -#endif // LL_LIBXUL_ENABLED - #if LL_WINDOWS #include "llwindebug.h" #include "lldxhardware.h" @@ -675,6 +671,16 @@ bool idle_startup() delete gAudiop; gAudiop = NULL; } + + if (gAudiop) + { + // if the audio engine hasn't set up its own preferred handler for streaming audio then set up the generic streaming audio implementation which uses media plugins + if (NULL == gAudiop->getStreamingAudioImpl()) + { + LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL; + gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins()); + } + } } } @@ -760,7 +766,7 @@ bool idle_startup() std::string msg = LLTrans::getString("LoginInitializingBrowser"); set_startup_status(0.03f, msg.c_str(), gAgent.mMOTD.c_str()); display_startup(); - LLViewerMedia::initBrowser(); + // LLViewerMedia::initBrowser(); LLStartUp::setStartupState( STATE_LOGIN_SHOW ); return FALSE; @@ -2234,6 +2240,8 @@ bool idle_startup() LLStringUtil::truncate(gWindowTitle, 255); gViewerWindow->getWindow()->setWindowTitle(gWindowTitle); } + // Inform simulator of our language preference + LLAgentLanguage::update(); // unpack thin inventory LLUserAuth::options_t options; @@ -2553,9 +2561,6 @@ bool idle_startup() // JC - 7/20/2002 gViewerWindow->sendShapeToSim(); - // Inform simulator of our language preference - LLAgentLanguage::update(); - // Ignore stipend information for now. Money history is on the web site. // if needed, show the L$ history window @@ -3824,7 +3829,7 @@ void LLStartUp::multimediaInit() set_startup_status(0.42f, msg.c_str(), gAgent.mMOTD.c_str()); display_startup(); - LLViewerMedia::initClass(); + //LLViewerMedia::initClass(); LLViewerParcelMedia::initClass(); } @@ -3833,7 +3838,7 @@ bool LLStartUp::dispatchURL() // ok, if we've gotten this far and have a startup URL if (!sSLURLCommand.empty()) { - LLWebBrowserCtrl* web = NULL; + LLMediaCtrl* web = NULL; const bool trusted_browser = false; LLURLDispatcher::dispatch(sSLURLCommand, web, trusted_browser); } @@ -3851,7 +3856,7 @@ bool LLStartUp::dispatchURL() || (dy*dy > SLOP*SLOP) ) { std::string url = LLURLSimString::getURL(); - LLWebBrowserCtrl* web = NULL; + LLMediaCtrl* web = NULL; const bool trusted_browser = false; LLURLDispatcher::dispatch(url, web, trusted_browser); } diff --git a/linden/indra/newview/llstatusbar.cpp b/linden/indra/newview/llstatusbar.cpp index 366363b..d08d3da 100644 --- a/linden/indra/newview/llstatusbar.cpp +++ b/linden/indra/newview/llstatusbar.cpp @@ -857,7 +857,7 @@ class LLBalanceHandler : public LLCommandHandler public: // Requires "trusted" browser/URL source LLBalanceHandler() : LLCommandHandler("balance", true) { } - bool handle(const LLSD& tokens, const LLSD& query_map, LLWebBrowserCtrl* web) + bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { if (tokens.size() == 1 && tokens[0].asString() == "request") diff --git a/linden/indra/newview/lltoolcomp.cpp b/linden/indra/newview/lltoolcomp.cpp index b6090bc..16e0136 100644 --- a/linden/indra/newview/lltoolcomp.cpp +++ b/linden/indra/newview/lltoolcomp.cpp @@ -766,10 +766,6 @@ void LLToolCompGun::onMouseCaptureLost() return; } mCur->onMouseCaptureLost(); - - // JC - I don't know if this is necessary. Maybe we could lose capture - // if someone ALT-Tab's out when in mouselook. - setCurrentTool( (LLTool*) mGun ); } void LLToolCompGun::handleSelect() diff --git a/linden/indra/newview/lltoolcomp.h b/linden/indra/newview/lltoolcomp.h index b24ba25..81ed0ba 100644 --- a/linden/indra/newview/lltoolcomp.h +++ b/linden/indra/newview/lltoolcomp.h @@ -229,6 +229,7 @@ public: virtual void onMouseCaptureLost(); virtual void handleSelect(); virtual void handleDeselect(); + virtual LLTool* getOverrideTool(MASK mask) { return NULL; } protected: LLToolGun* mGun; diff --git a/linden/indra/newview/lltoolgun.cpp b/linden/indra/newview/lltoolgun.cpp index d21fd49..f7af018 100644 --- a/linden/indra/newview/lltoolgun.cpp +++ b/linden/indra/newview/lltoolgun.cpp @@ -49,7 +49,8 @@ #include "lltoolgrab.h" LLToolGun::LLToolGun( LLToolComposite* composite ) -: LLTool( std::string("gun"), composite ) +: LLTool( std::string("gun"), composite ), + mIsSelected(FALSE) { } @@ -58,6 +59,7 @@ void LLToolGun::handleSelect() gViewerWindow->hideCursor(); gViewerWindow->moveCursorToCenter(); gViewerWindow->mWindow->setMouseClipping(TRUE); + mIsSelected = TRUE; } void LLToolGun::handleDeselect() @@ -65,6 +67,7 @@ void LLToolGun::handleDeselect() gViewerWindow->moveCursorToCenter(); gViewerWindow->showCursor(); gViewerWindow->mWindow->setMouseClipping(FALSE); + mIsSelected = FALSE; } BOOL LLToolGun::handleMouseDown(S32 x, S32 y, MASK mask) @@ -77,7 +80,7 @@ BOOL LLToolGun::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLToolGun::handleHover(S32 x, S32 y, MASK mask) { - if( gAgent.cameraMouselook() ) + if( gAgent.cameraMouselook() && mIsSelected ) { const F32 NOMINAL_MOUSE_SENSITIVITY = 0.0025f; diff --git a/linden/indra/newview/lltoolgun.h b/linden/indra/newview/lltoolgun.h index 4e945d7..4644e68 100644 --- a/linden/indra/newview/lltoolgun.h +++ b/linden/indra/newview/lltoolgun.h @@ -52,6 +52,8 @@ public: virtual LLTool* getOverrideTool(MASK mask) { return NULL; } virtual BOOL clipMouseWhenDown() { return FALSE; } +private: + BOOL mIsSelected; }; #endif diff --git a/linden/indra/newview/lltoolmgr.cpp b/linden/indra/newview/lltoolmgr.cpp index 3a776d1..8204374 100644 --- a/linden/indra/newview/lltoolmgr.cpp +++ b/linden/indra/newview/lltoolmgr.cpp @@ -281,22 +281,20 @@ void LLToolMgr::clearTransientTool() } -// The "gun tool", used for handling mouselook, captures the mouse and -// locks it within the window. When the app loses focus we need to -// release this locking. void LLToolMgr::onAppFocusLost() { - mSavedTool = mBaseTool; - mBaseTool = gToolNull; + if (mSelectedTool) + { + mSelectedTool->handleDeselect(); + } updateToolStatus(); } void LLToolMgr::onAppFocusGained() { - if (mSavedTool) + if (mSelectedTool) { - mBaseTool = mSavedTool; - mSavedTool = NULL; + mSelectedTool->handleSelect(); } updateToolStatus(); } diff --git a/linden/indra/newview/lltoolmorph.cpp b/linden/indra/newview/lltoolmorph.cpp index 75e1964..6e09efa 100644 --- a/linden/indra/newview/lltoolmorph.cpp +++ b/linden/indra/newview/lltoolmorph.cpp @@ -37,7 +37,7 @@ #include "llrender.h" // Library includes -#include "audioengine.h" +#include "llaudioengine.h" #include "llviewercontrol.h" #include "llfontgl.h" #include "sound_ids.h" diff --git a/linden/indra/newview/lltoolpie.cpp b/linden/indra/newview/lltoolpie.cpp index 2b63a24..b121b1a 100644 --- a/linden/indra/newview/lltoolpie.cpp +++ b/linden/indra/newview/lltoolpie.cpp @@ -36,11 +36,11 @@ #include "indra_constants.h" #include "llclickaction.h" -#include "llmediabase.h" // for status codes #include "llparcel.h" #include "llagent.h" #include "llviewercontrol.h" +#include "llfocusmgr.h" #include "llfirstuse.h" #include "llfloateravatarinfo.h" #include "llfloaterland.h" @@ -63,6 +63,7 @@ #include "llviewerparcelmgr.h" #include "llviewerwindow.h" #include "llviewermedia.h" +#include "llviewermediafocus.h" #include "llvoavatar.h" #include "llworld.h" #include "llui.h" @@ -72,13 +73,15 @@ extern void handle_buy(void*); extern BOOL gDebugClicks; +static bool handle_media_click(const LLPickInfo& info); +static bool handle_media_hover(const LLPickInfo& info); static void handle_click_action_play(); static void handle_click_action_open_media(LLPointer<LLViewerObject> objectp); static ECursorType cursor_from_parcel_media(U8 click_action); LLToolPie::LLToolPie() -: LLTool(std::string("Select")), +: LLTool(std::string("Pie")), mPieMouseButtonDown( FALSE ), mGrabMouseButtonDown( FALSE ), mMouseOutsideSlop( FALSE ), @@ -110,6 +113,10 @@ BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask) return FALSE; } +BOOL LLToolPie::handleScrollWheel(S32 x, S32 y, S32 clicks) +{ + return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks); +} // static void LLToolPie::rightMouseCallback(const LLPickInfo& pick_info) { @@ -143,6 +150,7 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) } } + gFocusMgr.setKeyboardFocus(NULL); return LLTool::handleMouseDown(x, y, mask); } @@ -161,9 +169,11 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) parent = object->getRootEdit(); } + BOOL touchable = (object && object->flagHandleTouch()) || (parent && parent->flagHandleTouch()); + // If it's a left-click, and we have a special action, do it. if (useClickAction(always_show, mask, object, parent)) { @@ -195,6 +205,8 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->mIsSitting) && !gSavedSettings.getBOOL("BlockClickSit")) // agent not already sitting { handle_sit_or_stand(); + // put focus in world when sitting on an object + gFocusMgr.setKeyboardFocus(NULL); return TRUE; } // else nothing (fall through to touch) @@ -247,6 +259,14 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) } } + if (!always_show && handle_media_click(mPick)) + { + return FALSE; + } + + // put focus back "in world" + gFocusMgr.setKeyboardFocus(NULL); + // Switch to grab tool if physical or triggerable if (object && !object->isAvatar() && @@ -614,41 +634,46 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) mMouseOutsideSlop = TRUE; } */ + + gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); + LLViewerObject *object = NULL; LLViewerObject *parent = NULL; - if (gHoverView) - { - object = gViewerWindow->getHoverPick().getObject(); - } + object = gViewerWindow->getHoverPick().getObject(); if (object) { parent = object->getRootEdit(); - } - if (object && useClickAction(FALSE, mask, object, parent)) - { - ECursorType cursor = cursor_from_object(object); - gViewerWindow->getWindow()->setCursor(cursor); - lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl; - } - else if ((object && !object->isAvatar() && object->usePhysics()) - || (parent && !parent->isAvatar() && parent->usePhysics())) - { - gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLGRAB); - lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl; - } - else if ( (object && object->flagHandleTouch()) - || (parent && parent->flagHandleTouch())) - { - gViewerWindow->getWindow()->setCursor(UI_CURSOR_HAND); - lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl; + if (object && useClickAction(FALSE, mask, object, parent)) + { + ECursorType cursor = cursor_from_object(object); + gViewerWindow->getWindow()->setCursor(cursor); + } + else if (handle_media_hover(gViewerWindow->getHoverPick())) + { + // cursor set by media object + } + else if ((object && !object->isAvatar() && object->usePhysics()) + || (parent && !parent->isAvatar() && parent->usePhysics())) + { + gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLGRAB); + } + else if ( (object && object->flagHandleTouch()) + || (parent && parent->flagHandleTouch())) + { + gViewerWindow->getWindow()->setCursor(UI_CURSOR_HAND); + } } else { - gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); - lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl; + // We need to clear media hover flag + if (LLViewerMediaFocus::getInstance()->getMouseOverFlag()) + { + LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); + } + } return TRUE; @@ -830,14 +855,14 @@ static void handle_click_action_play() LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); if (!parcel) return; - LLMediaBase::EStatus status = LLViewerParcelMedia::getStatus(); + LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus(); switch(status) { - case LLMediaBase::STATUS_STARTED: + case LLViewerMediaImpl::MEDIA_PLAYING: LLViewerParcelMedia::pause(); break; - case LLMediaBase::STATUS_PAUSED: + case LLViewerMediaImpl::MEDIA_PAUSED: LLViewerParcelMedia::start(); break; @@ -847,6 +872,111 @@ static void handle_click_action_play() } } +static bool handle_media_click(const LLPickInfo& pick) +{ + //FIXME: how do we handle object in different parcel than us? + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + LLPointer<LLViewerObject> objectp = pick.getObject(); + + + if (!parcel || + objectp.isNull() || + pick.mObjectFace < 0 || + pick.mObjectFace >= objectp->getNumTEs()) + { + LLSelectMgr::getInstance()->deselect(); + LLViewerMediaFocus::getInstance()->clearFocus(); + + return false; + } + + + + // HACK: This is directly referencing an impl name. BAD! + // This can be removed when we have a truly generic media browser that only + // builds an impl based on the type of url it is passed. + + // is media playing on this face? + const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); + + viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(tep->getID()); + if (tep + && media_impl.notNull() + && media_impl->hasMedia() + && gSavedSettings.getBOOL("MediaOnAPrimUI")) + { + LLObjectSelectionHandle selection = LLViewerMediaFocus::getInstance()->getSelection(); + if (! selection->contains(pick.getObject(), pick.mObjectFace)) + { + LLViewerMediaFocus::getInstance()->setFocusFace(TRUE, pick.getObject(), pick.mObjectFace, media_impl); + } + else + { + media_impl->mouseDown(pick.mXYCoords.mX, pick.mXYCoords.mY); + media_impl->mouseCapture(); // the mouse-up will happen when capture is lost + } + + return true; + } + + LLSelectMgr::getInstance()->deselect(); + LLViewerMediaFocus::getInstance()->clearFocus(); + + return false; +} + +static bool handle_media_hover(const LLPickInfo& pick) +{ + //FIXME: how do we handle object in different parcel than us? + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (!parcel) return false; + + LLPointer<LLViewerObject> objectp = pick.getObject(); + + // Early out cases. Must clear mouse over media focus flag + // did not hit an object or did not hit a valid face + if ( objectp.isNull() || + pick.mObjectFace < 0 || + pick.mObjectFace >= objectp->getNumTEs() ) + { + LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); + return false; + } + + + // HACK: This is directly referencing an impl name. BAD! + // This can be removed when we have a truly generic media browser that only + // builds an impl based on the type of url it is passed. + + // is media playing on this face? + const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); + viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(tep->getID()); + if (tep + && media_impl.notNull() + && media_impl->hasMedia() + && gSavedSettings.getBOOL("MediaOnAPrimUI")) + { + if(LLViewerMediaFocus::getInstance()->getFocus()) + { + media_impl->mouseMove(pick.mXYCoords.mX, pick.mXYCoords.mY); + } + + // Set mouse over flag if unset + if (! LLViewerMediaFocus::getInstance()->getMouseOverFlag()) + { + LLSelectMgr::getInstance()->setHoverObject(objectp, pick.mObjectFace); + LLViewerMediaFocus::getInstance()->setMouseOverFlag(true, media_impl); + LLViewerMediaFocus::getInstance()->setPickInfo(pick); + } + + return true; + } + LLViewerMediaFocus::getInstance()->setMouseOverFlag(false); + + return false; +} + + static void handle_click_action_open_media(LLPointer<LLViewerObject> objectp) { //FIXME: how do we handle object in different parcel than us? @@ -861,7 +991,7 @@ static void handle_click_action_open_media(LLPointer<LLViewerObject> objectp) if( face < 0 || face >= objectp->getNumTEs() ) return; // is media playing on this face? - if (!LLViewerMedia::isActiveMediaTexture(objectp->getTE(face)->getID())) + if (LLViewerMedia::getMediaImplFromTextureID(objectp->getTE(face)->getID()) != NULL) { handle_click_action_play(); return; @@ -879,10 +1009,7 @@ static void handle_click_action_open_media(LLPointer<LLViewerObject> objectp) // This can be removed when we have a truly generic media browser that only // builds an impl based on the type of url it is passed. - if( LLMediaManager::getInstance()->supportsMediaType( "LLMediaImplLLMozLib", media_scheme, media_type ) ) - { - LLWeb::loadURL(media_url); - } + LLWeb::loadURL(media_url); } static ECursorType cursor_from_parcel_media(U8 click_action) @@ -900,19 +1027,12 @@ static ECursorType cursor_from_parcel_media(U8 click_action) std::string media_type = std::string ( parcel->getMediaType() ); LLStringUtil::trim(media_url); - // Get the scheme, see if that is handled as well. - LLURI uri(media_url); - std::string media_scheme = uri.scheme() != "" ? uri.scheme() : "http"; - - if( LLMediaManager::getInstance()->supportsMediaType( "LLMediaImplLLMozLib", media_scheme, media_type ) ) - { - open_cursor = UI_CURSOR_TOOLMEDIAOPEN; - } + open_cursor = UI_CURSOR_TOOLMEDIAOPEN; - LLMediaBase::EStatus status = LLViewerParcelMedia::getStatus(); + LLViewerMediaImpl::EMediaStatus status = LLViewerParcelMedia::getStatus(); switch(status) { - case LLMediaBase::STATUS_STARTED: + case LLViewerMediaImpl::MEDIA_PLAYING: return click_action == CLICK_ACTION_PLAY ? UI_CURSOR_TOOLPAUSE : open_cursor; default: return UI_CURSOR_TOOLPLAY; diff --git a/linden/indra/newview/lltoolpie.h b/linden/indra/newview/lltoolpie.h index 113fba7..001886f 100644 --- a/linden/indra/newview/lltoolpie.h +++ b/linden/indra/newview/lltoolpie.h @@ -51,6 +51,7 @@ public: virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); virtual void render(); diff --git a/linden/indra/newview/lltoolplacer.cpp b/linden/indra/newview/lltoolplacer.cpp index d5c4de1..c031a18 100644 --- a/linden/indra/newview/lltoolplacer.cpp +++ b/linden/indra/newview/lltoolplacer.cpp @@ -59,7 +59,7 @@ #include "llvolumemessage.h" #include "llhudmanager.h" #include "llagent.h" -#include "audioengine.h" +#include "llaudioengine.h" #include "llhudeffecttrail.h" #include "llviewerobjectlist.h" #include "llviewercamera.h" diff --git a/linden/indra/newview/llurldispatcher.cpp b/linden/indra/newview/llurldispatcher.cpp index f9b6b39..1144c58 100644 --- a/linden/indra/newview/llurldispatcher.cpp +++ b/linden/indra/newview/llurldispatcher.cpp @@ -39,7 +39,7 @@ #include "llfloaterurldisplay.h" #include "llfloaterdirectory.h" #include "llfloaterworldmap.h" -#include "llfloaterhtmlhelp.h" +#include "llfloatermediabrowser.h" #include "llpanellogin.h" #include "llstartup.h" // gStartupState #include "llurlsimstring.h" @@ -65,7 +65,7 @@ public: static bool isSLURLCommand(const std::string& url); static bool dispatch(const std::string& url, - LLWebBrowserCtrl* web, + LLMediaCtrl* web, bool trusted_browser); // returns true if handled or explicitly blocked. @@ -74,7 +74,7 @@ public: private: static bool dispatchCore(const std::string& url, bool right_mouse, - LLWebBrowserCtrl* web, + LLMediaCtrl* web, bool trusted_browser); // handles both left and right click @@ -84,7 +84,7 @@ private: static bool dispatchApp(const std::string& url, bool right_mouse, - LLWebBrowserCtrl* web, + LLMediaCtrl* web, bool trusted_browser); // Handles secondlife:///app/agent/<agent_id>/about and similar // by showing panel in Search floater. @@ -138,7 +138,7 @@ bool LLURLDispatcherImpl::isSLURLCommand(const std::string& url) // static bool LLURLDispatcherImpl::dispatchCore(const std::string& url, bool right_mouse, - LLWebBrowserCtrl* web, + LLMediaCtrl* web, bool trusted_browser) { if (url.empty()) return false; @@ -158,7 +158,7 @@ bool LLURLDispatcherImpl::dispatchCore(const std::string& url, // static bool LLURLDispatcherImpl::dispatch(const std::string& url, - LLWebBrowserCtrl* web, + LLMediaCtrl* web, bool trusted_browser) { llinfos << "url: " << url << llendl; @@ -171,7 +171,7 @@ bool LLURLDispatcherImpl::dispatchRightClick(const std::string& url) { llinfos << "url: " << url << llendl; const bool right_click = true; - LLWebBrowserCtrl* web = NULL; + LLMediaCtrl* web = NULL; const bool trusted_browser = false; return dispatchCore(url, right_click, web, trusted_browser); } @@ -192,7 +192,7 @@ bool LLURLDispatcherImpl::dispatchHelp(const std::string& url, bool right_mouse) // static bool LLURLDispatcherImpl::dispatchApp(const std::string& url, bool right_mouse, - LLWebBrowserCtrl* web, + LLMediaCtrl* web, bool trusted_browser) { if (!isSLURL(url)) @@ -386,7 +386,7 @@ public: LLTeleportHandler() : LLCommandHandler("teleport", true) { } bool handle(const LLSD& tokens, const LLSD& query_map, - LLWebBrowserCtrl* web) + LLMediaCtrl* web) { // construct a "normal" SLURL, resolve the region to // a global position, and teleport to it @@ -426,7 +426,7 @@ bool LLURLDispatcher::isSLURLCommand(const std::string& url) // static bool LLURLDispatcher::dispatch(const std::string& url, - LLWebBrowserCtrl* web, + LLMediaCtrl* web, bool trusted_browser) { return LLURLDispatcherImpl::dispatch(url, web, trusted_browser); @@ -448,7 +448,7 @@ bool LLURLDispatcher::dispatchFromTextEditor(const std::string& url) // click on it. // *TODO: Make this trust model more refined. JC const bool trusted_browser = true; - LLWebBrowserCtrl* web = NULL; + LLMediaCtrl* web = NULL; return LLURLDispatcherImpl::dispatch(url, web, trusted_browser); } diff --git a/linden/indra/newview/llurldispatcher.h b/linden/indra/newview/llurldispatcher.h index a4f6866..c947e5e 100644 --- a/linden/indra/newview/llurldispatcher.h +++ b/linden/indra/newview/llurldispatcher.h @@ -32,7 +32,7 @@ #ifndef LLURLDISPATCHER_H #define LLURLDISPATCHER_H -class LLWebBrowserCtrl; +class LLMediaCtrl; class LLURLDispatcher @@ -45,7 +45,7 @@ public: // Is this a special secondlife://app/ URL? static bool dispatch(const std::string& url, - LLWebBrowserCtrl* web, + LLMediaCtrl* web, bool trusted_browser); // At startup time and on clicks in internal web browsers, // teleport, open map, or run requested command. @@ -54,7 +54,7 @@ public: // secondlife:///app/agent/3d6181b0-6a4b-97ef-18d8-722652995cf1/show // sl://app/foo/bar // @param web - // Pointer to LLWebBrowserCtrl sending URL, can be NULL + // Pointer to LLMediaCtrl sending URL, can be NULL // @param trusted_browser // True if coming inside the app AND from a brower instance // that navigates to trusted (Linden Lab) pages. diff --git a/linden/indra/newview/llvieweraudio.cpp b/linden/indra/newview/llvieweraudio.cpp index f043fb5..74b8e8f 100644 --- a/linden/indra/newview/llvieweraudio.cpp +++ b/linden/indra/newview/llvieweraudio.cpp @@ -32,7 +32,7 @@ #include "llviewerprecompiledheaders.h" -#include "audioengine.h" +#include "llaudioengine.h" #include "llagent.h" #include "llappviewer.h" #include "llvieweraudio.h" @@ -130,7 +130,6 @@ void audio_update_volume(bool force_update) gAudiop->setMasterGain ( master_volume ); gAudiop->setDopplerFactor(gSavedSettings.getF32("AudioLevelDoppler")); - gAudiop->setDistanceFactor(gSavedSettings.getF32("AudioLevelDistance")); gAudiop->setRolloffFactor(gSavedSettings.getF32("AudioLevelRolloff")); if(wind_muted == false) diff --git a/linden/indra/newview/llviewercontrol.cpp b/linden/indra/newview/llviewercontrol.cpp index 50224ad..1531e6c 100644 --- a/linden/indra/newview/llviewercontrol.cpp +++ b/linden/indra/newview/llviewercontrol.cpp @@ -38,7 +38,7 @@ #include "indra_constants.h" // For Listeners -#include "audioengine.h" +#include "llaudioengine.h" #include "llagent.h" #include "llconsole.h" #include "lldrawpoolterrain.h" @@ -69,7 +69,6 @@ #include "llvosurfacepatch.h" #include "llvowlsky.h" #include "llrender.h" -#include "llmediamanager.h" #include "llslider.h" #include "llfloaterchat.h" @@ -498,21 +497,6 @@ bool handleTranslateChatPrefsChanged(const LLSD& newvalue) return true; } -bool handleMediaDebugLevelChanged(const LLSD& newvalue) -{ - LLMediaManager *mgr = LLMediaManager::getInstance(); - if (mgr) - { - LLMediaBase *impl = - mgr->createSourceFromMimeType("http", "audio/mpeg"); - - if (impl) - { - impl->setDebugLevel( (LLMediaBase::EDebugLevel)newvalue.asInteger() ); - } - } - return true; -} bool handleSliderScrollWheelMultiplierChanged(const LLSD& newvalue) { @@ -674,7 +658,6 @@ void settings_setup_listeners() gSavedSettings.getControl("VoiceOutputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1)); gSavedSettings.getControl("AudioLevelMic")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1)); gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1)); - gSavedSettings.getControl("MediaDebugLevel")->getSignal()->connect(boost::bind(&handleMediaDebugLevelChanged, _1)); gSavedSettings.getControl("SliderScrollWheelMultiplier")->getSignal()->connect(boost::bind(&handleSliderScrollWheelMultiplierChanged, _1)); gSavedSettings.getControl("TranslateChat")->getSignal()->connect(boost::bind(&handleTranslateChatPrefsChanged, _1)); diff --git a/linden/indra/newview/llviewergesture.cpp b/linden/indra/newview/llviewergesture.cpp index 01b3c58..7799c99 100644 --- a/linden/indra/newview/llviewergesture.cpp +++ b/linden/indra/newview/llviewergesture.cpp @@ -34,7 +34,7 @@ #include "llviewergesture.h" -#include "audioengine.h" +#include "llaudioengine.h" #include "lldir.h" #include "llviewerinventory.h" #include "sound_ids.h" // for testing diff --git a/linden/indra/newview/llviewerimagelist.cpp b/linden/indra/newview/llviewerimagelist.cpp index 703d233..29c630b 100644 --- a/linden/indra/newview/llviewerimagelist.cpp +++ b/linden/indra/newview/llviewerimagelist.cpp @@ -593,7 +593,7 @@ void LLViewerImageList::updateImages(F32 max_time) llpushcallstacks ; if (!gNoRender && !gGLManager.mIsDisabled) { - LLViewerMedia::updateImagesMediaStreams(); + LLViewerMedia::updateMedia(); } llpushcallstacks ; updateImagesUpdateStats(); diff --git a/linden/indra/newview/llviewerkeyboard.cpp b/linden/indra/newview/llviewerkeyboard.cpp index 15c8148..6dd7fb5 100644 --- a/linden/indra/newview/llviewerkeyboard.cpp +++ b/linden/indra/newview/llviewerkeyboard.cpp @@ -506,7 +506,7 @@ void start_chat( EKeystate s ) void start_gesture( EKeystate s ) { if (KEYSTATE_UP == s && - !(gFocusMgr.getKeyboardFocus() && gFocusMgr.getKeyboardFocus()->acceptsTextInput())) + !(gFocusMgr.getKeyboardFocus() && dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus())->acceptsTextInput())) { if (gChatBar->getCurrentChat().empty()) { diff --git a/linden/indra/newview/llviewermedia.cpp b/linden/indra/newview/llviewermedia.cpp index 6bcf8ce..92ccf25 100644 --- a/linden/indra/newview/llviewermedia.cpp +++ b/linden/indra/newview/llviewermedia.cpp @@ -33,687 +33,1137 @@ #include "llviewerprecompiledheaders.h" #include "llviewermedia.h" - +#include "llviewermediafocus.h" +#include "llhoverview.h" #include "llmimetypes.h" #include "llviewercontrol.h" #include "llviewerimage.h" #include "llviewerwindow.h" #include "llviewerimagelist.h" -#include "viewerversion.h" + +#include "llpluginclassmedia.h" #include "llevent.h" // LLSimpleListener -#include "llmediamanager.h" #include "lluuid.h" +#include "llkeyboard.h" -#include <boost/bind.hpp> // for SkinFolder listener -#include <boost/signal.hpp> +// Merov: Temporary definitions while porting the new viewer media code to Snowglobe +const int LEFT_BUTTON = 0; +const int RIGHT_BUTTON = 1; -// Implementation functions not exported into header file -class LLViewerMediaImpl - : public LLMediaObserver +// Move this to its own file. + +LLViewerMediaEventEmitter::~LLViewerMediaEventEmitter() { - public: - LLViewerMediaImpl() - : mMediaSource( NULL ), - mMovieImageID(), - mMovieImageHasMips(false) - { } - - void destroyMediaSource(); - - void play(const std::string& media_url, - const std::string& mime_type, - const LLUUID& placeholder_texture_id, - S32 media_width, S32 media_height, U8 media_auto_scale, - U8 media_loop); - - void stop(); - void pause(); - void start(); - void seek(F32 time); - void setVolume(F32 volume); - LLMediaBase::EStatus getStatus(); - - /*virtual*/ void onMediaSizeChange(const EventType& event_in); - /*virtual*/ void onMediaContentsChange(const EventType& event_in); - - void updateMovieImage(const LLUUID& image_id, BOOL active); - void updateImagesMediaStreams(); - LLUUID getMediaTextureID(); - - // Internally set our desired browser user agent string, including - // the Second Life version and skin name. Used because we can - // switch skins without restarting the app. - static void updateBrowserUserAgent(); - - // Callback for when the SkinCurrent control is changed to - // switch the user agent string to indicate the new skin. - static bool handleSkinCurrentChanged(const LLSD& newvalue); + observerListType::iterator iter = mObservers.begin(); - public: + while( iter != mObservers.end() ) + { + LLViewerMediaObserver *self = *iter; + iter++; + remObserver(self); + } +} - // a single media url with some data and an impl. - LLMediaBase* mMediaSource; - LLUUID mMovieImageID; - bool mMovieImageHasMips; - std::string mMediaURL; - std::string mMimeType; - private: - void initializePlaceholderImage(LLViewerImage *placeholder_image, LLMediaBase *media_source); -}; +/////////////////////////////////////////////////////////////////////////////// +// +bool LLViewerMediaEventEmitter::addObserver( LLViewerMediaObserver* observer ) +{ + if ( ! observer ) + return false; -static LLViewerMediaImpl sViewerMediaImpl; + if ( std::find( mObservers.begin(), mObservers.end(), observer ) != mObservers.end() ) + return false; -////////////////////////////////////////////////////////////////////////////////////////// + mObservers.push_back( observer ); + observer->mEmitters.push_back( this ); -void LLViewerMediaImpl::destroyMediaSource() + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// +bool LLViewerMediaEventEmitter::remObserver( LLViewerMediaObserver* observer ) +{ + if ( ! observer ) + return false; + + mObservers.remove( observer ); + observer->mEmitters.remove(this); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////// +// +void LLViewerMediaEventEmitter::emitEvent( LLPluginClassMedia* media, LLPluginClassMediaOwner::EMediaEvent event ) { - LLMediaManager* mgr = LLMediaManager::getInstance(); - if ( mMediaSource ) + observerListType::iterator iter = mObservers.begin(); + + while( iter != mObservers.end() ) { - bool was_playing = LLViewerMedia::isMediaPlaying(); - mMediaSource->remObserver(this); - mgr->destroySource( mMediaSource ); + LLViewerMediaObserver *self = *iter; + ++iter; + self->handleMediaEvent( media, event ); + } +} - // Restore the texture - updateMovieImage(LLUUID::null, was_playing); +// Move this to its own file. +LLViewerMediaObserver::~LLViewerMediaObserver() +{ + std::list<LLViewerMediaEventEmitter *>::iterator iter = mEmitters.begin(); + while( iter != mEmitters.end() ) + { + LLViewerMediaEventEmitter *self = *iter; + iter++; + self->remObserver( this ); } - mMediaSource = NULL; } -void LLViewerMediaImpl::play(const std::string& media_url, - const std::string& mime_type, - const LLUUID& placeholder_texture_id, - S32 media_width, S32 media_height, U8 media_auto_scale, - U8 media_loop) + +// Move this to its own file. +// helper class that tries to download a URL from a web site and calls a method +// on the Panel Land Media and to discover the MIME type +class LLMimeDiscoveryResponder : public LLHTTPClient::Responder { - // first stop any previously playing media - stop(); +LOG_CLASS(LLMimeDiscoveryResponder); +public: + LLMimeDiscoveryResponder( viewer_media_t media_impl) + : mMediaImpl(media_impl), + mInitialized(false) + {} + - // Save this first, as init/load below may fire events - mMovieImageID = placeholder_texture_id; - // If the mime_type passed in is different than the cached one, and - // Auto-discovery is turned OFF, replace the cached mime_type with the new one. - if(mime_type != mMimeType && - ! gSavedSettings.getBOOL("AutoMimeDiscovery")) + virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content) { - mMimeType = mime_type; + std::string media_type = content["content-type"].asString(); + std::string::size_type idx1 = media_type.find_first_of(";"); + std::string mime_type = media_type.substr(0, idx1); + completeAny(status, mime_type); } - LLURI url(media_url); - std::string scheme = url.scheme() != "" ? url.scheme() : "http"; - LLMediaManager* mgr = LLMediaManager::getInstance(); - mMediaSource = mgr->createSourceFromMimeType(scheme, mMimeType ); - if ( !mMediaSource ) + virtual void error( U32 status, const std::string& reason ) { - if (mMimeType != "none/none") + // completeAny(status, "none/none"); + } + + void completeAny(U32 status, const std::string& mime_type) + { + if(!mInitialized && ! mime_type.empty()) { - llwarns << "media source create failed " << media_url - << " type " << mMimeType - << llendl; + if (mMediaImpl->initializeMedia(mime_type)) + { + mInitialized = true; + mMediaImpl->play(); + } } - return; } - // Store the URL and Mime Type - mMediaURL = media_url; + public: + viewer_media_t mMediaImpl; + bool mInitialized; +}; +typedef std::list<LLViewerMediaImpl*> impl_list; +static impl_list sViewerMediaImplList; + +////////////////////////////////////////////////////////////////////////////////////////// +// LLViewerMedia - if ((media_width != 0) && (media_height != 0)) +////////////////////////////////////////////////////////////////////////////////////////// +// static +viewer_media_t LLViewerMedia::newMediaImpl(const std::string& media_url, + const LLUUID& texture_id, + S32 media_width, S32 media_height, U8 media_auto_scale, + U8 media_loop, + std::string mime_type) +{ + LLViewerMediaImpl* media_impl = getMediaImplFromTextureID(texture_id); + if(media_impl == NULL || texture_id.isNull()) { - mMediaSource->setRequestedMediaSize(media_width, media_height); + // Create the media impl + media_impl = new LLViewerMediaImpl(media_url, texture_id, media_width, media_height, media_auto_scale, media_loop, mime_type); + sViewerMediaImplList.push_back(media_impl); } - - mMediaSource->setLooping(media_loop); - mMediaSource->setAutoScaled(media_auto_scale); - mMediaSource->addObserver( this ); - mMediaSource->navigateTo( media_url ); - mMediaSource->addCommand(LLMediaBase::COMMAND_START); + else + { + media_impl->stop(); + media_impl->mTextureId = texture_id; + media_impl->mMediaURL = media_url; + media_impl->mMediaWidth = media_width; + media_impl->mMediaHeight = media_height; + media_impl->mMediaAutoScale = media_auto_scale; + media_impl->mMediaLoop = media_loop; + if(! media_url.empty()) + media_impl->navigateTo(media_url, mime_type, true); + } + return media_impl; } -void LLViewerMediaImpl::stop() +////////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::removeMedia(LLViewerMediaImpl* media) { - destroyMediaSource(); + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + + for(; iter != end; iter++) + { + if(media == *iter) + { + sViewerMediaImplList.erase(iter); + return; + } + } } -void LLViewerMediaImpl::pause() +////////////////////////////////////////////////////////////////////////////////////////// +// static +LLViewerMediaImpl* LLViewerMedia::getMediaImplFromTextureID(const LLUUID& texture_id) { - if(mMediaSource) + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + + for(; iter != end; iter++) { - mMediaSource->addCommand(LLMediaBase::COMMAND_PAUSE); + LLViewerMediaImpl* media_impl = *iter; + if(media_impl->getMediaTextureID() == texture_id) + { + return media_impl; + } } + return NULL; } -void LLViewerMediaImpl::start() +////////////////////////////////////////////////////////////////////////////////////////// +// static +std::string LLViewerMedia::getCurrentUserAgent() { - if(mMediaSource) - { - mMediaSource->addCommand(LLMediaBase::COMMAND_START); - } + // Don't use user-visible string to avoid + // punctuation and strange characters. + std::string skin_name = gSavedSettings.getString("SkinCurrent"); + + // Just in case we need to check browser differences in A/B test + // builds. + std::string channel = gSavedSettings.getString("VersionChannelName"); + + // append our magic version number string to the browser user agent id + // See the HTTP 1.0 and 1.1 specifications for allowed formats: + // http://www.ietf.org/rfc/rfc1945.txt section 10.15 + // http://www.ietf.org/rfc/rfc2068.txt section 3.8 + // This was also helpful: + // http://www.mozilla.org/build/revised-user-agent-strings.html + std::ostringstream codec; + codec << "SecondLife/"; + codec << "C64 Basic V2"; //imprudence fixme : this isn't anybodys business anyway +// codec << LL_VERSION_MAJOR << "." << LL_VERSION_MINOR << "." << LL_VERSION_PATCH << "." << LL_VERSION_BUILD; +// codec << " (" << channel << "; " << skin_name << " skin)"; +// llinfos << codec.str() << llendl; + + return codec.str(); } -void LLViewerMediaImpl::seek(F32 time) +////////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::updateBrowserUserAgent() { - if(mMediaSource) + std::string user_agent = getCurrentUserAgent(); + + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + + for(; iter != end; iter++) { - mMediaSource->seek(time); + LLViewerMediaImpl* pimpl = *iter; + if(pimpl->mMediaSource && pimpl->mMediaSource->pluginSupportsMediaBrowser()) + { + pimpl->mMediaSource->setBrowserUserAgent(user_agent); + } } + } -void LLViewerMediaImpl::setVolume(F32 volume) +////////////////////////////////////////////////////////////////////////////////////////// +// static +bool LLViewerMedia::handleSkinCurrentChanged(const LLSD& /*newvalue*/) { - if(mMediaSource) + // gSavedSettings is already updated when this function is called. + updateBrowserUserAgent(); + return true; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// static +bool LLViewerMedia::textureHasMedia(const LLUUID& texture_id) +{ + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + + for(; iter != end; iter++) { - mMediaSource->setVolume( volume); + LLViewerMediaImpl* pimpl = *iter; + if(pimpl->getMediaTextureID() == texture_id) + { + return true; + } } + return false; } -LLMediaBase::EStatus LLViewerMediaImpl::getStatus() +////////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::setVolume(F32 volume) { - if (mMediaSource) + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + + for(; iter != end; iter++) { - return mMediaSource->getStatus(); + LLViewerMediaImpl* pimpl = *iter; + pimpl->setVolume(volume); } - else +} + +////////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::updateMedia() +{ + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + + for(; iter != end; iter++) { - return LLMediaBase::STATUS_UNKNOWN; + LLViewerMediaImpl* pimpl = *iter; + pimpl->update(); } } ////////////////////////////////////////////////////////////////////////////////////////// // static -void LLViewerMediaImpl::updateMovieImage(const LLUUID& uuid, BOOL active) +void LLViewerMedia::cleanupClass() { - // IF the media image hasn't changed, do nothing - if (mMovieImageID == uuid) + // This is no longer necessary, since the list is no longer smart pointers. +#if 0 + while(!sViewerMediaImplList.empty()) { - return; + sViewerMediaImplList.pop_back(); } - // If we have changed media uuid, restore the old one - if (!mMovieImageID.isNull()) +#endif +} + +////////////////////////////////////////////////////////////////////////////////////////// +// LLViewerMediaImpl +////////////////////////////////////////////////////////////////////////////////////////// +LLViewerMediaImpl::LLViewerMediaImpl(const std::string& media_url, + const LLUUID& texture_id, + S32 media_width, + S32 media_height, + U8 media_auto_scale, + U8 media_loop, + const std::string& mime_type) +: + mMediaSource( NULL ), + mMovieImageHasMips(false), + mTextureId(texture_id), + mMediaWidth(media_width), + mMediaHeight(media_height), + mMediaAutoScale(media_auto_scale), + mMediaLoop(media_loop), + mMediaURL(media_url), + mMimeType(mime_type), + mNeedsNewTexture(true), + mSuspendUpdates(false), + mVisible(true) +{ + createMediaSource(); +} + +////////////////////////////////////////////////////////////////////////////////////////// +LLViewerMediaImpl::~LLViewerMediaImpl() +{ + if( gEditMenuHandler == this ) { - LLViewerImage* oldImage = LLViewerImage::getImage( mMovieImageID ); - if (oldImage) - { - oldImage->reinit(mMovieImageHasMips); - oldImage->mIsMediaTexture = FALSE; - } - mMovieImageID.setNull(); + gEditMenuHandler = NULL; } - // If the movie is playing, set the new media image - if (active && !uuid.isNull()) + + destroyMediaSource(); + LLViewerMedia::removeMedia(this); +} + +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) +{ + if((mMediaSource == NULL) || (mMimeType != mime_type)) { - LLViewerImage* viewerImage = LLViewerImage::getImage( uuid ); - if( viewerImage ) + if(! initializePlugin(mime_type)) { - mMovieImageID = uuid; - // Can't use mipmaps for movies because they don't update the full image - mMovieImageHasMips = viewerImage->getUseMipMaps(); - viewerImage->reinit(FALSE); - viewerImage->mIsMediaTexture = TRUE; + LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << mime_type << LL_ENDL; + LLSD args; + args["MIME_TYPE"] = mime_type; + LLNotifications::instance().add("NoPlugin", args); + + return false; } } -} + // play(); + return (mMediaSource != NULL); +} ////////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMediaImpl::updateImagesMediaStreams() +void LLViewerMediaImpl::createMediaSource() { - LLMediaManager::updateClass(); + if(! mMediaURL.empty()) + { + navigateTo(mMediaURL, mMimeType, true); + } + else if(! mMimeType.empty()) + { + initializeMedia(mMimeType); + } + } -void LLViewerMediaImpl::initializePlaceholderImage(LLViewerImage *placeholder_image, LLMediaBase *media_source) +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::destroyMediaSource() { - int media_width = media_source->getMediaWidth(); - int media_height = media_source->getMediaHeight(); - //int media_rowspan = media_source->getMediaRowSpan(); - - // if width & height are invalid, don't bother doing anything - if ( media_width < 1 || media_height < 1 ) + mNeedsNewTexture = true; + if(! mMediaSource) + { return; + } + // Restore the texture + updateMovieImage(LLUUID::null, false); + delete mMediaSource; + mMediaSource = NULL; +} - llinfos << "initializing media placeholder" << llendl; - llinfos << "movie image id " << mMovieImageID << llendl; - - int texture_width = LLMediaManager::textureWidthFromMediaWidth( media_width ); - int texture_height = LLMediaManager::textureHeightFromMediaHeight( media_height ); - int texture_depth = media_source->getMediaDepth(); - - // MEDIAOPT: check to see if size actually changed before doing work - placeholder_image->destroyGLTexture(); - // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work? - placeholder_image->reinit(FALSE); // probably not needed +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::setMediaType(const std::string& media_type) +{ + mMimeType = media_type; +} - // MEDIAOPT: seems insane that we actually have to make an imageraw then - // immediately discard it - LLPointer<LLImageRaw> raw = new LLImageRaw(texture_width, texture_height, texture_depth); - raw->clear(0x0f, 0x0f, 0x0f, 0xff); - int discard_level = 0; +////////////////////////////////////////////////////////////////////////////////////////// +/*static*/ +LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height) +{ + std::string plugin_basename = LLMIMETypes::implType(media_type); - // ask media source for correct GL image format constants - placeholder_image->setExplicitFormat(media_source->getTextureFormatInternal(), - media_source->getTextureFormatPrimary(), - media_source->getTextureFormatType()); + if(plugin_basename.empty()) + { + LL_WARNS("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL; + } + else + { + std::string launcher_name = gDirUtilp->getLLPluginLauncher(); + std::string plugin_name = gDirUtilp->getLLPluginFilename(plugin_basename); + std::string user_data_path = gDirUtilp->getOSUserAppDir(); + user_data_path += gDirUtilp->getDirDelimiter(); + + // See if the plugin executable exists + llstat s; + if(LLFile::stat(launcher_name, &s)) + { + LL_WARNS("Media") << "Couldn't find launcher at " << launcher_name << LL_ENDL; + } + else if(LLFile::stat(plugin_name, &s)) + { + LL_WARNS("Media") << "Couldn't find plugin at " << plugin_name << LL_ENDL; + } + else + { + LLPluginClassMedia* media_source = new LLPluginClassMedia(owner); + media_source->setSize(default_width, default_height); + if (media_source->init(launcher_name, plugin_name, false, user_data_path)) + { + return media_source; + } + else + { + LL_WARNS("Media") << "Failed to init plugin. Destroying." << LL_ENDL; + delete media_source; + } + } + } + + return NULL; +} - placeholder_image->createGLTexture(discard_level, raw); +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) +{ + if(mMediaSource) + { + // Save the previous media source's last set size before destroying it. + mMediaWidth = mMediaSource->getSetWidth(); + mMediaHeight = mMediaSource->getSetHeight(); + } + + // Always delete the old media impl first. + destroyMediaSource(); + + // and unconditionally set the mime type + mMimeType = media_type; - // placeholder_image->setExplicitFormat() - placeholder_image->setUseMipMaps(FALSE); + LLPluginClassMedia* media_source = newSourceFromMediaType(media_type, this, mMediaWidth, mMediaHeight); + + if (media_source) + { + media_source->setDisableTimeout(gSavedSettings.getBOOL("DebugPluginDisableTimeout")); + media_source->setLoop(mMediaLoop); + media_source->setAutoScale(mMediaAutoScale); + media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent()); + + mMediaSource = media_source; + return true; + } - // MEDIAOPT: set this dynamically on play/stop - placeholder_image->mIsMediaTexture = true; + return false; } +void LLViewerMediaImpl::setSize(int width, int height) +{ + mMediaWidth = width; + mMediaHeight = height; + if(mMediaSource) + { + mMediaSource->setSize(width, height); + } +} - -// virtual -void LLViewerMediaImpl::onMediaContentsChange(const EventType& event_in) +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::play() { - LLMediaBase* media_source = event_in.getSubject(); - LLViewerImage* placeholder_image = gImageList.getImage( mMovieImageID ); - if ((placeholder_image) && (placeholder_image->getHasGLTexture())) + // first stop any previously playing media + // stop(); + + // mMediaSource->addObserver( this ); + if(mMediaSource == NULL) { - if (placeholder_image->getUseMipMaps()) + if(!initializePlugin(mMimeType)) { - // bad image! NO MIPMAPS! - initializePlaceholderImage(placeholder_image, media_source); + // Plugin failed initialization... should assert or something + return; } + } + + // updateMovieImage(mTextureId, true); - U8* data = media_source->getMediaData(); - S32 x_pos = 0; - S32 y_pos = 0; - S32 width = media_source->getMediaWidth(); - S32 height = media_source->getMediaHeight(); - S32 data_width = media_source->getMediaDataWidth(); - S32 data_height = media_source->getMediaDataHeight(); - placeholder_image->setSubImage(data, data_width, data_height, - x_pos, y_pos, width, height); + mMediaSource->loadURI( mMediaURL ); + if(/*mMediaSource->pluginSupportsMediaTime()*/ true) + { + start(); } } +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::stop() +{ + if(mMediaSource) + { + mMediaSource->stop(); + // destroyMediaSource(); + } +} -// virtual -void LLViewerMediaImpl::onMediaSizeChange(const EventType& event_in) +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::pause() { - LLMediaBase* media_source = event_in.getSubject(); - LLViewerImage* placeholder_image = gImageList.getImage( mMovieImageID ); - if (placeholder_image) + if(mMediaSource) { - initializePlaceholderImage(placeholder_image, media_source); + mMediaSource->pause(); } - else +} + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::start() +{ + if(mMediaSource) { - llinfos << "no placeholder image" << llendl; + mMediaSource->start(); } } +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::seek(F32 time) +{ + if(mMediaSource) + { + mMediaSource->seek(time); + } +} - // Get the image we're using +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::setVolume(F32 volume) +{ + if(mMediaSource) + { + mMediaSource->setVolume(volume); + } +} - /* - // update media stream if required - LLMediaEngine* media_engine = LLMediaEngine::getInstance(); - if (media_engine) +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::focus(bool focus) +{ + if (mMediaSource) { - if ( media_engine->update() ) - { - LLUUID media_uuid = media_engine->getImageUUID(); - updateMovieImage(media_uuid, TRUE); - if (!media_uuid.isNull()) - { - LLViewerImage* viewerImage = getImage( media_uuid ); - if( viewerImage ) - { - LLMediaBase* renderer = media_engine->getMediaRenderer(); - if ((renderer->getTextureWidth() != viewerImage->getWidth()) || - (renderer->getTextureHeight() != viewerImage->getHeight()) || - (renderer->getTextureDepth() != viewerImage->getComponents()) || - (viewerImage->getHasGLTexture() == FALSE)) - { - // destroy existing GL image - viewerImage->destroyGLTexture(); - - // set new size - viewerImage->setSize( renderer->getTextureWidth(), - renderer->getTextureHeight(), - renderer->getTextureDepth() ); - - LLPointer<LLImageRaw> raw = new LLImageRaw(renderer->getTextureWidth(), - renderer->getTextureHeight(), - renderer->getTextureDepth()); - raw->clear(0x7f,0x7f,0x7f,0xff); - viewerImage->createGLTexture(0, raw); - } - - // Set the explicit format the instance wants - viewerImage->setExplicitFormat(renderer->getTextureFormatInternal(), - renderer->getTextureFormatPrimary(), - renderer->getTextureFormatType(), - renderer->getTextureFormatSwapBytes()); - // This should be redundant, but just in case: - viewerImage->setUseMipMaps(FALSE); - - LLImageRaw* rawImage = media_engine->getImageRaw(); - if ( rawImage ) - { - viewerImage->setSubImage(rawImage, 0, 0, - renderer->getMediaWidth(), - renderer->getMediaHeight()); - } - } - else - { - llwarns << "MediaEngine update unable to get viewer image for GL texture" << llendl; - } - } - } - else + // call focus just for the hell of it, even though this apopears to be a nop + mMediaSource->focus(focus); + if (focus) { - LLUUID media_uuid = media_engine->getImageUUID(); - updateMovieImage(media_uuid, FALSE); + // spoof a mouse click to *actually* pass focus + // Don't do this anymore -- it actually clicks through now. +// mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, 1, 1, 0); +// mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 1, 1, 0); } } - */ - +} -LLUUID LLViewerMediaImpl::getMediaTextureID() +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::mouseDown(S32 x, S32 y) { - return mMovieImageID; + scaleMouse(&x, &y); + mLastMouseX = x; + mLastMouseY = y; + if (mMediaSource) + { + mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, LEFT_BUTTON, x, y, 0); + } } -// static -void LLViewerMediaImpl::updateBrowserUserAgent() +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::mouseUp(S32 x, S32 y) { - // Don't use user-visible string to avoid - // punctuation and strange characters. - std::string skin_name = gSavedSettings.getString("SkinCurrent"); - - // Just in case we need to check browser differences in A/B test - // builds. - std::string channel = gSavedSettings.getString("VersionChannelName"); - - // append our magic version number string to the browser user agent id - // See the HTTP 1.0 and 1.1 specifications for allowed formats: - // http://www.ietf.org/rfc/rfc1945.txt section 10.15 - // http://www.ietf.org/rfc/rfc2068.txt section 3.8 - // This was also helpful: - // http://www.mozilla.org/build/revised-user-agent-strings.html - std::ostringstream codec; - codec << "SecondLife/"; - codec << ViewerVersion::getLLMajorVersion() << "." << ViewerVersion::getLLMinorVersion() << "." << ViewerVersion::getLLPatchVersion() << "." << ViewerVersion::getLLBuildVersion(); - codec << " (" << channel << "; " << skin_name << " skin)"; - llinfos << codec.str() << llendl; - LLMediaManager::setBrowserUserAgent( codec.str() ); + scaleMouse(&x, &y); + mLastMouseX = x; + mLastMouseY = y; + if (mMediaSource) + { + mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, x, y, 0); + } } -// static -bool LLViewerMediaImpl::handleSkinCurrentChanged(const LLSD& /*newvalue*/) +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::mouseMove(S32 x, S32 y) { - // gSavedSettings is already updated when this function is called. - updateBrowserUserAgent(); - return true; + scaleMouse(&x, &y); + mLastMouseX = x; + mLastMouseY = y; + if (mMediaSource) + { + mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, LEFT_BUTTON, x, y, 0); + } } ////////////////////////////////////////////////////////////////////////////////////////// -// Wrapper class +void LLViewerMediaImpl::mouseLeftDoubleClick(S32 x, S32 y) +{ + scaleMouse(&x, &y); + mLastMouseX = x; + mLastMouseY = y; + if (mMediaSource) + { + mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, LEFT_BUTTON, x, y, 0); + } +} + ////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::onMouseCaptureLost() +{ + if (mMediaSource) + { + mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, mLastMouseX, mLastMouseY, 0); + } +} +////////////////////////////////////////////////////////////////////////////////////////// +BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask) +{ + // NOTE: this is called when the mouse is released when we have capture. + // Due to the way mouse coordinates are mapped to the object, we can't use the x and y coordinates that come in with the event. + + if(hasMouseCapture()) + { + // Release the mouse -- this will also send a mouseup to the media + gFocusMgr.setMouseCapture( FALSE ); + } + return TRUE; +} ////////////////////////////////////////////////////////////////////////////////////////// -// The viewer takes a long time to load the start screen. Part of the problem -// is media initialization -- in particular, QuickTime loads many DLLs and -// hits the disk heavily. So we initialize only the browser component before -// the login screen, then do the rest later when we have a progress bar. JC -// static -void LLViewerMedia::initBrowser() +void LLViewerMediaImpl::navigateHome() { - LLMediaManagerData* init_data = new LLMediaManagerData; - buildMediaManagerData( init_data ); - LLMediaManager::initBrowser( init_data ); - delete init_data; - - // We use a custom user agent with viewer version and skin name. - LLViewerMediaImpl::updateBrowserUserAgent(); + if(mMediaSource) + { + mMediaSource->loadURI( mHomeURL ); + } } ////////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::initClass() +void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type) { - // *TODO: This looks like a memory leak to me. JC - LLMediaManagerData* init_data = new LLMediaManagerData; - buildMediaManagerData( init_data ); - LLMediaManager::initClass( init_data ); - delete init_data; + if(rediscover_type) + { + + LLURI uri(url); + std::string scheme = uri.scheme(); - LLMediaManager* mm = LLMediaManager::getInstance(); - LLMIMETypes::mime_info_map_t::const_iterator it; - for (it = LLMIMETypes::sMap.begin(); it != LLMIMETypes::sMap.end(); ++it) + if(scheme.empty() || "http" == scheme || "https" == scheme) + { + LLHTTPClient::getHeaderOnly( url, new LLMimeDiscoveryResponder(this)); + } + else if("data" == scheme || "file" == scheme || "about" == scheme) + { + // FIXME: figure out how to really discover the type for these schemes + // We use "data" internally for a text/html url for loading the login screen + if(initializeMedia("text/html")) + { + mMediaSource->loadURI( url ); + } + } + else + { + // This catches 'rtsp://' urls + if(initializeMedia(scheme)) + { + mMediaSource->loadURI( url ); + } + } + } + else if (mMediaSource) { - const std::string& mime_type = it->first; - const LLMIMETypes::LLMIMEInfo& info = it->second; - mm->addMimeTypeImplNameMap( mime_type, info.mImpl ); + mMediaSource->loadURI( url ); } - - LLMediaBase *impl = mm->createSourceFromMimeType("http", "audio/mpeg"); - if (impl) + else if(initializeMedia(mime_type) && mMediaSource) + { + mMediaSource->loadURI( url ); + } + else { - U32 level = gSavedSettings.getU32("MediaDebugLevel"); - impl->setDebugLevel( (LLMediaBase::EDebugLevel)level ); + LL_WARNS("Media") << "Couldn't navigate to: " << url << " as there is no media type for: " << mime_type << LL_ENDL; + return; } + mMediaURL = url; + } ////////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::buildMediaManagerData( LLMediaManagerData* init_data ) -{ -// std::string executable_dir = std::string( arg0 ).substr( 0, std::string( arg0 ).find_last_of("\\/") ); -// std::string component_dir = std::string( executable_dir ).substr( 0, std::string( executable_dir ).find_last_of("\\/") ); -// component_dir = std::string( component_dir ).substr( 0, std::string( component_dir ).find_last_of("\\/") ); -// component_dir = std::string( component_dir ).substr( 0, std::string( component_dir ).find_last_of("\\/") ); -// component_dir += "\\newview\\app_settings\\mozilla"; - - -#if LL_DARWIN - // For Mac OS, we store both the shared libraries and the runtime files (chrome/, plugins/, etc) in - // Second Life.app/Contents/MacOS/. This matches the way Firefox is distributed on the Mac. - std::string component_dir(gDirUtilp->getExecutableDir()); -#elif LL_WINDOWS - std::string component_dir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) ); - component_dir += gDirUtilp->getDirDelimiter(); - #ifdef LL_DEBUG - component_dir += "mozilla_debug"; - #else // LL_DEBUG - component_dir += "mozilla"; - #endif // LL_DEBUG -#elif LL_LINUX - std::string component_dir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) ); - component_dir += gDirUtilp->getDirDelimiter(); - - #if LINUX64 - component_dir += "mozilla-runtime-linux-x86_64"; - #else - component_dir += "mozilla-runtime-linux-i686"; - #endif - -#elif LL_SOLARIS - std::string component_dir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) ); - component_dir += gDirUtilp->getDirDelimiter(); - #ifdef __sparc - component_dir += "mozilla-solaris-sparc"; - #else - component_dir += "mozilla-solaris-i686"; - #endif -#else - std::string component_dir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) ); - component_dir += gDirUtilp->getDirDelimiter(); - component_dir += "mozilla"; -#endif - - std::string application_dir = gDirUtilp->getExecutableDir(); +void LLViewerMediaImpl::navigateStop() +{ + if(mMediaSource) + { + mMediaSource->browse_stop(); + } - init_data->setBrowserApplicationDir( application_dir ); - std::string profile_dir = gDirUtilp->getExpandedFilename( LL_PATH_MOZILLA_PROFILE, "" ); - init_data->setBrowserProfileDir( profile_dir ); - init_data->setBrowserComponentDir( component_dir ); - std::string profile_name("Second Life"); - init_data->setBrowserProfileName( profile_name ); - init_data->setBrowserParentWindow( gViewerWindow->getMediaWindow() ); +} - // Users can change skins while client is running, so make sure - // we pick up on changes. - gSavedSettings.getControl("SkinCurrent")->getSignal()->connect( - boost::bind( LLViewerMediaImpl::handleSkinCurrentChanged, _1 ) ); +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) +{ + bool result = false; + + if (mMediaSource) + { + result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask); + } + + return result; +} +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) +{ + bool result = false; + + if (mMediaSource) + { + // only accept 'printable' characters, sigh... + if (uni_char >= 32 // discard 'control' characters + && uni_char != 127) // SDL thinks this is 'delete' - yuck. + { + mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE)); + } + } + + return result; } ////////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::cleanupClass() +bool LLViewerMediaImpl::canNavigateForward() { - stop() ; - LLMediaManager::cleanupClass(); + BOOL result = FALSE; + if (mMediaSource) + { + result = mMediaSource->getHistoryForwardAvailable(); + } + return result; } -// static -void LLViewerMedia::play(const std::string& media_url, - const std::string& mime_type, - const LLUUID& placeholder_texture_id, - S32 media_width, S32 media_height, U8 media_auto_scale, - U8 media_loop) +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::canNavigateBack() { - sViewerMediaImpl.play(media_url, mime_type, placeholder_texture_id, - media_width, media_height, media_auto_scale, media_loop); + BOOL result = FALSE; + if (mMediaSource) + { + result = mMediaSource->getHistoryBackAvailable(); + } + return result; } -// static -void LLViewerMedia::stop() + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::updateMovieImage(const LLUUID& uuid, BOOL active) { - sViewerMediaImpl.stop(); + // IF the media image hasn't changed, do nothing + if (mTextureId == uuid) + { + return; + } + // If we have changed media uuid, restore the old one + if (!mTextureId.isNull()) + { + LLViewerImage* oldImage = LLViewerImage::getImage( mTextureId ); + if (oldImage) + { + oldImage->reinit(mMovieImageHasMips); + oldImage->mIsMediaTexture = FALSE; + } + } + // If the movie is playing, set the new media image + if (active && !uuid.isNull()) + { + LLViewerImage* viewerImage = LLViewerImage::getImage( uuid ); + if( viewerImage ) + { + mTextureId = uuid; + // Can't use mipmaps for movies because they don't update the full image + mMovieImageHasMips = viewerImage->getUseMipMaps(); + viewerImage->reinit(FALSE); + viewerImage->mIsMediaTexture = TRUE; + } + } } -// static -void LLViewerMedia::pause() +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::update() { - sViewerMediaImpl.pause(); + if(mMediaSource == NULL) + { + return; + } + + mMediaSource->idle(); + + if(mMediaSource->isPluginExited()) + { + destroyMediaSource(); + return; + } + + if(!mMediaSource->textureValid()) + { + return; + } + + if(mSuspendUpdates || !mVisible) + { + return; + } + + LLViewerImage* placeholder_image = updatePlaceholderImage(); + + if(placeholder_image) + { + LLRect dirty_rect; + if(mMediaSource->getDirty(&dirty_rect)) + { + // Constrain the dirty rect to be inside the texture + S32 x_pos = llmax(dirty_rect.mLeft, 0); + S32 y_pos = llmax(dirty_rect.mBottom, 0); + S32 width = llmin(dirty_rect.mRight, placeholder_image->getWidth()) - x_pos; + S32 height = llmin(dirty_rect.mTop, placeholder_image->getHeight()) - y_pos; + + if(width > 0 && height > 0) + { + + U8* data = mMediaSource->getBitsData(); + + // Offset the pixels pointer to match x_pos and y_pos + data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() ); + data += ( y_pos * mMediaSource->getTextureDepth() ); + + placeholder_image->setSubImage( + data, + mMediaSource->getBitsWidth(), + mMediaSource->getBitsHeight(), + x_pos, + y_pos, + width, + height, + TRUE); // force a fast update (i.e. don't call analyzeAlpha, etc.) + + } + + mMediaSource->resetDirty(); + } + } } -// static -void LLViewerMedia::start() + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::updateImagesMediaStreams() { - sViewerMediaImpl.start(); } -// static -void LLViewerMedia::seek(F32 time) + +////////////////////////////////////////////////////////////////////////////////////////// +LLViewerImage* LLViewerMediaImpl::updatePlaceholderImage() { - sViewerMediaImpl.seek(time); + if(mTextureId.isNull()) + { + // The code that created this instance will read from the plugin's bits. + return NULL; + } + + LLViewerImage* placeholder_image = gImageList.getImage( mTextureId ); + + if (mNeedsNewTexture + || placeholder_image->getUseMipMaps() + || ! placeholder_image->mIsMediaTexture + || placeholder_image->getWidth() != mMediaSource->getTextureWidth() + || placeholder_image->getHeight() != mMediaSource->getTextureHeight()) + { + llinfos << "initializing media placeholder" << llendl; + llinfos << "movie image id " << mTextureId << llendl; + + int texture_width = mMediaSource->getTextureWidth(); + int texture_height = mMediaSource->getTextureHeight(); + int texture_depth = mMediaSource->getTextureDepth(); + + // MEDIAOPT: check to see if size actually changed before doing work + placeholder_image->destroyGLTexture(); + // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work? + placeholder_image->reinit(FALSE); // probably not needed + + // MEDIAOPT: seems insane that we actually have to make an imageraw then + // immediately discard it + LLPointer<LLImageRaw> raw = new LLImageRaw(texture_width, texture_height, texture_depth); + raw->clear(0x0f, 0x0f, 0x0f, 0xff); + int discard_level = 0; + + // ask media source for correct GL image format constants + placeholder_image->setExplicitFormat(mMediaSource->getTextureFormatInternal(), + mMediaSource->getTextureFormatPrimary(), + mMediaSource->getTextureFormatType(), + mMediaSource->getTextureFormatSwapBytes()); + + placeholder_image->createGLTexture(discard_level, raw); + + // placeholder_image->setExplicitFormat() + placeholder_image->setUseMipMaps(FALSE); + + // MEDIAOPT: set this dynamically on play/stop + placeholder_image->mIsMediaTexture = true; + mNeedsNewTexture = false; + } + + return placeholder_image; } -// static -void LLViewerMedia::setVolume(F32 volume) + +////////////////////////////////////////////////////////////////////////////////////////// +LLUUID LLViewerMediaImpl::getMediaTextureID() { - sViewerMediaImpl.setVolume(volume); + return mTextureId; } -// static -LLMediaBase::EStatus LLViewerMedia::getStatus() +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::setVisible(bool visible) { - return sViewerMediaImpl.getStatus(); + mVisible = visible; + + if(mVisible) + { + if(mMediaSource && mMediaSource->isPluginExited()) + { + destroyMediaSource(); + } + + if(!mMediaSource) + { + createMediaSource(); + } + } + + if(mMediaSource) + { + mMediaSource->setPriority(mVisible?LLPluginClassMedia::PRIORITY_NORMAL:LLPluginClassMedia::PRIORITY_HIDDEN); + } } ////////////////////////////////////////////////////////////////////////////////////////// -// static -LLUUID LLViewerMedia::getMediaTextureID() +void LLViewerMediaImpl::mouseCapture() { - return sViewerMediaImpl.getMediaTextureID(); + gFocusMgr.setMouseCapture(this); } ////////////////////////////////////////////////////////////////////////////////////////// -// static -bool LLViewerMedia::getMediaSize(S32 *media_width, S32 *media_height) +void LLViewerMediaImpl::getTextureSize(S32 *texture_width, S32 *texture_height) { - // make sure we're valid + if(mMediaSource && mMediaSource->textureValid()) + { + S32 real_texture_width = mMediaSource->getBitsWidth(); + S32 real_texture_height = mMediaSource->getBitsHeight(); - if ( sViewerMediaImpl.mMediaSource != NULL ) + { + // The "texture width" coming back from the plugin may not be a power of two (thanks to webkit). + // It will be the correct "data width" to pass to setSubImage + int i; + + for(i = 1; i < real_texture_width; i <<= 1) + ; + *texture_width = i; + + for(i = 1; i < real_texture_height; i <<= 1) + ; + *texture_height = i; + } + + } + else { - *media_width = sViewerMediaImpl.mMediaSource->getMediaWidth(); - *media_height = sViewerMediaImpl.mMediaSource->getMediaHeight(); - return true; + *texture_width = 0; + *texture_height = 0; } - return false; +} +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::scaleMouse(S32 *mouse_x, S32 *mouse_y) +{ +#if 0 + S32 media_width, media_height; + S32 texture_width, texture_height; + getMediaSize( &media_width, &media_height ); + getTextureSize( &texture_width, &texture_height ); + S32 y_delta = texture_height - media_height; + + *mouse_y -= y_delta; +#endif } ////////////////////////////////////////////////////////////////////////////////////////// -// static -bool LLViewerMedia::getTextureSize(S32 *texture_width, S32 *texture_height) +bool LLViewerMediaImpl::isMediaPlaying() { - if ( sViewerMediaImpl.mMediaSource != NULL ) + bool result = false; + + if(mMediaSource) { - S32 media_width = sViewerMediaImpl.mMediaSource->getMediaWidth(); - S32 media_height = sViewerMediaImpl.mMediaSource->getMediaHeight(); - *texture_width = LLMediaManager::textureWidthFromMediaWidth( media_width ); - *texture_height = LLMediaManager::textureHeightFromMediaHeight( media_height ); - return true; + EMediaStatus status = mMediaSource->getStatus(); + if(status == MEDIA_PLAYING || status == MEDIA_LOADING) + result = true; } - return false; + + return result; } +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::isMediaPaused() +{ + bool result = false; + if(mMediaSource) + { + if(mMediaSource->getStatus() == MEDIA_PAUSED) + result = true; + } + + return result; +} ////////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::updateImagesMediaStreams() +// +bool LLViewerMediaImpl::hasMedia() { - sViewerMediaImpl.updateImagesMediaStreams(); + return mMediaSource != NULL; } + ////////////////////////////////////////////////////////////////////////////////////////// -// static -bool LLViewerMedia::isMediaPlaying() +void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent event) { - LLMediaBase::EStatus status = sViewerMediaImpl.getStatus(); - return (status == LLMediaBase::STATUS_STARTED ); + switch(event) + { + case MEDIA_EVENT_PLUGIN_FAILED: + { + LLSD args; + args["PLUGIN"] = LLMIMETypes::implType(mMimeType); + LLNotifications::instance().add("MediaPluginFailed", args); + } + break; + default: + break; + } + // Just chain the event to observers. + emitEvent(self, event); } -////////////////////////////////////////////////////////////////////////////////////////// -// static -bool LLViewerMedia::isMediaPaused() + +//////////////////////////////////////////////////////////////////////////////// +// virtual +void +LLViewerMediaImpl::cut() { - LLMediaBase::EStatus status = sViewerMediaImpl.getStatus(); - return (status == LLMediaBase::STATUS_PAUSED); + if (mMediaSource) + mMediaSource->cut(); } -////////////////////////////////////////////////////////////////////////////////////////// -// static -bool LLViewerMedia::hasMedia() + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canCut() const { - return sViewerMediaImpl.mMediaSource != NULL; + if (mMediaSource) + return mMediaSource->canCut(); + else + return FALSE; } -////////////////////////////////////////////////////////////////////////////////////////// -//static -bool LLViewerMedia::isActiveMediaTexture(const LLUUID& id) +//////////////////////////////////////////////////////////////////////////////// +// virtual +void +LLViewerMediaImpl::copy() { - return (id.notNull() - && id == getMediaTextureID() - && isMediaPlaying()); + if (mMediaSource) + mMediaSource->copy(); } -////////////////////////////////////////////////////////////////////////////////////////// -// static -std::string LLViewerMedia::getMediaURL() +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canCopy() const { - return sViewerMediaImpl.mMediaURL; + if (mMediaSource) + return mMediaSource->canCopy(); + else + return FALSE; } -////////////////////////////////////////////////////////////////////////////////////////// -// static -std::string LLViewerMedia::getMimeType() + +//////////////////////////////////////////////////////////////////////////////// +// virtual +void +LLViewerMediaImpl::paste() { - return sViewerMediaImpl.mMimeType; + if (mMediaSource) + mMediaSource->paste(); } -////////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::setMimeType(std::string mime_type) + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canPaste() const { - sViewerMediaImpl.mMimeType = mime_type; + if (mMediaSource) + return mMediaSource->canPaste(); + else + return FALSE; } + diff --git a/linden/indra/newview/llviewermedia.h b/linden/indra/newview/llviewermedia.h index 600d740..afda426 100644 --- a/linden/indra/newview/llviewermedia.h +++ b/linden/indra/newview/llviewermedia.h @@ -33,50 +33,192 @@ #ifndef LLVIEWERMEDIA_H #define LLVIEWERMEDIA_H -#include "llmediabase.h" // for status codes +#include "llfocusmgr.h" -class LLMediaManagerData; +#include "llpanel.h" +#include "llpluginclassmediaowner.h" + +#include "llviewermediaobserver.h" + +class LLViewerMediaImpl; class LLUUID; +class LLViewerImage; + +typedef LLPointer<LLViewerMediaImpl> viewer_media_t; +/////////////////////////////////////////////////////////////////////////////// +// +class LLViewerMediaEventEmitter +{ +public: + virtual ~LLViewerMediaEventEmitter(); + + bool addObserver( LLViewerMediaObserver* subject ); + bool remObserver( LLViewerMediaObserver* subject ); + void emitEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent event); + +private: + typedef std::list< LLViewerMediaObserver* > observerListType; + observerListType mObservers; +}; class LLViewerMedia { + LOG_CLASS(LLViewerMedia); public: // Special case early init for just web browser component // so we can show login screen. See .cpp file for details. JC - static void initBrowser(); - static void initClass(); - static void cleanupClass(); + static viewer_media_t newMediaImpl(const std::string& media_url, + const LLUUID& texture_id, + S32 media_width, + S32 media_height, + U8 media_auto_scale, + U8 media_loop, + std::string mime_type = "none/none"); - static void play(const std::string& media_url, - const std::string& mime_type, - const LLUUID& placeholder_texture_id, - S32 media_width, S32 media_height, U8 media_auto_scale, - U8 media_loop); - static void stop(); - static void pause(); - static void start(); - static void seek(F32 time); + static void removeMedia(LLViewerMediaImpl* media); + static LLViewerMediaImpl* getMediaImplFromTextureID(const LLUUID& texture_id); + static std::string getCurrentUserAgent(); + static void updateBrowserUserAgent(); + static bool handleSkinCurrentChanged(const LLSD& /*newvalue*/); + static bool textureHasMedia(const LLUUID& texture_id); static void setVolume(F32 volume); - static LLMediaBase::EStatus getStatus(); - static LLUUID getMediaTextureID(); - static bool getMediaSize(S32 *media_width, S32 *media_height); - static bool getTextureSize(S32 *texture_width, S32 *texture_height); - static bool isMediaPlaying(); - static bool isMediaPaused(); - static bool hasMedia(); - static bool isActiveMediaTexture(const LLUUID& id); + static void updateMedia(); + + static void cleanupClass(); + +}; + +// Implementation functions not exported into header file +class LLViewerMediaImpl + : public LLMouseHandler, public LLRefCount, public LLPluginClassMediaOwner, public LLViewerMediaEventEmitter, public LLEditMenuHandler +{ + LOG_CLASS(LLViewerMediaImpl); +public: + + LLViewerMediaImpl(const std::string& media_url, + const LLUUID& texture_id, + S32 media_width, + S32 media_height, + U8 media_auto_scale, + U8 media_loop, + const std::string& mime_type); + + ~LLViewerMediaImpl(); + void createMediaSource(); + void destroyMediaSource(); + void setMediaType(const std::string& media_type); + bool initializeMedia(const std::string& mime_type); + bool initializePlugin(const std::string& media_type); + LLPluginClassMedia* getMediaPlugin() { return mMediaSource; } + void setSize(int width, int height); + + void play(); + void stop(); + void pause(); + void start(); + void seek(F32 time); + void setVolume(F32 volume); + void focus(bool focus); + void mouseDown(S32 x, S32 y); + void mouseUp(S32 x, S32 y); + void mouseMove(S32 x, S32 y); + void mouseLeftDoubleClick(S32 x,S32 y ); + void mouseCapture(); + + void navigateHome(); + void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false); + void navigateStop(); + bool handleKeyHere(KEY key, MASK mask); + bool handleUnicodeCharHere(llwchar uni_char); + bool canNavigateForward(); + bool canNavigateBack(); + std::string getMediaURL() { return mMediaURL; } + std::string getMediaHomeURL() { return mHomeURL; } + std::string getMimeType() { return mMimeType; } + void getTextureSize(S32 *texture_width, S32 *texture_height); + void scaleMouse(S32 *mouse_x, S32 *mouse_y); + + void update(); + void updateMovieImage(const LLUUID& image_id, BOOL active); + void updateImagesMediaStreams(); + LLUUID getMediaTextureID(); + + void suspendUpdates(bool suspend) { mSuspendUpdates = suspend; }; + void setVisible(bool visible); + + bool isMediaPlaying(); + bool isMediaPaused(); + bool hasMedia(); + + // utility function to create a ready-to-use media instance from a desired media type. + static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height); + + // Internally set our desired browser user agent string, including + // the Second Life version and skin name. Used because we can + // switch skins without restarting the app. + static void updateBrowserUserAgent(); + + // Callback for when the SkinCurrent control is changed to + // switch the user agent string to indicate the new skin. + static bool handleSkinCurrentChanged(const LLSD& newvalue); + + // need these to handle mouseup... + /*virtual*/ void onMouseCaptureLost(); + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + + // Grr... the only thing I want as an LLMouseHandler are the onMouseCaptureLost and handleMouseUp calls. + // Sadly, these are all pure virtual, so I have to supply implementations here: + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) { return FALSE; }; + /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE; }; + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; }; + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; + /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE; }; + /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) { return FALSE; }; + /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; + /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) {return FALSE; }; + /*virtual*/ const std::string& getName() const { return LLStringUtil::null; }; + /*virtual*/ BOOL isView() const { return FALSE; }; + /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {}; + /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const {}; + /*virtual*/ BOOL hasMouseCapture() { return gFocusMgr.getMouseCapture() == this; }; + + // Inherited from LLPluginClassMediaOwner + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent); + + // LLEditMenuHandler overrides + /*virtual*/ void cut(); + /*virtual*/ BOOL canCut() const; + + /*virtual*/ void copy(); + /*virtual*/ BOOL canCopy() const; - static std::string getMediaURL(); - static std::string getMimeType(); - static void setMimeType(std::string mime_type); + /*virtual*/ void paste(); + /*virtual*/ BOOL canPaste() const; + +public: + // a single media url with some data and an impl. + LLPluginClassMedia* mMediaSource; + LLUUID mTextureId; + bool mMovieImageHasMips; + std::string mMediaURL; + std::string mHomeURL; + std::string mMimeType; + S32 mLastMouseX; // save the last mouse coord we get, so when we lose capture we can simulate a mouseup at that point. + S32 mLastMouseY; + S32 mMediaWidth; + S32 mMediaHeight; + bool mMediaAutoScale; + bool mMediaLoop; + bool mNeedsNewTexture; + bool mSuspendUpdates; + bool mVisible; - static void updateImagesMediaStreams(); - private: - // Fill in initialization data for LLMediaManager::initClass() - static void buildMediaManagerData( LLMediaManagerData* init_data ); +private: + LLViewerImage *updatePlaceholderImage(); }; #endif // LLVIEWERMEDIA_H diff --git a/linden/indra/newview/llviewermedia_streamingaudio.cpp b/linden/indra/newview/llviewermedia_streamingaudio.cpp new file mode 100644 index 0000000..06946da --- /dev/null +++ b/linden/indra/newview/llviewermedia_streamingaudio.cpp @@ -0,0 +1,169 @@ +/** + * @file llviewermedia_streamingaudio.h + * @author Tofu Linden, Sam Kolb + * @brief LLStreamingAudio_MediaPlugins implementation - an implementation of the streaming audio interface which is implemented as a client of the media plugins API. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "linden_common.h" +#include "llpluginclassmedia.h" +#include "llviewermedia.h" + +#include "llviewermedia_streamingaudio.h" + +#include "llmimetypes.h" +#include "llvfs.h" +#include "lldir.h" + + +LLStreamingAudio_MediaPlugins::LLStreamingAudio_MediaPlugins() : + mMediaPlugin(NULL), + mGain(1.0) +{ + // nothing interesting to do? + // we will lazily create a media plugin at play-time, if none exists. +} + +LLStreamingAudio_MediaPlugins::~LLStreamingAudio_MediaPlugins() +{ + delete mMediaPlugin; + mMediaPlugin = NULL; +} + +void LLStreamingAudio_MediaPlugins::start(const std::string& url) +{ + if (!mMediaPlugin) // lazy-init the underlying media plugin + { + mMediaPlugin = initializeMedia("audio/mpeg"); // assumes that whatever media implementation supports mp3 also supports vorbis. + llinfos << "mMediaPlugin is now " << mMediaPlugin << llendl; + } + + if(!mMediaPlugin) + return; + + if (!url.empty()) { + llinfos << "Starting internet stream: " << url << llendl; + mURL = url; + mMediaPlugin->loadURI ( url ); + mMediaPlugin->start(); + llinfos << "Playing....." << llendl; + } else { + llinfos << "setting stream to NULL"<< llendl; + mURL.clear(); + mMediaPlugin->stop(); + } +} + +void LLStreamingAudio_MediaPlugins::stop() +{ + if(mMediaPlugin) + { + mMediaPlugin->stop(); + } + + mURL.clear(); +} + +void LLStreamingAudio_MediaPlugins::pause(int pause) +{ + if(!mMediaPlugin) + return; + + if(pause) + { + mMediaPlugin->pause(); + } + else + { + mMediaPlugin->start(); + } +} + +void LLStreamingAudio_MediaPlugins::update() +{ + if (mMediaPlugin) + mMediaPlugin->idle(); +} + +int LLStreamingAudio_MediaPlugins::isPlaying() +{ + if (!mMediaPlugin) + return 0; + + // *TODO: can probably do better than this + if (mMediaPlugin->isPluginRunning()) + { + return 1; // Active and playing + } + + if (mMediaPlugin->isPluginExited()) + { + return 0; // stopped + } + + return 2; // paused +} + +void LLStreamingAudio_MediaPlugins::setGain(F32 vol) +{ + mGain = vol; + + if(!mMediaPlugin) + return; + + vol = llclamp(vol, 0.f, 1.f); + mMediaPlugin->setVolume(vol); +} + +F32 LLStreamingAudio_MediaPlugins::getGain() +{ + return mGain; +} + +std::string LLStreamingAudio_MediaPlugins::getURL() +{ + return mURL; +} + +LLPluginClassMedia* LLStreamingAudio_MediaPlugins::initializeMedia(const std::string& media_type) +{ + LLPluginClassMediaOwner* owner = NULL; + S32 default_size = 1; // audio-only - be minimal, doesn't matter + LLPluginClassMedia* media_source = LLViewerMediaImpl::newSourceFromMediaType(media_type, owner, default_size, default_size); + + if (media_source) + { + media_source->setLoop(false); // audio streams are not expected to loop + } + + return media_source; +} + diff --git a/linden/indra/newview/llviewermedia_streamingaudio.h b/linden/indra/newview/llviewermedia_streamingaudio.h new file mode 100644 index 0000000..270bab7 --- /dev/null +++ b/linden/indra/newview/llviewermedia_streamingaudio.h @@ -0,0 +1,69 @@ +/** + * @file llviewermedia_streamingaudio.h + * @author Tofu Linden + * @brief Definition of LLStreamingAudio_MediaPlugins implementation - an implementation of the streaming audio interface which is implemented as a client of the media plugins API. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_VIEWERMEDIA_STREAMINGAUDIO_H +#define LL_VIEWERMEDIA_STREAMINGAUDIO_H + + +#include "stdtypes.h" // from llcommon + +#include "llstreamingaudio.h" + +class LLPluginClassMedia; + +class LLStreamingAudio_MediaPlugins : public LLStreamingAudioInterface +{ + public: + LLStreamingAudio_MediaPlugins(); + /*virtual*/ ~LLStreamingAudio_MediaPlugins(); + + /*virtual*/ void start(const std::string& url); + /*virtual*/ void stop(); + /*virtual*/ void pause(int pause); + /*virtual*/ void update(); + /*virtual*/ int isPlaying(); + /*virtual*/ void setGain(F32 vol); + /*virtual*/ F32 getGain(); + /*virtual*/ std::string getURL(); + +private: + LLPluginClassMedia* initializeMedia(const std::string& media_type); + + LLPluginClassMedia *mMediaPlugin; + + std::string mURL; + F32 mGain; +}; + + +#endif //LL_VIEWERMEDIA_STREAMINGAUDIO_H diff --git a/linden/indra/newview/llviewermediafocus.cpp b/linden/indra/newview/llviewermediafocus.cpp new file mode 100644 index 0000000..2e372a1 --- /dev/null +++ b/linden/indra/newview/llviewermediafocus.cpp @@ -0,0 +1,359 @@ +/** + * @file llviewermediafocus.cpp + * @brief Governs focus on Media prims + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llviewermediafocus.h" + +//LLViewerMediaFocus +#include "llviewerobjectlist.h" +#include "llpanelmediahud.h" +#include "llpluginclassmedia.h" +#include "llagent.h" +#include "lltoolpie.h" +#include "llviewercamera.h" +#include "llviewermedia.h" +#include "llhudview.h" +#include "lluictrlfactory.h" +#include "lldrawable.h" +#include "llparcel.h" +#include "llviewerparcelmgr.h" +#include "llweb.h" +// +// LLViewerMediaFocus +// + +LLViewerMediaFocus::LLViewerMediaFocus() +: mMouseOverFlag(false) +{ +} + +LLViewerMediaFocus::~LLViewerMediaFocus() +{ + // The destructor for LLSingletons happens at atexit() time, which is too late to do much. + // Clean up in cleanupClass() instead. +} + +void LLViewerMediaFocus::cleanupClass() +{ + LLViewerMediaFocus *self = LLViewerMediaFocus::getInstance(); + + if(self) + { + // mMediaHUD will have been deleted by this point -- don't try to delete it. + + /* Richard says: + all widgets are supposed to be destroyed at the same time + you shouldn't hold on to pointer to them outside of ui code + you can use the LLHandle approach + if you want to be type safe, you'll need to add a LLRootHandle to whatever derived class you are pointing to + look at llview::gethandle + its our version of a weak pointer + */ + if(self->mMediaHUD.get()) + { + self->mMediaHUD.get()->setMediaImpl(NULL); + } + self->mMediaImpl = NULL; + } + +} + + +void LLViewerMediaFocus::setFocusFace( BOOL b, LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl ) +{ + LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (b && media_impl.notNull()) + { + mMediaImpl = media_impl; + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->selectObjectOnly(objectp, face); + + mFocus = LLSelectMgr::getInstance()->getSelection(); + if(mMediaHUD.get() && ! parcel->getMediaPreventCameraZoom()) + { + mMediaHUD.get()->resetZoomLevel(); + mMediaHUD.get()->nextZoomLevel(); + } + if (!mFocus->isEmpty()) + { + gFocusMgr.setKeyboardFocus(this); + } + mObjectID = objectp->getID(); + // LLViewerMedia::addObserver(this, mObjectID); + + + } + else + { + gFocusMgr.setKeyboardFocus(NULL); + if(! parcel->getMediaPreventCameraZoom()) + { + if (!mFocus->isEmpty()) + { + gAgent.setFocusOnAvatar(TRUE, ANIMATE); + } + } + mFocus = NULL; + // LLViewerMedia::remObserver(this, mObjectID); + + // Null out the media hud media pointer + if(mMediaHUD.get()) + { + mMediaHUD.get()->setMediaImpl(NULL); + } + + // and null out the media impl + mMediaImpl = NULL; + } + if(mMediaHUD.get()) + { + mMediaHUD.get()->setMediaFocus(b); + } +} +bool LLViewerMediaFocus::getFocus() +{ + if (gFocusMgr.getKeyboardFocus() == this) + { + return true; + } + return false; +} + +// This function selects an ideal viewing distance given a selection bounding box, normal, and padding value +void LLViewerMediaFocus::setCameraZoom(F32 padding_factor) +{ + LLPickInfo& pick = LLToolPie::getInstance()->getPick(); + + if(LLSelectMgr::getInstance()->getSelection()->isEmpty()) + { + pick = mPickInfo; + setFocusFace(true, pick.getObject(), pick.mObjectFace, mMediaImpl); + } + + if (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) + { + gAgent.setFocusOnAvatar(FALSE, ANIMATE); + + LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); + F32 height; + F32 width; + F32 depth; + F32 angle_of_view; + F32 distance; + + // We need the aspect ratio, and the 3 components of the bbox as height, width, and depth. + F32 aspect_ratio = getBBoxAspectRatio(selection_bbox, pick.mNormal, &height, &width, &depth); + F32 camera_aspect = LLViewerCamera::getInstance()->getAspect(); + + // We will normally use the side of the volume aligned with the short side of the screen (i.e. the height for + // a screen in a landscape aspect ratio), however there is an edge case where the aspect ratio of the object is + // more extreme than the screen. In this case we invert the logic, using the longer component of both the object + // and the screen. + bool invert = (camera_aspect > 1.0f && aspect_ratio > camera_aspect) || + (camera_aspect < 1.0f && aspect_ratio < camera_aspect); + + // To calculate the optimum viewing distance we will need the angle of the shorter side of the view rectangle. + // In portrait mode this is the width, and in landscape it is the height. + // We then calculate the distance based on the corresponding side of the object bbox (width for portrait, height for landscape) + // We will add half the depth of the bounding box, as the distance projection uses the center point of the bbox. + if(camera_aspect < 1.0f || invert) + { + angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect()); + distance = width * 0.5 * padding_factor / tan(angle_of_view * 0.5f ); + } + else + { + angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getView()); + distance = height * 0.5 * padding_factor / tan(angle_of_view * 0.5f ); + } + + distance += depth * 0.5; + + // Finally animate the camera to this new position and focal point + gAgent.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(pick.mNormal * distance), + LLSelectMgr::getInstance()->getSelectionCenterGlobal(), LLSelectMgr::getInstance()->getSelection()->getFirstObject()->mID ); + } +} +void LLViewerMediaFocus::onFocusReceived() +{ + if(mMediaImpl.notNull()) + mMediaImpl->focus(true); + + LLFocusableElement::onFocusReceived(); +} + +void LLViewerMediaFocus::onFocusLost() +{ + if(mMediaImpl.notNull()) + mMediaImpl->focus(false); + gViewerWindow->focusClient(); + mFocus = NULL; + LLFocusableElement::onFocusLost(); +} +void LLViewerMediaFocus::setMouseOverFlag(bool b, viewer_media_t media_impl) +{ + if (b && media_impl.notNull()) + { + if(! mMediaHUD.get()) + { + LLPanelMediaHUD* media_hud = new LLPanelMediaHUD(mMediaImpl); + mMediaHUD = media_hud->getHandle(); + gHUDView->addChild(media_hud); + } + mMediaHUD.get()->setMediaImpl(media_impl); + mMediaImpl = media_impl; + } + mMouseOverFlag = b; +} +LLUUID LLViewerMediaFocus::getSelectedUUID() +{ + LLViewerObject* object = mFocus->getFirstObject(); + return object ? object->getID() : LLUUID::null; +} +#if 0 // Must re-implement when the new media api event system is ready +void LLViewerMediaFocus::onNavigateComplete( const EventType& event_in ) +{ + if (hasFocus() && mLastURL != event_in.getStringValue()) + { + LLViewerMedia::focus(true, mObjectID); + // spoof mouse event to reassert focus + LLViewerMedia::mouseDown(1,1, mObjectID); + LLViewerMedia::mouseUp(1,1, mObjectID); + } + mLastURL = event_in.getStringValue(); +} +#endif +BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ + if(mMediaImpl.notNull()) + mMediaImpl->handleKeyHere(key, mask); + return true; +} + +BOOL LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) +{ + if(mMediaImpl.notNull()) + mMediaImpl->handleUnicodeCharHere(uni_char); + return true; +} +BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks) +{ + BOOL retval = FALSE; + if(mFocus.notNull() && mMediaImpl.notNull() && mMediaImpl->hasMedia()) + { + mMediaImpl->getMediaPlugin()->scrollEvent(x, y, clicks); + retval = TRUE; + } + return retval; +} + +void LLViewerMediaFocus::update() +{ + if (mMediaHUD.get()) + { + if(mFocus.notNull() || mMouseOverFlag || mMediaHUD.get()->isMouseOver()) + { + // mMediaHUD.get()->setVisible(true); + mMediaHUD.get()->updateShape(); + } + else + { + mMediaHUD.get()->setVisible(false); + } + } +} +// This function calculates the aspect ratio and the world aligned components of a selection bounding box. +F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth) +{ + // Convert the selection normal and an up vector to local coordinate space of the bbox + LLVector3 local_normal = bbox.agentToLocalBasis(normal); + LLVector3 z_vec = bbox.agentToLocalBasis(LLVector3(0.0f, 0.0f, 1.0f)); + + LLVector3 comp1(0.f,0.f,0.f); + LLVector3 comp2(0.f,0.f,0.f); + LLVector3 bbox_max = bbox.getExtentLocal(); + F32 dot1 = 0.f; + F32 dot2 = 0.f; + + // The largest component of the localized normal vector is the depth component + // meaning that the other two are the legs of the rectangle. + local_normal.abs(); + if(local_normal.mV[VX] > local_normal.mV[VY]) + { + if(local_normal.mV[VX] > local_normal.mV[VZ]) + { + // Use the y and z comps + comp1.mV[VY] = bbox_max.mV[VY]; + comp2.mV[VZ] = bbox_max.mV[VZ]; + *depth = bbox_max.mV[VX]; + } + else + { + // Use the x and y comps + comp1.mV[VY] = bbox_max.mV[VY]; + comp2.mV[VZ] = bbox_max.mV[VZ]; + *depth = bbox_max.mV[VZ]; + } + } + else if(local_normal.mV[VY] > local_normal.mV[VZ]) + { + // Use the x and z comps + comp1.mV[VX] = bbox_max.mV[VX]; + comp2.mV[VZ] = bbox_max.mV[VZ]; + *depth = bbox_max.mV[VY]; + } + else + { + // Use the x and y comps + comp1.mV[VY] = bbox_max.mV[VY]; + comp2.mV[VZ] = bbox_max.mV[VZ]; + *depth = bbox_max.mV[VX]; + } + + // The height is the vector closest to vertical in the bbox coordinate space (highest dot product value) + dot1 = comp1 * z_vec; + dot2 = comp2 * z_vec; + if(fabs(dot1) > fabs(dot2)) + { + *height = comp1.length(); + *width = comp2.length(); + } + else + { + *height = comp2.length(); + *width = comp1.length(); + } + + // Return the aspect ratio. + return *width / *height; +} diff --git a/linden/indra/newview/llviewermediafocus.h b/linden/indra/newview/llviewermediafocus.h new file mode 100644 index 0000000..ed9597e --- /dev/null +++ b/linden/indra/newview/llviewermediafocus.h @@ -0,0 +1,91 @@ +/** + * @file llpanelmsgs.h + * @brief Message popup preferences panel + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_VIEWERMEDIAFOCUS_H +#define LL_VIEWERMEDIAFOCUS_H + +// includes for LLViewerMediaFocus +#include "llfocusmgr.h" +#include "llviewermedia.h" +#include "llviewerobject.h" +#include "llviewerwindow.h" +#include "llselectmgr.h" + +class LLViewerMediaImpl; +class LLPanelMediaHUD; + +class LLViewerMediaFocus : + public LLFocusableElement, + public LLSingleton<LLViewerMediaFocus> +{ +public: + LLViewerMediaFocus(); + ~LLViewerMediaFocus(); + + static void cleanupClass(); + + void setFocusFace(BOOL b, LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl); + void clearFocus() { setFocusFace(false, NULL, 0, NULL); } + /*virtual*/ bool getFocus(); + /*virtual*/ // void onNavigateComplete( const EventType& event_in ); + + /*virtual*/ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + /*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); + BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); + + LLUUID getSelectedUUID(); + LLObjectSelectionHandle getSelection() { return mFocus; } + + void update(); + + void setCameraZoom(F32 padding_factor); + void setMouseOverFlag(bool b, viewer_media_t media_impl = NULL); + bool getMouseOverFlag() { return mMouseOverFlag; } + void setPickInfo(LLPickInfo pick_info) { mPickInfo = pick_info; } + F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth); + +protected: + /*virtual*/ void onFocusReceived(); + /*virtual*/ void onFocusLost(); + +private: + LLObjectSelectionHandle mFocus; + std::string mLastURL; + bool mMouseOverFlag; + LLPickInfo mPickInfo; + LLHandle<LLPanelMediaHUD> mMediaHUD; + LLUUID mObjectID; + viewer_media_t mMediaImpl; +}; + + +#endif // LL_VIEWERMEDIAFOCUS_H diff --git a/linden/indra/newview/llviewermediaobserver.h b/linden/indra/newview/llviewermediaobserver.h new file mode 100644 index 0000000..6667f98 --- /dev/null +++ b/linden/indra/newview/llviewermediaobserver.h @@ -0,0 +1,71 @@ +/** + * @file llviewermediaobserver.h + * @brief Methods to override to catch events from LLViewerMedia class + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LLVIEWERMEDIAOBSERVER_H +#define LLVIEWERMEDIAOBSERVER_H + +#include "llpluginclassmediaowner.h" + +class LLViewerMediaEventEmitter; + +class LLViewerMediaObserver : public LLPluginClassMediaOwner +{ +public: + virtual ~LLViewerMediaObserver(); + +private: + // Emitters will manage this list in addObserver/remObserver. + friend class LLViewerMediaEventEmitter; + std::list<LLViewerMediaEventEmitter *> mEmitters; +}; + + +#if 0 + // Classes that inherit from LLViewerMediaObserver should add this to their class declaration: + + // inherited from LLViewerMediaObserver + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + + /* and will probably need to add this to their cpp file: + + #include "llpluginclassmedia.h" + + */ + + // The list of events is in llpluginclassmediaowner.h + + +#endif + + +#endif // LLVIEWERMEDIAOBSERVER_H + diff --git a/linden/indra/newview/llviewermenu.cpp b/linden/indra/newview/llviewermenu.cpp index fd6e842..7266dbc 100644 --- a/linden/indra/newview/llviewermenu.cpp +++ b/linden/indra/newview/llviewermenu.cpp @@ -40,7 +40,7 @@ #include <sstream> // linden library includes -#include "audioengine.h" +#include "llaudioengine.h" #include "indra_constants.h" #include "llassetstorage.h" #include "llchat.h" @@ -111,9 +111,8 @@ #include "llfloatergroupinfo.h" #include "llfloatergroupinvite.h" #include "llfloatergroups.h" -#include "llfloaterhtml.h" #include "llfloaterhtmlcurrency.h" -#include "llfloaterhtmlhelp.h" // gViewerHtmlHelp +#include "llfloatermediabrowser.h" // gViewerHtmlHelp #include "llfloaterhtmlsimple.h" #include "llfloaterhud.h" #include "llfloaterinspect.h" @@ -158,6 +157,7 @@ #include "lllineeditor.h" #include "llmenucommands.h" #include "llmenugl.h" +#include "llmimetypes.h" #include "llmorphview.h" #include "llmoveview.h" #include "llmutelist.h" @@ -934,6 +934,14 @@ void init_client_menu(LLMenuGL* menu) menu->appendMenu( sub ); sub->createJumpKeys(); } + { + LLMenuGL* sub = NULL; + sub = new LLMenuGL("Media"); + sub->append(new LLMenuItemCallGL("Reload MIME types", &LLMIMETypes::reload)); + sub->append(new LLMenuItemCallGL("Web Browser Test", &handle_web_browser_test)); + menu->appendMenu( sub ); + sub->createJumpKeys(); + } menu->appendSeparator(); @@ -1063,6 +1071,7 @@ void init_debug_ui_menu(LLMenuGL* menu) menu->appendSeparator(); menu->append(new LLMenuItemCallGL("Web Browser Test", &handle_web_browser_test)); + // commented out until work is complete: DEV-32268 // menu->append(new LLMenuItemCallGL("Buy Currency Test", &handle_buy_currency_test)); menu->append(new LLMenuItemCallGL("Editable UI", &edit_ui)); @@ -5493,6 +5502,7 @@ class LLWorldSetAway : public view_listener_t if (gAgent.getAFK()) { gAgent.clearAFK(); + llinfos << "Spawning HTML help window" << llendl; } else { @@ -6045,10 +6055,10 @@ class LLShowFloater : public view_listener_t { JCFloaterAnimList::toggleInstance(LLSD()); } - else if (floater_name == "inworld browser") - { - LLFloaterMediaBrowser::toggleInstance(LLSD()); - } +//imprudence fixme else if (floater_name == "inworld browser") +// { +// LLFloaterMediaBrowser::toggle(); +// } else if (floater_name == "beacons") { LLFloaterBeacons::toggleInstance(LLSD()); @@ -7844,7 +7854,7 @@ void handle_grab_texture(void* data) // user know that the image is now in inventory. if(view) { - LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); + LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus(); view->getPanel()->setSelection(item_id, TAKE_FOCUS_NO); view->getPanel()->openSelected(); @@ -8048,13 +8058,7 @@ void handle_load_from_xml(void*) void handle_web_browser_test(void*) { - const bool open_links_externally = false; - const bool open_app_slurls = true; - LLFloaterHtml::getInstance()->show( - "http://secondlife.com/app/search/slurls.html", - "Web Browser Test", - open_links_externally, - open_app_slurls); + LLWeb::loadURL("http://secondlife.com/app/search/slurls.html"); } void handle_buy_currency_test(void*) diff --git a/linden/indra/newview/llviewermenufile.cpp b/linden/indra/newview/llviewermenufile.cpp index 364dcfd..d3473df 100644 --- a/linden/indra/newview/llviewermenufile.cpp +++ b/linden/indra/newview/llviewermenufile.cpp @@ -66,7 +66,7 @@ #include "llstring.h" #include "lltransactiontypes.h" #include "lluuid.h" -#include "vorbisencode.h" +#include "llvorbisencode.h" // system libraries #include <boost/tokenizer.hpp> diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp index bfd1045..9f6ae3d 100755 --- a/linden/indra/newview/llviewermessage.cpp +++ b/linden/indra/newview/llviewermessage.cpp @@ -37,7 +37,7 @@ #include <deque> -#include "audioengine.h" +#include "llaudioengine.h" #include "indra_constants.h" #include "lscript_byteformat.h" #include "mean_collision_data.h" @@ -972,7 +972,7 @@ void open_offer(const std::vector<LLUUID>& items, const std::string& from_name) LL_DEBUGS("Messaging") << "Highlighting" << item->getUUID() << LL_ENDL; //highlight item - LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); + LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus(); view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO); gFocusMgr.setKeyboardFocus(focus_ctrl); } @@ -5197,11 +5197,11 @@ void mean_name_callback(const LLUUID &id, const std::string& first, const std::s return; } - static const int max_collision_list_size = 20; + static const U32 max_collision_list_size = 20; if (gMeanCollisionList.size() > max_collision_list_size) { mean_collision_list_t::iterator iter = gMeanCollisionList.begin(); - for (S32 i=0; i<max_collision_list_size; i++) iter++; + for (U32 i=0; i<max_collision_list_size; i++) iter++; for_each(iter, gMeanCollisionList.end(), DeletePointer()); gMeanCollisionList.erase(iter, gMeanCollisionList.end()); } diff --git a/linden/indra/newview/llviewerobject.cpp b/linden/indra/newview/llviewerobject.cpp index a854583..b40d4e0 100644 --- a/linden/indra/newview/llviewerobject.cpp +++ b/linden/indra/newview/llviewerobject.cpp @@ -34,7 +34,7 @@ #include "llviewerobject.h" -#include "audioengine.h" +#include "llaudioengine.h" #include "imageids.h" #include "indra_constants.h" #include "llmath.h" diff --git a/linden/indra/newview/llviewerparcelmedia.cpp b/linden/indra/newview/llviewerparcelmedia.cpp index b98f418..c7f0c4b 100644 --- a/linden/indra/newview/llviewerparcelmedia.cpp +++ b/linden/indra/newview/llviewerparcelmedia.cpp @@ -41,47 +41,22 @@ #include "llviewerparcelmgr.h" #include "lluuid.h" #include "message.h" +#include "llviewermediafocus.h" #include "llviewerparcelmediaautoplay.h" #include "llviewerwindow.h" #include "llfirstuse.h" +#include "llpluginclassmedia.h" // Static Variables S32 LLViewerParcelMedia::sMediaParcelLocalID = 0; LLUUID LLViewerParcelMedia::sMediaRegionID; +viewer_media_t LLViewerParcelMedia::sMediaImpl; + // Local functions bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel); -// Move this to its own file. -// helper class that tries to download a URL from a web site and calls a method -// on the Panel Land Media and to discover the MIME type -class LLMimeDiscoveryResponder : public LLHTTPClient::Responder -{ -public: - LLMimeDiscoveryResponder( ) - {} - - - - virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content) - { - std::string media_type = content["content-type"].asString(); - std::string::size_type idx1 = media_type.find_first_of(";"); - std::string mime_type = media_type.substr(0, idx1); - completeAny(status, mime_type); - } - - virtual void error( U32 status, const std::string& reason ) - { - completeAny(status, "none/none"); - } - - void completeAny(U32 status, const std::string& mime_type) - { - LLViewerMedia::setMimeType(mime_type); - } -}; // static void LLViewerParcelMedia::initClass() @@ -92,6 +67,13 @@ void LLViewerParcelMedia::initClass() LLViewerParcelMediaAutoPlay::initClass(); } +//static +void LLViewerParcelMedia::cleanupClass() +{ + // This needs to be destroyed before global destructor time. + sMediaImpl = NULL; +} + ////////////////////////////////////////////////////////////////////////////////////////// // static void LLViewerParcelMedia::update(LLParcel* parcel) @@ -105,6 +87,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel) { sMediaRegionID = LLUUID() ; stop() ; + LL_DEBUGS("Media") << "no agent region, bailing out." << LL_ENDL; return ; } @@ -115,64 +98,54 @@ void LLViewerParcelMedia::update(LLParcel* parcel) LLUUID regionid = gAgent.getRegion()->getRegionID(); if (parcelid != sMediaParcelLocalID || regionid != sMediaRegionID) { + LL_DEBUGS("Media") << "New parcel, parcel id = " << parcelid << ", region id = " << regionid << LL_ENDL; sMediaParcelLocalID = parcelid; sMediaRegionID = regionid; new_parcel = true; } std::string mediaUrl = std::string ( parcel->getMediaURL () ); + std::string mediaCurrentUrl = std::string( parcel->getMediaCurrentURL()); + + // First use warning + if( ! mediaUrl.empty() && gSavedSettings.getWarning("FirstStreamingVideo") ) + { + LLNotifications::instance().add("ParcelCanPlayMedia", LLSD(), LLSD(), + boost::bind(callback_play_media, _1, _2, parcel)); + return; + + } + + // if we have a current (link sharing) url, use it instead + if (mediaCurrentUrl != "" && parcel->getMediaType() == "text/html") + { + mediaUrl = mediaCurrentUrl; + } + LLStringUtil::trim(mediaUrl); + + // If no parcel media is playing, nothing left to do + if(sMediaImpl.isNull()) - // has something changed? - if ( ( LLViewerMedia::getMediaURL() != mediaUrl ) - || ( LLViewerMedia::getMediaTextureID() != parcel->getMediaID () ) ) { - bool video_was_playing = FALSE; - bool same_media_id = LLViewerMedia::getMediaTextureID() == parcel->getMediaID (); + return; + } - if (LLViewerMedia::isMediaPlaying()) + // Media is playing...has something changed? + else if (( sMediaImpl->getMediaURL() != mediaUrl ) + || ( sMediaImpl->getMediaTextureID() != parcel->getMediaID() ) + || ( sMediaImpl->getMimeType() != parcel->getMediaType() )) + { + // Only play if the media types are the same. + if(sMediaImpl->getMimeType() == parcel->getMediaType()) { - video_was_playing = TRUE; + play(parcel); } - if ( !mediaUrl.empty() && same_media_id && ! new_parcel) - { - // Someone has "changed the channel", changing the URL of a video - // you were already watching. Automatically play provided the texture ID is the same - if (video_was_playing) - { - // Poke the mime type in before calling play. - // This is necessary because in this instance we are not waiting - // for the results of a header curl. In order to change the channel - // a mime type MUST be provided. - LLViewerMedia::setMimeType(parcel->getMediaType()); - play(parcel); - } - } else { stop(); } - - // Discover the MIME type - // Disabled for the time being. Get the mime type from the parcel. - if(gSavedSettings.getBOOL("AutoMimeDiscovery")) - { - LLHTTPClient::getHeaderOnly( mediaUrl, new LLMimeDiscoveryResponder()); - } - else - { - LLViewerMedia::setMimeType(parcel->getMediaType()); - } - - // First use warning - if( gSavedSettings.getWarning("FirstStreamingVideo") ) - { - LLNotifications::instance().add("ParcelCanPlayMedia", LLSD(), LLSD(), - boost::bind(callback_play_media, _1, _2, parcel)); - - } - } } else @@ -183,7 +156,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel) /* else { - // no audio player, do a first use dialog if their is media here + // no audio player, do a first use dialog if there is media here if (parcel) { std::string mediaUrl = std::string ( parcel->getMediaURL () ); @@ -212,15 +185,54 @@ void LLViewerParcelMedia::play(LLParcel* parcel) return; std::string media_url = parcel->getMediaURL(); + std::string media_current_url = parcel->getMediaCurrentURL(); std::string mime_type = parcel->getMediaType(); LLUUID placeholder_texture_id = parcel->getMediaID(); U8 media_auto_scale = parcel->getMediaAutoScale(); U8 media_loop = parcel->getMediaLoop(); S32 media_width = parcel->getMediaWidth(); S32 media_height = parcel->getMediaHeight(); - LLViewerMedia::play(media_url, mime_type, placeholder_texture_id, - media_width, media_height, media_auto_scale, - media_loop); + + if(sMediaImpl) + { + // If the url and mime type are the same, call play again + if(sMediaImpl->getMediaURL() == media_url + && sMediaImpl->getMimeType() == mime_type + && sMediaImpl->getMediaTextureID() == placeholder_texture_id) + { + LL_DEBUGS("Media") << "playing with existing url " << media_url << LL_ENDL; + + sMediaImpl->play(); + } + // Else if the texture id's are the same, navigate and rediscover type + // MBW -- This causes other state from the previous parcel (texture size, autoscale, and looping) to get re-used incorrectly. + // It's also not really necessary -- just creating a new instance is fine. +// else if(sMediaImpl->getMediaTextureID() == placeholder_texture_id) +// { +// sMediaImpl->navigateTo(media_url, mime_type, true); +// } + else + { + // Since the texture id is different, we need to generate a new impl + LL_DEBUGS("Media") << "new media impl with mime type " << mime_type << ", url " << media_url << LL_ENDL; + + // Delete the old one first so they don't fight over the texture. + sMediaImpl->stop(); + + sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id, + media_width, media_height, media_auto_scale, + media_loop); + } + } + else + { + // There is no media impl, make a new one + sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id, + media_width, media_height, media_auto_scale, + media_loop); + } + + LLFirstUse::useMedia(); LLViewerParcelMediaAutoPlay::playStarted(); @@ -229,20 +241,38 @@ void LLViewerParcelMedia::play(LLParcel* parcel) // static void LLViewerParcelMedia::stop() { + if(sMediaImpl.isNull()) + { + return; + } + + // We need to remove the media HUD if it is up. + LLViewerMediaFocus::getInstance()->clearFocus(); - LLViewerMedia::stop(); + // This will kill the media instance. + sMediaImpl->stop(); + sMediaImpl = NULL; } // static void LLViewerParcelMedia::pause() { - LLViewerMedia::pause(); + if(sMediaImpl.isNull()) + { + return; + } + sMediaImpl->pause(); } // static void LLViewerParcelMedia::start() { - LLViewerMedia::start(); + if(sMediaImpl.isNull()) + { + return; + } + sMediaImpl->start(); + LLFirstUse::useMedia(); LLViewerParcelMediaAutoPlay::playStarted(); @@ -251,16 +281,41 @@ void LLViewerParcelMedia::start() // static void LLViewerParcelMedia::seek(F32 time) { - LLViewerMedia::seek(time); + if(sMediaImpl.isNull()) + { + return; + } + sMediaImpl->seek(time); } - // static -LLMediaBase::EStatus LLViewerParcelMedia::getStatus() +void LLViewerParcelMedia::focus(bool focus) { - return LLViewerMedia::getStatus(); + sMediaImpl->focus(focus); +} + +// static +LLViewerMediaImpl::EMediaStatus LLViewerParcelMedia::getStatus() +{ + LLViewerMediaImpl::EMediaStatus result = LLViewerMediaImpl::MEDIA_NONE; + + if(sMediaImpl.notNull() && sMediaImpl->hasMedia()) + { + result = sMediaImpl->getMediaPlugin()->getStatus(); + } + + return result; } +// static +std::string LLViewerParcelMedia::getMimeType() +{ + return sMediaImpl.notNull() ? sMediaImpl->getMimeType() : "none/none"; +} +viewer_media_t LLViewerParcelMedia::getParcelMedia() +{ + return sMediaImpl; +} ////////////////////////////////////////////////////////////////////////////////////////// // static void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg, void ** ) @@ -298,7 +353,7 @@ void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg if(( command == PARCEL_MEDIA_COMMAND_PLAY ) || ( command == PARCEL_MEDIA_COMMAND_LOOP )) { - if (LLViewerMedia::isMediaPaused()) + if (getStatus() == LLViewerMediaImpl::MEDIA_PAUSED) { start(); } @@ -318,7 +373,7 @@ void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg if (flags & (1<<PARCEL_MEDIA_COMMAND_TIME)) { - if(! LLViewerMedia::hasMedia()) + if(sMediaImpl.isNull()) { LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); play(parcel); @@ -382,6 +437,119 @@ void LLViewerParcelMedia::processParcelMediaUpdate( LLMessageSystem *msg, void * } } } +// Static +///////////////////////////////////////////////////////////////////////////////////////// +void LLViewerParcelMedia::sendMediaNavigateMessage(const std::string& url) +{ + std::string region_url = gAgent.getRegion()->getCapability("ParcelNavigateMedia"); + if (!region_url.empty()) + { + // send navigate event to sim for link sharing + LLSD body; + body["agent-id"] = gAgent.getID(); + body["local-id"] = LLViewerParcelMgr::getInstance()->getAgentParcel()->getLocalID(); + body["url"] = url; + LLHTTPClient::post(region_url, body, new LLHTTPClient::Responder); + } + else + { + llwarns << "can't get ParcelNavigateMedia capability" << llendl; + } + +} + +///////////////////////////////////////////////////////////////////////////////////////// +// inherited from LLViewerMediaObserver +// virtual +void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ + switch(event) + { + case MEDIA_EVENT_CONTENT_UPDATED: + { + // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL; + }; + break; + + case MEDIA_EVENT_TIME_DURATION_UPDATED: + { + // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << LL_ENDL; + }; + break; + + case MEDIA_EVENT_SIZE_CHANGED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_SIZE_CHANGED " << LL_ENDL; + }; + break; + + case MEDIA_EVENT_CURSOR_CHANGED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL; + }; + break; + + case MEDIA_EVENT_NAVIGATE_BEGIN: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN " << LL_ENDL; + }; + break; + + case MEDIA_EVENT_NAVIGATE_COMPLETE: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL; + }; + break; + + case MEDIA_EVENT_PROGRESS_UPDATED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << LL_ENDL; + }; + break; + + case MEDIA_EVENT_STATUS_TEXT_CHANGED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << LL_ENDL; + }; + break; + + case MEDIA_EVENT_LOCATION_CHANGED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << LL_ENDL; + }; + break; + + case MEDIA_EVENT_CLICK_LINK_HREF: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL; + }; + break; + + case MEDIA_EVENT_CLICK_LINK_NOFOLLOW: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL; + }; + break; + + case MEDIA_EVENT_PLUGIN_FAILED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL; + }; + break; + + case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL; + }; + break; + + case MEDIA_EVENT_NAME_CHANGED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAME_CHANGED" << LL_ENDL; + }; + break; + }; +} bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel) { @@ -399,3 +567,19 @@ bool callback_play_media(const LLSD& notification, const LLSD& response, LLParce return false; } +// TODO: observer +/* +void LLViewerParcelMediaNavigationObserver::onNavigateComplete( const EventType& event_in ) +{ + std::string url = event_in.getStringValue(); + + if (mCurrentURL != url && ! mFromMessage) + { + LLViewerParcelMedia::sendMediaNavigateMessage(url); + } + + mCurrentURL = url; + mFromMessage = false; + +} +*/ diff --git a/linden/indra/newview/llviewerparcelmedia.h b/linden/indra/newview/llviewerparcelmedia.h index 1898870..0f1e85c 100644 --- a/linden/indra/newview/llviewerparcelmedia.h +++ b/linden/indra/newview/llviewerparcelmedia.h @@ -33,18 +33,22 @@ #ifndef LLVIEWERPARCELMEDIA_H #define LLVIEWERPARCELMEDIA_H -#include "llmediabase.h" +#include "llviewermedia.h" class LLMessageSystem; class LLParcel; +class LLViewerParcelMediaNavigationObserver; + // This class understands land parcels, network traffic, LSL media // transport commands, and talks to the LLViewerMedia class to actually // do playback. It allows us to remove code from LLViewerParcelMgr. -class LLViewerParcelMedia +class LLViewerParcelMedia : public LLViewerMediaObserver { + LOG_CLASS(LLViewerParcelMedia); public: static void initClass(); + static void cleanupClass(); static void update(LLParcel* parcel); // called when the agent's parcel has a new URL, or the agent has @@ -60,17 +64,38 @@ class LLViewerParcelMedia static void start(); // restart after pause - no need for all the setup + static void focus(bool focus); + static void seek(F32 time); // jump to timecode time - static LLMediaBase::EStatus getStatus(); + static LLViewerMediaImpl::EMediaStatus getStatus(); + static std::string getMimeType(); + static viewer_media_t getParcelMedia(); static void processParcelMediaCommandMessage( LLMessageSystem *msg, void ** ); static void processParcelMediaUpdate( LLMessageSystem *msg, void ** ); + static void sendMediaNavigateMessage(const std::string& url); + + // inherited from LLViewerMediaObserver + virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); public: static S32 sMediaParcelLocalID; static LLUUID sMediaRegionID; + // HACK: this will change with Media on a Prim + static viewer_media_t sMediaImpl; +}; + + +class LLViewerParcelMediaNavigationObserver +{ +public: + std::string mCurrentURL; + bool mFromMessage; + + // void onNavigateComplete( const EventType& event_in ); + }; #endif diff --git a/linden/indra/newview/llviewerparcelmediaautoplay.cpp b/linden/indra/newview/llviewerparcelmediaautoplay.cpp index dbb9c32..ccd6b14 100644 --- a/linden/indra/newview/llviewerparcelmediaautoplay.cpp +++ b/linden/indra/newview/llviewerparcelmediaautoplay.cpp @@ -109,7 +109,7 @@ BOOL LLViewerParcelMediaAutoPlay::tick() if ((!mPlayed) && // if we've never played (mTimeInParcel > AUTOPLAY_TIME) && // and if we've been here for so many seconds (this_media_url.size() != 0) && // and if the parcel has media - (!LLViewerMedia::isMediaPlaying())) // and if the media is not already playing + (LLViewerParcelMedia::sMediaImpl.isNull())) // and if the media is not already playing { if (this_media_texture_id.notNull()) // and if the media texture is good { diff --git a/linden/indra/newview/llviewerparcelmediaautoplay.h b/linden/indra/newview/llviewerparcelmediaautoplay.h index cc2e70b..16279e7 100644 --- a/linden/indra/newview/llviewerparcelmediaautoplay.h +++ b/linden/indra/newview/llviewerparcelmediaautoplay.h @@ -33,7 +33,6 @@ #ifndef LLVIEWERPARCELMEDIAAUTOPLAY_H #define LLVIEWERPARCELMEDIAAUTOPLAY_H -#include "llmediabase.h" #include "lltimer.h" // timer to automatically play media diff --git a/linden/indra/newview/llviewerparcelmgr.cpp b/linden/indra/newview/llviewerparcelmgr.cpp index 61b91fe..3ed41a3 100644 --- a/linden/indra/newview/llviewerparcelmgr.cpp +++ b/linden/indra/newview/llviewerparcelmgr.cpp @@ -35,7 +35,7 @@ #include "llviewerparcelmgr.h" // Library includes -#include "audioengine.h" +#include "llaudioengine.h" #include "indra_constants.h" #include "llcachename.h" #include "llgl.h" @@ -1599,6 +1599,9 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use // Request access list information for this land LLViewerParcelMgr::getInstance()->sendParcelAccessListRequest(AL_ACCESS | AL_BAN); + // Request the media url filter list for this land + LLViewerParcelMgr::getInstance()->requestParcelMediaURLFilter(); + // Request dwell for this land, if it's not public land. LLViewerParcelMgr::getInstance()->mSelectedDwell = 0.f; if (0 != local_id) @@ -1726,21 +1729,6 @@ void optionally_start_music(const std::string& music_url) } } - -void callback_start_music(S32 option, void* data) -{ - if (option == 0) - { - // Before the callback, we verified the url was good. - // We fetch again to avoid lag while loading. - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - gAudiop->startInternetStream(parcel->getMusicURL()); - - LLOverlayBar::musicFirstRun(); - } - gSavedSettings.setWarning("FirstStreamingMusic", FALSE); -} - // static void LLViewerParcelMgr::processParcelAccessListReply(LLMessageSystem *msg, void **user) { @@ -1937,6 +1925,66 @@ void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which) } } +class LLParcelMediaURLFilterResponder : public LLHTTPClient::Responder +{ + virtual void result(const LLSD& content) + { + LLViewerParcelMgr::getInstance()->receiveParcelMediaURLFilter(content); + } +}; + +void LLViewerParcelMgr::requestParcelMediaURLFilter() +{ + if (!mSelected) + { + return; + } + + LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth ); + if (!region) + { + return; + } + + LLParcel* parcel = mCurrentParcel; + if (!parcel) + { + llwarns << "no parcel" << llendl; + return; + } + + LLSD body; + body["local-id"] = parcel->getLocalID(); + body["list"] = parcel->getMediaURLFilterList(); + + std::string url = region->getCapability("ParcelMediaURLFilterList"); + if (!url.empty()) + { + LLHTTPClient::post(url, body, new LLParcelMediaURLFilterResponder); + } + else + { + llwarns << "can't get ParcelMediaURLFilterList cap" << llendl; + } +} + + +void LLViewerParcelMgr::receiveParcelMediaURLFilter(const LLSD &content) +{ + if (content.has("list")) + { + LLParcel* parcel = LLViewerParcelMgr::getInstance()->mCurrentParcel; + if (!parcel) return; + + if (content["local-id"].asInteger() == parcel->getLocalID()) + { + parcel->setMediaURLFilterList(content["list"]); + + LLViewerParcelMgr::getInstance()->notifyObservers(); + } + } +} + void LLViewerParcelMgr::deedLandToGroup() { diff --git a/linden/indra/newview/llviewerparcelmgr.h b/linden/indra/newview/llviewerparcelmgr.h index 9f762a1..9bf6096 100644 --- a/linden/indra/newview/llviewerparcelmgr.h +++ b/linden/indra/newview/llviewerparcelmgr.h @@ -198,6 +198,11 @@ public: // Takes an Access List flag, like AL_ACCESS or AL_BAN void sendParcelAccessListRequest(U32 flags); + // asks for the parcel's media url filter list + void requestParcelMediaURLFilter(); + // receive the response + void receiveParcelMediaURLFilter(const LLSD &content); + // Dwell is not part of the usual parcel update information because the // simulator doesn't actually know the per-parcel dwell. Ack! We have // to get it out of the database. diff --git a/linden/indra/newview/llviewerregion.cpp b/linden/indra/newview/llviewerregion.cpp index 4257f70..f06c3d8 100644 --- a/linden/indra/newview/llviewerregion.cpp +++ b/linden/indra/newview/llviewerregion.cpp @@ -322,7 +322,7 @@ void LLViewerRegion::loadCache() LLUUID cache_id; nread = fread(&cache_id.mData, 1, UUID_BYTES, fp); - if (nread != UUID_BYTES || mCacheID != cache_id) + if (nread != (size_t)UUID_BYTES || mCacheID != cache_id) { llinfos << "Cache ID doesn't match for this region, discarding" << llendl; @@ -398,7 +398,7 @@ void LLViewerRegion::saveCache() } // write the cache id for this sim - if (fwrite(&mCacheID.mData, 1, UUID_BYTES, fp) != UUID_BYTES) + if (fwrite(&mCacheID.mData, 1, UUID_BYTES, fp) != (size_t)UUID_BYTES) { llwarns << "Short write" << llendl; } @@ -1428,6 +1428,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("MapLayerGod"); capabilityNames.append("NewFileAgentInventory"); capabilityNames.append("ParcelPropertiesUpdate"); + capabilityNames.append("ParcelMediaURLFilterList"); + capabilityNames.append("ParcelNavigateMedia"); capabilityNames.append("ParcelVoiceInfoRequest"); capabilityNames.append("ProductInfoRequest"); capabilityNames.append("ProvisionVoiceAccountRequest"); diff --git a/linden/indra/newview/llviewertexteditor.cpp b/linden/indra/newview/llviewertexteditor.cpp index 981c9bc..34577a7 100644 --- a/linden/indra/newview/llviewertexteditor.cpp +++ b/linden/indra/newview/llviewertexteditor.cpp @@ -33,7 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llfocusmgr.h" -#include "audioengine.h" +#include "llaudioengine.h" #include "llagent.h" #include "llinventory.h" #include "llinventorymodel.h" diff --git a/linden/indra/newview/llviewerwindow.cpp b/linden/indra/newview/llviewerwindow.cpp index eb8977c..f7713c2 100644 --- a/linden/indra/newview/llviewerwindow.cpp +++ b/linden/indra/newview/llviewerwindow.cpp @@ -54,7 +54,7 @@ // // linden library includes -#include "audioengine.h" // mute on minimize +#include "llaudioengine.h" // mute on minimize #include "indra_constants.h" #include "llassetstorage.h" #include "llfontgl.h" @@ -156,7 +156,6 @@ #include "lltoolselectland.h" #include "lltoolview.h" #include "lluictrlfactory.h" -#include "lluploaddialog.h" #include "llurldispatcher.h" // SLURL from other app instance #include "llvieweraudio.h" #include "llviewercamera.h" @@ -164,6 +163,8 @@ #include "llviewerimagelist.h" #include "llviewerinventory.h" #include "llviewerkeyboard.h" +#include "llviewermedia.h" +#include "llviewermediafocus.h" #include "llviewermenu.h" #include "llviewermessage.h" #include "llviewerobjectlist.h" @@ -310,7 +311,9 @@ public: S32 hours = (S32)(time / (60*60)); S32 mins = (S32)((time - hours*(60*60)) / 60); S32 secs = (S32)((time - hours*(60*60) - mins*60)); - addText(xpos, ypos, llformat(" Debug %d: %d:%02d:%02d", idx, hours,mins,secs)); ypos += y_inc2; + std::string label = gDebugTimerLabel[idx]; + if (label.empty()) label = llformat("Debug: %d", idx); + addText(xpos, ypos, llformat(" %s: %d:%02d:%02d", label.c_str(), hours,mins,secs)); ypos += y_inc2; } F32 time = gFrameTimeSeconds; @@ -795,6 +798,7 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK if (handle) return handle; + // *HACK: this should be rolled into the composite tool logic, not // hardcoded at the top level. if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance()) @@ -1141,7 +1145,7 @@ void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data) case SLURL_MESSAGE_TYPE: // received URL std::string url = (const char*)data; - LLWebBrowserCtrl* web = NULL; + LLMediaCtrl* web = NULL; const bool trusted_browser = false; if (LLURLDispatcher::dispatch(url, web, trusted_browser)) { @@ -1736,6 +1740,19 @@ void LLViewerWindow::initWorldUI() // menu holder appears on top to get first pass at all mouse events mRootView->sendChildToFront(gMenuHolder); + + if ( gHUDView == NULL ) + { + LLRect hud_rect = full_window; + hud_rect.mBottom += 50; + if (gMenuBarView) + { + hud_rect.mTop -= gMenuBarView->getRect().getHeight(); + } + gHUDView = new LLHUDView(hud_rect); + // put behind everything else in the UI + mRootView->addChildAtEnd(gHUDView); + } } // Destroy the UI @@ -2180,7 +2197,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) if (key < 0x80) { // Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first. - return gFocusMgr.childHasKeyboardFocus(mRootView); + return (gFocusMgr.getKeyboardFocus() != NULL); } } @@ -2243,7 +2260,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) } // Traverses up the hierarchy - LLUICtrl* keyboard_focus = gFocusMgr.getKeyboardFocus(); + LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); if( keyboard_focus ) { // arrow keys move avatar while chatting hack @@ -2377,7 +2394,7 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask) } // Traverses up the hierarchy - LLView* keyboard_focus = gFocusMgr.getKeyboardFocus(); + LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); if( keyboard_focus ) { if (keyboard_focus->handleUnicodeChar(uni_char, FALSE)) @@ -2530,7 +2547,7 @@ BOOL LLViewerWindow::handlePerFrameHover() } // clean up current focus - LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus(); + LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); if (cur_focus) { if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain()) @@ -2910,12 +2927,18 @@ BOOL LLViewerWindow::handlePerFrameHover() { do_pick = FALSE; } + + if(LLViewerMediaFocus::getInstance()->getFocus()) + { + // When in-world media is in focus, pick every frame so that browser mouse-overs, dragging scrollbars, etc. work properly. + do_pick = TRUE; + } if (do_pick) { mouse_moved_since_pick = FALSE; mPickTimer.reset(); - pickAsync(getCurrentMouseX(), getCurrentMouseY(), mask, hoverPickCallback, TRUE); + pickAsync(getCurrentMouseX(), getCurrentMouseY(), mask, hoverPickCallback, TRUE, TRUE); } previous_x = x; @@ -4694,7 +4717,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, BOOL result_first_try = FALSE; BOOL result_second_try = FALSE; - LLUICtrl* keyboard_focus = gFocusMgr.getKeyboardFocus(); + LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); send_agent_pause(); llinfos << "Stopping GL during changeDisplaySettings" << llendl; stopGL(); @@ -4923,7 +4946,6 @@ LLBottomPanel::LLBottomPanel(const LLRect &rect) : mFactoryMap["toolbar"] = LLCallbackMap(createToolBar, NULL); mFactoryMap["overlay"] = LLCallbackMap(createOverlayBar, NULL); - mFactoryMap["hud"] = LLCallbackMap(createHUD, NULL); LLUICtrlFactory::getInstance()->buildPanel(this, "panel_bars.xml", &getFactoryMap()); setOrigin(rect.mLeft, rect.mBottom); @@ -4946,12 +4968,6 @@ void LLBottomPanel::draw() LLPanel::draw(); } -void* LLBottomPanel::createHUD(void* data) -{ - gHUDView = new LLHUDView(); - return gHUDView; -} - void* LLBottomPanel::createOverlayBar(void* data) { @@ -5164,12 +5180,8 @@ void LLPickInfo::updateXYCoords() LLPointer<LLViewerImage> imagep = gImageList.getImage(tep->getID()); if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull()) { - LLCoordGL coords; - - coords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth()); - coords.mY = llround(mUVCoords.mV[VY] * (F32)imagep->getHeight()); - - gViewerWindow->getWindow()->convertCoords(coords, &mXYCoords); + mXYCoords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth()); + mXYCoords.mY = llround((1.f - mUVCoords.mV[VY]) * (F32)imagep->getHeight()); } } } diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp index c8b26be..14b8d3e 100644 --- a/linden/indra/newview/llvoavatar.cpp +++ b/linden/indra/newview/llvoavatar.cpp @@ -37,7 +37,7 @@ #include <stdio.h> #include <ctype.h> -#include "audioengine.h" +#include "llaudioengine.h" #include "noise.h" #include "llagent.h" // Get state values from here @@ -69,6 +69,7 @@ #include "lltoolmorph.h" #include "llviewercamera.h" #include "llviewerimagelist.h" +#include "llviewermedia.h" #include "llviewermenu.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" @@ -3825,6 +3826,18 @@ void LLVOAvatar::idleUpdateTractorBeam() { return; } + const LLPickInfo& pick = gViewerWindow->getLastPick(); + + // No beam for media textures + // TODO: this will change for Media on a Prim + if(pick.getObject() && pick.mObjectFace >= 0) + { + const LLTextureEntry* tep = pick.getObject()->getTE(pick.mObjectFace); + if (tep && LLViewerMedia::textureHasMedia(tep->getID())) + { + return; + } + } // This is only done for yourself (maybe it should be in the agent?) if (!needsRenderBeam() || !mIsBuilt) @@ -3935,7 +3948,7 @@ void LLVOAvatar::idleUpdateTractorBeam() } else { - const LLPickInfo& pick = gViewerWindow->getLastPick(); + mBeam->setPositionGlobal(pick.mPosGlobal); } diff --git a/linden/indra/newview/llvovolume.cpp b/linden/indra/newview/llvovolume.cpp index 5f7327d..385dbe0 100644 --- a/linden/indra/newview/llvovolume.cpp +++ b/linden/indra/newview/llvovolume.cpp @@ -1694,7 +1694,7 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p trans_mat.translate(getRegion()->getOriginAgent()); } - volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, nodep->mSilhouetteSegments, view_vector, trans_mat, mRelativeXformInvTrans); + volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, nodep->mSilhouetteSegments, view_vector, trans_mat, mRelativeXformInvTrans, nodep->getTESelectMask()); nodep->mSilhouetteExists = TRUE; } diff --git a/linden/indra/newview/llweb.cpp b/linden/indra/newview/llweb.cpp index fb4b063..7021b48 100644 --- a/linden/indra/newview/llweb.cpp +++ b/linden/indra/newview/llweb.cpp @@ -38,7 +38,7 @@ #include "llviewerwindow.h" #include "llviewercontrol.h" -#include "llfloaterhtmlhelp.h" +#include "llfloatermediabrowser.h" // static void LLWeb::initClass() diff --git a/linden/indra/newview/mozilla-powerpc-darwin-readme.txt b/linden/indra/newview/mozilla-powerpc-darwin-readme.txt index be67ad3..e69de29 100644 --- a/linden/indra/newview/mozilla-powerpc-darwin-readme.txt +++ b/linden/indra/newview/mozilla-powerpc-darwin-readme.txt @@ -1,71 +0,0 @@ -NOTE: these directions have been obsoleted. There are now shell scripts that will check out, build, and package the necessary pieces -of the mozilla code in lindelib/mozilla-1.8.0/mac-build. I'm leaving this file here for historical interest. -------------- -Written by Monroe on June 17, 2005. - -Here's how to rebuild the Mozilla components for the Mac build. - -Check out the mozilla source from cvs - -cd to the mozilla directory (the same one that contains client.mk) - -cp .mozconfig.opt.shared.small .mozconfig - -Add the following line to the .mozconfig file you just created: - -ac_add_options --with-macos-sdk=/Developer/SDKs/MacOSX10.2.8.sdk - -make -f client.mk build - -wait a while. - -The build products you need to extract are in objdir-opt-shared-small/dist/bin and objdir-opt-shared-small/dist/lib. - -Copy the following to linden/libraries/firefox-1.0.4/<arch>/lib_release and linden/libraries/firefox-1.0.4/<arch>/lib_release: - -objdir-opt-shared-small/dist/lib/libembed_base_s.a -objdir-opt-shared-small/dist/lib/libxpcomglue_s.a -objdir-opt-shared-small/dist/bin/libxpcom.dylib -objdir-opt-shared-small/dist/bin/libplds4.dylib -objdir-opt-shared-small/dist/bin/libplc4.dylib -objdir-opt-shared-small/dist/bin/libnspr4.dylib -objdir-opt-shared-small/dist/bin/libgkgfx.dylib - -This first part should be repeated with .mozconfig.debug.shared.small to generate the libraries in the two matching lib_debug directories. The debug version of the bin directory is prohibitively large, so we're just using the release version of that part. - -Much of the contents of objdir-opt-shared-small/dist/bin also needs to go into a tar file that will be used when generating the application bundle. - -The bin directory will be populated with symlinks. If you just tar it up as-is, you'll get a tar file full of symlinks, which is not useful. - -Use 'cp -RL source dest' to make a copy of the bin directory with all symlinks expanded. This will be more useful. - -Remove things that aren't needed. This includes at least: - -asdecode -firefox -firefox-bin -firefox-config -LICENSE -nsinstall -mangle -regxpcom -regchrome -README.txt -run-mozilla.sh -xpcshell -xpt_dump -shlibsign -xpt_link -xpidl -xpicleanup - -There may be other pieces that aren't needed as well. I expect this will be refined moving forward. - -Because of the way the tar file will be expanded (directly inside the application bundle, in Contents/MacOS), it's important to create it so that it won't expand at a subdirectory of the current path. The way to to this is to cd to the dist/bin directory and do something like this: - -tar -zcvf ../mozilla-powerpc-darwin.tgz . - -This will create a tar file containing everything in the current directory, and will place the file one level up (so it doesn't interfere with its own creation). This file should replace the file with the above name checked into cvs in linden/indra/newview/. One of the lines in the shell script phase of the build extracts it appropriately into the application bundle. - -If any of this is unclear, please contact Monroe and I'll try to clarify and update this file. - diff --git a/linden/indra/newview/pipeline.cpp b/linden/indra/newview/pipeline.cpp index f10aca5..72da3c6 100644 --- a/linden/indra/newview/pipeline.cpp +++ b/linden/indra/newview/pipeline.cpp @@ -35,7 +35,7 @@ #include "pipeline.h" // library includes -#include "audioengine.h" // For MAX_BUFFERS for debugging. +#include "llaudioengine.h" // For MAX_BUFFERS for debugging. #include "imageids.h" #include "llerror.h" #include "llviewercontrol.h" diff --git a/linden/indra/newview/skins/default/textures/textures.xml b/linden/indra/newview/skins/default/textures/textures.xml index 0b4a088..f2189a4 100644 --- a/linden/indra/newview/skins/default/textures/textures.xml +++ b/linden/indra/newview/skins/default/textures/textures.xml @@ -16,7 +16,9 @@ <texture name="toolbar_btn_selected.tga" scale_left="7" scale_top="32" scale_right="121" scale_bottom="0" /> <texture name="button_enabled_selected_32x128.tga" preload="true" scale_left="16" scale_top="16" scale_right="112" scale_bottom="16" /> - + + <texture name="media_panel_bg.png" preload="true" scale_left="9" scale_top="9" scale_right="9" scale_bottom="9" /> + <texture name="media_panel_hoverrectangle.png" preload="true" scale_left="9" scale_top="9" scale_right="9" scale_bottom="9" /> <texture name="checkbox_disabled_false.tga" preload="true"/> <texture name="checkbox_disabled_true.tga" preload="true"/> <texture name="checkbox_enabled_false.tga" preload="true"/> @@ -376,7 +378,23 @@ <texture name="default_profile_picture.j2c"/> <texture name="locked_image.j2c"/> + <!-- Kitty Viewer Art --> <texture name="Inv_WindLight" file_name="Inv_WindLight.png" preload="false" /> <texture name="Inv_WaterLight" file_name="Inv_WaterLight.png" preload="false" /> + + <texture name="media_btn_back.png"/> + <texture name="media_btn_done.png"/> + <texture name="media_btn_forward.png"/> + <texture name="media_btn_home.png"/> + <texture name="media_btn_newwindow.png"/> + <texture name="media_btn_optimalzoom.png"/> + <texture name="media_btn_reload.png"/> + <texture name="media_btn_scrolldown.png"/> + <texture name="media_btn_scrollleft.png"/> + <texture name="media_btn_scrollright.png"/> + <texture name="media_btn_scrollup.png"/> + <texture name="media_btn_stoploading.png"/> + <texture name="media_panel_divider.png"/> + </textures> diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_about_land.xml b/linden/indra/newview/skins/default/xui/en-us/floater_about_land.xml index 9bc91e7..c8aacba 100644 --- a/linden/indra/newview/skins/default/xui/en-us/floater_about_land.xml +++ b/linden/indra/newview/skins/default/xui/en-us/floater_about_land.xml @@ -800,143 +800,633 @@ Only large parcels can be listed in search. No Pushing (Region Override) </string> </panel> - <panel border="true" bottom="-349" enabled="true" follows="left|top|right|bottom" - height="363" label="Media" left="1" mouse_opaque="true" - name="land_media_panel" width="458"> - <text type="string" length="1" bottom="-25" follows="left|top" font="SansSerifSmall" halign="left" height="16" - left="10" mouse_opaque="true" name="with media:" width="65"> - Media Type: - </text> - <combo_box allow_text_entry="false" bottom_delta="0" follows="left|top" height="18" - left="80" max_chars="20" name="media type" - tool_tip="Specify if the URL is a movie, web page, or other media" - width="120" /> - <text bottom_delta="0" follows="left|top" font="SansSerifSmall" height="16" - left_delta="130" name="mime_type" width="200" /> - <text type="string" length="1" bottom_delta="-20" follows="left|top" font="SansSerifSmall" halign="left" - height="16" left="10" name="at URL:" width="65"> - Media URL: - </text> - <line_editor bottom_delta="0" follows="left|top" font="SansSerifSmall" height="16" left="80" - max_length="255" name="media_url" right="-80" - select_all_on_focus_received="true" select_on_focus="true" - text_readonly_color="0.576471 0.662745 0.835294 1" /> - <button bottom_delta="0" follows="left|top" font="SansSerifSmall" halign="center" - height="16" label="Set..." label_selected="Set..." mouse_opaque="true" - name="set_media_url" right="-12" scale_image="true" width="60" /> - <text type="string" length="1" bottom_delta="-20" follows="left|top" font="SansSerifSmall" halign="left" - height="16" left="10" name="Description:" width="364"> + <panel + border="true" + border_visible="true" + bottom="-363" + enabled="true" + follows="left|top|right|bottom" + height="513" + label="Media" + left="1" + mouse_opaque="true" + name="land_media_panel" + width="458"> + <text + bottom="-25" + follows="left|top" + font="SansSerifSmall" + halign="left" + height="16" + left="10" + length="1" + mouse_opaque="true" + name="with media:" + type="string" + width="65"> + Type: + </text> + <combo_box + allow_text_entry="false" + bottom_delta="0" + follows="left|top" + height="18" + left="80" + max_chars="20" + name="media type" + tool_tip="Specify if the URL is a movie, web page, or other media" + width="120" /> + <text + bottom_delta="0" + follows="left|top" + font="SansSerifSmall" + height="16" + left_delta="130" + name="mime_type" + width="200" /> + <text type="string" + bottom_delta="-21" + follows="left|top" + font="SansSerifSmall" halign="left" + height="16" + left="10" + length="1" + name="at URL:" + width="65"> + Home URL: + </text> + <line_editor + bottom_delta="0" + follows="left|top|right" + font="SansSerifSmall" + height="16" + left="80" + max_length="255" + name="media_url" + right="-90" + select_all_on_focus_received="true" + select_on_focus="true" + text_readonly_color="0.576471 0.662745 0.835294 1" /> + <button + bottom_delta="0" + follows="right|top" + font="SansSerifSmall" + halign="center" + height="16" + label="Set..." + label_selected="Set..." + mouse_opaque="true" + name="set_media_url" + right="-12" + scale_image="true" + width="70" /> + <text + bottom_delta="-22" + follows="left|top" + font="SansSerifSmall" + halign="left" + height="16" + left="10" + length="1" + name="at URL:" + type="string" + width="65"> + Current URL: + </text> + <text + bottom_delta="0" + follows="left|top|right" + font="SansSerifSmall" + halign="left" + height="16" + left="80" + name="current_url" + right="-90" /> + <button + bottom_delta="0" + follows="right|top" + font="SansSerifSmall" + halign="center" + height="16" + label="Reset..." + label_selected="Reset..." + mouse_opaque="true" + name="reset_media_url" + right="-12" + scale_image="true" + width="70" /> + <check_box + bottom_delta="-22" + enabled="true" + follows="left|top" + font="SansSerifSmall" + height="16" + initial_value="false" + label="Hide URL" + left="80" + mouse_opaque="true" + name="hide_media_url" + radio_style="false" + tool_tip="Checking this option will hide the media URL from any non-authorized viewers of this parcel information. Note this is not available for HTML types." + width="150" /> + <text + bottom_delta="0" + follows="right|top" + font="SansSerifSmall" + halign="right" + height="16" + length="1" + name="media_reset" + right="-164" + tool_tip="Amount of time until parcel automatically reverts to default URL (0 for never return)" + type="string" + width="185"> + Return to Home URL in: + </text> + <spinner + bottom_delta="0" + decimal_digits="0" + enabled="false" + follows="right|top" + halign="right" + height="16" + increment="1" + initial_val="0" + max_val="1024" + min_val="0" + name="media_reset_time" + right="-90" + tool_tip="Amount of time until parcel reverts to default URL (0 for never return)" + width="64" /> + <text + bottom_delta="0" + follows="right|top" + font="SansSerifSmall" + halign="left" + height="16" + left_delta="70" + length="1" + name="minutes" + right="-10" + type="string"> + Minutes + </text> + <text + bottom_delta="-22" + follows="left|top" + font="SansSerifSmall" + halign="left" + height="16" + left="10" + length="1" + name="Description:" + type="string" + width="364"> Description: </text> - <line_editor bevel_style="in" border_style="line" border_thickness="1" bottom_delta="0" - follows="left|top" font="SansSerifSmall" height="16" left="80" - max_length="255" name="url_description" right="-80" - select_all_on_focus_received="true" select_on_focus="true" - tool_tip="Text displayed next to play/load button" spell_check="true" /> - <text type="string" length="1" bottom_delta="-20" follows="left|top" font="SansSerifSmall" halign="left" - height="16" left="10" name="Media texture:" width="364"> - Replace -Texture: - </text> - <texture_picker allow_no_texture="true" bottom_delta="-64" can_apply_immediately="false" - default_image_name="Default" follows="left|top" height="80" label="" - left="80" name="media texture" tool_tip="Click to choose a picture" - width="64" /> - <text type="string" length="1" bottom_delta="48" follows="left|top" font="SansSerifSmall" halign="left" - height="16" left_delta="75" name="replace_texture_help" width="270"> - (Objects using this texture will show the movie or -web page after you click the play arrow.) - </text> - <text type="string" length="1" bottom_delta="-55" follows="left|top" font="SansSerifSmall" halign="left" - height="16" left="10" mouse_opaque="true" name="Options:" width="292"> - Media -Options: - </text> - <check_box bottom_delta="0" enabled="true" follows="left|top" font="SansSerifSmall" - height="16" initial_value="false" label="Auto scale" left="80" - mouse_opaque="true" name="media_auto_scale" radio_style="false" - tool_tip="Checking this option will scale the content for this parcel automatically. It may be slightly slower and lower quality visually but no other texture scaling or alignment will be required." - width="200" /> - <check_box bottom_delta="0" enabled="true" follows="left|top" font="SansSerifSmall" - height="16" initial_value="false" label="Loop Media" left="250" - mouse_opaque="true" name="media_loop" radio_style="false" - tool_tip="Play media in a loop. When the media has finished playing, it will restart from the beginning." - width="200" /> - <check_box bottom_delta="-20" enabled="true" follows="left|top" font="SansSerifSmall" - height="16" initial_value="false" label="Hide Media URL" left="80" - mouse_opaque="true" name="hide_media_url" radio_style="false" - tool_tip="Checking this option will hide the media url to any non-authorized viewers of this parcel information. Note this is not available for HTML types." - width="200" /> - <check_box bottom_delta="0" enabled="true" follows="left|top" font="SansSerifSmall" - height="16" initial_value="false" label="Hide Music URL" left="250" - mouse_opaque="true" name="hide_music_url" radio_style="false" - tool_tip="Checking this option will hide the music url to any non-authorized viewers of this parcel information" - width="200" /> - <text type="string" length="1" bottom_delta="-25" follows="left|top" font="SansSerifSmall" halign="left" - height="16" left="85" name="media_size" - tool_tip="Size to render Web media, leave 0 for default." width="85"> - Media size: - </text> - <spinner bottom_delta="0" decimal_digits="0" enabled="false" follows="left|top" - halign="right" height="16" increment="1" initial_val="0" left_delta="65" - max_val="1024" min_val="0" name="media_size_width" - tool_tip="Size to render Web media, leave 0 for default." width="64" /> - <spinner bottom_delta="0" decimal_digits="0" enabled="false" follows="left|top" - halign="right" height="16" increment="1" initial_val="0" left_delta="80" - max_val="1024" min_val="0" name="media_size_height" - tool_tip="Size to render Web media, leave 0 for default." width="64" /> - <text type="string" length="1" bottom_delta="0" follows="left|top" font="SansSerifSmall" halign="left" - height="16" left_delta="70" name="pixels" right="-10"> + <line_editor + bevel_style="in" + border_style="line" + border_thickness="1" + bottom_delta="0" + follows="left|top|right" + font="SansSerifSmall" + height="16" + left="80" + max_length="255" + name="url_description" + right="-90" + select_all_on_focus_received="true" + select_on_focus="true" + tool_tip="Text displayed next to play/load button" /> + <text + bottom_delta="-28" + follows="left|top" + font="SansSerifSmall" + halign="left" + height="16" + left="10" + length="1" + name="Media texture:" + type="string" + width="364"> + Texture: + </text> + <texture_picker + allow_no_texture="true" + bottom_delta="-64" + can_apply_immediately="false" + default_image_name="Default" + follows="left|top" + height="80" + label="" + left="80" + name="media texture" + tool_tip="Click to choose a texture" + width="64" /> + <text + type="string" + length="1" + bottom_delta="0" + follows="left|top" + font="SansSerifSmall" + halign="left" + height="80" + left_delta="75" + name="replace_texture_help" + width="270"> + Objects using this texture will show the movie or +web page after you click the play arrow. + +Select the thumbnail to choose a different texture. + </text> + <text + bottom_delta="-16" + follows="left|top" + font="SansSerifSmall" + halign="left" + height="16" + left="10" + length="1" + mouse_opaque="true" + name="Options:" + top_delta="0" + type="string" + width="64"> + Options: + </text> + <check_box + bottom_delta="0" + enabled="true" + follows="left|top" + font="SansSerifSmall" + height="16" + initial_value="false" + label="Loop" + left="80" + mouse_opaque="true" + name="media_loop" + radio_style="false" + tool_tip="Play media in a loop. When the media has finished playing, it will restart from the beginning." + width="200" /> + <check_box + bottom_delta="0" + enabled="true" + follows="left|top" + font="SansSerifSmall" + height="16" + initial_value="false" + label="Auto scale" + left_delta="80" + mouse_opaque="true" + name="media_auto_scale" + radio_style="false" + tool_tip="Checking this option will scale the content for this parcel automatically. It may be slightly slower and lower quality visually but no other texture scaling or alignment will be required." + width="200" /> + <text + bottom_delta="-24" + follows="left|top" + font="SansSerifSmall" + halign="left" + height="16" + left="10" + length="1" + name="media_size" + tool_tip="Size to render Web media, leave 0 for default." + type="string" + width="85"> + Media Size: + </text> + <spinner + bottom_delta="0" + decimal_digits="0" + enabled="false" + follows="left|top" + halign="right" + height="16" + increment="1" + initial_val="0" + left="80" + max_val="1024" + min_val="0" + name="media_size_width" + tool_tip="Width to render Web media, leave 0 for default." + width="60" /> + <spinner + bottom_delta="0" + decimal_digits="0" + enabled="false" + follows="left|top" + halign="right" + height="16" + increment="1" + initial_val="0" + left_delta="64" + max_val="1024" + min_val="0" + name="media_size_height" + tool_tip="Height to render Web media, leave 0 for default." + width="60" /> + <text + bottom_delta="0" + follows="left|top" + font="SansSerifSmall" + halign="left" + height="16" + left_delta="64" + length="1" + name="pixels" + type="string" + width="70"> pixels </text> - <text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false" - bottom_delta="-40" drop_shadow_visible="true" enabled="true" - follows="left|top" font="SansSerifSmall" h_pad="0" halign="left" - height="16" left="10" mouse_opaque="true" name="MusicURL:" v_pad="0" - width="364"> + <text + bg_visible="false" + border_drop_shadow_visible="false" + border_visible="false" + bottom_delta="-30" + drop_shadow_visible="true" + enabled="true" + follows="left|top" + font="SansSerifSmall" + h_pad="0" + halign="left" + height="16" + left="10" + length="1" + mouse_opaque="true" + name="Interaction:" + type="string" + v_pad="0" + width="364"> + Interaction: + </text> + <radio_group + bottom_delta="-2" + draw_border="false" + enabled="true" + follows="left|top" + height="22" + left="80" + mouse_opaque="true" + name="radio_navigate_allow" + tab_stop="true" + width="219"> + <radio_item + bottom="-20" + enabled="true" + follows="left|top" + height="16" + left="0" + length="1" + mouse_opaque="true" + name="Anyone" + tool_tip="Any resident can interact with media." + type="string" + width="70"> + Anyone + </radio_item> + <radio_item + bottom="-20" + enabled="true" + follows="left|top" + height="16" + left="80" + length="1" + mouse_opaque="true" + name="Group" + tool_tip="Group permissions control who can interact with media." + type="string" + width="70"> + Group + </radio_item> + </radio_group> + <check_box + bottom_delta="-22" + enabled="true" + follows="left|top" + font="SansSerifSmall" + height="16" + initial_value="false" + label="Allow browsing only within these domains:" + left="80" + mouse_opaque="true" + name="check navigate filter" + radio_style="false" + width="292" /> + <line_editor + bevel_style="in" + border_style="line" + border_thickness="1" + bottom_delta="-20" + enabled="true" + follows="left|top|right" + font="SansSerifSmall" + handle_edit_keys_directly="false" + height="16" + left="80" + max_length="63" + mouse_opaque="true" + name="navigate_filter_domain" + right="-90" + select_all_on_focus_received="false" + select_on_focus="false" /> + <button + bottom_delta="0" + enabled="true" + follows="right|top" + font="SansSerifSmall" + halign="center" + height="16" + label="Add..." + label_selected="Add..." + right="-12" + mouse_opaque="true" + name="add_navigate_filter" + scale_image="true" + width="70" /> + <scroll_list + bottom_delta="-52" + can_resize="false" + column_padding="0" + draw_heading="false" + draw_stripes="false" + follows="left|top|right" + height="50" + halign="left" + left="80" + multi_select="false" + name="filter_list" + right="-90" + search_column="0" + sort_column="0"> + <column + halign="left" + label="Domain" + name="domain" + sort="domain"/> + </scroll_list> + <button + bottom_delta="0" + enabled="true" + follows="right|top" + font="SansSerifSmall" + halign="center" + height="16" + label="Remove" + label_selected="Remove" + right="-12" + mouse_opaque="true" + name="remove_navigate_filter" + scale_image="true" + width="70" /> + </panel> + <panel + border="true" + follows="left|top|right|bottom" + height="363" + label="Audio" + layout="topleft" + left_delta="0" + name="land_audio_panel" + top_delta="1" + width="458"> + <text + bottom="-45" + follows="left|top" + height="16" + layout="topleft" + left="10" + length="1" + name="MusicURL:" + type="string" + width="364"> Music URL: </text> - <line_editor bevel_style="in" border_style="line" border_thickness="1" bottom_delta="0" - enabled="true" follows="left|top" font="SansSerifSmall" - handle_edit_keys_directly="false" height="16" left="80" max_length="255" - mouse_opaque="true" name="music_url" right="-15" - select_all_on_focus_received="true" select_on_focus="true"/> - <text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false" - bottom_delta="-40" drop_shadow_visible="true" enabled="true" - follows="left|top" font="SansSerifSmall" h_pad="0" halign="left" - height="16" left="10" mouse_opaque="true" name="Sound:" v_pad="0" - width="364"> + <line_editor + border_style="line" + border_thickness="1" + bottom_delta="0" + follows="left|top|right" + height="16" + layout="topleft" + left="80" + max_length="255" + name="music_url" + right="-15" + select_on_focus="true" /> + <check_box + bottom_delta="-25" + enabled="true" + follows="left|top" + font="SansSerifSmall" + height="16" + initial_value="false" + label="Hide URL" + left="80" + mouse_opaque="true" + name="hide_music_url" + radio_style="false" + tool_tip="Checking this option will hide the music URL from any non-authorized viewers of this parcel information." + width="150" /> + <text + bottom_delta="-65" + follows="left|top" + height="16" + layout="topleft" + left="10" + length="1" + name="Sound:" + type="string" + width="364"> Sound: </text> - <check_box bottom_delta="0" enabled="true" follows="left|top" font="SansSerifSmall" - height="16" initial_value="false" - label="Restrict gesture and object sounds to this parcel" left="80" - mouse_opaque="true" name="check sound local" radio_style="false" - width="292" /> - <button bottom_delta="0" enabled="true" follows="left|top" font="SansSerif" - halign="center" height="18" label="?" label_selected="?" left="372" - mouse_opaque="true" name="?" width="18" /> - <text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false" - bottom_delta="-40" enabled="true" follows="left|top" font="SansSerifSmall" - h_pad="0" halign="left" height="16" left="10" mouse_opaque="false" - name="Voice settings:" tab_stop="false" v_pad="0" width="364"> + <check_box + bottom_delta="0" + follows="left|top" + height="16" + label="Restrict gesture and object sounds to this parcel" + layout="topleft" + left_delta="70" + name="check_sound_local" + width="200" /> + <button + bottom_delta="0" + follows="left|top" + height="18" + label="?" + label_selected="?" + layout="topleft" + left_delta="292" + name="?" + width="18" /> + <text + bottom_delta="-65" + follows="left|top" + height="16" + layout="topleft" + left="10" + length="1" + mouse_opaque="false" + name="Voice:" + type="string" + width="364"> Voice: </text> - <check_box bottom_delta="-0" enabled="true" follows="left|top" - height="54" left="80" mouse_opaque="true" name="parcel_enable_voice_channel" - tab_stop="true" width="463" - label="Enable Voice" - /> - <check_box bottom_delta="-0" enabled="false" follows="left|top" - height="54" left="80" mouse_opaque="true" name="parcel_enable_voice_channel_is_estate_disabled" - tab_stop="true" width="463" - label="Enable Voice (established by the Estate)" - /> - <check_box bottom_delta="-20" enabled="true" follows="left|top" - height="54" left="100" mouse_opaque="true" name="parcel_enable_voice_channel_parcel" - tab_stop="true" width="443" - label="Restrict Voice to this parcel" - /> + <radio_group + bottom_delta="-40" + draw_border="false" + enabled="true" + follows="left|top" + height="60" + left="80" + mouse_opaque="true" + name="parcel_voice_channel" + tab_stop="true" + width="219"> + <radio_item + bottom="-19" + enabled="true" + follows="left|top" + height="16" + left="0" + length="1" + mouse_opaque="true" + name="Estate" + tool_tip="Use the estate voice channel." + type="string" + width="70"> + Estate Channel + </radio_item> + <radio_item + bottom="-39" + enabled="true" + follows="left|top" + height="16" + left="0" + length="1" + mouse_opaque="true" + name="Parcel" + tool_tip="Restrict Voice to this parcel." + type="string" + width="70"> + Parcel Channel + </radio_item> + <radio_item + bottom="-59" + enabled="true" + follows="left|top" + height="16" + left="0" + length="1" + mouse_opaque="true" + name="Disabled" + tool_tip="Disable voice on this parcel." + type="string" + width="70"> + Disabled + </radio_item> + </radio_group> </panel> <panel border="true" bottom="-349" enabled="true" follows="left|top|right|bottom" height="333" label="Access" left="1" mouse_opaque="true" diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_media_browser.xml b/linden/indra/newview/skins/default/xui/en-us/floater_media_browser.xml index b30ca89..c1bfdcc 100644 --- a/linden/indra/newview/skins/default/xui/en-us/floater_media_browser.xml +++ b/linden/indra/newview/skins/default/xui/en-us/floater_media_browser.xml @@ -18,7 +18,20 @@ <button bottom_delta="0" enabled="true" follows="right|top" height="20" label="Home" left_delta="58" name="home" width="55" /> </layout_panel> - <layout_panel auto_resize="false" bottom="0" height="20" left="0" + <layout_panel auto_resize="false" bottom="0" height="20" left="0" name="time_controls" user_resize="false" + width="800"> + <button bottom="0" follows="left|top" height="20" label="rewind" left="0" name="rewind" + width="55" /> + <button bottom_delta="0" follows="left|top" height="20" label="" left_delta="55" + name="play" width="55" image_unselected="button_anim_play.tga" image_selected="button_anim_play_selected.tga" scale_image="true" /> + <button bottom_delta="0" follows="left|top" height="20" label="" left_delta="0" + name="pause" width="55" image_unselected="button_anim_pause.tga" image_selected="button_anim_pause_selected.tga" scale_image="true" /> + <button bottom_delta="0" follows="left|top" height="20" label="stop" + left_delta="65" name="stop" width="55" /> + <button bottom_delta="0" follows="left|top" height="20" label="forward" + left_delta="75" name="seek" width="55" /> + </layout_panel> + <layout_panel auto_resize="false" bottom="0" height="20" left="0" name="parcel_owner_controls" user_resize="false" width="540"> <button bottom="0" enabled="false" follows="left|top" height="20" label="Send Current URL to Parcel" left="0" name="assign" width="200" /> @@ -38,4 +51,10 @@ name="close" width="70" /> </layout_panel> </layout_stack> + <string name="home_page_url"> + http://www.secondlife.com + </string> + <string name="support_page_url"> + http://support.secondlife.com + </string> </floater> diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types.xml index e3d1021..e69de29 100644 --- a/linden/indra/newview/skins/default/xui/en-us/mime_types.xml +++ b/linden/indra/newview/skins/default/xui/en-us/mime_types.xml @@ -1,456 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<mimetypes name="default"> - <defaultlabel> - (Unknown) - </defaultlabel> - <defaultwidget> - none - </defaultwidget> - <defaultimpl> - LLMediaImplLLMozLib - </defaultimpl> - <widgetset name="web"> - <label name="web_label"> - Web Content - </label> - <icon> - icn_media_web.tga - </icon> - <default_type> - text/html - </default_type> - <tooltip name="web_tooltip"> - This location has Web content - </tooltip> - <playtip name="web_playtip"> - Show Web content - </playtip> - <allow_resize> - true - </allow_resize> - <allow_looping> - false - </allow_looping> - </widgetset> - <widgetset name="movie"> - <label name="movie_label"> - Movie - </label> - <default_type> - video/* - </default_type> - <icon> - icn_media_movie.tga - </icon> - <tooltip name="movie_tooltip"> - There is a movie to play here - </tooltip> - <playtip name="movie_playtip"> - Play movie - </playtip> - <allow_resize> - false - </allow_resize> - <allow_looping> - true - </allow_looping> - </widgetset> - <widgetset name="none"> - <label name="none_label"> - No Content - </label> - <default_type> - none/none - </default_type> - <icon> - icn_media_web.tga - </icon> - <tooltip name="none_tooltip"> - No media here - </tooltip> - <playtip name="none_playtip" /> - <allow_resize> - false - </allow_resize> - <allow_looping> - false - </allow_looping> - </widgetset> - <widgetset name="image"> - <label name="image_label"> - Image - </label> - <icon> - icn_media_web.tga - </icon> - <default_type> - image/* - </default_type> - <tooltip name="image_tooltip"> - There is an image at this location - </tooltip> - <playtip name="image_playtip"> - View this location's image - </playtip> - <allow_resize> - false - </allow_resize> - <allow_looping> - false - </allow_looping> - </widgetset> - <widgetset name="audio"> - <label name="audio_label"> - Audio - </label> - <icon> - icn_media_web.tga - </icon> - <default_type> - audio/* - </default_type> - <tooltip name="audio_tooltip"> - There is audio at this location - </tooltip> - <playtip name="audio_playtip"> - Play this location's audio - </playtip> - <allow_resize> - false - </allow_resize> - <allow_looping> - true - </allow_looping> - </widgetset> - <scheme name="rtsp"> - <label name="rtsp_label"> - Real Time Streaming - </label> - <widgettype> - movie - </widgettype> - </scheme> - <mimetype name="blank"> - <label name="blank_label"> - - None - - </label> - <widgettype> - none - </widgettype> - <impl> - LLMediaImplQuickTime - </impl> - </mimetype> - <mimetype name="none/none"> - <label name="none/none_label"> - - None - - </label> - <widgettype> - none - </widgettype> - </mimetype> - <mimetype name="audio/*"> - <label name="audio2_label"> - Audio - </label> - <widgettype> - audio - </widgettype> - </mimetype> - <mimetype name="video/*"> - <label name="video2_label"> - Video - </label> - <widgettype> - movie - </widgettype> - </mimetype> - <mimetype name="image/*"> - <label name="image2_label"> - Image - </label> - <widgettype> - image - </widgettype> - </mimetype> - <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> - <label name="vnd.secondlife.qt.legacy_label"> - Movie (QuickTime) - </label> - <widgettype> - movie - </widgettype> - <impl> - LLMediaImplQuickTime - </impl> - </mimetype> - <mimetype name="application/javascript"> - <label name="application/javascript_label"> - Javascript - </label> - <widgettype> - web - </widgettype> - </mimetype> - <mimetype name="application/ogg"> - <label name="application/ogg_label"> - Ogg Audio/Video - </label> - <widgettype> - audio - </widgettype> - </mimetype> - <mimetype name="application/pdf"> - <label name="application/pdf_label"> - PDF Document - </label> - <widgettype> - image - </widgettype> - </mimetype> - <mimetype name="application/postscript"> - <label name="application/postscript_label"> - Postscript Document - </label> - <widgettype> - image - </widgettype> - </mimetype> - <mimetype name="application/rtf"> - <label name="application/rtf_label"> - Rich Text (RTF) - </label> - <widgettype> - image - </widgettype> - </mimetype> - <mimetype name="application/smil"> - <label name="application/smil_label"> - Synchronized Multimedia Integration Language (SMIL) - </label> - <widgettype> - movie - </widgettype> - </mimetype> - <mimetype name="application/xhtml+xml"> - <label name="application/xhtml+xml_label"> - Web Page (XHTML) - </label> - <widgettype> - web - </widgettype> - </mimetype> - <mimetype name="application/x-director"> - <label name="application/x-director_label"> - Macromedia Director - </label> - <widgettype> - image - </widgettype> - </mimetype> - <mimetype name="application/x-shockwave-flash"> - <label name="application/x-shockwave-flash_label"> - Flash - </label> - <widgettype> - image - </widgettype> - </mimetype> - <mimetype name="audio/mid"> - <label name="audio/mid_label"> - Audio (MIDI) - </label> - <widgettype> - audio - </widgettype> - </mimetype> - <mimetype name="audio/mpeg"> - <label name="audio/mpeg_label"> - Audio (MP3) - </label> - <widgettype> - audio - </widgettype> - </mimetype> - <mimetype name="audio/x-aiff"> - <label name="audio/x-aiff_label"> - Audio (AIFF) - </label> - <widgettype> - audio - </widgettype> - </mimetype> - <mimetype name="audio/x-wav"> - <label name="audio/x-wav_label"> - Audio (WAV) - </label> - <widgettype> - audio - </widgettype> - </mimetype> - <mimetype menu="1" name="image/bmp"> - <label name="image/bmp_label"> - Image (BMP) - </label> - <widgettype> - image - </widgettype> - <impl> - LLMediaImplLLMozLib - </impl> - </mimetype> - <mimetype menu="1" name="image/gif"> - <label name="image/gif_label"> - Image (GIF) - </label> - <widgettype> - image - </widgettype> - <impl> - LLMediaImplLLMozLib - </impl> - </mimetype> - <mimetype menu="1" name="image/jpeg"> - <label name="image/jpeg_label"> - Image (JPEG) - </label> - <widgettype> - image - </widgettype> - <impl> - LLMediaImplLLMozLib - </impl> - </mimetype> - <mimetype menu="1" name="image/png"> - <label name="image/png_label"> - Image (PNG) - </label> - <widgettype> - image - </widgettype> - <impl> - LLMediaImplLLMozLib - </impl> - </mimetype> - <mimetype name="image/svg+xml"> - <label name="image/svg+xml_label"> - Image (SVG) - </label> - <widgettype> - image - </widgettype> - <impl> - LLMediaImplLLMozLib - </impl> - </mimetype> - <mimetype menu="1" name="image/tiff"> - <label name="image/tiff_label"> - Image (TIFF) - </label> - <widgettype> - image - </widgettype> - <impl> - LLMediaImplLLMozLib - </impl> - </mimetype> - <mimetype menu="1" name="text/html"> - <label name="text/html_label"> - Web Page - </label> - <widgettype> - web - </widgettype> - <impl> - LLMediaImplLLMozLib - </impl> - </mimetype> - <mimetype menu="1" name="text/plain"> - <label name="text/plain_label"> - Text - </label> - <widgettype> - text - </widgettype> - <impl> - LLMediaImplLLMozLib - </impl> - </mimetype> - <mimetype name="text/xml"> - <label name="text/xml_label"> - XML - </label> - <widgettype> - text - </widgettype> - <impl> - LLMediaImplLLMozLib - </impl> - </mimetype> - <mimetype menu="1" name="video/mpeg"> - <label name="video/mpeg_label"> - Movie (MPEG) - </label> - <widgettype> - movie - </widgettype> - <impl> - LLMediaImplQuickTime - </impl> - </mimetype> - <mimetype name="video/mp4"> - <label name="video/mp4_label"> - Movie (MP4) - </label> - <widgettype> - movie - </widgettype> - <impl> - LLMediaImplQuickTime - </impl> - </mimetype> - <mimetype menu="1" name="video/quicktime"> - <label name="video/quicktime_label"> - Movie (QuickTime) - </label> - <widgettype> - movie - </widgettype> - <impl> - LLMediaImplQuickTime - </impl> - </mimetype> - <mimetype name="video/x-ms-asf"> - <label name="video/x-ms-asf_label"> - Movie (Windows Media ASF) - </label> - <widgettype> - movie - </widgettype> - <impl> - LLMediaImplQuickTime - </impl> - </mimetype> - <mimetype name="video/x-ms-wmv"> - <label name="video/x-ms-wmv_label"> - Movie (Windows Media WMV) - </label> - <widgettype> - movie - </widgettype> - <impl> - LLMediaImplQuickTime - </impl> - </mimetype> - <mimetype menu="1" name="video/x-msvideo"> - <label name="video/x-msvideo_label"> - Movie (AVI) - </label> - <widgettype> - movie - </widgettype> - <impl> - LLMediaImplQuickTime - </impl> - </mimetype> -</mimetypes> diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types_linux.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types_linux.xml new file mode 100644 index 0000000..2977d7a --- /dev/null +++ b/linden/indra/newview/skins/default/xui/en-us/mime_types_linux.xml @@ -0,0 +1,445 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<mimetypes name="default"> + <defaultlabel> + (Unknown) + </defaultlabel> + <defaultwidget> + none + </defaultwidget> + <defaultimpl> + media_plugin_webkit + </defaultimpl> + <widgetset name="web"> + <label name="web_label"> + Web Content + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + text/html + </default_type> + <tooltip name="web_tooltip"> + This location has Web content + </tooltip> + <playtip name="web_playtip"> + Show Web content + </playtip> + <allow_resize> + true + </allow_resize> + <allow_looping> + false + </allow_looping> + </widgetset> + <widgetset name="movie"> + <label name="movie_label"> + Movie + </label> + <default_type> + video/* + </default_type> + <icon> + icn_media_movie.tga + </icon> + <tooltip name="movie_tooltip"> + There is a movie to play here + </tooltip> + <playtip name="movie_playtip"> + Play movie + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + true + </allow_looping> + </widgetset> + <widgetset name="image"> + <label name="image_label"> + Image + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + image/* + </default_type> + <tooltip name="image_tooltip"> + There is an image at this location + </tooltip> + <playtip name="image_playtip"> + View this location's image + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + false + </allow_looping> + </widgetset> + <widgetset name="audio"> + <label name="audio_label"> + Audio + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + audio/* + </default_type> + <tooltip name="audio_tooltip"> + There is audio at this location + </tooltip> + <playtip name="audio_playtip"> + Play this location's audio + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + true + </allow_looping> + </widgetset> + <scheme name="rtsp"> + <label name="rtsp_label"> + Real Time Streaming + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </scheme> + <mimetype name="blank"> + <label name="blank_label"> + - None - + </label> + <widgettype> + none + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="none/none"> + <label name="none/none_label"> + - None - + </label> + <widgettype> + none + </widgettype> + </mimetype> + <mimetype name="audio/*"> + <label name="audio2_label"> + Audio + </label> + <widgettype> + audio + </widgettype> + </mimetype> + <mimetype name="video/*"> + <label name="video2_label"> + Video + </label> + <widgettype> + movie + </widgettype> + </mimetype> + <mimetype name="image/*"> + <label name="image2_label"> + Image + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> + <label name="vnd.secondlife.qt.legacy_label"> + Movie (QuickTime) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="application/javascript"> + <label name="application/javascript_label"> + Javascript + </label> + <widgettype> + web + </widgettype> + </mimetype> + <mimetype name="application/ogg"> + <label name="application/ogg_label"> + Ogg Audio/Video + </label> + <widgettype> + audio + </widgettype> + </mimetype> + <mimetype name="application/pdf"> + <label name="application/pdf_label"> + PDF Document + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/postscript"> + <label name="application/postscript_label"> + Postscript Document + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/rtf"> + <label name="application/rtf_label"> + Rich Text (RTF) + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/smil"> + <label name="application/smil_label"> + Synchronized Multimedia Integration Language (SMIL) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="application/xhtml+xml"> + <label name="application/xhtml+xml_label"> + Web Page (XHTML) + </label> + <widgettype> + web + </widgettype> + </mimetype> + <mimetype name="application/x-director"> + <label name="application/x-director_label"> + Macromedia Director + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="audio/mid"> + <label name="audio/mid_label"> + Audio (MIDI) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="audio/mpeg"> + <label name="audio/mpeg_label"> + Audio (MP3) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="audio/x-aiff"> + <label name="audio/x-aiff_label"> + Audio (AIFF) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="audio/x-wav"> + <label name="audio/x-wav_label"> + Audio (WAV) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype menu="1" name="image/bmp"> + <label name="image/bmp_label"> + Image (BMP) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/gif"> + <label name="image/gif_label"> + Image (GIF) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/jpeg"> + <label name="image/jpeg_label"> + Image (JPEG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/png"> + <label name="image/png_label"> + Image (PNG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype name="image/svg+xml"> + <label name="image/svg+xml_label"> + Image (SVG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/tiff"> + <label name="image/tiff_label"> + Image (TIFF) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="text/html"> + <label name="text/html_label"> + Web Page + </label> + <widgettype> + web + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="text/plain"> + <label name="text/plain_label"> + Text + </label> + <widgettype> + text + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype name="text/xml"> + <label name="text/xml_label"> + XML + </label> + <widgettype> + text + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="video/mpeg"> + <label name="video/mpeg_label"> + Movie (MPEG) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="video/mp4"> + <label name="video/mp4_label"> + Movie (MP4) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype menu="1" name="video/quicktime"> + <label name="video/quicktime_label"> + Movie (QuickTime) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="video/x-ms-asf"> + <label name="video/x-ms-asf_label"> + Movie (Windows Media ASF) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype name="video/x-ms-wmv"> + <label name="video/x-ms-wmv_label"> + Movie (Windows Media WMV) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> + <mimetype menu="1" name="video/x-msvideo"> + <label name="video/x-msvideo_label"> + Movie (AVI) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_gstreamer + </impl> + </mimetype> +</mimetypes> diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types_mac.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types_mac.xml new file mode 100644 index 0000000..4a7a6e1 --- /dev/null +++ b/linden/indra/newview/skins/default/xui/en-us/mime_types_mac.xml @@ -0,0 +1,445 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<mimetypes name="default"> + <defaultlabel> + (Unknown) + </defaultlabel> + <defaultwidget> + none + </defaultwidget> + <defaultimpl> + media_plugin_webkit + </defaultimpl> + <widgetset name="web"> + <label name="web_label"> + Web Content + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + text/html + </default_type> + <tooltip name="web_tooltip"> + This location has Web content + </tooltip> + <playtip name="web_playtip"> + Show Web content + </playtip> + <allow_resize> + true + </allow_resize> + <allow_looping> + false + </allow_looping> + </widgetset> + <widgetset name="movie"> + <label name="movie_label"> + Movie + </label> + <default_type> + video/* + </default_type> + <icon> + icn_media_movie.tga + </icon> + <tooltip name="movie_tooltip"> + There is a movie to play here + </tooltip> + <playtip name="movie_playtip"> + Play movie + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + true + </allow_looping> + </widgetset> + <widgetset name="image"> + <label name="image_label"> + Image + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + image/* + </default_type> + <tooltip name="image_tooltip"> + There is an image at this location + </tooltip> + <playtip name="image_playtip"> + View this location's image + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + false + </allow_looping> + </widgetset> + <widgetset name="audio"> + <label name="audio_label"> + Audio + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + audio/* + </default_type> + <tooltip name="audio_tooltip"> + There is audio at this location + </tooltip> + <playtip name="audio_playtip"> + Play this location's audio + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + true + </allow_looping> + </widgetset> + <scheme name="rtsp"> + <label name="rtsp_label"> + Real Time Streaming + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </scheme> + <mimetype name="blank"> + <label name="blank_label"> + - None - + </label> + <widgettype> + none + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="none/none"> + <label name="none/none_label"> + - None - + </label> + <widgettype> + none + </widgettype> + </mimetype> + <mimetype name="audio/*"> + <label name="audio2_label"> + Audio + </label> + <widgettype> + audio + </widgettype> + </mimetype> + <mimetype name="video/*"> + <label name="video2_label"> + Video + </label> + <widgettype> + movie + </widgettype> + </mimetype> + <mimetype name="image/*"> + <label name="image2_label"> + Image + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> + <label name="vnd.secondlife.qt.legacy_label"> + Movie (QuickTime) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="application/javascript"> + <label name="application/javascript_label"> + Javascript + </label> + <widgettype> + web + </widgettype> + </mimetype> + <mimetype name="application/ogg"> + <label name="application/ogg_label"> + Ogg Audio/Video + </label> + <widgettype> + audio + </widgettype> + </mimetype> + <mimetype name="application/pdf"> + <label name="application/pdf_label"> + PDF Document + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/postscript"> + <label name="application/postscript_label"> + Postscript Document + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/rtf"> + <label name="application/rtf_label"> + Rich Text (RTF) + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/smil"> + <label name="application/smil_label"> + Synchronized Multimedia Integration Language (SMIL) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="application/xhtml+xml"> + <label name="application/xhtml+xml_label"> + Web Page (XHTML) + </label> + <widgettype> + web + </widgettype> + </mimetype> + <mimetype name="application/x-director"> + <label name="application/x-director_label"> + Macromedia Director + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="audio/mid"> + <label name="audio/mid_label"> + Audio (MIDI) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="audio/mpeg"> + <label name="audio/mpeg_label"> + Audio (MP3) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="audio/x-aiff"> + <label name="audio/x-aiff_label"> + Audio (AIFF) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="audio/x-wav"> + <label name="audio/x-wav_label"> + Audio (WAV) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype menu="1" name="image/bmp"> + <label name="image/bmp_label"> + Image (BMP) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/gif"> + <label name="image/gif_label"> + Image (GIF) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/jpeg"> + <label name="image/jpeg_label"> + Image (JPEG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/png"> + <label name="image/png_label"> + Image (PNG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype name="image/svg+xml"> + <label name="image/svg+xml_label"> + Image (SVG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/tiff"> + <label name="image/tiff_label"> + Image (TIFF) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="text/html"> + <label name="text/html_label"> + Web Page + </label> + <widgettype> + web + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="text/plain"> + <label name="text/plain_label"> + Text + </label> + <widgettype> + text + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype name="text/xml"> + <label name="text/xml_label"> + XML + </label> + <widgettype> + text + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="video/mpeg"> + <label name="video/mpeg_label"> + Movie (MPEG) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="video/mp4"> + <label name="video/mp4_label"> + Movie (MP4) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype menu="1" name="video/quicktime"> + <label name="video/quicktime_label"> + Movie (QuickTime) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="video/x-ms-asf"> + <label name="video/x-ms-asf_label"> + Movie (Windows Media ASF) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="video/x-ms-wmv"> + <label name="video/x-ms-wmv_label"> + Movie (Windows Media WMV) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype menu="1" name="video/x-msvideo"> + <label name="video/x-msvideo_label"> + Movie (AVI) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> +</mimetypes> diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml new file mode 100644 index 0000000..4a7a6e1 --- /dev/null +++ b/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml @@ -0,0 +1,445 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<mimetypes name="default"> + <defaultlabel> + (Unknown) + </defaultlabel> + <defaultwidget> + none + </defaultwidget> + <defaultimpl> + media_plugin_webkit + </defaultimpl> + <widgetset name="web"> + <label name="web_label"> + Web Content + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + text/html + </default_type> + <tooltip name="web_tooltip"> + This location has Web content + </tooltip> + <playtip name="web_playtip"> + Show Web content + </playtip> + <allow_resize> + true + </allow_resize> + <allow_looping> + false + </allow_looping> + </widgetset> + <widgetset name="movie"> + <label name="movie_label"> + Movie + </label> + <default_type> + video/* + </default_type> + <icon> + icn_media_movie.tga + </icon> + <tooltip name="movie_tooltip"> + There is a movie to play here + </tooltip> + <playtip name="movie_playtip"> + Play movie + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + true + </allow_looping> + </widgetset> + <widgetset name="image"> + <label name="image_label"> + Image + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + image/* + </default_type> + <tooltip name="image_tooltip"> + There is an image at this location + </tooltip> + <playtip name="image_playtip"> + View this location's image + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + false + </allow_looping> + </widgetset> + <widgetset name="audio"> + <label name="audio_label"> + Audio + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + audio/* + </default_type> + <tooltip name="audio_tooltip"> + There is audio at this location + </tooltip> + <playtip name="audio_playtip"> + Play this location's audio + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + true + </allow_looping> + </widgetset> + <scheme name="rtsp"> + <label name="rtsp_label"> + Real Time Streaming + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </scheme> + <mimetype name="blank"> + <label name="blank_label"> + - None - + </label> + <widgettype> + none + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="none/none"> + <label name="none/none_label"> + - None - + </label> + <widgettype> + none + </widgettype> + </mimetype> + <mimetype name="audio/*"> + <label name="audio2_label"> + Audio + </label> + <widgettype> + audio + </widgettype> + </mimetype> + <mimetype name="video/*"> + <label name="video2_label"> + Video + </label> + <widgettype> + movie + </widgettype> + </mimetype> + <mimetype name="image/*"> + <label name="image2_label"> + Image + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> + <label name="vnd.secondlife.qt.legacy_label"> + Movie (QuickTime) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="application/javascript"> + <label name="application/javascript_label"> + Javascript + </label> + <widgettype> + web + </widgettype> + </mimetype> + <mimetype name="application/ogg"> + <label name="application/ogg_label"> + Ogg Audio/Video + </label> + <widgettype> + audio + </widgettype> + </mimetype> + <mimetype name="application/pdf"> + <label name="application/pdf_label"> + PDF Document + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/postscript"> + <label name="application/postscript_label"> + Postscript Document + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/rtf"> + <label name="application/rtf_label"> + Rich Text (RTF) + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/smil"> + <label name="application/smil_label"> + Synchronized Multimedia Integration Language (SMIL) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="application/xhtml+xml"> + <label name="application/xhtml+xml_label"> + Web Page (XHTML) + </label> + <widgettype> + web + </widgettype> + </mimetype> + <mimetype name="application/x-director"> + <label name="application/x-director_label"> + Macromedia Director + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="audio/mid"> + <label name="audio/mid_label"> + Audio (MIDI) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="audio/mpeg"> + <label name="audio/mpeg_label"> + Audio (MP3) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="audio/x-aiff"> + <label name="audio/x-aiff_label"> + Audio (AIFF) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="audio/x-wav"> + <label name="audio/x-wav_label"> + Audio (WAV) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype menu="1" name="image/bmp"> + <label name="image/bmp_label"> + Image (BMP) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/gif"> + <label name="image/gif_label"> + Image (GIF) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/jpeg"> + <label name="image/jpeg_label"> + Image (JPEG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/png"> + <label name="image/png_label"> + Image (PNG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype name="image/svg+xml"> + <label name="image/svg+xml_label"> + Image (SVG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/tiff"> + <label name="image/tiff_label"> + Image (TIFF) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="text/html"> + <label name="text/html_label"> + Web Page + </label> + <widgettype> + web + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="text/plain"> + <label name="text/plain_label"> + Text + </label> + <widgettype> + text + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype name="text/xml"> + <label name="text/xml_label"> + XML + </label> + <widgettype> + text + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="video/mpeg"> + <label name="video/mpeg_label"> + Movie (MPEG) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="video/mp4"> + <label name="video/mp4_label"> + Movie (MP4) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype menu="1" name="video/quicktime"> + <label name="video/quicktime_label"> + Movie (QuickTime) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="video/x-ms-asf"> + <label name="video/x-ms-asf_label"> + Movie (Windows Media ASF) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="video/x-ms-wmv"> + <label name="video/x-ms-wmv_label"> + Movie (Windows Media WMV) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype menu="1" name="video/x-msvideo"> + <label name="video/x-msvideo_label"> + Movie (AVI) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> +</mimetypes> diff --git a/linden/indra/newview/skins/default/xui/en-us/panel_bars.xml b/linden/indra/newview/skins/default/xui/en-us/panel_bars.xml index 4a13604..aab98db 100644 --- a/linden/indra/newview/skins/default/xui/en-us/panel_bars.xml +++ b/linden/indra/newview/skins/default/xui/en-us/panel_bars.xml @@ -15,7 +15,4 @@ <layout_panel auto_resize="false" filename="panel_toolbar.xml" name="toolbar" use_bounding_rect="true" user_resize="false" width="1024" min_height="28" /> </layout_stack> - <panel auto_resize="true" background_visible="false" bottom="50" - follows="left|right|top|bottom" height="728" left="0" mouse_opaque="false" - name="hud" user_resize="false" width="1024" /> </panel> diff --git a/linden/indra/newview/skins/default/xui/en-us/panel_hud.xml b/linden/indra/newview/skins/default/xui/en-us/panel_hud.xml new file mode 100644 index 0000000..95f8289 --- /dev/null +++ b/linden/indra/newview/skins/default/xui/en-us/panel_hud.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel border="false" auto_resize="true" background_visible="false" bottom="50" + follows="left|right|top|bottom" height="728" left="0" mouse_opaque="false" + name="hud" user_resize="false" width="1024" /> diff --git a/linden/indra/newview/skins/default/xui/en-us/panel_media_hud.xml b/linden/indra/newview/skins/default/xui/en-us/panel_media_hud.xml new file mode 100644 index 0000000..1c0781a --- /dev/null +++ b/linden/indra/newview/skins/default/xui/en-us/panel_media_hud.xml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel border="false" follows="" height="160" visible="false" mouse_opaque="false" + label="" name="MediaHUD" width="208" background_visible="false" background_opaque="false" bg_alpha_color="1 1 1 0.0"> +<panel name="media_region" left="20" right="-20" bottom="35" top="-20" follows="left|right|top|bottom" visible="true" background_opaque="false" + mouse_opaque="false"/> + <!--icon name="bg_image" image_name="media_panel_hoverrectangle.png" visible="true" left="10" bottom="32" right="-10" top="-10" follows="left|right|top|bottom"/--> + <layout_stack orientation="horizontal" left="0" bottom="0" follows="left|right|bottom" visible="true" width="208" height="32"> + <layout_panel user_resize="false"/> + <layout_panel user_resize="false" auto_resize="false" width="210" min_width="208"> + <panel name="media_focused_controls" width="208" left="0" height="32" bottom="0" visible="true"> + <icon name="media_panel_transportcontrols_bg" image_name="media_panel_bg.png" visible="true" height="32" width="99" scale_image="true" bottom="0"/> + <button name="back" label="" left="4" width="20" bottom="6" height="22" image_unselected="media_btn_back.png" + image_selected="media_btn_back.png" scale_image="true"/> + <icon name="media_panel_divider-1" image_name="media_panel_divider.png" visible="true" height="22" width="3" left_delta="20" + scale_image="false" bottom="5"/> + <button name="fwd" label="" left_delta="3" width="17" bottom_delta="0" height="22" image_unselected="media_btn_forward.png" + image_selected="media_btn_forward.png" scale_image="true"/> + <icon name="media_panel_divider-2" image_name="media_panel_divider.png" visible="true" height="22" width="3" left_delta="17" + scale_image="false" bottom="5"/> + <button name="home" label="" left_delta="3" width="22" bottom_delta="0" height="22" image_unselected="media_btn_home.png" + image_selected="media_btn_home.png" scale_image="true"/> + <button name="media_stop" label="" left_delta="0" width="22" bottom_delta="0" height="22" image_unselected="button_anim_stop.tga" + image_selected="button_anim_stop.tga" scale_image="true"/> + <icon name="media_panel_divider-3" image_name="media_panel_divider.png" visible="true" height="22" width="3" left_delta="22" + scale_image="false" bottom="5"/> + <button name="reload" label="" left_delta="3" width="22" bottom_delta="0" height="22" image_unselected="media_btn_reload.png" + image_selected="media_btn_reload.png" scale_image="true"/> + <button name="stop" label="" left_delta="0" width="22" bottom_delta="0" height="22" image_unselected="media_btn_stoploading.png" + image_selected="media_btn_stoploading.png" scale_image="true" visible="false"/> + <button name="play" label="" left_delta="0" width="22" bottom_delta="0" height="22" image_unselected="button_anim_play.tga" + image_selected="button_anim_play.tga" scale_image="true" visible="false"/> + <button name="pause" label="" left_delta="0" width="22" bottom_delta="0" height="22" image_unselected="button_anim_pause.tga" + image_selected="button_anim_pause.tga" scale_image="true" visible="false"/> + <icon name="media_panel_scrollbg" image_name="media_panel_scrollbg.png" visible="true" height="32" width="32" + scale_image="false" bottom="0" left="97"/> + <button name="scrollup" label="" left="109" width="8" bottom="20" height="8" image_unselected="media_btn_scrollup.png" + image_selected="media_btn_scrollup.png" scale_image="false"/> + <button name="scrollleft" label="" left="100" width="8" bottom="12" height="8" image_unselected="media_btn_scrollleft.png" + image_selected="media_btn_scrollleft.png" scale_image="false"/> + <button name="scrollright" label="" left="117" width="8" bottom="12" height="8" image_unselected="media_btn_scrollright.png" + image_selected="media_btn_scrollright.png" scale_image="false"/> + <button name="scrolldown" label="" left="109" width="8" bottom="4" height="8" image_unselected="media_btn_scrolldown.png" + image_selected="media_btn_scrolldown.png" scale_image="false"/> + <icon name="media_panel_metacontrols_bg" image_name="media_panel_bg.png" visible="true" height="32" width="81" + scale_image="true" bottom="0" left="127"/> + <button name="zoom_frame" label="" left_delta="4" width="22" bottom="5" height="22" image_unselected="media_btn_optimalzoom.png" + image_selected="media_btn_optimalzoom.png" scale_image="true"/> + <icon name="media_panel_divider-4" image_name="media_panel_divider.png" visible="true" height="22" width="3" left_delta="22" + scale_image="false" bottom="5"/> + <button name="new_window" label="" left_delta="3" width="24" bottom_delta="1" height="22" image_unselected="media_btn_newwindow.png" + image_selected="media_btn_newwindow.png" scale_image="true"/> + <icon name="media_panel_divider-5" image_name="media_panel_divider.png" visible="true" height="22" width="3" left_delta="24" + scale_image="false" bottom="5"/> + <button name="close" label="" left_delta="3" width="21" bottom_delta="1" height="22" image_unselected="media_btn_done.png" + image_selected="media_btn_done.png" scale_image="true"/> + </panel> + <panel name="media_hover_controls" width="57" left="74" height="32" bottom="0" visible="false"> + <icon name="media_panel_metacontrols_bg-hover" image_name="media_panel_bg.png" visible="true" height="32" width="57" scale_image="true" bottom="0" left="0"/> + <button name="zoom_frame_hover" label="" left_delta="4" width="22" bottom="5" height="22" image_unselected="media_btn_optimalzoom.png" image_selected="media_btn_optimalzoom.png" + scale_image="true"/> + <icon name="media_panel_divider" image_name="media_panel_divider.png" visible="true" height="22" width="3" left_delta="22" scale_image="false" bottom="5"/> + <button name="new_window_hover" label="" left_delta="3" width="24" bottom_delta="1" height="22" image_unselected="media_btn_newwindow.png" image_selected="media_btn_newwindow.png" + scale_image="true"/> + </panel> + </layout_panel> + <layout_panel user_resize="false"/> + </layout_stack> +</panel> diff --git a/linden/indra/newview/viewer_manifest.py b/linden/indra/newview/viewer_manifest.py index 6b5e800..fcebda9 100755 --- a/linden/indra/newview/viewer_manifest.py +++ b/linden/indra/newview/viewer_manifest.py @@ -229,6 +229,12 @@ class WindowsManifest(ViewerManifest): self.path("imprudence.url") + # Plugin host application + self.path(os.path.join(os.pardir, + 'llplugin', 'slplugin', self.args['configuration'], "SLPlugin.exe"), + "SLPlugin.exe") + + self.path("featuretable.txt") # For use in crash reporting (generates minidumps) @@ -251,7 +257,41 @@ class WindowsManifest(ViewerManifest): self.path("alut.dll") self.end_prefix() - # Mozilla appears to force a dependency on these files so we need to ship it (CP) - updated to vc8 versions (nyx) + + # Media plugins - QuickTime + if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"): + self.path("media_plugin_quicktime.dll") + self.end_prefix() + + # Media plugins - WebKit/Qt + if self.prefix(src='../media_plugins/webkit/%s' % self.args['configuration'], dst="llplugin"): + self.path("media_plugin_webkit.dll") + self.end_prefix() + + # For WebKit/Qt plugin runtimes + if self.prefix(src="../../libraries/i686-win32/lib/release", dst="llplugin"): + self.path("libeay32.dll") + self.path("qtcore4.dll") + self.path("qtgui4.dll") + self.path("qtnetwork4.dll") + self.path("qtopengl4.dll") + self.path("qtwebkit4.dll") + self.path("ssleay32.dll") + self.end_prefix() + + # For WebKit/Qt plugin runtimes (image format plugins) + if self.prefix(src="../../libraries/i686-win32/lib/release/imageformats", dst="llplugin/imageformats"): + self.path("qgif4.dll") + self.path("qico4.dll") + self.path("qjpeg4.dll") + self.path("qmng4.dll") + self.path("qsvg4.dll") + self.path("qtiff4.dll") + self.end_prefix() + + # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388 + self.path("skins/default/xui/en-us/mime_types_windows.xml", "skins/default/xui/en-us/mime_types.xml") + # These need to be installed as a SxS assembly, currently a 'private' assembly. # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx if self.prefix(src=self.args['configuration'], dst=""): @@ -278,34 +318,6 @@ class WindowsManifest(ViewerManifest): # same thing for auto-updater. #self.path(src="%s/imprudence-bin.exe.config" % self.args['configuration'], dst="updater.exe.config") - # Mozilla runtime DLLs (CP) - if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): - self.path("freebl3.dll") - self.path("js3250.dll") - self.path("nspr4.dll") - self.path("nss3.dll") - self.path("nssckbi.dll") - self.path("plc4.dll") - self.path("plds4.dll") - self.path("smime3.dll") - self.path("softokn3.dll") - self.path("ssl3.dll") - self.path("xpcom.dll") - self.path("xul.dll") - self.end_prefix() - - # Mozilla runtime misc files (CP) - if self.prefix(src="app_settings/mozilla"): - self.path("chrome/*.*") - self.path("components/*.*") - self.path("greprefs/*.*") - self.path("plugins/*.*") - self.path("res/*.*") - self.path("res/*/*") - self.end_prefix() - - # Mozilla hack to get it to accept newer versions of msvc*80.dll than are listed in manifest - # necessary as llmozlib2-vc80.lib refers to an old version of msvc*80.dll - can be removed when new version of llmozlib is built - Nyx # Vivox runtimes if self.prefix(src="vivox-runtime/i686-win32", dst=""): # self.path("alut.dll") @@ -534,11 +546,8 @@ class DarwinManifest(ViewerManifest): self.path(self.args['configuration'] + "/Imprudence.app", dst="") if self.prefix(src="", dst="Contents"): # everything goes in Contents - # Expand the tar file containing the assorted mozilla bits into - # <bundle>/Contents/MacOS/ - self.contents_of_tar(self.args['source']+'/mozilla-universal-darwin.tgz', 'MacOS') - - self.path("Info-Imprudence.plist", dst="Info.plist") + + self.path("Info-Imprudence.plist", dst="Info.plist") # copy additional libs in <bundle>/Contents/MacOS/ if self.prefix(src="../../libraries/universal-darwin/lib_release", dst="MacOS/"): @@ -590,12 +599,6 @@ class DarwinManifest(ViewerManifest): self.end_prefix("../../libraries/universal-darwin/lib_release") - # replace the default theme with our custom theme (so scrollbars work). - if self.prefix(src="mozilla-theme", dst="MacOS/chrome"): - self.path("classic.jar") - self.path("classic.manifest") - self.end_prefix("MacOS/chrome") - # most everything goes in the Resources directory if self.prefix(src="", dst="Resources"): super(DarwinManifest, self).construct() @@ -723,7 +726,21 @@ class DarwinManifest(ViewerManifest): # our apps # self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app") self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app") + + # plugin launcher + self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin", "SLPlugin") + + # plugins + if self.prefix(src="", dst="llplugin"): + self.path("../media_plugins/quicktime/" + self.args['configuration'] + "/media_plugin_quicktime.dylib", "media_plugin_quicktime.dylib") + self.path("../media_plugins/webkit/" + self.args['configuration'] + "/media_plugin_webkit.dylib", "media_plugin_webkit.dylib") + self.path("../../libraries/universal-darwin/lib_release/libllqtwebkit.dylib", "libllqtwebkit.dylib") + + self.end_prefix("llplugin") + # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388 + self.path("skins/default/xui/en-us/mime_types_mac.xml", "skins/default/xui/en-us/mime_types.xml") + # command line arguments for connecting to the proper grid self.put_in_file(self.flags_list(), 'arguments.txt') @@ -766,7 +783,7 @@ class DarwinManifest(ViewerManifest): # make sure we don't have stale files laying about self.remove(sparsename, finalname) - self.run_command('hdiutil create "%(sparse)s" -volname "%(vol)s" -fs HFS+ -type SPARSE -megabytes 300 -layout SPUD' % { + self.run_command('hdiutil create "%(sparse)s" -volname "%(vol)s" -fs HFS+ -type SPARSE -megabytes 400 -layout SPUD' % { 'sparse':sparsename, 'vol':volname}) @@ -851,6 +868,23 @@ class LinuxManifest(ViewerManifest): # Create an appropriate gridargs.dat for this package, denoting required grid. self.put_in_file(self.flags_list(), 'gridargs.dat') + self.path("linux_tools/launch_url.sh","launch_url.sh") + self.path("../llplugin/slplugin/SLPlugin", "bin/SLPlugin") + if self.prefix("res-sdl"): + self.path("*") + # recurse + self.end_prefix("res-sdl") + + # plugins + if self.prefix(src="", dst="bin/llplugin"): + self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so") + self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") + self.end_prefix("bin/llplugin") + + # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388 + self.path("skins/default/xui/en-us/mime_types_linux.xml", "skins/default/xui/en-us/mime_types.xml") + + self.path("featuretable_linux.txt") def package_finish(self): @@ -904,17 +938,7 @@ class Linux_i686Manifest(LinuxManifest): def construct(self): super(Linux_i686Manifest, self).construct() self.path("imprudence-stripped","bin/do-not-directly-run-imprudence-bin") -# self.path("../linux_crash_logger/linux-crash-logger-stripped","linux-crash-logger.bin") - self.path("linux_tools/launch_url.sh","launch_url.sh") - if self.prefix("res-sdl"): - self.path("*") - # recurse - self.end_prefix("res-sdl") - - self.path("featuretable_linux.txt") - #self.path("secondlife-i686.supp") - self.path("app_settings/mozilla-runtime-linux-i686") if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"): self.path("libapr-1.so.0") diff --git a/linden/indra/newview/viewer_manifest.py~ b/linden/indra/newview/viewer_manifest.py~ new file mode 100755 index 0000000..452b165 --- /dev/null +++ b/linden/indra/newview/viewer_manifest.py~ @@ -0,0 +1,1176 @@ +#!/usr/bin/python +# @file viewer_manifest.py +# @author Ryan Williams +# @brief Description of all installer viewer files, and methods for packaging +# them into installers for all supported platforms. +# +# $LicenseInfo:firstyear=2006&license=viewergpl$ +# +# Copyright (c) 2006-2009, Linden Research, Inc. +# +# Second Life Viewer Source Code +# The source code in this file ("Source Code") is provided by Linden Lab +# to you under the terms of the GNU General Public License, version 2.0 +# ("GPL"), unless you have obtained a separate licensing agreement +# ("Other License"), formally executed by you and Linden Lab. Terms of +# the GPL can be found in doc/GPL-license.txt in this distribution, or +# online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +# +# There are special exceptions to the terms and conditions of the GPL as +# it is applied to this Source Code. View the full text of the exception +# in the file doc/FLOSS-exception.txt in this software distribution, or +# online at +# http://secondlifegrid.net/programs/open_source/licensing/flossexception +# +# By copying, modifying or distributing this software, you acknowledge +# that you have read and understood your obligations described above, +# and agree to abide by those obligations. +# +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + +# DO NOT RUN THIS FILE DIRECTLY +# Instead, run develop.py with "configure -DPACKAGE:BOOL=ON" e.g.: +# develop.py -G vc80 configure -DPACKAGE:BOOL=ON +# to generate the "package" project in Visual Studio 2005 +# Note: as of Imprudence 1.3, this defaults to on for Windows + +import sys +import os.path +import re +import tarfile +viewer_dir = os.path.dirname(__file__) +# add llmanifest library to our path so we don't have to muck with PYTHONPATH +sys.path.append(os.path.join(viewer_dir, '../lib/python/indra/util')) +from llmanifest import LLManifest, main, proper_windows_path, path_ancestors + +class ViewerManifest(LLManifest): + def construct(self): + super(ViewerManifest, self).construct() + self.exclude("*.svn*") + self.path(src="../../scripts/messages/message_template.msg", dst="app_settings/message_template.msg") + self.path(src="../../etc/message.xml", dst="app_settings/message.xml") + + if self.prefix(src="app_settings"): + self.exclude("logcontrol.xml") + self.exclude("logcontrol-dev.xml") + self.path("*.pem") + self.path("*.ini") + self.path("*.xml") + self.path("*.db2") + + # include the entire shaders directory recursively + self.path("shaders") + # ... and the entire windlight directory + self.path("windlight") + self.end_prefix("app_settings") + + if self.prefix(src="character"): + self.path("*.llm") + self.path("*.xml") + self.path("*.tga") + self.end_prefix("character") + + # Include our fonts + if self.prefix(src="fonts"): + self.path("LiberationSans-Bold.ttf") + self.path("LiberationSans-Regular.ttf") + self.path("VeraMono.ttf") + self.path("DejaVuSansCondensed-BoldOblique.ttf") + self.path("DejaVuSansCondensed-Bold.ttf") + self.path("DejaVuSansCondensed-Oblique.ttf") + self.path("DejaVuSansCondensed.ttf") + self.path("GPL.txt") + self.path("Liberation-License.txt") + self.path("Vera-License.txt") + self.end_prefix("fonts") + + # skins + if self.prefix(src="skins"): + self.path("paths.xml") + # include the entire textures directory recursively + if self.prefix(src="*/textures"): + self.path("*.tga") + self.path("*.j2c") + self.path("*.jpg") + self.path("*.png") + self.path("textures.xml") + self.end_prefix("*/textures") + self.path("*/xui/*/*.xml") + self.path("*/*.xml") + + # Local HTML files (e.g. loading screen) + if self.prefix(src="*/html"): + self.path("*.png") + self.path("*/*/*.html") + self.path("*/*/*.gif") + self.path("*/*/*.png") + self.end_prefix("*/html") + self.end_prefix("skins") + + # Files in the newview/ directory + self.path("gpu_table.txt") + + + # Gather up the README file, etc. + def gather_documents(self): + # From the top level directory (imprudence) + if self.prefix("../../..", dst=""): + self.path("README.txt") + self.path("MANIFESTO.txt") + self.path("CONTRIBUTE.txt") + self.path("RELEASE_NOTES.txt") + self.path("ChangeLog.txt", required=False) + self.end_prefix("../../..") + + # From the linden directory + if self.prefix("../..", dst="doc"): + self.path("LICENSE-source.txt") + self.path("LICENSE-logos.txt", "LICENSE-artwork.txt") + self.end_prefix("../..") + + # From the linden/doc directory + if self.prefix("../../doc", dst="doc"): + self.path("contributions.txt") + self.path("GPL-license.txt", "GPL.txt") + self.path("FLOSS-exception.txt") + self.end_prefix("../../doc") + + + def login_channel(self): + """Channel reported for login and upgrade purposes ONLY; + used for A/B testing""" + # NOTE: Do not return the normal channel if login_channel + # is not specified, as some code may branch depending on + # whether or not this is present + return self.args.get('login_channel') + + def grid(self): + return self.args['grid'] + def channel(self): + return self.args['channel'] + def channel_unique(self): + return self.channel().replace("Imprudence", "").strip() + def channel_oneword(self): + return "".join(self.channel_unique().split()) + def channel_lowerword(self): + return self.channel_oneword().lower() + + def flags_list(self): + """ Convenience function that returns the command-line flags + for the grid""" + + # Set command line flags relating to the target grid + grid_flags = '' + if not self.default_grid(): + grid_flags = "--grid %(grid)s "\ + "--helperuri http://preview-%(grid)s.secondlife.com/helpers/" %\ + {'grid':self.grid()} + + # set command line flags for channel + channel_flags = '' + if self.login_channel() and self.login_channel() != self.channel(): + # Report a special channel during login, but use default + channel_flags = '--channel "%s"' % (self.login_channel()) + elif not self.default_channel(): + channel_flags = '--channel "%s"' % self.channel() + + # Deal with settings + setting_flags = '' + if not self.default_channel() or not self.default_grid(): + if self.default_grid(): + setting_flags = '--settings settings_%s.xml'\ + % self.channel_lowerword() + else: + setting_flags = '--settings settings_%s_%s.xml'\ + % (self.grid(), self.channel_lowerword()) + + return " ".join((channel_flags, grid_flags, setting_flags)).strip() + + +class WindowsManifest(ViewerManifest): + def final_exe(self): + if self.default_channel(): + if self.default_grid(): + return "imprudence.exe" + else: + return "imprudencepreview.exe" + else: + return ''.join(self.channel().split()) + '.exe' + + + def construct(self): + super(WindowsManifest, self).construct() + # the final exe is complicated because we're not sure where it's coming from, + # nor do we have a fixed name for the executable + self.path(self.find_existing_file('debug/imprudence-bin.exe', 'release/imprudence-bin.exe', 'relwithdebinfo/imprudence-bin.exe'), dst=self.final_exe()) + + self.gather_documents() + + if self.prefix("../..", dst="doc"): + self.path("LICENSE-libraries.txt") + self.end_prefix("../..") + + + self.path("imprudence.url") + + # Plugin host application + self.path(os.path.join(os.pardir, + 'llplugin', 'slplugin', self.args['configuration'], "SLPlugin.exe"), + "SLPlugin.exe") + + + self.path("featuretable.txt") + + # For use in crash reporting (generates minidumps) + self.path("dbghelp.dll") + + # For using FMOD for sound... DJS + #self.path("fmod.dll") + + # For spellchecking + self.path("libhunspell.dll") + + # For textures + if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): + self.path("openjpeg.dll") + self.end_prefix() + + # For sound + if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): + self.path("openal32.dll") + self.path("alut.dll") + self.end_prefix() + + + # Media plugins - QuickTime + if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"): + self.path("media_plugin_quicktime.dll") + self.end_prefix() + + # Media plugins - WebKit/Qt + if self.prefix(src='../media_plugins/webkit/%s' % self.args['configuration'], dst="llplugin"): + self.path("media_plugin_webkit.dll") + self.end_prefix() + + # For WebKit/Qt plugin runtimes + if self.prefix(src="../../libraries/i686-win32/lib/release", dst="llplugin"): + self.path("libeay32.dll") + self.path("qtcore4.dll") + self.path("qtgui4.dll") + self.path("qtnetwork4.dll") + self.path("qtopengl4.dll") + self.path("qtwebkit4.dll") + self.path("ssleay32.dll") + self.end_prefix() + + # For WebKit/Qt plugin runtimes (image format plugins) + if self.prefix(src="../../libraries/i686-win32/lib/release/imageformats", dst="llplugin/imageformats"): + self.path("qgif4.dll") + self.path("qico4.dll") + self.path("qjpeg4.dll") + self.path("qmng4.dll") + self.path("qsvg4.dll") + self.path("qtiff4.dll") + self.end_prefix() + + # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388 + self.path("skins/default/xui/en-us/mime_types_windows.xml", "skins/default/xui/en-us/mime_types.xml") + + # These need to be installed as a SxS assembly, currently a 'private' assembly. + # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx + if self.prefix(src=self.args['configuration'], dst=""): + if self.args['configuration'] == 'Debug': + self.path("msvcr80d.dll") + self.path("msvcp80d.dll") + self.path("Microsoft.VC80.DebugCRT.manifest") + else: + self.path("msvcr80.dll") + self.path("msvcp80.dll") + self.path("Microsoft.VC80.CRT.manifest") + self.end_prefix() + + # The config file name needs to match the exe's name. + self.path(src="%s/imprudence-bin.exe.config" % self.args['configuration'], dst=self.final_exe() + ".config") + + # We need this one too, so that llkdu loads at runtime - DEV-41194 + #self.path(src="%s/imprudence-bin.exe.config" % self.args['configuration'], dst="llkdu.dll.2.config") + self.path("llkdu.dll.2.config") + + # We need this one too, so that win_crash_logger.exe loads at runtime - DEV-19004 + #self.path(src="%s/imprudence-bin.exe.config" % self.args['configuration'], dst="win_crash_logger.exe.config") + + # same thing for auto-updater. + #self.path(src="%s/imprudence-bin.exe.config" % self.args['configuration'], dst="updater.exe.config") + + # Vivox runtimes + if self.prefix(src="vivox-runtime/i686-win32", dst=""): + # self.path("alut.dll") + self.path("wrap_oal.dll") + self.path("SLVoice.exe") + # self.path("SLVoiceAgent.exe") + # self.path("libeay32.dll") + # self.path("srtp.dll") + # self.path("ssleay32.dll") + # self.path("tntk.dll") + self.path("vivoxsdk.dll") + self.path("ortp.dll") + + self.end_prefix() + + # Gstreamer plugins + if self.prefix(src="lib/gstreamer-plugins", dst=""): + self.path("*.dll", dst="lib/gstreamer-plugins/*.dll") + self.end_prefix() + + # Gstreamer libs + if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): + self.path("iconv.dll") + self.path("libxml2.dll") + self.path("libcairo-2.dll") + self.path("libgio-2.0-0.dll") + self.path("libglib-2.0-0.dll") + self.path("libgmodule-2.0-0.dll") + self.path("libgobject-2.0-0.dll") + self.path("libgthread-2.0-0.dll") + self.path("charset.dll") + self.path("intl.dll") + self.path("libgcrypt-11.dll") + self.path("libgnutls-26.dll") + self.path("libgpg-error-0.dll") + self.path("libgstapp.dll") + self.path("libgstaudio.dll") + self.path("libgstbase-0.10.dll") + self.path("libgstcdda.dll") + self.path("libgstcontroller-0.10.dll") + self.path("libgstdataprotocol-0.10.dll") + self.path("libgstdshow.dll") + self.path("libgstfft.dll") + self.path("libgstinterfaces.dll") + self.path("libgstnet-0.10.dll") + self.path("libgstnetbuffer.dll") + self.path("libgstpbutils.dll") + self.path("libgstreamer-0.10.dll") + self.path("libgstriff.dll") + self.path("libgstrtp.dll") + self.path("libgstrtsp.dll") + self.path("libgstsdp.dll") + self.path("libgsttag.dll") + self.path("libgstvideo.dll") + self.path("libjpeg.dll") + self.path("libmp3lame-0.dll") + self.path("libneon-27.dll") + self.path("libogg-0.dll") + self.path("liboil-0.3-0.dll") + self.path("libopenjpeg-2.dll") + self.path("libpng12-0.dll") + self.path("libschroedinger-1.0-0.dll") + self.path("libspeex-1.dll") + self.path("libtheora-0.dll") + self.path("libvorbis-0.dll") + self.path("libvorbisenc-2.dll") + self.path("libxml2-2.dll") + self.path("glew32.dll") + self.path("xvidcore.dll") + self.path("zlib1.dll") + self.end_prefix() + +# # pull in the crash logger and updater from other projects +# self.path(src=self.find_existing_file( # tag:"crash-logger" here as a cue to the exporter +# "../win_crash_logger/debug/windows-crash-logger.exe", +# "../win_crash_logger/release/windows-crash-logger.exe", +# "../win_crash_logger/relwithdebinfo/windows-crash-logger.exe"), +# dst="win_crash_logger.exe") + self.path(src=self.find_existing_file( + "../win_updater/debug/windows-updater.exe", + "../win_updater/release/windows-updater.exe", + "../win_updater/relwithdebinfo/windows-updater.exe"), + dst="updater.exe") + + # For google-perftools tcmalloc allocator. + #if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): + # self.path("libtcmalloc_minimal.dll") + # self.end_prefix() + + + def nsi_file_commands(self, install=True): + def wpath(path): + if path.endswith('/') or path.endswith(os.path.sep): + path = path[:-1] + path = path.replace('/', '\\') + return path + + result = "" + dest_files = [pair[1] for pair in self.file_list if pair[0] and os.path.isfile(pair[1])] + # sort deepest hierarchy first + dest_files.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b)) + dest_files.reverse() + out_path = None + for pkg_file in dest_files: + rel_file = os.path.normpath(pkg_file.replace(self.get_dst_prefix()+os.path.sep,'')) + installed_dir = wpath(os.path.join('$INSTDIR', os.path.dirname(rel_file))) + pkg_file = wpath(os.path.normpath(pkg_file)) + if installed_dir != out_path: + if install: + out_path = installed_dir + result += 'SetOutPath ' + out_path + '\n' + if install: + result += 'File ' + pkg_file + '\n' + else: + result += 'Delete ' + wpath(os.path.join('$INSTDIR', rel_file)) + '\n' + # at the end of a delete, just rmdir all the directories + if not install: + deleted_file_dirs = [os.path.dirname(pair[1].replace(self.get_dst_prefix()+os.path.sep,'')) for pair in self.file_list] + # find all ancestors so that we don't skip any dirs that happened to have no non-dir children + deleted_dirs = [] + for d in deleted_file_dirs: + deleted_dirs.extend(path_ancestors(d)) + # sort deepest hierarchy first + deleted_dirs.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b)) + deleted_dirs.reverse() + prev = None + for d in deleted_dirs: + if d != prev: # skip duplicates + result += 'RMDir ' + wpath(os.path.join('$INSTDIR', os.path.normpath(d))) + '\n' + prev = d + + return result + + def package_finish(self): + # a standard map of strings for replacing in the templates + substitution_strings = { + 'version' : '.'.join(self.args['version']).replace(' ', '_'), + 'version_short' : '.'.join(self.args['version'][:-1]).replace(' ', '_'), + 'version_dashes' : '-'.join(self.args['version']).replace(' ', '_'), + 'final_exe' : self.final_exe(), + 'grid':self.args['grid'], + 'grid_caps':self.args['grid'].upper(), + # escape quotes becase NSIS doesn't handle them well + 'flags':self.flags_list().replace('"', '$\\"'), + 'channel':self.channel(), + 'channel_oneword':self.channel_oneword(), + 'channel_unique':self.channel_unique(), + } + + version_vars = """ + !define INSTEXE "%(final_exe)s" + !define VERSION "%(version_short)s" + !define VERSION_LONG "%(version)s" + !define VERSION_DASHES "%(version_dashes)s" + """ % substitution_strings + if self.default_channel(): + if self.default_grid(): + # release viewer + installer_file = "Imprudence_%(version_dashes)s_Setup.exe" + grid_vars_template = """ + OutFile "%(installer_file)s" + !define INSTFLAGS "%(flags)s" + !define INSTNAME "Imprudence" + !define SHORTCUT "Imprudence" + !define URLNAME "imprudence" + Caption "Imprudence ${VERSION}" + """ + else: + # beta grid viewer + installer_file = "Imprudence_%(version_dashes)s_(%(grid_caps)s)_Setup.exe" + grid_vars_template = """ + OutFile "%(installer_file)s" + !define INSTFLAGS "%(flags)s" + !define INSTNAME "Imprudence%(grid_caps)s" + !define SHORTCUT "Imprudence (%(grid_caps)s)" + !define URLNAME "imprudence%(grid)s" + !define UNINSTALL_SETTINGS 1 + Caption "Imprudence %(grid)s ${VERSION}" + """ + else: + # some other channel on some grid + installer_file = "Imprudence_%(version_dashes)s_%(channel_oneword)s_Setup.exe" + grid_vars_template = """ + OutFile "%(installer_file)s" + !define INSTFLAGS "%(flags)s" + !define INSTNAME "Imprudence%(channel_oneword)s" + !define SHORTCUT "%(channel)s" + !define URLNAME "imprudence" + !define UNINSTALL_SETTINGS 1 + Caption "%(channel)s ${VERSION}" + """ + if 'installer_name' in self.args: + installer_file = self.args['installer_name'] + else: + installer_file = installer_file % substitution_strings + substitution_strings['installer_file'] = installer_file + + tempfile = "imprudence_setup_tmp.nsi" + # the following replaces strings in the nsi template + # it also does python-style % substitution + self.replace_in("installers/windows/installer_template.nsi", tempfile, { + "%%VERSION%%":version_vars, + "%%SOURCE%%":self.get_src_prefix(), + "%%GRID_VARS%%":grid_vars_template % substitution_strings, + "%%INSTALL_FILES%%":self.nsi_file_commands(True), + "%%DELETE_FILES%%":self.nsi_file_commands(False)}) + + # We use the Unicode version of NSIS, available from + # http://www.scratchpaper.com/ + NSIS_path = 'C:\\Program Files\\NSIS\\Unicode\\makensis.exe' + self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile)) + # self.remove(self.dst_path_of(tempfile)) + # If we're on a build machine, sign the code using our Authenticode certificate. JC + sign_py = 'C:\\buildscripts\\code-signing\\sign.py' + if os.path.exists(sign_py): + self.run_command(sign_py + ' ' + self.dst_path_of(installer_file)) + else: + print "Skipping code signing,", sign_py, "does not exist" + self.created_path(self.dst_path_of(installer_file)) + self.package_file = installer_file + + +class DarwinManifest(ViewerManifest): + def construct(self): + # copy over the build result (this is a no-op if run within the xcode script) + self.path(self.args['configuration'] + "/Imprudence.app", dst="") + + if self.prefix(src="", dst="Contents"): # everything goes in Contents + + self.path("Info-Imprudence.plist", dst="Info.plist") + + # copy additional libs in <bundle>/Contents/MacOS/ + if self.prefix(src="../../libraries/universal-darwin/lib_release", dst="MacOS/"): + + self.path("libndofdev.dylib") + + self.path("libopenal.1.dylib") + self.path("libalut.0.dylib") + + self.path("libglib-2.0.dylib") + self.path("libgmodule-2.0.dylib") + self.path("libgobject-2.0.dylib") + self.path("libgthread-2.0.dylib") + + self.path("libgstreamer-0.10.dylib") + self.path("libgstapp-0.10.dylib") + self.path("libgstaudio-0.10.dylib") + self.path("libgstbase-0.10.dylib") + self.path("libgstcdda-0.10.dylib") + self.path("libgstcontroller-0.10.dylib") + self.path("libgstdataprotocol-0.10.dylib") + self.path("libgstfft-0.10.dylib") + self.path("libgstinterfaces-0.10.dylib") + self.path("libgstnet-0.10.dylib") + self.path("libgstnetbuffer-0.10.dylib") + self.path("libgstpbutils-0.10.dylib") + self.path("libgstriff-0.10.dylib") + self.path("libgstrtp-0.10.dylib") + self.path("libgstrtsp-0.10.dylib") + self.path("libgstsdp-0.10.dylib") + self.path("libgsttag-0.10.dylib") + self.path("libgstvideo-0.10.dylib") + + self.path("libxml2.2.dylib") + self.path("libfaad.2.dylib") + self.path("libFLAC.8.dylib") + self.path("libintl.3.dylib") + self.path("libjpeg.62.dylib") + self.path("libpng12.0.dylib") + self.path("libneon.27.dylib") + self.path("libogg.0.dylib") + self.path("liboil-0.3.0.dylib") + self.path("libopenjpeg.1.4.dylib") + self.path("libtheora.0.dylib") + self.path("libvorbis.0.dylib") + self.path("libvorbisenc.2.dylib") + self.path("libvorbisfile.3.dylib") + + self.end_prefix("../../libraries/universal-darwin/lib_release") + + # most everything goes in the Resources directory + if self.prefix(src="", dst="Resources"): + super(DarwinManifest, self).construct() + + if self.prefix("cursors_mac"): + self.path("*.tif") + self.end_prefix("cursors_mac") + + # From the linden directory + if self.prefix("../..", dst="doc"): + self.path("LICENSE-libraries.txt") + self.end_prefix("../..") + + self.gather_documents() + + self.path("featuretable_mac.txt") + self.path("SecondLife.nib") + + self.path("viewer.icns") + + # Translations + self.path("English.lproj") + self.path("German.lproj") + self.path("Japanese.lproj") + self.path("Korean.lproj") + self.path("da.lproj") + self.path("es.lproj") + self.path("fr.lproj") + self.path("hu.lproj") + self.path("it.lproj") + self.path("nl.lproj") + self.path("pl.lproj") + self.path("pt.lproj") + self.path("ru.lproj") + self.path("tr.lproj") + self.path("uk.lproj") + self.path("zh-Hans.lproj") + + + if self.prefix(src="../../libraries/universal-darwin/lib_release/gstreamer-plugins", dst="lib/gstreamer-plugins"): + self.path("libgstaacparse.so") + self.path("libgstadder.so") + self.path("libgstaiffparse.so") + self.path("libgstamrparse.so") + self.path("libgstapp.so") + self.path("libgstaudioconvert.so") + self.path("libgstaudiorate.so") + self.path("libgstaudioresample.so") + self.path("libgstautodetect.so") + self.path("libgstavi.so") + self.path("libgstcoreelements.so") + self.path("libgstcoreindexers.so") + self.path("libgstdebug.so") + self.path("libgstdecodebin.so") + self.path("libgstdecodebin2.so") + self.path("libgstdeinterlace2.so") + self.path("libgstequalizer.so") + self.path("libgstfaad.so") + self.path("libgstffmpeg.so") + self.path("libgstffmpegcolorspace.so") + self.path("libgstffmpegscale.so") + self.path("libgstfilter.so") + self.path("libgstflac.so") + self.path("libgstflv.so") + self.path("libgstgdp.so") + self.path("libgsth264parse.so") + self.path("libgsticydemux.so") + self.path("libgstid3demux.so") + self.path("libgstinterleave.so") + self.path("libgstjpeg.so") + self.path("libgstlevel.so") + self.path("libgstmetadata.so") + self.path("libgstmpeg4videoparse.so") + self.path("libgstmpegdemux.so") + self.path("libgstmpegvideoparse.so") + self.path("libgstmultifile.so") + self.path("libgstmultipart.so") + self.path("libgstneonhttpsrc.so") + self.path("libgstogg.so") + self.path("libgstosxaudio.so") + self.path("libgstosxvideosink.so") + self.path("libgstplaybin.so") + self.path("libgstpng.so") + self.path("libgstpostproc.so") + self.path("libgstqtdemux.so") + #self.path("libgstqtwrapper.so") + self.path("libgstqueue2.so") + self.path("libgstreal.so") + self.path("libgstrtp.so") + self.path("libgstrtpmanager.so") + self.path("libgstrtsp.so") + self.path("libgstsdpelem.so") + self.path("libgstselector.so") + self.path("libgststereo.so") + self.path("libgsttcp.so") + self.path("libgsttheora.so") + self.path("libgsttypefindfunctions.so") + self.path("libgstudp.so") + self.path("libgstvideobalance.so") + self.path("libgstvideobox.so") + self.path("libgstvideocrop.so") + self.path("libgstvideoflip.so") + self.path("libgstvideomixer.so") + self.path("libgstvideorate.so") + self.path("libgstvideoscale.so") + self.path("libgstvideosignal.so") + self.path("libgstvolume.so") + self.path("libgstvorbis.so") + self.path("libgstwavparse.so") + + self.end_prefix("../../libraries/universal-darwin/lib_release/gstreamer-plugins") + + + # SLVoice and vivox lols + self.path("vivox-runtime/universal-darwin/libalut.dylib", "libalut.dylib") + self.path("vivox-runtime/universal-darwin/libopenal.dylib", "libopenal.dylib") + self.path("vivox-runtime/universal-darwin/libortp.dylib", "libortp.dylib") + self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib") + self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice") + #self.path("vivox-runtime/universal-darwin/SLVoiceAgent.app", "SLVoiceAgent.app") + + #libfmodwrapper.dylib + #self.path(self.args['configuration'] + "/libfmodwrapper.dylib", "libfmodwrapper.dylib") + + # our apps +# self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app") + self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app") + + # plugin launcher + self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin", "SLPlugin") + + # plugins + if self.prefix(src="", dst="llplugin"): + self.path("../media_plugins/quicktime/" + self.args['configuration'] + "/media_plugin_quicktime.dylib", "media_plugin_quicktime.dylib") + self.path("../media_plugins/webkit/" + self.args['configuration'] + "/media_plugin_webkit.dylib", "media_plugin_webkit.dylib") + self.path("../../libraries/universal-darwin/lib_release/libllqtwebkit.dylib", "libllqtwebkit.dylib") + + self.end_prefix("llplugin") + + # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388 + self.path("skins/default/xui/en-us/mime_types_mac.xml", "skins/default/xui/en-us/mime_types.xml") + + # command line arguments for connecting to the proper grid + self.put_in_file(self.flags_list(), 'arguments.txt') + + self.end_prefix("Resources") + + self.end_prefix("Contents") + + # NOTE: the -S argument to strip causes it to keep enough info for + # annotated backtraces (i.e. function names in the crash log). 'strip' with no + # arguments yields a slightly smaller binary but makes crash logs mostly useless. + # This may be desirable for the final release. Or not. + if ("package" in self.args['actions'] or + "unpacked" in self.args['actions']): + self.run_command('strip -S "%(viewer_binary)s"' % + { 'viewer_binary' : self.dst_path_of('Contents/MacOS/Second Life')}) + + + def package_finish(self): + channel_standin = 'Imprudence' # hah, our default channel is not usable on its own + if not self.default_channel(): + channel_standin = self.channel() + + imagename="Imprudence_" + '_'.join(self.args['version']) + + # MBW -- If the mounted volume name changes, it breaks the .DS_Store's background image and icon positioning. + # If we really need differently named volumes, we'll need to create multiple DS_Store file images, or use some other trick. + + volname="Imprudence Installer" # DO NOT CHANGE without understanding comment above + + if self.default_channel(): + if not self.default_grid(): + # beta case + imagename = imagename + '_' + self.args['grid'].upper() + else: + # first look, etc + imagename = imagename + '_' + self.channel_oneword().upper() + + sparsename = imagename + ".sparseimage" + finalname = imagename + ".dmg" + # make sure we don't have stale files laying about + self.remove(sparsename, finalname) + + self.run_command('hdiutil create "%(sparse)s" -volname "%(vol)s" -fs HFS+ -type SPARSE -megabytes 400 -layout SPUD' % { + 'sparse':sparsename, + 'vol':volname}) + + # mount the image and get the name of the mount point and device node + hdi_output = self.run_command('hdiutil attach -private "' + sparsename + '"') + devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip() + volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip() + + # Copy everything in to the mounted .dmg + + if self.default_channel() and not self.default_grid(): + app_name = "Imprudence " + self.args['grid'] + else: + app_name = channel_standin.strip() + + # Hack: + # Because there is no easy way to coerce the Finder into positioning + # the app bundle in the same place with different app names, we are + # adding multiple .DS_Store files to svn. There is one for release, + # one for release candidate and one for first look. Any other channels + # will use the release .DS_Store, and will look broken. + # - Ambroff 2008-08-20 + dmg_template = os.path.join( + 'installers', + 'darwin', + '%s-dmg' % "".join(self.channel_unique().split()).lower()) + + if not os.path.exists (self.src_path_of(dmg_template)): + dmg_template = os.path.join ('installers', 'darwin', 'release-dmg') + + for s,d in {self.get_dst_prefix():app_name + ".app", + os.path.join(dmg_template, "_VolumeIcon.icns"): ".VolumeIcon.icns", + os.path.join(dmg_template, "background.jpg"): "background.jpg", + os.path.join(dmg_template, "_DS_Store"): ".DS_Store"}.items(): + print "Copying to dmg", s, d + self.copy_action(self.src_path_of(s), os.path.join(volpath, d)) + + # Hide the background image, DS_Store file, and volume icon file (set their "visible" bit) + self.run_command('SetFile -a V "' + os.path.join(volpath, ".VolumeIcon.icns") + '"') + self.run_command('SetFile -a V "' + os.path.join(volpath, "background.jpg") + '"') + self.run_command('SetFile -a V "' + os.path.join(volpath, ".DS_Store") + '"') + + # Create the alias file (which is a resource file) from the .r + self.run_command('rez "' + self.src_path_of("installers/darwin/release-dmg/Applications-alias.r") + '" -o "' + os.path.join(volpath, "Applications") + '"') + + # Set the alias file's alias and custom icon bits + self.run_command('SetFile -a AC "' + os.path.join(volpath, "Applications") + '"') + + # Set the disk image root's custom icon bit + self.run_command('SetFile -a C "' + volpath + '"') + + # Unmount the image + self.run_command('hdiutil detach -force "' + devfile + '"') + + print "Converting temp disk image to final disk image" + self.run_command('hdiutil convert "%(sparse)s" -format UDZO -imagekey zlib-level=9 -o "%(final)s"' % {'sparse':sparsename, 'final':finalname}) + # get rid of the temp file + self.package_file = finalname + self.remove(sparsename) + +class LinuxManifest(ViewerManifest): + def construct(self): + super(LinuxManifest, self).construct() + + self.path("res/imprudence_icon.png","imprudence_icon.png") + if self.prefix("linux_tools", dst=""): + #self.path("client-readme.txt","README-linux.txt") + self.path("client-readme-voice.txt","README-linux-voice.txt") + #self.path("client-readme-joystick.txt","README-linux-joystick.txt") + self.path("wrapper.sh","imprudence") + self.path("handle_secondlifeprotocol.sh") + self.path("register_secondlifeprotocol.sh") + self.path("getvoice.sh") + self.end_prefix("linux_tools") + + self.gather_documents() + + # From the linden directory + if self.prefix("../..", dst="doc"): + self.path("LICENSE-libraries.txt") + self.end_prefix("../..") + + # Create an appropriate gridargs.dat for this package, denoting required grid. + self.put_in_file(self.flags_list(), 'gridargs.dat') + self.path("linux_tools/launch_url.sh","launch_url.sh") + self.path("../llplugin/slplugin/SLPlugin", "bin/SLPlugin") + if self.prefix("res-sdl"): + self.path("*") + # recurse + self.end_prefix("res-sdl") + + # plugins + if self.prefix(src="", dst="bin/llplugin"): + self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so") + self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") + self.end_prefix("bin/llplugin") + + # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388 + self.path("skins/default/xui/en-us/mime_types_linux.xml", "skins/default/xui/en-us/mime_types.xml") + + self.path("featuretable_linux.txt") + + + def package_finish(self): + if 'installer_name' in self.args: + installer_name = self.args['installer_name'] + else: + installer_name_components = ['Imprudence_', self.args.get('arch')] + installer_name_components.extend(self.args['version']) + installer_name = "_".join(installer_name_components) + if self.default_channel(): + if not self.default_grid(): + installer_name += '_' + self.args['grid'].upper() + else: + installer_name += '_' + self.channel_oneword().upper() + + # Fix access permissions + self.run_command(""" + find %(dst)s -type d | xargs --no-run-if-empty chmod 755; + find %(dst)s -type f -perm 0700 | xargs --no-run-if-empty chmod 0755; + find %(dst)s -type f -perm 0500 | xargs --no-run-if-empty chmod 0555; + find %(dst)s -type f -perm 0600 | xargs --no-run-if-empty chmod 0644; + find %(dst)s -type f -perm 0400 | xargs --no-run-if-empty chmod 0444; + true""" % {'dst':self.get_dst_prefix() }) + + self.package_file = installer_name + '.tar.bz2' + + # Disabled for now. It's a waste of time to package every compile. + + # if("package" in self.args['actions'] or + # "unpacked" in self.args['actions']): + # + # # temporarily move directory tree so that it has the right + # # name in the tarfile + # self.run_command("mv %(dst)s %(inst)s" % { + # 'dst': self.get_dst_prefix(), + # 'inst': self.build_path_of(installer_name)}) + # try: + # # --numeric-owner hides the username of the builder for + # # security etc. + # self.run_command('tar -C %(dir)s --numeric-owner -cjf ' + # '%(inst_path)s.tar.bz2 %(inst_name)s' % { + # 'dir': self.get_build_prefix(), + # 'inst_name': installer_name, + # 'inst_path':self.build_path_of(installer_name)}) + # finally: + # self.run_command("mv %(inst)s %(dst)s" % { + # 'dst': self.get_dst_prefix(), + # 'inst': self.build_path_of(installer_name)}) + +class Linux_i686Manifest(LinuxManifest): + def construct(self): + super(Linux_i686Manifest, self).construct() + self.path("imprudence-stripped","bin/do-not-directly-run-imprudence-bin") + + + if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"): + self.path("libapr-1.so.0") + self.path("libaprutil-1.so.0") + self.path("libdb-4.2.so") + self.path("libcrypto.so.0.9.7") + self.path("libexpat.so.1") + self.path("libssl.so.0.9.7") + self.path("libuuid.so", "libuuid.so.1") + self.path("libSDL-1.2.so.0") + self.path("libELFIO.so") + self.path("libopenjpeg.so.2") + self.path("libxml2.so.2") + self.path("libz.so.1") + + # OpenAL + self.path("libopenal.so.1") + self.path("libalut.so.0") + + # GTK+ and dependencies + self.path("libatk-1.0.so.0") + self.path("libcairo.so.2") + self.path("libfontconfig.so.1") + self.path("libfreetype.so.6") + # self.path("libgdk_pixbuf-2.0.so.0") # see linux64 why + self.path("libgdk-x11-2.0.so.0") + self.path("libgtk-x11-2.0.so.0") + # self.path("libpango-1.0.so.0") # dto. + # self.path("libpangoft2-1.0.so.0") + # self.path("libpangox-1.0.so.0") + # self.path("libpangoxft-1.0.so.0") + self.path("libpixman-1.so.0") + + # Gstreamer libs + self.path("libgstbase-0.10.so.0") + self.path("libgstreamer-0.10.so.0") + self.path("libgstaudio-0.10.so.0") + self.path("libgstbase-0.10.so.0") + self.path("libgstcontroller-0.10.so.0") + self.path("libgstdataprotocol-0.10.so.0") + self.path("libgstinterfaces-0.10.so.0") + self.path("libgstnetbuffer-0.10.so.0") + self.path("libgstpbutils-0.10.so.0") + self.path("libgstriff-0.10.so.0") + self.path("libgstrtp-0.10.so.0") + self.path("libgstrtsp-0.10.so.0") + self.path("libgstsdp-0.10.so.0") + self.path("libgsttag-0.10.so.0") + self.path("libgstvideo-0.10.so.0") + + # Gstreamer plugin dependencies + self.path("libfaad.so.0") + self.path("libogg.so.0") + self.path("libtheora.so.0") + self.path("libvorbis.so.0") + self.path("libvorbisenc.so.2") + self.path("liboil-0.3.so.0") + + # Gstreamer plugins + if self.prefix("gstreamer-plugins"): + self.path("libgstalsa.so") + self.path("libgstasf.so") + self.path("libgstaudioconvert.so") + self.path("libgstaudioresample.so") + self.path("libgstautodetect.so") + self.path("libgstavi.so") + self.path("libgstcoreelements.so") + self.path("libgstcoreindexers.so") + self.path("libgstdecodebin2.so") + self.path("libgstdecodebin.so") + self.path("libgstesd.so") + self.path("libgstfaad.so") + self.path("libgstffmpeg.so") + self.path("libgstgnomevfs.so") + self.path("libgsticydemux.so") + self.path("libgstid3demux.so") + self.path("libgstmpegdemux.so") + self.path("libgstmultifile.so") + self.path("libgstmultipart.so") + self.path("libgstogg.so") + self.path("libgstossaudio.so") + self.path("libgstplaybin.so") + self.path("libgstpulse.so") + self.path("libgstqtdemux.so") + self.path("libgstqueue2.so") + self.path("libgsttcp.so") + self.path("libgsttheora.so") + self.path("libgsttypefindfunctions.so") + self.path("libgstudp.so") + self.path("libgstvideoscale.so") + self.path("libgstvolume.so") + self.path("libgstvorbis.so") + self.path("libgstwavparse.so") + + self.end_prefix("gstreamer-plugins") + + self.end_prefix("lib") + + # Vivox runtimes and libs + if self.prefix(src="vivox-runtime/i686-linux", dst="bin"): + self.path("SLVoice") + self.end_prefix("bin") + + if self.prefix(src="vivox-runtime/i686-linux", dst="lib"): + self.path("libalut.so") + self.path("libortp.so") + self.path("libvivoxsdk.so") + self.end_prefix("lib") + +class Linux_x86_64Manifest(LinuxManifest): + def construct(self): + super(Linux_x86_64Manifest, self).construct() + self.path("imprudence-stripped","bin/do-not-directly-run-imprudence-bin") +# self.path("../linux_crash_logger/linux-crash-logger-stripped","linux-crash-logger.bin") + + self.path("linux_tools/launch_url.sh","launch_url.sh") + if self.prefix("res-sdl"): + self.path("*") + # recurse + self.end_prefix("res-sdl") + + self.path("featuretable_linux.txt") + #self.path("secondlife-x86_64.supp") + + self.path("app_settings/mozilla-runtime-linux-x86_64") + + if self.prefix("../../libraries/x86_64-linux/lib_release_client", dst="lib64"): + self.path("libapr-1.so.0") + self.path("libaprutil-1.so.0") + self.path("libdb-4.2.so") + self.path("libcrypto.so.0.9.8") + self.path("libexpat.so.1") + self.path("libssl.so.0.9.8") + self.path("libuuid.so", "libuuid.so.1") + self.path("libSDL-1.2.so.0") + self.path("libELFIO.so") + self.path("libjpeg.so.7") + self.path("libpng12.so.0") + self.path("libopenjpeg.so.2") + self.path("libxml2.so.2") + #self.path("libz.so.1") #not needed + + # OpenAL + self.path("libopenal.so.1") + self.path("libalut.so.0") + + # GTK+ and dependencies + self.path("libatk-1.0.so.0") + self.path("libcairo.so.2") + self.path("libfontconfig.so.1") + self.path("libfreetype.so.6") + self.path("libgdk_pixbuf-2.0.so.0") # was commented to use systems gdk pixbufs instead - + # but seems webkit needs it o_O . Packaging for testing now. + self.path("libgdk-x11-2.0.so.0") + self.path("libgtk-x11-2.0.so.0") +# self.path("libpango-1.0.so.0") # use systems pango instead +# self.path("libpangoft2-1.0.so.0") # Both gdk pixbufs and pango would load systems modules +# self.path("libpangox-1.0.so.0") # and crash if not compatible or present. +# self.path("libpangoxft-1.0.so.0") # So we depend system gdk pixbufs and pango anyway. + self.path("libpixman-1.so.0") + + # Gstreamer libs + self.path("libgstbase-0.10.so.0") + self.path("libgstreamer-0.10.so.0") + self.path("libgstaudio-0.10.so.0") + self.path("libgstbase-0.10.so.0") + self.path("libgstcontroller-0.10.so.0") + self.path("libgstdataprotocol-0.10.so.0") + self.path("libgstinterfaces-0.10.so.0") + self.path("libgstnetbuffer-0.10.so.0") + self.path("libgstpbutils-0.10.so.0") + self.path("libgstriff-0.10.so.0") + self.path("libgstrtp-0.10.so.0") + self.path("libgstrtsp-0.10.so.0") + self.path("libgstsdp-0.10.so.0") + self.path("libgsttag-0.10.so.0") + self.path("libgstvideo-0.10.so.0") + + # Gstreamer plugin dependencies + self.path("libfaad.so.0") + self.path("libogg.so.0") + self.path("libtheora.so.0") + self.path("libvorbis.so.0") + self.path("libvorbisenc.so.2") + self.path("liboil-0.3.so.0") + + # Gstreamer plugins + if self.prefix("gstreamer-plugins"): + self.path("libgstalsa.so") + self.path("libgstasf.so") + self.path("libgstaudioconvert.so") + self.path("libgstaudioresample.so") + self.path("libgstautodetect.so") + self.path("libgstavi.so") + self.path("libgstcoreelements.so") + self.path("libgstcoreindexers.so") + self.path("libgstdecodebin2.so") + self.path("libgstdecodebin.so") + self.path("libgstesd.so") + self.path("libgstfaad.so") + self.path("libgstffmpeg.so") + self.path("libgstffmpegcolorspace.so") + self.path("libgstgnomevfs.so") + self.path("libgsticydemux.so") + self.path("libgstid3demux.so") + self.path("libgstmpegdemux.so") + self.path("libgstmultifile.so") + self.path("libgstmultipart.so") + self.path("libgstogg.so") + self.path("libgstossaudio.so") + self.path("libgstplaybin.so") + self.path("libgstpulse.so") + self.path("libgstqtdemux.so") + self.path("libgstqueue2.so") + self.path("libgsttcp.so") + self.path("libgsttheora.so") + self.path("libgsttypefindfunctions.so") + self.path("libgstudp.so") + self.path("libgstvideoscale.so") + self.path("libgstvolume.so") + self.path("libgstvorbis.so") + self.path("libgstwavparse.so") + + self.end_prefix("gstreamer-plugins") + self.end_prefix("lib64") + + + # Vivox runtimes and libs + if self.prefix(src="vivox-runtime/i686-linux", dst="bin"): + self.path("SLVoice") + self.end_prefix("bin") + + if self.prefix(src="vivox-runtime/i686-linux", dst="lib32"): + #self.path("libalut.so") + self.path("libortp.so") + self.path("libvivoxsdk.so") + self.end_prefix("lib32") + + # 32bit libs needed for voice + if self.prefix("../../libraries/x86_64-linux/lib_release_client/32bit-compat", dst="lib32"): + self.path("libalut.so") + self.path("libidn.so.11") + self.path("libopenal.so.1") + # self.path("libortp.so") + self.path("libuuid.so.1") + self.end_prefix("lib32") + +if __name__ == "__main__": + main() diff --git a/linden/indra/test_apps/llplugintest/CMakeLists.txt b/linden/indra/test_apps/llplugintest/CMakeLists.txt new file mode 100644 index 0000000..a6cb740 --- /dev/null +++ b/linden/indra/test_apps/llplugintest/CMakeLists.txt @@ -0,0 +1,378 @@ +# -*- cmake -*- + +project(llplugintest) + +include(00-Common) +include(FindOpenGL) +include(LLCommon) +include(LLPlugin) +include(Linking) +include(PluginAPI) +include(LLImage) +include(LLMath) +include(LLMessage) +include(LLRender) +include(LLWindow) +include(Glut) +include(Glui) + +include_directories( + ${LLPLUGIN_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLMESSAGE_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} +) + +if (DARWIN) + include(CMakeFindFrameworks) + find_library(COREFOUNDATION_LIBRARY CoreFoundation) +endif (DARWIN) + +### demo_plugin + +#set(demo_plugin_SOURCE_FILES +# demo_plugin.cpp +# ) +# +#add_library(demo_plugin +# SHARED +# ${demo_plugin_SOURCE_FILES} +#) +# +#target_link_libraries(demo_plugin +# ${LLPLUGIN_LIBRARIES} +# ${LLCOMMON_LIBRARIES} +# ${PLUGIN_API_WINDOWS_LIBRARIES} +#) +# +#add_dependencies(demo_plugin +# ${LLPLUGIN_LIBRARIES} +# ${LLCOMMON_LIBRARIES} +#) +# +#if (DARWIN) +# # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name +# set_target_properties( +# demo_plugin +# PROPERTIES +# PREFIX "" +# BUILD_WITH_INSTALL_RPATH 1 +# INSTALL_NAME_DIR "@executable_path" +# ) +#endif (DARWIN) + +### plugin_host + +#set(plugin_host_SOURCE_FILES +# plugin_host.cpp +# ) +# +#add_executable(plugin_host +# WIN32 +# ${plugin_host_SOURCE_FILES} +#) +# +#set_target_properties(plugin_host +# PROPERTIES +# WIN32_EXECUTABLE +# FALSE +#) +# +#target_link_libraries(plugin_host +# ${LLPLUGIN_LIBRARIES} +# ${LLCOMMON_LIBRARIES} +# ${PLUGIN_API_WINDOWS_LIBRARIES} +#) +# +#add_dependencies(plugin_host +# demo_plugin +# ${LLPLUGIN_LIBRARIES} +# ${LLCOMMON_LIBRARIES} +#) + +### plugin_process_launcher + +#set(plugin_process_launcher_SOURCE_FILES +# plugin_process_launcher.cpp +# ) +# +#add_executable(plugin_process_launcher +# WIN32 +# ${plugin_process_launcher_SOURCE_FILES} +#) +# +#set_target_properties(plugin_process_launcher +# PROPERTIES +# WIN32_EXECUTABLE +# FALSE +#) +# +#target_link_libraries(plugin_process_launcher +# ${LLPLUGIN_LIBRARIES} +# ${LLMESSAGE_LIBRARIES} +# ${LLCOMMON_LIBRARIES} +# ${PLUGIN_API_WINDOWS_LIBRARIES} +#) +# +#add_dependencies(plugin_process_launcher +# SLPlugin +# demo_plugin +# ${LLPLUGIN_LIBRARIES} +# ${LLMESSAGE_LIBRARIES} +# ${LLCOMMON_LIBRARIES} +#) + +### media_simple_test + +#set(media_simple_test_SOURCE_FILES +# media_simple_test.cpp +# ) +# +#add_executable(media_simple_test +# WIN32 +# ${media_simple_test_SOURCE_FILES} +#) +# +#add_dependencies(media_simple_test copy_win_libs) +# +#set_target_properties(media_simple_test +# PROPERTIES +# WIN32_EXECUTABLE +# FALSE +#) +# +#target_link_libraries(media_simple_test +# ${GLUT_LIBRARY} +# ${OPENGL_LIBRARIES} +# ${LLCOMMON_LIBRARIES} +#) + +### media_plugin_test + +#set(media_plugin_test_SOURCE_FILES +# media_plugin_test.cpp +# ) +# +#add_executable(media_plugin_test +# WIN32 +# ${media_plugin_test_SOURCE_FILES} +#) +# +#set_target_properties(media_plugin_test +# PROPERTIES +# WIN32_EXECUTABLE +# FALSE +#) +# +#target_link_libraries(media_plugin_test +# ${GLUT_LIBRARY} +# ${OPENGL_LIBRARIES} +# ${LLPLUGIN_LIBRARIES} +# ${LLMESSAGE_LIBRARIES} +# ${LLCOMMON_LIBRARIES} +# ${PLUGIN_API_WINDOWS_LIBRARIES} +#) +# +#add_dependencies(media_plugin_test +# copy_win_libs +# SLPlugin +# demo_media_plugin +# ${LLPLUGIN_LIBRARIES} +# ${LLMESSAGE_LIBRARIES} +# ${LLCOMMON_LIBRARIES} +#) + +### demo_media_plugin + +#set(demo_media_plugin_SOURCE_FILES +# demo_media_plugin.cpp +# ) +# +#add_library(demo_media_plugin +# SHARED +# ${demo_media_plugin_SOURCE_FILES} +#) +# +#target_link_libraries(demo_media_plugin +# ${LLPLUGIN_LIBRARIES} +# ${LLCOMMON_LIBRARIES} +# ${PLUGIN_API_WINDOWS_LIBRARIES} +#) +# +#add_dependencies(demo_media_plugin +# ${LLPLUGIN_LIBRARIES} +# ${LLCOMMON_LIBRARIES} +#) +# +#if (DARWIN) +# # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name +# set_target_properties( +# demo_media_plugin +# PROPERTIES +# PREFIX "" +# BUILD_WITH_INSTALL_RPATH 1 +# INSTALL_NAME_DIR "@executable_path" +# ) +#endif (DARWIN) + +### demo_media_plugin_2 + +#set(demo_media_plugin_2_SOURCE_FILES +# demo_media_plugin_2.cpp +# ) +# +#add_library(demo_media_plugin_2 +# SHARED +# ${demo_media_plugin_2_SOURCE_FILES} +#) +# +#target_link_libraries(demo_media_plugin_2 +# ${LLPLUGIN_LIBRARIES} +# ${LLCOMMON_LIBRARIES} +# ${PLUGIN_API_WINDOWS_LIBRARIES} +#) +# +#add_dependencies(demo_media_plugin_2 +# ${LLPLUGIN_LIBRARIES} +# ${LLCOMMON_LIBRARIES} +#) +# +#if (DARWIN) +# # Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name +# set_target_properties( +# demo_media_plugin_2 +# PROPERTIES +# PREFIX "" +# BUILD_WITH_INSTALL_RPATH 1 +# INSTALL_NAME_DIR "@executable_path" +# ) +#endif (DARWIN) + +### llmediaplugintest + +set(llmediaplugintest_SOURCE_FILES + llmediaplugintest.cpp + llmediaplugintest.h + bookmarks.txt + ) + +add_executable(llmediaplugintest + WIN32 + ${llmediaplugintest_SOURCE_FILES} +) + +set_target_properties(llmediaplugintest + PROPERTIES + WIN32_EXECUTABLE + FALSE +) + +target_link_libraries(llmediaplugintest + ${GLUT_LIBRARY} + ${GLUI_LIBRARY} + ${OPENGL_LIBRARIES} + ${LLPLUGIN_LIBRARIES} + ${LLMESSAGE_LIBRARIES} + ${LLCOMMON_LIBRARIES} + ${PLUGIN_API_WINDOWS_LIBRARIES} +) + +if (DARWIN) + # The testbed needs to use a couple of CoreFoundation calls now, to deal with being a bundled app. + target_link_libraries(llmediaplugintest + ${COREFOUNDATION_LIBRARY} + ) +endif (DARWIN) + +add_dependencies(llmediaplugintest + copy_win_libs + SLPlugin + media_plugin_quicktime + media_plugin_webkit + media_plugin_example + ${LLPLUGIN_LIBRARIES} + ${LLMESSAGE_LIBRARIES} + ${LLCOMMON_LIBRARIES} +) + +# turn off weird GLUI pragma +add_definitions(-DGLUI_NO_LIB_PRAGMA) + +if (DARWIN OR LINUX) + # glui.h contains code that triggers the "overloaded-virtual" warning in gcc. + set_source_files_properties(llmediaplugintest.cpp PROPERTIES COMPILE_FLAGS "-Wno-overloaded-virtual") +endif (DARWIN OR LINUX) + +# Gather build products of the various dependencies into the build directory for the testbed. + +if (DARWIN) + # path inside the app bundle where we'll need to copy plugins and other related files + set(PLUGINS_DESTINATION_DIR + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llmediaplugintest.app/Contents/Resources + ) + + # create the Contents/Resources directory + add_custom_command( + TARGET llmediaplugintest POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + make_directory + ${PLUGINS_DESTINATION_DIR} + COMMENT "Creating Resources directory in app bundle." + ) +else (DARWIN) + set(PLUGINS_DESTINATION_DIR + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/ + ) +endif (DARWIN) + +get_target_property(BUILT_SLPLUGIN SLPlugin LOCATION) +add_custom_command(TARGET llmediaplugintest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_SLPLUGIN} ${PLUGINS_DESTINATION_DIR} + DEPENDS ${BUILT_SLPLUGIN} +) + +if (DARWIN OR WINDOWS) + get_target_property(BUILT_WEBKIT_PLUGIN media_plugin_webkit LOCATION) + add_custom_command(TARGET llmediaplugintest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_WEBKIT_PLUGIN} ${PLUGINS_DESTINATION_DIR} + DEPENDS ${BUILT_WEBKIT_PLUGIN} + ) + + get_target_property(BUILT_QUICKTIME_PLUGIN media_plugin_quicktime LOCATION) + add_custom_command(TARGET llmediaplugintest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_QUICKTIME_PLUGIN} ${PLUGINS_DESTINATION_DIR} + DEPENDS ${BUILT_QUICKTIME_PLUGIN} + ) + + get_target_property(BUILT_EXAMPLE_PLUGIN media_plugin_example LOCATION) + add_custom_command(TARGET llmediaplugintest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_EXAMPLE_PLUGIN} ${PLUGINS_DESTINATION_DIR} + DEPENDS ${BUILT_EXAMPLE_PLUGIN} + ) + + # copy over bookmarks file if llmediaplugintest gets built + get_target_property(BUILT_LLMEDIAPLUGINTEST llmediaplugintest LOCATION) + add_custom_command(TARGET llmediaplugintest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${CMAKE_CURRENT_BINARY_DIR}/ + DEPENDS ${BUILT_LLMEDIAPLUGINTEST} + ) + # also copy it to the same place as SLPlugin, which is what the mac wants... + add_custom_command(TARGET llmediaplugintest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bookmarks.txt ${PLUGINS_DESTINATION_DIR} + DEPENDS ${BUILT_LLMEDIAPLUGINTEST} + ) +endif (DARWIN OR WINDOWS) + +if (DARWIN) + add_custom_command(TARGET llmediaplugintest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib ${PLUGINS_DESTINATION_DIR} + DEPENDS ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib + ) +endif (DARWIN) + + diff --git a/linden/indra/test_apps/llplugintest/bookmarks.txt b/linden/indra/test_apps/llplugintest/bookmarks.txt new file mode 100644 index 0000000..796cc5d --- /dev/null +++ b/linden/indra/test_apps/llplugintest/bookmarks.txt @@ -0,0 +1,28 @@ +# format is description, url (don't put ',' chars in description :) +# if no ',' found, whole line is used for both description and url +(WK) Google Home Page,http://www.google.com +(WK) BBC News Home Page,http://news.bbc.co.uk +(WK) Second Life,http://secondlife.com +(WK) WebKit Home ,http://www.webkit.org +(WK) Yahoo News,http://news.yahoo.com +(WK) Canvas Paint (DHTML version of MS Paint),http://www.canvaspaint.org +(WK) DHTML Lemmings!,http://www.elizium.nu/scripts/lemmings/ +(WK) DHTML graphics demos,http://www.dhteumeuleu.com/ +(WK) Neat Javascript 3D,http://gyu.que.jp/jscloth/ +(QT) Local sample,file:///C|/Program Files/QuickTime/Sample.mov +(QT) Movie - Watchmen Trailer,http://movies.apple.com/movies/wb/watchmen/watchmen-tlr2_480p.mov +(QT) Movie - Transformers - Revenge of the Fallen,http://movies.apple.com/movies/paramount/transformers2/transformersrevengeofthefallen-tlr1_h.320.mov +(QT) Movie - Terminator Salvation,http://movies.apple.com/movies/wb/terminatorsalvation/terminatorsalvation-tlr3_h.320.mov +(QT) Movie - Angels and Demons,http://movies.apple.com/movies/sony_pictures/angelsanddemons/angelsanddemons-video_h.320.mov +(QT) Movie - Sin City Trailer,http://movies.apple.com/movies/miramax/sin_city/sin_city_480.mov +(QT) Movie - The Incredibles Trailer,http://movies.apple.com/movies/disney/the_incredibles/the_incredibles-tlr_a480.mov +(QT) Movie - Streaming Apple Event,http://stream.qtv.apple.com/events/mar/0903lajkszg/m_090374535329zdwg_650_ref.mov +(QT) Movie - MPEG-4 from Amazon S3,http://s3.amazonaws.com/callum-linden/flashdemo/interactive_flash_demo.mp4 +(QT) Movie - Star Trek,http://movies.apple.com/movies/paramount/star_trek/startrek-tlr3_h.320.mov +(QT) Movie - Ice Age 3,http://movies.apple.com/movies/fox/ice_age_iii/iceage3-tlrd_h.320.mov +(QT) Movie - AstroBoy,http://movies.apple.com/movies/summit/astroboy/astroboy-tsr_h.320.mov +(QT) Movie - Ante Up,http://movies.apple.com/movies/independent/anteup/anteup_h.320.mov +(QT) Movie - Every Little Step,http://movies.apple.com/movies/sony/everylittlestep/everylittlestep-clip_h.320.mov +(QT) Movie - The Informers,http://movies.apple.com/movies/independent/theinformers/theinformers_h.320.mov +(QT) Animated GIF,http://upload.wikimedia.org/wikipedia/commons/4/44/Optical.greysquares.arp-animated.gif +(QT) Apple Text Descriptors,http://ubrowser.com/tmp/apple_text.txt diff --git a/linden/indra/test_apps/llplugintest/demo_media_plugin.cpp b/linden/indra/test_apps/llplugintest/demo_media_plugin.cpp new file mode 100644 index 0000000..89e15fd --- /dev/null +++ b/linden/indra/test_apps/llplugintest/demo_media_plugin.cpp @@ -0,0 +1,472 @@ +/** + * @file demo_plugin.cpp + * @brief Test plugin to be loaded by the llplugin testbed. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llgl.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" + +// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint + +class DemoMediaPlugin +{ +public: + + static int init(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data); + +private: + DemoMediaPlugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~DemoMediaPlugin(); + + static void staticReceiveMessage(const char *message_string, void **user_data); + void receiveMessage(const char *message_string); + void sendMessage(const LLPluginMessage &message); + void setDirty(int left, int top, int right, int bottom); + + LLPluginInstance::sendMessageFunction mHostSendFunction; + void *mHostUserData; + bool mDeleteMe; + + class SharedSegmentInfo + { + public: + void *mAddress; + size_t mSize; + }; + + typedef std::map<std::string, SharedSegmentInfo> SharedSegmentMap; + + SharedSegmentMap mSharedSegments; + +public: + + void clear(void) + { +// return; + + if(mPixels != NULL) + { + for( int y = 0; y < mHeight; ++y ) + { + unsigned char *row = mPixels + ( y * mTextureWidth * mDepth); + for(int x = 0; x < mWidth; ++x) + { + unsigned char *pixel = row + (x * mDepth); + if(0) + { + pixel[0] = 0x20; + pixel[1] = 0x20; + pixel[2] = 0x20; + } + else + { + pixel[0] = rand() % 0x40; + pixel[1] = rand() % 0x40; + pixel[2] = rand() % 0x40; + } + } + } + + setDirty(0, 0, mWidth, mHeight); + } + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void update() + { + const time_t interval = 5; + static time_t last_time = time( NULL ); + time_t cur_time = time( NULL ); + + if ( cur_time - last_time > interval ) + { + clear(); + + last_time = cur_time; + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ) + { + // make sure we don't write outside the buffer + if((x < 0) || (x >= mWidth) || (y < 0) || (y >= mHeight)) + return; + + if(mPixels != NULL) + { + unsigned char *pixel = mPixels; + pixel += y * mTextureWidth * mDepth; // row offset + pixel += (x * mDepth); // columm offset + pixel[0] = b; + pixel[1] = g; + pixel[2] = r; + + setDirty(x, y, x+1, y+1); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseDown( int x, int y ) + { + write_pixel( x, y, 0xff, 0x00, 0x00 ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseUp( int x, int y ) + { + write_pixel( x, y, 0xff, 0xff, 0x00 ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseMove( int x, int y ) + { + write_pixel( x , y , 0xff, 0x00, 0xff ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void keyPress( unsigned char key ) + { + }; + +private: + unsigned char* mPixels; + int mWidth; + int mHeight; + int mTextureWidth; + int mTextureHeight; + int mDepth; +}; + +int DemoMediaPlugin::init(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + DemoMediaPlugin *self = new DemoMediaPlugin(host_send_func, host_user_data); + *plugin_send_func = staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; +} + + +DemoMediaPlugin::DemoMediaPlugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) +{ + std::cerr << "DemoMediaPlugin constructor" << std::endl; + + mHostSendFunction = host_send_func; + mHostUserData = host_user_data; + mDeleteMe = false; +} + +DemoMediaPlugin::~DemoMediaPlugin() +{ + std::cerr << "DemoMediaPlugin destructor" << std::endl; +} + +void DemoMediaPlugin::staticReceiveMessage(const char *message_string, void **user_data) +{ + DemoMediaPlugin *self = (DemoMediaPlugin*)*user_data; + + if(self != NULL) + { + self->receiveMessage(message_string); + + // If the plugin has processed the delete message, delete it. + if(self->mDeleteMe) + { + delete self; + *user_data = NULL; + } + } +} + +void DemoMediaPlugin::receiveMessage(const char *message_string) +{ +// std::cerr << "DemoMediaPlugin::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if(message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + // Normally a plugin would only specify one of these two subclasses, but this is a demo... + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; + message.setValueLLSD("versions", versions); + sendMessage(message); + + // Plugin gets to decide the texture parameters to use. + mDepth = 3; + + message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueU32("format", GL_RGB); + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", false); // true == use OpenGL-style coordinates, false == (0,0) is upper left. + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. + update(); + } + else if(message_name == "shutdown") + { + sendMessage(LLPluginMessage("base", "shutdown_response")); + + mDeleteMe = true; + } + else if(message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = (void*)message_in.getValueU32("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + + std::cerr << "DemoMediaPlugin::receiveMessage: shared memory added, name: " << name + << ", size: " << info.mSize + << ", address: " << info.mAddress + << std::endl; + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if(message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + std::cerr << "DemoMediaPlugin::receiveMessage: shared memory remove, name = " << name << std::endl; + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + if(mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + } + mSharedSegments.erase(iter); + } + else + { + std::cerr << "DemoMediaPlugin::receiveMessage: unknown shared memory region!" << std::endl; + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { + std::cerr << "DemoMediaPlugin::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if(message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + if(!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + std::cerr << "Got size change, new size is " << width << " by " << height << std::endl; + std::cerr << " texture size is " << texture_width << " by " << texture_height << std::endl; + + mPixels = (unsigned char*)iter->second.mAddress; + mWidth = width; + mHeight = height; + mTextureWidth = texture_width; + mTextureHeight = texture_height; + + clear(); + } + } + } + else if(message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); +// std::string modifiers = message.getValue("modifiers"); + +// std::cerr << "DemoMediaPlugin::receiveMessage: mouse event \"" << event +// << "\", coords " << x << ", " << y +// << std::endl; + + if(event == "down") + { + mouseDown(x, y); + } + else if(event == "up") + { + mouseUp(x, y); + } + else if(event == "move") + { + mouseMove(x, y); + } + } + else + { + std::cerr << "DemoMediaPlugin::receiveMessage: unknown media message: " << message_string << std::endl; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) + { + if(message_name == "focus") + { + // foo = message_in.getValueBoolean("focused"); + } + else if(message_name == "clear_cache") + { + } + else if(message_name == "clear_cookies") + { + } + else if(message_name == "enable_cookies") + { + // foo = message_in.getValueBoolean("enable"); + } + else if(message_name == "proxy_setup") + { + // foo = message_in.getValueBoolean("enable"); + // bar = message_in.getValue("host"); + // baz = message_in.getValueS32("port"); + } + else if(message_name == "browse_stop") + { + } + else if(message_name == "browse_reload") + { + // foo = message_in.getValueBoolean("ignore_cache"); + } + else if(message_name == "browse_forward") + { + } + else if(message_name == "browse_back") + { + } + else if(message_name == "set_status_redirect") + { + // foo = message_in.getValueS32("code"); + // bar = message_in.getValue("url"); + } + else + { + std::cerr << "DemoMediaPlugin::receiveMessage: unknown media_browser message: " << message_string << std::endl; + } + } + else + { + std::cerr << "DemoMediaPlugin::receiveMessage: unknown message class: " << message_class << std::endl; + } + + } +} + +void DemoMediaPlugin::sendMessage(const LLPluginMessage &message) +{ + std::string output = message.generate(); + mHostSendFunction(output.c_str(), &mHostUserData); +} + +void DemoMediaPlugin::setDirty(int left, int top, int right, int bottom) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); + + message.setValueS32("left", left); + message.setValueS32("top", top); + message.setValueS32("right", right); + message.setValueS32("bottom", bottom); + + sendMessage(message); +} + + +extern "C" +{ +#ifdef WIN32 + __declspec(dllexport) +#endif + int LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data); +} + +int +#ifdef WIN32 + __declspec(dllexport) +#endif + LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + return DemoMediaPlugin::init(host_send_func, host_user_data, plugin_send_func, plugin_user_data); +} + +#ifdef WIN32 +int WINAPI DllEntryPoint( HINSTANCE hInstance, unsigned long reason, void* params ) +{ + return 1; +} +#endif diff --git a/linden/indra/test_apps/llplugintest/demo_media_plugin_2.cpp b/linden/indra/test_apps/llplugintest/demo_media_plugin_2.cpp new file mode 100644 index 0000000..7a76f74 --- /dev/null +++ b/linden/indra/test_apps/llplugintest/demo_media_plugin_2.cpp @@ -0,0 +1,578 @@ +/** + * @file demo_plugin.cpp + * @brief Test plugin to be loaded by the llplugin testbed. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llgl.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" + +// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint + +class DemoMediaPlugin2 +{ +public: + + static int init(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data); + +private: + DemoMediaPlugin2(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~DemoMediaPlugin2(); + + static void staticReceiveMessage(const char *message_string, void **user_data); + void receiveMessage(const char *message_string); + void sendMessage(const LLPluginMessage &message); + void setDirty(int left, int top, int right, int bottom); + + LLPluginInstance::sendMessageFunction mHostSendFunction; + void *mHostUserData; + bool mDeleteMe; + + class SharedSegmentInfo + { + public: + void *mAddress; + size_t mSize; + }; + + typedef std::map<std::string, SharedSegmentInfo> SharedSegmentMap; + + SharedSegmentMap mSharedSegments; + +public: + void updatePixels(void) + { + if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 ) + return; + + if ( mPixels == 0 ) + return; + + if ( mFirstTime ) + { + // now we have a valid width/height - we can initialize positions + for( int n = 0; n < NumObjects; ++n ) + { + mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 ); + mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 ); + + mColorR[ n ] = rand() % 0xa0 + 0x60; + mColorG[ n ] = rand() % 0xa0 + 0x60; + mColorB[ n ] = rand() % 0xa0 + 0x60; + + mXInc[ n ] = 0; + while ( mXInc[ n ] == 0 ) + mXInc[ n ] = rand() % 7 - 3; + + mYInc[ n ] = 0; + while ( mYInc[ n ] == 0 ) + mYInc[ n ] = rand() % 9 - 4; + + mBlockSize[ n ] = rand() % 0x16 + 0x04; + }; + + delete [] mBackgroundPixels; + + mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ]; + + mFirstTime = false; + }; + + if ( time( NULL ) > mLastUpdateTime + 3 ) + { + const int num_squares = rand() % 20 + 4; + int sqr1_r = rand() % 0x80 + 0x20; + int sqr1_g = rand() % 0x80 + 0x20; + int sqr1_b = rand() % 0x80 + 0x20; + int sqr2_r = rand() % 0x80 + 0x20; + int sqr2_g = rand() % 0x80 + 0x20; + int sqr2_b = rand() % 0x80 + 0x20; + + for ( int y1 = 0; y1 < num_squares; ++y1 ) + { + for ( int x1 = 0; x1 < num_squares; ++x1 ) + { + int px_start = mWidth * x1 / num_squares; + int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares; + int py_start = mHeight * y1 / num_squares; + int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares; + + for( int y2 = py_start; y2 < py_end; ++y2 ) + { + for( int x2 = px_start; x2 < px_end; ++x2 ) + { + int rowspan = mWidth * mDepth; + + if ( ( y1 % 2 ) ^ ( x1 % 2 ) ) + { + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b; + } + else + { + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b; + }; + }; + }; + }; + }; + + time( &mLastUpdateTime ); + }; + + memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth ); + + for( int n = 0; n < NumObjects; ++n ) + { + if ( rand() % 50 == 0 ) + { + mXInc[ n ] = 0; + while ( mXInc[ n ] == 0 ) + mXInc[ n ] = rand() % 7 - 3; + + mYInc[ n ] = 0; + while ( mYInc[ n ] == 0 ) + mYInc[ n ] = rand() % 9 - 4; + }; + + if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] ) + mXInc[ n ] =- mXInc[ n ]; + + if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] ) + mYInc[ n ] =- mYInc[ n ]; + + mXpos[ n ] += mXInc[ n ]; + mYpos[ n ] += mYInc[ n ]; + + for( int y = 0; y < mBlockSize[ n ]; ++y ) + { + for( int x = 0; x < mBlockSize[ n ]; ++x ) + { + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ]; + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ]; + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ]; + }; + }; + }; + + // TODO: experiment with setDirty to just follow block position + setDirty( 0, 0, mWidth, mHeight ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void update() + { + updatePixels(); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ) + { + // make sure we don't write outside the buffer + if((x < 0) || (x >= mWidth) || (y < 0) || (y >= mHeight)) + return; + + if( mBackgroundPixels != NULL) + { + unsigned char *pixel = mBackgroundPixels; + pixel += y * mWidth * mDepth; // row offset + pixel += (x * mDepth); // columm offset + pixel[0] = b; + pixel[1] = g; + pixel[2] = r; + + setDirty(x, y, x+1, y+1); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseDown( int x, int y ) + { + write_pixel( x, y, 0xff, 0x00, 0x00 ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseUp( int x, int y ) + { + write_pixel( x, y, 0xff, 0xff, 0x00 ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseMove( int x, int y ) + { + write_pixel( x , y , 0xff, 0x00, 0xff ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void keyPress( unsigned char key ) + { + }; + +private: + unsigned char* mPixels; + int mWidth; + int mHeight; + int mTextureWidth; + int mTextureHeight; + int mDepth; + time_t mLastUpdateTime; + bool mFirstTime; + unsigned char* mBackgroundPixels; + enum Constants2 { NumObjects = 20 }; + int mColorR[ NumObjects ]; + int mColorG[ NumObjects ]; + int mColorB[ NumObjects ]; + int mXpos[ NumObjects ]; + int mYpos[ NumObjects ]; + int mXInc[ NumObjects ]; + int mYInc[ NumObjects ]; + int mBlockSize[ NumObjects ]; +}; + +int DemoMediaPlugin2::init(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + DemoMediaPlugin2 *self = new DemoMediaPlugin2(host_send_func, host_user_data); + *plugin_send_func = staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; +} + + +DemoMediaPlugin2::DemoMediaPlugin2(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) +{ + std::cerr << "DemoMediaPlugin2 constructor" << std::endl; + + mHostSendFunction = host_send_func; + mHostUserData = host_user_data; + mDeleteMe = false; + + mLastUpdateTime = 0; + mFirstTime = true; + mLastUpdateTime = 0; + mWidth = 0; + mHeight = 0; + mDepth = 0; + mPixels = 0; + mBackgroundPixels = 0; + + srand( get_clock_count() ) ; +} + +DemoMediaPlugin2::~DemoMediaPlugin2() +{ + std::cerr << "DemoMediaPlugin2 destructor" << std::endl; +} + +void DemoMediaPlugin2::staticReceiveMessage(const char *message_string, void **user_data) +{ + DemoMediaPlugin2 *self = (DemoMediaPlugin2*)*user_data; + + if(self != NULL) + { + self->receiveMessage(message_string); + + // If the plugin has processed the delete message, delete it. + if(self->mDeleteMe) + { + delete self; + *user_data = NULL; + } + } +} + +void DemoMediaPlugin2::receiveMessage(const char *message_string) +{ +// std::cerr << "DemoMediaPlugin2::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if(message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + // Normally a plugin would only specify one of these two subclasses, but this is a demo... + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; + message.setValueLLSD("versions", versions); + sendMessage(message); + + // Plugin gets to decide the texture parameters to use. + mDepth = 3; + + message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueU32("format", GL_RGB); + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", false); // true == use OpenGL-style coordinates, false == (0,0) is upper left. + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. + update(); + } + else if(message_name == "shutdown") + { + sendMessage(LLPluginMessage("base", "shutdown_response")); + + mDeleteMe = true; + } + else if(message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = (void*)message_in.getValueU32("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + + std::cerr << "DemoMediaPlugin2::receiveMessage: shared memory added, name: " << name + << ", size: " << info.mSize + << ", address: " << info.mAddress + << std::endl; + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if(message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + std::cerr << "DemoMediaPlugin2::receiveMessage: shared memory remove, name = " << name << std::endl; + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + if(mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + } + mSharedSegments.erase(iter); + } + else + { + std::cerr << "DemoMediaPlugin2::receiveMessage: unknown shared memory region!" << std::endl; + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { + std::cerr << "DemoMediaPlugin2::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if(message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + if(!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + std::cerr << "Got size change, new size is " << width << " by " << height << std::endl; + std::cerr << " texture size is " << texture_width << " by " << texture_height << std::endl; + + mPixels = (unsigned char*)iter->second.mAddress; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + + mFirstTime = true; + updatePixels(); + } + } + } + else if(message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); +// std::string modifiers = message.getValue("modifiers"); + +// std::cerr << "DemoMediaPlugin2::receiveMessage: mouse event \"" << event +// << "\", coords " << x << ", " << y +// << std::endl; + + if(event == "down") + { + mouseDown(x, y); + } + else if(event == "up") + { + mouseUp(x, y); + } + else if(event == "move") + { + mouseMove(x, y); + } + } + else + { + std::cerr << "DemoMediaPlugin2::receiveMessage: unknown media message: " << message_string << std::endl; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) + { + if(message_name == "focus") + { + // foo = message_in.getValueBoolean("focused"); + } + else if(message_name == "clear_cache") + { + } + else if(message_name == "clear_cookies") + { + } + else if(message_name == "enable_cookies") + { + // foo = message_in.getValueBoolean("enable"); + } + else if(message_name == "proxy_setup") + { + // foo = message_in.getValueBoolean("enable"); + // bar = message_in.getValue("host"); + // baz = message_in.getValueS32("port"); + } + else if(message_name == "browse_stop") + { + } + else if(message_name == "browse_reload") + { + // foo = message_in.getValueBoolean("ignore_cache"); + } + else if(message_name == "browse_forward") + { + } + else if(message_name == "browse_back") + { + } + else if(message_name == "set_status_redirect") + { + // foo = message_in.getValueS32("code"); + // bar = message_in.getValue("url"); + } + else + { + std::cerr << "DemoMediaPlugin2::receiveMessage: unknown media_browser message: " << message_string << std::endl; + } + } + else + { + std::cerr << "DemoMediaPlugin2::receiveMessage: unknown message class: " << message_class << std::endl; + } + + } +} + +void DemoMediaPlugin2::sendMessage(const LLPluginMessage &message) +{ + std::string output = message.generate(); + mHostSendFunction(output.c_str(), &mHostUserData); +} + +void DemoMediaPlugin2::setDirty(int left, int top, int right, int bottom) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); + + message.setValueS32("left", left); + message.setValueS32("top", top); + message.setValueS32("right", right); + message.setValueS32("bottom", bottom); + + sendMessage(message); +} + + +extern "C" +{ +#ifdef WIN32 + __declspec(dllexport) +#endif + int LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data); +} + +int +#ifdef WIN32 + __declspec(dllexport) +#endif + LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + return DemoMediaPlugin2::init(host_send_func, host_user_data, plugin_send_func, plugin_user_data); +} + +#ifdef WIN32 +int WINAPI DllEntryPoint( HINSTANCE hInstance, unsigned long reason, void* params ) +{ + return 1; +} +#endif diff --git a/linden/indra/test_apps/llplugintest/demo_plugin.cpp b/linden/indra/test_apps/llplugintest/demo_plugin.cpp new file mode 100644 index 0000000..772fa16 --- /dev/null +++ b/linden/indra/test_apps/llplugintest/demo_plugin.cpp @@ -0,0 +1,220 @@ +/** + * @file demo_plugin.cpp + * @brief Test plugin to be loaded by the llplugin testbed. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#ifdef WIN32 +#include <windows.h> +#endif + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" + +// TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint + +class DemoPlugin +{ +public: + + static int init(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data); + +private: + DemoPlugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~DemoPlugin(); + + static void staticReceiveMessage(const char *message_string, void **user_data); + void receiveMessage(const char *message_string); + void sendMessage(const LLPluginMessage &message); + + LLPluginInstance::sendMessageFunction mHostSendFunction; + void *mHostUserData; + bool mDeleteMe; + + int mSharedSegmentFillValue; + void *mSharedSegmentBase; + size_t mSharedSegmentSize; +}; + +int DemoPlugin::init(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + DemoPlugin *self = new DemoPlugin(host_send_func, host_user_data); + *plugin_send_func = staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; +} + +DemoPlugin::DemoPlugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) +{ + std::cerr << "DemoPlugin constructor" << std::endl; + + mHostSendFunction = host_send_func; + mHostUserData = host_user_data; + mDeleteMe = false; + mSharedSegmentBase = NULL; + mSharedSegmentSize = 0; + mSharedSegmentFillValue = 0; +} + +DemoPlugin::~DemoPlugin() +{ + std::cerr << "DemoPlugin destructor" << std::endl; +} + +void DemoPlugin::staticReceiveMessage(const char *message_string, void **user_data) +{ + DemoPlugin *self = (DemoPlugin*)*user_data; + + if(self != NULL) + { + self->receiveMessage(message_string); + + // If the plugin has processed the delete message, delete it. + if(self->mDeleteMe) + { + delete self; + *user_data = NULL; + } + } +} + +void DemoPlugin::receiveMessage(const char *message_string) +{ +// std::cerr << "DemoPlugin::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if(message_class == "base") + { + if(message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + message.setValueLLSD("versions", versions); + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. +// std::cerr << "DemoPlugin::receiveMessage: idle processing" << std::endl; + if(mSharedSegmentBase != NULL) + { + // Fill the shared memory segment + memset(mSharedSegmentBase, mSharedSegmentFillValue, mSharedSegmentSize); + // and increment the fill value + mSharedSegmentFillValue++; + } + } + else if(message_name == "shutdown") + { + sendMessage(LLPluginMessage("base", "shutdown_response")); + + mDeleteMe = true; + } + else if(message_name == "shm_added") + { + // Normally, we would check the name and match it up with something from another message. + // For this test, just fill any segment that comes in. + mSharedSegmentSize = (size_t)message_in.getValueS32("size"); + mSharedSegmentBase = (void*)message_in.getValueU32("address"); + + std::cerr << "DemoPlugin::receiveMessage: shared memory added, name: " << message_in.getValue("name") + << ", size: " << mSharedSegmentSize + << ", address: " << mSharedSegmentBase + << std::endl; + + memset(mSharedSegmentBase, mSharedSegmentFillValue, mSharedSegmentSize); + + } + else if(message_name == "shm_remove") + { + std::cerr << "DemoPlugin::receiveMessage: shared memory remove" << std::endl; + + // Normally, we would check the name and match it up with something from another message. + // For this test, just stop filling the only segment we track. + + mSharedSegmentBase = NULL; + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", message_in.getValue("name")); + sendMessage(message); + } + else + { + std::cerr << "DemoPlugin::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else + { + std::cerr << "DemoPlugin::receiveMessage: unknown message class: " << message_class << std::endl; + } + + } +} + +void DemoPlugin::sendMessage(const LLPluginMessage &message) +{ + std::string output = message.generate(); + mHostSendFunction(output.c_str(), &mHostUserData); +} + + +extern "C" +{ +#ifdef WIN32 + __declspec(dllexport) +#endif + int LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data); +} + +int +#ifdef WIN32 + __declspec(dllexport) +#endif + LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + return DemoPlugin::init(host_send_func, host_user_data, plugin_send_func, plugin_user_data); +} + +#ifdef WIN32 +int WINAPI DllEntryPoint( HINSTANCE hInstance, unsigned long reason, void* params ) +{ + return 1; +} +#endif diff --git a/linden/indra/test_apps/llplugintest/llmediaplugintest.cpp b/linden/indra/test_apps/llplugintest/llmediaplugintest.cpp new file mode 100644 index 0000000..27cb52a --- /dev/null +++ b/linden/indra/test_apps/llplugintest/llmediaplugintest.cpp @@ -0,0 +1,2179 @@ +/** + * @file LLMediaPluginTest.cpp + * @brief Primary test application for LLMedia (Separate Process) Plugin system + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "indra_constants.h" + +#include "llapr.h" +#include "llerrorcontrol.h" + +#include <math.h> +#include <iomanip> +#include <sstream> +#include <ctime> + +#include "llmediaplugintest.h" + +#if __APPLE__ + #include <GLUT/glut.h> + #include <CoreFoundation/CoreFoundation.h> +#else + #define FREEGLUT_STATIC + #include "GL/freeglut.h" + #define GLUI_FREEGLUT +#endif + +#if LL_WINDOWS +#pragma warning(disable: 4263) +#pragma warning(disable: 4264) +#endif +#include "glui.h" + + +LLMediaPluginTest* gApplication = 0; +static void gluiCallbackWrapper( int control_id ); + +//////////////////////////////////////////////////////////////////////////////// +// +static bool isTexture( GLuint texture ) +{ + bool result = false; + + // glIsTexture will sometimes return false for real textures... do this instead. + if(texture != 0) + result = true; + + return result; +} + +//////////////////////////////////////////////////////////////////////////////// +// +mediaPanel::mediaPanel() +{ + mMediaTextureHandle = 0; + mPickTextureHandle = 0; + mMediaSource = NULL; + mPickTexturePixels = NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// +mediaPanel::~mediaPanel() +{ + // delete OpenGL texture handles + if ( isTexture( mPickTextureHandle ) ) + { + std::cerr << "remMediaPanel: deleting pick texture " << mPickTextureHandle << std::endl; + glDeleteTextures( 1, &mPickTextureHandle ); + mPickTextureHandle = 0; + } + + if ( isTexture( mMediaTextureHandle ) ) + { + std::cerr << "remMediaPanel: deleting media texture " << mMediaTextureHandle << std::endl; + glDeleteTextures( 1, &mMediaTextureHandle ); + mMediaTextureHandle = 0; + } + + if(mPickTexturePixels) + { + delete mPickTexturePixels; + } + + if(mMediaSource) + { + delete mMediaSource; + } + +} + +//////////////////////////////////////////////////////////////////////////////// +// +LLMediaPluginTest::LLMediaPluginTest( int app_window, int window_width, int window_height ) : + mVersionMajor( 2 ), + mVersionMinor( 0 ), + mVersionPatch( 0 ), + mMaxPanels( 25 ), + mViewportAspect( 0 ), + mAppWindow( app_window ), + mCurMouseX( 0 ), + mCurMouseY( 0 ), + mFuzzyMedia( true ), + mSelectedPanel( 0 ), + mMediaBrowserControlEnableCookies( 0 ), + mMediaBrowserControlBackButton( 0 ), + mMediaBrowserControlForwardButton( 0 ), + mMediaTimeControlVolume( 100 ), + mMediaTimeControlSeekSeconds( 0 ), + mGluiMediaTimeControlWindowFlag( true ), + mGluiMediaBrowserControlWindowFlag( true ), + mMediaBrowserControlBackButtonFlag( true ), + mMediaBrowserControlForwardButtonFlag( true ), + mHomeWebUrl( "http://www.google.com/" ) +{ + // debugging spam + std::cout << std::endl << " GLUT version: " << "3.7.6" << std::endl; // no way to get real version from GLUT + std::cout << std::endl << " GLUI version: " << GLUI_Master.get_version() << std::endl; + std::cout << std::endl << "Media Plugin Test version: " << mVersionMajor << "." << mVersionMinor << "." << mVersionPatch << std::endl; + + // bookmark title + mBookmarks.push_back( std::pair< std::string, std::string >( "--- Bookmarks ---", "" ) ); + + // insert hardcoded URLs here as required for testing + //mBookmarks.push_back( std::pair< std::string, std::string >( "description", "url" ) ); + + // read bookmarks from file. + // note: uses command in ./CmakeLists.txt which copies bookmmarks file from source directory + // to app directory (WITHOUT build configuration dir) (this is cwd in Windows within MSVC) + // For example, test_apps\llplugintest and not test_apps\llplugintest\Release + // This may need to be changed for Mac/Linux builds. + // See https://jira.lindenlab.com/browse/DEV-31350 for large list of media URLs from AGNI + const std::string bookmarks_filename( "bookmarks.txt" ); + std::ifstream file_handle( bookmarks_filename.c_str() ); + if ( file_handle.is_open() ) + { + std::cout << "Reading bookmarks for test" << std::endl; + while( ! file_handle.eof() ) + { + std::string line; + std::getline( file_handle, line ); + if ( file_handle.eof() ) + break; + + if ( line.substr( 0, 1 ) != "#" ) + { + size_t comma_pos = line.find_first_of( ',' ); + if ( comma_pos != std::string::npos ) + { + std::string description = line.substr( 0, comma_pos ); + std::string url = line.substr( comma_pos + 1 ); + mBookmarks.push_back( std::pair< std::string, std::string >( description, url ) ); + } + else + { + mBookmarks.push_back( std::pair< std::string, std::string >( line, line ) ); + }; + }; + }; + std::cout << "Read " << mBookmarks.size() << " bookmarks" << std::endl; + } + else + { + std::cout << "Unable to read bookmarks from file: " << bookmarks_filename << std::endl; + }; + + // initialize linden lab APR module + ll_init_apr(); + + // Set up llerror logging + { + LLError::initForApplication("."); + LLError::setDefaultLevel(LLError::LEVEL_INFO); + //LLError::setTagLevel("Plugin", LLError::LEVEL_DEBUG); + } + + // lots of randomness in this app + srand( ( unsigned int )time( 0 ) ); + + // build GUI + makeChrome(); + + // OpenGL initialilzation + glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); + glClearDepth( 1.0f ); + glEnable( GL_DEPTH_TEST ); + glEnable( GL_COLOR_MATERIAL ); + glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE ); + glDepthFunc( GL_LEQUAL ); + glEnable( GL_TEXTURE_2D ); + glDisable( GL_BLEND ); + glColor3f( 1.0f, 1.0f, 1.0f ); + glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); + glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); + + // start with a sane view + resetView(); + + // initial media panel + const int num_initial_panels = 1; + for( int i = 0; i < num_initial_panels; ++i ) + { + //addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second ); + addMediaPanel( mHomeWebUrl ); + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +LLMediaPluginTest::~LLMediaPluginTest() +{ + // delete all media panels + for( int i = 0; i < (int)mMediaPanels.size(); ++i ) + { + remMediaPanel( mMediaPanels[ i ] ); + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::reshape( int width, int height ) +{ + // update viewport (the active window inside the chrome) + int viewport_x, viewport_y; + int viewport_height, viewport_width; + GLUI_Master.get_viewport_area( &viewport_x, &viewport_y, &viewport_width, &viewport_height ); + mViewportAspect = (float)( viewport_width ) / (float)( viewport_height ); + glViewport( viewport_x, viewport_y, viewport_width, viewport_height ); + + // save these as we'll need them later + mWindowWidth = width; + mWindowHeight = height; + + // adjust size of URL bar so it doesn't get clipped + mUrlEdit->set_w( mWindowWidth - 360 ); + + // GLUI requires this + if ( glutGetWindow() != mAppWindow ) + glutSetWindow( mAppWindow ); + + // trigger re-display + glutPostRedisplay(); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::bindTexture(GLuint texture, GLint row_length, GLint alignment) +{ + glEnable( GL_TEXTURE_2D ); + + glBindTexture( GL_TEXTURE_2D, texture ); + glPixelStorei( GL_UNPACK_ROW_LENGTH, row_length ); + glPixelStorei( GL_UNPACK_ALIGNMENT, alignment ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +bool LLMediaPluginTest::checkGLError(const char *name) +{ + bool result = false; + GLenum error = glGetError(); + + if(error != GL_NO_ERROR) + { + // For some reason, glGenTextures is returning GL_INVALID_VALUE... + std::cout << name << " ERROR 0x" << std::hex << error << std::dec << std::endl; + result = true; + } + + return result; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::drawGeometry( int panel ) +{ + // texture coordinates for each panel + GLfloat non_opengl_texture_coords[ 8 ] = { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f }; + GLfloat opengl_texture_coords[ 8 ] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }; + + GLfloat *texture_coords = mMediaPanels[ panel ]->mAppTextureCoordsOpenGL?opengl_texture_coords:non_opengl_texture_coords; + + // base coordinates for each panel + GLfloat base_vertex_pos[ 8 ] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }; + + // calculate posiitons + const int num_panels = (int)mMediaPanels.size(); + const int num_rows = (int)sqrt( (float)num_panels ); + const int num_cols = num_panels / num_rows; + const int panel_x = ( panel / num_rows ); + const int panel_y = ( panel % num_rows ); + + const float spacing = 0.1f; + const GLfloat offset_x = num_cols * ( 1.0 + spacing ) / 2; + const GLfloat offset_y = num_rows * ( 1.0 + spacing ) / 2; + + // Adjust for media aspect ratios + { + float aspect = 1.0f; + + if(mMediaPanels[ panel ]->mMediaHeight != 0) + { + aspect = (float)mMediaPanels[ panel ]->mMediaWidth / (float)mMediaPanels[ panel ]->mMediaHeight; + } + + if(aspect > 1.0f) + { + // media is wider than it is high -- adjust the top and bottom in + for( int corner = 0; corner < 4; ++corner ) + { + float temp = base_vertex_pos[corner * 2 + 1]; + + if(temp < 0.5f) + temp += 0.5 - (0.5f / aspect); + else + temp -= 0.5 - (0.5f / aspect); + + base_vertex_pos[corner * 2 + 1] = temp; + } + } + else if(aspect < 1.0f) + { + // media is higher than it is wide -- adjust the left and right sides in + for( int corner = 0; corner < 4; ++corner ) + { + float temp = base_vertex_pos[corner * 2]; + + if(temp < 0.5f) + temp += 0.5f - (0.5f * aspect); + else + temp -= 0.5f - (0.5f * aspect); + + base_vertex_pos[corner * 2] = temp; + } + } + } + + glBegin( GL_QUADS ); + for( int corner = 0; corner < 4; ++corner ) + { + glTexCoord2f( texture_coords[ corner * 2 ], texture_coords[ corner * 2 + 1 ] ); + GLfloat x = base_vertex_pos[ corner * 2 ] + panel_x * ( 1.0 + spacing ) - offset_x + spacing / 2.0f; + GLfloat y = base_vertex_pos[ corner * 2 + 1 ] + panel_y * ( 1.0 + spacing ) - offset_y + spacing / 2.0f; + + glVertex3f( x, y, 0.0f ); + }; + glEnd(); +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::startPanelHighlight( float red, float green, float blue, float line_width ) +{ + glPushAttrib( GL_ALL_ATTRIB_BITS ); + glEnable( GL_POLYGON_OFFSET_FILL ); + glPolygonOffset( -2.5f, -2.5f ); + glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); + glLineWidth( line_width ); + glColor3f( red, green, blue ); + glDisable( GL_TEXTURE_2D ); +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::endPanelHighlight() +{ + glPopAttrib(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::draw( int draw_type ) +{ + for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel ) + { + // drawing pick texture + if ( draw_type == DrawTypePickTexture ) + { + // only bother with pick if we have something to render + // Actually, we need to pick even if we're not ready to render. + // Otherwise you can't select and remove a panel which has gone bad. + //if ( mMediaPanels[ panel ]->mReadyToRender ) + { + glMatrixMode( GL_TEXTURE ); + glPushMatrix(); + + // pick texture is a power of 2 so no need to scale + glLoadIdentity(); + + // bind to media texture + glLoadIdentity(); + bindTexture( mMediaPanels[ panel ]->mPickTextureHandle ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + + // draw geometry using pick texture + drawGeometry( panel ); + + glMatrixMode( GL_TEXTURE ); + glPopMatrix(); + }; + } + else + if ( draw_type == DrawTypeMediaTexture ) + { + bool texture_valid = false; + bool plugin_exited = false; + + if(mMediaPanels[ panel ]->mMediaSource) + { + texture_valid = mMediaPanels[ panel ]->mMediaSource->textureValid(); + plugin_exited = mMediaPanels[ panel ]->mMediaSource->isPluginExited(); + } + + // save texture matrix (changes for each panel) + glMatrixMode( GL_TEXTURE ); + glPushMatrix(); + + // only process texture if the media is ready to draw + // (we still want to draw the geometry) + if ( mMediaPanels[ panel ]->mReadyToRender && texture_valid ) + { + // bind to media texture + bindTexture( mMediaPanels[ panel ]->mMediaTextureHandle ); + + if ( mFuzzyMedia ) + { + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + } + else + { + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + } + + // scale to fit panel + glScalef( mMediaPanels[ panel ]->mTextureScaleX, + mMediaPanels[ panel ]->mTextureScaleY, + 1.0f ); + }; + + float intensity = plugin_exited?0.25f:1.0f; + + // highlight the selected panel + if ( mSelectedPanel && ( mMediaPanels[ panel ]->mId == mSelectedPanel->mId ) ) + { + startPanelHighlight( intensity, intensity, 0.0f, 5.0f ); + drawGeometry( panel ); + endPanelHighlight(); + } + else + // this panel not able to render yet since it + // doesn't have enough information + if ( !mMediaPanels[ panel ]->mReadyToRender ) + { + startPanelHighlight( intensity, 0.0f, 0.0f, 2.0f ); + drawGeometry( panel ); + endPanelHighlight(); + } + else + // just display a border around the media + { + startPanelHighlight( 0.0f, intensity, 0.0f, 2.0f ); + drawGeometry( panel ); + endPanelHighlight(); + }; + + if ( mMediaPanels[ panel ]->mReadyToRender && texture_valid ) + { + // draw visual geometry + drawGeometry( panel ); + } + + // restore texture matrix (changes for each panel) + glMatrixMode( GL_TEXTURE ); + glPopMatrix(); + }; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::display() +{ + // GLUI requires this + if ( glutGetWindow() != mAppWindow ) + glutSetWindow( mAppWindow ); + + // start with a clean slate + glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + // set up OpenGL view + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glFrustum( -mViewportAspect * 0.04f, mViewportAspect * 0.04f, -0.04f, 0.04f, 0.1f, 50.0f ); + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + glTranslatef( 0.0, 0.0, 0.0f ); + glTranslatef( mViewPos[ 0 ], mViewPos[ 1 ], -mViewPos[ 2 ] ); + glMultMatrixf( mViewRotation ); + + // draw pick texture + draw( DrawTypePickTexture ); + + // read colors and get coordinate values + glReadPixels( mCurMouseX, mCurMouseY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, mPixelReadColor ); + + // clear the pick render (otherwise it may depth-fight with the textures rendered later) + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + // draw visible geometry + draw( DrawTypeMediaTexture ); + + glutSwapBuffers(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::idle() +{ +// checkGLError("LLMediaPluginTest::idle"); + + // GLUI requires this + if ( glutGetWindow() != mAppWindow ) + glutSetWindow( mAppWindow ); + + // random creation/destruction of panels enabled? + const time_t panel_timeout_time = 5; + if ( mRandomPanelCount ) + { + // time for a change + static time_t last_panel_time = 0; + if ( time( NULL ) - last_panel_time > panel_timeout_time ) + { + if ( rand() % 2 == 0 ) + { + if ( mMediaPanels.size() < 16 ) + { + std::cout << "Randomly adding new panel" << std::endl; + addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second ); + }; + } + else + { + if ( mMediaPanels.size() > 0 ) + { + std::cout << "Deleting selected panel" << std::endl; + remMediaPanel( mSelectedPanel ); + }; + }; + time( &last_panel_time ); + }; + }; + + // random selection of bookmarks enabled? + const time_t bookmark_timeout_time = 5; + if ( mRandomBookmarks ) + { + // time for a change + static time_t last_bookmark_time = 0; + if ( time( NULL ) - last_bookmark_time > bookmark_timeout_time ) + { + // go to a different random bookmark on each panel + for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel ) + { + std::string uri = mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second; + + std::cout << "Random: navigating to : " << uri << std::endl; + + std::string mime_type = mimeTypeFromUrl( uri ); + + if ( mime_type != mMediaPanels[ panel ]->mMimeType ) + { + replaceMediaPanel( mMediaPanels[ panel ], uri ); + } + else + { + mMediaPanels[ panel ]->mMediaSource->loadURI( uri ); + mMediaPanels[ panel ]->mMediaSource->start(); + }; + }; + + time( &last_bookmark_time ); + }; + }; + + // update UI + if ( mSelectedPanel ) + { + // set volume based on slider if we have time media + //if ( mGluiMediaTimeControlWindowFlag ) + //{ + // mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f ); + //}; + + // NOTE: it is absurd that we need cache the state of GLUI controls + // but enabling/disabling controls drags framerate from 500+ + // down to 15. Not a problem for plugin system - only this test + // enable/disable time based UI controls based on type of plugin + if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() ) + { + if ( ! mGluiMediaTimeControlWindowFlag ) + { + mGluiMediaTimeControlWindow->enable(); + mGluiMediaTimeControlWindowFlag = true; + }; + } + else + { + if ( mGluiMediaTimeControlWindowFlag ) + { + mGluiMediaTimeControlWindow->disable(); + mGluiMediaTimeControlWindowFlag = false; + }; + }; + + // enable/disable browser based UI controls based on type of plugin + if ( mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() ) + { + if ( ! mGluiMediaBrowserControlWindowFlag ) + { + mGluiMediaBrowserControlWindow->enable(); + mGluiMediaBrowserControlWindowFlag = true; + }; + } + else + { + if ( mGluiMediaBrowserControlWindowFlag ) + { + mGluiMediaBrowserControlWindow->disable(); + mGluiMediaBrowserControlWindowFlag = false; + }; + }; + + // enable/disable browser back button depending on browser history + if ( mSelectedPanel->mMediaSource->getHistoryBackAvailable() ) + { + if ( ! mMediaBrowserControlBackButtonFlag ) + { + mMediaBrowserControlBackButton->enable(); + mMediaBrowserControlBackButtonFlag = true; + }; + } + else + { + if ( mMediaBrowserControlBackButtonFlag ) + { + mMediaBrowserControlBackButton->disable(); + mMediaBrowserControlBackButtonFlag = false; + }; + }; + + // enable/disable browser forward button depending on browser history + if ( mSelectedPanel->mMediaSource->getHistoryForwardAvailable() ) + { + if ( ! mMediaBrowserControlForwardButtonFlag ) + { + mMediaBrowserControlForwardButton->enable(); + mMediaBrowserControlForwardButtonFlag = true; + }; + } + else + { + if ( mMediaBrowserControlForwardButtonFlag ) + { + mMediaBrowserControlForwardButton->disable(); + mMediaBrowserControlForwardButtonFlag = false; + }; + }; + + // NOTE: This is *very* slow and not worth optimising + updateStatusBar(); + }; + + // update all the panels + for( int panel_index = 0; panel_index < (int)mMediaPanels.size(); ++panel_index ) + { + mediaPanel *panel = mMediaPanels[ panel_index ]; + + // call plugins idle function so it can potentially update itself + panel->mMediaSource->idle(); + + // update each media panel + updateMediaPanel( panel ); + + LLRect dirty_rect; + if ( ! panel->mMediaSource->textureValid() ) + { + //std::cout << "texture invalid, skipping update..." << std::endl; + } + else + if ( panel && + ( panel->mMediaWidth != panel->mMediaSource->getWidth() || + panel->mMediaHeight != panel->mMediaSource->getHeight() ) ) + { + //std::cout << "Resize in progress, skipping update..." << std::endl; + } + else + if ( panel->mMediaSource->getDirty( &dirty_rect ) ) + { + const unsigned char* pixels = panel->mMediaSource->getBitsData(); + if ( pixels && isTexture(panel->mMediaTextureHandle)) + { + int x_offset = dirty_rect.mLeft; + int y_offset = dirty_rect.mBottom; + int width = dirty_rect.mRight - dirty_rect.mLeft; + int height = dirty_rect.mTop - dirty_rect.mBottom; + + if((dirty_rect.mRight <= panel->mTextureWidth) && (dirty_rect.mTop <= panel->mTextureHeight)) + { + // Offset the pixels pointer properly + pixels += ( y_offset * panel->mMediaSource->getTextureDepth() * panel->mMediaSource->getBitsWidth() ); + pixels += ( x_offset * panel->mMediaSource->getTextureDepth() ); + + // set up texture + bindTexture( panel->mMediaTextureHandle, panel->mMediaSource->getBitsWidth() ); + if ( mFuzzyMedia ) + { + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + } + else + { + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + }; + + checkGLError("glTexParameteri"); + + if(panel->mMediaSource->getTextureFormatSwapBytes()) + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); + checkGLError("glPixelStorei"); + } + + // draw portion that changes into texture + glTexSubImage2D( GL_TEXTURE_2D, 0, + x_offset, + y_offset, + width, + height, + panel->mMediaSource->getTextureFormatPrimary(), + panel->mMediaSource->getTextureFormatType(), + pixels ); + + if(checkGLError("glTexSubImage2D")) + { + std::cerr << " panel ID=" << panel->mId << std::endl; + std::cerr << " texture size = " << panel->mTextureWidth << " x " << panel->mTextureHeight << std::endl; + std::cerr << " media size = " << panel->mMediaWidth << " x " << panel->mMediaHeight << std::endl; + std::cerr << " dirty rect = " << dirty_rect.mLeft << ", " << dirty_rect.mBottom << ", " << dirty_rect.mRight << ", " << dirty_rect.mTop << std::endl; + std::cerr << " texture width = " << panel->mMediaSource->getBitsWidth() << std::endl; + std::cerr << " format primary = 0x" << std::hex << panel->mMediaSource->getTextureFormatPrimary() << std::dec << std::endl; + std::cerr << " format type = 0x" << std::hex << panel->mMediaSource->getTextureFormatType() << std::dec << std::endl; + std::cerr << " pixels = " << (void*)pixels << std::endl; + } + + if(panel->mMediaSource->getTextureFormatSwapBytes()) + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); + checkGLError("glPixelStorei"); + } + + panel->mMediaSource->resetDirty(); + + panel->mReadyToRender = true; + } + else + { + std::cerr << "dirty rect is outside current media size, skipping update" << std::endl; + } + }; + }; + }; + + // GLUI requires this + if ( glutGetWindow() != mAppWindow ) + glutSetWindow( mAppWindow ); + + // trigger re-display + glutPostRedisplay(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::windowPosToTexturePos( int window_x, int window_y, + int& media_x, int& media_y, + int& id ) +{ + if ( ! mSelectedPanel ) + { + media_x = 0; + media_y = 0; + id = 0; + return; + }; + + // record cursor poisiton for a readback next frame + mCurMouseX = window_x; + // OpenGL app == coordinate system this way + // NOTE: unrelated to settings in plugin - this + // is just for this app + mCurMouseY = mWindowHeight - window_y; + + // extract x (0..1023, y (0..1023) and id (0..15) from RGB components + unsigned long pixel_read_color_bits = ( mPixelReadColor[ 0 ] << 16 ) | ( mPixelReadColor[ 1 ] << 8 ) | mPixelReadColor[ 2 ]; + int texture_x = pixel_read_color_bits & 0x3ff; + int texture_y = ( pixel_read_color_bits >> 10 ) & 0x3ff; + id = ( pixel_read_color_bits >> 20 ) & 0x0f; + + // scale to size of media (1024 because we use 10 bits for X and Y from 24) + media_x = (int)( ( (float)mSelectedPanel->mMediaWidth * (float)texture_x ) / 1024.0f ); + media_y = (int)( ( (float)mSelectedPanel->mMediaHeight * (float)texture_y ) / 1024.0f ); + + // we assume the plugin uses an inverted coordinate scheme like OpenGL + // if not, the plugin code inverts the Y coordinate for us - we don't need to + media_y = mSelectedPanel->mMediaHeight - media_y; + + if ( media_x > 0 && media_y > 0 ) + { + //std::cout << " mouse coords: " << mCurMouseX << " x " << mCurMouseY << " and id = " << id << std::endl; + //std::cout << "raw texture coords: " << texture_x << " x " << texture_y << " and id = " << id << std::endl; + //std::cout << " media coords: " << media_x << " x " << media_y << " and id = " << id << std::endl; + //std::cout << std::endl; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::selectPanelById( int id ) +{ + for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel ) + { + if ( mMediaPanels[ panel ]->mId == id ) + { + selectPanel(mMediaPanels[ panel ]); + return; + }; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::selectPanel( mediaPanel* panel ) +{ + if( mSelectedPanel == panel ) + return; + + // turn off volume before we delete it + if( mSelectedPanel && mSelectedPanel->mMediaSource ) + { + mSelectedPanel->mMediaSource->setVolume( 0.0f ); + mSelectedPanel->mMediaSource->setPriority( LLPluginClassMedia::PRIORITY_LOW ); + }; + + mSelectedPanel = panel; + + if( mSelectedPanel && mSelectedPanel->mMediaSource ) + { + mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f ); + mSelectedPanel->mMediaSource->setPriority( LLPluginClassMedia::PRIORITY_NORMAL ); + + if(!mSelectedPanel->mStartUrl.empty()) + { + mUrlEdit->set_text(const_cast<char*>(mSelectedPanel->mStartUrl.c_str()) ); + } + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +mediaPanel* LLMediaPluginTest::findMediaPanel( LLPluginClassMedia* source ) +{ + mediaPanel *result = NULL; + + for( int panel = 0; panel < (int)mMediaPanels.size(); ++panel ) + { + if ( mMediaPanels[ panel ]->mMediaSource == source ) + { + result = mMediaPanels[ panel ]; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::navigateToNewURI( std::string uri ) +{ + if ( uri.length() ) + { + std::string mime_type = mimeTypeFromUrl( uri ); + + if ( !mSelectedPanel->mMediaSource->isPluginExited() && (mime_type == mSelectedPanel->mMimeType) ) + { + std::cout << "MIME type is the same" << std::endl; + mSelectedPanel->mMediaSource->loadURI( uri ); + mSelectedPanel->mMediaSource->start(); + mBookmarkList->do_selection( 0 ); + } + else + { + std::cout << "MIME type changed or plugin had exited" << std::endl; + replaceMediaPanel( mSelectedPanel, uri ); + mBookmarkList->do_selection( 0 ); + } + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::initUrlHistory( std::string uris ) +{ + if ( uris.length() > 0 ) + { + std::cout << "init URL : " << uris << std::endl; + LLSD historySD; + + char *cstr, *p; + cstr = new char[uris.size()+1]; + strcpy(cstr, uris.c_str()); + const char *DELIMS = " ,;"; + p = strtok(cstr, DELIMS); + while (p != NULL) { + historySD.insert(0, p); + p = strtok(NULL, DELIMS); + } + mSelectedPanel->mMediaSource->initializeUrlHistory(historySD); + delete[] cstr; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::gluiCallback( int control_id ) +{ + if ( control_id == mIdBookmarks ) + { + std::string uri = mBookmarks[ mSelBookmark ].second; + + navigateToNewURI( uri ); + } + else + if ( control_id == mIdUrlEdit) + { + std::string uri = mUrlEdit->get_text(); + + navigateToNewURI( uri ); + } + else + if ( control_id == mIdUrlInitHistoryEdit ) + { + std::string uri = mUrlInitHistoryEdit->get_text(); + + initUrlHistory( uri ); + } + else + if ( control_id == mIdControlAddPanel ) + { + addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second ); + } + else + if ( control_id == mIdControlRemPanel ) + { + remMediaPanel( mSelectedPanel ); + } + else + if ( control_id == mIdDisableTimeout ) + { + // Set the "disable timeout" flag for all active plugins. + for( int i = 0; i < (int)mMediaPanels.size(); ++i ) + { + mMediaPanels[ i ]->mMediaSource->setDisableTimeout(mDisableTimeout); + } + } + else + if ( control_id == mIdControlCrashPlugin ) + { + // send message to plugin and ask it to crash + // (switch out for ReleaseCandidate version :) ) + if(mSelectedPanel && mSelectedPanel->mMediaSource) + { + mSelectedPanel->mMediaSource->crashPlugin(); + } + } + else + if ( control_id == mIdControlHangPlugin ) + { + // send message to plugin and ask it to hang + // (switch out for ReleaseCandidate version :) ) + if(mSelectedPanel && mSelectedPanel->mMediaSource) + { + mSelectedPanel->mMediaSource->hangPlugin(); + } + } + else + if ( control_id == mIdControlExitApp ) + { + // text for exiting plugin system cleanly + delete this; // clean up + exit( 0 ); + } + else + if ( control_id == mIdMediaTimeControlPlay ) + { + if ( mSelectedPanel ) + { + mSelectedPanel->mMediaSource->setLoop( false ); + mSelectedPanel->mMediaSource->start(); + }; + } + else + if ( control_id == mIdMediaTimeControlLoop ) + { + if ( mSelectedPanel ) + { + mSelectedPanel->mMediaSource->setLoop( true ); + mSelectedPanel->mMediaSource->start(); + }; + } + else + if ( control_id == mIdMediaTimeControlPause ) + { + if ( mSelectedPanel ) + mSelectedPanel->mMediaSource->pause(); + } + else + if ( control_id == mIdMediaTimeControlStop ) + { + if ( mSelectedPanel ) + { + mSelectedPanel->mMediaSource->stop(); + }; + } + else + if ( control_id == mIdMediaTimeControlSeek ) + { + if ( mSelectedPanel ) + { + // get value from spinner + float seconds_to_seek = mMediaTimeControlSeekSeconds; + mSelectedPanel->mMediaSource->seek( seconds_to_seek ); + mSelectedPanel->mMediaSource->start(); + }; + } + else + if ( control_id == mIdMediaTimeControlRewind ) + { + if ( mSelectedPanel ) + { + mSelectedPanel->mMediaSource->setLoop( false ); + mSelectedPanel->mMediaSource->start(-2.0f); + }; + } + else + if ( control_id == mIdMediaTimeControlFastForward ) + { + if ( mSelectedPanel ) + { + mSelectedPanel->mMediaSource->setLoop( false ); + mSelectedPanel->mMediaSource->start(2.0f); + }; + } + else + if ( control_id == mIdMediaBrowserControlBack ) + { + if ( mSelectedPanel ) + mSelectedPanel->mMediaSource->browse_back(); + } + else + if ( control_id == mIdMediaBrowserControlStop ) + { + if ( mSelectedPanel ) + mSelectedPanel->mMediaSource->browse_stop(); + } + else + if ( control_id == mIdMediaBrowserControlForward ) + { + if ( mSelectedPanel ) + mSelectedPanel->mMediaSource->browse_forward(); + } + else + if ( control_id == mIdMediaBrowserControlHome ) + { + if ( mSelectedPanel ) + mSelectedPanel->mMediaSource->loadURI( mHomeWebUrl ); + } + else + if ( control_id == mIdMediaBrowserControlReload ) + { + if ( mSelectedPanel ) + mSelectedPanel->mMediaSource->browse_reload( true ); + } + else + if ( control_id == mIdMediaBrowserControlClearCache ) + { + if ( mSelectedPanel ) + mSelectedPanel->mMediaSource->clear_cache(); + } + else + if ( control_id == mIdMediaBrowserControlClearCookies ) + { + if ( mSelectedPanel ) + mSelectedPanel->mMediaSource->clear_cookies(); + } + else + if ( control_id == mIdMediaBrowserControlEnableCookies ) + { + if ( mSelectedPanel ) + { + if ( mMediaBrowserControlEnableCookies ) + { + mSelectedPanel->mMediaSource->enable_cookies( true ); + } + else + { + mSelectedPanel->mMediaSource->enable_cookies( false ); + } + }; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::keyboard( int key ) +{ + //if ( key == 'a' || key == 'A' ) + // addMediaPanel( mBookmarks[ rand() % ( mBookmarks.size() - 1 ) + 1 ].second ); + //else + //if ( key == 'r' || key == 'R' ) + // remMediaPanel( mSelectedPanel ); + //else + //if ( key == 'd' || key == 'D' ) + // dumpPanelInfo(); + //else + if ( key == 27 ) + { + std::cout << "Application finished - exiting..." << std::endl; + delete this; + exit( 0 ); + }; + + mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_DOWN, key, 0 ); + mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_UP, key, 0 ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::mouseButton( int button, int state, int x, int y ) +{ + if ( button == GLUT_LEFT_BUTTON ) + { + if ( state == GLUT_DOWN ) + { + int media_x, media_y, id; + windowPosToTexturePos( x, y, media_x, media_y, id ); + + if ( mSelectedPanel ) + mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_DOWN, 0, media_x, media_y, 0 ); + } + else + if ( state == GLUT_UP ) + { + int media_x, media_y, id; + windowPosToTexturePos( x, y, media_x, media_y, id ); + + // only select a panel if we're on a panel + // (HACK: strictly speaking this rules out clicking on + // the origin of a panel but that's very unlikely) + if ( media_x > 0 && media_y > 0 ) + { + selectPanelById( id ); + + if ( mSelectedPanel ) + mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_UP, 0, media_x, media_y, 0 ); + }; + }; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::mousePassive( int x, int y ) +{ + int media_x, media_y, id; + windowPosToTexturePos( x, y, media_x, media_y, id ); + + if ( mSelectedPanel ) + mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::mouseMove( int x, int y ) +{ + int media_x, media_y, id; + windowPosToTexturePos( x, y, media_x, media_y, id ); + + if ( mSelectedPanel ) + mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::makeChrome() +{ + // IDs used by GLUI + int start_id = 0x1000; + + // right side window - geometry manipulators +#if __APPLE__ + // the Apple GLUT implementation doesn't seem to set the graphic offset of subwindows correctly when they overlap in certain ways. + // Use a separate controls window in this case. + // GLUI window at right containing manipulation controls and other buttons + int x = glutGet(GLUT_WINDOW_X) + glutGet(GLUT_WINDOW_WIDTH) + 4; + int y = glutGet(GLUT_WINDOW_Y); + GLUI* right_glui_window = GLUI_Master.create_glui( "", 0, x, y ); +#else + GLUI* right_glui_window = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_RIGHT ); +#endif + mViewRotationCtrl = right_glui_window->add_rotation( "Rotation", mViewRotation ); + mViewTranslationCtrl = right_glui_window->add_translation( "Translate", GLUI_TRANSLATION_XY, mViewPos ); + mViewTranslationCtrl->set_speed( 0.01f ); + mViewScaleCtrl = right_glui_window->add_translation( "Scale", GLUI_TRANSLATION_Z, &mViewPos[ 2 ] ); + mViewScaleCtrl->set_speed( 0.05f ); + right_glui_window->set_main_gfx_window( mAppWindow ); + + // right side window - app controls + mIdControlAddPanel = start_id++; + right_glui_window->add_statictext( "" ); + right_glui_window->add_separator(); + right_glui_window->add_statictext( "" ); + right_glui_window->add_button( "Add panel", mIdControlAddPanel, gluiCallbackWrapper ); + right_glui_window->add_statictext( "" ); + mIdControlRemPanel = start_id++; + right_glui_window->add_button( "Rem panel", mIdControlRemPanel, gluiCallbackWrapper ); + right_glui_window->add_statictext( "" ); + right_glui_window->add_separator(); + right_glui_window->add_statictext( "" ); + mIdControlCrashPlugin = start_id++; + right_glui_window->add_button( "Crash plugin", mIdControlCrashPlugin, gluiCallbackWrapper ); + mIdControlHangPlugin = start_id++; + right_glui_window->add_button( "Hang plugin", mIdControlHangPlugin, gluiCallbackWrapper ); + + right_glui_window->add_statictext( "" ); + right_glui_window->add_separator(); + right_glui_window->add_statictext( "" ); + mIdControlExitApp = start_id++; + right_glui_window->add_button( "Exit app", mIdControlExitApp, gluiCallbackWrapper ); + + //// top window - holds bookmark UI + mIdBookmarks = start_id++; + mSelBookmark = 0; + GLUI* glui_window_top = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP ); + mBookmarkList = glui_window_top->add_listbox( "", &mSelBookmark, mIdBookmarks, gluiCallbackWrapper ); + // only add the first 50 bookmarks - list can be very long sometimes (30,000+) + // when testing list of media URLs from AGNI for example + for( unsigned int each = 0; each < mBookmarks.size() && each < 50; ++each ) + mBookmarkList->add_item( each, const_cast< char* >( mBookmarks[ each ].first.c_str() ) ); + glui_window_top->set_main_gfx_window( mAppWindow ); + + glui_window_top->add_column( false ); + mIdUrlEdit = start_id++; + mUrlEdit = glui_window_top->add_edittext( "Url:", GLUI_EDITTEXT_TEXT, 0, mIdUrlEdit, gluiCallbackWrapper ); + mUrlEdit->set_w( 600 ); + GLUI* glui_window_top2 = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP ); + mIdUrlInitHistoryEdit = start_id++; + mUrlInitHistoryEdit = glui_window_top2->add_edittext( "Init History (separate by commas or semicolons):", + GLUI_EDITTEXT_TEXT, 0, mIdUrlInitHistoryEdit, gluiCallbackWrapper ); + mUrlInitHistoryEdit->set_w( 800 ); + + // top window - media controls for "time" media types (e.g. movies) + mGluiMediaTimeControlWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP ); + mGluiMediaTimeControlWindow->set_main_gfx_window( mAppWindow ); + mIdMediaTimeControlPlay = start_id++; + mGluiMediaTimeControlWindow->add_button( "PLAY", mIdMediaTimeControlPlay, gluiCallbackWrapper ); + mGluiMediaTimeControlWindow->add_column( false ); + mIdMediaTimeControlLoop = start_id++; + mGluiMediaTimeControlWindow->add_button( "LOOP", mIdMediaTimeControlLoop, gluiCallbackWrapper ); + mGluiMediaTimeControlWindow->add_column( false ); + mIdMediaTimeControlPause = start_id++; + mGluiMediaTimeControlWindow->add_button( "PAUSE", mIdMediaTimeControlPause, gluiCallbackWrapper ); + mGluiMediaTimeControlWindow->add_column( false ); + + GLUI_Button *button; + mIdMediaTimeControlRewind = start_id++; + button = mGluiMediaTimeControlWindow->add_button( "<<", mIdMediaTimeControlRewind, gluiCallbackWrapper ); + button->set_w(30); + mGluiMediaTimeControlWindow->add_column( false ); + mIdMediaTimeControlFastForward = start_id++; + button = mGluiMediaTimeControlWindow->add_button( ">>", mIdMediaTimeControlFastForward, gluiCallbackWrapper ); + button->set_w(30); + + mGluiMediaTimeControlWindow->add_column( true ); + + mIdMediaTimeControlStop = start_id++; + mGluiMediaTimeControlWindow->add_button( "STOP", mIdMediaTimeControlStop, gluiCallbackWrapper ); + mGluiMediaTimeControlWindow->add_column( false ); + mIdMediaTimeControlVolume = start_id++; + GLUI_Spinner* spinner = mGluiMediaTimeControlWindow->add_spinner( "Volume", 2, &mMediaTimeControlVolume, mIdMediaTimeControlVolume, gluiCallbackWrapper); + spinner->set_float_limits( 0, 100 ); + mGluiMediaTimeControlWindow->add_column( true ); + mIdMediaTimeControlSeekSeconds = start_id++; + spinner = mGluiMediaTimeControlWindow->add_spinner( "", 2, &mMediaTimeControlSeekSeconds, mIdMediaTimeControlSeekSeconds, gluiCallbackWrapper); + spinner->set_float_limits( 0, 200 ); + spinner->set_w( 32 ); + spinner->set_speed( 0.025f ); + mGluiMediaTimeControlWindow->add_column( false ); + mIdMediaTimeControlSeek = start_id++; + mGluiMediaTimeControlWindow->add_button( "SEEK", mIdMediaTimeControlSeek, gluiCallbackWrapper ); + mGluiMediaTimeControlWindow->add_column( false ); + + + // top window - media controls for "browser" media types (e.g. web browser) + mGluiMediaBrowserControlWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP ); + mGluiMediaBrowserControlWindow->set_main_gfx_window( mAppWindow ); + mIdMediaBrowserControlBack = start_id++; + mMediaBrowserControlBackButton = mGluiMediaBrowserControlWindow->add_button( "BACK", mIdMediaBrowserControlBack, gluiCallbackWrapper ); + mGluiMediaBrowserControlWindow->add_column( false ); + mIdMediaBrowserControlStop = start_id++; + mGluiMediaBrowserControlWindow->add_button( "STOP", mIdMediaBrowserControlStop, gluiCallbackWrapper ); + mGluiMediaBrowserControlWindow->add_column( false ); + mIdMediaBrowserControlForward = start_id++; + mMediaBrowserControlForwardButton = mGluiMediaBrowserControlWindow->add_button( "FORWARD", mIdMediaBrowserControlForward, gluiCallbackWrapper ); + mGluiMediaBrowserControlWindow->add_column( false ); + mIdMediaBrowserControlHome = start_id++; + mGluiMediaBrowserControlWindow->add_button( "HOME", mIdMediaBrowserControlHome, gluiCallbackWrapper ); + mGluiMediaBrowserControlWindow->add_column( false ); + mIdMediaBrowserControlReload = start_id++; + mGluiMediaBrowserControlWindow->add_button( "RELOAD", mIdMediaBrowserControlReload, gluiCallbackWrapper ); + mGluiMediaBrowserControlWindow->add_column( false ); + mIdMediaBrowserControlClearCache = start_id++; + mGluiMediaBrowserControlWindow->add_button( "CLEAR CACHE", mIdMediaBrowserControlClearCache, gluiCallbackWrapper ); + mGluiMediaBrowserControlWindow->add_column( false ); + mIdMediaBrowserControlClearCookies = start_id++; + mGluiMediaBrowserControlWindow->add_button( "CLEAR COOKIES", mIdMediaBrowserControlClearCookies, gluiCallbackWrapper ); + mGluiMediaBrowserControlWindow->add_column( false ); + mIdMediaBrowserControlEnableCookies = start_id++; + mMediaBrowserControlEnableCookies = 0; + mGluiMediaBrowserControlWindow->add_checkbox( "Enable Cookies", &mMediaBrowserControlEnableCookies, mIdMediaBrowserControlEnableCookies, gluiCallbackWrapper ); + + // top window - misc controls + GLUI* glui_window_misc_control = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_TOP ); + mIdRandomPanelCount = start_id++; + mRandomPanelCount = 0; + glui_window_misc_control->add_checkbox( "Randomize panel count", &mRandomPanelCount, mIdRandomPanelCount, gluiCallbackWrapper ); + glui_window_misc_control->set_main_gfx_window( mAppWindow ); + glui_window_misc_control->add_column( true ); + mIdRandomBookmarks = start_id++; + mRandomBookmarks = 0; + glui_window_misc_control->add_checkbox( "Randomize bookmarks", &mRandomBookmarks, mIdRandomBookmarks, gluiCallbackWrapper ); + glui_window_misc_control->set_main_gfx_window( mAppWindow ); + glui_window_misc_control->add_column( true ); + + mIdDisableTimeout = start_id++; + mDisableTimeout = 0; + glui_window_misc_control->add_checkbox( "Disable plugin timeout", &mDisableTimeout, mIdDisableTimeout, gluiCallbackWrapper ); + glui_window_misc_control->set_main_gfx_window( mAppWindow ); + + // bottom window - status + mBottomGLUIWindow = GLUI_Master.create_glui_subwindow( mAppWindow, GLUI_SUBWINDOW_BOTTOM ); + mStatusText = mBottomGLUIWindow->add_statictext( "" ); + mBottomGLUIWindow->set_main_gfx_window( mAppWindow ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::resetView() +{ + mViewRotationCtrl->reset(); + + mViewScaleCtrl->set_x( 0.0f ); + mViewScaleCtrl->set_y( 0.0f ); + mViewScaleCtrl->set_z( 3.0f ); + + mViewTranslationCtrl->set_x( 0.0f ); + mViewTranslationCtrl->set_y( 0.0f ); + mViewTranslationCtrl->set_z( 0.0f ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels ) +{ + int pick_texture_width = 1024; + int pick_texture_height = 1024; + int pick_texture_depth = 3; + unsigned char* ptr = new unsigned char[ pick_texture_width * pick_texture_height * pick_texture_depth ]; + for( int y = 0; y < pick_texture_height; ++y ) + { + for( int x = 0; x < pick_texture_width * pick_texture_depth ; x += pick_texture_depth ) + { + unsigned long bits = 0L; + bits |= ( id << 20 ) | ( y << 10 ) | ( x / 3 ); + unsigned char r_component = ( bits >> 16 ) & 0xff; + unsigned char g_component = ( bits >> 8 ) & 0xff; + unsigned char b_component = bits & 0xff; + + ptr[ y * pick_texture_width * pick_texture_depth + x + 0 ] = r_component; + ptr[ y * pick_texture_width * pick_texture_depth + x + 1 ] = g_component; + ptr[ y * pick_texture_width * pick_texture_depth + x + 2 ] = b_component; + }; + }; + + glGenTextures( 1, texture_handle ); + + checkGLError("glGenTextures"); + std::cout << "glGenTextures returned " << *texture_handle << std::endl; + + bindTexture( *texture_handle ); + glTexImage2D( GL_TEXTURE_2D, 0, + GL_RGB, + pick_texture_width, pick_texture_height, + 0, GL_RGB, GL_UNSIGNED_BYTE, ptr ); + + *texture_pixels = ptr; +} + +//////////////////////////////////////////////////////////////////////////////// +// +std::string LLMediaPluginTest::mimeTypeFromUrl( std::string& url ) +{ + // default to web + std::string mime_type = "text/html"; + + // we may need a more advanced MIME type accessor later :-) + if ( url.find( ".mov" ) != std::string::npos ) // Movies + mime_type = "video/quicktime"; + else + if ( url.find( ".txt" ) != std::string::npos ) // Apple Text descriptors + mime_type = "video/quicktime"; + else + if ( url.find( ".mp3" ) != std::string::npos ) // Apple Text descriptors + mime_type = "video/quicktime"; + else + if ( url.find( "example://" ) != std::string::npos ) // Example plugin + mime_type = "example/example"; + + return mime_type; +} + +//////////////////////////////////////////////////////////////////////////////// +// +std::string LLMediaPluginTest::pluginNameFromMimeType( std::string& mime_type ) +{ +#if LL_DARWIN + std::string plugin_name( "media_plugin_null.dylib" ); + if ( mime_type == "video/quicktime" ) + plugin_name = "media_plugin_quicktime.dylib"; + else + if ( mime_type == "text/html" ) + plugin_name = "media_plugin_webkit.dylib"; + +#elif LL_WINDOWS + std::string plugin_name( "media_plugin_null.dll" ); + + if ( mime_type == "video/quicktime" ) + plugin_name = "media_plugin_quicktime.dll"; + else + if ( mime_type == "text/html" ) + plugin_name = "media_plugin_webkit.dll"; + else + if ( mime_type == "example/example" ) + plugin_name = "media_plugin_example.dll"; + +#elif LL_LINUX + std::string plugin_name( "libmedia_plugin_null.so" ); + + if ( mime_type == "video/quicktime" ) + plugin_name = "libmedia_plugin_quicktime.so"; + else + if ( mime_type == "text/html" ) + plugin_name = "libmedia_plugin_webkit.so"; +#endif + return plugin_name; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::addMediaPanel( std::string url ) +{ + // Get the plugin filename using the URL + std::string mime_type = mimeTypeFromUrl( url ); + std::string plugin_name = pluginNameFromMimeType( mime_type ); + + // create a random size for the new media + int media_width; + int media_height; + getRandomMediaSize( media_width, media_height, mime_type ); + + // make a new plugin + LLPluginClassMedia* media_source = new LLPluginClassMedia(this); + + // tell the plugin what size we asked for + media_source->setSize( media_width, media_height ); + + // Use the launcher start and initialize the plugin +#if LL_DARWIN || LL_LINUX + std::string launcher_name( "SLPlugin" ); +#elif LL_WINDOWS + std::string launcher_name( "SLPlugin.exe" ); +#endif + media_source->init( launcher_name, plugin_name ); + media_source->setDisableTimeout(mDisableTimeout); + + // make a new panel and save parameters + mediaPanel* panel = new mediaPanel; + panel->mMediaSource = media_source; + panel->mStartUrl = url; + panel->mMimeType = mime_type; + panel->mMediaWidth = media_width; + panel->mMediaHeight = media_height; + panel->mTextureWidth = 0; + panel->mTextureHeight = 0; + panel->mTextureScaleX = 0; + panel->mTextureScaleY = 0; + panel->mMediaTextureHandle = 0; + panel->mPickTextureHandle = 0; + panel->mAppTextureCoordsOpenGL = false; // really need an 'undefined' state here too + panel->mReadyToRender = false; + + // look through current media panels to find an unused index number + bool id_exists = true; + for( int nid = 0; nid < mMaxPanels; ++nid ) + { + // does this id exist already? + id_exists = false; + for( int pid = 0; pid < (int)mMediaPanels.size(); ++pid ) + { + if ( nid == mMediaPanels[ pid ]->mId ) + { + id_exists = true; + break; + }; + }; + + // id wasn't found so we can use it + if ( ! id_exists ) + { + panel->mId = nid; + break; + }; + }; + + // if we get here and this flag is set, there is no room for any more panels + if ( id_exists ) + { + std::cout << "No room for any more panels" << std::endl; + } + else + { + // now we have the ID we can use it to make the + // pick texture (id is baked into texture pixels) + makePickTexture( panel->mId, &panel->mPickTextureHandle, &panel->mPickTexturePixels ); + + // save this in the list of panels + mMediaPanels.push_back( panel ); + + // select the panel that was just created + selectPanel( panel ); + + // load and start the URL + panel->mMediaSource->loadURI( url ); + panel->mMediaSource->start(); + + std::cout << "Adding new media panel for " << url << "(" << media_width << "x" << media_height << ") with index " << panel->mId << " - total panels = " << mMediaPanels.size() << std::endl; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::updateMediaPanel( mediaPanel* panel ) +{ +// checkGLError("LLMediaPluginTest::updateMediaPanel"); + + if ( ! panel ) + return; + + if(!panel->mMediaSource || !panel->mMediaSource->textureValid()) + { + panel->mReadyToRender = false; + return; + } + + // take a reference copy of the plugin values since they + // might change during this lifetime of this function + int plugin_media_width = panel->mMediaSource->getWidth(); + int plugin_media_height = panel->mMediaSource->getHeight(); + int plugin_texture_width = panel->mMediaSource->getBitsWidth(); + int plugin_texture_height = panel->mMediaSource->getBitsHeight(); + + // If the texture isn't created or the media or texture dimensions changed AND + // the sizes are valid then we need to delete the old media texture (if necessary) + // then make a new one. + if ((panel->mMediaTextureHandle == 0 || + panel->mMediaWidth != plugin_media_width || + panel->mMediaHeight != plugin_media_height || + panel->mTextureWidth != plugin_texture_width || + panel->mTextureHeight != plugin_texture_height) && + ( plugin_media_width > 0 && plugin_media_height > 0 && + plugin_texture_width > 0 && plugin_texture_height > 0 ) ) + { + std::cout << "Valid media size (" << plugin_media_width << " x " << plugin_media_height + << ") and texture size (" << plugin_texture_width << " x " << plugin_texture_height + << ") for panel with ID=" << panel->mId << " - making texture" << std::endl; + + // delete old GL texture + if ( isTexture( panel->mMediaTextureHandle ) ) + { + std::cerr << "updateMediaPanel: deleting texture " << panel->mMediaTextureHandle << std::endl; + glDeleteTextures( 1, &panel->mMediaTextureHandle ); + panel->mMediaTextureHandle = 0; + } + + std::cerr << "before: pick texture is " << panel->mPickTextureHandle << ", media texture is " << panel->mMediaTextureHandle << std::endl; + + // make a GL texture based on the dimensions the plugin told us + GLuint new_texture = 0; + glGenTextures( 1, &new_texture ); + + checkGLError("glGenTextures"); + + std::cout << "glGenTextures returned " << new_texture << std::endl; + + panel->mMediaTextureHandle = new_texture; + + bindTexture( panel->mMediaTextureHandle ); + + std::cout << "Setting texture size to " << plugin_texture_width << " x " << plugin_texture_height << std::endl; + glTexImage2D( GL_TEXTURE_2D, 0, + GL_RGB, + plugin_texture_width, plugin_texture_height, + 0, GL_RGB, GL_UNSIGNED_BYTE, + 0 ); + + + std::cerr << "after: pick texture is " << panel->mPickTextureHandle << ", media texture is " << panel->mMediaTextureHandle << std::endl; + }; + + // update our record of the media and texture dimensions + // NOTE: do this after we we check for sizes changes + panel->mMediaWidth = plugin_media_width; + panel->mMediaHeight = plugin_media_height; + panel->mTextureWidth = plugin_texture_width; + panel->mTextureHeight = plugin_texture_height; + if ( plugin_texture_width > 0 ) + { + panel->mTextureScaleX = (double)panel->mMediaWidth / (double)panel->mTextureWidth; + }; + if ( plugin_texture_height > 0 ) + { + panel->mTextureScaleY = (double)panel->mMediaHeight / (double)panel->mTextureHeight; + }; + + // update the flag which tells us if the media source uses OprnGL coords or not. + panel->mAppTextureCoordsOpenGL = panel->mMediaSource->getTextureCoordsOpenGL(); + + // Check to see if we have enough to render this panel. + // If we do, set a flag that the display functions use so + // they only render a panel with media if it's ready. + if ( panel->mMediaWidth < 0 || + panel->mMediaHeight < 0 || + panel->mTextureWidth < 1 || + panel->mTextureHeight < 1 || + panel->mMediaTextureHandle == 0 ) + { + panel->mReadyToRender = false; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url ) +{ + // no media panels so we can't change anything - have to add + if ( mMediaPanels.size() == 0 ) + return; + + // sanity check + if ( ! panel ) + return; + + int index; + for(index = 0; index < (int)mMediaPanels.size(); index++) + { + if(mMediaPanels[index] == panel) + break; + } + + if(index >= (int)mMediaPanels.size()) + { + // panel isn't in mMediaPanels + return; + } + + std::cout << "Replacing media panel with index " << panel->mId << std::endl; + + int panel_id = panel->mId; + + if(mSelectedPanel == panel) + mSelectedPanel = NULL; + + delete panel; + + // Get the plugin filename using the URL + std::string mime_type = mimeTypeFromUrl( url ); + std::string plugin_name = pluginNameFromMimeType( mime_type ); + + // create a random size for the new media + int media_width; + int media_height; + getRandomMediaSize( media_width, media_height, mime_type ); + + // make a new plugin + LLPluginClassMedia* media_source = new LLPluginClassMedia(this); + + // tell the plugin what size we asked for + media_source->setSize( media_width, media_height ); + + // Use the launcher start and initialize the plugin +#if LL_DARWIN || LL_LINUX + std::string launcher_name( "SLPlugin" ); +#elif LL_WINDOWS + std::string launcher_name( "SLPlugin.exe" ); +#endif + media_source->init( launcher_name, plugin_name ); + media_source->setDisableTimeout(mDisableTimeout); + + // make a new panel and save parameters + panel = new mediaPanel; + panel->mMediaSource = media_source; + panel->mStartUrl = url; + panel->mMimeType = mime_type; + panel->mMediaWidth = media_width; + panel->mMediaHeight = media_height; + panel->mTextureWidth = 0; + panel->mTextureHeight = 0; + panel->mTextureScaleX = 0; + panel->mTextureScaleY = 0; + panel->mMediaTextureHandle = 0; + panel->mPickTextureHandle = 0; + panel->mAppTextureCoordsOpenGL = false; // really need an 'undefined' state here too + panel->mReadyToRender = false; + + panel->mId = panel_id; + + // Replace the entry in the panels array + mMediaPanels[index] = panel; + + // now we have the ID we can use it to make the + // pick texture (id is baked into texture pixels) + makePickTexture( panel->mId, &panel->mPickTextureHandle, &panel->mPickTexturePixels ); + + // select the panel that was just created + selectPanel( panel ); + + // load and start the URL + panel->mMediaSource->loadURI( url ); + panel->mMediaSource->start(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::getRandomMediaSize( int& width, int& height, std::string mime_type ) +{ + // Make a new media source with a random size which we'll either + // directly or the media plugin will tell us what it wants later. + // Use a random size so we can test support for weird media sizes. + // (Almost everything else will get filled in later once the + // plugin responds) + // NB. Do we need to enforce that width is on 4 pixel boundary? + width = ( ( rand() % 170 ) + 30 ) * 4; + height = ( ( rand() % 170 ) + 30 ) * 4; + + // adjust this random size if it's a browser so we get + // a more useful size for testing.. + if ( mime_type == "text/html" || mime_type == "example/example" ) + { + width = ( ( rand() % 100 ) + 100 ) * 4; + height = ( width * ( ( rand() % 400 ) + 1000 ) ) / 1000; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::remMediaPanel( mediaPanel* panel ) +{ + // always leave one panel + if ( mMediaPanels.size() == 1 ) + return; + + // sanity check - don't think this can happen but see above for a case where it might... + if ( ! panel ) + return; + + std::cout << "Removing media panel with index " << panel->mId << " - total panels = " << mMediaPanels.size() - 1 << std::endl; + + if(mSelectedPanel == panel) + mSelectedPanel = NULL; + + delete panel; + + // remove from storage list + for( int i = 0; i < (int)mMediaPanels.size(); ++i ) + { + if ( mMediaPanels[ i ] == panel ) + { + mMediaPanels.erase( mMediaPanels.begin() + i ); + break; + }; + }; + + // select the first panel + selectPanel( mMediaPanels[ 0 ] ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::updateStatusBar() +{ + if ( ! mSelectedPanel ) + return; + + // cache results - this is a very slow function + static int cached_id = -1; + static int cached_media_width = -1; + static int cached_media_height = -1; + static int cached_texture_width = -1; + static int cached_texture_height = -1; + static bool cached_supports_browser_media = true; + static bool cached_supports_time_media = false; + static int cached_movie_time = -1; + + static std::string cached_plugin_version = ""; + if ( + cached_id == mSelectedPanel->mId && + cached_media_width == mSelectedPanel->mMediaWidth && + cached_media_height == mSelectedPanel->mMediaHeight && + cached_texture_width == mSelectedPanel->mTextureWidth && + cached_texture_height == mSelectedPanel->mTextureHeight && + cached_supports_browser_media == mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() && + cached_supports_time_media == mSelectedPanel->mMediaSource->pluginSupportsMediaTime() && + cached_plugin_version == mSelectedPanel->mMediaSource->getPluginVersion() && + cached_movie_time == (int)mSelectedPanel->mMediaSource->getCurrentTime() + ) + { + // nothing changed so don't spend time in this shitty function + return; + }; + + std::ostringstream stream( "" ); + + stream.str( "" ); + stream.clear(); + + stream << "Id: "; + stream << std::setw( 2 ) << std::setfill( '0' ); + stream << mSelectedPanel->mId; + stream << " | "; + stream << "Media: "; + stream << std::setw( 3 ) << std::setfill( '0' ); + stream << mSelectedPanel->mMediaWidth; + stream << " x "; + stream << std::setw( 3 ) << std::setfill( '0' ); + stream << mSelectedPanel->mMediaHeight; + stream << " | "; + stream << "Texture: "; + stream << std::setw( 4 ) << std::setfill( '0' ); + stream << mSelectedPanel->mTextureWidth; + stream << " x "; + stream << std::setw( 4 ) << std::setfill( '0' ); + stream << mSelectedPanel->mTextureHeight; + stream << " | "; + if ( mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser() ) + stream << "BROWSER"; + else + if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() ) + stream << "TIME "; + stream << " | "; + stream << mSelectedPanel->mMediaSource->getPluginVersion(); + stream << " | "; + if ( mSelectedPanel->mMediaSource->pluginSupportsMediaTime() ) + { + stream << std::setw( 3 ) << std::setfill( '0' ); + stream << (int)mSelectedPanel->mMediaSource->getCurrentTime(); + stream << " / "; + stream << std::setw( 3 ) << std::setfill( '0' ); + stream << (int)mSelectedPanel->mMediaSource->getDuration(); + stream << " @ "; + stream << (int)mSelectedPanel->mMediaSource->getCurrentPlayRate(); + stream << " | "; + }; + + glutSetWindow( mBottomGLUIWindow->get_glut_window_id() ); + mStatusText->set_text( const_cast< char*>( stream.str().c_str() ) ); + glutSetWindow( mAppWindow ); + + // caching + cached_id = mSelectedPanel->mId; + cached_media_width = mSelectedPanel->mMediaWidth; + cached_media_height = mSelectedPanel->mMediaHeight; + cached_texture_width = mSelectedPanel->mTextureWidth; + cached_texture_height = mSelectedPanel->mTextureHeight; + cached_supports_browser_media = mSelectedPanel->mMediaSource->pluginSupportsMediaBrowser(); + cached_supports_time_media = mSelectedPanel->mMediaSource->pluginSupportsMediaTime(); + cached_plugin_version = mSelectedPanel->mMediaSource->getPluginVersion(); + cached_movie_time = (int)mSelectedPanel->mMediaSource->getCurrentTime(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::dumpPanelInfo() +{ + std::cout << std::endl << "===== Media Panels =====" << std::endl; + for( int i = 0; i < (int)mMediaPanels.size(); ++i ) + { + std::cout << std::setw( 2 ) << std::setfill( '0' ); + std::cout << i + 1 << "> "; + std::cout << "Id: "; + std::cout << std::setw( 2 ) << std::setfill( '0' ); + std::cout << mMediaPanels[ i ]->mId; + std::cout << " | "; + std::cout << "Media: "; + std::cout << std::setw( 3 ) << std::setfill( '0' ); + std::cout << mMediaPanels[ i ]->mMediaWidth; + std::cout << " x "; + std::cout << std::setw( 3 ) << std::setfill( '0' ); + std::cout << mMediaPanels[ i ]->mMediaHeight; + std::cout << " | "; + std::cout << "Texture: "; + std::cout << std::setw( 4 ) << std::setfill( '0' ); + std::cout << mMediaPanels[ i ]->mTextureWidth; + std::cout << " x "; + std::cout << std::setw( 4 ) << std::setfill( '0' ); + std::cout << mMediaPanels[ i ]->mTextureHeight; + std::cout << " | "; + if ( mMediaPanels[ i ] == mSelectedPanel ) + std::cout << "(selected)"; + + std::cout << std::endl; + }; + std::cout << "========================" << std::endl; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ + // Uncomment this to make things much, much quieter. +// return; + + switch(event) + { + case MEDIA_EVENT_CONTENT_UPDATED: + // too spammy -- don't log these +// std::cerr << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << std::endl; + break; + + case MEDIA_EVENT_TIME_DURATION_UPDATED: + // too spammy -- don't log these +// std::cerr << "Media event: MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << std::endl; + break; + + case MEDIA_EVENT_SIZE_CHANGED: + std::cerr << "Media event: MEDIA_EVENT_SIZE_CHANGED " << std::endl; + break; + + case MEDIA_EVENT_CURSOR_CHANGED: + std::cerr << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << std::endl; + break; + + case MEDIA_EVENT_NAVIGATE_BEGIN: + std::cerr << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN " << std::endl; + break; + + case MEDIA_EVENT_NAVIGATE_COMPLETE: + std::cerr << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << std::endl; + break; + + case MEDIA_EVENT_PROGRESS_UPDATED: + std::cerr << "Media event: MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << std::endl; + break; + + case MEDIA_EVENT_STATUS_TEXT_CHANGED: + std::cerr << "Media event: MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << std::endl; + break; + + case MEDIA_EVENT_NAME_CHANGED: + std::cerr << "Media event: MEDIA_EVENT_NAME_CHANGED, new name is: " << self->getMediaName() << std::endl; + glutSetWindowTitle( self->getMediaName().c_str() ); + break; + + case MEDIA_EVENT_LOCATION_CHANGED: + { + std::cerr << "Media event: MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << std::endl; + mediaPanel* panel = findMediaPanel(self); + if(panel != NULL) + { + panel->mStartUrl = self->getLocation(); + if(panel == mSelectedPanel) + { + mUrlEdit->set_text(const_cast<char*>(panel->mStartUrl.c_str()) ); + } + } + } + break; + + case MEDIA_EVENT_CLICK_LINK_HREF: + std::cerr << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, uri is " << self->getClickURL() << std::endl; + break; + + case MEDIA_EVENT_CLICK_LINK_NOFOLLOW: + std::cerr << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << std::endl; + break; + + case MEDIA_EVENT_PLUGIN_FAILED: + std::cerr << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << std::endl; + break; + + case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH: + std::cerr << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << std::endl; + break; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +static void gluiCallbackWrapper( int control_id ) +{ + if ( gApplication ) + gApplication->gluiCallback( control_id ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void glutReshape( int width, int height ) +{ + if ( gApplication ) + gApplication->reshape( width, height ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutDisplay() +{ + if ( gApplication ) + gApplication->display(); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutIdle(int update_ms) +{ + GLUI_Master.set_glutTimerFunc( update_ms, glutIdle, update_ms); + + if ( gApplication ) + gApplication->idle(); + +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutKeyboard( unsigned char key, int x, int y ) +{ + if ( gApplication ) + gApplication->keyboard( key ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutMousePassive( int x, int y ) +{ + if ( gApplication ) + gApplication->mousePassive( x, y ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void glutMouseMove( int x , int y ) +{ + if ( gApplication ) + gApplication->mouseMove( x, y ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void glutMouseButton( int button, int state, int x, int y ) +{ + if ( gApplication ) + gApplication->mouseButton( button, state, x, y ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +int main( int argc, char* argv[] ) +{ +#if LL_DARWIN + // Set the current working directory to <application bundle>/Contents/Resources/ + CFURLRef resources_url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); + if(resources_url != NULL) + { + CFStringRef resources_string = CFURLCopyFileSystemPath(resources_url, kCFURLPOSIXPathStyle); + CFRelease(resources_url); + if(resources_string != NULL) + { + char buffer[PATH_MAX] = ""; + if(CFStringGetCString(resources_string, buffer, sizeof(buffer), kCFStringEncodingUTF8)) + { + chdir(buffer); + } + CFRelease(resources_string); + } + } +#endif + + glutInit( &argc, argv ); + glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB ); + + const int app_window_x = 80; + const int app_window_y = 0; + const int app_window_width = 960; + const int app_window_height = 960; + + glutInitWindowPosition( app_window_x, app_window_y ); + glutInitWindowSize( app_window_width, app_window_height ); + + int app_window_handle = glutCreateWindow( "LLMediaPluginTest" ); + + glutDisplayFunc( glutDisplay ); + + GLUI_Master.set_glutReshapeFunc( glutReshape ); + GLUI_Master.set_glutKeyboardFunc( glutKeyboard ); + GLUI_Master.set_glutMouseFunc( glutMouseButton ); + + glutPassiveMotionFunc( glutMousePassive ); + glutMotionFunc( glutMouseMove ); + + glutSetWindow( app_window_handle ); + + gApplication = new LLMediaPluginTest( app_window_handle, app_window_width, app_window_height ); + + // update at approximately 60hz + int update_ms = 1000 / 60; + + GLUI_Master.set_glutTimerFunc( update_ms, glutIdle, update_ms); + + glutMainLoop(); + + delete gApplication; +} diff --git a/linden/indra/test_apps/llplugintest/llmediaplugintest.h b/linden/indra/test_apps/llplugintest/llmediaplugintest.h new file mode 100644 index 0000000..c2b2bab --- /dev/null +++ b/linden/indra/test_apps/llplugintest/llmediaplugintest.h @@ -0,0 +1,201 @@ +/** + * @file LLMediaPluginTest.cpp + * @brief Primary test application for LLMedia (Separate Process) Plugin system + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_MEDIA_PLUGIN_TEST_H +#define LL_MEDIA_PLUGIN_TEST_H + +#include <vector> +#include <string> +#include "llpluginclassmedia.h" +#include "llgl.h" + +// Forward declarations +class GLUI_Rotation; +class GLUI_Translation; +class GLUI_Listbox; +class GLUI_EditText; +class GLUI_StaticText; +class GLUI; +class GLUI_Button; + +//////////////////////////////////////////////////////////////////////////////// +// +struct mediaPanel +{ + public: + mediaPanel(); + ~mediaPanel(); + int mId; + std::string mStartUrl; + std::string mMimeType; + LLPluginClassMedia *mMediaSource; + int mMediaWidth; + int mMediaHeight; + int mTextureWidth; + int mTextureHeight; + double mTextureScaleX; + double mTextureScaleY; + GLuint mMediaTextureHandle; + GLuint mPickTextureHandle; + unsigned char* mPickTexturePixels; + bool mAppTextureCoordsOpenGL; + bool mReadyToRender; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +class LLMediaPluginTest : public LLPluginClassMediaOwner +{ + public: + LLMediaPluginTest( int app_window, int window_width, int window_height ); + ~LLMediaPluginTest(); + + void reshape( int width, int height ); + void display(); + void idle(); + void gluiCallback( int control_id ); + void keyboard( int key ); + void mousePassive( int x, int y ); + void mouseButton( int button, int state, int x, int y ); + void mouseMove( int x, int y ); + + void bindTexture(GLuint texture, GLint row_length = 0, GLint alignment = 1); + bool checkGLError(const char *name = "OpenGL"); + void drawGeometry( int panel ); + void startPanelHighlight( float red, float green, float blue, float line_width ); + void endPanelHighlight(); + enum { DrawTypePickTexture, DrawTypeMediaTexture }; + void draw( int draw_type ); + void windowPosToTexturePos( int window_x, int window_y, int& media_x, int& media_y, int& id ); + + void addMediaPanel( std::string url ); + void updateMediaPanel( mediaPanel* panel ); + void remMediaPanel( mediaPanel* panel ); + void replaceMediaPanel( mediaPanel* panel, std::string url ); + void getRandomMediaSize( int& width, int& height, std::string mime_type ); + void navigateToNewURI( std::string uri ); + void initUrlHistory( std::string uri ); + void selectPanelById( int id ); + void selectPanel( mediaPanel* panel ); + mediaPanel* findMediaPanel( LLPluginClassMedia* panel ); + void makePickTexture( int id, GLuint* texture_handle, unsigned char** texture_pixels ); + void makeChrome(); + void resetView(); + + void dumpPanelInfo(); + void updateStatusBar(); + + // Inherited from LLPluginClassMediaOwner + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent); + + private: + const int mVersionMajor; + const int mVersionMinor; + const int mVersionPatch; + const int mMaxPanels; + int mAppWindow; + int mWindowWidth; + int mWindowHeight; + int mCurMouseX; + int mCurMouseY; + unsigned char mPixelReadColor[ 3 ]; + bool mFuzzyMedia; + const std::string mHomeWebUrl; + + std::vector< mediaPanel* > mMediaPanels; + mediaPanel* mSelectedPanel; + std::string mimeTypeFromUrl( std::string& url ); + std::string pluginNameFromMimeType( std::string& mime_type ); + + GLUI_Rotation* mViewRotationCtrl; + GLUI_Translation* mViewScaleCtrl; + GLUI_Translation* mViewTranslationCtrl; + float mViewportAspect; + float mViewPos[ 3 ]; + float mViewRotation[ 16 ]; + + int mIdControlAddPanel; + int mIdControlRemPanel; + + std::vector< std::pair< std::string, std::string > > mBookmarks; + GLUI_Listbox* mBookmarkList; + int mIdBookmarks; + int mIdUrlEdit; + GLUI_EditText* mUrlEdit; + int mIdUrlInitHistoryEdit; + GLUI_EditText* mUrlInitHistoryEdit; + int mSelBookmark; + int mIdRandomPanelCount; + int mRandomPanelCount; + int mIdRandomBookmarks; + int mRandomBookmarks; + int mIdDisableTimeout; + int mDisableTimeout; + int mIdControlCrashPlugin; + int mIdControlHangPlugin; + int mIdControlExitApp; + + GLUI* mGluiMediaTimeControlWindow; + int mIdMediaTimeControlPlay; + int mIdMediaTimeControlLoop; + int mIdMediaTimeControlPause; + int mIdMediaTimeControlStop; + int mIdMediaTimeControlSeek; + int mIdMediaTimeControlVolume; + int mMediaTimeControlVolume; + int mIdMediaTimeControlSeekSeconds; + int mMediaTimeControlSeekSeconds; + int mIdMediaTimeControlRewind; + int mIdMediaTimeControlFastForward; + + GLUI* mGluiMediaBrowserControlWindow; + int mIdMediaBrowserControlBack; + GLUI_Button* mMediaBrowserControlBackButton; + int mIdMediaBrowserControlStop; + int mIdMediaBrowserControlForward; + GLUI_Button* mMediaBrowserControlForwardButton; + bool mGluiMediaTimeControlWindowFlag; + bool mGluiMediaBrowserControlWindowFlag; + bool mMediaBrowserControlBackButtonFlag; + bool mMediaBrowserControlForwardButtonFlag; + int mIdMediaBrowserControlHome; + int mIdMediaBrowserControlReload; + int mIdMediaBrowserControlClearCache; + int mIdMediaBrowserControlClearCookies; + int mIdMediaBrowserControlEnableCookies; + int mMediaBrowserControlEnableCookies; + + GLUI* mBottomGLUIWindow; + GLUI_StaticText* mStatusText; +}; + +#endif // LL_MEDIA_PLUGIN_TEST_H + diff --git a/linden/indra/test_apps/llplugintest/media_mappings.txt b/linden/indra/test_apps/llplugintest/media_mappings.txt new file mode 100644 index 0000000..74188bc --- /dev/null +++ b/linden/indra/test_apps/llplugintest/media_mappings.txt @@ -0,0 +1,3 @@ +Flash demo_media_plugin_flash.dll +ColNoise demo_media_plugin.dll +CheckBounce demo_media_plugin_2.dll diff --git a/linden/indra/test_apps/llplugintest/media_plugin_test.cpp b/linden/indra/test_apps/llplugintest/media_plugin_test.cpp new file mode 100644 index 0000000..8e42fa7 --- /dev/null +++ b/linden/indra/test_apps/llplugintest/media_plugin_test.cpp @@ -0,0 +1,511 @@ +/** + * @file demo_plugin.cpp + * @brief Test plugin to be loaded by the llplugin testbed. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "indra_constants.h" + +#include "lltimer.h" // for ms_sleep() +#include "llpumpio.h" +#include "llapr.h" +#include "llerrorcontrol.h" +#include "llpluginclassmedia.h" + +#include <string> +#include <iostream> +#include <stdlib.h> +#include <time.h> + +#include "llmediaplugintest.h" // for GLUT headers + + +//////////////////////////////////////////////////////////////////////////////// +// +class mediaPluginTest : public LLPluginClassMediaOwner +{ + private: + int mAppWindowWidth; + int mAppWindowHeight; + LLPluginClassMedia* mMediaSource; + int mAppTextureWidth; + int mAppTextureHeight; + bool mAppTextureCoordsOpenGL; + GLuint mAppTexture; + std::string mAppWindowName; + std::string mHomeUrl; + std::string mLauncherFilename; + std::string mPluginFilename; + + LLPluginClassMedia *mPlugin; + + public: + mediaPluginTest(const std::string &launcher_filename, const std::string &plugin_filename) : + mAppWindowWidth( 800 ), + mAppWindowHeight( 600 ), + mAppTextureWidth( 0 ), + mAppTextureHeight( 0 ), + mAppTextureCoordsOpenGL(false), + mAppTexture( 0 ), + mAppWindowName( "Media Simple Test" ), + mHomeUrl( "" ) + { + mLauncherFilename = launcher_filename; + mMediaSource = new LLPluginClassMedia(this); + mMediaSource->init(launcher_filename, plugin_filename); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + virtual ~mediaPluginTest() + { + delete mMediaSource; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void createTexture() + { + // create the texture used to display the browser data + if(mMediaSource->textureValid()) + { + mAppTextureWidth = mMediaSource->getTextureWidth(); + mAppTextureHeight = mMediaSource->getTextureHeight(); + mAppTextureCoordsOpenGL = mMediaSource->getTextureCoordsOpenGL(); + + if(mAppTexture != 0) + { + glDeleteTextures( 1, &mAppTexture ); + mAppTexture = 0; + } + + glGenTextures( 1, &mAppTexture ); + glBindTexture( GL_TEXTURE_2D, mAppTexture ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexImage2D( GL_TEXTURE_2D, 0, + mMediaSource->getTextureFormatInternal(), + mAppTextureWidth, + mAppTextureHeight, + 0, + mMediaSource->getTextureFormatPrimary(), + mMediaSource->getTextureFormatType(), + NULL ); + } + } + + //////////////////////////////////////////////////////////////////////////////// + // + void initGL() + { + // OpenGL initialization + glClearColor( 0.0f, 0.0f, 0.0f, 0.5f); + glEnable( GL_COLOR_MATERIAL ); + glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE ); + glEnable( GL_TEXTURE_2D ); + glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); + glEnable( GL_CULL_FACE ); + } + + //////////////////////////////////////////////////////////////////////////////// + // + void reshape( int width, int height ) + { + if ( height == 0 ) + height = 1; + + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + + glViewport( 0, 0, width, height ); + glOrtho( 0.0f, width, height, 0.0f, -1.0f, 1.0f ); + + // we use these values elsewhere so save + mAppWindowWidth = width; + mAppWindowHeight = height; + + // Request a media size change + mMediaSource->setSize(width, height); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + + glutPostRedisplay(); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void idle() + { + // lots of updates for smooth motion + glutPostRedisplay(); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void display() + { + mMediaSource->idle(); + + // Check whether the texture needs to be recreated. + if(mMediaSource->textureValid()) + { + if( + (mAppTextureWidth != mMediaSource->getTextureWidth() || mAppTextureHeight != mMediaSource->getTextureHeight()) && + (mAppWindowWidth == mMediaSource->getWidth() && mAppWindowHeight == mMediaSource->getHeight()) + ) + { + // Attempt to (re)create the texture + createTexture(); + } + } + + // clear screen + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + glLoadIdentity(); + + if(mAppTexture != 0) + { + // use the browser texture + glBindTexture( GL_TEXTURE_2D, mAppTexture ); + + // If dirty, update the texture. + LLRect dirtyRect; + if(!mMediaSource->textureValid()) + { +// LL_DEBUGS("media_plugin_test") << "Resize in progress, skipping update..." << LL_ENDL; + } + else if(mAppWindowWidth != mMediaSource->getWidth() || mAppWindowHeight != mMediaSource->getHeight()) + { + // A resize is in progress. Just wait for it... + } + else if(mMediaSource->getDirty(&dirtyRect)) + { + // grab the page + const unsigned char* pixels = mMediaSource->getBitsData(); + if ( pixels ) + { + // write them into the texture + + // Paranoia: intersect dirtyRect with (0, 0, mAppTextureWidth, mAppTextureHeight)? + + int x_offset = dirtyRect.mLeft; + int y_offset = dirtyRect.mBottom; + int width = dirtyRect.mRight - dirtyRect.mLeft; + int height = dirtyRect.mTop - dirtyRect.mBottom; + + LL_DEBUGS("media_plugin_test") << "Updating, dirty rect is (" + << dirtyRect.mLeft << ", " + << dirtyRect.mTop << ", " + << dirtyRect.mRight << ", " + << dirtyRect.mBottom << "), update params are: (" + << x_offset << ", " + << y_offset << ", " + << width << ", " + << height << ")" + << LL_ENDL; + + // Offset the pixels pointer properly + pixels += (y_offset * mMediaSource->getTextureDepth() * mMediaSource->getTextureWidth()); + pixels += (x_offset * mMediaSource->getTextureDepth()); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, mMediaSource->getTextureWidth()); + + glTexSubImage2D( GL_TEXTURE_2D, 0, + x_offset, + y_offset, + width, + height, + mMediaSource->getTextureFormatPrimary(), + mMediaSource->getTextureFormatType(), + pixels ); + + mMediaSource->resetDirty(); + } + } + + // scale the texture so that it fits the screen + GLdouble media_texture_x = mAppWindowWidth / (double)mAppTextureWidth; + GLdouble media_texture_y = mAppWindowHeight / (double)mAppTextureHeight; + + // draw the single quad full screen (orthographic) + + glEnable( GL_TEXTURE_2D ); + glColor3f( 1.0f, 1.0f, 1.0f ); + glBegin( GL_QUADS ); + if(mAppTextureCoordsOpenGL) + { + // Render the texture as per opengl coords (where 0,0 is at the lower left) + glTexCoord2d( 0, 0 ); + glVertex2d( 0, 0 ); + + glTexCoord2d( 0 , media_texture_y ); + glVertex2d( 0, mAppWindowHeight); + + glTexCoord2d( media_texture_x, media_texture_y ); + glVertex2d( mAppWindowWidth , mAppWindowHeight); + + glTexCoord2d( media_texture_x, 0 ); + glVertex2d( mAppWindowWidth, 0 ); + } + else + { + // Render the texture the "other way round" (where 0,0 is at the upper left) + glTexCoord2d( 0, media_texture_y ); + glVertex2d( 0, 0 ); + + glTexCoord2d( 0 , 0 ); + glVertex2d( 0, mAppWindowHeight); + + glTexCoord2d( media_texture_x, 0 ); + glVertex2d( mAppWindowWidth , mAppWindowHeight); + + glTexCoord2d( media_texture_x, media_texture_y ); + glVertex2d( mAppWindowWidth, 0 ); + } + glEnd(); + + } + + glutSwapBuffers(); + }; + + + //////////////////////////////////////////////////////////////////////////////// + // + MASK getModifiers(void) + { + MASK result = 0; + + int modifiers = glutGetModifiers(); + + if(modifiers & GLUT_ACTIVE_SHIFT) + result |= MASK_SHIFT; + if(modifiers & GLUT_ACTIVE_CTRL) + result |= MASK_CONTROL; + if(modifiers & GLUT_ACTIVE_ALT) + result |= MASK_ALT; + + return result; + } + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseButton( int button, int state, int x, int y ) + { + // Texture has been scaled so it's 1:1 with screen pixels, so no need to scale mouse coords here. +// x = ( x * mAppTextureWidth ) / mAppWindowWidth; +// y = ( y * mAppTextureHeight ) / mAppWindowHeight; + + if ( button == GLUT_LEFT_BUTTON ) + { + if ( state == GLUT_DOWN ) + mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, x, y, getModifiers()); + else if ( state == GLUT_UP ) + mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, x, y, getModifiers()); + } + + // force a GLUT update + glutPostRedisplay(); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseMove( int x , int y ) + { + // Texture has been scaled so it's 1:1 with screen pixels, so no need to scale mouse coords here. +// x = ( x * mAppTextureWidth ) / mAppWindowWidth; +// y = ( y * mAppTextureHeight ) / mAppWindowHeight; + + // GLUT complains if I get the keyboard modifiers here, so just pretend there aren't any. + mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, x, y, 0); + + // force a GLUT update + glutPostRedisplay(); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void keyboard( unsigned char key ) + { + mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_DOWN, key, getModifiers()); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + int getAppWindowWidth() + { + return mAppWindowWidth; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + int getAppWindowHeight() + { + return mAppWindowHeight; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + std::string getAppWindowName() + { + return mAppWindowName; + }; + +}; + +mediaPluginTest* gApplication; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutReshape( int width, int height ) +{ + if ( gApplication ) + gApplication->reshape( width, height ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutDisplay() +{ + if ( gApplication ) + gApplication->display(); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutIdle() +{ + if ( gApplication ) + gApplication->idle(); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutKeyboard( unsigned char key, int x, int y ) +{ + if ( key == 27 ) + { + delete gApplication; + exit( 0 ); + }; + + if ( gApplication ) + gApplication->keyboard( key ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutMouseMove( int x, int y ) +{ + if ( gApplication ) + gApplication->mouseMove( x, y ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void glutMouseButton( int button, int state, int x, int y ) +{ + if ( gApplication ) + gApplication->mouseButton( button, state, x, y ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +int main( int argc, char* argv[] ) +{ + + ll_init_apr(); + + // Set up llerror logging + { + LLError::initForApplication("."); + LLError::setDefaultLevel(LLError::LEVEL_INFO); + } + + std::string launcher_name; + std::string plugin_name; + + if(argc >= 3) + { + launcher_name = argv[1]; + plugin_name = argv[2]; + } + else + { +#if LL_DARWIN + // hardcoding the testbed arguments by default + launcher_name = "plugin_process_host"; + plugin_name = "libdemo_media_plugin_quicktime.dylib"; +#elif LL_WINDOWS + // hardcoding the testbed arguments by default + launcher_name = "plugin_process_host.exe"; + plugin_name = "demo_media_plugin_quicktime.dll"; +#else + LL_ERRS("plugin_process_launcher") << "usage: " << argv[0] << " launcher_filename plugin_filename" << LL_ENDL; +#endif + } + + gApplication = new mediaPluginTest(launcher_name, plugin_name); + + if ( gApplication ) + { + glutInit( &argc, argv ); + glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB ); + + glutInitWindowPosition( 80, 0 ); + glutInitWindowSize( gApplication->getAppWindowWidth(), gApplication->getAppWindowHeight() ); + + glutCreateWindow( gApplication->getAppWindowName().c_str() ); + + glutKeyboardFunc( glutKeyboard ); + + glutMouseFunc( glutMouseButton ); + glutPassiveMotionFunc( glutMouseMove ); + glutMotionFunc( glutMouseMove ); + + glutDisplayFunc( glutDisplay ); + glutReshapeFunc( glutReshape ); + + glutIdleFunc( glutIdle ); + + gApplication->initGL(); + + glutMainLoop(); + + delete gApplication; + }; + + ll_cleanup_apr(); + + return 0; +} + diff --git a/linden/indra/test_apps/llplugintest/media_simple_test.cpp b/linden/indra/test_apps/llplugintest/media_simple_test.cpp new file mode 100644 index 0000000..9a60e8e --- /dev/null +++ b/linden/indra/test_apps/llplugintest/media_simple_test.cpp @@ -0,0 +1,460 @@ +/** + * @file demo_plugin.cpp + * @brief Test plugin to be loaded by the llplugin testbed. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include <string> +#include <iostream> +#include <stdlib.h> +#include <time.h> + +#if LL_DARWIN + #include <GLUT/glut.h> +#elif LL_LINUX + #include <GL/glut.h> +#else + #include "glut.h" +#endif + +//////////////////////////////////////////////////////////////////////////////// +// +class mediaSource +{ + public: + //////////////////////////////////////////////////////////////////////////////// + // + mediaSource() : + mPixels( 0 ), + mIsDirty( false ), + mWidth( 200 ), + mHeight( 100 ), + mDepth( 3 ), + mPixelFormat( GL_BGR_EXT ) + { + mPixels = new unsigned char [ mWidth * mHeight * mDepth ]; + + for( int i = 0; i < mWidth * mHeight * mDepth; ++i ) + *( mPixels + i ) = rand() % 0x40; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void update() + { + const time_t interval = 1; + static time_t last_time = time( NULL ); + time_t cur_time = time( NULL ); + + if ( cur_time - last_time > interval ) + { + for( int i = 0; i < mWidth * mHeight * mDepth; ++i ) + *( mPixels + i ) = rand() % 0x40; + + mIsDirty = true; + + last_time = cur_time; + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ) + { + // make sure we don't write outside the buffer + if((x < 0) || (x >= mWidth) || (y < 0) || (y >= mHeight)) + return; + + *( mPixels + ( mHeight - y ) * mWidth * mDepth + x * mDepth + 0 ) = b; + *( mPixels + ( mHeight - y ) * mWidth * mDepth + x * mDepth + 1 ) = g; + *( mPixels + ( mHeight - y ) * mWidth * mDepth + x * mDepth + 2 ) = r; + + mIsDirty = true; + } + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseDown( int x, int y ) + { + write_pixel( x, y, 0xff, 0x00, 0x00 ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseUp( int x, int y ) + { + write_pixel( x, y, 0xff, 0xff, 0x00 ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseMove( int x, int y ) + { + write_pixel( x, y, 0xff, 0x00, 0xff ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void keyPress( unsigned char key ) + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + int getWidth() { return mWidth; }; + int getHeight() { return mHeight; }; + int getDepth() { return mDepth; }; + int getPixelFormat() { return mPixelFormat; }; + bool isDirty() { return mIsDirty; }; + void ackDirty() { mIsDirty = false; }; + unsigned char* getPixels() { return mPixels; }; + + private: + unsigned char* mPixels; + bool mIsDirty; + int mWidth; + int mHeight; + int mDepth; + int mPixelFormat; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +class mediaSimpleTest +{ + public: + mediaSimpleTest() : + mAppWindowWidth( 800 ), + mAppWindowHeight( 600 ), + mAppTextureWidth( 0 ), + mAppTextureHeight( 0 ), + mAppTexture( 0 ), + mAppWindowName( "Media Simple Test" ), + mHomeUrl( "" ) + { + mMediaSource = new mediaSource; + + // calculate texture size required (next power of two above browser window size + for ( mAppTextureWidth = 1; mAppTextureWidth < mMediaSource->getWidth(); mAppTextureWidth <<= 1 ) {}; + for ( mAppTextureHeight = 1; mAppTextureHeight < mMediaSource->getHeight(); mAppTextureHeight <<= 1 ) {}; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + ~mediaSimpleTest() + { + delete mMediaSource; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void initGL() + { + // OpenGL initialization + glClearColor( 0.0f, 0.0f, 0.0f, 0.5f); + glEnable( GL_COLOR_MATERIAL ); + glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE ); + glEnable( GL_TEXTURE_2D ); + glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); + glEnable( GL_CULL_FACE ); + + // create the texture used to display the browser data + glGenTextures( 1, &mAppTexture ); + glBindTexture( GL_TEXTURE_2D, mAppTexture ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexImage2D( GL_TEXTURE_2D, 0, + GL_RGB, + mAppTextureWidth, mAppTextureHeight, + 0, GL_RGB, GL_UNSIGNED_BYTE, 0 ); + } + + //////////////////////////////////////////////////////////////////////////////// + // + void reshape( int width, int height ) + { + if ( height == 0 ) + height = 1; + + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + + glViewport( 0, 0, width, height ); + glOrtho( 0.0f, width, height, 0.0f, -1.0f, 1.0f ); + + // we use these values elsewhere so save + mAppWindowWidth = width; + mAppWindowHeight = height; + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + + glutPostRedisplay(); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void idle() + { + // lots of updates for smooth motion + glutPostRedisplay(); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void display() + { + // clear screen + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + glLoadIdentity(); + + // use the browser texture + glBindTexture( GL_TEXTURE_2D, mAppTexture ); + + // needs to be updated? + mMediaSource->update(); + if ( mMediaSource->isDirty() ) + { + // grab the page + const unsigned char* pixels = mMediaSource->getPixels(); + if ( pixels ) + { + // write them into the texture + glTexSubImage2D( GL_TEXTURE_2D, 0, + 0, 0, + mMediaSource->getWidth(), + mMediaSource->getHeight(), + mMediaSource->getPixelFormat(), + GL_UNSIGNED_BYTE, + pixels ); + + // acknowledge we saw media was dirty and updated + mMediaSource->ackDirty(); + }; + }; + + // scale the texture so that it fits the screen + GLfloat texture_scale_x = ( GLfloat )mMediaSource->getWidth() / ( GLfloat )mAppTextureWidth; + GLfloat texture_scale_y = ( GLfloat )mMediaSource->getHeight() / ( GLfloat )mAppTextureHeight; + + // draw the single quad full screen (orthographic) + glMatrixMode( GL_TEXTURE ); + glPushMatrix(); + glScalef( texture_scale_x, texture_scale_y, 1.0f ); + + glEnable( GL_TEXTURE_2D ); + glColor3f( 1.0f, 1.0f, 1.0f ); + glBegin( GL_QUADS ); + glTexCoord2f( 1.0f, 1.0f ); + glVertex2d( mAppWindowWidth, 0 ); + + glTexCoord2f( 0.0f, 1.0f ); + glVertex2d( 0, 0 ); + + glTexCoord2f( 0.0f, 0.0f ); + glVertex2d( 0, mAppWindowHeight ); + + glTexCoord2f( 1.0f, .0f ); + glVertex2d( mAppWindowWidth, mAppWindowHeight ); + glEnd(); + + glMatrixMode( GL_TEXTURE ); + glPopMatrix(); + + glutSwapBuffers(); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseButton( int button, int state, int x, int y ) + { + // texture is scaled to fit the screen so we scale mouse coords in the same way + x = ( x * mMediaSource->getWidth() ) / mAppWindowWidth; + y = ( y * mMediaSource->getHeight() ) / mAppWindowHeight; + + if ( button == GLUT_LEFT_BUTTON ) + { + if ( state == GLUT_DOWN ) + mMediaSource->mouseDown( x, y ); + else + if ( state == GLUT_UP ) + mMediaSource->mouseUp( x, y ); + }; + + // force a GLUT update + glutPostRedisplay(); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void mouseMove( int x , int y ) + { + // texture is scaled to fit the screen so we scale mouse coords in the same way + x = ( x * mMediaSource->getWidth() ) / mAppWindowWidth; + y = ( y * mMediaSource->getHeight() ) / mAppWindowHeight; + + mMediaSource->mouseMove( x, y ); + + // force a GLUT update + glutPostRedisplay(); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void keyboard( unsigned char key ) + { + mMediaSource->keyPress( key ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + int getAppWindowWidth() + { + return mAppWindowWidth; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + int getAppWindowHeight() + { + return mAppWindowHeight; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + std::string getAppWindowName() + { + return mAppWindowName; + }; + + private: + int mAppWindowWidth; + int mAppWindowHeight; + mediaSource* mMediaSource; + int mAppTextureWidth; + int mAppTextureHeight; + GLuint mAppTexture; + std::string mAppWindowName; + std::string mHomeUrl; +}; + +mediaSimpleTest* gApplication; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutReshape( int width, int height ) +{ + if ( gApplication ) + gApplication->reshape( width, height ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutDisplay() +{ + if ( gApplication ) + gApplication->display(); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutIdle() +{ + if ( gApplication ) + gApplication->idle(); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutKeyboard( unsigned char key, int x, int y ) +{ + if ( key == 27 ) + { + delete gApplication; + exit( 0 ); + }; + + if ( gApplication ) + gApplication->keyboard( key ); +}; + +//////////////////////////////////////////////////////////////////////////////// +// +void glutMouseMove( int x, int y ) +{ + if ( gApplication ) + gApplication->mouseMove( x, y ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void glutMouseButton( int button, int state, int x, int y ) +{ + if ( gApplication ) + gApplication->mouseButton( button, state, x, y ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +int main( int argc, char* argv[] ) +{ + gApplication = new mediaSimpleTest; + + if ( gApplication ) + { + glutInit( &argc, argv ); + glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB ); + + glutInitWindowPosition( 80, 0 ); + glutInitWindowSize( gApplication->getAppWindowWidth(), gApplication->getAppWindowHeight() ); + + glutCreateWindow( gApplication->getAppWindowName().c_str() ); + + glutKeyboardFunc( glutKeyboard ); + + glutMouseFunc( glutMouseButton ); + glutPassiveMotionFunc( glutMouseMove ); + glutMotionFunc( glutMouseMove ); + + glutDisplayFunc( glutDisplay ); + glutReshapeFunc( glutReshape ); + + glutIdleFunc( glutIdle ); + + gApplication->initGL(); + + glutMainLoop(); + + delete gApplication; + }; + + return 0; +} + diff --git a/linden/indra/test_apps/llplugintest/plugin_host.cpp b/linden/indra/test_apps/llplugintest/plugin_host.cpp new file mode 100644 index 0000000..5ba5d8b --- /dev/null +++ b/linden/indra/test_apps/llplugintest/plugin_host.cpp @@ -0,0 +1,92 @@ +/** + * @file plugin_host.cpp + * @brief Testbed for llplugin which directly loads a plugin dynamic library. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#include "linden_common.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llerrorcontrol.h" + +class MessageReceiver: public LLPluginInstanceMessageListener +{ + // Inherited from LLPluginInstanceMessageListener + /* virtual */ void receivePluginMessage(const std::string &message) + { + LL_INFOS("plugin_host") << "message received from plugin: " << message << LL_ENDL; + } + +}; + +int main(int argc, char **argv) +{ + ll_init_apr(); + + // Set up llerror logging + { + LLError::initForApplication("."); + LLError::setDefaultLevel(LLError::LEVEL_DEBUG); + } + + if(argc < 2) + { + LL_ERRS("plugin_host") << "usage: " << argv[0] << " plugin_filename" << LL_ENDL; + exit(1); + } + + std::string name = argv[1]; + + MessageReceiver receiver; + LLPluginInstance *plugin = new LLPluginInstance(&receiver); + if(plugin->load(name) == 0) + { + LLPluginMessage message; + message.setMessage("base", "init"); + message.setValue("foo", "1"); + message.setValue("bar", "2"); + plugin->sendMessage(message.generate()); + + message.setMessage("base", "idle"); + message.setValue("baz", "3"); + plugin->sendMessage(message.generate()); + + message.setMessage("base", "shutdown"); + plugin->sendMessage(message.generate()); + + plugin->idle(); + } + + delete plugin; + + ll_cleanup_apr(); +} + diff --git a/linden/indra/test_apps/llplugintest/plugin_process_launcher.cpp b/linden/indra/test_apps/llplugintest/plugin_process_launcher.cpp new file mode 100644 index 0000000..82b11e3 --- /dev/null +++ b/linden/indra/test_apps/llplugintest/plugin_process_launcher.cpp @@ -0,0 +1,197 @@ +/** + * @file plugin_process_launcher.cpp + * @brief Testbed for llplugin which launches the plugin loader shell. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llprocesslauncher.h" +#include "lltimer.h" // for ms_sleep() +#include "llpumpio.h" +#include "llapr.h" +#include "llerrorcontrol.h" +#include "llpluginprocessparent.h" + +class PluginProcessLauncherMessageReceiver : public LLPluginProcessParentOwner +{ +LOG_CLASS(PluginProcessLauncherMessageReceiver); + +public: + virtual ~PluginProcessLauncherMessageReceiver() + { + } + + /* virtual */ void receivePluginMessage(const LLPluginMessage &message) + { + LL_INFOS("plugin_process_launcher") << "received message: \n" << message.generate() << LL_ENDL; + } +}; + +LLPumpIO* gServicePump; +LLPluginProcessParent *gPlugin; + + +#define SHARED_MEMORY_SIZE 0x10000 +#define SHARED_MEMORY_NAME "testsegment" +enum State +{ + STATE_STARTUP, + STATE_ADD_MEMORY, + STATE_RUNNING, + STATE_REMOVE_MEMORY, + STATE_SHUTDOWN, + STATE_CLEANUP, + STATE_DONE +}; + +int main(int argc, char **argv) +{ + ll_init_apr(); + + // Set up llerror logging + { + LLError::initForApplication("."); + LLError::setDefaultLevel(LLError::LEVEL_INFO); + } + + std::string launcher_name; + std::string plugin_name; + + if(argc >= 3) + { + launcher_name = argv[1]; + plugin_name = argv[2]; + } + else + { +#if LL_DARWIN + // hardcoding the testbed arguments by default + launcher_name = "plugin_process_host"; + plugin_name = "libdemo_plugin.dylib"; +#elif LL_WINDOWS + // hardcoding the testbed arguments by default + launcher_name = "plugin_process_host.exe"; + plugin_name = "demo_plugin.dll"; +#else + LL_ERRS("plugin_process_launcher") << "usage: " << argv[0] << " launcher_filename plugin_filename" << LL_ENDL; +#endif + } + + PluginProcessLauncherMessageReceiver receiver; + + gServicePump = new LLPumpIO(gAPRPoolp); + gServicePump->prime(gAPRPoolp); + + gPlugin = new LLPluginProcessParent(gServicePump, &receiver); + + State state = STATE_STARTUP; + while(state != STATE_DONE) + { + switch(state) + { + case STATE_STARTUP: + LL_INFOS("plugin_process_launcher") << "startup" << LL_ENDL; + gPlugin->init(launcher_name, plugin_name); + state = STATE_ADD_MEMORY; + break; + + case STATE_ADD_MEMORY: + if(gPlugin->isRunning()) + { + LL_INFOS("plugin_process_launcher") << "adding shared memory" << LL_ENDL; + gPlugin->addSharedMemory(SHARED_MEMORY_SIZE); + state = STATE_RUNNING; + } + break; + + case STATE_RUNNING: + { + volatile unsigned char *addr = (unsigned char*)gPlugin->getSharedMemoryAddress(SHARED_MEMORY_NAME); + if(addr != NULL) + { + int val = (int)(addr[0]); + if(val >= 16) + { + state = STATE_REMOVE_MEMORY; + } + else + { + LL_INFOS("plugin_process_launcher") << "running, value from shared memory is " << val << LL_ENDL; + } + } + } + break; + + case STATE_REMOVE_MEMORY: + LL_INFOS("plugin_process_launcher") << "removing shared memory" << LL_ENDL; + gPlugin->removeSharedMemory(SHARED_MEMORY_NAME); + state = STATE_SHUTDOWN; + break; + + case STATE_SHUTDOWN: + { + volatile unsigned char *addr = (unsigned char*)gPlugin->getSharedMemoryAddress(SHARED_MEMORY_NAME); + if(addr == NULL) + { + LL_INFOS("plugin_process_launcher") << "sending shutdown request" << LL_ENDL; + gPlugin->shutdownRequest(); + state = STATE_CLEANUP; + } + } + break; + + case STATE_CLEANUP: + if(gPlugin->isDone()) + { + LL_INFOS("plugin_process_launcher") << "plugin is done" << LL_ENDL; + state = STATE_DONE; + } + break; + + case STATE_DONE: + // should never reach here -- the while() should exit first. + break; + } + + // Do this every time through the loop + if(state != STATE_DONE) + { + gServicePump->pump(); + gServicePump->callback(); + gPlugin->idle(); + ms_sleep(100); + } + } + + delete gPlugin; + + ll_cleanup_apr(); + +} diff --git a/linden/install.xml b/linden/install.xml old mode 100755 new mode 100644 index 6332244..2118090 --- a/linden/install.xml +++ b/linden/install.xml @@ -1112,39 +1112,32 @@ Portions copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura </map> </map> </map> - <key>llmozlib</key> + <key>llqtwebkit</key> <map> <key>license</key> - <string>mozillaPL</string> + <string>lgpl</string> <key>packages</key> <map> <key>darwin</key> <map> <key>md5sum</key> - <string>c951587726618d33646f2b169c290bd3</string> + <string>b40a13847ee773c9ee06f641fe0dd1c2</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llmozlib-2_0_0_21-darwin-20090304.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-darwin-20091023.tar.bz2</uri> </map> <key>linux</key> <map> <key>md5sum</key> - <string>b7ebcf0fb764ed4fa57c62d068b4a769</string> - <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llmozlib-linux-20090304prfhk.tar.bz2</uri> - </map> - <key>linux64</key> - <map> - <key>md5sum</key> - <string>afa946a118d3d71123003785189a31f2</string> + <string>ffede2775355676096b1085cbb9d0da7</string> <key>url</key> - <uri>http://imprudenceviewer.org/download/libs/llmozlib-linux64-20091231.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-20091117.tar.bz2</uri> </map> <key>windows</key> <map> <key>md5sum</key> - <string>e9454e258b99668782d8570481b5eda1</string> + <string>6f2f911545e5906edc87f4f3cda423a1</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llmozlib-windows-20090306.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-20091023.tar.bz2</uri> </map> </map> </map> -- cgit v1.1 From 09b7d25b1d24b5b6d5bb1ce31544d8f4abaa3bb7 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Tue, 7 Sep 2010 10:08:26 +0200 Subject: lost in merge: 1 debug setting, some member variables from llpanellandmedia todo: review llpanellandmedia; port flotervoicelicense --- linden/indra/newview/app_settings/settings.xml | 11 +++++++ linden/indra/newview/llpanellandmedia.cpp | 40 +++++++++++++------------- linden/indra/newview/llpanellandmedia.h | 7 +++++ 3 files changed, 38 insertions(+), 20 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml index 4d80845..f70c0fc 100644 --- a/linden/indra/newview/app_settings/settings.xml +++ b/linden/indra/newview/app_settings/settings.xml @@ -4135,6 +4135,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>DebugPluginDisableTimeout</key> + <map> + <key>Comment</key> + <string>Disable the code which watches for plugins that are crashed or hung</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>DebugShowColor</key> <map> <key>Comment</key> diff --git a/linden/indra/newview/llpanellandmedia.cpp b/linden/indra/newview/llpanellandmedia.cpp index a8e7c4a..fc84bb5 100644 --- a/linden/indra/newview/llpanellandmedia.cpp +++ b/linden/indra/newview/llpanellandmedia.cpp @@ -171,8 +171,8 @@ void LLPanelLandMedia::refresh() // Display options BOOL can_change_media = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_CHANGE_MEDIA); -//imprudence fixme mCheckSoundLocal->set( parcel->getSoundLocal() ); -//imprudence fixme mCheckSoundLocal->setEnabled( can_change_media ); + mCheckSoundLocal->set( parcel->getSoundLocal() ); + mCheckSoundLocal->setEnabled( can_change_media ); LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); if (!region) @@ -188,39 +188,39 @@ void LLPanelLandMedia::refresh() { if (region && region->isVoiceEnabled()) // estate-wide voice-disable overrides all { -//imprudence fixme mCheckEnableVoiceChatIsEstateDisabled->setVisible(false); + mCheckEnableVoiceChatIsEstateDisabled->setVisible(false); -//imprudence fixme mCheckEnableVoiceChat->setVisible(true); -//imprudence fixme mCheckEnableVoiceChat->setEnabled( can_change_media ); -//imprudence fixme mCheckEnableVoiceChat->set(allow_voice); + mCheckEnableVoiceChat->setVisible(true); + mCheckEnableVoiceChat->setEnabled( can_change_media ); + mCheckEnableVoiceChat->set(allow_voice); -//imprudence fixme mCheckEnableVoiceChatParcel->setEnabled( can_change_media && allow_voice ); + mCheckEnableVoiceChatParcel->setEnabled( can_change_media && allow_voice ); } else // disabled at region level { -//imprudence fixme mCheckEnableVoiceChatIsEstateDisabled->setVisible(true); // always disabled -//imprudence fixme mCheckEnableVoiceChat->setVisible(false); -//imprudence fixme mCheckEnableVoiceChat->setEnabled(false); -//imprudence fixme mCheckEnableVoiceChat->set(false); + mCheckEnableVoiceChatIsEstateDisabled->setVisible(true); // always disabled + mCheckEnableVoiceChat->setVisible(false); + mCheckEnableVoiceChat->setEnabled(false); + mCheckEnableVoiceChat->set(false); -//imprudence fixme mCheckEnableVoiceChatParcel->setEnabled(false); + mCheckEnableVoiceChatParcel->setEnabled(false); } } else { -//imprudence fixme mCheckEnableVoiceChatIsEstateDisabled->setVisible(true); + mCheckEnableVoiceChatIsEstateDisabled->setVisible(true); -//imprudence fixme mCheckEnableVoiceChat->setVisible(true); -//imprudence fixme mCheckEnableVoiceChat->setEnabled( can_change_media ); -//imprudence fixme mCheckEnableVoiceChat->set(allow_voice); + mCheckEnableVoiceChat->setVisible(true); + mCheckEnableVoiceChat->setEnabled( can_change_media ); + mCheckEnableVoiceChat->set(allow_voice); -//imprudence fixme mCheckEnableVoiceChatParcel->setEnabled( can_change_media && allow_voice ); + mCheckEnableVoiceChatParcel->setEnabled( can_change_media && allow_voice ); } -//imprudence fixme mCheckEnableVoiceChatParcel->set(!parcel->getParcelFlagUseEstateVoiceChannel()); + mCheckEnableVoiceChatParcel->set(!parcel->getParcelFlagUseEstateVoiceChannel()); -//imprudence fixme mMusicURLEdit->setText(parcel->getMusicURL()); -//imprudence fixme mMusicURLEdit->setEnabled( can_change_media ); + mMusicURLEdit->setText(parcel->getMusicURL()); + mMusicURLEdit->setEnabled( can_change_media ); diff --git a/linden/indra/newview/llpanellandmedia.h b/linden/indra/newview/llpanellandmedia.h index c883d98..d63f0f6 100644 --- a/linden/indra/newview/llpanellandmedia.h +++ b/linden/indra/newview/llpanellandmedia.h @@ -61,6 +61,12 @@ private: static void onClickRemoveURLFilter(void *userdata); private: + LLCheckBoxCtrl* mCheckSoundLocal; + LLButton* mSoundHelpButton; + LLCheckBoxCtrl* mCheckEnableVoiceChat; + LLCheckBoxCtrl* mCheckEnableVoiceChatIsEstateDisabled; + LLCheckBoxCtrl* mCheckEnableVoiceChatParcel; + LLLineEditor* mMusicURLEdit; LLLineEditor* mMediaURLEdit; LLLineEditor* mMediaDescEdit; LLComboBox* mMediaTypeCombo; @@ -75,6 +81,7 @@ private: LLCheckBoxCtrl* mMediaAutoScaleCheck; LLCheckBoxCtrl* mMediaLoopCheck; LLCheckBoxCtrl* mMediaUrlCheck; + LLCheckBoxCtrl* mMusicUrlCheck; LLHandle<LLFloater> mURLEntryFloater; LLCheckBoxCtrl* mMediaNavigateAllowCheck; LLCheckBoxCtrl* mMediaURLFilterCheck; -- cgit v1.1 From 9d37fb4eeb15f7ac35ebaa3fd7c5cc11e5b1a1dc Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Tue, 7 Sep 2010 10:26:01 +0200 Subject: First LL update of plugins, mainly documentation --- .../indra/media_plugins/base/media_plugin_base.cpp | 57 ++++++- .../indra/media_plugins/base/media_plugin_base.h | 45 ++++-- .../llmediaimplgstreamertriviallogging.h | 6 + .../gstreamer010/llmediaimplgstreamervidplug.cpp | 35 +++-- .../gstreamer010/llmediaimplgstreamervidplug.h | 2 +- .../gstreamer010/media_plugin_gstreamer010.cpp | 78 ++++++---- .../indra/media_plugins/quicktime/CMakeLists.txt | 8 + .../quicktime/media_plugin_quicktime.cpp | 170 ++++++++++++++++++--- .../media_plugins/webkit/media_plugin_webkit.cpp | 53 +++++-- linden/indra/newview/llviewerparcelmedia.cpp | 7 +- 10 files changed, 358 insertions(+), 103 deletions(-) (limited to 'linden') diff --git a/linden/indra/media_plugins/base/media_plugin_base.cpp b/linden/indra/media_plugins/base/media_plugin_base.cpp index 1919419..4d5e374 100644 --- a/linden/indra/media_plugins/base/media_plugin_base.cpp +++ b/linden/indra/media_plugins/base/media_plugin_base.cpp @@ -2,6 +2,8 @@ * @file media_plugin_base.cpp * @brief Media plugin base class for LLMedia API plugin system * + * All plugins should be a subclass of MediaPluginBase. + * * $LicenseInfo:firstyear=2008&license=viewergpl$ * * Copyright (c) 2008-2009, Linden Research, Inc. @@ -36,7 +38,10 @@ // TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint //////////////////////////////////////////////////////////////////////////////// -// +/// Media plugin constructor. +/// +/// @param[in] host_send_func Function for sending messages from plugin to plugin loader shell +/// @param[in] host_user_data Message data for messages from plugin to plugin loader shell MediaPluginBase::MediaPluginBase( LLPluginInstance::sendMessageFunction host_send_func, @@ -54,6 +59,12 @@ MediaPluginBase::MediaPluginBase( mStatus = STATUS_NONE; } +/** + * Converts current media status enum value into string (STATUS_LOADING into "loading", etc.) + * + * @return Media status string ("loading", "playing", "paused", etc) + * + */ std::string MediaPluginBase::statusString() { std::string result; @@ -65,6 +76,7 @@ std::string MediaPluginBase::statusString() case STATUS_ERROR: result = "error"; break; case STATUS_PLAYING: result = "playing"; break; case STATUS_PAUSED: result = "paused"; break; + case STATUS_DONE: result = "done"; break; default: // keep the empty string break; @@ -73,6 +85,12 @@ std::string MediaPluginBase::statusString() return result; } +/** + * Set media status. + * + * @param[in] status Media status (STATUS_LOADING, STATUS_PLAYING, STATUS_PAUSED, etc) + * + */ void MediaPluginBase::setStatus(EStatus status) { if(mStatus != status) @@ -83,6 +101,13 @@ void MediaPluginBase::setStatus(EStatus status) } +/** + * Receive message from plugin loader shell. + * + * @param[in] message_string Message string + * @param[in] user_data Message data + * + */ void MediaPluginBase::staticReceiveMessage(const char *message_string, void **user_data) { MediaPluginBase *self = (MediaPluginBase*)*user_data; @@ -100,12 +125,27 @@ void MediaPluginBase::staticReceiveMessage(const char *message_string, void **us } } +/** + * Send message to plugin loader shell. + * + * @param[in] message Message data being sent to plugin loader shell + * + */ void MediaPluginBase::sendMessage(const LLPluginMessage &message) { std::string output = message.generate(); mHostSendFunction(output.c_str(), &mHostUserData); } +/** + * Notifies plugin loader shell that part of display area needs to be redrawn. + * + * @param[in] left Left X coordinate of area to redraw (0,0 is at top left corner) + * @param[in] top Top Y coordinate of area to redraw (0,0 is at top left corner) + * @param[in] right Right X-coordinate of area to redraw (0,0 is at top left corner) + * @param[in] bottom Bottom Y-coordinate of area to redraw (0,0 is at top left corner) + * + */ void MediaPluginBase::setDirty(int left, int top, int right, int bottom) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated"); @@ -118,6 +158,10 @@ void MediaPluginBase::setDirty(int left, int top, int right, int bottom) sendMessage(message); } +/** + * Sends "media_status" message to plugin loader shell ("loading", "playing", "paused", etc.) + * + */ void MediaPluginBase::sendStatus() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "media_status"); @@ -141,6 +185,17 @@ extern "C" LLSYMEXPORT int LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data); } +/** + * Plugin initialization and entry point. Establishes communication channel for messages between plugin and plugin loader shell. TODO:DOC - Please check! + * + * @param[in] host_send_func Function for sending messages from plugin to plugin loader shell + * @param[in] host_user_data Message data for messages from plugin to plugin loader shell + * @param[out] plugin_send_func Function for plugin to receive messages from plugin loader shell + * @param[out] plugin_user_data Pointer to plugin instance + * + * @return int, where 0=success + * + */ LLSYMEXPORT int LLPluginInitEntryPoint(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) { diff --git a/linden/indra/media_plugins/base/media_plugin_base.h b/linden/indra/media_plugins/base/media_plugin_base.h index 4872706..24198af 100644 --- a/linden/indra/media_plugins/base/media_plugin_base.h +++ b/linden/indra/media_plugins/base/media_plugin_base.h @@ -41,14 +41,17 @@ class MediaPluginBase { public: MediaPluginBase(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + /** Media plugin destructor. */ virtual ~MediaPluginBase() {} + /** Handle received message from plugin loader shell. */ virtual void receiveMessage(const char *message_string) = 0; static void staticReceiveMessage(const char *message_string, void **user_data); protected: + /** Plugin status. */ typedef enum { STATUS_NONE, @@ -57,12 +60,16 @@ protected: STATUS_ERROR, STATUS_PLAYING, STATUS_PAUSED, + STATUS_DONE } EStatus; + /** Plugin shared memory. */ class SharedSegmentInfo { public: + /** Shared memory address. */ void *mAddress; + /** Shared memory size. */ size_t mSize; }; @@ -71,42 +78,56 @@ protected: std::string statusString(); void setStatus(EStatus status); - // The quicktime plugin overrides this to add current time and duration to the message... + /// Note: The quicktime plugin overrides this to add current time and duration to the message. virtual void setDirty(int left, int top, int right, int bottom); + /** Map of shared memory names to shared memory. */ typedef std::map<std::string, SharedSegmentInfo> SharedSegmentMap; + /** Function to send message from plugin to plugin loader shell. */ LLPluginInstance::sendMessageFunction mHostSendFunction; + /** Message data being sent to plugin loader shell by mHostSendFunction. */ void *mHostUserData; + /** Flag to delete plugin instance (self). */ bool mDeleteMe; + /** Pixel array to display. TODO:DOC are pixels always 24-bit RGB format, aligned on 32-bit boundary? Also: calling this a pixel array may be misleading since 1 pixel > 1 char. */ unsigned char* mPixels; + /** TODO:DOC what's this for -- does a texture have its own piece of shared memory? updated on size_change_request, cleared on shm_remove */ std::string mTextureSegmentName; + /** Width of plugin display in pixels. */ int mWidth; + /** Height of plugin display in pixels. */ int mHeight; + /** Width of plugin texture. */ int mTextureWidth; + /** Height of plugin texture. */ int mTextureHeight; + /** Pixel depth (pixel size in bytes). */ int mDepth; + /** Current status of plugin. */ EStatus mStatus; + /** Map of shared memory segments. */ SharedSegmentMap mSharedSegments; }; -// The plugin must define this function to create its instance. +/** The plugin <b>must</b> define this function to create its instance. + * It should look something like this: + * @code + * { + * MediaPluginFoo *self = new MediaPluginFoo(host_send_func, host_user_data); + * *plugin_send_func = MediaPluginFoo::staticReceiveMessage; + * *plugin_user_data = (void*)self; + * + * return 0; + * } + * @endcode + */ int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data); -// It should look something like this: -/* -{ - MediaPluginFoo *self = new MediaPluginFoo(host_send_func, host_user_data); - *plugin_send_func = MediaPluginFoo::staticReceiveMessage; - *plugin_user_data = (void*)self; - - return 0; -} -*/ diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h index e31d4a3..04976b9 100644 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h @@ -35,10 +35,16 @@ #include <cstdio> +extern "C" { +#include <sys/types.h> +#include <unistd.h> +} + ///////////////////////////////////////////////////////////////////////// // Debug/Info/Warning macros. #define MSGMODULEFOO "(media plugin)" #define STDERRMSG(...) do{\ + fprintf(stderr, " pid:%d: ", (int)getpid());\ fprintf(stderr, MSGMODULEFOO " %s:%d: ", __FUNCTION__, __LINE__);\ fprintf(stderr, __VA_ARGS__);\ fputc('\n',stderr);\ diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp index 25e96d4..ef8ff58 100644 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp @@ -52,7 +52,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug); #define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ( - (gchar*)"sink", + "sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS (SLV_ALLCAPS) @@ -106,11 +106,10 @@ gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf) slvideo = GST_SLVIDEO(bsink); -#if 0 - fprintf(stderr, "\n\ntransferring a frame of %dx%d <- %p (%d)\n\n", - slvideo->width, slvideo->height, GST_BUFFER_DATA(buf), - slvideo->format); -#endif + DEBUGMSG("transferring a frame of %dx%d <- %p (%d)", + slvideo->width, slvideo->height, GST_BUFFER_DATA(buf), + slvideo->format); + if (GST_BUFFER_DATA(buf)) { // copy frame and frame info into neutral territory @@ -335,7 +334,7 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, #define MAXDEPTHHACK 4 GST_OBJECT_LOCK(slvideo); - if (slvideo->resize_forced) + if (slvideo->resize_forced_always) // app is giving us a fixed size to work with { gint slwantwidth, slwantheight; slwantwidth = slvideo->resize_try_width; @@ -384,6 +383,8 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, } } + GST_OBJECT_UNLOCK(slvideo); + if (!made_bufferdata_ptr) // need to fallback to malloc at original size { GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK; @@ -392,8 +393,6 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps); } - GST_OBJECT_UNLOCK(slvideo); - *buf = GST_BUFFER_CAST(newbuf); return GST_FLOW_OK; @@ -457,7 +456,7 @@ gst_slvideo_init (GstSLVideo * filter, filter->retained_frame_format = SLV_PF_UNKNOWN; GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS); llgst_caps_replace (&filter->caps, caps); - filter->resize_forced = false; + filter->resize_forced_always = false; filter->resize_try_width = -1; filter->resize_try_height = -1; GST_OBJECT_UNLOCK(filter); @@ -498,12 +497,12 @@ gst_slvideo_get_property (GObject * object, guint prop_id, static gboolean plugin_init (GstPlugin * plugin) { - DEBUGMSG("\n\n\nPLUGIN INIT\n\n\n"); + DEBUGMSG("PLUGIN INIT"); GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin", 0, (gchar*)"Second Life Video Sink"); - return llgst_element_register (plugin, (gchar*)"private-slvideo", + return llgst_element_register (plugin, "private-slvideo", GST_RANK_NONE, GST_TYPE_SLVIDEO); } @@ -519,14 +518,14 @@ void gst_slvideo_init_class (void) // this macro quietly refers to PACKAGE internally static GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, - (gchar*)"private-slvideoplugin", - (gchar*)"SL Video sink plugin", - plugin_init, (gchar*)"0.1", (gchar*)GST_LICENSE_UNKNOWN, - (gchar*)"Second Life", - (gchar*)"http://www.secondlife.com/"); + "private-slvideoplugin", + "SL Video sink plugin", + plugin_init, "0.1", GST_LICENSE_UNKNOWN, + "Second Life", + "http://www.secondlife.com/"); #undef PACKAGE ll_gst_plugin_register_static (&gst_plugin_desc); - DEBUGMSG(stderr, "\n\n\nCLASS INIT\n\n\n"); + DEBUGMSG("CLASS INIT"); } #endif // LL_GSTREAMER010_ENABLED diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h index f6d55b8..8cdc72d 100644 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h @@ -88,7 +88,7 @@ struct _GstSLVideo int retained_frame_width, retained_frame_height; SLVPixelFormat retained_frame_format; // sticky resize info - bool resize_forced; + bool resize_forced_always; int resize_try_width; int resize_try_height; }; diff --git a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp index 77b7c13..5b3152d 100644 --- a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp +++ b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp @@ -104,7 +104,7 @@ private: void mouseUp( int x, int y ); void mouseMove( int x, int y ); - bool sizeChanged(); + void sizeChanged(); static bool mDoneInit; @@ -114,13 +114,16 @@ private: int mDepth; - // media natural size + // media NATURAL size int mNaturalWidth; int mNaturalHeight; - int mNaturalRowbytes; - // previous media natural size so we can detect changes - int mPreviousNaturalWidth; - int mPreviousNaturalHeight; + // media current size + int mCurrentWidth; + int mCurrentHeight; + int mCurrentRowbytes; + // previous media size so we can detect changes + int mPreviousWidth; + int mPreviousHeight; // desired render size from host int mWidth; int mHeight; @@ -148,7 +151,7 @@ MediaPluginGStreamer010::MediaPluginGStreamer010( void *host_user_data ) : MediaPluginBase(host_send_func, host_user_data), mBusWatchID ( 0 ), - mNaturalRowbytes ( 4 ), + mCurrentRowbytes ( 4 ), mTextureFormatPrimary ( GL_RGBA ), mTextureFormatType ( GL_UNSIGNED_INT_8_8_8_8_REV ), mSeekWanted(false), @@ -194,6 +197,7 @@ MediaPluginGStreamer010::processGSTEvents(GstBus *bus, } else { + // TODO: grok 'duration' message type DEBUGMSG("Got GST message type: %s", LLGST_MESSAGE_TYPE_NAME (message)); } @@ -428,8 +432,8 @@ MediaPluginGStreamer010::update(int milliseconds) { DEBUGMSG("NEW FRAME READY"); - if (mVideoSink->retained_frame_width != mNaturalWidth || - mVideoSink->retained_frame_height != mNaturalHeight) + if (mVideoSink->retained_frame_width != mCurrentWidth || + mVideoSink->retained_frame_height != mCurrentHeight) // *TODO: also check for change in format { // just resize container, don't consume frame @@ -456,39 +460,38 @@ MediaPluginGStreamer010::update(int milliseconds) GST_OBJECT_UNLOCK(mVideoSink); - mNaturalRowbytes = neww * newd; + mCurrentRowbytes = neww * newd; DEBUGMSG("video container resized to %dx%d", neww, newh); mDepth = newd; - mNaturalWidth = neww; - mNaturalHeight = newh; + mCurrentWidth = neww; + mCurrentHeight = newh; sizeChanged(); return true; } if (mPixels && - mNaturalHeight <= mHeight && - mNaturalWidth <= mWidth && + mCurrentHeight <= mHeight && + mCurrentWidth <= mWidth && !mTextureSegmentName.empty()) { - // we're gonna totally consume this frame - reset 'ready' flag - mVideoSink->retained_frame_ready = FALSE; + mVideoSink->retained_frame_ready = FALSE; int destination_rowbytes = mWidth * mDepth; - for (int row=0; row<mNaturalHeight; ++row) + for (int row=0; row<mCurrentHeight; ++row) { memcpy(&mPixels [destination_rowbytes * row], &mVideoSink->retained_frame_data - [mNaturalRowbytes * row], - mNaturalRowbytes); + [mCurrentRowbytes * row], + mCurrentRowbytes); } GST_OBJECT_UNLOCK(mVideoSink); DEBUGMSG("NEW FRAME REALLY TRULY CONSUMED, TELLING HOST"); - setDirty(0,0,mNaturalWidth,mNaturalHeight); + setDirty(0,0,mCurrentWidth,mCurrentHeight); } else { @@ -835,27 +838,35 @@ MediaPluginGStreamer010::startup() } -bool +void MediaPluginGStreamer010::sizeChanged() { // the shared writing space has possibly changed size/location/whatever - // Check to see whether the movie's natural size has updated - if (mNaturalWidth != mPreviousNaturalWidth || - mNaturalHeight != mPreviousNaturalHeight) + // Check to see whether the movie's NATURAL size has been set yet + if (1 == mNaturalWidth && + 1 == mNaturalHeight) { - mPreviousNaturalWidth = mNaturalWidth; - mPreviousNaturalHeight = mNaturalHeight; + mNaturalWidth = mCurrentWidth; + mNaturalHeight = mCurrentHeight; + DEBUGMSG("Media NATURAL size better detected as %dx%d", + mNaturalWidth, mNaturalHeight); + } + + // if the size has changed then the shm has changed and the app needs telling + if (mCurrentWidth != mPreviousWidth || + mCurrentHeight != mPreviousHeight) + { + mPreviousWidth = mCurrentWidth; + mPreviousHeight = mCurrentHeight; LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); message.setValue("name", mTextureSegmentName); message.setValueS32("width", mNaturalWidth); message.setValueS32("height", mNaturalHeight); - DEBUGMSG("<--- Sending size change request to application with name: '%s' - size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight); + DEBUGMSG("<--- Sending size change request to application with name: '%s' - natural size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight); sendMessage(message); } - - return true; } @@ -940,10 +951,12 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string) // lame to have to decide this now, it depends on the movie. Oh well. mDepth = 4; + mCurrentWidth = 1; + mCurrentHeight = 1; + mPreviousWidth = 1; + mPreviousHeight = 1; mNaturalWidth = 1; mNaturalHeight = 1; - mPreviousNaturalWidth = 1; - mPreviousNaturalHeight = 1; mWidth = 1; mHeight = 1; mTextureWidth = 1; @@ -984,7 +997,6 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string) INFOMSG("MediaPluginGStreamer010::receiveMessage: shared memory added, name: %s, size: %d, address: %p", name.c_str(), int(info.mSize), info.mAddress); mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - } else if(message_name == "shm_remove") { @@ -1063,7 +1075,7 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string) INFOMSG("**** = REAL RESIZE REQUEST FROM APP"); GST_OBJECT_LOCK(mVideoSink); - mVideoSink->resize_forced = true; + mVideoSink->resize_forced_always = true; mVideoSink->resize_try_width = texture_width; mVideoSink->resize_try_height = texture_height; GST_OBJECT_UNLOCK(mVideoSink); diff --git a/linden/indra/media_plugins/quicktime/CMakeLists.txt b/linden/indra/media_plugins/quicktime/CMakeLists.txt index db11c9a..f0b8f0d 100644 --- a/linden/indra/media_plugins/quicktime/CMakeLists.txt +++ b/linden/indra/media_plugins/quicktime/CMakeLists.txt @@ -56,6 +56,14 @@ add_dependencies(media_plugin_quicktime ${LLCOMMON_LIBRARIES} ) +if (WINDOWS) + set_target_properties( + media_plugin_quicktime + PROPERTIES + LINK_FLAGS "/MANIFEST:NO" + ) +endif (WINDOWS) + if (QUICKTIME) add_definitions(-DLL_QUICKTIME_ENABLED=1) diff --git a/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index 51cc8dd..6c8c41d 100644 --- a/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -49,6 +49,7 @@ #include "Movies.h" #include "QDoffscreen.h" #include "FixMath.h" + #include "QTLoadLibraryUtils.h" #endif // TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint @@ -72,11 +73,14 @@ private: int mCurVolume; bool mMediaSizeChanging; bool mIsLooping; + std::string mMovieTitle; + bool mReceivedTitle; const int mMinWidth; const int mMaxWidth; const int mMinHeight; const int mMaxHeight; F64 mPlayRate; + std::string mNavigateURL; enum ECommand { COMMAND_NONE, @@ -175,6 +179,11 @@ private: setStatus(STATUS_ERROR); return; }; + + mNavigateURL = url; + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); + message.setValue("uri", mNavigateURL); + sendMessage(message); // do pre-roll actions (typically fired for streaming movies but not always) PrePrerollMovie( mMovieHandle, 0, getPlayRate(), moviePrePrerollCompleteCallback, ( void * )this ); @@ -199,6 +208,9 @@ private: bool unload() { + // new movie and have to get title again + mReceivedTitle = false; + if ( mMovieHandle ) { StopMovie( mMovieHandle ); @@ -382,11 +394,18 @@ private: static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref ) { - //MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; + MediaPluginQuickTime* self = ( MediaPluginQuickTime* )ref; // TODO: //LLMediaEvent event( self ); //self->mEventEmitter.update( &LLMediaObserver::onMediaPreroll, event ); + + // Send a "navigate complete" event. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); + message.setValue("uri", self->mNavigateURL); + message.setValueS32("result_code", 200); + message.setValue("result_string", "OK"); + self->sendMessage(message); }; @@ -400,7 +419,7 @@ private: { if ( mCommand == COMMAND_PLAY ) { - if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING ) + if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING || mStatus == STATUS_DONE ) { long state = GetMovieLoadState( mMovieHandle ); @@ -426,7 +445,7 @@ private: else if ( mCommand == COMMAND_STOP ) { - if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED ) + if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED || mStatus == STATUS_DONE ) { if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) { @@ -508,11 +527,17 @@ private: if ( ! mMovieController ) return; - // service QuickTime - // Calling it this way doesn't have good behavior on Windows... -// MoviesTask( mMovieHandle, milliseconds ); - // This was the original, but I think using both MoviesTask and MCIdle is redundant. Trying with only MCIdle. -// MoviesTask( mMovieHandle, 0 ); + // this wasn't required in 1.xx viewer but we have to manually + // work the Windows message pump now + #if defined( LL_WINDOWS ) + MSG msg; + while ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) + { + GetMessage( &msg, NULL, 0, 0 ); + TranslateMessage( &msg ); + DispatchMessage( &msg ); + }; + #endif MCIdle( mMovieController ); @@ -525,11 +550,14 @@ private: // update state machine processState(); - // special code for looping - need to rewind at the end of the movie - if ( mIsLooping ) + // see if title arrived and if so, update member variable with contents + checkTitle(); + + // QT call to see if we are at the end - can't do with controller + if ( IsMovieDone( mMovieHandle ) ) { - // QT call to see if we are at the end - can't do with controller - if ( IsMovieDone( mMovieHandle ) ) + // special code for looping - need to rewind at the end of the movie + if ( mIsLooping ) { // go back to start rewind(); @@ -542,8 +570,16 @@ private: // set the volume MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); }; - }; - }; + } + else + { + if(mStatus == STATUS_PLAYING) + { + setStatus(STATUS_DONE); + } + } + } + }; int getDataWidth() const @@ -586,6 +622,19 @@ private: }; }; + F64 getLoadedDuration() + { + TimeValue duration; + if(GetMaxLoadedTimeInMovie( mMovieHandle, &duration ) != noErr) + { + // If GetMaxLoadedTimeInMovie returns an error, return the full duration of the movie. + duration = GetMovieDuration( mMovieHandle ); + } + TimeValue scale = GetMovieTimeScale( mMovieHandle ); + + return (F64)duration / (F64)scale; + }; + F64 getDuration() { TimeValue duration = GetMovieDuration( mMovieHandle ); @@ -643,6 +692,77 @@ private: { }; + //////////////////////////////////////////////////////////////////////////////// + // Grab movie title into mMovieTitle - should be called repeatedly + // until it returns true since movie title takes a while to become + // available. + const bool getMovieTitle() + { + // grab meta data from movie + QTMetaDataRef media_data_ref; + OSErr result = QTCopyMovieMetaData( mMovieHandle, &media_data_ref ); + if ( noErr != result ) + return false; + + // look up "Display Name" in meta data + OSType meta_data_key = kQTMetaDataCommonKeyDisplayName; + QTMetaDataItem item = kQTMetaDataItemUninitialized; + result = QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard, + 0, kQTMetaDataKeyFormatCommon, + (const UInt8 *)&meta_data_key, + sizeof( meta_data_key ), &item ); + if ( noErr != result ) + return false; + + // find the size of the title + ByteCount size; + result = 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 ); + if ( noErr != result ) + { + delete [] item_data; + return false; + }; + + // save it + if ( strlen( (char*)item_data ) ) + mMovieTitle = std::string( (char* )item_data ); + else + mMovieTitle = ""; + + // clean up + delete [] item_data; + + return true; + }; + + // called regularly to see if title changed + void checkTitle() + { + // we did already receive title so keep checking + if ( ! mReceivedTitle ) + { + // grab title from movie meta data + if ( getMovieTitle() ) + { + // pass back to host application + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", mMovieTitle ); + sendMessage( message ); + + // stop looking once we find a title for this movie. + // TODO: this may to be reset if movie title changes + // during playback but this is okay for now + mReceivedTitle = true; + }; + }; + }; }; MediaPluginQuickTime::MediaPluginQuickTime( @@ -664,6 +784,8 @@ MediaPluginQuickTime::MediaPluginQuickTime( mCurVolume = 0x99; mMediaSizeChanging = false; mIsLooping = false; + mMovieTitle = std::string(); + mReceivedTitle = false; mCommand = COMMAND_NONE; mPlayRate = 0.0f; mStatus = STATUS_NONE; @@ -700,22 +822,29 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; // Normally a plugin would only specify one of these two subclasses, but this is a demo... -// versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; message.setValueLLSD("versions", versions); #ifdef LL_WINDOWS - if ( InitializeQTML( 0L ) != noErr ) + + // QuickTime 7.6.4 has an issue (that was not present in 7.6.2) with initializing QuickTime + // according to this article: http://lists.apple.com/archives/QuickTime-API/2009/Sep/msg00097.html + // The solution presented there appears to work. + QTLoadLibrary("qtcf.dll"); + + // main initialization for QuickTime - only required on Windows + OSErr result = InitializeQTML( 0L ); + if ( result != noErr ) { //TODO: If no QT on Windows, this fails - respond accordingly. - //return false; } else { -// std::cerr << "QuickTime initialized" << std::endl; + //std::cerr << "QuickTime initialized" << std::endl; }; #endif + // required for both Windows and Mac EnterMovies(); std::string plugin_version = "QuickTime media plugin, QuickTime version "; @@ -773,10 +902,7 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) else if(message_name == "shm_added") { SharedSegmentInfo info; - U64 address_lo = message_in.getValueU32("address"); - U64 address_hi = message_in.hasValue("address_1") ? message_in.getValueU32("address_1") : 0; - info.mAddress = (void*)((address_lo) | - (address_hi * (U64(1)<<31))); + info.mAddress = message_in.getValuePointer("address"); info.mSize = (size_t)message_in.getValueS32("size"); std::string name = message_in.getValue("name"); diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp index f115c28..91efdae 100644 --- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -75,6 +75,8 @@ public: private: + std::string mProfileDir; + enum { INIT_STATE_UNINITIALIZED, // Browser instance hasn't been set up yet @@ -95,6 +97,12 @@ private: int mLastMouseY; bool mFirstFocus; + void setInitState(int state) + { +// std::cerr << "changing init state to " << state << std::endl; + mInitState = state; + } + //////////////////////////////////////////////////////////////////////////////// // void update(int milliseconds) @@ -186,7 +194,6 @@ private: #else std::string component_dir = application_dir; #endif - std::string profileDir = application_dir + "/" + "browser_profile"; // cross platform? // window handle - needed on Windows and must be app window. #if LL_WINDOWS @@ -198,7 +205,7 @@ private: #endif // main browser initialization - bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, profileDir, native_window_handle ); + bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, mProfileDir, native_window_handle ); if ( result ) { // create single browser window @@ -208,13 +215,15 @@ private: // Enable plugins LLQtWebKit::getInstance()->enablePlugins(true); #elif LL_DARWIN - // Disable plugins - LLQtWebKit::getInstance()->enablePlugins(false); + // Enable plugins + LLQtWebKit::getInstance()->enablePlugins(true); #elif LL_LINUX - // Disable plugins - LLQtWebKit::getInstance()->enablePlugins(false); + // Enable plugins + LLQtWebKit::getInstance()->enablePlugins(true); #endif - + // Enable cookies + LLQtWebKit::getInstance()->enableCookies( true ); + // tell LLQtWebKit about the size of the browser window LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); @@ -227,11 +236,11 @@ private: // don't flip bitmap LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true ); - // Set the background color to black - mostly for initial login page + // set background color to be black - mostly for initial login page LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, 0x00, 0x00, 0x00 ); // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns. - mInitState = INIT_STATE_NAVIGATING; + setInitState(INIT_STATE_NAVIGATING); // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance. // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially @@ -285,7 +294,7 @@ private: { if(mInitState == INIT_STATE_WAIT_REDRAW) { - mInitState = INIT_STATE_RUNNING; + setInitState(INIT_STATE_RUNNING); } // flag that an update is required @@ -307,7 +316,7 @@ private: if(mInitState == INIT_STATE_NAVIGATE_COMPLETE) { - mInitState = INIT_STATE_WAIT_REDRAW; + setInitState(INIT_STATE_WAIT_REDRAW); } } @@ -330,7 +339,7 @@ private: } else if(mInitState == INIT_STATE_NAVIGATING) { - mInitState = INIT_STATE_NAVIGATE_COMPLETE; + setInitState(INIT_STATE_NAVIGATE_COMPLETE); } } @@ -495,7 +504,16 @@ private: { // std::cerr << "unicode input, code = 0x" << std::hex << (unsigned long)(wstr[i]) << std::dec << std::endl; - LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, wstr[i], modifiers); + if(wstr[i] == 32) + { + // For some reason, the webkit plugin really wants the space bar to come in through the key-event path, not the unicode path. + LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, 32, modifiers); + LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, 32, modifiers); + } + else + { + LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, wstr[i], modifiers); + } } checkEditState(); @@ -576,6 +594,9 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) { if(message_name == "init") { + std::string user_data_path = message_in.getValue("user_data_path"); // n.b. always has trailing platform-specific dir-delimiter + mProfileDir = user_data_path + "browser_profile"; + LLPluginMessage message("base", "init_response"); LLSD versions = LLSD::emptyMap(); versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; @@ -611,7 +632,11 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) } else if(message_name == "cleanup") { - // TODO: clean up here + // DTOR most likely won't be called but the recent change to the way this process + // is (not) killed means we see this message and can do what we need to here. + // Note: this cleanup is ultimately what writes cookies to the disk + LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this ); + LLQtWebKit::getInstance()->reset(); } else if(message_name == "shm_added") { diff --git a/linden/indra/newview/llviewerparcelmedia.cpp b/linden/indra/newview/llviewerparcelmedia.cpp index c7f0c4b..d4ebbd9 100644 --- a/linden/indra/newview/llviewerparcelmedia.cpp +++ b/linden/indra/newview/llviewerparcelmedia.cpp @@ -193,6 +193,9 @@ void LLViewerParcelMedia::play(LLParcel* parcel) S32 media_width = parcel->getMediaWidth(); S32 media_height = parcel->getMediaHeight(); + // Debug print + // LL_DEBUGS("Media") << "Play media type : " << mime_type << ", url : " << media_url << LL_ENDL; + if(sMediaImpl) { // If the url and mime type are the same, call play again @@ -221,7 +224,7 @@ void LLViewerParcelMedia::play(LLParcel* parcel) sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id, media_width, media_height, media_auto_scale, - media_loop); + media_loop, mime_type); } } else @@ -229,7 +232,7 @@ void LLViewerParcelMedia::play(LLParcel* parcel) // There is no media impl, make a new one sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id, media_width, media_height, media_auto_scale, - media_loop); + media_loop, mime_type); } -- cgit v1.1 From c1bfe1d0a5d0cf638a69e308cb0867eb29d6bcb8 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 7 Sep 2010 02:03:07 -0700 Subject: Added missing glui and freeglut libs on Windows --- linden/install.xml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'linden') diff --git a/linden/install.xml b/linden/install.xml index 2118090..b43d5aa 100644 --- a/linden/install.xml +++ b/linden/install.xml @@ -516,6 +516,21 @@ </map> </map> </map> + <key>freeglut</key> + <map> + <key>license</key> + <string>mit</string> + <key>packages</key> + <map> + <key>windows</key> + <map> + <key>md5sum</key> + <string>fcbb695ff203775fad96d184bf5f34fc</string> + <key>url</key> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/freeglut-2.4.0-windows-20090608.tar.bz2</uri> + </map> + </map> + </map> <key>freetype</key> <map> <key>copyright</key> @@ -634,6 +649,28 @@ </map> </map> </map> + <key>glui</key> + <map> + <key>license</key> + <string>lgpl</string> + <key>packages</key> + <map> + <key>darwin</key> + <map> + <key>md5sum</key> + <string>84f792a860691d0fad6d1de6eeb31baa</string> + <key>url</key> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/glui-2.36-darwin-20090623a.tar.bz2</uri> + </map> + <key>windows</key> + <map> + <key>md5sum</key> + <string>5b8631fe510d4ebaeb965c673937e1e7</string> + <key>url</key> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/glui-2.3.6-windows-freeglut-20090608.tar.bz2</uri> + </map> + </map> + </map> <key>google</key> <map> <key>license</key> -- cgit v1.1 From 02957499966f101c150756047bc97495eda347cd Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 7 Sep 2010 02:03:44 -0700 Subject: Fixed newview\CMakeLists.txt not parsing on Windows --- linden/indra/newview/CMakeLists.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index 15561d0..aef0b44 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt @@ -1415,6 +1415,8 @@ if (LINUX) --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched DEPENDS imprudence-stripped ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) + + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer010 media_plugin_webkit) if (NOT INSTALL) add_custom_target(package ALL DEPENDS ${product}.tar.bz2) @@ -1452,8 +1454,8 @@ if (DARWIN) --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer010 media_plugin_webkit) + + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) if (PACKAGE) add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME}) @@ -1473,13 +1475,10 @@ if (DARWIN) --build=${CMAKE_CURRENT_BINARY_DIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched - - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_custom_command( TARGET package POST_BUILD COMMAND ${PYTHON_EXECUTABLE} -- cgit v1.1 From ac551638773309e865e384d74aff6473c5690ca7 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 7 Sep 2010 14:13:17 -0700 Subject: Fixed Windows compile error with WIND_BUFFER_SIZE_SEC --- linden/indra/llaudio/llaudioengine_openal.cpp | 2 ++ linden/indra/llaudio/llaudioengine_openal.h | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'linden') diff --git a/linden/indra/llaudio/llaudioengine_openal.cpp b/linden/indra/llaudio/llaudioengine_openal.cpp index 99ab18e..93bc42b 100644 --- a/linden/indra/llaudio/llaudioengine_openal.cpp +++ b/linden/indra/llaudio/llaudioengine_openal.cpp @@ -38,6 +38,8 @@ #include "lllistener_openal.h" +static const float WIND_BUFFER_SIZE_SEC = 0.05f; // 1/20th sec + LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() : mWindGen(NULL), diff --git a/linden/indra/llaudio/llaudioengine_openal.h b/linden/indra/llaudio/llaudioengine_openal.h index 5aca03e..900bcb3 100644 --- a/linden/indra/llaudio/llaudioengine_openal.h +++ b/linden/indra/llaudio/llaudioengine_openal.h @@ -73,7 +73,6 @@ class LLAudioEngine_OpenAL : public LLAudioEngine int mNumEmptyWindALBuffers; static const int MAX_NUM_WIND_BUFFERS = 80; - static const float WIND_BUFFER_SIZE_SEC = 0.05f; // 1/20th sec }; class LLAudioChannelOpenAL : public LLAudioChannel -- cgit v1.1 From fa2c390b870f5705941e36978b8a31dffb5d26db Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 7 Sep 2010 16:01:42 -0700 Subject: Fixed CopyWinLibs. Still a bunch of CMake errors and plugins don't load on Windows --- linden/indra/cmake/CopyWinLibs.cmake | 302 ++++++++++++--------- ...den%2findra%2fcmake%2fCopyWinLibs.cmake.rej.txt | 257 ------------------ 2 files changed, 173 insertions(+), 386 deletions(-) delete mode 100644 linden/indra/cmake/linden%2findra%2fcmake%2fCopyWinLibs.cmake.rej.txt (limited to 'linden') diff --git a/linden/indra/cmake/CopyWinLibs.cmake b/linden/indra/cmake/CopyWinLibs.cmake index b544c15..72cef0c 100644 --- a/linden/indra/cmake/CopyWinLibs.cmake +++ b/linden/indra/cmake/CopyWinLibs.cmake @@ -6,6 +6,7 @@ include(CMakeCopyIfDifferent) +# Copying vivox's alut.dll breaks inworld audio, never use it set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-win32") set(vivox_files SLVoice.exe @@ -14,76 +15,20 @@ set(vivox_files ortp.dll wrap_oal.dll ) +copy_if_different( + ${vivox_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/Debug" + out_targets + ${vivox_files} + ) +set(all_targets ${all_targets} ${out_targets}) set(debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") set(debug_files alut.dll - freebl3.dll - js3250.dll - nspr4.dll - nss3.dll - nssckbi.dll openal32.dll openjpegd.dll libhunspell.dll - plc4.dll - plds4.dll - smime3.dll - softokn3.dll - ssl3.dll - xpcom.dll - xul.dll - windbgdlg.exe - iconv.dll - libxml2.dll - libcairo-2.dll - libfaad-2.dll - libgio-2.0-0.dll - libglib-2.0-0.dll - libgmodule-2.0-0.dll - libgobject-2.0-0.dll - libgthread-2.0-0.dll - charset.dll - intl.dll - libgcrypt-11.dll - libgnutls-26.dll - libgpg-error-0.dll - libgstapp.dll - libgstaudio.dll - libgstaudio-0.10.dll - libgstbase-0.10.dll - libgstcdda.dll - libgstcontroller-0.10.dll - libgstdataprotocol-0.10.dll - libgstdshow.dll - libgstfft.dll - libgstinterfaces.dll - libgstnet-0.10.dll - libgstnetbuffer.dll - libgstpbutils.dll - libgstreamer-0.10.dll - libgstriff.dll - libgstrtp.dll - libgstrtsp.dll - libgstsdp.dll - libgsttag.dll - libgstvideo.dll - libjpeg.dll - libmp3lame-0.dll - libneon-27.dll - libogg-0.dll - liboil-0.3-0.dll - libopenjpeg-2.dll - libpng12-0.dll - libschroedinger-1.0-0.dll - libspeex-1.dll - libtheora-0.dll - libvorbis-0.dll - libvorbisenc-2.dll - libxml2-2.dll - glew32.dll - xvidcore.dll - zlib1.dll ) copy_if_different( @@ -94,82 +39,180 @@ copy_if_different( ) set(all_targets ${all_targets} ${out_targets}) +# Debug config runtime files required for the plugin test mule +set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") +set(plugintest_debug_files + libeay32.dll + libglib-2.0-0.dll + libgmodule-2.0-0.dll + libgobject-2.0-0.dll + libgthread-2.0-0.dll + qtcored4.dll + qtguid4.dll + qtnetworkd4.dll + qtopengld4.dll + qtwebkitd4.dll + ssleay32.dll + ) copy_if_different( - ${vivox_src_dir} - "${CMAKE_CURRENT_BINARY_DIR}/Debug" - out_targets - ${vivox_files} + ${plugintest_debug_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Debug" + out_targets + ${plugintest_debug_files} + ) +set(all_targets ${all_targets} ${out_targets}) + +# Debug config runtime files required for the plugin test mule (Qt image format plugins) +set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/imageformats") +set(plugintest_debug_files + qgifd4.dll + qicod4.dll + qjpegd4.dll + qmngd4.dll + qsvgd4.dll + qtiffd4.dll + ) +copy_if_different( + ${plugintest_debug_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Debug/imageformats" + out_targets + ${plugintest_debug_files} + ) +set(all_targets ${all_targets} ${out_targets}) + +copy_if_different( + ${plugintest_debug_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/llplugin/imageformats" + out_targets + ${plugintest_debug_files} + ) +set(all_targets ${all_targets} ${out_targets}) + +# Release & ReleaseDebInfo config runtime files required for the plugin test mule +set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") +set(plugintest_release_files + libeay32.dll + libglib-2.0-0.dll + libgmodule-2.0-0.dll + libgobject-2.0-0.dll + libgthread-2.0-0.dll + qtcore4.dll + qtgui4.dll + qtnetwork4.dll + qtopengl4.dll + qtwebkit4.dll + ssleay32.dll + ) +copy_if_different( + ${plugintest_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Release" + out_targets + ${plugintest_release_files} + ) +set(all_targets ${all_targets} ${out_targets}) + +copy_if_different( + ${plugintest_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/RelWithDebInfo" + out_targets + ${plugintest_release_files} + ) +set(all_targets ${all_targets} ${out_targets}) + +# Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt image format plugins) +set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/imageformats") +set(plugintest_release_files + qgif4.dll + qico4.dll + qjpeg4.dll + qmng4.dll + qsvg4.dll + qtiff4.dll + ) +copy_if_different( + ${plugintest_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Release/imageformats" + out_targets + ${plugintest_release_files} + ) +set(all_targets ${all_targets} ${out_targets}) + +copy_if_different( + ${plugintest_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/RelWithDebInfo/imageformats" + out_targets + ${plugintest_release_files} + ) +set(all_targets ${all_targets} ${out_targets}) + +copy_if_different( + ${plugintest_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/Release/llplugin/imageformats" + out_targets + ${plugintest_release_files} + ) +set(all_targets ${all_targets} ${out_targets}) + +copy_if_different( + ${plugintest_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin/imageformats" + out_targets + ${plugintest_release_files} + ) +set(all_targets ${all_targets} ${out_targets}) + +# Debug config runtime files required for the plugins +set(plugins_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") +set(plugins_debug_files + libeay32.dll + qtcored4.dll + qtguid4.dll + qtnetworkd4.dll + qtopengld4.dll + qtwebkitd4.dll + ssleay32.dll + ) +copy_if_different( + ${plugins_debug_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/Debug/llplugin" + out_targets + ${plugins_debug_files} + ) +set(all_targets ${all_targets} ${out_targets}) + +# Release & ReleaseDebInfo config runtime files required for the plugins +set(plugins_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") +set(plugins_release_files + libeay32.dll + qtcore4.dll + qtgui4.dll + qtnetwork4.dll + qtopengl4.dll + qtwebkit4.dll + ssleay32.dll + ) +copy_if_different( + ${plugins_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/Release/llplugin" + out_targets + ${plugins_release_files} + ) +set(all_targets ${all_targets} ${out_targets}) + +copy_if_different( + ${plugins_release_src_dir} + "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin" + out_targets + ${plugins_release_files} ) set(all_targets ${all_targets} ${out_targets}) set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") set(release_files alut.dll - freebl3.dll - js3250.dll - nspr4.dll - nss3.dll - nssckbi.dll openal32.dll openjpeg.dll libhunspell.dll - plc4.dll - plds4.dll - smime3.dll - softokn3.dll - ssl3.dll - xpcom.dll - xul.dll - iconv.dll - libxml2.dll - libcairo-2.dll - libfaad-2.dll - libgio-2.0-0.dll - libglib-2.0-0.dll - libgmodule-2.0-0.dll - libgobject-2.0-0.dll - libgthread-2.0-0.dll - charset.dll - intl.dll - libgcrypt-11.dll - libgnutls-26.dll - libgpg-error-0.dll - libgstapp.dll - libgstaudio.dll - libgstaudio-0.10.dll - libgstbase-0.10.dll - libgstcdda.dll - libgstcontroller-0.10.dll - libgstdataprotocol-0.10.dll - libgstdshow.dll - libgstfft.dll - libgstinterfaces.dll - libgstnet-0.10.dll - libgstnetbuffer.dll - libgstpbutils.dll - libgstreamer-0.10.dll - libgstriff.dll - libgstrtp.dll - libgstrtsp.dll - libgstsdp.dll - libgsttag.dll - libgstvideo.dll - libjpeg.dll - libmp3lame-0.dll - libneon-27.dll - libogg-0.dll - liboil-0.3-0.dll - libopenjpeg-2.dll - libpng12-0.dll - libschroedinger-1.0-0.dll - libspeex-1.dll - libtheora-0.dll - libvorbis-0.dll - libvorbisenc-2.dll - libxml2-2.dll - glew32.dll - xvidcore.dll - zlib1.dll ) copy_if_different( @@ -310,6 +353,7 @@ add_custom_target(copy_win_libs ALL ${relwithdebinfo_appconfig_file} ${debug_appconfig_file} ) +add_dependencies(copy_win_libs prepare) if(EXISTS ${internal_llkdu_path}) add_dependencies(copy_win_libs llkdu) diff --git a/linden/indra/cmake/linden%2findra%2fcmake%2fCopyWinLibs.cmake.rej.txt b/linden/indra/cmake/linden%2findra%2fcmake%2fCopyWinLibs.cmake.rej.txt deleted file mode 100644 index 295c9fe..0000000 --- a/linden/indra/cmake/linden%2findra%2fcmake%2fCopyWinLibs.cmake.rej.txt +++ /dev/null @@ -1,257 +0,0 @@ -*************** -*** 15,35 **** - wrap_oal.dll - ) - - set(debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") - set(debug_files -- freebl3.dll -- js3250.dll -- nspr4.dll -- nss3.dll -- nssckbi.dll -- plc4.dll -- plds4.dll -- smime3.dll -- softokn3.dll -- ssl3.dll -- xpcom.dll -- xul.dll - openjpegd.dll -- windbgdlg.exe - ) - ---- 15,30 ---- - wrap_oal.dll - ) -+ copy_if_different( -+ ${vivox_src_dir} -+ "${CMAKE_CURRENT_BINARY_DIR}/Debug" -+ out_targets -+ ${vivox_files} -+ ) -+ set(all_targets ${all_targets} ${out_targets}) -+ - - set(debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") - set(debug_files - openjpegd.dll - ) - -*************** -*** 42,50 **** - set(all_targets ${all_targets} ${out_targets}) - -- copy_if_different( -- ${vivox_src_dir} -- "${CMAKE_CURRENT_BINARY_DIR}/Debug" -- out_targets -- ${vivox_files} - ) - set(all_targets ${all_targets} ${out_targets}) ---- 37,206 ---- - set(all_targets ${all_targets} ${out_targets}) - -+ # Debug config runtime files required for the plugin test mule -+ set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") -+ set(plugintest_debug_files -+ libeay32.dll -+ libglib-2.0-0.dll -+ libgmodule-2.0-0.dll -+ libgobject-2.0-0.dll -+ libgthread-2.0-0.dll -+ qtcored4.dll -+ qtguid4.dll -+ qtnetworkd4.dll -+ qtopengld4.dll -+ qtwebkitd4.dll -+ ssleay32.dll -+ ) -+ copy_if_different( -+ ${plugintest_debug_src_dir} -+ "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Debug" -+ out_targets -+ ${plugintest_debug_files} -+ ) -+ set(all_targets ${all_targets} ${out_targets}) -+ -+ # Debug config runtime files required for the plugin test mule (Qt image format plugins) -+ set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/imageformats") -+ set(plugintest_debug_files -+ qgifd4.dll -+ qicod4.dll -+ qjpegd4.dll -+ qmngd4.dll -+ qsvgd4.dll -+ qtiffd4.dll -+ ) -+ copy_if_different( -+ ${plugintest_debug_src_dir} -+ "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Debug/imageformats" -+ out_targets -+ ${plugintest_debug_files} -+ ) -+ set(all_targets ${all_targets} ${out_targets}) -+ -+ copy_if_different( -+ ${plugintest_debug_src_dir} -+ "${CMAKE_CURRENT_BINARY_DIR}/llplugin/imageformats" -+ out_targets -+ ${plugintest_debug_files} -+ ) -+ set(all_targets ${all_targets} ${out_targets}) -+ -+ # Release & ReleaseDebInfo config runtime files required for the plugin test mule -+ set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") -+ set(plugintest_release_files -+ libeay32.dll -+ libglib-2.0-0.dll -+ libgmodule-2.0-0.dll -+ libgobject-2.0-0.dll -+ libgthread-2.0-0.dll -+ # llkdu.dll (not required for plugin test) -+ qtcore4.dll -+ qtgui4.dll -+ qtnetwork4.dll -+ qtopengl4.dll -+ qtwebkit4.dll -+ ssleay32.dll -+ ) -+ copy_if_different( -+ ${plugintest_release_src_dir} -+ "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Release" -+ out_targets -+ ${plugintest_release_files} -+ ) -+ set(all_targets ${all_targets} ${out_targets}) -+ -+ copy_if_different( -+ ${plugintest_release_src_dir} -+ "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/RelWithDebInfo" -+ out_targets -+ ${plugintest_release_files} -+ ) -+ set(all_targets ${all_targets} ${out_targets}) -+ -+ # Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt image format plugins) -+ set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/imageformats") -+ set(plugintest_release_files -+ qgif4.dll -+ qico4.dll -+ qjpeg4.dll -+ qmng4.dll -+ qsvg4.dll -+ qtiff4.dll -+ ) -+ copy_if_different( -+ ${plugintest_release_src_dir} -+ "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/Release/imageformats" -+ out_targets -+ ${plugintest_release_files} -+ ) -+ set(all_targets ${all_targets} ${out_targets}) -+ -+ copy_if_different( -+ ${plugintest_release_src_dir} -+ "${CMAKE_CURRENT_BINARY_DIR}/../test_apps/llplugintest/RelWithDebInfo/imageformats" -+ out_targets -+ ${plugintest_release_files} -+ ) -+ set(all_targets ${all_targets} ${out_targets}) -+ -+ copy_if_different( -+ ${plugintest_release_src_dir} -+ "${CMAKE_CURRENT_BINARY_DIR}/Release/llplugin/imageformats" -+ out_targets -+ ${plugintest_release_files} -+ ) -+ set(all_targets ${all_targets} ${out_targets}) -+ -+ copy_if_different( -+ ${plugintest_release_src_dir} -+ "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin/imageformats" -+ out_targets -+ ${plugintest_release_files} -+ ) -+ set(all_targets ${all_targets} ${out_targets}) -+ -+ # Debug config runtime files required for the plugins -+ set(plugins_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") -+ set(plugins_debug_files -+ libeay32.dll -+ qtcored4.dll -+ qtguid4.dll -+ qtnetworkd4.dll -+ qtopengld4.dll -+ qtwebkitd4.dll -+ ssleay32.dll -+ ) -+ copy_if_different( -+ ${plugins_debug_src_dir} -+ "${CMAKE_CURRENT_BINARY_DIR}/Debug/llplugin" -+ out_targets -+ ${plugins_debug_files} -+ ) -+ set(all_targets ${all_targets} ${out_targets}) -+ -+ # Release & ReleaseDebInfo config runtime files required for the plugins -+ set(plugins_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") -+ set(plugins_release_files -+ libeay32.dll -+ qtcore4.dll -+ qtgui4.dll -+ qtnetwork4.dll -+ qtopengl4.dll -+ qtwebkit4.dll -+ ssleay32.dll -+ ) -+ copy_if_different( -+ ${plugins_release_src_dir} -+ "${CMAKE_CURRENT_BINARY_DIR}/Release/llplugin" -+ out_targets -+ ${plugins_release_files} -+ ) -+ set(all_targets ${all_targets} ${out_targets}) -+ -+ copy_if_different( -+ ${plugins_release_src_dir} -+ "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin" -+ out_targets -+ ${plugins_release_files} - ) - set(all_targets ${all_targets} ${out_targets}) -*************** -*** 52,67 **** - set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") - set(release_files -- freebl3.dll -- js3250.dll -- nspr4.dll -- nss3.dll -- nssckbi.dll -- plc4.dll -- plds4.dll -- smime3.dll -- softokn3.dll -- ssl3.dll -- xpcom.dll -- xul.dll - openjpeg.dll - ) ---- 208,211 ---- - set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") - set(release_files - openjpeg.dll - ) -*************** -*** 252,256 **** - ${debug_appconfig_file} - ) -- add_dependencies(copy_win_libs prepare) - - if(EXISTS ${internal_llkdu_path}) ---- 396,399 ---- - ${debug_appconfig_file} - ) - - if(EXISTS ${internal_llkdu_path}) -- cgit v1.1 From 1a8709f9910460a90ac1c2466d99fd0897436554 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 7 Sep 2010 16:08:49 -0700 Subject: Removed gstreamer and gstreamer-plugins from install.xml for Windows --- linden/install.xml | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'linden') diff --git a/linden/install.xml b/linden/install.xml index b43d5aa..99d3bb2 100644 --- a/linden/install.xml +++ b/linden/install.xml @@ -720,13 +720,6 @@ <key>url</key> <uri>http://imprudenceviewer.org/download/libs/gstreamer-0.10.24-linux64-20091230.tar.bz2</uri> </map> - <key>windows</key> - <map> - <key>md5sum</key> - <string>da6c3fd73a7e5c9bef768edab8a38c2f</string> - <key>url</key> - <uri>http://imprudenceviewer.org/download/libs/gstreamer-0.10.22-windows-20100825.tar.bz2</uri> - </map> </map> </map> <key>gstreamer-plugins</key> @@ -756,13 +749,6 @@ <key>url</key> <uri>http://imprudenceviewer.org/download/libs/gstreamer-plugins-linux64-20100827.tar.bz2</uri> </map> - <key>windows</key> - <map> - <key>md5sum</key> - <string>a5c7e5f2dbd5ed247f6e9c54f03a8b42</string> - <key>url</key> - <uri>http://imprudenceviewer.org/download/libs/gstreamer-plugins-windows-20100825.tar.bz2</uri> - </map> </map> </map> <key>gtk-etc</key> -- cgit v1.1 From c8bd2bd6a92ad681fda6b8e142b86f233668c3de Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 7 Sep 2010 16:21:13 -0700 Subject: Removed 'prepare' dependency from cmake --- linden/indra/cmake/CopyWinLibs.cmake | 1 - linden/indra/llmath/CMakeLists.txt | 1 - linden/indra/llvfs/CMakeLists.txt | 1 - 3 files changed, 3 deletions(-) (limited to 'linden') diff --git a/linden/indra/cmake/CopyWinLibs.cmake b/linden/indra/cmake/CopyWinLibs.cmake index 72cef0c..2bea40c 100644 --- a/linden/indra/cmake/CopyWinLibs.cmake +++ b/linden/indra/cmake/CopyWinLibs.cmake @@ -353,7 +353,6 @@ add_custom_target(copy_win_libs ALL ${relwithdebinfo_appconfig_file} ${debug_appconfig_file} ) -add_dependencies(copy_win_libs prepare) if(EXISTS ${internal_llkdu_path}) add_dependencies(copy_win_libs llkdu) diff --git a/linden/indra/llmath/CMakeLists.txt b/linden/indra/llmath/CMakeLists.txt index c05bf1d..e5ec3e1 100644 --- a/linden/indra/llmath/CMakeLists.txt +++ b/linden/indra/llmath/CMakeLists.txt @@ -83,4 +83,3 @@ set_source_files_properties(${llmath_HEADER_FILES} list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES}) add_library (llmath ${llmath_SOURCE_FILES}) -add_dependencies(llmath prepare) diff --git a/linden/indra/llvfs/CMakeLists.txt b/linden/indra/llvfs/CMakeLists.txt index d6a0bbc..25b57e0 100644 --- a/linden/indra/llvfs/CMakeLists.txt +++ b/linden/indra/llvfs/CMakeLists.txt @@ -57,7 +57,6 @@ set_source_files_properties(${llvfs_HEADER_FILES} list(APPEND llvfs_SOURCE_FILES ${llvfs_HEADER_FILES}) add_library (llvfs ${llvfs_SOURCE_FILES}) -add_dependencies(llvfs prepare) if (DARWIN) include(CMakeFindFrameworks) -- cgit v1.1 From 53c622976519614eea6a46a5c9b3e938482b170f Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 7 Sep 2010 17:03:10 -0700 Subject: Added missing plugins notifications --- .../newview/skins/default/xui/en-us/notifications.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'linden') diff --git a/linden/indra/newview/skins/default/xui/en-us/notifications.xml b/linden/indra/newview/skins/default/xui/en-us/notifications.xml index d7b078c..b439dba 100644 --- a/linden/indra/newview/skins/default/xui/en-us/notifications.xml +++ b/linden/indra/newview/skins/default/xui/en-us/notifications.xml @@ -5556,7 +5556,25 @@ Apple's QuickTime software does not appear to be installed on your system. If you want to view streaming media on parcels that support it you should go to the QuickTime site (http://www.apple.com/quicktime) and install the QuickTime Player. </notification> +<notification + icon="notify.tga" + name="NoPlugin" + type="notify"> +No Media Plugin was found to handle the "[MIME_TYPE]" mime type. Media of this type will be unavailable. +</notification> +<notification + icon="alertmodal.tga" + name="MediaPluginFailed" + type="alertmodal"> +The following Media Plugin has failed: +[PLUGIN] +Please re-install the plugin or contact the vendor if you continue to experience problems. + <form name="form"> + <ignore name="ignore" + text="When a Media Plugin fails"/> + </form> +</notification> <notification icon="notify.tga" name="OwnedObjectsReturned" -- cgit v1.1 From 891b747e8b6aa0b9e4a99311804438b37c8c05b4 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 7 Sep 2010 17:59:58 -0700 Subject: CMake now runs correctly on Windows --- linden/indra/cmake/ExamplePlugin.cmake | 16 ++++++++++++++++ linden/indra/llplugin/CMakeLists.txt | 8 ++++++++ 2 files changed, 24 insertions(+) create mode 100644 linden/indra/cmake/ExamplePlugin.cmake (limited to 'linden') diff --git a/linden/indra/cmake/ExamplePlugin.cmake b/linden/indra/cmake/ExamplePlugin.cmake new file mode 100644 index 0000000..599787a --- /dev/null +++ b/linden/indra/cmake/ExamplePlugin.cmake @@ -0,0 +1,16 @@ +# -*- cmake -*- +include(Linking) +include(Prebuilt) + +if (STANDALONE) + set(EXAMPLEPLUGIN OFF CACHE BOOL + "EXAMPLEPLUGIN support for the llplugin/llmedia test apps.") +else (STANDALONE) + set(EXAMPLEPLUGIN ON CACHE BOOL + "EXAMPLEPLUGIN support for the llplugin/llmedia test apps.") +endif (STANDALONE) + +if (WINDOWS) +elseif (DARWIN) +elseif (LINUX) +endif (WINDOWS) diff --git a/linden/indra/llplugin/CMakeLists.txt b/linden/indra/llplugin/CMakeLists.txt index 6706775..e41cdf7 100644 --- a/linden/indra/llplugin/CMakeLists.txt +++ b/linden/indra/llplugin/CMakeLists.txt @@ -48,6 +48,14 @@ set(llplugin_HEADER_FILES set_source_files_properties(${llplugin_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) +if(WORD_SIZE EQUAL 64) + if(WINDOWS) + add_definitions(/FIXED:NO) + else(WINDOWS) # not windows therefore gcc LINUX and DARWIN + add_definitions(-fPIC) + endif(WINDOWS) +endif (WORD_SIZE EQUAL 64) + list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES}) add_library (llplugin ${llplugin_SOURCE_FILES}) -- cgit v1.1 From df82325063d61b92cac749c11b7057abf7d769e8 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 7 Sep 2010 18:00:34 -0700 Subject: Removed some bad merge entries from newview/CMakeLists.txt --- linden/indra/newview/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index aef0b44..b576ccd 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt @@ -1139,8 +1139,6 @@ set(viewer_XUI_FILES ) -list(APPEND viewer_XUI_FILES ${viewer_XUI_FILE_GLOB_LIST}) -list(SORT viewer_XUI_FILES) list(APPEND viewer_XUI_FILES ${viewer_XUI_FILE_GLOB_LIST}) list(SORT viewer_XUI_FILES) -- cgit v1.1 From 092fda55d8537e7655a545634e443c6c6c3dde0b Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 7 Sep 2010 18:01:44 -0700 Subject: Added fix for word size from Snowglobe (only for Windows--didn't update Linux or Mac as I can't test them) --- linden/indra/cmake/Variables.cmake | 1 + linden/indra/llplugin/llpluginsharedmemory.cpp | 7 ++++++ linden/indra/media_plugins/CMakeLists.txt | 2 ++ linden/indra/media_plugins/base/CMakeLists.txt | 8 +++++++ linden/indra/media_plugins/example/CMakeLists.txt | 10 ++++++++- .../indra/media_plugins/quicktime/CMakeLists.txt | 3 ++- linden/indra/media_plugins/webkit/CMakeLists.txt | 25 ++++++++++++++++------ 7 files changed, 48 insertions(+), 8 deletions(-) (limited to 'linden') diff --git a/linden/indra/cmake/Variables.cmake b/linden/indra/cmake/Variables.cmake index 5d4dffe..cd5bfc1 100644 --- a/linden/indra/cmake/Variables.cmake +++ b/linden/indra/cmake/Variables.cmake @@ -45,6 +45,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") set(ARCH i686) set(LL_ARCH ${ARCH}_win32) set(LL_ARCH_DIR ${ARCH}-win32) + set(WORD_SIZE 32) endif (${CMAKE_SYSTEM_NAME} MATCHES "Windows") if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") diff --git a/linden/indra/llplugin/llpluginsharedmemory.cpp b/linden/indra/llplugin/llpluginsharedmemory.cpp index 2be4648..c946619 100644 --- a/linden/indra/llplugin/llpluginsharedmemory.cpp +++ b/linden/indra/llplugin/llpluginsharedmemory.cpp @@ -34,6 +34,13 @@ #include "llpluginsharedmemory.h" +#if LL_WINDOWS +#include <process.h> +#else // LL_WINDOWS +#include <sys/types.h> +#include <unistd.h> +#endif // LL_WINDOWS + // on Mac and Linux, we use the native shm_open/mmap interface by using // #define USE_SHM_OPEN_SHARED_MEMORY 1 // in the appropriate sections below. diff --git a/linden/indra/media_plugins/CMakeLists.txt b/linden/indra/media_plugins/CMakeLists.txt index d35afd8..cc03d9c 100644 --- a/linden/indra/media_plugins/CMakeLists.txt +++ b/linden/indra/media_plugins/CMakeLists.txt @@ -9,3 +9,5 @@ add_subdirectory(gstreamer010) if (WINDOWS OR DARWIN) add_subdirectory(quicktime) endif (WINDOWS OR DARWIN) + +add_subdirectory(example) diff --git a/linden/indra/media_plugins/base/CMakeLists.txt b/linden/indra/media_plugins/base/CMakeLists.txt index f8d2dab..a3ee02e 100644 --- a/linden/indra/media_plugins/base/CMakeLists.txt +++ b/linden/indra/media_plugins/base/CMakeLists.txt @@ -25,6 +25,14 @@ include_directories( ### media_plugin_base +if(WORD_SIZE EQUAL 64) + if(WINDOWS) + add_definitions(/FIXED:NO) + else(WINDOWS) # not windows therefore gcc LINUX and DARWIN + add_definitions(-fPIC) + endif(WINDOWS) +endif (WORD_SIZE EQUAL 64) + set(media_plugin_base_SOURCE_FILES media_plugin_base.cpp ) diff --git a/linden/indra/media_plugins/example/CMakeLists.txt b/linden/indra/media_plugins/example/CMakeLists.txt index 4d82f27..b074a1d 100644 --- a/linden/indra/media_plugins/example/CMakeLists.txt +++ b/linden/indra/media_plugins/example/CMakeLists.txt @@ -29,6 +29,14 @@ include_directories( ### media_plugin_example +if(WORD_SIZE EQUAL 64) + if(WINDOWS) + add_definitions(/FIXED:NO) + else(WINDOWS) # not windows therefore gcc LINUX and DARWIN + add_definitions(-fPIC) + endif(WINDOWS) +endif (WORD_SIZE EQUAL 64) + set(media_plugin_example_SOURCE_FILES media_plugin_example.cpp ) @@ -71,4 +79,4 @@ if (DARWIN) LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" ) -endif (DARWIN) \ No newline at end of file +endif (DARWIN) diff --git a/linden/indra/media_plugins/quicktime/CMakeLists.txt b/linden/indra/media_plugins/quicktime/CMakeLists.txt index f0b8f0d..df191f5 100644 --- a/linden/indra/media_plugins/quicktime/CMakeLists.txt +++ b/linden/indra/media_plugins/quicktime/CMakeLists.txt @@ -60,7 +60,8 @@ if (WINDOWS) set_target_properties( media_plugin_quicktime PROPERTIES - LINK_FLAGS "/MANIFEST:NO" + LINK_FLAGS "/MANIFEST:NO /NODEFAULTLIB:LIBCMT" + LINK_FLAGS_DEBUG "/MANIFEST:NO /NODEFAULTLIB:\"LIBCMT;LIBCMTD\"" ) endif (WINDOWS) diff --git a/linden/indra/media_plugins/webkit/CMakeLists.txt b/linden/indra/media_plugins/webkit/CMakeLists.txt index 5bccd58..54bc364 100644 --- a/linden/indra/media_plugins/webkit/CMakeLists.txt +++ b/linden/indra/media_plugins/webkit/CMakeLists.txt @@ -24,6 +24,7 @@ include_directories( ${LLIMAGE_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} + ${LLQTWEBKIT_INCLUDE_DIR} ) @@ -33,12 +34,15 @@ set(media_plugin_webkit_SOURCE_FILES media_plugin_webkit.cpp ) -add_library(media_plugin_webkit - SHARED - ${media_plugin_webkit_SOURCE_FILES} -) +if(WORD_SIZE EQUAL 64) + if(WINDOWS) + add_definitions(/FIXED:NO) + else(WINDOWS) # not windows therefore gcc LINUX and DARWIN + add_definitions(-fPIC) + endif(WINDOWS) +endif (WORD_SIZE EQUAL 64) -target_link_libraries(media_plugin_webkit +set(media_plugin_webkit_LINK_LIBRARIES ${LLPLUGIN_LIBRARIES} ${MEDIA_PLUGIN_BASE_LIBRARIES} ${LLCOMMON_LIBRARIES} @@ -46,6 +50,15 @@ target_link_libraries(media_plugin_webkit ${PLUGIN_API_WINDOWS_LIBRARIES} ) + + +add_library(media_plugin_webkit + SHARED + ${media_plugin_webkit_SOURCE_FILES} +) + +target_link_libraries(media_plugin_webkit ${media_plugin_webkit_LINK_LIBRARIES}) + add_dependencies(media_plugin_webkit ${LLPLUGIN_LIBRARIES} ${MEDIA_PLUGIN_BASE_LIBRARIES} @@ -79,4 +92,4 @@ if (DARWIN) DEPENDS media_plugin_webkit ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib ) -endif (DARWIN) \ No newline at end of file +endif (DARWIN) -- cgit v1.1 From 0df07dde8df981c1c7ffac1aea5977dbbb386354 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 7 Sep 2010 22:57:19 -0700 Subject: Fixed llvewermedia version info (and kept it disabled unless there's a good reason for enabling it) --- linden/indra/newview/llviewermedia.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/llviewermedia.cpp b/linden/indra/newview/llviewermedia.cpp index 92ccf25..5bdb26f 100644 --- a/linden/indra/newview/llviewermedia.cpp +++ b/linden/indra/newview/llviewermedia.cpp @@ -40,6 +40,7 @@ #include "llviewerimage.h" #include "llviewerwindow.h" #include "llviewerimagelist.h" +//#include "viewerversion.h" #include "llpluginclassmedia.h" @@ -241,13 +242,15 @@ LLViewerMediaImpl* LLViewerMedia::getMediaImplFromTextureID(const LLUUID& textur // static std::string LLViewerMedia::getCurrentUserAgent() { + // Don't include version, channel, or skin -- MC + // Don't use user-visible string to avoid // punctuation and strange characters. - std::string skin_name = gSavedSettings.getString("SkinCurrent"); + //std::string skin_name = gSavedSettings.getString("SkinCurrent"); // Just in case we need to check browser differences in A/B test // builds. - std::string channel = gSavedSettings.getString("VersionChannelName"); + //std::string channel = gSavedSettings.getString("VersionChannelName"); // append our magic version number string to the browser user agent id // See the HTTP 1.0 and 1.1 specifications for allowed formats: @@ -257,9 +260,9 @@ std::string LLViewerMedia::getCurrentUserAgent() // http://www.mozilla.org/build/revised-user-agent-strings.html std::ostringstream codec; codec << "SecondLife/"; - codec << "C64 Basic V2"; //imprudence fixme : this isn't anybodys business anyway -// codec << LL_VERSION_MAJOR << "." << LL_VERSION_MINOR << "." << LL_VERSION_PATCH << "." << LL_VERSION_BUILD; -// codec << " (" << channel << "; " << skin_name << " skin)"; + codec << "C64 Basic V2"; + //codec << ViewerVersion::getImpMajorVersion() << "." << ViewerVersion::getImpMinorVersion() << "." << ViewerVersion::getImpPatchVersion() << " " << ViewerVersion::getImpTestVersion(); + //codec << " (" << channel << "; " << skin_name << " skin)"; // llinfos << codec.str() << llendl; return codec.str(); -- cgit v1.1 From 811e2d201bef3dd946e415789676c65e7833f80e Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 7 Sep 2010 22:57:54 -0700 Subject: Fixed floatervicelicense not compiling with the new media changes --- linden/indra/newview/floatervoicelicense.cpp | 31 +++++++++++++--------------- linden/indra/newview/floatervoicelicense.h | 11 +++++----- linden/indra/newview/llfirstuse.cpp | 4 ++-- linden/indra/newview/llprefsvoice.cpp | 4 ++-- linden/indra/newview/llwebbrowserctrl.h | 1 - 5 files changed, 24 insertions(+), 27 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/floatervoicelicense.cpp b/linden/indra/newview/floatervoicelicense.cpp index 74d16c3..0697b5c 100644 --- a/linden/indra/newview/floatervoicelicense.cpp +++ b/linden/indra/newview/floatervoicelicense.cpp @@ -27,7 +27,7 @@ * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ -/* + #include "llviewerprecompiledheaders.h" #include "floatervoicelicense.h" @@ -122,7 +122,7 @@ BOOL FloaterVoiceLicense::postBuild() LLTextEditor *editor = getChild<LLTextEditor>("license_text"); editor->setVisible( FALSE ); - LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("license_html"); + LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("license_html"); if ( web_browser ) { // start to observe it so we see navigate complete events @@ -137,7 +137,7 @@ BOOL FloaterVoiceLicense::postBuild() void FloaterVoiceLicense::setSiteIsAlive( bool alive ) { - LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("license_html"); + LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("license_html"); // if the contents of the site was retrieved if ( alive ) { @@ -158,12 +158,6 @@ void FloaterVoiceLicense::setSiteIsAlive( bool alive ) FloaterVoiceLicense::~FloaterVoiceLicense() { - // stop observing events - LLWebBrowserCtrl* web_browser = getChild<LLWebBrowserCtrl>("license_html"); - if ( web_browser ) - { - web_browser->remObserver( this ); - } // tell the responder we're not here anymore if ( gResponsePtr ) @@ -224,14 +218,17 @@ void FloaterVoiceLicense::onCancel( void* userdata ) } //virtual -void FloaterVoiceLicense::onNavigateComplete( const EventType& eventIn ) +void FloaterVoiceLicense::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent event) { - // skip past the loading screen navigate complete - if ( ++mLoadCompleteCount == 2 ) + if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) { - llinfos << "NAVIGATE COMPLETE" << llendl; - // enable Agree to License radio button now that page has loaded - LLCheckBoxCtrl * license_agreement = getChild<LLCheckBoxCtrl>("agree_chk"); - license_agreement->setEnabled( true ); + // skip past the loading screen navigate complete + if ( ++mLoadCompleteCount == 2 ) + { + llinfos << "NAVIGATE COMPLETE" << llendl; + // enable Agree to License radio button now that page has loaded + LLCheckBoxCtrl * license_agreement = getChild<LLCheckBoxCtrl>("agree_chk"); + license_agreement->setEnabled( true ); + } } -}*/ +} diff --git a/linden/indra/newview/floatervoicelicense.h b/linden/indra/newview/floatervoicelicense.h index 9d2012d..30dbb2f 100644 --- a/linden/indra/newview/floatervoicelicense.h +++ b/linden/indra/newview/floatervoicelicense.h @@ -35,8 +35,8 @@ #include "llmodaldialog.h" #include "llassetstorage.h" -//imprudence fixme: removed for media plugins #include "llwebbrowserctrl.h" -/* +#include "llmediactrl.h" + class LLButton; class LLRadioGroup; class LLVFS; @@ -45,7 +45,7 @@ class LLUUID; class FloaterVoiceLicense : public LLModalDialog, - public LLViewerMediaObserver + public LLViewerMediaObserver, public LLFloaterSingleton<FloaterVoiceLicense> { public: @@ -62,11 +62,12 @@ public: void setSiteIsAlive( bool alive ); - virtual void onNavigateComplete( const EventType& eventIn ); + // inherited from LLViewerMediaObserver + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); private: int mWebBrowserWindowId; int mLoadCompleteCount; -};*/ +}; #endif // FLOATERVOICELICENSE_H diff --git a/linden/indra/newview/llfirstuse.cpp b/linden/indra/newview/llfirstuse.cpp index ca8614c..e82aa96 100644 --- a/linden/indra/newview/llfirstuse.cpp +++ b/linden/indra/newview/llfirstuse.cpp @@ -397,8 +397,8 @@ void LLFirstUse::voiceLicenseAgreement() { gSavedSettings.setWarning("FirstVoiceLicense", FALSE); -// imprudence fixme FloaterVoiceLicense::getInstance()->open(); -// FloaterVoiceLicense::getInstance()->center(); + FloaterVoiceLicense::getInstance()->open(); + FloaterVoiceLicense::getInstance()->center(); } else // currently in STATE_LOGIN_VOICE_LICENSE when arriving here { diff --git a/linden/indra/newview/llprefsvoice.cpp b/linden/indra/newview/llprefsvoice.cpp index 609d30a..7c50f4a 100644 --- a/linden/indra/newview/llprefsvoice.cpp +++ b/linden/indra/newview/llprefsvoice.cpp @@ -153,8 +153,8 @@ void LLPrefsVoice::apply() if (enable_voice && !gSavedSettings.getBOOL("VivoxLicenseAccepted")) { // This window enables voice chat if license is accepted -//imprudence fixme FloaterVoiceLicense::getInstance()->open(); -//imprudence fixme FloaterVoiceLicense::getInstance()->center(); + FloaterVoiceLicense::getInstance()->open(); + FloaterVoiceLicense::getInstance()->center(); } else { diff --git a/linden/indra/newview/llwebbrowserctrl.h b/linden/indra/newview/llwebbrowserctrl.h index 0100807..79b8942 100644 --- a/linden/indra/newview/llwebbrowserctrl.h +++ b/linden/indra/newview/llwebbrowserctrl.h @@ -106,7 +106,6 @@ class LLWebBrowserCtrlObserver #include "lluictrl.h" #include "llframetimer.h" #include "lldynamictexture.h" -#include "llmediamanager.h" #include "llmediaobserver.h" class LLViewBorder; -- cgit v1.1 From 12810aeb0cc9c252d9295101d06dd0eb8711d8c6 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 7 Sep 2010 23:35:39 -0700 Subject: Fixed 'there is no media type for text/html' errors --- linden/indra/newview/llmimetypes.cpp | 18 + .../newview/skins/default/xui/en-us/mime_types.xml | 451 +++++++++++++++++++++ 2 files changed, 469 insertions(+) (limited to 'linden') diff --git a/linden/indra/newview/llmimetypes.cpp b/linden/indra/newview/llmimetypes.cpp index 525e89c..c45e0ab 100644 --- a/linden/indra/newview/llmimetypes.cpp +++ b/linden/indra/newview/llmimetypes.cpp @@ -56,6 +56,24 @@ bool LLMIMETypes::parseMIMETypes(const std::string& xml_filename) { LLXMLNodePtr root; bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); + + if (!success) + { + // If fails, check if we can read the file from the app_settings folder + std::string settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, xml_filename); + success = LLUICtrlFactory::getLayeredXMLNode(settings_filename, root); + + #if LL_WINDOWS + // On the windows dev builds, unpackaged, the mime_types.xml file will be located in + // indra/build-vc**/newview/<config>/app_settings. + if (!success) + { + settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", xml_filename); + success = LLUICtrlFactory::getLayeredXMLNode(settings_filename, root); + } + #endif + } + if ( ! success || root.isNull() || ! root->hasName( "mimetypes" ) ) { llwarns << "Unable to read MIME type file: " diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types.xml index e69de29..9f0c631 100644 --- a/linden/indra/newview/skins/default/xui/en-us/mime_types.xml +++ b/linden/indra/newview/skins/default/xui/en-us/mime_types.xml @@ -0,0 +1,451 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<mimetypes name="default"> + <defaultlabel> + (Unknown) + </defaultlabel> + <defaultwidget> + none + </defaultwidget> + <defaultimpl> + media_plugin_webkit + </defaultimpl> + <widgetset name="web"> + <label name="web_label"> + Web Content + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + text/html + </default_type> + <tooltip name="web_tooltip"> + This location has Web content + </tooltip> + <playtip name="web_playtip"> + Show Web content + </playtip> + <allow_resize> + true + </allow_resize> + <allow_looping> + false + </allow_looping> + </widgetset> + <widgetset name="movie"> + <label name="movie_label"> + Movie + </label> + <default_type> + video/* + </default_type> + <icon> + icn_media_movie.tga + </icon> + <tooltip name="movie_tooltip"> + There is a movie to play here + </tooltip> + <playtip name="movie_playtip"> + Play movie + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + true + </allow_looping> + </widgetset> + <widgetset name="image"> + <label name="image_label"> + Image + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + image/* + </default_type> + <tooltip name="image_tooltip"> + There is an image at this location + </tooltip> + <playtip name="image_playtip"> + View this location's image + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + false + </allow_looping> + </widgetset> + <widgetset name="audio"> + <label name="audio_label"> + Audio + </label> + <icon> + icn_media_web.tga + </icon> + <default_type> + audio/* + </default_type> + <tooltip name="audio_tooltip"> + There is audio at this location + </tooltip> + <playtip name="audio_playtip"> + Play this location's audio + </playtip> + <allow_resize> + false + </allow_resize> + <allow_looping> + true + </allow_looping> + </widgetset> + <scheme name="rtsp"> + <label name="rtsp_label"> + Real Time Streaming + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </scheme> + <mimetype name="blank"> + <label name="blank_label"> + - None - + </label> + <widgettype> + none + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="none/none"> + <label name="none/none_label"> + - None - + </label> + <widgettype> + none + </widgettype> + </mimetype> + <mimetype name="audio/*"> + <label name="audio2_label"> + Audio + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="video/*"> + <label name="video2_label"> + Video + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="image/*"> + <label name="image2_label"> + Image + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> + <label name="vnd.secondlife.qt.legacy_label"> + Movie (QuickTime) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="application/javascript"> + <label name="application/javascript_label"> + Javascript + </label> + <widgettype> + web + </widgettype> + </mimetype> + <mimetype name="application/ogg"> + <label name="application/ogg_label"> + Ogg Audio/Video + </label> + <widgettype> + audio + </widgettype> + </mimetype> + <mimetype name="application/pdf"> + <label name="application/pdf_label"> + PDF Document + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/postscript"> + <label name="application/postscript_label"> + Postscript Document + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/rtf"> + <label name="application/rtf_label"> + Rich Text (RTF) + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="application/smil"> + <label name="application/smil_label"> + Synchronized Multimedia Integration Language (SMIL) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="application/xhtml+xml"> + <label name="application/xhtml+xml_label"> + Web Page (XHTML) + </label> + <widgettype> + web + </widgettype> + </mimetype> + <mimetype name="application/x-director"> + <label name="application/x-director_label"> + Macromedia Director + </label> + <widgettype> + image + </widgettype> + </mimetype> + <mimetype name="audio/mid"> + <label name="audio/mid_label"> + Audio (MIDI) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="audio/mpeg"> + <label name="audio/mpeg_label"> + Audio (MP3) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="audio/x-aiff"> + <label name="audio/x-aiff_label"> + Audio (AIFF) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="audio/x-wav"> + <label name="audio/x-wav_label"> + Audio (WAV) + </label> + <widgettype> + audio + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype menu="1" name="image/bmp"> + <label name="image/bmp_label"> + Image (BMP) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/gif"> + <label name="image/gif_label"> + Image (GIF) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/jpeg"> + <label name="image/jpeg_label"> + Image (JPEG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/png"> + <label name="image/png_label"> + Image (PNG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype name="image/svg+xml"> + <label name="image/svg+xml_label"> + Image (SVG) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="image/tiff"> + <label name="image/tiff_label"> + Image (TIFF) + </label> + <widgettype> + image + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="text/html"> + <label name="text/html_label"> + Web Page + </label> + <widgettype> + web + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="text/plain"> + <label name="text/plain_label"> + Text + </label> + <widgettype> + text + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype name="text/xml"> + <label name="text/xml_label"> + XML + </label> + <widgettype> + text + </widgettype> + <impl> + media_plugin_webkit + </impl> + </mimetype> + <mimetype menu="1" name="video/mpeg"> + <label name="video/mpeg_label"> + Movie (MPEG) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="video/mp4"> + <label name="video/mp4_label"> + Movie (MP4) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype menu="1" name="video/quicktime"> + <label name="video/quicktime_label"> + Movie (QuickTime) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="video/x-ms-asf"> + <label name="video/x-ms-asf_label"> + Movie (Windows Media ASF) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype name="video/x-ms-wmv"> + <label name="video/x-ms-wmv_label"> + Movie (Windows Media WMV) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> + <mimetype menu="1" name="video/x-msvideo"> + <label name="video/x-msvideo_label"> + Movie (AVI) + </label> + <widgettype> + movie + </widgettype> + <impl> + media_plugin_quicktime + </impl> + </mimetype> +</mimetypes> -- cgit v1.1 From ca628a8d0bf76872cc5b7e9a3d67dc37ea554cb7 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Sat, 20 Feb 2010 18:36:56 +0100 Subject: remove deprecated files --- linden/indra/newview/llfloaterhtml.cpp | 1 - linden/indra/newview/llwebbrowserctrl.cpp | 1068 ----------------------------- linden/indra/newview/llwebbrowserctrl.h | 325 --------- 3 files changed, 1394 deletions(-) delete mode 100644 linden/indra/newview/llwebbrowserctrl.cpp delete mode 100644 linden/indra/newview/llwebbrowserctrl.h (limited to 'linden') diff --git a/linden/indra/newview/llfloaterhtml.cpp b/linden/indra/newview/llfloaterhtml.cpp index a5d24f4..5822ed5 100644 --- a/linden/indra/newview/llfloaterhtml.cpp +++ b/linden/indra/newview/llfloaterhtml.cpp @@ -41,7 +41,6 @@ #include "llviewerwindow.h" #include "llweb.h" -#include "llwebbrowserctrl.h" LLFloaterHtml* LLFloaterHtml::sInstance = 0; diff --git a/linden/indra/newview/llwebbrowserctrl.cpp b/linden/indra/newview/llwebbrowserctrl.cpp deleted file mode 100644 index 453b9d2..0000000 --- a/linden/indra/newview/llwebbrowserctrl.cpp +++ /dev/null @@ -1,1068 +0,0 @@ -/** - * @file llwebbrowserctrl.cpp - * @brief Web browser UI control - * - * $LicenseInfo:firstyear=2006&license=viewergpl$ - * - * Copyright (c) 2006-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - - -#include "llwebbrowserctrl.h" - -// viewer includes -#include "llfloaterhtml.h" -#include "llfloaterworldmap.h" -#include "lluictrlfactory.h" -#include "llurldispatcher.h" -#include "llurlsimstring.h" -#include "llviewborder.h" -#include "llviewercontrol.h" -#include "llviewerwindow.h" -#include "llnotifications.h" -#include "llweb.h" -#include "llrender.h" - -// linden library includes -#include "llfocusmgr.h" - -extern BOOL gRestoreGL; - -// Setting the mozilla buffer width to 2048 exactly doesn't work, since it pads its rowbytes a bit, pushing the texture width over 2048. -// 2000 should give enough headroom for any amount of padding it cares to add. -const S32 MAX_DIMENSION = 2000; -const S32 MAX_TEXTURE_DIMENSION = 2048; - -static LLRegisterWidget<LLWebBrowserCtrl> r("web_browser"); - -LLWebBrowserCtrl::LLWebBrowserCtrl( const std::string& name, const LLRect& rect ) : - LLUICtrl( name, rect, FALSE, NULL, NULL ), - mTextureDepthBytes( 4 ), - mWebBrowserImage( 0 ), - mEmbeddedBrowserWindowId( 0 ), - mBorder(NULL), - mFrequentUpdates( true ), - mForceUpdate( false ), - mOpenLinksInExternalBrowser( false ), - mOpenLinksInInternalBrowser( false ), - mTrusted( false ), - mHomePageUrl( "" ), - mIgnoreUIScale( true ), - mAlwaysRefresh( false ), - mExternalUrl( "" ), - mMediaSource( 0 ), - mTakeFocusOnClick( true ), - mCurrentNavUrl( "about:blank" ) -{ - S32 screen_width = mIgnoreUIScale ? - llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]) : getRect().getWidth(); - S32 screen_height = mIgnoreUIScale ? - llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight(); - - - LLMediaManager *mgr = LLMediaManager::getInstance(); - - if (!mgr) - { - llwarns << "cannot get media manager" << llendl; - return; - } - - mMediaSource = mgr->createSourceFromMimeType("http", "text/html" ); - if ( !mMediaSource ) - { - llwarns << "media source create failed " << llendl; - // return; - } - else - { - - // mMediaSource->init(); - mMediaSource->addCommand( LLMediaBase::COMMAND_START ); - - // observe the browser so we can trap HREF events) - mMediaSource->addObserver(this); - - // create a new texture (based on LLDynamic texture) that will be used to display the output - mWebBrowserImage = new LLWebBrowserTexture( screen_width, screen_height, this, mMediaSource ); - } - - LLRect border_rect( 0, getRect().getHeight() + 2, getRect().getWidth() + 2, 0 ); - mBorder = new LLViewBorder( std::string("web control border"), border_rect, LLViewBorder::BEVEL_IN ); - addChild( mBorder ); -} - -//////////////////////////////////////////////////////////////////////////////// -// note: this is now a singleton and destruction happens via initClass() now -LLWebBrowserCtrl::~LLWebBrowserCtrl() -{ - LLMediaManager *mgr = LLMediaManager::getInstance(); - - if (!mgr) - { - llwarns << "cannot get media manager" << llendl; - return; - } - - if (mMediaSource) - { - mgr->destroySource(mMediaSource); - mMediaSource = NULL; - } - - if ( mWebBrowserImage ) - { - delete mWebBrowserImage; - mWebBrowserImage = 0; - }; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLWebBrowserCtrl::addObserver( LLWebBrowserCtrlObserver* subjectIn ) -{ - return mEventEmitter.addObserver( subjectIn ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLWebBrowserCtrl::remObserver( LLWebBrowserCtrlObserver* subjectIn ) -{ - return mEventEmitter.remObserver( subjectIn ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserCtrl::setBorderVisible( BOOL border_visible ) -{ - if ( mBorder ) - { - mBorder->setVisible( border_visible ); - }; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserCtrl::setTakeFocusOnClick( bool take_focus ) -{ - mTakeFocusOnClick = take_focus; -} - -//////////////////////////////////////////////////////////////////////////////// -// set flag that forces the embedded browser to open links in the external system browser -void LLWebBrowserCtrl::setOpenInExternalBrowser( bool valIn ) -{ - mOpenLinksInExternalBrowser = valIn; -}; - -//////////////////////////////////////////////////////////////////////////////// -// set flag that forces the embedded browser to open links in the internal browser floater -void LLWebBrowserCtrl::setOpenInInternalBrowser( bool valIn ) -{ - mOpenLinksInInternalBrowser = valIn; -}; - -//////////////////////////////////////////////////////////////////////////////// -void LLWebBrowserCtrl::setTrusted( bool valIn ) -{ - mTrusted = valIn; -} - -//////////////////////////////////////////////////////////////////////////////// -// -BOOL LLWebBrowserCtrl::handleHover( S32 x, S32 y, MASK mask ) -{ - convertInputCoords(x, y); - - if (mMediaSource) - mMediaSource->mouseMove(x, y); - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////////////// -// -BOOL LLWebBrowserCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks ) -{ - if (mMediaSource) - mMediaSource->scrollByLines(clicks); - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////////////// -// -BOOL LLWebBrowserCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) -{ - convertInputCoords(x, y); - - if (mMediaSource) - { - mMediaSource->mouseUp(x, y); - - // *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup, - // in addition to the onFocusReceived() call below. Undo this. JC - if (!mTakeFocusOnClick) - { - mMediaSource->focus(false); - gViewerWindow->focusClient(); - } - } - - gFocusMgr.setMouseCapture( NULL ); - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////////////// -// -BOOL LLWebBrowserCtrl::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - convertInputCoords(x, y); - - if (mMediaSource) - mMediaSource->mouseDown(x, y); - - gFocusMgr.setMouseCapture( this ); - - if (mTakeFocusOnClick) - { - setFocus( TRUE ); - } - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////////////// -// -BOOL LLWebBrowserCtrl::handleDoubleClick( S32 x, S32 y, MASK mask ) -{ - convertInputCoords(x, y); - - if (mMediaSource) - mMediaSource->mouseLeftDoubleClick( x, y ); - - gFocusMgr.setMouseCapture( this ); - - if (mTakeFocusOnClick) - { - setFocus( TRUE ); - } - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserCtrl::onFocusReceived() -{ - if (mMediaSource) - mMediaSource->focus(true); - - - LLUICtrl::onFocusReceived(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserCtrl::onFocusLost() -{ - if (mMediaSource) - mMediaSource->focus(false); - - gViewerWindow->focusClient(); - - LLUICtrl::onFocusLost(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -BOOL LLWebBrowserCtrl::handleKeyHere( KEY key, MASK mask ) -{ - unsigned long media_key; - - // First, turn SL internal keycode enum into Mozilla keycode enum - - // We don't have to deal with printable characters here - they should - // go through handleUnicodeChar(). This table could be more complete - // than it is, but I think this covers all of the important - // non-printables. - - switch (key) - { - case KEY_BACKSPACE: - media_key = LL_MEDIA_KEY_BACKSPACE; break; - case KEY_TAB: - media_key = LL_MEDIA_KEY_TAB; break; - case KEY_RETURN: - media_key = LL_MEDIA_KEY_RETURN; break; - case KEY_PAD_RETURN: - media_key = LL_MEDIA_KEY_PAD_RETURN; break; - case KEY_ESCAPE: - media_key = LL_MEDIA_KEY_ESCAPE; break; - case KEY_PAGE_UP: - media_key = LL_MEDIA_KEY_PAGE_UP; break; - case KEY_PAGE_DOWN: - media_key = LL_MEDIA_KEY_PAGE_DOWN; break; - case KEY_END: - media_key = LL_MEDIA_KEY_END; break; - case KEY_HOME: - media_key = LL_MEDIA_KEY_HOME; break; - case KEY_LEFT: - media_key = LL_MEDIA_KEY_LEFT; break; - case KEY_UP: - media_key = LL_MEDIA_KEY_UP; break; - case KEY_RIGHT: - media_key = LL_MEDIA_KEY_RIGHT; break; - case KEY_DOWN: - media_key = LL_MEDIA_KEY_DOWN; break; - case KEY_INSERT: - media_key = LL_MEDIA_KEY_INSERT; break; - case KEY_DELETE: - media_key = LL_MEDIA_KEY_DELETE; break; - default: - llinfos << "Don't know how to map LL keycode " << U32(key) - << " to DOM key. Ignoring." << llendl; - return FALSE; // don't know how to map this key. - } - - if (mMediaSource) - mMediaSource->keyPress(media_key); - - return TRUE; -} - -BOOL LLWebBrowserCtrl::handleUnicodeCharHere(llwchar uni_char) -{ - // only accept 'printable' characters, sigh... - if (uni_char >= 32 // discard 'control' characters - && uni_char != 127) // SDL thinks this is 'delete' - yuck. - { - if (mMediaSource) - mMediaSource->unicodeInput(uni_char); - } - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserCtrl::onVisibilityChange ( BOOL new_visibility ) -{ - // set state of frequent updates automatically if visibility changes - if ( new_visibility ) - { - mFrequentUpdates = true; - } - else - { - mFrequentUpdates = false; - } - LLUICtrl::onVisibilityChange(new_visibility); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserCtrl::reshape( S32 width, S32 height, BOOL called_from_parent ) -{ - S32 screen_width = mIgnoreUIScale ? llround((F32)width * LLUI::sGLScaleFactor.mV[VX]) : width; - S32 screen_height = mIgnoreUIScale ? llround((F32)height * LLUI::sGLScaleFactor.mV[VY]) : height; - - // when floater is minimized, these sizes are negative - if ( mWebBrowserImage && screen_height > 0 && screen_width > 0 ) - { - mWebBrowserImage->resize( screen_width, screen_height ); - mForceUpdate = true; - } - - LLUICtrl::reshape( width, height, called_from_parent ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserCtrl::navigateBack() -{ - if (mMediaSource) - mMediaSource->navigateBack(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserCtrl::navigateForward() -{ - if (mMediaSource) - mMediaSource->navigateForward(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLWebBrowserCtrl::canNavigateBack() -{ - if (mMediaSource) - return mMediaSource->canNavigateBack(); - else - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLWebBrowserCtrl::canNavigateForward() -{ - if (mMediaSource) - return mMediaSource->canNavigateForward(); - else - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLWebBrowserCtrl::set404RedirectUrl( std::string redirect_url ) -{ - if(mMediaSource) - return mMediaSource->set404RedirectUrl( redirect_url ); - else - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLWebBrowserCtrl::clr404RedirectUrl() -{ - if(mMediaSource) - return mMediaSource->clr404RedirectUrl(); - else - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserCtrl::navigateTo( std::string urlIn ) -{ - // don't browse to anything that starts with secondlife:// or sl:// - const std::string protocol1 = "secondlife://"; - const std::string protocol2 = "sl://"; - if ((LLStringUtil::compareInsensitive(urlIn.substr(0, protocol1.length()), protocol1) == 0) || - (LLStringUtil::compareInsensitive(urlIn.substr(0, protocol2.length()), protocol2) == 0)) - { - // TODO: Print out/log this attempt? - // llinfos << "Rejecting attempt to load restricted website :" << urlIn << llendl; - return; - } - - if (mMediaSource) - { - mCurrentNavUrl = urlIn; - mMediaSource->navigateTo(urlIn); - } -} - - -void LLWebBrowserCtrl::navigateToLocalPage( const std::string& subdir, const std::string& filename_in ) -{ - std::string language = LLUI::getLanguage(); - std::string delim = gDirUtilp->getDirDelimiter(); - std::string filename; - - filename += subdir; - filename += delim; - filename += filename_in; - - std::string expanded_filename = gDirUtilp->findSkinnedFilename("html", language, filename); - - if (gDirUtilp->fileExists(expanded_filename)) - { - navigateTo(expanded_filename); - return; - } - if (language != "en-us") - { - expanded_filename = gDirUtilp->findSkinnedFilename("html", "en-us", filename); - if (gDirUtilp->fileExists(expanded_filename)) - { - navigateTo(expanded_filename); - return; - } - } - - llwarns << "File " << subdir << delim << filename_in << "not found" << llendl; -} - - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserCtrl::navigateHome() -{ - if( mHomePageUrl.length() ) - { - if (mMediaSource) - mMediaSource->navigateTo(mHomePageUrl); - }; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserCtrl::setHomePageUrl( const std::string urlIn ) -{ - mHomePageUrl = urlIn; -} - -//////////////////////////////////////////////////////////////////////////////// -// -bool LLWebBrowserCtrl::setCaretColor(unsigned int red, unsigned int green, unsigned int blue) -{ - if (mMediaSource) - return mMediaSource->setCaretColor(red, green, blue); - else - return false; -} -//////////////////////////////////////////////////////////////////////////////// -// -std::string LLWebBrowserCtrl::getHomePageUrl() -{ - return mHomePageUrl; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserCtrl::draw() -{ - if ( ! mWebBrowserImage ) - return; - - if ( gRestoreGL == 1 ) - { - LLRect r = getRect(); - mMediaSource->updateMedia(); - reshape( r.getWidth(), r.getHeight(), FALSE ); - return; - }; - - // NOTE: optimization needed here - probably only need to do this once - // unless tearoffs change the parent which they probably do. - const LLUICtrl* ptr = findRootMostFocusRoot(); - if ( ptr && ptr->hasFocus() ) - { - setFrequentUpdates( true ); - } - else - { - setFrequentUpdates( false ); - }; - - // alpha off for this - LLGLSUIDefault gls_ui; - LLGLDisable gls_alphaTest( GL_ALPHA_TEST ); - - gGL.pushMatrix(); - { - if (mIgnoreUIScale) - { - glLoadIdentity(); - // font system stores true screen origin, need to scale this by UI scale factor - // to get render origin for this view (with unit scale) - gGL.translatef(floorf(LLFontGL::sCurOrigin.mX * LLUI::sGLScaleFactor.mV[VX]), - floorf(LLFontGL::sCurOrigin.mY * LLUI::sGLScaleFactor.mV[VY]), - LLFontGL::sCurOrigin.mZ); - } - - // scale texture to fit the space using texture coords - gGL.getTexUnit(0)->bind(mWebBrowserImage->getTexture()); - gGL.color4fv( LLColor4::white.mV ); - F32 max_u = ( F32 )mWebBrowserImage->getBrowserWidth() / ( F32 )mWebBrowserImage->getWidth(); - F32 max_v = ( F32 )mWebBrowserImage->getBrowserHeight() / ( F32 )mWebBrowserImage->getHeight(); - - // draw the browser - gGL.setSceneBlendType(LLRender::BT_REPLACE); - gGL.begin( LLRender::QUADS ); - { - // render using web browser reported width and height, instead of trying to invert GL scale - gGL.texCoord2f( max_u, max_v ); - gGL.vertex2i( mWebBrowserImage->getBrowserWidth(), mWebBrowserImage->getBrowserHeight() ); - - gGL.texCoord2f( 0.f, max_v ); - gGL.vertex2i( 0, mWebBrowserImage->getBrowserHeight() ); - - gGL.texCoord2f( 0.f, 0.f ); - gGL.vertex2i( 0, 0 ); - - gGL.texCoord2f( max_u, 0.f ); - gGL.vertex2i( mWebBrowserImage->getBrowserWidth(), 0 ); - } - gGL.end(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - } - gGL.popMatrix(); - - // highlight if keyboard focus here. (TODO: this needs some work) - if ( mBorder->getVisible() ) - mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) ); - - - LLUICtrl::draw(); -} - -void LLWebBrowserCtrl::convertInputCoords(S32& x, S32& y) -{ - x = mIgnoreUIScale ? llround((F32)x * LLUI::sGLScaleFactor.mV[VX]) : x; - y = mIgnoreUIScale ? llround((F32)(getRect().getHeight() - y) * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight() - y; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLWebBrowserCtrl::onNavigateBegin( const EventType& eventIn ) -{ - LLWebBrowserCtrlEvent event( eventIn.getStringValue() ); - mEventEmitter.update( &LLWebBrowserCtrlObserver::onNavigateBegin, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLWebBrowserCtrl::onNavigateComplete( const EventType& eventIn ) -{ - // chain this event on to observers of an instance of LLWebBrowserCtrl - LLWebBrowserCtrlEvent event( eventIn.getStringValue() ); - mEventEmitter.update( &LLWebBrowserCtrlObserver::onNavigateComplete, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLWebBrowserCtrl::onUpdateProgress( const EventType& eventIn ) -{ - // chain this event on to observers of an instance of LLWebBrowserCtrl - LLWebBrowserCtrlEvent event( eventIn.getIntValue() ); - mEventEmitter.update( &LLWebBrowserCtrlObserver::onUpdateProgress, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLWebBrowserCtrl::onStatusTextChange( const EventType& eventIn ) -{ - // chain this event on to observers of an instance of LLWebBrowserCtrl - LLWebBrowserCtrlEvent event( eventIn.getStringValue() ); - mEventEmitter.update( &LLWebBrowserCtrlObserver::onStatusTextChange, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLWebBrowserCtrl::onLocationChange( const EventType& eventIn ) -{ - // chain this event on to observers of an instance of LLWebBrowserCtrl - LLWebBrowserCtrlEvent event( eventIn.getStringValue() ); - mEventEmitter.update( &LLWebBrowserCtrlObserver::onLocationChange, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLWebBrowserCtrl::onMediaContentsChange( const EventType& event_in ) -{ - if ( mWebBrowserImage ) - { - mWebBrowserImage->setNeedsUpdate(); - mForceUpdate = true; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// static -bool LLWebBrowserCtrl::onClickLinkExternalTarget(const LLSD& notification, const LLSD& response ) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - if ( 0 == option ) - { - // open in external browser because we don't support - // creation of our own secondary browser windows - LLWeb::loadURLExternal( notification["payload"]["external_url"].asString() ); - } - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLWebBrowserCtrl::onClickLinkHref( const EventType& eventIn ) -{ - // if there is a value for the target (passed in stringValueEx) - if ( eventIn.getStringValueEx().length() ) - { - // if the target = "_new" - if ( eventIn.getStringValueEx() == "_external" ) - { - mExternalUrl = eventIn.getStringValue(); - LLSD payload; - payload["external_url"] = mExternalUrl; - LLNotifications::instance().add( "WebLaunchExternalTarget", LLSD(), payload, onClickLinkExternalTarget); - return; - } - } - - const std::string protocol1( "http://" ); - const std::string protocol2( "https://" ); - if( mOpenLinksInExternalBrowser ) - { - if ( eventIn.getStringValue().length() ) - { - if ( LLStringUtil::compareInsensitive( eventIn.getStringValue().substr( 0, protocol1.length() ), protocol1 ) == 0 || - LLStringUtil::compareInsensitive( eventIn.getStringValue().substr( 0, protocol2.length() ), protocol2 ) == 0 ) - { - LLWeb::loadURLExternal( eventIn.getStringValue() ); - } - } - } - else - if( mOpenLinksInInternalBrowser ) - { - if ( eventIn.getStringValue().length() ) - { - if ( LLStringUtil::compareInsensitive( eventIn.getStringValue().substr( 0, protocol1.length() ), protocol1 ) == 0 || - LLStringUtil::compareInsensitive( eventIn.getStringValue().substr( 0, protocol2.length() ), protocol2 ) == 0 ) - { - // If we spawn a new LLFloaterHTML, assume we want it to - // follow this LLWebBrowserCtrl's trust for whether or - // not to open secondlife:///app/ links. JC. - const bool open_links_externally = false; - LLFloaterHtml::getInstance()->show( - eventIn.getStringValue(), - "Second Life Browser", - open_links_externally, - mTrusted); - } - } - } - - // chain this event on to observers of an instance of LLWebBrowserCtrl - LLWebBrowserCtrlEvent event( eventIn.getStringValue(), eventIn.getStringValueEx() ); - mEventEmitter.update( &LLWebBrowserCtrlObserver::onClickLinkHref, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -void LLWebBrowserCtrl::onClickLinkNoFollow( const EventType& eventIn ) -{ - std::string url = eventIn.getStringValue(); - if (LLURLDispatcher::isSLURLCommand(url) - && !mTrusted) - { - // block handling of this secondlife:///app/ URL - LLNotifications::instance().add("UnableToOpenCommandURL"); - return; - } - - LLURLDispatcher::dispatch(url, this, mTrusted); - - // chain this event on to observers of an instance of LLWebBrowserCtrl - LLWebBrowserCtrlEvent event( eventIn.getStringValue() ); - mEventEmitter.update( &LLWebBrowserCtrlObserver::onClickLinkNoFollow, event ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -LLWebBrowserTexture::LLWebBrowserTexture( S32 width, S32 height, LLWebBrowserCtrl* browserCtrl, LLMediaBase *media_source ) : - LLDynamicTexture( 512, 512, 4, ORDER_FIRST, TRUE ), - mLastBrowserDepth( 0 ), - mNeedsUpdate( true ), - mWebBrowserCtrl( browserCtrl ), - mMediaSource(media_source) -{ - mElapsedTime.start(); - - resize( width, height ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -LLWebBrowserTexture::~LLWebBrowserTexture() -{ - mElapsedTime.stop(); -} - -//////////////////////////////////////////////////////////////////////////////// -// -BOOL LLWebBrowserTexture::needsRender() -{ - if ( mWebBrowserCtrl->getFrequentUpdates() || - mWebBrowserCtrl->getAlwaysRefresh() || - mWebBrowserCtrl->getForceUpdate() ) - { - // only update mozilla/texture occasionally - if ( mElapsedTime.getElapsedTimeF32() > ( 1.0f / 15.0f ) ) - { - return TRUE; - } - } - - return FALSE; -} - -//////////////////////////////////////////////////////////////////////////////// -// -BOOL LLWebBrowserTexture::render() -{ - if (!mMediaSource) - return FALSE; - - // frequent updates turned on? - if ( mWebBrowserCtrl->getFrequentUpdates() || - mWebBrowserCtrl->getAlwaysRefresh() || - mWebBrowserCtrl->getForceUpdate() ) - { - - if ( mNeedsUpdate ) - { - - const unsigned char* pixels = mMediaSource->getMediaData(); - if ( ! pixels ) - return FALSE; - - mNeedsUpdate = false; - mWebBrowserCtrl->setForceUpdate(false); - - S32 media_depth = mMediaSource->getMediaDepth(); - S32 media_width = mMediaSource->getMediaWidth(); - S32 media_height = mMediaSource->getMediaHeight(); - - // these are both invalid conditions and should never happen but SL-27583 indicates it does - if ((media_width < 1) || (media_depth < 2)) - return FALSE; - - // Browser depth hasn't changed. - if(mLastBrowserDepth == media_depth) - { - S32 width = llmin(media_width, mBrowserWidth); - S32 height = llmin(media_height, mBrowserHeight); - - S32 media_data_width = mMediaSource->getMediaDataWidth(); - S32 media_data_height = mMediaSource->getMediaDataHeight(); - - // Just grab the pixels. - if ( media_data_width > 0 && media_data_height > 0 && - media_data_width < MAX_DIMENSION && media_data_height < MAX_DIMENSION ) - { - mTexture->setSubImage( pixels, - media_data_width, media_data_height, - 0, 0, - llmin(width, media_data_width), llmin(media_data_height, height) ); - }; - } - else - { - // Browser depth has changed -- need to recreate texture to match. - resize(mBrowserWidth, mBrowserHeight); - }; - }; - }; - - return TRUE; -} - -//////////////////////////////////////////////////////////////////////////////// -// -S32 LLWebBrowserTexture::getBrowserWidth() -{ - return mBrowserWidth; -} - -//////////////////////////////////////////////////////////////////////////////// -// -S32 LLWebBrowserTexture::getBrowserHeight() -{ - return mBrowserHeight; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserTexture::setNeedsUpdate() -{ - mNeedsUpdate = true; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLWebBrowserTexture::resize( S32 new_width, S32 new_height ) -{ - if (!mMediaSource) - return; - - F32 scale_ratio = 1.f; - if (new_width > MAX_DIMENSION) - { - scale_ratio = (F32)MAX_DIMENSION / (F32)new_width; - } - if (new_height > MAX_DIMENSION) - { - scale_ratio = llmin(scale_ratio, (F32)MAX_DIMENSION / (F32)new_height); - } - - mBrowserWidth = llround(scale_ratio * (F32)new_width); - mBrowserHeight = llround(scale_ratio * (F32)new_height); - - mMediaSource->setRequestedMediaSize(mBrowserWidth, mBrowserHeight); - - // HACK - this code is executing a render - resize should call render() instead - // (and render() should be refactored so it doesn't call resize()) - - mMediaSource->updateMedia(); - const unsigned char* pixels = mMediaSource->getMediaData(); - - S32 media_width = mMediaSource->getMediaWidth(); - S32 media_height = mMediaSource->getMediaHeight(); - S32 media_depth = mMediaSource->getMediaDepth(); - - // these are both invalid conditions and should never happen but SL-27583 indicates it does - if ( media_width < 1 || media_depth < 2 ) - return; - - releaseGLTexture(); - - // calculate the next power of 2 bigger than reqquested size for width and height - for ( mWidth = 1; mWidth < mBrowserWidth; mWidth <<= 1 ) - { - if ( mWidth >= MAX_TEXTURE_DIMENSION ) - { - break; - }; - }; - - for ( mHeight = 1; mHeight < mBrowserHeight; mHeight <<= 1 ) - { - if ( mHeight >= MAX_TEXTURE_DIMENSION ) - { - break; - }; - }; - - LLGLint internal_format; - LLGLenum primary_format; - LLGLenum type_format; - BOOL swap_bytes = FALSE; - - switch(media_depth) - { - default: - case 4: - internal_format = GL_RGBA8; - primary_format = GL_BGRA_EXT; - #if LL_DARWIN - #if LL_BIG_ENDIAN - type_format = GL_UNSIGNED_INT_8_8_8_8_REV; - #else - type_format = GL_UNSIGNED_INT_8_8_8_8; - #endif - #else // windows or linux - type_format = GL_UNSIGNED_BYTE; - #endif - break; - - case 2: - #if LL_DARWIN - internal_format = GL_RGBA8; - primary_format = GL_BGRA_EXT; - type_format = GL_UNSIGNED_SHORT_1_5_5_5_REV; - #if LL_LITTLE_ENDIAN - swap_bytes = TRUE; - #endif - #else // windows or linux - // MBW -- XXX -- This is just a guess on my part. Someone needs to verify which GL texture format matches the 16-bit format used on windows. - internal_format = GL_RGB8; - primary_format = GL_RGB; - type_format = GL_UNSIGNED_SHORT_5_6_5; - #endif - break; - } - - // will create mWidth * mHeight sized texture, using BGR ordering - LLDynamicTexture::generateGLTexture(internal_format, primary_format, type_format, swap_bytes); - - - S32 width = llmin(media_width, mBrowserWidth); - S32 height = llmin(media_height, mBrowserHeight); - - S32 media_data_width = mMediaSource->getMediaDataWidth(); - S32 media_data_height = mMediaSource->getMediaDataHeight(); - - if (pixels) - { - mTexture->setSubImage( pixels, media_data_width, media_data_height, - 0, 0, width, height ); - } - - mLastBrowserDepth = media_depth; -} - -// virtual -LLXMLNodePtr LLWebBrowserCtrl::getXML(bool save_children) const -{ - LLXMLNodePtr node = LLUICtrl::getXML(); - - node->setName(LL_WEB_BROWSER_CTRL_TAG); - - return node; -} - -LLView* LLWebBrowserCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) -{ - std::string name("web_browser"); - node->getAttributeString("name", name); - - std::string start_url("start_url"); - node->getAttributeString("start_url", start_url ); - - BOOL border_visible = true; - node->getAttributeBOOL("border_visible", border_visible); - - LLRect rect; - createRect(node, rect, parent, LLRect()); - - LLWebBrowserCtrl* web_browser = new LLWebBrowserCtrl( name, rect ); - - if(node->hasAttribute("caret_color")) - { - LLColor4 color; - LLUICtrlFactory::getAttributeColor(node, "caret_color", color); - LLColor4U colorU = LLColor4U(color); - web_browser->setCaretColor( colorU.mV[0], colorU.mV[1], colorU.mV[2] ); - } - - BOOL ignore_ui_scale = web_browser->getIgnoreUIScale(); - node->getAttributeBOOL("ignore_ui_scale", ignore_ui_scale); - web_browser->setIgnoreUIScale((bool)ignore_ui_scale); - - web_browser->initFromXML(node, parent); - - web_browser->setHomePageUrl( start_url ); - - web_browser->setBorderVisible( border_visible ); - - web_browser->navigateHome(); - - return web_browser; -} - -std::string LLWebBrowserCtrl::getCurrentNavUrl() -{ - return mCurrentNavUrl; -} - diff --git a/linden/indra/newview/llwebbrowserctrl.h b/linden/indra/newview/llwebbrowserctrl.h deleted file mode 100644 index 79b8942..0000000 --- a/linden/indra/newview/llwebbrowserctrl.h +++ /dev/null @@ -1,325 +0,0 @@ -/** - * @file llwebbrowserctrl.h - * @brief Web browser UI control - * - * $LicenseInfo:firstyear=2006&license=viewergpl$ - * - * Copyright (c) 2006-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLWEBBROWSERCTRL_H -#define LL_LLWEBBROWSERCTRL_H - -//////////////////////////////////////////////////////////////////////////////// -// data class that is passed with an event -class LLWebBrowserCtrlEvent -{ - public: - LLWebBrowserCtrlEvent() - { - }; - - LLWebBrowserCtrlEvent( int intValIn ) : - mIntVal( intValIn ) - { - }; - - LLWebBrowserCtrlEvent( std::string stringValIn ) : - mIntVal(-1), - mStringVal( stringValIn ) - { - }; - - LLWebBrowserCtrlEvent( std::string stringValIn, std::string stringValExIn ) : - mIntVal(-1), - mStringVal( stringValIn ), - mStringValEx( stringValExIn ) - { - }; - - virtual ~LLWebBrowserCtrlEvent() - { - }; - - int getIntValue() const - { - return mIntVal; - }; - - std::string getStringValue() const - { - return mStringVal; - }; - - std::string getStringValueEx() const - { - return mStringValEx; - }; - - private: - int mIntVal; - std::string mStringVal; - std::string mStringValEx; -}; - -//////////////////////////////////////////////////////////////////////////////// -// Override these methods to observe web browser control events -// (they are chained and fired after observing LLMozLibEvents) -class LLWebBrowserCtrlObserver -{ - public: - virtual ~LLWebBrowserCtrlObserver() { }; - - typedef LLWebBrowserCtrlEvent EventType; - virtual void onNavigateBegin( const EventType& eventIn ) { }; - virtual void onNavigateComplete( const EventType& eventIn ) { }; - virtual void onUpdateProgress( const EventType& eventIn ) { }; - virtual void onStatusTextChange( const EventType& eventIn ) { }; - virtual void onLocationChange( const EventType& eventIn ) { }; - virtual void onClickLinkHref( const EventType& eventIn ) { }; - virtual void onClickLinkNoFollow( const EventType& eventIn ) { }; -}; - -#include "lluictrl.h" -#include "llframetimer.h" -#include "lldynamictexture.h" -#include "llmediaobserver.h" - -class LLViewBorder; -class LLWebBrowserTexture; - -/////////////////////////////////////////////////////////////////////////////// -// manages the process of storing and emitting events that the consumer -// of the embedding class can observe -template< class T > -class LLWebBrowserCtrlEventEmitter -{ - public: - LLWebBrowserCtrlEventEmitter() { }; - ~LLWebBrowserCtrlEventEmitter() { }; - - typedef typename T::EventType EventType; - typedef std::list< T* > ObserverContainer; - typedef void( T::*observerMethod )( const EventType& ); - - /////////////////////////////////////////////////////////////////////////////// - // - bool addObserver( T* observerIn ) - { - if ( ! observerIn ) - return false; - - if ( std::find( observers.begin(), observers.end(), observerIn ) != observers.end() ) - return false; - - observers.push_back( observerIn ); - - return true; - }; - - /////////////////////////////////////////////////////////////////////////////// - // - bool remObserver( T* observerIn ) - { - if ( ! observerIn ) - return false; - - observers.remove( observerIn ); - - return true; - }; - - /////////////////////////////////////////////////////////////////////////////// - // - void update( observerMethod method, const EventType& msgIn ) - { - typename std::list< T* >::iterator iter = observers.begin(); - - while( iter != observers.end() ) - { - ( ( *iter )->*method )( msgIn ); - - ++iter; - }; - }; - - protected: - ObserverContainer observers; -}; - -class LLUICtrlFactory; - -//////////////////////////////////////////////////////////////////////////////// -// -class LLWebBrowserCtrl : - public LLUICtrl, - public LLMediaObserver -{ - public: - LLWebBrowserCtrl( const std::string& name, const LLRect& rect ); - virtual ~LLWebBrowserCtrl(); - - void setBorderVisible( BOOL border_visible ); - - // For the tutorial window, we don't want to take focus on clicks, - // as the examples include how to move around with the arrow - // keys. Thus we keep focus on the app by setting this false. - // Defaults to true. - void setTakeFocusOnClick( bool take_focus ); - - virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - - // handle mouse related methods - virtual BOOL handleHover( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); - - // navigation - void navigateTo( std::string urlIn ); - void navigateBack(); - void navigateHome(); - void navigateForward(); - void navigateToLocalPage( const std::string& subdir, const std::string& filename_in ); - bool canNavigateBack(); - bool canNavigateForward(); - void setOpenInExternalBrowser( bool valIn ); - void setOpenInInternalBrowser( bool valIn ); - std::string getCurrentNavUrl(); - - // By default, we do not handle "secondlife:///app/" SLURLs, because - // those can cause teleports, open windows, etc. We cannot be sure - // that each "click" is actually due to a user action, versus - // Javascript or some other mechanism. However, we need the search - // floater and login page to handle these URLs. Those are safe - // because we control the page content. See DEV-9530. JC. - void setTrusted( bool valIn ); - - void setHomePageUrl( const std::string urlIn ); - std::string getHomePageUrl(); - - // set/clear URL to visit when a 404 page is reached - bool set404RedirectUrl( std::string redirect_url ); - bool clr404RedirectUrl(); - - // accessor/mutator for flag that indicates if frequent updates to texture happen - bool getFrequentUpdates() { return mFrequentUpdates; }; - void setFrequentUpdates( bool frequentUpdatesIn ) { mFrequentUpdates = frequentUpdatesIn; }; - - void setIgnoreUIScale(bool ignore) { mIgnoreUIScale = ignore; } - bool getIgnoreUIScale() { return mIgnoreUIScale; } - - void setAlwaysRefresh(bool refresh) { mAlwaysRefresh = refresh; } - bool getAlwaysRefresh() { return mAlwaysRefresh; } - - void setForceUpdate(bool force_update) { mForceUpdate = force_update; } - bool getForceUpdate() { return mForceUpdate; } - - bool setCaretColor( unsigned int red, unsigned int green, unsigned int blue ); - - - // over-rides - virtual BOOL handleKeyHere( KEY key, MASK mask); - virtual BOOL handleUnicodeCharHere(llwchar uni_char); - virtual void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE); - virtual void draw(); - virtual void onVisibilityChange ( BOOL curVisibilityIn ); - - // focus overrides - void onFocusLost(); - void onFocusReceived(); - - // observer interface - bool addObserver( LLWebBrowserCtrlObserver* subjectIn ); - bool remObserver( LLWebBrowserCtrlObserver* subjectIn ); - - // LLMozlib observer overrides - virtual void onNavigateBegin( const EventType& eventIn ); - virtual void onNavigateComplete( const EventType& eventIn ); - virtual void onUpdateProgress( const EventType& eventIn ); - virtual void onStatusTextChange( const EventType& eventIn ); - virtual void onLocationChange( const EventType& eventIn ); - virtual void onClickLinkHref( const EventType& eventIn ); - virtual void onClickLinkNoFollow( const EventType& eventIn ); - virtual void onMediaContentsChange( const EventType& event_in ); - - protected: - void convertInputCoords(S32& x, S32& y); - - private: - static bool onClickLinkExternalTarget( const LLSD&, const LLSD& ); - - LLWebBrowserCtrlEventEmitter< LLWebBrowserCtrlObserver > mEventEmitter; - const S32 mTextureDepthBytes; - int mEmbeddedBrowserWindowId; - LLWebBrowserTexture* mWebBrowserImage; - LLViewBorder* mBorder; - bool mFrequentUpdates; - bool mForceUpdate; - bool mOpenLinksInExternalBrowser; - bool mOpenLinksInInternalBrowser; - bool mTrusted; - std::string mHomePageUrl; - std::string mExternalUrl; - std::string mCurrentNavUrl; - bool mIgnoreUIScale; - bool mAlwaysRefresh; - LLMediaBase* mMediaSource; - bool mTakeFocusOnClick; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -class LLWebBrowserTexture : public LLDynamicTexture -{ - public: - LLWebBrowserTexture( S32 width, S32 height, LLWebBrowserCtrl* browserCtrl, LLMediaBase *media_source ); - virtual ~LLWebBrowserTexture(); - - virtual BOOL needsRender(); - virtual void preRender( BOOL clear_depth = TRUE ) {}; - virtual void postRender( BOOL success ) {}; - virtual BOOL render(); - - S32 getBrowserWidth(); - S32 getBrowserHeight(); - void setNeedsUpdate(); - - void resize( S32 new_width, S32 new_height ); - - protected: - S32 mBrowserWidth; - S32 mBrowserHeight; - S32 mLastBrowserDepth; - bool mNeedsUpdate; - LLFrameTimer mElapsedTime; - LLWebBrowserCtrl* mWebBrowserCtrl; - LLMediaBase *mMediaSource; -}; - -#endif // LL_LLWEBBROWSERCTRL_H -- cgit v1.1 From dcdfa1ebab37dd78282bc95093a5f347f5846b1c Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Fri, 26 Feb 2010 17:06:16 +0100 Subject: port SG2.0 Mediaplugs (webkit supports flash now) --- linden/indra/llplugin/CMakeLists.txt | 0 linden/indra/llplugin/llpluginclassmedia.cpp | 51 ++++- linden/indra/llplugin/llpluginclassmedia.h | 26 ++- linden/indra/llplugin/llpluginclassmediaowner.h | 4 +- linden/indra/llplugin/llplugininstance.cpp | 4 +- linden/indra/llplugin/llplugininstance.h | 5 +- linden/indra/llplugin/llpluginmessage.cpp | 4 +- linden/indra/llplugin/llpluginmessage.h | 5 +- linden/indra/llplugin/llpluginmessageclasses.h | 4 +- linden/indra/llplugin/llpluginmessagepipe.cpp | 13 +- linden/indra/llplugin/llpluginmessagepipe.h | 4 +- linden/indra/llplugin/llpluginprocesschild.cpp | 39 ++-- linden/indra/llplugin/llpluginprocesschild.h | 7 +- linden/indra/llplugin/llpluginprocessparent.cpp | 8 +- linden/indra/llplugin/llpluginprocessparent.h | 4 +- linden/indra/llplugin/llpluginsharedmemory.cpp | 6 +- linden/indra/llplugin/llpluginsharedmemory.h | 5 +- linden/indra/llplugin/slplugin/CMakeLists.txt | 0 linden/indra/llplugin/slplugin/slplugin.cpp | 56 +++--- linden/indra/llplugin/slplugin/slplugin_info.plist | 0 linden/indra/llwindow/llwindow.h | 4 + linden/indra/llwindow/llwindowmacosx.cpp | 2 +- linden/indra/llwindow/llwindowmacosx.h | 4 + linden/indra/llwindow/llwindowsdl.cpp | 39 +++- linden/indra/llwindow/llwindowsdl.h | 9 +- linden/indra/llwindow/llwindowwin32.cpp | 13 ++ linden/indra/llwindow/llwindowwin32.h | 8 +- linden/indra/media_plugins/CMakeLists.txt | 0 linden/indra/media_plugins/base/CMakeLists.txt | 0 .../indra/media_plugins/base/media_plugin_base.cpp | 4 +- .../indra/media_plugins/base/media_plugin_base.exp | 1 + .../indra/media_plugins/base/media_plugin_base.h | 4 +- linden/indra/media_plugins/example/CMakeLists.txt | 2 +- .../media_plugins/example/media_plugin_example.cpp | 19 +- .../media_plugins/gstreamer010/CMakeLists.txt | 4 +- .../gstreamer010/llmediaimplgstreamer.h | 4 +- .../gstreamer010/llmediaimplgstreamer_syms.cpp | 4 +- .../gstreamer010/llmediaimplgstreamer_syms.h | 4 +- .../gstreamer010/llmediaimplgstreamer_syms_raw.inc | 0 .../llmediaimplgstreamer_syms_rawv.inc | 0 .../llmediaimplgstreamertriviallogging.h | 4 +- .../gstreamer010/llmediaimplgstreamervidplug.cpp | 6 +- .../gstreamer010/llmediaimplgstreamervidplug.h | 4 +- .../gstreamer010/media_plugin_gstreamer010.cpp | 4 +- .../indra/media_plugins/quicktime/CMakeLists.txt | 0 .../quicktime/media_plugin_quicktime.cpp | 84 ++++---- linden/indra/media_plugins/webkit/CMakeLists.txt | 7 + .../media_plugins/webkit/media_plugin_webkit.cpp | 213 +++++++++++++-------- linden/indra/newview/llviewermedia.cpp | 37 +++- linden/install.xml | 12 +- 50 files changed, 520 insertions(+), 221 deletions(-) mode change 100644 => 100755 linden/indra/llplugin/CMakeLists.txt mode change 100644 => 100755 linden/indra/llplugin/llpluginclassmedia.cpp mode change 100644 => 100755 linden/indra/llplugin/llpluginclassmedia.h mode change 100644 => 100755 linden/indra/llplugin/llpluginclassmediaowner.h mode change 100644 => 100755 linden/indra/llplugin/llplugininstance.cpp mode change 100644 => 100755 linden/indra/llplugin/llplugininstance.h mode change 100644 => 100755 linden/indra/llplugin/llpluginmessage.cpp mode change 100644 => 100755 linden/indra/llplugin/llpluginmessage.h mode change 100644 => 100755 linden/indra/llplugin/llpluginmessageclasses.h mode change 100644 => 100755 linden/indra/llplugin/llpluginmessagepipe.cpp mode change 100644 => 100755 linden/indra/llplugin/llpluginmessagepipe.h mode change 100644 => 100755 linden/indra/llplugin/llpluginprocesschild.cpp mode change 100644 => 100755 linden/indra/llplugin/llpluginprocesschild.h mode change 100644 => 100755 linden/indra/llplugin/llpluginprocessparent.cpp mode change 100644 => 100755 linden/indra/llplugin/llpluginprocessparent.h mode change 100644 => 100755 linden/indra/llplugin/llpluginsharedmemory.cpp mode change 100644 => 100755 linden/indra/llplugin/llpluginsharedmemory.h mode change 100644 => 100755 linden/indra/llplugin/slplugin/CMakeLists.txt mode change 100644 => 100755 linden/indra/llplugin/slplugin/slplugin.cpp mode change 100644 => 100755 linden/indra/llplugin/slplugin/slplugin_info.plist mode change 100644 => 100755 linden/indra/media_plugins/CMakeLists.txt mode change 100644 => 100755 linden/indra/media_plugins/base/CMakeLists.txt mode change 100644 => 100755 linden/indra/media_plugins/base/media_plugin_base.cpp mode change 100644 => 100755 linden/indra/media_plugins/base/media_plugin_base.exp mode change 100644 => 100755 linden/indra/media_plugins/base/media_plugin_base.h mode change 100644 => 100755 linden/indra/media_plugins/example/CMakeLists.txt mode change 100644 => 100755 linden/indra/media_plugins/example/media_plugin_example.cpp mode change 100644 => 100755 linden/indra/media_plugins/gstreamer010/CMakeLists.txt mode change 100644 => 100755 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h mode change 100644 => 100755 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp mode change 100644 => 100755 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h mode change 100644 => 100755 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc mode change 100644 => 100755 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc mode change 100644 => 100755 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h mode change 100644 => 100755 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp mode change 100644 => 100755 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h mode change 100644 => 100755 linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp mode change 100644 => 100755 linden/indra/media_plugins/quicktime/CMakeLists.txt mode change 100644 => 100755 linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp mode change 100644 => 100755 linden/indra/media_plugins/webkit/media_plugin_webkit.cpp (limited to 'linden') diff --git a/linden/indra/llplugin/CMakeLists.txt b/linden/indra/llplugin/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/linden/indra/llplugin/llpluginclassmedia.cpp b/linden/indra/llplugin/llpluginclassmedia.cpp old mode 100644 new mode 100755 index a6f6f30..2e8bf3f --- a/linden/indra/llplugin/llpluginclassmedia.cpp +++ b/linden/indra/llplugin/llpluginclassmedia.cpp @@ -2,9 +2,10 @@ * @file llpluginclassmedia.cpp * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #include "linden_common.h" @@ -36,6 +38,8 @@ #include "llpluginclassmedia.h" #include "llpluginmessageclasses.h" +#include "llqtwebkit.h" + static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256; static int nextPowerOf2( int value ) @@ -101,6 +105,8 @@ void LLPluginClassMedia::reset() mSetMediaHeight = -1; mRequestedMediaWidth = 0; mRequestedMediaHeight = 0; + mRequestedTextureWidth = 0; + mRequestedTextureHeight = 0; mFullMediaWidth = 0; mFullMediaHeight = 0; mTextureWidth = 0; @@ -123,7 +129,8 @@ void LLPluginClassMedia::reset() mCanPaste = false; mMediaName.clear(); mMediaDescription.clear(); - + mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f); + // media_browser class mNavigateURI.clear(); mNavigateResultCode = -1; @@ -132,6 +139,9 @@ void LLPluginClassMedia::reset() mHistoryForwardAvailable = false; mStatusText.clear(); mProgressPercent = 0; + mClickURL.clear(); + mClickTarget.clear(); + mClickTargetType = TARGET_NONE; // media_time class mCurrentTime = 0.0f; @@ -233,6 +243,10 @@ void LLPluginClassMedia::idle(void) message.setValueS32("height", mRequestedMediaHeight); message.setValueS32("texture_width", mRequestedTextureWidth); message.setValueS32("texture_height", mRequestedTextureHeight); + message.setValueReal("background_r", mBackgroundColor.mV[VX]); + message.setValueReal("background_g", mBackgroundColor.mV[VY]); + message.setValueReal("background_b", mBackgroundColor.mV[VZ]); + message.setValueReal("background_a", mBackgroundColor.mV[VW]); mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue. LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL; @@ -370,7 +384,7 @@ bool LLPluginClassMedia::textureValid(void) bool LLPluginClassMedia::getDirty(LLRect *dirty_rect) { - bool result = !mDirtyRect.isNull(); + bool result = !mDirtyRect.isNull();//awfixme isEmpty(); if(dirty_rect != NULL) { @@ -458,7 +472,7 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int sendMessage(message); } -bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers) +bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data) { bool result = true; @@ -515,6 +529,7 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie message.setValueS32("key", key_code); message.setValue("modifiers", translateModifiers(modifiers)); + message.setValueLLSD("native_key_data", native_key_data); sendMessage(message); } @@ -533,12 +548,13 @@ void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers) sendMessage(message); } -bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers) +bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event"); message.setValue("text", text); message.setValue("modifiers", translateModifiers(modifiers)); + message.setValueLLSD("native_key_data", native_key_data); sendMessage(message); @@ -663,6 +679,26 @@ void LLPluginClassMedia::paste() sendMessage(message); } +LLPluginClassMedia::ETargetType getTargetTypeFromLLQtWebkit(int target_type) +{ + // convert a LinkTargetType value from llqtwebkit to an ETargetType + // so that we don't expose the llqtwebkit header in viewer code + switch (target_type) + { + case LLQtWebKit::LTT_TARGET_NONE: + return LLPluginClassMedia::TARGET_NONE; + + case LLQtWebKit::LTT_TARGET_BLANK: + return LLPluginClassMedia::TARGET_BLANK; + + case LLQtWebKit::LTT_TARGET_EXTERNAL: + return LLPluginClassMedia::TARGET_EXTERNAL; + + default: + return LLPluginClassMedia::TARGET_OTHER; + } +} + /* virtual */ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { @@ -710,7 +746,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) newDirtyRect.mBottom = temp; } - if(mDirtyRect.isNull()) + if(mDirtyRect.isNull())//awfixme isEmpty()) { mDirtyRect = newDirtyRect; } @@ -915,12 +951,15 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { mClickURL = message.getValue("uri"); mClickTarget = message.getValue("target"); + U32 target_type = message.getValueU32("target_type"); + mClickTargetType = ::getTargetTypeFromLLQtWebkit(target_type); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF); } else if(message_name == "click_nofollow") { mClickURL = message.getValue("uri"); mClickTarget.clear(); + mClickTargetType = TARGET_NONE; mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW); } else diff --git a/linden/indra/llplugin/llpluginclassmedia.h b/linden/indra/llplugin/llpluginclassmedia.h old mode 100644 new mode 100755 index c45010e..ab54348 --- a/linden/indra/llplugin/llpluginclassmedia.h +++ b/linden/indra/llplugin/llpluginclassmedia.h @@ -2,9 +2,10 @@ * @file llpluginclassmedia.h * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #ifndef LL_LLPLUGINCLASSMEDIA_H @@ -38,7 +40,7 @@ #include "llrect.h" #include "llpluginclassmediaowner.h" #include <queue> - +#include "v4color.h" class LLPluginClassMedia : public LLPluginProcessParentOwner { @@ -85,6 +87,8 @@ public: void setSize(int width, int height); void setAutoScale(bool auto_scale); + void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; }; + // Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent. // This will initially be false, and will also be false for some time after setSize while the resize is processed. // Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values @@ -111,12 +115,12 @@ public: KEY_EVENT_REPEAT }EKeyEventType; - bool keyEvent(EKeyEventType type, int key_code, MASK modifiers); + bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data); void scrollEvent(int x, int y, MASK modifiers); // Text may be unicode (utf8 encoded) - bool textInput(const std::string &text, MASK modifiers); + bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data); void loadURI(const std::string &uri); @@ -211,6 +215,17 @@ public: // This is valid after MEDIA_EVENT_CLICK_LINK_HREF std::string getClickTarget() const { return mClickTarget; }; + typedef enum + { + TARGET_NONE, // empty href target string + TARGET_BLANK, // target to open link in user's preferred browser + TARGET_EXTERNAL, // target to open link in external browser + TARGET_OTHER // nonempty and unsupported target type + }ETargetType; + + // This is valid after MEDIA_EVENT_CLICK_LINK_HREF + ETargetType getClickTargetType() const { return mClickTargetType; }; + std::string getMediaName() const { return mMediaName; }; std::string getMediaDescription() const { return mMediaDescription; }; @@ -327,6 +342,8 @@ protected: std::string mMediaName; std::string mMediaDescription; + LLColor4 mBackgroundColor; + ///////////////////////////////////////// // media_browser class std::string mNavigateURI; @@ -339,6 +356,7 @@ protected: std::string mLocation; std::string mClickURL; std::string mClickTarget; + ETargetType mClickTargetType; ///////////////////////////////////////// // media_time class diff --git a/linden/indra/llplugin/llpluginclassmediaowner.h b/linden/indra/llplugin/llpluginclassmediaowner.h old mode 100644 new mode 100755 index 182eb92..239f692 --- a/linden/indra/llplugin/llpluginclassmediaowner.h +++ b/linden/indra/llplugin/llpluginclassmediaowner.h @@ -2,9 +2,10 @@ * @file llpluginclassmediaowner.h * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #ifndef LL_LLPLUGINCLASSMEDIAOWNER_H diff --git a/linden/indra/llplugin/llplugininstance.cpp b/linden/indra/llplugin/llplugininstance.cpp old mode 100644 new mode 100755 index 5185b36..ce10cb6 --- a/linden/indra/llplugin/llplugininstance.cpp +++ b/linden/indra/llplugin/llplugininstance.cpp @@ -2,9 +2,10 @@ * @file llplugininstance.cpp * @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #include "linden_common.h" diff --git a/linden/indra/llplugin/llplugininstance.h b/linden/indra/llplugin/llplugininstance.h old mode 100644 new mode 100755 index 0b53b5f..baa51cc --- a/linden/indra/llplugin/llplugininstance.h +++ b/linden/indra/llplugin/llplugininstance.h @@ -1,10 +1,10 @@ /** * @file llplugininstance.h - * @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +28,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #ifndef LL_LLPLUGININSTANCE_H diff --git a/linden/indra/llplugin/llpluginmessage.cpp b/linden/indra/llplugin/llpluginmessage.cpp old mode 100644 new mode 100755 index 67ac995..8efc774 --- a/linden/indra/llplugin/llpluginmessage.cpp +++ b/linden/indra/llplugin/llpluginmessage.cpp @@ -2,9 +2,10 @@ * @file llpluginmessage.cpp * @brief LLPluginMessage encapsulates the serialization/deserialization of messages passed to and from plugins. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #include "linden_common.h" diff --git a/linden/indra/llplugin/llpluginmessage.h b/linden/indra/llplugin/llpluginmessage.h old mode 100644 new mode 100755 index 8bcb896..82eb89f --- a/linden/indra/llplugin/llpluginmessage.h +++ b/linden/indra/llplugin/llpluginmessage.h @@ -1,10 +1,10 @@ /** * @file llpluginmessage.h - * @brief LLPluginMessage encapsulates the serialization/deserialization of messages passed to and from plugins. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +28,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #ifndef LL_LLPLUGINMESSAGE_H diff --git a/linden/indra/llplugin/llpluginmessageclasses.h b/linden/indra/llplugin/llpluginmessageclasses.h old mode 100644 new mode 100755 index 1f60d5e..9a39e98 --- a/linden/indra/llplugin/llpluginmessageclasses.h +++ b/linden/indra/llplugin/llpluginmessageclasses.h @@ -2,9 +2,10 @@ * @file llpluginmessageclasses.h * @brief This file defines the versions of existing message classes for LLPluginMessage. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #ifndef LL_LLPLUGINMESSAGECLASSES_H diff --git a/linden/indra/llplugin/llpluginmessagepipe.cpp b/linden/indra/llplugin/llpluginmessagepipe.cpp old mode 100644 new mode 100755 index 209f49f..85ed227 --- a/linden/indra/llplugin/llpluginmessagepipe.cpp +++ b/linden/indra/llplugin/llpluginmessagepipe.cpp @@ -2,9 +2,10 @@ * @file llpluginmessagepipe.cpp * @brief Classes that implement connections from the plugin system to pipes/pumps. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #include "linden_common.h" @@ -303,7 +305,14 @@ void LLPluginMessagePipe::processInput(void) while((delim = mInput.find(MESSAGE_DELIMITER, start)) != std::string::npos) { // Let the owner process this message - mOwner->receiveMessageRaw(mInput.substr(start, delim - start)); + if (mOwner) + { + mOwner->receiveMessageRaw(mInput.substr(start, delim - start)); + } + else + { + LL_WARNS("Plugin") << "!mOwner" << LL_ENDL; + } start = delim + 1; } diff --git a/linden/indra/llplugin/llpluginmessagepipe.h b/linden/indra/llplugin/llpluginmessagepipe.h old mode 100644 new mode 100755 index 9bf1781..63fd569 --- a/linden/indra/llplugin/llpluginmessagepipe.h +++ b/linden/indra/llplugin/llpluginmessagepipe.h @@ -2,9 +2,10 @@ * @file llpluginmessagepipe.h * @brief Classes that implement connections from the plugin system to pipes/pumps. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #ifndef LL_LLPLUGINMESSAGEPIPE_H diff --git a/linden/indra/llplugin/llpluginprocesschild.cpp b/linden/indra/llplugin/llpluginprocesschild.cpp old mode 100644 new mode 100755 index 9b5eafc..e13376f --- a/linden/indra/llplugin/llpluginprocesschild.cpp +++ b/linden/indra/llplugin/llpluginprocesschild.cpp @@ -2,9 +2,10 @@ * @file llpluginprocesschild.cpp * @brief LLPluginProcessChild handles the child side of the external-process plugin API. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #include "linden_common.h" @@ -42,6 +44,7 @@ static const F32 PLUGIN_IDLE_SECONDS = 1.0f / 100.0f; // Each call to idle will LLPluginProcessChild::LLPluginProcessChild() { + mState = STATE_UNINITIALIZED; mInstance = NULL; mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz @@ -53,8 +56,14 @@ LLPluginProcessChild::~LLPluginProcessChild() if(mInstance != NULL) { sendMessageToPlugin(LLPluginMessage("base", "cleanup")); - delete mInstance; - mInstance = NULL; + + // IMPORTANT: under some (unknown) circumstances the apr_dso_unload() triggered when mInstance is deleted + // appears to fail and lock up which means that a given instance of the slplugin process never exits. + // This is bad, especially when users try to update their version of SL - it fails because the slplugin + // process as well as a bunch of plugin specific files are locked and cannot be overwritten. + exit( 0 ); + //delete mInstance; + //mInstance = NULL; } } @@ -270,14 +279,21 @@ bool LLPluginProcessChild::isDone(void) void LLPluginProcessChild::sendMessageToPlugin(const LLPluginMessage &message) { - std::string buffer = message.generate(); - - LL_DEBUGS("Plugin") << "Sending to plugin: " << buffer << LL_ENDL; - LLTimer elapsed; - - mInstance->sendMessage(buffer); - - mCPUElapsed += elapsed.getElapsedTimeF64(); + if (mInstance) + { + std::string buffer = message.generate(); + + LL_DEBUGS("Plugin") << "Sending to plugin: " << buffer << LL_ENDL; + LLTimer elapsed; + + mInstance->sendMessage(buffer); + + mCPUElapsed += elapsed.getElapsedTimeF64(); + } + else + { + LL_WARNS("Plugin") << "mInstance == NULL" << LL_ENDL; + } } void LLPluginProcessChild::sendMessageToParent(const LLPluginMessage &message) @@ -352,6 +368,7 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) else { LL_WARNS("Plugin") << "Couldn't create a shared memory segment!" << LL_ENDL; + delete region; } } diff --git a/linden/indra/llplugin/llpluginprocesschild.h b/linden/indra/llplugin/llpluginprocesschild.h old mode 100644 new mode 100755 index 16a1ae8..8e9579e --- a/linden/indra/llplugin/llpluginprocesschild.h +++ b/linden/indra/llplugin/llpluginprocesschild.h @@ -2,9 +2,10 @@ * @file llpluginprocesschild.h * @brief LLPluginProcessChild handles the child side of the external-process plugin API. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #ifndef LL_LLPLUGINPROCESSCHILD_H @@ -88,8 +90,9 @@ private: STATE_ERROR, // generic bailout state STATE_DONE // state machine will sit in this state after either error or normal termination. }; - EState mState; void setState(EState state); + + EState mState; LLHost mLauncherHost; LLSocket::ptr_t mSocket; diff --git a/linden/indra/llplugin/llpluginprocessparent.cpp b/linden/indra/llplugin/llpluginprocessparent.cpp old mode 100644 new mode 100755 index bd36d11..9b8ea8b --- a/linden/indra/llplugin/llpluginprocessparent.cpp +++ b/linden/indra/llplugin/llpluginprocessparent.cpp @@ -2,9 +2,10 @@ * @file llpluginprocessparent.cpp * @brief LLPluginProcessParent handles the parent side of the external-process plugin API. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #include "linden_common.h" @@ -49,11 +51,13 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner) mOwner = owner; mBoundPort = 0; mState = STATE_UNINITIALIZED; + mSleepTime = 0.0; + mCPUUsage = 0.0; mDisableTimeout = false; mDebug = false; mPluginLaunchTimeout = 60.0f; - mPluginLockupTimeout = 30.0f; + mPluginLockupTimeout = 15.0f; // Don't start the timer here -- start it when we actually launch the plugin process. mHeartbeat.stop(); diff --git a/linden/indra/llplugin/llpluginprocessparent.h b/linden/indra/llplugin/llpluginprocessparent.h old mode 100644 new mode 100755 index 00c60b5..6dbe0c1 --- a/linden/indra/llplugin/llpluginprocessparent.h +++ b/linden/indra/llplugin/llpluginprocessparent.h @@ -2,9 +2,10 @@ * @file llpluginprocessparent.h * @brief LLPluginProcessParent handles the parent side of the external-process plugin API. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #ifndef LL_LLPLUGINPROCESSPARENT_H diff --git a/linden/indra/llplugin/llpluginsharedmemory.cpp b/linden/indra/llplugin/llpluginsharedmemory.cpp old mode 100644 new mode 100755 index c946619..a475f12 --- a/linden/indra/llplugin/llpluginsharedmemory.cpp +++ b/linden/indra/llplugin/llpluginsharedmemory.cpp @@ -1,10 +1,11 @@ /** * @file llpluginsharedmemory.cpp - * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API. + * LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #include "linden_common.h" diff --git a/linden/indra/llplugin/llpluginsharedmemory.h b/linden/indra/llplugin/llpluginsharedmemory.h old mode 100644 new mode 100755 index 2dc550e..1d23cbe --- a/linden/indra/llplugin/llpluginsharedmemory.h +++ b/linden/indra/llplugin/llpluginsharedmemory.h @@ -1,10 +1,10 @@ /** * @file llpluginsharedmemory.h - * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +28,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #ifndef LL_LLPLUGINSHAREDMEMORY_H diff --git a/linden/indra/llplugin/slplugin/CMakeLists.txt b/linden/indra/llplugin/slplugin/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/linden/indra/llplugin/slplugin/slplugin.cpp b/linden/indra/llplugin/slplugin/slplugin.cpp old mode 100644 new mode 100755 index fa3924b..526734a --- a/linden/indra/llplugin/slplugin/slplugin.cpp +++ b/linden/indra/llplugin/slplugin/slplugin.cpp @@ -1,10 +1,12 @@ -/** +/** * @file slplugin.cpp * @brief Loader shell for plugins, intended to be launched by the plugin host application, which directly loads a plugin dynamic library. * + * @cond + * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +30,8 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * + * @endcond */ @@ -49,15 +53,15 @@ /* On Mac OS, since we call WaitNextEvent, this process will show up in the dock unless we set the LSBackgroundOnly flag in the Info.plist. - + Normally non-bundled binaries don't have an info.plist file, but it's possible to embed one in the binary by adding this to the linker flags: - + -sectcreate __TEXT __info_plist /path/to/slplugin_info.plist - + which means adding this to the gcc flags: - + -Wl,-sectcreate,__TEXT,__info_plist,/path/to/slplugin_info.plist - + */ #if LL_DARWIN || LL_LINUX @@ -68,7 +72,7 @@ static void crash_handler(int sig) // TODO: add our own crash reporting _exit(1); } -#endif +#endif #if LL_WINDOWS #include <windows.h> @@ -81,7 +85,7 @@ LONG WINAPI myWin32ExceptionHandler( struct _EXCEPTION_POINTERS* exception_infop //std::cerr << "intercepted an unhandled exception and will exit immediately." << std::endl; // TODO: replace exception handler before we exit? - return EXCEPTION_EXECUTE_HANDLER; + return EXCEPTION_EXECUTE_HANDLER; } // Taken from : http://blog.kalmbachnet.de/?postid=75 @@ -153,7 +157,7 @@ bool checkExceptionHandler() if (prev_filter == NULL) { ok = FALSE; - if (myWin32ExceptionHandler == NULL) + if (NULL == myWin32ExceptionHandler) { LL_WARNS("AppInit") << "Exception handler uninitialized." << LL_ENDL; } @@ -167,7 +171,7 @@ bool checkExceptionHandler() } #endif -// If this application on Windows platform is a console application, a console is always +// If this application on Windows platform is a console application, a console is always // created which is bad. Making it a Windows "application" via CMake settings but not // adding any code to explicitly create windows does the right thing. #if LL_WINDOWS @@ -178,7 +182,7 @@ int main(int argc, char **argv) { ll_init_apr(); - // Set up llerror logging + // Set up llerror logging { LLError::initForApplication("."); LLError::setDefaultLevel(LLError::LEVEL_INFO); @@ -191,14 +195,14 @@ int main(int argc, char **argv) { LL_ERRS("slplugin") << "usage: " << "SLPlugin" << " launcher_port" << LL_ENDL; }; - + U32 port = 0; if(!LLStringUtil::convertToU32(lpCmdLine, port)) { LL_ERRS("slplugin") << "port number must be numeric" << LL_ENDL; }; - // Insert our exception handler into the system so this plugin doesn't + // Insert our exception handler into the system so this plugin doesn't // display a crash message if something bad happens. The host app will // see the missing heartbeat and log appropriately. initExceptionHandler(); @@ -207,7 +211,7 @@ int main(int argc, char **argv) { LL_ERRS("slplugin") << "usage: " << argv[0] << " launcher_port" << LL_ENDL; } - + U32 port = 0; if(!LLStringUtil::convertToU32(argv[1], port)) { @@ -228,17 +232,17 @@ int main(int argc, char **argv) LLPluginProcessChild *plugin = new LLPluginProcessChild(); plugin->init(port); - + LLTimer timer; timer.start(); #if LL_WINDOWS checkExceptionHandler(); #endif - + while(!plugin->isDone()) { - timer.reset(); + timer.reset(); plugin->idle(); #if LL_DARWIN { @@ -249,7 +253,7 @@ int main(int argc, char **argv) #endif F64 elapsed = timer.getElapsedTimeF64(); F64 remaining = plugin->getSleepTime() - elapsed; - + if(remaining <= 0.0f) { // We've already used our full allotment. @@ -262,26 +266,26 @@ int main(int argc, char **argv) { // LL_INFOS("slplugin") << "elapsed = " << elapsed * 1000.0f << " ms, remaining = " << remaining * 1000.0f << " ms, sleeping for " << remaining * 1000.0f << " ms" << LL_ENDL; -// timer.reset(); - +// timer.reset(); + // This also services the network as needed. plugin->sleep(remaining); - + // LL_INFOS("slplugin") << "slept for "<< timer.getElapsedTimeF64() * 1000.0f << " ms" << LL_ENDL; } #if LL_WINDOWS // More agressive checking of interfering exception handlers. - // Doesn't appear to be required so far - even for plugins - // that do crash with a single call to the intercept + // Doesn't appear to be required so far - even for plugins + // that do crash with a single call to the intercept // exception handler such as QuickTime. //checkExceptionHandler(); #endif } delete plugin; - - ll_cleanup_apr(); + + ll_cleanup_apr(); return 0; } diff --git a/linden/indra/llplugin/slplugin/slplugin_info.plist b/linden/indra/llplugin/slplugin/slplugin_info.plist old mode 100644 new mode 100755 diff --git a/linden/indra/llwindow/llwindow.h b/linden/indra/llwindow/llwindow.h index 14759cc..2e96294 100644 --- a/linden/indra/llwindow/llwindow.h +++ b/linden/indra/llwindow/llwindow.h @@ -37,6 +37,7 @@ #include "llcoord.h" #include "llstring.h" #include "llcursortypes.h" +#include "llsd.h" class LLSplashScreen; @@ -208,6 +209,9 @@ public: static std::vector<std::string> getDynamicFallbackFontList(); + // Provide native key event data + virtual LLSD getNativeKeyData() { return LLSD::emptyMap(); } + protected: LLWindow(BOOL fullscreen, U32 flags); virtual ~LLWindow() {} diff --git a/linden/indra/llwindow/llwindowmacosx.cpp b/linden/indra/llwindow/llwindowmacosx.cpp index 7efba51..430687b 100644 --- a/linden/indra/llwindow/llwindowmacosx.cpp +++ b/linden/indra/llwindow/llwindowmacosx.cpp @@ -3217,7 +3217,7 @@ void LLWindowMacOSX::ShellEx(const std::string& command) } } -BOOL LLWindowMacOSX::dialog_color_picker ( F32 *r, F32 *g, F32 *b) +BOOL LLWindowMacOSX::dialog_color_picker( F32 *r, F32 *g, F32 *b) { BOOL retval = FALSE; OSErr error = noErr; diff --git a/linden/indra/llwindow/llwindowmacosx.h b/linden/indra/llwindow/llwindowmacosx.h index 9e87e9f..92c73e8 100644 --- a/linden/indra/llwindow/llwindowmacosx.h +++ b/linden/indra/llwindow/llwindowmacosx.h @@ -117,6 +117,10 @@ public: static std::vector<std::string> getDynamicFallbackFontList(); + // Provide native key event data + /*virtual*/ LLSD getNativeKeyData(); + + protected: LLWindowMacOSX( const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags, diff --git a/linden/indra/llwindow/llwindowsdl.cpp b/linden/indra/llwindow/llwindowsdl.cpp index bf339f2..9310ff5 100644 --- a/linden/indra/llwindow/llwindowsdl.cpp +++ b/linden/indra/llwindow/llwindowsdl.cpp @@ -250,6 +250,10 @@ LLWindowSDL::LLWindowSDL(const std::string& title, S32 x, S32 y, S32 width, #if LL_X11 mFlashing = FALSE; #endif // LL_X11 + + mKeyScanCode = 0; + mKeyVirtualKey = 0; + mKeyModifiers = KMOD_NONE; } static SDL_Surface *Load_BMP_Resource(const char *basename) @@ -2227,7 +2231,40 @@ static void color_changed_callback(GtkWidget *widget, gtk_color_selection_get_current_color(colorsel, colorp); } -BOOL LLWindowSDL::dialog_color_picker ( F32 *r, F32 *g, F32 *b) + +/* + Make the raw keyboard data available - used to poke through to LLQtWebKit so + that Qt/Webkit has access to the virtual keycodes etc. that it needs +*/ +LLSD LLWindowSDL::getNativeKeyData() +{ + LLSD result = LLSD::emptyMap(); + + U32 modifiers = 0; // pretend-native modifiers... oh what a tangled web we weave! + + // we go through so many levels of device abstraction that I can't really guess + // what a plugin under GDK under Qt under SL under SDL under X11 considers + // a 'native' modifier mask. this has been sort of reverse-engineered... they *appear* + // to match GDK consts, but that may be co-incidence. + modifiers |= (mKeyModifiers & KMOD_LSHIFT) ? 0x0001 : 0; + modifiers |= (mKeyModifiers & KMOD_RSHIFT) ? 0x0001 : 0;// munge these into the same shift + modifiers |= (mKeyModifiers & KMOD_CAPS) ? 0x0002 : 0; + modifiers |= (mKeyModifiers & KMOD_LCTRL) ? 0x0004 : 0; + modifiers |= (mKeyModifiers & KMOD_RCTRL) ? 0x0004 : 0;// munge these into the same ctrl + modifiers |= (mKeyModifiers & KMOD_LALT) ? 0x0008 : 0;// untested + modifiers |= (mKeyModifiers & KMOD_RALT) ? 0x0008 : 0;// untested + // *todo: test ALTs - I don't have a case for testing these. Do you? + // *todo: NUM? - I don't care enough right now (and it's not a GDK modifier). + + result["scan_code"] = (S32)mKeyScanCode; + result["virtual_key"] = (S32)mKeyVirtualKey; + result["modifiers"] = (S32)modifiers; + + return result; +} + + +BOOL LLWindowSDL::dialog_color_picker( F32 *r, F32 *g, F32 *b) { BOOL rtn = FALSE; diff --git a/linden/indra/llwindow/llwindowsdl.h b/linden/indra/llwindow/llwindowsdl.h index 39a6007..37b0835 100644 --- a/linden/indra/llwindow/llwindowsdl.h +++ b/linden/indra/llwindow/llwindowsdl.h @@ -154,6 +154,8 @@ protected: BOOL ignore_pixel_depth, U32 fsaa_samples); ~LLWindowSDL(); + /*virtual*/ LLSD getNativeKeyData(); + void initCursors(); void quitCursors(); BOOL isValid(); @@ -206,12 +208,17 @@ protected: friend class LLWindowManager; -#if LL_X11 + private: +#if LL_X11 void x11_set_urgent(BOOL urgent); BOOL mFlashing; LLTimer mFlashTimer; #endif //LL_X11 + U32 mKeyScanCode; + U32 mKeyVirtualKey; + SDLMod mKeyModifiers; + }; diff --git a/linden/indra/llwindow/llwindowwin32.cpp b/linden/indra/llwindow/llwindowwin32.cpp index e47cab4..12a488a 100644 --- a/linden/indra/llwindow/llwindowwin32.cpp +++ b/linden/indra/llwindow/llwindowwin32.cpp @@ -3052,6 +3052,19 @@ void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url ) */ } +/* + Make the raw keyboard data available - used to poke through to LLQtWebKit so + that Qt/Webkit has access to the virtual keycodes etc. that it needs +*/ +LLSD LLWindowWin32::getNativeKeyData() +{ + LLSD result = LLSD::emptyMap(); + + result["scan_code"] = (S32)mKeyScanCode; + result["virtual_key"] = (S32)mKeyVirtualKey; + + return result; +} BOOL LLWindowWin32::dialog_color_picker ( F32 *r, F32 *g, F32 *b ) { diff --git a/linden/indra/llwindow/llwindowwin32.h b/linden/indra/llwindow/llwindowwin32.h index cc95993..0e40115 100644 --- a/linden/indra/llwindow/llwindowwin32.h +++ b/linden/indra/llwindow/llwindowwin32.h @@ -128,7 +128,7 @@ protected: HCURSOR loadColorCursor(LPCTSTR name); BOOL isValid(); void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size); - + LLSD getNativeKeyData(); // Changes display resolution. Returns true if successful BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh); @@ -208,6 +208,12 @@ protected: LLPreeditor *mPreeditor; + + + U32 mKeyCharCode; + U32 mKeyScanCode; + U32 mKeyVirtualKey; + friend class LLWindowManager; }; diff --git a/linden/indra/media_plugins/CMakeLists.txt b/linden/indra/media_plugins/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/linden/indra/media_plugins/base/CMakeLists.txt b/linden/indra/media_plugins/base/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/linden/indra/media_plugins/base/media_plugin_base.cpp b/linden/indra/media_plugins/base/media_plugin_base.cpp old mode 100644 new mode 100755 index 4d5e374..baae68c --- a/linden/indra/media_plugins/base/media_plugin_base.cpp +++ b/linden/indra/media_plugins/base/media_plugin_base.cpp @@ -4,9 +4,10 @@ * * All plugins should be a subclass of MediaPluginBase. * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -30,6 +31,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #include "linden_common.h" diff --git a/linden/indra/media_plugins/base/media_plugin_base.exp b/linden/indra/media_plugins/base/media_plugin_base.exp old mode 100644 new mode 100755 index 1e27d1f..d8c7bb7 --- a/linden/indra/media_plugins/base/media_plugin_base.exp +++ b/linden/indra/media_plugins/base/media_plugin_base.exp @@ -1 +1,2 @@ _LLPluginInitEntryPoint + diff --git a/linden/indra/media_plugins/base/media_plugin_base.h b/linden/indra/media_plugins/base/media_plugin_base.h old mode 100644 new mode 100755 index 24198af..8311e66 --- a/linden/indra/media_plugins/base/media_plugin_base.h +++ b/linden/indra/media_plugins/base/media_plugin_base.h @@ -2,9 +2,10 @@ * @file media_plugin_base.h * @brief Media plugin base class for LLMedia API plugin system * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #include "linden_common.h" diff --git a/linden/indra/media_plugins/example/CMakeLists.txt b/linden/indra/media_plugins/example/CMakeLists.txt old mode 100644 new mode 100755 index b074a1d..6d14c1b --- a/linden/indra/media_plugins/example/CMakeLists.txt +++ b/linden/indra/media_plugins/example/CMakeLists.txt @@ -14,7 +14,7 @@ include(PluginAPI) include(MediaPluginBase) include(FindOpenGL) -include(ExamplePlugin) +#awfixme include(ExamplePlugin) include_directories( ${LLPLUGIN_INCLUDE_DIRS} diff --git a/linden/indra/media_plugins/example/media_plugin_example.cpp b/linden/indra/media_plugins/example/media_plugin_example.cpp old mode 100644 new mode 100755 index 99e0199..83abae0 --- a/linden/indra/media_plugins/example/media_plugin_example.cpp +++ b/linden/indra/media_plugins/example/media_plugin_example.cpp @@ -2,31 +2,34 @@ * @file media_plugin_example.cpp * @brief Example plugin for LLMedia API plugin system * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ - * - * Copyright (c) 2009, Linden Research, Inc. - * + * + * Copyright (c) 2008-2010, Linden Research, Inc. + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #include "linden_common.h" diff --git a/linden/indra/media_plugins/gstreamer010/CMakeLists.txt b/linden/indra/media_plugins/gstreamer010/CMakeLists.txt old mode 100644 new mode 100755 index a3a32d8..3b73e04 --- a/linden/indra/media_plugins/gstreamer010/CMakeLists.txt +++ b/linden/indra/media_plugins/gstreamer010/CMakeLists.txt @@ -42,12 +42,12 @@ set(media_plugin_gstreamer010_HEADER_FILES llmediaimplgstreamertriviallogging.h ) -#awfixme if (${CXX_VERSION_NUMBER} MATCHES "4[23].") +if (${CXX_VERSION_NUMBER} MATCHES "4[23].") # Work around a bad interaction between broken gstreamer headers and # g++ 4.3's increased strictness. set_source_files_properties(llmediaimplgstreamervidplug.cpp PROPERTIES COMPILE_FLAGS -Wno-write-strings) -#awfixme endif (${CXX_VERSION_NUMBER} MATCHES "4[23].") +endif (${CXX_VERSION_NUMBER} MATCHES "4[23].") add_library(media_plugin_gstreamer010 SHARED diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h old mode 100644 new mode 100755 index ef41736..6920c3b --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h @@ -3,9 +3,10 @@ * @author Tofu Linden * @brief implementation that supports media playback via GStreamer. * + * @cond * $LicenseInfo:firstyear=2007&license=viewergpl$ * - * Copyright (c) 2007-2009, Linden Research, Inc. + * Copyright (c) 2007-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -29,6 +30,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ // header guard diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp old mode 100644 new mode 100755 index cc52232..28960ac --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp @@ -2,9 +2,10 @@ * @file llmediaimplgstreamer_syms.cpp * @brief dynamic GStreamer symbol-grabbing code * + * @cond * $LicenseInfo:firstyear=2007&license=viewergpl$ * - * Copyright (c) 2007-2009, Linden Research, Inc. + * Copyright (c) 2007-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #if LL_GSTREAMER010_ENABLED diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h old mode 100644 new mode 100755 index ee7473d..7955898 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h @@ -2,9 +2,10 @@ * @file llmediaimplgstreamer_syms.h * @brief dynamic GStreamer symbol-grabbing code * + * @cond * $LicenseInfo:firstyear=2007&license=viewergpl$ * - * Copyright (c) 2007-2009, Linden Research, Inc. + * Copyright (c) 2007-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #include "linden_common.h" diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc old mode 100644 new mode 100755 diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc old mode 100644 new mode 100755 diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h old mode 100644 new mode 100755 index 04976b9..27f0eed --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h @@ -2,9 +2,10 @@ * @file llmediaimplgstreamertriviallogging.h * @brief minimal logging utilities. * + * @cond * $LicenseInfo:firstyear=2009&license=viewergpl$ * - * Copyright (c) 2009, Linden Research, Inc. + * Copyright (c) 2009-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #ifndef __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp old mode 100644 new mode 100755 index ef8ff58..2b10a2a --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp @@ -1,10 +1,11 @@ /** - * @file llmediaimplgstreamervidplug.cpp + * @file llmediaimplgstreamervidplug.h * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl * + * @cond * $LicenseInfo:firstyear=2007&license=viewergpl$ * - * Copyright (c) 2007-2009, Linden Research, Inc. + * Copyright (c) 2007-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #if LL_GSTREAMER010_ENABLED diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h old mode 100644 new mode 100755 index 8cdc72d..fad80cb --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h @@ -2,9 +2,10 @@ * @file llmediaimplgstreamervidplug.h * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl * + * @cond * $LicenseInfo:firstyear=2007&license=viewergpl$ * - * Copyright (c) 2007-2009, Linden Research, Inc. + * Copyright (c) 2007-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #ifndef __GST_SLVIDEO_H__ diff --git a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp old mode 100644 new mode 100755 index 5b3152d..82e6fdc --- a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp +++ b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp @@ -2,9 +2,10 @@ * @file media_plugin_gstreamer010.cpp * @brief GStreamer-0.10 plugin for LLMedia API plugin system * + * @cond * $LicenseInfo:firstyear=2007&license=viewergpl$ * - * Copyright (c) 2007-2009, Linden Research, Inc. + * Copyright (c) 2007-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #include "linden_common.h" diff --git a/linden/indra/media_plugins/quicktime/CMakeLists.txt b/linden/indra/media_plugins/quicktime/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp old mode 100644 new mode 100755 index 6c8c41d..9b4c531 --- a/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -1,10 +1,11 @@ -/** +/** * @file media_plugin_quicktime.cpp * @brief QuickTime plugin for LLMedia API plugin system * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ #include "linden_common.h" @@ -102,14 +104,14 @@ private: message.setValueS32("top", top); message.setValueS32("right", right); message.setValueS32("bottom", bottom); - + if(mMovieHandle) { message.setValueReal("current_time", getCurrentTime()); message.setValueReal("duration", getDuration()); message.setValueReal("current_rate", Fix2X(GetMovieRate(mMovieHandle))); } - + sendMessage(message); } @@ -117,16 +119,16 @@ private: static Rect rectFromSize(int width, int height) { Rect result; - + result.left = 0; result.top = 0; result.right = width; result.bottom = height; - + return result; } - + Fixed getPlayRate(void) { Fixed result; @@ -145,25 +147,27 @@ private: { result = X2Fix(mPlayRate); } - + return result; } - + void load( const std::string url ) { + if ( url.empty() ) return; - + // Stop and unload any existing movie before starting another one. unload(); - + setStatus(STATUS_LOADING); - + //In case std::string::c_str() makes a copy of the url data, //make sure there is memory to hold it before allocating memory for handle. //if fails, NewHandleClear(...) should return NULL. const char* url_string = url.c_str() ; Handle handle = NewHandleClear( ( Size )( url.length() + 1 ) ); + if ( NULL == handle || noErr != MemError() || NULL == *handle ) { setStatus(STATUS_ERROR); @@ -202,7 +206,7 @@ private: SetMovieDrawingCompleteProc( mMovieHandle, movieDrawingCallWhenChanged, movieDrawingCompleteCallback, ( long )this ); setStatus(STATUS_LOADED); - + sizeChanged(); }; @@ -239,7 +243,7 @@ private: DisposeGWorld( mGWorldHandle ); mGWorldHandle = NULL; }; - + setStatus(STATUS_NONE); return true; @@ -249,7 +253,7 @@ private: { unload(); load( url ); - + return true; }; @@ -257,7 +261,7 @@ private: { if ( ! mMovieHandle ) return false; - + // Check to see whether the movie's natural size has updated { int width, height; @@ -275,14 +279,14 @@ private: //std::cerr << "<--- Sending size change request to application with name: " << mTextureSegmentName << " - size is " << width << " x " << height << std::endl; } } - + // sanitize destination size Rect dest_rect = rectFromSize(mWidth, mHeight); // media depth won't change int depth_bits = mDepth * 8; long rowbytes = mDepth * mTextureWidth; - + GWorldPtr old_gworld_handle = mGWorldHandle; if(mPixels != NULL) @@ -314,7 +318,7 @@ private: { DisposeGWorld( old_gworld_handle ); } - + // Set up the movie display matrix { // scale movie to fit rect and invert vertically to match opengl image format @@ -327,7 +331,7 @@ private: ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) ); SetMovieMatrix( mMovieHandle, &transform ); } - + // update movie controller if ( mMovieController ) { @@ -345,7 +349,6 @@ private: return true; } - static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref ) { Boolean result = false; @@ -355,9 +358,9 @@ private: switch( action ) { // handle window resizing - case mcActionControllerSizeChanged: + case mcActionControllerSizeChanged: // Ensure that the movie draws correctly at the new size - self->sizeChanged(); + self->sizeChanged(); break; // Block any movie controller actions that open URLs. @@ -386,6 +389,7 @@ private: // self->updateQuickTime(); // TODO ^^^ + if ( self->mWidth > 0 && self->mHeight > 0 ) self->setDirty( 0, 0, self->mWidth, self->mHeight ); @@ -434,7 +438,7 @@ private: MCDoAction( mMovieController, mcActionPlay, (void*)rate ); rewind(); }; - + MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() ); MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); setStatus(STATUS_PLAYING); @@ -462,7 +466,7 @@ private: if ( mCommand == COMMAND_PAUSE ) { if ( mStatus == STATUS_PLAYING ) - { + { if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) { Fixed rate = X2Fix( 0.0 ); @@ -495,7 +499,7 @@ private: void getMovieNaturalSize(int *movie_width, int *movie_height) { Rect rect; - + GetMovieNaturalBoundsRect( mMovieHandle, &rect ); int width = ( rect.right - rect.left ); @@ -518,7 +522,7 @@ private: *movie_width = width; *movie_height = height; } - + void updateQuickTime(int milliseconds) { if ( ! mMovieHandle ) @@ -721,8 +725,8 @@ private: return false; // allocate some space and grab it - UInt8* item_data = new UInt8( size + 1 ); - memset( item_data, 0, ( size + 1 ) * sizeof( UInt8* ) ); + 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 ); if ( noErr != result ) { @@ -861,7 +865,7 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); #if defined(LL_WINDOWS) // Values for Windows - mDepth = 3; + mDepth = 3; message.setValueU32("format", GL_RGB); message.setValueU32("type", GL_UNSIGNED_BYTE); @@ -870,7 +874,7 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) message.setValueU32("padding", 32 * 3); #else // Values for Mac - mDepth = 4; + mDepth = 4; message.setValueU32("format", GL_BGRA_EXT); #ifdef __BIG_ENDIAN__ message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV ); @@ -891,7 +895,7 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) { // no response is necessary here. F64 time = message_in.getValueReal("time"); - + // Convert time to milliseconds for update() update((int)(time * 1000.0f)); } @@ -905,8 +909,6 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) info.mAddress = message_in.getValuePointer("address"); info.mSize = (size_t)message_in.getValueS32("size"); std::string name = message_in.getValue("name"); - - // std::cerr << "MediaPluginQuickTime::receiveMessage: shared memory added, name: " << name // << ", size: " << info.mSize // << ", address: " << info.mAddress @@ -929,9 +931,9 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) // This is the currently active pixel buffer. Make sure we stop drawing to it. mPixels = NULL; mTextureSegmentName.clear(); - + // Make sure the movie GWorld is no longer pointed at the shared segment. - sizeChanged(); + sizeChanged(); } mSharedSegments.erase(iter); } @@ -988,9 +990,9 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) mTextureHeight = texture_height; mMediaSizeChanging = false; - + sizeChanged(); - + update(); }; }; @@ -999,14 +1001,14 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) { std::string uri = message_in.getValue("uri"); load( uri ); - sendStatus(); + sendStatus(); } else if(message_name == "mouse_event") { std::string event = message_in.getValue("event"); S32 x = message_in.getValueS32("x"); S32 y = message_in.getValueS32("y"); - + if(event == "down") { mouseDown(x, y); @@ -1099,7 +1101,7 @@ MediaPluginQuickTime::~MediaPluginQuickTime() void MediaPluginQuickTime::receiveMessage(const char *message_string) { - // no-op + // no-op } // We're building without quicktime enabled. Just refuse to initialize. diff --git a/linden/indra/media_plugins/webkit/CMakeLists.txt b/linden/indra/media_plugins/webkit/CMakeLists.txt index 54bc364..1c999ba 100644 --- a/linden/indra/media_plugins/webkit/CMakeLists.txt +++ b/linden/indra/media_plugins/webkit/CMakeLists.txt @@ -9,6 +9,7 @@ include(LLPlugin) include(LLMath) include(LLRender) include(LLWindow) +include(UI) include(Linking) include(PluginAPI) include(MediaPluginBase) @@ -50,6 +51,11 @@ set(media_plugin_webkit_LINK_LIBRARIES ${PLUGIN_API_WINDOWS_LIBRARIES} ) +if(LINUX) + list(APPEND media_plugin_webkit_LINK_LIBRARIES + ${UI_LIBRARIES} # for glib/GTK + ) +endif(LINUX) add_library(media_plugin_webkit @@ -93,3 +99,4 @@ if (DARWIN) ) endif (DARWIN) + diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp old mode 100644 new mode 100755 index 91efdae..2e3f06d --- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -2,9 +2,10 @@ * @file media_plugin_webkit.cpp * @brief Webkit plugin for LLMedia API plugin system * + * @cond * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2009, Linden Research, Inc. + * Copyright (c) 2008-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -28,8 +29,9 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * @endcond */ - +#include <iomanip>//FIXME: This is included from elsewhere in SG2.0 #include "llqtwebkit.h" #include "linden_common.h" @@ -50,7 +52,7 @@ #endif #if LL_WINDOWS - // NOTE - This captures the module handle of the dll. This is used below + // *NOTE:Mani - This captures the module handle fo rthe dll. This is used below // to get the path to this dll for webkit initialization. // I don't know how/if this can be done with apr... namespace { HMODULE gModuleHandle;}; @@ -83,6 +85,7 @@ private: INIT_STATE_NAVIGATING, // Browser instance has been set up and initial navigate to about:blank has been issued INIT_STATE_NAVIGATE_COMPLETE, // initial navigate to about:blank has completed INIT_STATE_WAIT_REDRAW, // First real navigate begin has been received, waiting for page changed event to start handling redraws + INIT_STATE_WAIT_COMPLETE, // Waiting for first real navigate complete event INIT_STATE_RUNNING // All initialization gymnastics are complete. }; int mBrowserWindowId; @@ -96,6 +99,9 @@ private: int mLastMouseX; int mLastMouseY; bool mFirstFocus; + F32 mBackgroundR; + F32 mBackgroundG; + F32 mBackgroundB; void setInitState(int state) { @@ -121,7 +127,7 @@ private: } } - if ( (mInitState == INIT_STATE_RUNNING) && mNeedsUpdate ) + if ( (mInitState > INIT_STATE_WAIT_REDRAW) && mNeedsUpdate ) { const unsigned char* browser_pixels = LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId ); @@ -170,8 +176,17 @@ private: } std::string application_dir = std::string( cwd ); +#if LL_DARWIN + // When running under the Xcode debugger, there's a setting called "Break on Debugger()/DebugStr()" which defaults to being turned on. + // This causes the environment variable USERBREAK to be set to 1, which causes these legacy calls to break into the debugger. + // This wouldn't cause any problems except for the fact that the current release version of the Flash plugin has a call to Debugger() in it + // which gets hit when the plugin is probed by webkit. + // Unsetting the environment variable here works around this issue. + unsetenv("USERBREAK"); +#endif + #if LL_WINDOWS - // NOTE - On windows, at least, the component path is the + //*NOTE:Mani - On windows, at least, the component path is the // location of this dll's image file. std::string component_dir; char dll_path[_MAX_PATH]; @@ -187,8 +202,8 @@ private: } else { - // NOTE - This case should be a rare exception. - // GetModuleFileNameA should always give you a full path. + // *NOTE:Mani - This case should be an rare exception. + // GetModuleFileNameA should always give you a full path, no? component_dir = application_dir; } #else @@ -210,7 +225,6 @@ private: { // create single browser window mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight ); - #if LL_WINDOWS // Enable plugins LLQtWebKit::getInstance()->enablePlugins(true); @@ -236,8 +250,9 @@ private: // don't flip bitmap LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true ); - // set background color to be black - mostly for initial login page - LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, 0x00, 0x00, 0x00 ); + // set background color + // convert background color channels from [0.0, 1.0] to [0, 255]; + LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, int(mBackgroundR * 255.0f), int(mBackgroundG * 255.0f), int(mBackgroundB * 255.0f) ); // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns. setInitState(INIT_STATE_NAVIGATING); @@ -245,7 +260,21 @@ private: // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance. // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date. - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" ); + // Build a data URL like this: "data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#RRGGBB%22%3E%3C/body%3E%3C/html%3E" + // where RRGGBB is the background color in HTML style + std::stringstream url; + + url << "data:text/html,%3Chtml%3E%3Cbody%20bgcolor=%22#"; + // convert background color channels from [0.0, 1.0] to [0, 255]; + url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundR * 255.0f); + url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundG * 255.0f); + url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f); + url << "%22%3E%3C/body%3E%3C/html%3E"; + + lldebugs << "data url is: " << url.str() << llendl; + + LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() ); +// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" ); return true; }; @@ -253,6 +282,7 @@ private: return false; }; + //////////////////////////////////////////////////////////////////////////////// // virtual void onCursorChanged(const EventType& event) @@ -294,7 +324,7 @@ private: { if(mInitState == INIT_STATE_WAIT_REDRAW) { - setInitState(INIT_STATE_RUNNING); + setInitState(INIT_STATE_WAIT_COMPLETE); } // flag that an update is required @@ -316,7 +346,9 @@ private: if(mInitState == INIT_STATE_NAVIGATE_COMPLETE) { - setInitState(INIT_STATE_WAIT_REDRAW); + // Skip the WAIT_REDRAW state now -- with the right background color set, it should no longer be necessary. +// setInitState(INIT_STATE_WAIT_REDRAW); + setInitState(INIT_STATE_WAIT_COMPLETE); } } @@ -327,6 +359,14 @@ private: { if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) { + if(mInitState < INIT_STATE_RUNNING) + { + setInitState(INIT_STATE_RUNNING); + + // Clear the history, so the "back" button doesn't take you back to "about:blank". + LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId); + } + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); message.setValue("uri", event.getEventUri()); message.setValueS32("result_code", event.getIntValue()); @@ -399,6 +439,7 @@ private: LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href"); message.setValue("uri", event.getStringValue()); message.setValue("target", event.getStringValue2()); + message.setValueU32("target_type", event.getLinkType()); sendMessage(message); } @@ -430,92 +471,96 @@ private: return (LLQtWebKit::EKeyboardModifier)result; } - //////////////////////////////////////////////////////////////////////////////// // - void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers) + void deserializeKeyboardData( LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers ) { - int llqt_key; + native_scan_code = 0; + native_virtual_key = 0; + native_modifiers = 0; + if( native_key_data.isMap() ) + { +#if LL_DARWIN + native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger()); + native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger()); + native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); +#elif LL_WINDOWS + native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); + native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); + // TODO: I don't think we need to do anything with native modifiers here -- please verify +#elif LL_LINUX + native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); + native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); + native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); +#else + // Add other platforms here as needed +#endif + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) + { // The incoming values for 'key' will be the ones from indra_constants.h - // the outgoing values are the ones from llqtwebkit.h + std::string utf8_text; + if(key < KEY_SPECIAL) + { + // Low-ascii characters need to get passed through. + utf8_text = (char)key; + } + + // Any special-case handling we want to do for particular keys... switch((KEY)key) { - // This is the list that the llqtwebkit implementation actually maps into Qt keys. -// case KEY_XXX: llqt_key = LL_DOM_VK_CANCEL; break; -// case KEY_XXX: llqt_key = LL_DOM_VK_HELP; break; - case KEY_BACKSPACE: llqt_key = LL_DOM_VK_BACK_SPACE; break; - case KEY_TAB: llqt_key = LL_DOM_VK_TAB; break; -// case KEY_XXX: llqt_key = LL_DOM_VK_CLEAR; break; - case KEY_RETURN: llqt_key = LL_DOM_VK_RETURN; break; - case KEY_PAD_RETURN: llqt_key = LL_DOM_VK_ENTER; break; - case KEY_SHIFT: llqt_key = LL_DOM_VK_SHIFT; break; - case KEY_CONTROL: llqt_key = LL_DOM_VK_CONTROL; break; - case KEY_ALT: llqt_key = LL_DOM_VK_ALT; break; -// case KEY_XXX: llqt_key = LL_DOM_VK_PAUSE; break; - case KEY_CAPSLOCK: llqt_key = LL_DOM_VK_CAPS_LOCK; break; - case KEY_ESCAPE: llqt_key = LL_DOM_VK_ESCAPE; break; - case KEY_PAGE_UP: llqt_key = LL_DOM_VK_PAGE_UP; break; - case KEY_PAGE_DOWN: llqt_key = LL_DOM_VK_PAGE_DOWN; break; - case KEY_END: llqt_key = LL_DOM_VK_END; break; - case KEY_HOME: llqt_key = LL_DOM_VK_HOME; break; - case KEY_LEFT: llqt_key = LL_DOM_VK_LEFT; break; - case KEY_UP: llqt_key = LL_DOM_VK_UP; break; - case KEY_RIGHT: llqt_key = LL_DOM_VK_RIGHT; break; - case KEY_DOWN: llqt_key = LL_DOM_VK_DOWN; break; -// case KEY_XXX: llqt_key = LL_DOM_VK_PRINTSCREEN; break; - case KEY_INSERT: llqt_key = LL_DOM_VK_INSERT; break; - case KEY_DELETE: llqt_key = LL_DOM_VK_DELETE; break; -// case KEY_XXX: llqt_key = LL_DOM_VK_CONTEXT_MENU; break; + // ASCII codes for some standard keys + case LLQtWebKit::KEY_BACKSPACE: utf8_text = (char)8; break; + case LLQtWebKit::KEY_TAB: utf8_text = (char)9; break; + case LLQtWebKit::KEY_RETURN: utf8_text = (char)13; break; + case LLQtWebKit::KEY_PAD_RETURN: utf8_text = (char)13; break; + case LLQtWebKit::KEY_ESCAPE: utf8_text = (char)27; break; - default: - if(key < KEY_SPECIAL) - { - // Pass the incoming key through -- it should be regular ASCII, which should be correct for webkit. - llqt_key = key; - } - else - { - // Don't pass through untranslated special keys -- they'll be all wrong. - llqt_key = 0; - } + default: break; } -// std::cerr << "keypress, original code = 0x" << std::hex << key << ", converted code = 0x" << std::hex << llqt_key << std::dec << std::endl; +// std::cerr << "key event " << (int)key_event << ", native_key_data = " << native_key_data << std::endl; - if(llqt_key != 0) - { - LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, key_event, llqt_key, modifiers); - } + uint32_t native_scan_code = 0; + uint32_t native_virtual_key = 0; + uint32_t native_modifiers = 0; + deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers ); + + LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); checkEditState(); }; //////////////////////////////////////////////////////////////////////////////// // - void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers) - { - LLWString wstr = utf8str_to_wstring(utf8str); + void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) + { + uint32_t key = LLQtWebKit::KEY_NONE; - unsigned int i; - for(i=0; i < wstr.size(); i++) +// std::cerr << "unicode input, native_key_data = " << native_key_data << std::endl; + + if(utf8str.size() == 1) { -// std::cerr << "unicode input, code = 0x" << std::hex << (unsigned long)(wstr[i]) << std::dec << std::endl; - - if(wstr[i] == 32) - { - // For some reason, the webkit plugin really wants the space bar to come in through the key-event path, not the unicode path. - LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, 32, modifiers); - LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, 32, modifiers); - } - else - { - LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, wstr[i], modifiers); - } + // The only way a utf8 string can be one byte long is if it's actually a single 7-bit ascii character. + // In this case, use it as the key value. + key = utf8str[0]; } + uint32_t native_scan_code = 0; + uint32_t native_virtual_key = 0; + uint32_t native_modifiers = 0; + deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers ); + + LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); + LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers); + checkEditState(); }; @@ -568,6 +613,9 @@ MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_ mLastMouseX = 0; mLastMouseY = 0; mFirstFocus = true; + mBackgroundR = 0.0f; + mBackgroundG = 0.0f; + mBackgroundB = 0.0f; } MediaPluginWebKit::~MediaPluginWebKit() @@ -645,7 +693,6 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) info.mSize = (size_t)message_in.getValueS32("size"); std::string name = message_in.getValue("name"); - // std::cerr << "MediaPluginWebKit::receiveMessage: shared memory added, name: " << name // << ", size: " << info.mSize // << ", address: " << info.mAddress @@ -695,7 +742,11 @@ 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"); +// mBackgroundA = message_in.setValueReal("background_a"); // Ignore any alpha + if(!name.empty()) { // Find the shared memory region with this name @@ -809,6 +860,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) std::string event = message_in.getValue("event"); S32 key = message_in.getValueS32("key"); std::string modifiers = message_in.getValue("modifiers"); + LLSD native_key_data = message_in.getValueLLSD("native_key_data"); // Treat unknown events as key-up for safety. LLQtWebKit::EKeyEvent key_event = LLQtWebKit::KE_KEY_UP; @@ -821,14 +873,15 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) key_event = LLQtWebKit::KE_KEY_REPEAT; } - keyEvent(key_event, key, decodeModifiers(modifiers)); + keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); } else if(message_name == "text_event") { std::string text = message_in.getValue("text"); std::string modifiers = message_in.getValue("modifiers"); + LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - unicodeInput(text, decodeModifiers(modifiers)); + unicodeInput(text, decodeModifiers(modifiers), native_key_data); } if(message_name == "edit_cut") { diff --git a/linden/indra/newview/llviewermedia.cpp b/linden/indra/newview/llviewermedia.cpp index 5bdb26f..c0d1460 100644 --- a/linden/indra/newview/llviewermedia.cpp +++ b/linden/indra/newview/llviewermedia.cpp @@ -770,7 +770,38 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) if (mMediaSource) { - result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask); + // FIXME: THIS IS SO WRONG. + // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... + if( MASK_CONTROL & mask ) + { + if( 'C' == key ) + { + mMediaSource->copy(); + result = true; + } + else + if( 'V' == key ) + { + mMediaSource->paste(); + result = true; + } + else + if( 'X' == key ) + { + mMediaSource->cut(); + result = true; + } + } + + if(!result) + { + + LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData(); + + result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask, native_key_data); + // Since the viewer internal event dispatching doesn't give us key-up events, simulate one here. + (void)mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask, native_key_data); + } } return result; @@ -787,7 +818,9 @@ bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) if (uni_char >= 32 // discard 'control' characters && uni_char != 127) // SDL thinks this is 'delete' - yuck. { - mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE)); + LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData(); + + mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE), native_key_data); } } diff --git a/linden/install.xml b/linden/install.xml index 99d3bb2..d9f400a 100644 --- a/linden/install.xml +++ b/linden/install.xml @@ -1144,23 +1144,23 @@ Portions copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura <key>darwin</key> <map> <key>md5sum</key> - <string>b40a13847ee773c9ee06f641fe0dd1c2</string> + <string>95f44f0023dddc80be4398fc4f213861</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-darwin-20091023.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20100208.tar.bz2</uri> </map> <key>linux</key> <map> <key>md5sum</key> - <string>ffede2775355676096b1085cbb9d0da7</string> + <string>4c75b2f1e8524c7844ee3ea1cd59a3db</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-20091117.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-20100209b.tar.bz2</uri> </map> <key>windows</key> <map> <key>md5sum</key> - <string>6f2f911545e5906edc87f4f3cda423a1</string> + <string>1e9798dc424a6f6c2bea50649bbcc7ae</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-20091023.tar.bz2</uri> + <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.6-20100210.tar.bz2</uri> </map> </map> </map> -- cgit v1.1 From 791d4c2de7c0219392aeb625cf7940290dc1e79a Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Mon, 14 Jun 2010 12:27:35 +0200 Subject: port llprimitive from SG2.0 --- linden/indra/llcommon/lllslconstants.h | 2 +- linden/indra/llmath/llsdutil_math.h | 70 +++ linden/indra/llprimitive/CMakeLists.txt | 12 + linden/indra/llprimitive/llmaterialtable.cpp | 16 +- linden/indra/llprimitive/llmaterialtable.h | 87 +-- linden/indra/llprimitive/llmediaentry.cpp | 602 +++++++++++++++++++++ linden/indra/llprimitive/llmediaentry.h | 228 ++++++++ linden/indra/llprimitive/llprimitive.cpp | 581 ++++++++++++-------- linden/indra/llprimitive/llprimitive.h | 58 +- linden/indra/llprimitive/llprimlinkinfo.h | 2 +- linden/indra/llprimitive/llprimtexturelist.cpp | 424 +++++++++++++++ linden/indra/llprimitive/llprimtexturelist.h | 127 +++++ linden/indra/llprimitive/lltextureentry.cpp | 314 ++++++++++- linden/indra/llprimitive/lltextureentry.h | 66 ++- linden/indra/llprimitive/material_codes.cpp | 46 ++ linden/indra/llprimitive/material_codes.h | 21 +- .../indra/llprimitive/tests/llmediaentry_test.cpp | 508 +++++++++++++++++ .../llprimitive/tests/llmessagesystem_stub.cpp | 53 ++ .../indra/llprimitive/tests/llprimitive_test.cpp | 237 ++++++++ linden/indra/newview/llselectmgr.cpp | 2 +- 20 files changed, 3121 insertions(+), 335 deletions(-) mode change 100644 => 100755 linden/indra/llcommon/lllslconstants.h create mode 100755 linden/indra/llmath/llsdutil_math.h mode change 100644 => 100755 linden/indra/llprimitive/CMakeLists.txt mode change 100644 => 100755 linden/indra/llprimitive/llmaterialtable.cpp mode change 100644 => 100755 linden/indra/llprimitive/llmaterialtable.h create mode 100755 linden/indra/llprimitive/llmediaentry.cpp create mode 100755 linden/indra/llprimitive/llmediaentry.h mode change 100644 => 100755 linden/indra/llprimitive/llprimitive.cpp mode change 100644 => 100755 linden/indra/llprimitive/llprimitive.h mode change 100644 => 100755 linden/indra/llprimitive/llprimlinkinfo.h create mode 100755 linden/indra/llprimitive/llprimtexturelist.cpp create mode 100755 linden/indra/llprimitive/llprimtexturelist.h mode change 100644 => 100755 linden/indra/llprimitive/lltextureentry.cpp mode change 100644 => 100755 linden/indra/llprimitive/lltextureentry.h create mode 100755 linden/indra/llprimitive/material_codes.cpp mode change 100644 => 100755 linden/indra/llprimitive/material_codes.h create mode 100755 linden/indra/llprimitive/tests/llmediaentry_test.cpp create mode 100755 linden/indra/llprimitive/tests/llmessagesystem_stub.cpp create mode 100755 linden/indra/llprimitive/tests/llprimitive_test.cpp (limited to 'linden') diff --git a/linden/indra/llcommon/lllslconstants.h b/linden/indra/llcommon/lllslconstants.h old mode 100644 new mode 100755 index fc5363f..222b85d --- a/linden/indra/llcommon/lllslconstants.h +++ b/linden/indra/llcommon/lllslconstants.h @@ -5,7 +5,7 @@ * * $LicenseInfo:firstyear=2006&license=viewergpl$ * - * Copyright (c) 2006-2009, Linden Research, Inc. + * Copyright (c) 2006-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab diff --git a/linden/indra/llmath/llsdutil_math.h b/linden/indra/llmath/llsdutil_math.h new file mode 100755 index 0000000..5b64942 --- /dev/null +++ b/linden/indra/llmath/llsdutil_math.h @@ -0,0 +1,70 @@ +/** + * @file llsdutil_math.h + * @author Brad + * @date 2009-05-19 + * @brief Utility classes, functions, etc, for using structured data with math classes. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLSDUTIL_MATH_H +#define LL_LLSDUTIL_MATH_H + +class LL_COMMON_API LLSD; + +// vector3 +class LLVector3; +LLSD ll_sd_from_vector3(const LLVector3& vec); +LLVector3 ll_vector3_from_sd(const LLSD& sd, S32 start_index = 0); + +// vector4 +class LLVector4; +LLSD ll_sd_from_vector4(const LLVector4& vec); +LLVector4 ll_vector4_from_sd(const LLSD& sd, S32 start_index = 0); + +// vector3d (double) +class LLVector3d; +LLSD ll_sd_from_vector3d(const LLVector3d& vec); +LLVector3d ll_vector3d_from_sd(const LLSD& sd, S32 start_index = 0); + +// vector2 +class LLVector2; +LLSD ll_sd_from_vector2(const LLVector2& vec); +LLVector2 ll_vector2_from_sd(const LLSD& sd); + +// Quaternion +class LLQuaternion; +LLSD ll_sd_from_quaternion(const LLQuaternion& quat); +LLQuaternion ll_quaternion_from_sd(const LLSD& sd); + +// color4 +class LLColor4; +LLSD ll_sd_from_color4(const LLColor4& c); +LLColor4 ll_color4_from_sd(const LLSD& sd); + +#endif // LL_LLSDUTIL_MATH_H diff --git a/linden/indra/llprimitive/CMakeLists.txt b/linden/indra/llprimitive/CMakeLists.txt old mode 100644 new mode 100755 index 5dc4c70..e7ee811 --- a/linden/indra/llprimitive/CMakeLists.txt +++ b/linden/indra/llprimitive/CMakeLists.txt @@ -17,12 +17,15 @@ include_directories( set(llprimitive_SOURCE_FILES llmaterialtable.cpp + llmediaentry.cpp llprimitive.cpp + llprimtexturelist.cpp lltextureanim.cpp lltextureentry.cpp lltreeparams.cpp llvolumemessage.cpp llvolumexml.cpp + material_codes.cpp ) set(llprimitive_HEADER_FILES @@ -30,7 +33,9 @@ set(llprimitive_HEADER_FILES legacy_object_types.h llmaterialtable.h + llmediaentry.h llprimitive.h + llprimtexturelist.h lltextureanim.h lltextureentry.h lltreeparams.h @@ -47,3 +52,10 @@ set_source_files_properties(${llprimitive_HEADER_FILES} list(APPEND llprimitive_SOURCE_FILES ${llprimitive_HEADER_FILES}) add_library (llprimitive ${llprimitive_SOURCE_FILES}) + +#add unit tests +INCLUDE(LLAddBuildTest) +SET(llprimitive_TEST_SOURCE_FILES + llmediaentry.cpp + ) +#LL_ADD_PROJECT_UNIT_TESTS(llprimitive "${llprimitive_TEST_SOURCE_FILES}") diff --git a/linden/indra/llprimitive/llmaterialtable.cpp b/linden/indra/llprimitive/llmaterialtable.cpp old mode 100644 new mode 100755 index 4c22203..f06bfe8 --- a/linden/indra/llprimitive/llmaterialtable.cpp +++ b/linden/indra/llprimitive/llmaterialtable.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2001&license=viewergpl$ * - * Copyright (c) 2001-2009, Linden Research, Inc. + * Copyright (c) 2001-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -92,6 +92,9 @@ F32 const LLMaterialTable::DEFAULT_FRICTION = 0.5f; F32 const LLMaterialTable::DEFAULT_RESTITUTION = 0.4f; LLMaterialTable::LLMaterialTable() + : mCollisionSoundMatrix(NULL), + mSlidingSoundMatrix(NULL), + mRollingSoundMatrix(NULL) { } @@ -124,6 +127,17 @@ LLMaterialTable::~LLMaterialTable() mMaterialInfoList.clear(); } +void LLMaterialTable::initTableTransNames(std::map<std::string, std::string> namemap) +{ + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + std::string name = infop->mName; + infop->mName = namemap[name]; + } +} + void LLMaterialTable::initBasicTable() { // *TODO: Translate diff --git a/linden/indra/llprimitive/llmaterialtable.h b/linden/indra/llprimitive/llmaterialtable.h old mode 100644 new mode 100755 index ca9017a..7950c40 --- a/linden/indra/llprimitive/llmaterialtable.h +++ b/linden/indra/llprimitive/llmaterialtable.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2001&license=viewergpl$ * - * Copyright (c) 2001-2009, Linden Research, Inc. + * Copyright (c) 2001-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -38,6 +38,8 @@ #include <list> +class LLMaterialInfo; + const U32 LLMATERIAL_INFO_NAME_LENGTH = 256; // We've moved toward more reasonable mass values for the Havok4 engine. @@ -64,45 +66,6 @@ const F32 LEGACY_DEFAULT_OBJECT_DENSITY = 10.0f; const F32 DEFAULT_AVATAR_DENSITY = 445.3f; // was 444.24f; -class LLMaterialInfo -{ -public: - U8 mMCode; - std::string mName; - LLUUID mDefaultTextureID; - LLUUID mShatterSoundID; - F32 mDensity; // kg/m^3 - F32 mFriction; - F32 mRestitution; - - // damage and energy constants - F32 mHPModifier; // modifier on mass based HP total - F32 mDamageModifier; // modifier on KE based damage - F32 mEPModifier; // modifier on mass based EP total - - LLMaterialInfo(U8 mcode, const std::string& name, const LLUUID &uuid) - { - init(mcode,name,uuid); - }; - - void init(U8 mcode, const std::string& name, const LLUUID &uuid) - { - mDensity = 1000.f; // default to 1000.0 (water) - mHPModifier = 1.f; - mDamageModifier = 1.f; - mEPModifier = 1.f; - - mMCode = mcode; - mName = name; - mDefaultTextureID = uuid; - }; - - ~LLMaterialInfo() - { - }; - -}; - class LLMaterialTable { public: @@ -147,6 +110,8 @@ public: void initBasicTable(); + void initTableTransNames(std::map<std::string, std::string> namemap); + BOOL add(U8 mcode, const std::string& name, const LLUUID &uuid); BOOL addCollisionSound(U8 mcode, U8 mcode2, const LLUUID &uuid); BOOL addSlidingSound(U8 mcode, U8 mcode2, const LLUUID &uuid); @@ -183,5 +148,47 @@ public: static LLMaterialTable basic; }; + +class LLMaterialInfo +{ +public: + U8 mMCode; + std::string mName; + LLUUID mDefaultTextureID; + LLUUID mShatterSoundID; + F32 mDensity; // kg/m^3 + F32 mFriction; + F32 mRestitution; + + // damage and energy constants + F32 mHPModifier; // modifier on mass based HP total + F32 mDamageModifier; // modifier on KE based damage + F32 mEPModifier; // modifier on mass based EP total + + LLMaterialInfo(U8 mcode, const std::string& name, const LLUUID &uuid) + { + init(mcode,name,uuid); + }; + + void init(U8 mcode, const std::string& name, const LLUUID &uuid) + { + mDensity = 1000.f; // default to 1000.0 (water) + mFriction = LLMaterialTable::DEFAULT_FRICTION; + mRestitution = LLMaterialTable::DEFAULT_RESTITUTION; + mHPModifier = 1.f; + mDamageModifier = 1.f; + mEPModifier = 1.f; + + mMCode = mcode; + mName = name; + mDefaultTextureID = uuid; + }; + + ~LLMaterialInfo() + { + }; + +}; + #endif diff --git a/linden/indra/llprimitive/llmediaentry.cpp b/linden/indra/llprimitive/llmediaentry.cpp new file mode 100755 index 0000000..e4b31e2 --- /dev/null +++ b/linden/indra/llprimitive/llmediaentry.cpp @@ -0,0 +1,602 @@ +/** + * @file llmediaentry.cpp + * @brief This is a single instance of media data related to the face of a prim + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llmediaentry.h" +#include "lllslconstants.h" + +#include <boost/regex.hpp> + +// LLSD key defines +// DO NOT REORDER OR REMOVE THESE! + +// Some LLSD keys. Do not change! +#define MEDIA_ALT_IMAGE_ENABLE_KEY_STR "alt_image_enable" +#define MEDIA_CONTROLS_KEY_STR "controls" +#define MEDIA_CURRENT_URL_KEY_STR "current_url" +#define MEDIA_HOME_URL_KEY_STR "home_url" +#define MEDIA_AUTO_LOOP_KEY_STR "auto_loop" +#define MEDIA_AUTO_PLAY_KEY_STR "auto_play" +#define MEDIA_AUTO_SCALE_KEY_STR "auto_scale" +#define MEDIA_AUTO_ZOOM_KEY_STR "auto_zoom" +#define MEDIA_FIRST_CLICK_INTERACT_KEY_STR "first_click_interact" +#define MEDIA_WIDTH_PIXELS_KEY_STR "width_pixels" +#define MEDIA_HEIGHT_PIXELS_KEY_STR "height_pixels" + +// "security" fields +#define MEDIA_WHITELIST_ENABLE_KEY_STR "whitelist_enable" +#define MEDIA_WHITELIST_KEY_STR "whitelist" + +// "permissions" fields +#define MEDIA_PERMS_INTERACT_KEY_STR "perms_interact" +#define MEDIA_PERMS_CONTROL_KEY_STR "perms_control" + +// "general" fields +const char* LLMediaEntry::ALT_IMAGE_ENABLE_KEY = MEDIA_ALT_IMAGE_ENABLE_KEY_STR; +const char* LLMediaEntry::CONTROLS_KEY = MEDIA_CONTROLS_KEY_STR; +const char* LLMediaEntry::CURRENT_URL_KEY = MEDIA_CURRENT_URL_KEY_STR; +const char* LLMediaEntry::HOME_URL_KEY = MEDIA_HOME_URL_KEY_STR; +const char* LLMediaEntry::AUTO_LOOP_KEY = MEDIA_AUTO_LOOP_KEY_STR; +const char* LLMediaEntry::AUTO_PLAY_KEY = MEDIA_AUTO_PLAY_KEY_STR; +const char* LLMediaEntry::AUTO_SCALE_KEY = MEDIA_AUTO_SCALE_KEY_STR; +const char* LLMediaEntry::AUTO_ZOOM_KEY = MEDIA_AUTO_ZOOM_KEY_STR; +const char* LLMediaEntry::FIRST_CLICK_INTERACT_KEY = MEDIA_FIRST_CLICK_INTERACT_KEY_STR; +const char* LLMediaEntry::WIDTH_PIXELS_KEY = MEDIA_WIDTH_PIXELS_KEY_STR; +const char* LLMediaEntry::HEIGHT_PIXELS_KEY = MEDIA_HEIGHT_PIXELS_KEY_STR; + +// "security" fields +const char* LLMediaEntry::WHITELIST_ENABLE_KEY = MEDIA_WHITELIST_ENABLE_KEY_STR; +const char* LLMediaEntry::WHITELIST_KEY = MEDIA_WHITELIST_KEY_STR; + +// "permissions" fields +const char* LLMediaEntry::PERMS_INTERACT_KEY = MEDIA_PERMS_INTERACT_KEY_STR; +const char* LLMediaEntry::PERMS_CONTROL_KEY = MEDIA_PERMS_CONTROL_KEY_STR; + +#define DEFAULT_URL_PREFIX "http://" + +// Constructor(s) +LLMediaEntry::LLMediaEntry() : + mAltImageEnable(false), + mControls(STANDARD), + mCurrentURL(""), + mHomeURL(""), + mAutoLoop(false), + mAutoPlay(false), + mAutoScale(false), + mAutoZoom(false), + mFirstClickInteract(false), + mWidthPixels(0), + mHeightPixels(0), + mWhiteListEnable(false), + // mWhiteList + mPermsInteract(PERM_ALL), + mPermsControl(PERM_ALL), + mMediaIDp(NULL) +{ +} + +LLMediaEntry::LLMediaEntry(const LLMediaEntry &rhs) : + mMediaIDp(NULL) +{ + // "general" fields + mAltImageEnable = rhs.mAltImageEnable; + mControls = rhs.mControls; + mCurrentURL = rhs.mCurrentURL; + mHomeURL = rhs.mHomeURL; + mAutoLoop = rhs.mAutoLoop; + mAutoPlay = rhs.mAutoPlay; + mAutoScale = rhs.mAutoScale; + mAutoZoom = rhs.mAutoZoom; + mFirstClickInteract = rhs.mFirstClickInteract; + mWidthPixels = rhs.mWidthPixels; + mHeightPixels = rhs.mHeightPixels; + + // "security" fields + mWhiteListEnable = rhs.mWhiteListEnable; + mWhiteList = rhs.mWhiteList; + + // "permissions" fields + mPermsInteract = rhs.mPermsInteract; + mPermsControl = rhs.mPermsControl; +} + +LLMediaEntry::~LLMediaEntry() +{ + if (NULL != mMediaIDp) + { + delete mMediaIDp; + } +} + +LLSD LLMediaEntry::asLLSD() const +{ + LLSD sd; + asLLSD(sd); + return sd; +} + +// +// LLSD functions +// +void LLMediaEntry::asLLSD(LLSD& sd) const +{ + // "general" fields + sd[ALT_IMAGE_ENABLE_KEY] = mAltImageEnable; + sd[CONTROLS_KEY] = (LLSD::Integer)mControls; + sd[CURRENT_URL_KEY] = mCurrentURL; + sd[HOME_URL_KEY] = mHomeURL; + sd[AUTO_LOOP_KEY] = mAutoLoop; + sd[AUTO_PLAY_KEY] = mAutoPlay; + sd[AUTO_SCALE_KEY] = mAutoScale; + sd[AUTO_ZOOM_KEY] = mAutoZoom; + sd[FIRST_CLICK_INTERACT_KEY] = mFirstClickInteract; + sd[WIDTH_PIXELS_KEY] = mWidthPixels; + sd[HEIGHT_PIXELS_KEY] = mHeightPixels; + + // "security" fields + sd[WHITELIST_ENABLE_KEY] = mWhiteListEnable; + sd.erase(WHITELIST_KEY); + for (U32 i=0; i<mWhiteList.size(); i++) + { + sd[WHITELIST_KEY].append(mWhiteList[i]); + } + + // "permissions" fields + sd[PERMS_INTERACT_KEY] = mPermsInteract; + sd[PERMS_CONTROL_KEY] = mPermsControl; +} + +// static +bool LLMediaEntry::checkLLSD(const LLSD& sd) +{ + if (sd.isUndefined()) return true; + LLMediaEntry temp; + return temp.fromLLSDInternal(sd, true); +} + +void LLMediaEntry::fromLLSD(const LLSD& sd) +{ + (void)fromLLSDInternal(sd, true); +} + +void LLMediaEntry::mergeFromLLSD(const LLSD& sd) +{ + (void)fromLLSDInternal(sd, false); +} + +// *NOTE: returns true if NO failures to set occurred, false otherwise. +// However, be aware that if a failure to set does occur, it does +// not stop setting fields from the LLSD! +bool LLMediaEntry::fromLLSDInternal(const LLSD& sd, bool overwrite) +{ + // *HACK: we sort of cheat here and assume that status is a + // bit field. We "or" into status and instead of returning + // it, we return whether it finishes off as LSL_STATUS_OK or not. + U32 status = LSL_STATUS_OK; + + // "general" fields + if ( overwrite || sd.has(ALT_IMAGE_ENABLE_KEY) ) + { + status |= setAltImageEnable( sd[ALT_IMAGE_ENABLE_KEY] ); + } + if ( overwrite || sd.has(CONTROLS_KEY) ) + { + status |= setControls( (MediaControls)(LLSD::Integer)sd[CONTROLS_KEY] ); + } + if ( overwrite || sd.has(CURRENT_URL_KEY) ) + { + // Don't check whitelist + status |= setCurrentURLInternal( sd[CURRENT_URL_KEY], false ); + } + if ( overwrite || sd.has(HOME_URL_KEY) ) + { + status |= setHomeURL( sd[HOME_URL_KEY] ); + } + if ( overwrite || sd.has(AUTO_LOOP_KEY) ) + { + status |= setAutoLoop( sd[AUTO_LOOP_KEY] ); + } + if ( overwrite || sd.has(AUTO_PLAY_KEY) ) + { + status |= setAutoPlay( sd[AUTO_PLAY_KEY] ); + } + if ( overwrite || sd.has(AUTO_SCALE_KEY) ) + { + status |= setAutoScale( sd[AUTO_SCALE_KEY] ); + } + if ( overwrite || sd.has(AUTO_ZOOM_KEY) ) + { + status |= setAutoZoom( sd[AUTO_ZOOM_KEY] ); + } + if ( overwrite || sd.has(FIRST_CLICK_INTERACT_KEY) ) + { + status |= setFirstClickInteract( sd[FIRST_CLICK_INTERACT_KEY] ); + } + if ( overwrite || sd.has(WIDTH_PIXELS_KEY) ) + { + status |= setWidthPixels( (LLSD::Integer)sd[WIDTH_PIXELS_KEY] ); + } + if ( overwrite || sd.has(HEIGHT_PIXELS_KEY) ) + { + status |= setHeightPixels( (LLSD::Integer)sd[HEIGHT_PIXELS_KEY] ); + } + + // "security" fields + if ( overwrite || sd.has(WHITELIST_ENABLE_KEY) ) + { + status |= setWhiteListEnable( sd[WHITELIST_ENABLE_KEY] ); + } + if ( overwrite || sd.has(WHITELIST_KEY) ) + { + status |= setWhiteList( sd[WHITELIST_KEY] ); + } + + // "permissions" fields + if ( overwrite || sd.has(PERMS_INTERACT_KEY) ) + { + status |= setPermsInteract( 0xff & (LLSD::Integer)sd[PERMS_INTERACT_KEY] ); + } + if ( overwrite || sd.has(PERMS_CONTROL_KEY) ) + { + status |= setPermsControl( 0xff & (LLSD::Integer)sd[PERMS_CONTROL_KEY] ); + } + + return LSL_STATUS_OK == status; +} + +LLMediaEntry& LLMediaEntry::operator=(const LLMediaEntry &rhs) +{ + if (this != &rhs) + { + // "general" fields + mAltImageEnable = rhs.mAltImageEnable; + mControls = rhs.mControls; + mCurrentURL = rhs.mCurrentURL; + mHomeURL = rhs.mHomeURL; + mAutoLoop = rhs.mAutoLoop; + mAutoPlay = rhs.mAutoPlay; + mAutoScale = rhs.mAutoScale; + mAutoZoom = rhs.mAutoZoom; + mFirstClickInteract = rhs.mFirstClickInteract; + mWidthPixels = rhs.mWidthPixels; + mHeightPixels = rhs.mHeightPixels; + + // "security" fields + mWhiteListEnable = rhs.mWhiteListEnable; + mWhiteList = rhs.mWhiteList; + + // "permissions" fields + mPermsInteract = rhs.mPermsInteract; + mPermsControl = rhs.mPermsControl; + } + + return *this; +} + +bool LLMediaEntry::operator==(const LLMediaEntry &rhs) const +{ + return ( + // "general" fields + mAltImageEnable == rhs.mAltImageEnable && + mControls == rhs.mControls && + mCurrentURL == rhs.mCurrentURL && + mHomeURL == rhs.mHomeURL && + mAutoLoop == rhs.mAutoLoop && + mAutoPlay == rhs.mAutoPlay && + mAutoScale == rhs.mAutoScale && + mAutoZoom == rhs.mAutoZoom && + mFirstClickInteract == rhs.mFirstClickInteract && + mWidthPixels == rhs.mWidthPixels && + mHeightPixels == rhs.mHeightPixels && + + // "security" fields + mWhiteListEnable == rhs.mWhiteListEnable && + mWhiteList == rhs.mWhiteList && + + // "permissions" fields + mPermsInteract == rhs.mPermsInteract && + mPermsControl == rhs.mPermsControl + + ); +} + +bool LLMediaEntry::operator!=(const LLMediaEntry &rhs) const +{ + return ( + // "general" fields + mAltImageEnable != rhs.mAltImageEnable || + mControls != rhs.mControls || + mCurrentURL != rhs.mCurrentURL || + mHomeURL != rhs.mHomeURL || + mAutoLoop != rhs.mAutoLoop || + mAutoPlay != rhs.mAutoPlay || + mAutoScale != rhs.mAutoScale || + mAutoZoom != rhs.mAutoZoom || + mFirstClickInteract != rhs.mFirstClickInteract || + mWidthPixels != rhs.mWidthPixels || + mHeightPixels != rhs.mHeightPixels || + + // "security" fields + mWhiteListEnable != rhs.mWhiteListEnable || + mWhiteList != rhs.mWhiteList || + + // "permissions" fields + mPermsInteract != rhs.mPermsInteract || + mPermsControl != rhs.mPermsControl + + ); +} + +U32 LLMediaEntry::setWhiteList( const std::vector<std::string> &whitelist ) +{ + // *NOTE: This code is VERY similar to the setWhitelist below. + // IF YOU CHANGE THIS IMPLEMENTATION, BE SURE TO CHANGE THE OTHER! + U32 size = 0; + U32 count = 0; + // First count to make sure the size constraint is not violated + std::vector<std::string>::const_iterator iter = whitelist.begin(); + std::vector<std::string>::const_iterator end = whitelist.end(); + for ( ; iter < end; ++iter) + { + const std::string &entry = (*iter); + size += entry.length() + 1; // Include one for \0 + count ++; + if (size > MAX_WHITELIST_SIZE || count > MAX_WHITELIST_COUNT) + { + return LSL_STATUS_BOUNDS_ERROR; + } + } + // Next clear the vector + mWhiteList.clear(); + // Then re-iterate and copy entries + iter = whitelist.begin(); + for ( ; iter < end; ++iter) + { + const std::string &entry = (*iter); + mWhiteList.push_back(entry); + } + return LSL_STATUS_OK; +} + +U32 LLMediaEntry::setWhiteList( const LLSD &whitelist ) +{ + // If whitelist is undef, the whitelist is cleared + if (whitelist.isUndefined()) + { + mWhiteList.clear(); + return LSL_STATUS_OK; + } + + // However, if the whitelist is an empty array, erase it. + if (whitelist.isArray()) + { + // *NOTE: This code is VERY similar to the setWhitelist above. + // IF YOU CHANGE THIS IMPLEMENTATION, BE SURE TO CHANGE THE OTHER! + U32 size = 0; + U32 count = 0; + // First check to make sure the size and count constraints are not violated + LLSD::array_const_iterator iter = whitelist.beginArray(); + LLSD::array_const_iterator end = whitelist.endArray(); + for ( ; iter < end; ++iter) + { + const std::string &entry = (*iter).asString(); + size += entry.length() + 1; // Include one for \0 + count ++; + if (size > MAX_WHITELIST_SIZE || count > MAX_WHITELIST_COUNT) + { + return LSL_STATUS_BOUNDS_ERROR; + } + } + // Next clear the vector + mWhiteList.clear(); + // Then re-iterate and copy entries + iter = whitelist.beginArray(); + for ( ; iter < end; ++iter) + { + const std::string &entry = (*iter).asString(); + mWhiteList.push_back(entry); + } + return LSL_STATUS_OK; + } + else + { + return LSL_STATUS_MALFORMED_PARAMS; + } +} + + +static void prefix_with(std::string &str, const char *chars, const char *prefix) +{ + // Given string 'str', prefix all instances of any character in 'chars' + // with 'prefix' + size_t found = str.find_first_of(chars); + size_t prefix_len = strlen(prefix); + while (found != std::string::npos) + { + str.insert(found, prefix, prefix_len); + found = str.find_first_of(chars, found+prefix_len+1); + } +} + +static bool pattern_match(const std::string &candidate_str, const std::string &pattern) +{ + // If the pattern is empty, it matches + if (pattern.empty()) return true; + + // 'pattern' is a glob pattern, we only accept '*' chars + // copy it + std::string expression = pattern; + + // Escape perl's regexp chars with a backslash, except all "*" chars + prefix_with(expression, ".[{()\\+?|^$", "\\"); + prefix_with(expression, "*", "."); + + // case-insensitive matching: + boost::regex regexp(expression, boost::regex::perl|boost::regex::icase); + return boost::regex_match(candidate_str, regexp); +} + +bool LLMediaEntry::checkCandidateUrl(const std::string& url) const +{ + if (getWhiteListEnable()) + { + return checkUrlAgainstWhitelist(url, getWhiteList()); + } + else + { + return true; + } +} + +// static +bool LLMediaEntry::checkUrlAgainstWhitelist(const std::string& url, + const std::vector<std::string> &whitelist) +{ + bool passes = true; + // *NOTE: no entries? Don't check + if (whitelist.size() > 0) + { + passes = false; + + // Case insensitive: the reason why we toUpper both this and the + // filter + std::string candidate_url = url; + // Use lluri to see if there is a path part in the candidate URL. No path? Assume "/" + LLURI candidate_uri(candidate_url); + std::vector<std::string>::const_iterator iter = whitelist.begin(); + std::vector<std::string>::const_iterator end = whitelist.end(); + for ( ; iter < end; ++iter ) + { + std::string filter = *iter; + + LLURI filter_uri(filter); + bool scheme_passes = pattern_match( candidate_uri.scheme(), filter_uri.scheme() ); + if (filter_uri.scheme().empty()) + { + filter_uri = LLURI(DEFAULT_URL_PREFIX + filter); + } + bool authority_passes = pattern_match( candidate_uri.authority(), filter_uri.authority() ); + bool path_passes = pattern_match( candidate_uri.escapedPath(), filter_uri.escapedPath() ); + + if (scheme_passes && authority_passes && path_passes) + { + passes = true; + break; + } + } + } + return passes; +} + +U32 LLMediaEntry::setStringFieldWithLimit( std::string &field, const std::string &value, U32 limit ) +{ + if ( value.length() > limit ) + { + return LSL_STATUS_BOUNDS_ERROR; + } + else + { + field = value; + return LSL_STATUS_OK; + } +} + +U32 LLMediaEntry::setControls(LLMediaEntry::MediaControls controls) +{ + if (controls == STANDARD || + controls == MINI) + { + mControls = controls; + return LSL_STATUS_OK; + } + return LSL_STATUS_BOUNDS_ERROR; +} + +U32 LLMediaEntry::setPermsInteract( U8 val ) +{ + mPermsInteract = val & PERM_MASK; + return LSL_STATUS_OK; +} + +U32 LLMediaEntry::setPermsControl( U8 val ) +{ + mPermsControl = val & PERM_MASK; + return LSL_STATUS_OK; +} + +U32 LLMediaEntry::setCurrentURL(const std::string& current_url) +{ + return setCurrentURLInternal( current_url, true ); +} + +U32 LLMediaEntry::setCurrentURLInternal(const std::string& current_url, bool check_whitelist) +{ + if ( ! check_whitelist || checkCandidateUrl(current_url)) + { + return setStringFieldWithLimit( mCurrentURL, current_url, MAX_URL_LENGTH ); + } + else + { + return LSL_STATUS_WHITELIST_FAILED; + } +} + +U32 LLMediaEntry::setHomeURL(const std::string& home_url) +{ + return setStringFieldWithLimit( mHomeURL, home_url, MAX_URL_LENGTH ); +} + +U32 LLMediaEntry::setWidthPixels(U16 width) +{ + if (width > MAX_WIDTH_PIXELS) return LSL_STATUS_BOUNDS_ERROR; + mWidthPixels = width; + return LSL_STATUS_OK; +} + +U32 LLMediaEntry::setHeightPixels(U16 height) +{ + if (height > MAX_HEIGHT_PIXELS) return LSL_STATUS_BOUNDS_ERROR; + mHeightPixels = height; + return LSL_STATUS_OK; +} + +const LLUUID &LLMediaEntry::getMediaID() const +{ + // Lazily generate media ID + if (NULL == mMediaIDp) + { + mMediaIDp = new LLUUID(); + mMediaIDp->generate(); + } + return *mMediaIDp; +} + diff --git a/linden/indra/llprimitive/llmediaentry.h b/linden/indra/llprimitive/llmediaentry.h new file mode 100755 index 0000000..ca52e6e --- /dev/null +++ b/linden/indra/llprimitive/llmediaentry.h @@ -0,0 +1,228 @@ +/** + * @file llmediaentry.h + * @brief This is a single instance of media data related to the face of a prim + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLMEDIAENTRY_H +#define LL_LLMEDIAENTRY_H + +#include "llsd.h" +#include "llstring.h" + +// For return values of set* +#include "lllslconstants.h" + +class LLMediaEntry +{ +public: + enum MediaControls { + STANDARD = 0, + MINI + }; + + // Constructors + LLMediaEntry(); + LLMediaEntry(const LLMediaEntry &rhs); + + LLMediaEntry &operator=(const LLMediaEntry &rhs); + virtual ~LLMediaEntry(); + + bool operator==(const LLMediaEntry &rhs) const; + bool operator!=(const LLMediaEntry &rhs) const; + + // Render as LLSD + LLSD asLLSD() const; + void asLLSD(LLSD& sd) const; + operator LLSD() const { return asLLSD(); } + // Returns false iff the given LLSD contains fields that violate any bounds + // limits. + static bool checkLLSD(const LLSD& sd); + // This doesn't merge, it overwrites the data, so will use + // LLSD defaults if need be. Note: does not check limits! + // Use checkLLSD() above first to ensure the LLSD is valid. + void fromLLSD(const LLSD& sd); + // This merges data from the incoming LLSD into our fields. + // Note that it also does NOT check limits! Use checkLLSD() above first. + void mergeFromLLSD(const LLSD& sd); + + // "general" fields + bool getAltImageEnable() const { return mAltImageEnable; } + MediaControls getControls() const { return mControls; } + std::string getCurrentURL() const { return mCurrentURL; } + std::string getHomeURL() const { return mHomeURL; } + bool getAutoLoop() const { return mAutoLoop; } + bool getAutoPlay() const { return mAutoPlay; } + bool getAutoScale() const { return mAutoScale; } + bool getAutoZoom() const { return mAutoZoom; } + bool getFirstClickInteract() const { return mFirstClickInteract; } + U16 getWidthPixels() const { return mWidthPixels; } + U16 getHeightPixels() const { return mHeightPixels; } + + // "security" fields + bool getWhiteListEnable() const { return mWhiteListEnable; } + const std::vector<std::string> &getWhiteList() const { return mWhiteList; } + + // "permissions" fields + U8 getPermsInteract() const { return mPermsInteract; } + U8 getPermsControl() const { return mPermsControl; } + + // Setters. Those that return a U32 return a status error code + // See lllslconstants.h + + // "general" fields + U32 setAltImageEnable(bool alt_image_enable) { mAltImageEnable = alt_image_enable; return LSL_STATUS_OK; } + U32 setControls(MediaControls controls); + U32 setCurrentURL(const std::string& current_url); + U32 setHomeURL(const std::string& home_url); + U32 setAutoLoop(bool auto_loop) { mAutoLoop = auto_loop; return LSL_STATUS_OK; } + U32 setAutoPlay(bool auto_play) { mAutoPlay = auto_play; return LSL_STATUS_OK; } + U32 setAutoScale(bool auto_scale) { mAutoScale = auto_scale; return LSL_STATUS_OK; } + U32 setAutoZoom(bool auto_zoom) { mAutoZoom = auto_zoom; return LSL_STATUS_OK; } + U32 setFirstClickInteract(bool first_click) { mFirstClickInteract = first_click; return LSL_STATUS_OK; } + U32 setWidthPixels(U16 width); + U32 setHeightPixels(U16 height); + + // "security" fields + U32 setWhiteListEnable( bool whitelist_enable ) { mWhiteListEnable = whitelist_enable; return LSL_STATUS_OK; } + U32 setWhiteList( const std::vector<std::string> &whitelist ); + U32 setWhiteList( const LLSD &whitelist ); // takes an LLSD array + + // "permissions" fields + U32 setPermsInteract( U8 val ); + U32 setPermsControl( U8 val ); + + const LLUUID& getMediaID() const; + + // Helper function to check a candidate URL against the whitelist + // Returns true iff candidate URL passes (or if there is no whitelist), false otherwise + bool checkCandidateUrl(const std::string& url) const; + +public: + // Static function to check a URL against a whitelist + // Returns true iff url passes the given whitelist + static bool checkUrlAgainstWhitelist(const std::string &url, + const std::vector<std::string> &whitelist); + +public: + // LLSD key defines + // "general" fields + static const char* ALT_IMAGE_ENABLE_KEY; + static const char* CONTROLS_KEY; + static const char* CURRENT_URL_KEY; + static const char* HOME_URL_KEY; + static const char* AUTO_LOOP_KEY; + static const char* AUTO_PLAY_KEY; + static const char* AUTO_SCALE_KEY; + static const char* AUTO_ZOOM_KEY; + static const char* FIRST_CLICK_INTERACT_KEY; + static const char* WIDTH_PIXELS_KEY; + static const char* HEIGHT_PIXELS_KEY; + + // "security" fields + static const char* WHITELIST_ENABLE_KEY; + static const char* WHITELIST_KEY; + + // "permissions" fields + static const char* PERMS_INTERACT_KEY; + static const char* PERMS_CONTROL_KEY; + + // Field enumerations & constants + + // *NOTE: DO NOT change the order of these, and do not insert values + // in the middle! + // Add values to the end, and make sure to change PARAM_MAX_ID! + enum Fields { + ALT_IMAGE_ENABLE_ID = 0, + CONTROLS_ID = 1, + CURRENT_URL_ID = 2, + HOME_URL_ID = 3, + AUTO_LOOP_ID = 4, + AUTO_PLAY_ID = 5, + AUTO_SCALE_ID = 6, + AUTO_ZOOM_ID = 7, + FIRST_CLICK_INTERACT_ID = 8, + WIDTH_PIXELS_ID = 9, + HEIGHT_PIXELS_ID = 10, + WHITELIST_ENABLE_ID = 11, + WHITELIST_ID = 12, + PERMS_INTERACT_ID = 13, + PERMS_CONTROL_ID = 14, + PARAM_MAX_ID = PERMS_CONTROL_ID + }; + + // "permissions" values + // (e.g. (PERM_OWNER | PERM_GROUP) sets permissions on for OWNER and GROUP + static const U8 PERM_NONE = 0x0; + static const U8 PERM_OWNER = 0x1; + static const U8 PERM_GROUP = 0x2; + static const U8 PERM_ANYONE = 0x4; + static const U8 PERM_ALL = PERM_OWNER|PERM_GROUP|PERM_ANYONE; + static const U8 PERM_MASK = PERM_OWNER|PERM_GROUP|PERM_ANYONE; + + // Limits (in bytes) + static const U32 MAX_URL_LENGTH = 1024; + static const U32 MAX_WHITELIST_SIZE = 1024; + static const U32 MAX_WHITELIST_COUNT = 64; + static const U16 MAX_WIDTH_PIXELS = 2048; + static const U16 MAX_HEIGHT_PIXELS = 2048; + +private: + + U32 setStringFieldWithLimit( std::string &field, const std::string &value, U32 limit ); + U32 setCurrentURLInternal( const std::string &url, bool check_whitelist); + bool fromLLSDInternal(const LLSD &sd, bool overwrite); + +private: + // "general" fields + bool mAltImageEnable; + MediaControls mControls; + std::string mCurrentURL; + std::string mHomeURL; + bool mAutoLoop; + bool mAutoPlay; + bool mAutoScale; + bool mAutoZoom; + bool mFirstClickInteract; + U16 mWidthPixels; + U16 mHeightPixels; + + // "security" fields + bool mWhiteListEnable; + std::vector<std::string> mWhiteList; + + // "permissions" fields + U8 mPermsInteract; + U8 mPermsControl; + + mutable LLUUID *mMediaIDp; // temporary id assigned to media on the viewer +}; + +#endif + diff --git a/linden/indra/llprimitive/llprimitive.cpp b/linden/indra/llprimitive/llprimitive.cpp old mode 100644 new mode 100755 index f1b7522..7546764 --- a/linden/indra/llprimitive/llprimitive.cpp +++ b/linden/indra/llprimitive/llprimitive.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2001&license=viewergpl$ * - * Copyright (c) 2001-2009, Linden Research, Inc. + * Copyright (c) 2001-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -43,7 +43,8 @@ #include "llvolumemgr.h" #include "llstring.h" #include "lldatapacker.h" -#include "llsdutil.h" +#include "llsdutil.h"//_math.h" +#include "llprimtexturelist.h" /** * exported constants @@ -111,6 +112,7 @@ const F32 FLEXIBLE_OBJECT_DEFAULT_LENGTH = 1.0f; const BOOL FLEXIBLE_OBJECT_DEFAULT_USING_COLLISION_SPHERE = FALSE; const BOOL FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE = FALSE; +const S32 MAX_FACE_BITS = 9; const char *SCULPT_DEFAULT_TEXTURE = "be293869-d0d9-0a69-5989-ad27f1946fd4"; // old inverted texture: "7595d345-a24c-e7ef-f0bd-78793792133e"; @@ -129,7 +131,7 @@ void LLPrimitive::setVolumeManager( LLVolumeMgr* volume_manager ) { if ( !volume_manager || sVolumeManager ) { - llerrs << "Unable to set LLPrimitive::sVolumeManager to NULL" << llendl; + llerrs << "LLPrimitive::sVolumeManager attempting to be set to NULL or it already has been set." << llendl; } sVolumeManager = volume_manager; } @@ -150,7 +152,9 @@ bool LLPrimitive::cleanupVolumeManager() //=============================================================== LLPrimitive::LLPrimitive() -: mMiscFlags(0) +: mTextureList(), + mNumTEs(0), + mMiscFlags(0) { mPrimitiveCode = 0; @@ -167,20 +171,12 @@ LLPrimitive::LLPrimitive() mAngularVelocity.setVec(0.f,0.f,0.f); mScale.setVec(1.f,1.f,1.f); - - mNumTEs = 0; - mTextureList = NULL; } //=============================================================== LLPrimitive::~LLPrimitive() { - if (mTextureList) - { - delete [] mTextureList; - mTextureList = NULL; - } - + clearTextureList(); // Cleanup handled by volume manager if (mVolumep) { @@ -189,6 +185,10 @@ LLPrimitive::~LLPrimitive() mVolumep = NULL; } +void LLPrimitive::clearTextureList() +{ +} + //=============================================================== // static LLPrimitive *LLPrimitive::createPrimitive(LLPCode p_code) @@ -212,15 +212,7 @@ LLPrimitive *LLPrimitive::createPrimitive(LLPCode p_code) void LLPrimitive::init_primitive(LLPCode p_code) { LLMemType m1(LLMemType::MTYPE_PRIMITIVE); - if (mNumTEs) - { - if (mTextureList) - { - delete [] mTextureList; - } - mTextureList = new LLTextureEntry[mNumTEs]; - } - + clearTextureList(); mPrimitiveCode = p_code; } @@ -230,82 +222,30 @@ void LLPrimitive::setPCode(const U8 p_code) } //=============================================================== -const LLTextureEntry * LLPrimitive::getTE(const U8 te_num) const +LLTextureEntry* LLPrimitive::getTE(const U8 index) const { - // if we're asking for a non-existent face, return null - if (mNumTEs && (te_num< mNumTEs)) - { - return(&mTextureList[te_num]); - } - else - { - return(NULL); - } + return mTextureList.getTexture(index); } //=============================================================== void LLPrimitive::setNumTEs(const U8 num_tes) { - if (num_tes == mNumTEs) - { - return; - } - - // Right now, we don't try and preserve entries when the number of faces - // changes. - - LLMemType m1(LLMemType::MTYPE_PRIMITIVE); - if (num_tes) - { - LLTextureEntry *new_tes; - new_tes = new LLTextureEntry[num_tes]; - U32 i; - for (i = 0; i < num_tes; i++) - { - if (i < mNumTEs) - { - new_tes[i] = mTextureList[i]; - } - else if (mNumTEs) - { - new_tes[i] = mTextureList[mNumTEs - 1]; - } - else - { - new_tes[i] = LLTextureEntry(); - } - } - delete[] mTextureList; - mTextureList = new_tes; - } - else - { - delete[] mTextureList; - mTextureList = NULL; - } - - - mNumTEs = num_tes; + mTextureList.setSize(num_tes); } //=============================================================== void LLPrimitive::setAllTETextures(const LLUUID &tex_id) { - U8 i; - - for (i = 0; i < mNumTEs; i++) - { - mTextureList[i].setID(tex_id); - } + mTextureList.setAllIDs(tex_id); } //=============================================================== -void LLPrimitive::setTE(const U8 index, const LLTextureEntry &te) +void LLPrimitive::setTE(const U8 index, const LLTextureEntry& te) { - mTextureList[index] = te; + mTextureList.copyTexture(index, te); } -S32 LLPrimitive::setTETexture(const U8 te, const LLUUID &tex_id) +S32 LLPrimitive::setTETexture(const U8 index, const LLUUID &id) { // if we're asking for a non-existent face, return null if (te >= mNumTEs) @@ -314,10 +254,10 @@ S32 LLPrimitive::setTETexture(const U8 te, const LLUUID &tex_id) return 0; } - return mTextureList[te].setID(tex_id); + return mTextureList.setID(index, id); } -S32 LLPrimitive::setTEColor(const U8 te, const LLColor4 &color) +S32 LLPrimitive::setTEColor(const U8 index, const LLColor4 &color) { // if we're asking for a non-existent face, return null if (te >= mNumTEs) @@ -326,10 +266,11 @@ S32 LLPrimitive::setTEColor(const U8 te, const LLColor4 &color) return 0; } - return mTextureList[te].setColor(color); + + return mTextureList.setColor(index, color); } -S32 LLPrimitive::setTEColor(const U8 te, const LLColor3 &color) +S32 LLPrimitive::setTEColor(const U8 index, const LLColor3 &color) { // if we're asking for a non-existent face, return null if (te >= mNumTEs) @@ -338,10 +279,10 @@ S32 LLPrimitive::setTEColor(const U8 te, const LLColor3 &color) return 0; } - return mTextureList[te].setColor(color); + return mTextureList.setColor(index, color); } -S32 LLPrimitive::setTEAlpha(const U8 te, const F32 alpha) +S32 LLPrimitive::setTEAlpha(const U8 index, const F32 alpha) { // if we're asking for a non-existent face, return null if (te >= mNumTEs) @@ -350,117 +291,64 @@ S32 LLPrimitive::setTEAlpha(const U8 te, const F32 alpha) return 0; } - return mTextureList[te].setAlpha(alpha); + return mTextureList.setAlpha(index, alpha); } //=============================================================== -S32 LLPrimitive::setTEScale(const U8 te, const F32 s, const F32 t) +S32 LLPrimitive::setTEScale(const U8 index, const F32 s, const F32 t) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "Setting nonexistent face" << llendl; - return 0; - } - - return mTextureList[te].setScale(s,t); + return mTextureList.setScale(index, s, t); } // BUG: slow - done this way because texture entries have some // voodoo related to texture coords -S32 LLPrimitive::setTEScaleS(const U8 te, const F32 s) +S32 LLPrimitive::setTEScaleS(const U8 index, const F32 s) { - if (te >= mNumTEs) - { - llwarns << "Setting nonexistent face" << llendl; - return 0; - } - - F32 ignore, t; - mTextureList[te].getScale(&ignore, &t); - return mTextureList[te].setScale(s,t); + return mTextureList.setScaleS(index, s); } // BUG: slow - done this way because texture entries have some // voodoo related to texture coords -S32 LLPrimitive::setTEScaleT(const U8 te, const F32 t) +S32 LLPrimitive::setTEScaleT(const U8 index, const F32 t) { - if (te >= mNumTEs) - { - llwarns << "Setting nonexistent face" << llendl; - return 0; - } - - F32 s, ignore; - mTextureList[te].getScale(&s, &ignore); - return mTextureList[te].setScale(s,t); + return mTextureList.setScaleT(index, t); } //=============================================================== -S32 LLPrimitive::setTEOffset(const U8 te, const F32 s, const F32 t) +S32 LLPrimitive::setTEOffset(const U8 index, const F32 s, const F32 t) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "Setting nonexistent face" << llendl; - return 0; - } - - return mTextureList[te].setOffset(s,t); + return mTextureList.setOffset(index, s, t); } // BUG: slow - done this way because texture entries have some // voodoo related to texture coords -S32 LLPrimitive::setTEOffsetS(const U8 te, const F32 s) +S32 LLPrimitive::setTEOffsetS(const U8 index, const F32 s) { - if (te >= mNumTEs) - { - llwarns << "Setting nonexistent face" << llendl; - return 0; - } - - F32 ignore, t; - mTextureList[te].getOffset(&ignore, &t); - return mTextureList[te].setOffset(s,t); + return mTextureList.setOffsetS(index, s); } // BUG: slow - done this way because texture entries have some // voodoo related to texture coords -S32 LLPrimitive::setTEOffsetT(const U8 te, const F32 t) +S32 LLPrimitive::setTEOffsetT(const U8 index, const F32 t) { - if (te >= mNumTEs) - { - llwarns << "Setting nonexistent face" << llendl; - return 0; - } - - F32 s, ignore; - mTextureList[te].getOffset(&s, &ignore); - return mTextureList[te].setOffset(s,t); + return mTextureList.setOffsetT(index, t); } //=============================================================== -S32 LLPrimitive::setTERotation(const U8 te, const F32 r) +S32 LLPrimitive::setTERotation(const U8 index, const F32 r) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "Setting nonexistent face" << llendl; - return 0; - } - - return mTextureList[te].setRotation(r); + return mTextureList.setRotation(index, r); } //=============================================================== -S32 LLPrimitive::setTEBumpShinyFullbright(const U8 te, const U8 bump) +S32 LLPrimitive::setTEBumpShinyFullbright(const U8 index, const U8 bump) { // if we're asking for a non-existent face, return null if (te >= mNumTEs) @@ -469,10 +357,10 @@ S32 LLPrimitive::setTEBumpShinyFullbright(const U8 te, const U8 bump) return 0; } - return mTextureList[te].setBumpShinyFullbright( bump ); + return mTextureList.setBumpShinyFullbright(index, bump); } -S32 LLPrimitive::setTEMediaTexGen(const U8 te, const U8 media) +S32 LLPrimitive::setTEMediaTexGen(const U8 index, const U8 media) { // if we're asking for a non-existent face, return null if (te >= mNumTEs) @@ -481,10 +369,10 @@ S32 LLPrimitive::setTEMediaTexGen(const U8 te, const U8 media) return 0; } - return mTextureList[te].setMediaTexGen( media ); + return mTextureList.setMediaTexGen(index, media); } -S32 LLPrimitive::setTEBumpmap(const U8 te, const U8 bump) +S32 LLPrimitive::setTEBumpmap(const U8 index, const U8 bump) { // if we're asking for a non-existent face, return null if (te >= mNumTEs) @@ -493,10 +381,10 @@ S32 LLPrimitive::setTEBumpmap(const U8 te, const U8 bump) return 0; } - return mTextureList[te].setBumpmap( bump ); + return mTextureList.setBumpMap(index, bump); } -S32 LLPrimitive::setTEBumpShiny(const U8 te, const U8 bump_shiny) +S32 LLPrimitive::setTEBumpShiny(const U8 index, const U8 bump_shiny) { // if we're asking for a non-existent face, return null if (te >= mNumTEs) @@ -505,10 +393,10 @@ S32 LLPrimitive::setTEBumpShiny(const U8 te, const U8 bump_shiny) return 0; } - return mTextureList[te].setBumpShiny( bump_shiny ); + return mTextureList.setBumpShiny(index, bump_shiny); } -S32 LLPrimitive::setTETexGen(const U8 te, const U8 texgen) +S32 LLPrimitive::setTETexGen(const U8 index, const U8 texgen) { // if we're asking for a non-existent face, return null if (te >= mNumTEs) @@ -517,10 +405,10 @@ S32 LLPrimitive::setTETexGen(const U8 te, const U8 texgen) return 0; } - return mTextureList[te].setTexGen( texgen ); + return mTextureList.setTexGen(index, texgen); } -S32 LLPrimitive::setTEShiny(const U8 te, const U8 shiny) +S32 LLPrimitive::setTEShiny(const U8 index, const U8 shiny) { // if we're asking for a non-existent face, return null if (te >= mNumTEs) @@ -529,11 +417,13 @@ S32 LLPrimitive::setTEShiny(const U8 te, const U8 shiny) return 0; } - return mTextureList[te].setShiny( shiny ); + + return mTextureList.setShiny(index, shiny); } -S32 LLPrimitive::setTEFullbright(const U8 te, const U8 fullbright) +S32 LLPrimitive::setTEFullbright(const U8 index, const U8 fullbright) { + // if we're asking for a non-existent face, return null if (te >= mNumTEs) { @@ -541,10 +431,10 @@ S32 LLPrimitive::setTEFullbright(const U8 te, const U8 fullbright) return 0; } - return mTextureList[te].setFullbright( fullbright ); + return mTextureList.setFullbright(index, fullbright); } -S32 LLPrimitive::setTEMediaFlags(const U8 te, const U8 media_flags) +S32 LLPrimitive::setTEMediaFlags(const U8 index, const U8 media_flags) { // if we're asking for a non-existent face, return null if (te >= mNumTEs) @@ -553,10 +443,10 @@ S32 LLPrimitive::setTEMediaFlags(const U8 te, const U8 media_flags) return 0; } - return mTextureList[te].setMediaFlags( media_flags ); + return mTextureList.setMediaFlags(index, media_flags); } -S32 LLPrimitive::setTEGlow(const U8 te, const F32 glow) +S32 LLPrimitive::setTEGlow(const U8 index, const F32 glow) { // if we're asking for a non-existent face, return null if (te >= mNumTEs) @@ -565,7 +455,7 @@ S32 LLPrimitive::setTEGlow(const U8 te, const F32 glow) return 0; } - return mTextureList[te].setGlow( glow ); + return mTextureList.setGlow(index, glow); } @@ -877,25 +767,18 @@ std::string LLPrimitive::pCodeToString(const LLPCode pcode) void LLPrimitive::copyTEs(const LLPrimitive *primitivep) { U32 i; - if (primitivep->getNumTEs() != getNumTEs()) + if (primitivep->getExpectedNumTEs() != getExpectedNumTEs()) + { + llwarns << "Primitives don't have same expected number of TE's" << llendl; + } + U32 num_tes = llmin(primitivep->getExpectedNumTEs(), getExpectedNumTEs()); + if (mTextureList.size() < getExpectedNumTEs()) { - llwarns << "Primitives don't have same number of TE's" << llendl; + mTextureList.setSize(getExpectedNumTEs()); } - U32 num_tes = llmin(primitivep->getNumTEs(), getNumTEs()); for (i = 0; i < num_tes; i++) { - const LLTextureEntry *tep = primitivep->getTE(i); - F32 s, t; - setTETexture(i, tep->getID()); - setTEColor(i, tep->getColor()); - tep->getScale(&s, &t); - setTEScale(i, s, t); - tep->getOffset(&s, &t); - setTEOffset(i, s, t); - setTERotation(i, tep->getRotation()); - setTEBumpShinyFullbright(i, tep->getBumpShinyFullbright()); - setTEMediaTexGen(i, tep->getMediaTexGen()); - setTEGlow(i, tep->getGlow()); + mTextureList.copyTexture(i, *(primitivep->getTE(i))); } } @@ -957,73 +840,209 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai U32 old_face_mask = mVolumep->mFaceMask; + + S32 face_bit = 0; + S32 cur_mask = 0; + + // Grab copies of the old faces from the original shape, ordered by type. + // We will use these to figure out what old texture info gets mapped to new + // faces in the new shape. + std::vector<LLProfile::Face> old_faces; + for (S32 face = 0; face < mVolumep->getNumFaces(); face++) + { + old_faces.push_back(mVolumep->getProfile().mFaces[face]); + } + + // Copy the old texture info off to the side, but not in the order in which + // they live in the mTextureList, rather in order of ther "face id" which + // is the corresponding value of LLVolueParams::LLProfile::mFaces::mIndex. + // + // Hence, some elements of old_tes::mEntryList will be invalid. It is + // initialized to a size of 9 (max number of possible faces on a volume?) + // and only the ones with valid types are filled in. + LLPrimTextureList old_tes; + old_tes.setSize(9); + for (face_bit = 0; face_bit < 9; face_bit++) + { + cur_mask = 0x1 << face_bit; + if (old_face_mask & cur_mask) + { + S32 te_index = face_index_from_id(cur_mask, old_faces); + old_tes.copyTexture(face_bit, *(getTE(te_index))); + //llinfos << face_bit << ":" << te_index << ":" << old_tes[face_bit].getID() << llendl; + } + } + + // build the new object sVolumeManager->unrefVolume(mVolumep); mVolumep = volumep; - U32 new_face_mask = mVolumep->mFaceMask; - if (old_face_mask != new_face_mask) - { - setNumTEs(mVolumep->getNumFaces()); - } - - return TRUE; -} + U32 new_face_mask = mVolumep->mFaceMask; + S32 i; -BOOL LLPrimitive::setMaterial(U8 material) -{ - if (material != mMaterial) + if (old_face_mask == new_face_mask) { - mMaterial = material; + setNumTEs(mVolumep->getNumFaces()); return TRUE; } - else - { - return FALSE; - } -} -void LLPrimitive::setTEArrays(const U8 size, - const LLUUID* image_ids, - const F32* scale_s, - const F32* scale_t) -{ - S32 cur_size = size; - if (cur_size > getNumTEs()) + // initialize face_mapping + S32 face_mapping[9]; + for (face_bit = 0; face_bit < 9; face_bit++) { - llwarns << "Trying to set more TEs than exist!" << llendl; - cur_size = getNumTEs(); + face_mapping[face_bit] = face_bit; } - S32 i; - // Copy over image information - for (i = 0; i < cur_size; i++) + // The new shape may have more faces than the original, but we can't just + // add them to the end -- the ordering matters and it may be that we must + // insert the new faces in the middle of the list. When we add a face it + // will pick up the texture/color info of one of the old faces an so we + // now figure out which old face info gets mapped to each new face, and + // store in the face_mapping lookup table. + for (face_bit = 0; face_bit < 9; face_bit++) { - // This is very BAD!!!!!! - if (image_ids != NULL) + cur_mask = 0x1 << face_bit; + if (!(new_face_mask & cur_mask)) { - setTETexture(i,image_ids[i]); + // Face doesn't exist in new map. + face_mapping[face_bit] = -1; + continue; } - if (scale_s && scale_t) + else if (old_face_mask & cur_mask) { - setTEScale(i, scale_s[i], scale_t[i]); + // Face exists in new and old map. + face_mapping[face_bit] = face_bit; + continue; } - } - if (i < getNumTEs()) - { - cur_size--; - for (i=i; i < getNumTEs(); i++) // the i=i removes a gcc warning + // OK, how we've got a mismatch, where we have to fill a new face with one from + // the old face. + if (cur_mask & (LL_FACE_PATH_BEGIN | LL_FACE_PATH_END | LL_FACE_INNER_SIDE)) { - if (image_ids != NULL) + // It's a top/bottom/hollow interior face. + if (old_face_mask & LL_FACE_PATH_END) { - setTETexture(i, image_ids[cur_size]); + face_mapping[face_bit] = 1; + continue; } - if (scale_s && scale_t) + else { - setTEScale(i, scale_s[cur_size], scale_t[cur_size]); + S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0; + for (i = 0; i < 4; i++) + { + if (old_face_mask & cur_outer_mask) + { + face_mapping[face_bit] = 5 + i; + break; + } + cur_outer_mask <<= 1; + } + if (i == 4) + { + llwarns << "No path end or outer face in volume!" << llendl; + } + continue; + } + } + + if (cur_mask & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END)) + { + // A cut slice. Use the hollow interior if we have it. + if (old_face_mask & LL_FACE_INNER_SIDE) + { + face_mapping[face_bit] = 2; + continue; + } + + // No interior, use the bottom face. + // Could figure out which of the outer faces was nearest, but that would be harder. + if (old_face_mask & LL_FACE_PATH_END) + { + face_mapping[face_bit] = 1; + continue; + } + else + { + S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0; + for (i = 0; i < 4; i++) + { + if (old_face_mask & cur_outer_mask) + { + face_mapping[face_bit] = 5 + i; + break; + } + cur_outer_mask <<= 1; + } + if (i == 4) + { + llwarns << "No path end or outer face in volume!" << llendl; + } + continue; + } + } + + // OK, the face that's missing is an outer face... + // Pull from the nearest adjacent outer face (there's always guaranteed to be one... + S32 cur_outer = face_bit - 5; + S32 min_dist = 5; + S32 min_outer_bit = -1; + S32 i; + for (i = 0; i < 4; i++) + { + if (old_face_mask & (LL_FACE_OUTER_SIDE_0 << i)) + { + S32 dist = abs(i - cur_outer); + if (dist < min_dist) + { + min_dist = dist; + min_outer_bit = i + 5; + } } } + if (-1 == min_outer_bit) + { + llinfos << (LLVolume *)mVolumep << llendl; + llwarns << "Bad! No outer faces, impossible!" << llendl; + } + face_mapping[face_bit] = min_outer_bit; + } + + + setNumTEs(mVolumep->getNumFaces()); + for (face_bit = 0; face_bit < 9; face_bit++) + { + // For each possible face type on the new shape we check to see if that + // face exists and if it does we create a texture entry that is a copy + // of one of the originals. Since the originals might not have a + // matching face, we use the face_mapping lookup table to figure out + // which face information to copy. + cur_mask = 0x1 << face_bit; + if (new_face_mask & cur_mask) + { + if (-1 == face_mapping[face_bit]) + { + llwarns << "No mapping from old face to new face!" << llendl; + } + + S32 te_num = face_index_from_id(cur_mask, mVolumep->getProfile().mFaces); + setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit]))); + } + } +>>>>>>> 5faaca1... port llprimitive from SG2.0 + return TRUE; +} + +BOOL LLPrimitive::setMaterial(U8 material) +{ + if (material != mMaterial) + { + mMaterial = material; + return TRUE; + } + else + { + return FALSE; } } @@ -1178,6 +1197,7 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys, int shield) const else memcpy(&image_ids[face_index*16],LLUUID("4934f1bf-3b1f-cf4f-dbdf-a72550d05bc6").mData,16);//grey block }else memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); /* Flawfinder: ignore */ + // Cast LLColor4 to LLColor4U coloru.setVec( getTE(face_index)->getColor() ); @@ -1402,6 +1422,7 @@ S32 LLPrimitive::unpackTEMessage(LLMessageSystem *mesgsys, char *block_name, con color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f; retval |= setTEColor(i, color); + } return retval; @@ -1501,11 +1522,24 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) return retval; } -void LLPrimitive::setTextureList(LLTextureEntry *listp) +U8 LLPrimitive::getExpectedNumTEs() const +{ + U8 expected_face_count = 0; + if (mVolumep) + { + expected_face_count = mVolumep->getNumFaces(); + } + return expected_face_count; +} + +void LLPrimitive::copyTextureList(const LLPrimTextureList& other_list) +{ + mTextureList.copy(other_list); +} + +void LLPrimitive::takeTextureList(LLPrimTextureList& other_list) { - LLTextureEntry* old_texture_list = mTextureList; - mTextureList = listp; - delete[] old_texture_list; + mTextureList.take(other_list); } //============================================================================ @@ -1569,6 +1603,8 @@ BOOL LLNetworkData::isValid(U16 param_type, U32 size) return (size == 16); case PARAMS_SCULPT: return (size == 17); + case PARAMS_LIGHT_IMAGE: + return (size == 28); } return FALSE; @@ -1901,3 +1937,78 @@ bool LLSculptParams::fromLLSD(LLSD& sd) return false; } +//============================================================================ + +LLLightImageParams::LLLightImageParams() +{ + mType = PARAMS_LIGHT_IMAGE; + mParams.setVec(F_PI*0.5f, 0.f, 0.f); +} + +BOOL LLLightImageParams::pack(LLDataPacker &dp) const +{ + dp.packUUID(mLightTexture, "texture"); + dp.packVector3(mParams, "params"); + + return TRUE; +} + +BOOL LLLightImageParams::unpack(LLDataPacker &dp) +{ + dp.unpackUUID(mLightTexture, "texture"); + dp.unpackVector3(mParams, "params"); + + return TRUE; +} + +bool LLLightImageParams::operator==(const LLNetworkData& data) const +{ + if (data.mType != PARAMS_LIGHT_IMAGE) + { + return false; + } + + const LLLightImageParams *param = (const LLLightImageParams*)&data; + if ( (param->mLightTexture != mLightTexture) ) + { + return false; + } + + if ( (param->mParams != mParams ) ) + { + return false; + } + + return true; +} + +void LLLightImageParams::copy(const LLNetworkData& data) +{ + const LLLightImageParams *param = (LLLightImageParams*)&data; + mLightTexture = param->mLightTexture; + mParams = param->mParams; +} + + + +LLSD LLLightImageParams::asLLSD() const +{ + LLSD sd; + + sd["texture"] = mLightTexture; + sd["params"] = mParams.getValue(); + + return sd; +} + +bool LLLightImageParams::fromLLSD(LLSD& sd) +{ + if (sd.has("texture")) + { + setLightTexture( sd["texture"] ); + setParams( LLVector3( sd["params"] ) ); + return true; + } + + return false; +} diff --git a/linden/indra/llprimitive/llprimitive.h b/linden/indra/llprimitive/llprimitive.h old mode 100644 new mode 100755 index efabb82..e146fbe --- a/linden/indra/llprimitive/llprimitive.h +++ b/linden/indra/llprimitive/llprimitive.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2001&license=viewergpl$ * - * Copyright (c) 2001-2009, Linden Research, Inc. + * Copyright (c) 2001-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -37,9 +37,11 @@ #include "v3math.h" #include "xform.h" #include "message.h" -#include "llmemory.h" +#include "llmemory.h" // not in SG2.0 +//#include "llpointer.h"// instead in SG2.0 #include "llvolume.h" #include "lltextureentry.h" +#include "llprimtexturelist.h" // Moved to stdtypes.h --JC // typedef U8 LLPCode; @@ -105,7 +107,8 @@ public: { PARAMS_FLEXIBLE = 0x10, PARAMS_LIGHT = 0x20, - PARAMS_SCULPT = 0x30 + PARAMS_SCULPT = 0x30, + PARAMS_LIGHT_IMAGE = 0x40, }; public: @@ -260,11 +263,33 @@ public: bool fromLLSD(LLSD& sd); void setSculptTexture(const LLUUID& id) { mSculptTexture = id; } - LLUUID getSculptTexture() { return mSculptTexture; } + LLUUID getSculptTexture() const { return mSculptTexture; } void setSculptType(U8 type) { mSculptType = type; } - U8 getSculptType() { return mSculptType; } + U8 getSculptType() const { return mSculptType; } }; +class LLLightImageParams : public LLNetworkData +{ +protected: + LLUUID mLightTexture; + LLVector3 mParams; + +public: + LLLightImageParams(); + /*virtual*/ BOOL pack(LLDataPacker &dp) const; + /*virtual*/ BOOL unpack(LLDataPacker &dp); + /*virtual*/ bool operator==(const LLNetworkData& data) const; + /*virtual*/ void copy(const LLNetworkData& data); + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + void setLightTexture(const LLUUID& id) { mLightTexture = id; } + LLUUID getLightTexture() const { return mLightTexture; } + void setParams(const LLVector3& params) { mParams = params; } + LLVector3 getParams() const { return mParams; } + +}; class LLPrimitive : public LLXform @@ -294,6 +319,8 @@ public: LLPrimitive(); virtual ~LLPrimitive(); + void clearTextureList(); + static LLPrimitive *createPrimitive(LLPCode p_code); void init_primitive(LLPCode p_code); @@ -304,11 +331,11 @@ public: // Modify texture entry properties inline BOOL validTE(const U8 te_num) const; - const LLTextureEntry *getTE(const U8 te_num) const; + LLTextureEntry* getTE(const U8 te_num) const; virtual void setNumTEs(const U8 num_tes); virtual void setAllTETextures(const LLUUID &tex_id); - virtual void setTE(const U8 index, const LLTextureEntry &te); + virtual void setTE(const U8 index, const LLTextureEntry& te); virtual S32 setTEColor(const U8 te, const LLColor4 &color); virtual S32 setTEColor(const U8 te, const LLColor3 &color); virtual S32 setTEAlpha(const U8 te, const F32 alpha); @@ -331,10 +358,6 @@ public: virtual S32 setTEGlow(const U8 te, const F32 glow); virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed - void setTEArrays(const U8 size, - const LLUUID* image_ids, - const F32* scale_s, - const F32* scale_t); void copyTEs(const LLPrimitive *primitive); S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const; S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type); @@ -382,14 +405,21 @@ public: const LLVector3& getAngularVelocity() const { return mAngularVelocity; } const LLVector3& getVelocity() const { return mVelocity; } const LLVector3& getAcceleration() const { return mAcceleration; } - U8 getNumTEs() const { return mNumTEs; } + U8 getNumTEs() const { return mTextureList.size(); } + U8 getExpectedNumTEs() const; U8 getMaterial() const { return mMaterial; } void setVolumeType(const U8 code); U8 getVolumeType(); - void setTextureList(LLTextureEntry *listp); + // clears existing textures + // copies the contents of other_list into mEntryList + void copyTextureList(const LLPrimTextureList& other_list); + + // clears existing textures + // takes the contents of other_list and clears other_list + void takeTextureList(LLPrimTextureList& other_list); inline BOOL isAvatar() const; inline BOOL isSittingAvatar() const; @@ -414,7 +444,7 @@ protected: LLVector3 mAcceleration; // are we under constant acceleration? LLVector3 mAngularVelocity; // angular velocity LLPointer<LLVolume> mVolumep; - LLTextureEntry *mTextureList; // list of texture GUIDs, scales, offsets + LLPrimTextureList mTextureList; // list of texture GUIDs, scales, offsets U8 mMaterial; // Material code U8 mNumTEs; // # of faces on the primitve U32 mMiscFlags; // home for misc bools diff --git a/linden/indra/llprimitive/llprimlinkinfo.h b/linden/indra/llprimitive/llprimlinkinfo.h old mode 100644 new mode 100755 index 946fa75..dfe33c1 --- a/linden/indra/llprimitive/llprimlinkinfo.h +++ b/linden/indra/llprimitive/llprimlinkinfo.h @@ -5,7 +5,7 @@ * * $LicenseInfo:firstyear=2007&license=viewergpl$ * - * Copyright (c) 2007-2009, Linden Research, Inc. + * Copyright (c) 2007-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab diff --git a/linden/indra/llprimitive/llprimtexturelist.cpp b/linden/indra/llprimitive/llprimtexturelist.cpp new file mode 100755 index 0000000..691eb76 --- /dev/null +++ b/linden/indra/llprimitive/llprimtexturelist.cpp @@ -0,0 +1,424 @@ +/** + * @file lltexturelist.cpp + * @brief LLPrimTextureList (virtual) base class + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llprimtexturelist.h" +#include "lltextureentry.h" +#include "llmemtype.h" + +// static +//int (TMyClass::*pt2Member)(float, char, char) = NULL; // C++ +LLTextureEntry* (*LLPrimTextureList::sNewTextureEntryCallback)() = &(LLTextureEntry::newTextureEntry); + +// static +void LLPrimTextureList::setNewTextureEntryCallback( LLTextureEntry* (*callback)() ) +{ + if (callback) + { + LLPrimTextureList::sNewTextureEntryCallback = callback; + } + else + { + LLPrimTextureList::sNewTextureEntryCallback = &(LLTextureEntry::newTextureEntry); + } +} + +// static +// call this to get a new texture entry +LLTextureEntry* LLPrimTextureList::newTextureEntry() +{ + return (*sNewTextureEntryCallback)(); +} + +LLPrimTextureList::LLPrimTextureList() +{ +} + +// virtual +LLPrimTextureList::~LLPrimTextureList() +{ + clear(); +} + +void LLPrimTextureList::clear() +{ + texture_list_t::iterator itr = mEntryList.begin(); + while (itr != mEntryList.end()) + { + delete (*itr); + (*itr) = NULL; + ++itr; + } + mEntryList.clear(); +} + + +// clears current entries +// copies contents of other_list +// this is somewhat expensive, so it must be called explicitly +void LLPrimTextureList::copy(const LLPrimTextureList& other_list) +{ + // compare the sizes + S32 this_size = mEntryList.size(); + S32 other_size = other_list.mEntryList.size(); + + if (this_size > other_size) + { + // remove the extra entries + for (S32 index = this_size; index > other_size; --index) + { + delete mEntryList[index-1]; + } + mEntryList.resize(other_size); + this_size = other_size; + } + + S32 index = 0; + // copy for the entries that already exist + for ( ; index < this_size; ++index) + { + delete mEntryList[index]; + mEntryList[index] = other_list.getTexture(index)->newCopy(); + } + + // add new entires if needed + for ( ; index < other_size; ++index) + { + mEntryList.push_back( other_list.getTexture(index)->newCopy() ); + } +} + +// clears current copies +// takes contents of other_list +// clears other_list +void LLPrimTextureList::take(LLPrimTextureList& other_list) +{ + clear(); + mEntryList = other_list.mEntryList; + other_list.mEntryList.clear(); +} + +// virtual +// copies LLTextureEntry 'te' +// returns TEM_CHANGE_TEXTURE if successful, otherwise TEM_CHANGE_NONE +S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry& te) +{ + if (S32(index) >= mEntryList.size()) + { + S32 current_size = mEntryList.size(); + llwarns << "ignore copy of index = " << S32(index) << " into texture entry list of size = " << current_size << llendl; + return TEM_CHANGE_NONE; + } + + // we're changing an existing entry + llassert(mEntryList[index]); + delete (mEntryList[index]); + if (&te) + { + mEntryList[index] = te.newCopy(); + } + else + { + mEntryList[index] = LLPrimTextureList::newTextureEntry(); + } + return TEM_CHANGE_TEXTURE; +} + +// virtual +// takes ownership of LLTextureEntry* 'te' +// returns TEM_CHANGE_TEXTURE if successful, otherwise TEM_CHANGE_NONE +// IMPORTANT! -- if you use this function you must check the return value +S32 LLPrimTextureList::takeTexture(const U8 index, LLTextureEntry* te) +{ + if (S32(index) >= mEntryList.size()) + { + return TEM_CHANGE_NONE; + } + + // we're changing an existing entry + llassert(mEntryList[index]); + delete (mEntryList[index]); + mEntryList[index] = te; + return TEM_CHANGE_TEXTURE; +} + +// returns pointer to texture at 'index' slot +LLTextureEntry* LLPrimTextureList::getTexture(const U8 index) const +{ + if (index < mEntryList.size()) + { + return mEntryList[index]; + } + return NULL; +} + +//virtual +//S32 setTE(const U8 index, const LLTextureEntry& te) = 0; + +S32 LLPrimTextureList::setID(const U8 index, const LLUUID& id) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setID(id); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setColor(const U8 index, const LLColor3& color) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setColor(color); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setColor(const U8 index, const LLColor4& color) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setColor(color); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setAlpha(const U8 index, const F32 alpha) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setAlpha(alpha); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setScale(const U8 index, const F32 s, const F32 t) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setScale(s, t); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setScaleS(const U8 index, const F32 s) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setScaleS(s); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setScaleT(const U8 index, const F32 t) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setScaleT(t); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setOffset(const U8 index, const F32 s, const F32 t) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setOffset(s, t); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setOffsetS(const U8 index, const F32 s) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setOffsetS(s); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setOffsetT(const U8 index, const F32 t) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setOffsetT(t); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setRotation(const U8 index, const F32 r) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setRotation(r); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setBumpShinyFullbright(const U8 index, const U8 bump) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setBumpShinyFullbright(bump); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setMediaTexGen(const U8 index, const U8 media) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setMediaTexGen(media); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setBumpMap(const U8 index, const U8 bump) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setBumpmap(bump); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setBumpShiny(const U8 index, const U8 bump_shiny) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setBumpShiny(bump_shiny); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setTexGen(const U8 index, const U8 texgen) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setTexGen(texgen); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setShiny(const U8 index, const U8 shiny) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setShiny(shiny); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setFullbright(const U8 index, const U8 fullbright) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setFullbright(fullbright); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setMediaFlags(const U8 index, const U8 media_flags) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setMediaFlags(media_flags); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::setGlow(const U8 index, const F32 glow) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setGlow(glow); + } + return TEM_CHANGE_NONE; +} + +S32 LLPrimTextureList::size() const +{ + return mEntryList.size(); +} + +// sets the size of the mEntryList container +void LLPrimTextureList::setSize(S32 new_size) +{ + LLMemType m1(LLMemType::MTYPE_PRIMITIVE); + if (new_size < 0) + { + new_size = 0; + } + + S32 current_size = mEntryList.size(); + + if (new_size > current_size) + { + mEntryList.resize(new_size); + for (S32 index = current_size; index < new_size; ++index) + { + if (current_size > 0 + && mEntryList[current_size - 1]) + { + // copy the last valid entry for the new one + mEntryList[index] = mEntryList[current_size - 1]->newCopy(); + } + else + { + // no valid enries to copy, so we new one up + LLTextureEntry* new_entry = LLPrimTextureList::newTextureEntry(); + mEntryList[index] = new_entry; + } + } + } + else if (new_size < current_size) + { + for (S32 index = current_size-1; index >= new_size; --index) + { + delete mEntryList[index]; + } + mEntryList.resize(new_size); + } +} + + +void LLPrimTextureList::setAllIDs(const LLUUID& id) +{ + texture_list_t::iterator itr = mEntryList.begin(); + while (itr != mEntryList.end()) + { + (*itr)->setID(id); + ++itr; + } +} + + diff --git a/linden/indra/llprimitive/llprimtexturelist.h b/linden/indra/llprimitive/llprimtexturelist.h new file mode 100755 index 0000000..c62f7b9 --- /dev/null +++ b/linden/indra/llprimitive/llprimtexturelist.h @@ -0,0 +1,127 @@ +/** + * @file llprimtexturelist.h + * @brief LLPrimTextureList (virtual) base class + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPRIMTEXTURELIST_H +#define LL_LLPRIMTEXTURELIST_H + +#include <vector> +#include "lluuid.h" +#include "v3color.h" +#include "v4color.h" + + +class LLTextureEntry; + +// this is a list of LLTextureEntry*'s because in practice the list's elements +// are of some derived class: LLFooTextureEntry +typedef std::vector<LLTextureEntry*> texture_list_t; + +class LLPrimTextureList +{ +public: + // the LLPrimTextureList needs to know what type of LLTextureEntry + // to generate when it needs a new one, so we may need to set a + // callback for generating it, (or else use the base class default: + // static LLPrimTextureEntry::newTextureEntry() ) + //typedef LLTextureEntry* (__stdcall *NewTextureEntryFunction)(); + //static NewTextureEntryFunction sNewTextureEntryCallback; + static LLTextureEntry* newTextureEntry(); + static void setNewTextureEntryCallback( LLTextureEntry* (*callback)() ); + static LLTextureEntry* (*sNewTextureEntryCallback)(); + + LLPrimTextureList(); + virtual ~LLPrimTextureList(); + + void clear(); + + // clears current entries + // copies contents of other_list + // this is somewhat expensive, so it must be called explicitly + void copy(const LLPrimTextureList& other_list); + + // clears current copies + // takes contents of other_list + // clears other_list + void take(LLPrimTextureList& other_list); + + // copies LLTextureEntry 'te' + // returns TEM_CHANGE_TEXTURE if successful, otherwise TEM_CHANGE_NONE + S32 copyTexture(const U8 index, const LLTextureEntry& te); + + // takes ownership of LLTextureEntry* 'te' + // returns TEM_CHANGE_TEXTURE if successful, otherwise TEM_CHANGE_NONE + // IMPORTANT! -- if you use this function you must check the return value + S32 takeTexture(const U8 index, LLTextureEntry* te); + +// // copies contents of 'entry' and stores it in 'index' slot +// void copyTexture(const U8 index, const LLTextureEntry* entry); + + // returns pointer to texture at 'index' slot + LLTextureEntry* getTexture(const U8 index) const; + + S32 setID(const U8 index, const LLUUID& id); + S32 setColor(const U8 index, const LLColor3& color); + S32 setColor(const U8 index, const LLColor4& color); + S32 setAlpha(const U8 index, const F32 alpha); + S32 setScale(const U8 index, const F32 s, const F32 t); + S32 setScaleS(const U8 index, const F32 s); + S32 setScaleT(const U8 index, const F32 t); + S32 setOffset(const U8 index, const F32 s, const F32 t); + S32 setOffsetS(const U8 index, const F32 s); + S32 setOffsetT(const U8 index, const F32 t); + S32 setRotation(const U8 index, const F32 r); + S32 setBumpShinyFullbright(const U8 index, const U8 bump); + S32 setMediaTexGen(const U8 index, const U8 media); + S32 setBumpMap(const U8 index, const U8 bump); + S32 setBumpShiny(const U8 index, const U8 bump_shiny); + S32 setTexGen(const U8 index, const U8 texgen); + S32 setShiny(const U8 index, const U8 shiny); + S32 setFullbright(const U8 index, const U8 t); + S32 setMediaFlags(const U8 index, const U8 media_flags); + S32 setGlow(const U8 index, const F32 glow); + + S32 size() const; + +// void forceResize(S32 new_size); + void setSize(S32 new_size); + + void setAllIDs(const LLUUID& id); +protected: + texture_list_t mEntryList; +private: + LLPrimTextureList(const LLPrimTextureList& other_list) + { + // private so that it can't be used + } +}; + +#endif diff --git a/linden/indra/llprimitive/lltextureentry.cpp b/linden/indra/llprimitive/lltextureentry.cpp old mode 100644 new mode 100755 index 14b4544..11afdc0 --- a/linden/indra/llprimitive/lltextureentry.cpp +++ b/linden/indra/llprimitive/lltextureentry.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2001&license=viewergpl$ * - * Copyright (c) 2001-2009, Linden Research, Inc. + * Copyright (c) 2001-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -32,25 +32,52 @@ #include "linden_common.h" +#include "lluuid.h" +#include "llmediaentry.h" #include "lltextureentry.h" -#include "llsdutil.h" +#include "llsdutil.h"//_math.h" +#include "v4color.h" const U8 DEFAULT_BUMP_CODE = 0; // no bump or shininess const LLTextureEntry LLTextureEntry::null; +// Some LLSD keys. Do not change these! +#define OBJECT_ID_KEY_STR "object_id" +#define TEXTURE_INDEX_KEY_STR "texture_index" +#define OBJECT_MEDIA_VERSION_KEY_STR "object_media_version" +#define OBJECT_MEDIA_DATA_KEY_STR "object_media_data" +#define TEXTURE_MEDIA_DATA_KEY_STR "media_data" + +/*static*/ const char* LLTextureEntry::OBJECT_ID_KEY = OBJECT_ID_KEY_STR; +/*static*/ const char* LLTextureEntry::OBJECT_MEDIA_DATA_KEY = OBJECT_MEDIA_DATA_KEY_STR; +/*static*/ const char* LLTextureEntry::MEDIA_VERSION_KEY = OBJECT_MEDIA_VERSION_KEY_STR; +/*static*/ const char* LLTextureEntry::TEXTURE_INDEX_KEY = TEXTURE_INDEX_KEY_STR; +/*static*/ const char* LLTextureEntry::TEXTURE_MEDIA_DATA_KEY = TEXTURE_MEDIA_DATA_KEY_STR; + +static const std::string MEDIA_VERSION_STRING_PREFIX = "x-mv:"; + +// static +LLTextureEntry* LLTextureEntry::newTextureEntry() +{ + return new LLTextureEntry(); +} + //=============================================================== LLTextureEntry::LLTextureEntry() + : mMediaEntry(NULL) { init(LLUUID::null,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE); } LLTextureEntry::LLTextureEntry(const LLUUID& tex_id) + : mMediaEntry(NULL) { init(tex_id,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE); } LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs) + : mMediaEntry(NULL) { mID = rhs.mID; mScaleS = rhs.mScaleS; @@ -62,6 +89,10 @@ LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs) mBump = rhs.mBump; mMediaFlags = rhs.mMediaFlags; mGlow = rhs.mGlow; + if (rhs.mMediaEntry != NULL) { + // Make a copy + mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry); + } } LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs) @@ -78,6 +109,16 @@ LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs) mBump = rhs.mBump; mMediaFlags = rhs.mMediaFlags; mGlow = rhs.mGlow; + if (mMediaEntry != NULL) { + delete mMediaEntry; + } + if (rhs.mMediaEntry != NULL) { + // Make a copy + mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry); + } + else { + mMediaEntry = NULL; + } } return *this; @@ -97,10 +138,19 @@ void LLTextureEntry::init(const LLUUID& tex_id, F32 scale_s, F32 scale_t, F32 of mGlow = 0; setColor(LLColor4(1.f, 1.f, 1.f, 1.f)); + if (mMediaEntry != NULL) { + delete mMediaEntry; + } + mMediaEntry = NULL; } LLTextureEntry::~LLTextureEntry() { + if(mMediaEntry) + { + delete mMediaEntry; + mMediaEntry = NULL; + } } bool LLTextureEntry::operator!=(const LLTextureEntry &rhs) const @@ -136,23 +186,33 @@ bool LLTextureEntry::operator==(const LLTextureEntry &rhs) const LLSD LLTextureEntry::asLLSD() const { LLSD sd; + asLLSD(sd); + return sd; +} - sd["imageid"] = getID(); - sd["colors"] = ll_sd_from_color4(getColor()); +void LLTextureEntry::asLLSD(LLSD& sd) const +{ + sd["imageid"] = mID; + sd["colors"] = ll_sd_from_color4(mColor); sd["scales"] = mScaleS; sd["scalet"] = mScaleT; sd["offsets"] = mOffsetS; sd["offsett"] = mOffsetT; - sd["imagerot"] = getRotation(); + sd["imagerot"] = mRotation; sd["bump"] = getBumpShiny(); sd["fullbright"] = getFullbright(); - sd["media_flags"] = getMediaTexGen(); - sd["glow"] = getGlow(); - - return sd; + sd["media_flags"] = mMediaFlags; + if (hasMedia()) { + LLSD mediaData; + if (NULL != getMediaData()) { + getMediaData()->asLLSD(mediaData); + } + sd[TEXTURE_MEDIA_DATA_KEY] = mediaData; + } + sd["glow"] = mGlow; } -bool LLTextureEntry::fromLLSD(LLSD& sd) +bool LLTextureEntry::fromLLSD(const LLSD& sd) { const char *w, *x; w = "imageid"; @@ -197,6 +257,17 @@ bool LLTextureEntry::fromLLSD(LLSD& sd) { setMediaTexGen( sd[w].asInteger() ); } else goto fail; + // If the "has media" flag doesn't match the fact that + // media data exists, updateMediaData will "fix" it + // by either clearing or setting the flag + w = TEXTURE_MEDIA_DATA_KEY; + if (hasMedia() != sd.has(w)) + { + llwarns << "LLTextureEntry::fromLLSD: media_flags (" << hasMedia() << + ") does not match presence of media_data (" << sd.has(w) << "). Fixing." << llendl; + } + updateMediaData(sd[w]); + w = "glow"; if (sd.has(w)) { @@ -208,6 +279,19 @@ fail: return false; } +// virtual +// override this method for each derived class +LLTextureEntry* LLTextureEntry::newBlank() const +{ + return new LLTextureEntry(); +} + +// virtual +LLTextureEntry* LLTextureEntry::newCopy() const +{ + return new LLTextureEntry(*this); +} + S32 LLTextureEntry::setID(const LLUUID &tex_id) { if (mID != tex_id) @@ -215,7 +299,7 @@ S32 LLTextureEntry::setID(const LLUUID &tex_id) mID = tex_id; return TEM_CHANGE_TEXTURE; } - return 0; + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setScale(F32 s, F32 t) @@ -233,6 +317,28 @@ S32 LLTextureEntry::setScale(F32 s, F32 t) return retval; } +S32 LLTextureEntry::setScaleS(F32 s) +{ + S32 retval = TEM_CHANGE_NONE; + if (mScaleS != s) + { + mScaleS = s; + retval = TEM_CHANGE_TEXTURE; + } + return retval; +} + +S32 LLTextureEntry::setScaleT(F32 t) +{ + S32 retval = TEM_CHANGE_NONE; + if (mScaleT != t) + { + mScaleT = t; + retval = TEM_CHANGE_TEXTURE; + } + return retval; +} + S32 LLTextureEntry::setColor(const LLColor4 &color) { if (mColor != color) @@ -240,7 +346,7 @@ S32 LLTextureEntry::setColor(const LLColor4 &color) mColor = color; return TEM_CHANGE_COLOR; } - return 0; + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setColor(const LLColor3 &color) @@ -251,7 +357,7 @@ S32 LLTextureEntry::setColor(const LLColor3 &color) mColor.setVec(color); return TEM_CHANGE_COLOR; } - return 0; + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setAlpha(const F32 alpha) @@ -261,7 +367,7 @@ S32 LLTextureEntry::setAlpha(const F32 alpha) mColor.mV[VW] = alpha; return TEM_CHANGE_COLOR; } - return 0; + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setOffset(F32 s, F32 t) @@ -279,6 +385,28 @@ S32 LLTextureEntry::setOffset(F32 s, F32 t) return retval; } +S32 LLTextureEntry::setOffsetS(F32 s) +{ + S32 retval = 0; + if (mOffsetS != s) + { + mOffsetS = s; + retval = TEM_CHANGE_TEXTURE; + } + return retval; +} + +S32 LLTextureEntry::setOffsetT(F32 t) +{ + S32 retval = 0; + if (mOffsetT != t) + { + mOffsetT = t; + retval = TEM_CHANGE_TEXTURE; + } + return retval; +} + S32 LLTextureEntry::setRotation(F32 theta) { if (mRotation != theta) @@ -286,7 +414,7 @@ S32 LLTextureEntry::setRotation(F32 theta) mRotation = theta; return TEM_CHANGE_TEXTURE; } - return 0; + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setBumpShinyFullbright(U8 bump) @@ -296,7 +424,7 @@ S32 LLTextureEntry::setBumpShinyFullbright(U8 bump) mBump = bump; return TEM_CHANGE_TEXTURE; } - return 0; + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setMediaTexGen(U8 media) @@ -304,9 +432,21 @@ S32 LLTextureEntry::setMediaTexGen(U8 media) if (mMediaFlags != media) { mMediaFlags = media; - return TEM_CHANGE_TEXTURE; + + // Special code for media handling + if( hasMedia() && mMediaEntry == NULL) + { + mMediaEntry = new LLMediaEntry; + } + else if ( ! hasMedia() && mMediaEntry != NULL) + { + delete mMediaEntry; + mMediaEntry = NULL; + } + + return TEM_CHANGE_MEDIA; } - return 0; + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setBumpmap(U8 bump) @@ -318,7 +458,7 @@ S32 LLTextureEntry::setBumpmap(U8 bump) mBump |= bump; return TEM_CHANGE_TEXTURE; } - return 0; + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setFullbright(U8 fullbright) @@ -330,7 +470,7 @@ S32 LLTextureEntry::setFullbright(U8 fullbright) mBump |= fullbright << TEM_FULLBRIGHT_SHIFT; return TEM_CHANGE_TEXTURE; } - return 0; + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setShiny(U8 shiny) @@ -342,7 +482,7 @@ S32 LLTextureEntry::setShiny(U8 shiny) mBump |= shiny << TEM_SHINY_SHIFT; return TEM_CHANGE_TEXTURE; } - return 0; + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setBumpShiny(U8 bump_shiny) @@ -354,7 +494,7 @@ S32 LLTextureEntry::setBumpShiny(U8 bump_shiny) mBump |= bump_shiny; return TEM_CHANGE_TEXTURE; } - return 0; + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setMediaFlags(U8 media_flags) @@ -364,9 +504,21 @@ S32 LLTextureEntry::setMediaFlags(U8 media_flags) { mMediaFlags &= ~TEM_MEDIA_MASK; mMediaFlags |= media_flags; - return TEM_CHANGE_TEXTURE; + + // Special code for media handling + if( hasMedia() && mMediaEntry == NULL) + { + mMediaEntry = new LLMediaEntry; + } + else if ( ! hasMedia() && mMediaEntry != NULL) + { + delete mMediaEntry; + mMediaEntry = NULL; + } + + return TEM_CHANGE_MEDIA; } - return 0; + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setTexGen(U8 tex_gen) @@ -378,7 +530,7 @@ S32 LLTextureEntry::setTexGen(U8 tex_gen) mMediaFlags |= tex_gen; return TEM_CHANGE_TEXTURE; } - return 0; + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setGlow(F32 glow) @@ -388,5 +540,115 @@ S32 LLTextureEntry::setGlow(F32 glow) mGlow = glow; return TEM_CHANGE_TEXTURE; } - return 0; + return TEM_CHANGE_NONE; +} + +void LLTextureEntry::setMediaData(const LLMediaEntry &media_entry) +{ + mMediaFlags |= MF_HAS_MEDIA; + if (NULL != mMediaEntry) + { + delete mMediaEntry; + } + mMediaEntry = new LLMediaEntry(media_entry); +} + +bool LLTextureEntry::updateMediaData(const LLSD& media_data) +{ + if (media_data.isUndefined()) + { + // clear the media data + clearMediaData(); + return false; + } + else { + mMediaFlags |= MF_HAS_MEDIA; + if (mMediaEntry == NULL) + { + mMediaEntry = new LLMediaEntry; + } + // *NOTE: this will *clobber* all of the fields in mMediaEntry + // with whatever fields are present (or not present) in media_data! + mMediaEntry->fromLLSD(media_data); + return true; + } +} + +void LLTextureEntry::clearMediaData() +{ + mMediaFlags &= ~MF_HAS_MEDIA; + if (mMediaEntry != NULL) { + delete mMediaEntry; + } + mMediaEntry = NULL; +} + +void LLTextureEntry::mergeIntoMediaData(const LLSD& media_fields) +{ + mMediaFlags |= MF_HAS_MEDIA; + if (mMediaEntry == NULL) + { + mMediaEntry = new LLMediaEntry; + } + // *NOTE: this will *merge* the data in media_fields + // with the data in our media entry + mMediaEntry->mergeFromLLSD(media_fields); +} + +//static +std::string LLTextureEntry::touchMediaVersionString(const std::string &in_version, const LLUUID &agent_id) +{ + // XXX TODO: make media version string binary (base64-encoded?) + // Media "URL" is a representation of a version and the last-touched agent + // x-mv:nnnnn/agent-id + // where "nnnnn" is version number + // *NOTE: not the most efficient code in the world... + U32 current_version = getVersionFromMediaVersionString(in_version) + 1; + const size_t MAX_VERSION_LEN = 10; // 2^32 fits in 10 decimal digits + char buf[MAX_VERSION_LEN+1]; + snprintf(buf, (int)MAX_VERSION_LEN+1, "%0*u", (int)MAX_VERSION_LEN, current_version); // added int cast to fix warning/breakage on mac. + return MEDIA_VERSION_STRING_PREFIX + buf + "/" + agent_id.asString(); +} + +//static +U32 LLTextureEntry::getVersionFromMediaVersionString(const std::string &version_string) +{ + U32 version = 0; + if (!version_string.empty()) + { + size_t found = version_string.find(MEDIA_VERSION_STRING_PREFIX); + if (found != std::string::npos) + { + found = version_string.find_first_of("/", found); + std::string v = version_string.substr(MEDIA_VERSION_STRING_PREFIX.length(), found); + version = strtoul(v.c_str(),NULL,10); + } + } + return version; +} + +//static +LLUUID LLTextureEntry::getAgentIDFromMediaVersionString(const std::string &version_string) +{ + LLUUID id; + if (!version_string.empty()) + { + size_t found = version_string.find(MEDIA_VERSION_STRING_PREFIX); + if (found != std::string::npos) + { + found = version_string.find_first_of("/", found); + if (found != std::string::npos) + { + std::string v = version_string.substr(found + 1); + id.set(v); + } + } + } + return id; +} + +//static +bool LLTextureEntry::isMediaVersionString(const std::string &version_string) +{ + return std::string::npos != version_string.find(MEDIA_VERSION_STRING_PREFIX); } diff --git a/linden/indra/llprimitive/lltextureentry.h b/linden/indra/llprimitive/lltextureentry.h old mode 100644 new mode 100755 index c562545..e70673e --- a/linden/indra/llprimitive/lltextureentry.h +++ b/linden/indra/llprimitive/lltextureentry.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2001&license=viewergpl$ * - * Copyright (c) 2001-2009, Linden Research, Inc. + * Copyright (c) 2001-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -37,9 +37,13 @@ #include "v4color.h" #include "llsd.h" +// These bits are used while unpacking TEM messages to tell which aspects of +// the texture entry changed. +const S32 TEM_CHANGE_NONE = 0x0; const S32 TEM_CHANGE_COLOR = 0x1; const S32 TEM_CHANGE_TEXTURE = 0x2; -const S32 TEM_INVALID = 0x4; +const S32 TEM_CHANGE_MEDIA = 0x4; +const S32 TEM_INVALID = 0x8; const S32 TEM_BUMPMAP_COUNT = 32; @@ -64,10 +68,13 @@ const S32 TEM_MEDIA_MASK = 0x01; const S32 TEM_TEX_GEN_MASK = 0x06; const S32 TEM_TEX_GEN_SHIFT = 1; +// forward declarations +class LLMediaEntry; class LLTextureEntry { public: + static LLTextureEntry* newTextureEntry(); typedef enum e_texgen { @@ -82,14 +89,18 @@ public: LLTextureEntry(const LLTextureEntry &rhs); LLTextureEntry &operator=(const LLTextureEntry &rhs); - ~LLTextureEntry(); + virtual ~LLTextureEntry(); bool operator==(const LLTextureEntry &rhs) const; bool operator!=(const LLTextureEntry &rhs) const; LLSD asLLSD() const; + void asLLSD(LLSD& sd) const; operator LLSD() const { return asLLSD(); } - bool fromLLSD(LLSD& sd); + bool fromLLSD(const LLSD& sd); + + virtual LLTextureEntry* newBlank() const; + virtual LLTextureEntry* newCopy() const; void init(const LLUUID& tex_id, F32 scale_s, F32 scale_t, F32 offset_s, F32 offset_t, F32 rotation, U8 bump); @@ -99,7 +110,11 @@ public: S32 setColor(const LLColor3 &color); S32 setAlpha(const F32 alpha); S32 setScale(F32 s, F32 t); + S32 setScaleS(F32 s); + S32 setScaleT(F32 t); S32 setOffset(F32 s, F32 t); + S32 setOffsetS(F32 s); + S32 setOffsetT(F32 t); S32 setRotation(F32 theta); S32 setBumpmap(U8 bump); @@ -113,7 +128,7 @@ public: S32 setMediaTexGen(U8 media); S32 setGlow(F32 glow); - const LLUUID &getID() const { return mID; } + virtual const LLUUID &getID() const { return mID; } const LLColor4 &getColor() const { return mColor; } void getScale(F32 *s, F32 *t) const { *s = mScaleS; *t = mScaleT; } void getOffset(F32 *s, F32 *t) const { *s = mOffsetS; *t = mOffsetT; } @@ -130,9 +145,37 @@ public: U8 getTexGen() const { return mMediaFlags & TEM_TEX_GEN_MASK; } U8 getMediaTexGen() const { return mMediaFlags; } F32 getGlow() const { return mGlow; } + + // *NOTE: it is possible for hasMedia() to return true, but getMediaData() to return NULL. + // CONVERSELY, it is also possible for hasMedia() to return false, but getMediaData() + // to NOT return NULL. + bool hasMedia() const { return (bool)(mMediaFlags & MF_HAS_MEDIA); } + LLMediaEntry* getMediaData() const { return mMediaEntry; } + + // Completely change the media data on this texture entry. + void setMediaData(const LLMediaEntry &media_entry); + // Returns true if media data was updated, false if it was cleared + bool updateMediaData(const LLSD& media_data); + // Clears media data, and sets the media flags bit to 0 + void clearMediaData(); + // Merges the given LLSD of media fields with this media entry. + // Only those fields that are set that match the keys in + // LLMediaEntry will be affected. If no fields are set or if + // the LLSD is undefined, this is a no-op. + void mergeIntoMediaData(const LLSD& media_fields); + + // Takes a media version string (an empty string or a previously-returned string) + // and returns a "touched" string, touched by agent_id + static std::string touchMediaVersionString(const std::string &in_version, const LLUUID &agent_id); + // Given a media version string, return the version + static U32 getVersionFromMediaVersionString(const std::string &version_string); + // Given a media version string, return the UUID of the agent + static LLUUID getAgentIDFromMediaVersionString(const std::string &version_string); + // Return whether or not the given string is actually a media version + static bool isMediaVersionString(const std::string &version_string); // Media flags - enum { MF_NONE = 0x0, MF_WEB_PAGE = 0x1 }; + enum { MF_NONE = 0x0, MF_HAS_MEDIA = 0x1 }; public: F32 mScaleS; // S, T offset @@ -142,6 +185,14 @@ public: F32 mRotation; // anti-clockwise rotation in rad about the bottom left corner static const LLTextureEntry null; + + // LLSD key defines + static const char* OBJECT_ID_KEY; + static const char* OBJECT_MEDIA_DATA_KEY; + static const char* MEDIA_VERSION_KEY; + static const char* TEXTURE_INDEX_KEY; + static const char* TEXTURE_MEDIA_DATA_KEY; + protected: LLUUID mID; // Texture GUID LLColor4 mColor; @@ -149,6 +200,9 @@ protected: U8 mMediaFlags; // replace with web page, movie, etc. F32 mGlow; + // Note the media data is not sent via the same message structure as the rest of the TE + LLMediaEntry* mMediaEntry; // The media data for the face + // NOTE: when adding new data to this class, in addition to adding it to the serializers asLLSD/fromLLSD and the // message packers (e.g. LLPrimitive::packTEMessage) you must also implement its copy in LLPrimitive::copyTEs() diff --git a/linden/indra/llprimitive/material_codes.cpp b/linden/indra/llprimitive/material_codes.cpp new file mode 100755 index 0000000..8eb2ae7 --- /dev/null +++ b/linden/indra/llprimitive/material_codes.cpp @@ -0,0 +1,46 @@ +/** + * @file material_codes.cpp + * @brief Material_codes definitions + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "material_codes.h" + +#include "lluuid.h" + +const LLUUID LL_DEFAULT_STONE_UUID("87c5765b-aa26-43eb-b8c6-c09a1ca6208e"); +const LLUUID LL_DEFAULT_METAL_UUID("6f3c53e9-ba60-4010-8f3e-30f51a762476"); +const LLUUID LL_DEFAULT_GLASS_UUID("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); +const LLUUID LL_DEFAULT_WOOD_UUID("89556747-24cb-43ed-920b-47caed15465f"); +const LLUUID LL_DEFAULT_FLESH_UUID("80736669-e4b9-450e-8890-d5169f988a50"); +const LLUUID LL_DEFAULT_PLASTIC_UUID("304fcb4e-7d33-4339-ba80-76d3d22dc11a"); +const LLUUID LL_DEFAULT_RUBBER_UUID("9fae0bc5-666d-477e-9f70-84e8556ec867"); +const LLUUID LL_DEFAULT_LIGHT_UUID("00000000-0000-0000-0000-000000000000"); diff --git a/linden/indra/llprimitive/material_codes.h b/linden/indra/llprimitive/material_codes.h old mode 100644 new mode 100755 index e5a59a2..c63f295 --- a/linden/indra/llprimitive/material_codes.h +++ b/linden/indra/llprimitive/material_codes.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2000&license=viewergpl$ * - * Copyright (c) 2000-2009, Linden Research, Inc. + * Copyright (c) 2000-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -33,7 +33,7 @@ #ifndef LL_MATERIAL_CODES_H #define LL_MATERIAL_CODES_H -#include "lluuid.h" +class LLUUID; // material types const U8 LL_MCODE_STONE = 0; @@ -47,13 +47,14 @@ const U8 LL_MCODE_LIGHT = 7; const U8 LL_MCODE_END = 8; const U8 LL_MCODE_MASK = 0x0F; -const LLUUID LL_DEFAULT_STONE_UUID("87c5765b-aa26-43eb-b8c6-c09a1ca6208e"); -const LLUUID LL_DEFAULT_METAL_UUID("6f3c53e9-ba60-4010-8f3e-30f51a762476"); -const LLUUID LL_DEFAULT_GLASS_UUID("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); -const LLUUID LL_DEFAULT_WOOD_UUID("89556747-24cb-43ed-920b-47caed15465f"); -const LLUUID LL_DEFAULT_FLESH_UUID("80736669-e4b9-450e-8890-d5169f988a50"); -const LLUUID LL_DEFAULT_PLASTIC_UUID("304fcb4e-7d33-4339-ba80-76d3d22dc11a"); -const LLUUID LL_DEFAULT_RUBBER_UUID("9fae0bc5-666d-477e-9f70-84e8556ec867"); -const LLUUID LL_DEFAULT_LIGHT_UUID("00000000-0000-0000-0000-000000000000"); +// *NOTE: Define these in .cpp file to reduce duplicate instances +extern const LLUUID LL_DEFAULT_STONE_UUID; +extern const LLUUID LL_DEFAULT_METAL_UUID; +extern const LLUUID LL_DEFAULT_GLASS_UUID; +extern const LLUUID LL_DEFAULT_WOOD_UUID; +extern const LLUUID LL_DEFAULT_FLESH_UUID; +extern const LLUUID LL_DEFAULT_PLASTIC_UUID; +extern const LLUUID LL_DEFAULT_RUBBER_UUID; +extern const LLUUID LL_DEFAULT_LIGHT_UUID; #endif diff --git a/linden/indra/llprimitive/tests/llmediaentry_test.cpp b/linden/indra/llprimitive/tests/llmediaentry_test.cpp new file mode 100755 index 0000000..89f778d --- /dev/null +++ b/linden/indra/llprimitive/tests/llmediaentry_test.cpp @@ -0,0 +1,508 @@ +/** + * @file llmediaentry_test.cpp + * @brief llmediaentry unit tests + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "lltut.h" +#if LL_WINDOWS +#pragma warning (push) +#pragma warning (disable : 4702) // boost::lexical_cast generates this warning +#endif +#include <boost/lexical_cast.hpp> +#if LL_WINDOWS +#pragma warning (pop) +#endif +#include "llstring.h" +#include "llsdutil.h" +#include "llsdserialize.h" + +#include "../llmediaentry.h" +#include "lllslconstants.h" + +#define DEFAULT_MEDIA_ENTRY "<llsd>\n\ + <map>\n\ + <key>alt_image_enable</key>\n\ + <boolean>0</boolean>\n\ + <key>auto_loop</key>\n\ + <boolean>0</boolean>\n\ + <key>auto_play</key>\n\ + <boolean>0</boolean>\n\ + <key>auto_scale</key>\n\ + <boolean>0</boolean>\n\ + <key>auto_zoom</key>\n\ + <boolean>0</boolean>\n\ + <key>controls</key>\n\ + <integer>0</integer>\n\ + <key>current_url</key>\n\ + <string />\n\ + <key>first_click_interact</key>\n\ + <boolean>0</boolean>\n\ + <key>height_pixels</key>\n\ + <integer>0</integer>\n\ + <key>home_url</key>\n\ + <string />\n\ + <key>perms_control</key>\n\ + <integer>7</integer>\n\ + <key>perms_interact</key>\n\ + <integer>7</integer>\n\ + <key>whitelist_enable</key>\n\ + <boolean>0</boolean>\n\ + <key>width_pixels</key>\n\ + <integer>0</integer>\n\ + </map>\n\ + </llsd>" + +#define EMPTY_MEDIA_ENTRY "<llsd>\n\ + <map>\n\ + <key>alt_image_enable</key>\n\ + <boolean>0</boolean>\n\ + <key>auto_loop</key>\n\ + <boolean>0</boolean>\n\ + <key>auto_play</key>\n\ + <boolean>0</boolean>\n\ + <key>auto_scale</key>\n\ + <boolean>0</boolean>\n\ + <key>auto_zoom</key>\n\ + <boolean>0</boolean>\n\ + <key>controls</key>\n\ + <integer>0</integer>\n\ + <key>current_url</key>\n\ + <string />\n\ + <key>first_click_interact</key>\n\ + <boolean>0</boolean>\n\ + <key>height_pixels</key>\n\ + <integer>0</integer>\n\ + <key>home_url</key>\n\ + <string />\n\ + <key>perms_control</key>\n\ + <integer>0</integer>\n\ + <key>perms_interact</key>\n\ + <integer>0</integer>\n\ + <key>whitelist_enable</key>\n\ + <boolean>0</boolean>\n\ + <key>width_pixels</key>\n\ + <integer>0</integer>\n\ + </map>\n\ + </llsd>" + +#define PARTIAL_MEDIA_ENTRY(CURRENT_URL) "<llsd>\n\ + <map>\n\ + <key>alt_image_enable</key>\n\ + <boolean>0</boolean>\n\ + <key>auto_loop</key>\n\ + <boolean>0</boolean>\n\ + <key>auto_play</key>\n\ + <boolean>0</boolean>\n\ + <key>auto_scale</key>\n\ + <boolean>0</boolean>\n\ + <key>auto_zoom</key>\n\ + <boolean>0</boolean>\n\ + <key>controls</key>\n\ + <integer>0</integer>\n\ + <key>current_url</key>\n\ + <string>" CURRENT_URL "</string>\n\ + <key>first_click_interact</key>\n\ + <boolean>0</boolean>\n\ + <key>height_pixels</key>\n\ + <integer>0</integer>\n\ + <key>home_url</key>\n\ + <string />\n\ + <key>perms_control</key>\n\ + <integer>0</integer>\n\ + <key>perms_interact</key>\n\ + <integer>0</integer>\n\ + <key>whitelist_enable</key>\n\ + <boolean>0</boolean>\n\ + <key>width_pixels</key>\n\ + <integer>0</integer>\n\ + </map>\n\ + </llsd>" + +namespace tut +{ + // this is fixture data that gets created before each test and destroyed + // after each test. this is where we put all of the setup/takedown code + // and data needed for each test. + struct MediaEntry_test + { + MediaEntry_test() { + emptyMediaEntryStr = EMPTY_MEDIA_ENTRY; + std::istringstream e(EMPTY_MEDIA_ENTRY); + LLSDSerialize::fromXML(emptyMediaEntryLLSD, e); + defaultMediaEntryStr = DEFAULT_MEDIA_ENTRY; + std::istringstream d(DEFAULT_MEDIA_ENTRY); + LLSDSerialize::fromXML(defaultMediaEntryLLSD, d); + } + std::string emptyMediaEntryStr; + LLSD emptyMediaEntryLLSD; + std::string defaultMediaEntryStr; + LLSD defaultMediaEntryLLSD; + }; + + typedef test_group<MediaEntry_test, 55> factory; + typedef factory::object object; +} + + +namespace +{ + // this is for naming our tests to make pretty output + tut::factory tf("MediaEntry Test"); +} + +namespace tut +{ + void ensure_llsd_equals(const std::string& msg, const LLSD& expected, const LLSD& actual) + { + if (!llsd_equals(expected, actual)) + { + std::string message = msg; + message += ": actual: "; + message += ll_pretty_print_sd(actual); + message += "\n expected: "; + message += ll_pretty_print_sd(expected); + message += "\n"; + ensure(message, false); + } + } + + void ensure_string_equals(const std::string& msg, const std::string& expected, const std::string& actual) + { + if ( expected != actual ) + { + std::string message = msg; + message += ": actual: "; + message += actual; + message += "\n expected: "; + message += expected; + message += "\n"; + ensure(message, false); + } + } + + void set_whitelist(LLMediaEntry &entry, const char *str) + { + std::vector<std::string> tokens; + LLStringUtil::getTokens(std::string(str), tokens, ","); + entry.setWhiteList(tokens); + } + + void whitelist_test(int num, bool enable, const char *whitelist, const char *candidate_url, bool expected_pass) + { + std::string message = "Whitelist test " + boost::lexical_cast<std::string>(num); + LLMediaEntry entry; + entry.setWhiteListEnable(enable); + set_whitelist(entry, whitelist); + bool passed_whitelist = entry.checkCandidateUrl(candidate_url); + if (passed_whitelist != expected_pass) + { + message += " failed: expected "; + message += (expected_pass) ? "" : "NOT "; + message += "to match\nwhitelist = "; + message += whitelist; + message += "\ncandidate_url = "; + message += candidate_url; + } + ensure(message, expected_pass == passed_whitelist); + } + + void whitelist_test(int num, const char *whitelist, const char *candidate_url, bool expected_pass) + { + whitelist_test(num, true, whitelist, candidate_url, expected_pass); + } + void whitelist_test(int num, const char *whitelist, const char *candidate_url) + { + whitelist_test(num, true, whitelist, candidate_url, true); + } + + template<> template<> + void object::test<1>() + { + set_test_name("Test LLMediaEntry Instantiation"); + LLMediaEntry entry; + ensure_llsd_equals(get_test_name() + " failed", defaultMediaEntryLLSD, entry.asLLSD()); + } + + template<> template<> + void object::test<2>() + { + set_test_name("Test LLMediaEntry Instantiation from LLSD"); + LLMediaEntry entry; + LLSD sd; + entry.fromLLSD(sd); + ensure_llsd_equals(get_test_name() + " failed", emptyMediaEntryLLSD, entry.asLLSD()); + } + + template<> template<> + void object::test<3>() + { + set_test_name("Test LLMediaEntry Partial Instantiation from LLSD"); + LLMediaEntry entry; + LLSD sd; + sd[LLMediaEntry::CURRENT_URL_KEY] = "http://www.example.com"; + entry.fromLLSD(sd); + LLSD golden; + std::istringstream p(PARTIAL_MEDIA_ENTRY("http://www.example.com")); + LLSDSerialize::fromXML(golden,p); + ensure_llsd_equals(get_test_name() + " failed", golden, entry.asLLSD()); + } + + template<> template<> + void object::test<4>() + { + set_test_name("Test LLMediaEntry::asLLSD()"); + LLMediaEntry entry; + LLSD sd; + // Put some cruft in the LLSD + sd[LLMediaEntry::CURRENT_URL_KEY] = "http://www.example.com"; + LLSD whitelist; + whitelist.append("*.example.com"); + sd[LLMediaEntry::WHITELIST_KEY] = whitelist; + entry.asLLSD(sd); + ensure_llsd_equals(get_test_name() + " failed", defaultMediaEntryLLSD, sd); + } + + + template<> template<> + void object::test<5>() + { + set_test_name("Test LLMediaEntry::asLLSD() -> LLMediaEntry::fromLLSD()"); + LLMediaEntry entry1, entry2; + // Add a whitelist to entry2 + std::vector<std::string> whitelist; + whitelist.push_back("*.example.com"); + entry2.setWhiteList(whitelist); + // Render entry1 (which has no whitelist) as an LLSD + LLSD sd; + entry1.asLLSD(sd); + // "read" that LLSD into entry 2 + entry2.fromLLSD(sd); + ensure_llsd_equals(get_test_name() + " failed", defaultMediaEntryLLSD, entry2.asLLSD()); + } + + // limit tests + const char *URL_OK = "http://www.example.com"; + const char *URL_TOO_BIG = "http://www.example.com.qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"; + + template<> template<> + void object::test<6>() + { + set_test_name("Test Limits on setting current URL"); + LLMediaEntry entry; + U32 status = entry.setCurrentURL(URL_OK); + ensure(get_test_name() + " ok failed", status == LSL_STATUS_OK); + status = entry.setCurrentURL(URL_TOO_BIG); + ensure(get_test_name() + " ok failed", status == LSL_STATUS_BOUNDS_ERROR); + } + + template<> template<> + void object::test<7>() + { + set_test_name("Test Limits on setting home URL"); + LLMediaEntry entry; + U32 status = entry.setHomeURL(URL_OK); + ensure(get_test_name() + " ok failed", status == LSL_STATUS_OK); + status = entry.setHomeURL(URL_TOO_BIG); + ensure(get_test_name() + " ok failed", status == LSL_STATUS_BOUNDS_ERROR); + } + + template<> template<> + void object::test<8>() + { + set_test_name("Test Limits on setting whitelist"); + + // Test a valid list + LLMediaEntry entry; + std::vector<std::string> whitelist; + whitelist.push_back(std::string(URL_OK)); + S32 status = entry.setWhiteList(whitelist); + ensure(get_test_name() + " invalid result", status == LSL_STATUS_OK); + ensure(get_test_name() + " failed", whitelist == entry.getWhiteList()); + } + + template<> template<> + void object::test<9>() + { + set_test_name("Test Limits on setting whitelist too big"); + + // Test an invalid list + LLMediaEntry entry; + std::vector<std::string> whitelist, empty; + whitelist.push_back(std::string(URL_OK)); + whitelist.push_back(std::string(URL_TOO_BIG)); + S32 status = entry.setWhiteList(whitelist); + ensure(get_test_name() + " invalid result", status == LSL_STATUS_BOUNDS_ERROR); + ensure(get_test_name() + " failed", empty == entry.getWhiteList()); + } + + template<> template<> + void object::test<10>() + { + set_test_name("Test Limits on setting whitelist too many"); + + // Test an invalid list + LLMediaEntry entry; + std::vector<std::string> whitelist, empty; + for (int i=0; i < LLMediaEntry::MAX_WHITELIST_SIZE+1; i++) { + whitelist.push_back("Q"); + } + S32 status = entry.setWhiteList(whitelist); + ensure(get_test_name() + " invalid result", status == LSL_STATUS_BOUNDS_ERROR); + ensure(get_test_name() + " failed", empty == entry.getWhiteList()); + } + + template<> template<> + void object::test<11>() + { + set_test_name("Test to make sure both setWhiteList() functions behave the same"); + + // Test a valid list + std::vector<std::string> whitelist, empty; + LLSD whitelist_llsd; + whitelist.push_back(std::string(URL_OK)); + whitelist_llsd.append(std::string(URL_OK)); + LLMediaEntry entry1, entry2; + ensure(get_test_name() + " setWhiteList(s) don't match", + entry1.setWhiteList(whitelist) == LSL_STATUS_OK && + entry2.setWhiteList(whitelist_llsd)== LSL_STATUS_OK ); + ensure(get_test_name() + " failed", + entry1.getWhiteList() == entry2.getWhiteList()); + } + + template<> template<> + void object::test<12>() + { + set_test_name("Test to make sure both setWhiteList() functions behave the same"); + + // Test an invalid list + std::vector<std::string> whitelist, empty; + LLSD whitelist_llsd; + whitelist.push_back(std::string(URL_OK)); + whitelist.push_back(std::string(URL_TOO_BIG)); + whitelist_llsd.append(std::string(URL_OK)); + whitelist_llsd.append(std::string(URL_TOO_BIG)); + LLMediaEntry entry1, entry2; + ensure(get_test_name() + " setWhiteList(s) don't match", + entry1.setWhiteList(whitelist) == LSL_STATUS_BOUNDS_ERROR && + entry2.setWhiteList(whitelist_llsd) == LSL_STATUS_BOUNDS_ERROR); + ensure(get_test_name() + " failed", + empty == entry1.getWhiteList() && + empty == entry2.getWhiteList()); + } + + template<> template<> + void object::test<13>() + { + set_test_name("Test to make sure both setWhiteList() functions behave the same"); + + // Test an invalid list, too many + std::vector<std::string> whitelist, empty; + LLSD whitelist_llsd; + for (int i=0; i < LLMediaEntry::MAX_WHITELIST_SIZE+1; i++) { + whitelist.push_back("Q"); + whitelist_llsd.append("Q"); + } + LLMediaEntry entry1, entry2; + ensure(get_test_name() + " invalid result", + entry1.setWhiteList(whitelist) == LSL_STATUS_BOUNDS_ERROR && + entry2.setWhiteList(whitelist_llsd) == LSL_STATUS_BOUNDS_ERROR); + ensure(get_test_name() + " failed", + empty == entry1.getWhiteList() && + empty == entry2.getWhiteList()); + } + + template<> template<> + void object::test<14>() + { + // Whitelist check tests + int n=0; + + // Check the "empty whitelist" case + whitelist_test(++n, "", "http://www.example.com", true); + + // Check the "missing scheme" case + whitelist_test(++n, "www.example.com", "http://www.example.com", true); + + // Check the "exactly the same" case + whitelist_test(++n, "http://example.com", "http://example.com", true); + + // Check the enable flag + whitelist_test(++n, false, "www.example.com", "http://www.secondlife.com", true); + whitelist_test(++n, true, "www.example.com", "http://www.secondlife.com", false); + + // Check permutations of trailing slash: + whitelist_test(++n, "http://www.example.com", "http://www.example.com/", true); + whitelist_test(++n, "http://www.example.com/", "http://www.example.com/", true); + whitelist_test(++n, "http://www.example.com/", "http://www.example.com", false); + whitelist_test(++n, "http://www.example.com", "http://www.example.com/foobar", true); + whitelist_test(++n, "http://www.example.com/", "http://www.example.com/foobar", false); + + + // More cases... + whitelist_test(++n, "http://example.com", "http://example.com/wiki", true); + whitelist_test(++n, "www.example.com", "http://www.example.com/help", true); + whitelist_test(++n, "http://www.example.com", "http://wwwexample.com", false); + whitelist_test(++n, "http://www.example.com", "http://www.example.com/wiki", true); + whitelist_test(++n, "example.com", "http://wwwexample.com", false); + whitelist_test(++n, "http://www.example.com/", "http://www.amazon.com/wiki", false); + whitelist_test(++n, "www.example.com", "http://www.amazon.com", false); + + // regexp cases + whitelist_test(++n, "*.example.com", "http://www.example.com", true); + whitelist_test(++n, "*.example.com", "http://www.amazon.com", false); + whitelist_test(++n, "*.example.com", "http://www.example.com/foo/bar", true); + whitelist_test(++n, "*.example.com", "http:/example.com/foo/bar", false); + whitelist_test(++n, "*example.com", "http://example.com/foo/bar", true); + whitelist_test(++n, "*example.com", "http://my.virus.com/foo/bar?example.com", false); + whitelist_test(++n, "example.com", "http://my.virus.com/foo/bar?example.com", false); + whitelist_test(++n, "*example.com", "http://my.virus.com/foo/bar?*example.com", false); + whitelist_test(++n, "http://*example.com", "http://www.example.com", true); + whitelist_test(++n, "http://*.example.com", "http://www.example.com", true); + whitelist_test(++n, "http://*.e$?^.com", "http://www.e$?^.com", true); + whitelist_test(++n, "*.example.com/foo/bar", "http://www.example.com/", false); + whitelist_test(++n, "*.example.com/foo/bar", "http://example.com/foo/bar", false); + whitelist_test(++n, "http://*.example.com/foo/bar", "http://www.example.com", false); + whitelist_test(++n, "http://*.example.com", "https://www.example.com", false); + whitelist_test(++n, "http*://*.example.com", "rtsp://www.example.com", false); + whitelist_test(++n, "http*://*.example.com", "https://www.example.com", true); + whitelist_test(++n, "example.com", "http://www.example.com", false); + whitelist_test(++n, "www.example.com", "http://www.example.com:80", false); + whitelist_test(++n, "www.example.com", "http://www.example.com", true); + whitelist_test(++n, "www.example.com/", "http://www.example.com", false); + whitelist_test(++n, "www.example.com/foo/bar/*", "http://www.example.com/foo/bar/baz", true); + + // Path only + whitelist_test(++n, "/foo/*/baz", "http://www.example.com/foo/bar/baz", true); + whitelist_test(++n, "/foo/*/baz", "http://www.example.com/foo/bar/", false); + } + +} + diff --git a/linden/indra/llprimitive/tests/llmessagesystem_stub.cpp b/linden/indra/llprimitive/tests/llmessagesystem_stub.cpp new file mode 100755 index 0000000..37a61de --- /dev/null +++ b/linden/indra/llprimitive/tests/llmessagesystem_stub.cpp @@ -0,0 +1,53 @@ +/** + * @file llmessagesystem_stub.cpp + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +char * _PREHASH_TextureEntry; + +S32 LLMessageSystem::getSizeFast(char const*, char const*) const +{ + return 0; +} + +S32 LLMessageSystem::getSizeFast(char const*, int, char const*) const +{ + return 0; +} + +void LLMessageSystem::getBinaryDataFast(char const*, char const*, void*, int, int, int) +{ +} + +void LLMessageSystem::addBinaryDataFast(char const*, void const*, int) +{ +} + diff --git a/linden/indra/llprimitive/tests/llprimitive_test.cpp b/linden/indra/llprimitive/tests/llprimitive_test.cpp new file mode 100755 index 0000000..c923442 --- /dev/null +++ b/linden/indra/llprimitive/tests/llprimitive_test.cpp @@ -0,0 +1,237 @@ +/** + * @file llprimitive_test.cpp + * @brief llprimitive tests + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "../test/lltut.h" + +#include "../llprimitive.h" + +#include "../../llmath/llvolumemgr.h" + +class DummyVolumeMgr : public LLVolumeMgr +{ +public: + DummyVolumeMgr() : LLVolumeMgr(), mVolumeTest(NULL), mCurrDetailTest(0) {} + ~DummyVolumeMgr() + { + } + + + virtual LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail) + { + if (mVolumeTest.isNull() || volume_params != mCurrParamsTest || detail != mCurrDetailTest) + { + F32 volume_detail = LLVolumeLODGroup::getVolumeScaleFromDetail(detail); + mVolumeTest = new LLVolume(volume_params, volume_detail, FALSE, FALSE); + mCurrParamsTest = volume_params; + mCurrDetailTest = detail; + return mVolumeTest; + } + else + { + return mVolumeTest; + } + } + + virtual void unrefVolume(LLVolume *volumep) + { + if (mVolumeTest == volumep) + { + mVolumeTest = NULL; + } + } + +private: + LLPointer<LLVolume> mVolumeTest; + LLVolumeParams mCurrParamsTest; + S32 mCurrDetailTest; +}; + +class PRIMITIVE_TEST_SETUP +{ +public: + PRIMITIVE_TEST_SETUP() + { + volume_manager_test = new DummyVolumeMgr(); + LLPrimitive::setVolumeManager(volume_manager_test); + } + + ~PRIMITIVE_TEST_SETUP() + { + LLPrimitive::cleanupVolumeManager(); + } + DummyVolumeMgr * volume_manager_test; +}; + +namespace tut +{ + struct llprimitive + { + PRIMITIVE_TEST_SETUP setup_class; + }; + + typedef test_group<llprimitive> llprimitive_t; + typedef llprimitive_t::object llprimitive_object_t; + tut::llprimitive_t tut_llprimitive("llprimitive"); + + template<> template<> + void llprimitive_object_t::test<1>() + { + set_test_name("Test LLPrimitive Instantiation"); + LLPrimitive test; + } + + template<> template<> + void llprimitive_object_t::test<2>() + { + set_test_name("Test LLPrimitive PCode setter and getter."); + LLPrimitive test; + ensure_equals(test.getPCode(), 0); + LLPCode code = 1; + test.setPCode(code); + ensure_equals(test.getPCode(), code); + } + + template<> template<> + void llprimitive_object_t::test<3>() + { + set_test_name("Test llprimitive constructor and initer."); + LLPCode code = 1; + LLPrimitive primitive; + primitive.init_primitive(code); + ensure_equals(primitive.getPCode(), code); + } + + template<> template<> + void llprimitive_object_t::test<4>() + { + set_test_name("Test Static llprimitive constructor and initer."); + LLPCode code = 1; + LLPrimitive * primitive = LLPrimitive::createPrimitive(code); + ensure(primitive != NULL); + ensure_equals(primitive->getPCode(), code); + } + + template<> template<> + void llprimitive_object_t::test<5>() + { + set_test_name("Test setVolume creation of new unique volume."); + LLPrimitive primitive; + LLVolumeParams params; + + // Make sure volume starts off null + ensure(primitive.getVolume() == NULL); + + // Make sure we have no texture entries before setting the volume + ensure_equals(primitive.getNumTEs(), 0); + + // Test that GEOMETRY has not been flagged as changed. + ensure(!primitive.isChanged(LLXform::GEOMETRY)); + + // Make sure setVolume returns true + ensure(primitive.setVolume(params, 0, true) == TRUE); + LLVolume* new_volume = primitive.getVolume(); + + // make sure new volume was actually created + ensure(new_volume != NULL); + + // Make sure that now that we've set the volume we have texture entries + ensure_not_equals(primitive.getNumTEs(), 0); + + // Make sure that the number of texture entries equals the number of faces in the volume (should be 6) + ensure_equals(new_volume->getNumFaces(), 6); + ensure_equals(primitive.getNumTEs(), new_volume->getNumFaces()); + + // Test that GEOMETRY has been flagged as changed. + ensure(primitive.isChanged(LLXform::GEOMETRY)); + + // Run it twice to make sure it doesn't create a different one if params are the same + ensure(primitive.setVolume(params, 0, true) == FALSE); + ensure(new_volume == primitive.getVolume()); + + // Change the param definition and try setting it again. + params.setRevolutions(4); + ensure(primitive.setVolume(params, 0, true) == TRUE); + + // Ensure that we now have a different volume + ensure(new_volume != primitive.getVolume()); + } + + template<> template<> + void llprimitive_object_t::test<6>() + { + set_test_name("Test setVolume creation of new NOT-unique volume."); + LLPrimitive primitive; + LLVolumeParams params; + + // Make sure volume starts off null + ensure(primitive.getVolume() == NULL); + + // Make sure we have no texture entries before setting the volume + ensure_equals(primitive.getNumTEs(), 0); + + // Test that GEOMETRY has not been flagged as changed. + ensure(!primitive.isChanged(LLXform::GEOMETRY)); + + // Make sure setVolume returns true + ensure(primitive.setVolume(params, 0, false) == TRUE); + + LLVolume* new_volume = primitive.getVolume(); + + // make sure new volume was actually created + ensure(new_volume != NULL); + + // Make sure that now that we've set the volume we have texture entries + ensure_not_equals(primitive.getNumTEs(), 0); + + // Make sure that the number of texture entries equals the number of faces in the volume (should be 6) + ensure_equals(new_volume->getNumFaces(), 6); + ensure_equals(primitive.getNumTEs(), new_volume->getNumFaces()); + + // Test that GEOMETRY has been flagged as changed. + ensure(primitive.isChanged(LLXform::GEOMETRY)); + + // Run it twice to make sure it doesn't create a different one if params are the same + ensure(primitive.setVolume(params, 0, false) == FALSE); + ensure(new_volume == primitive.getVolume()); + + // Change the param definition and try setting it again. + params.setRevolutions(4); + ensure(primitive.setVolume(params, 0, false) == TRUE); + + // Ensure that we now have a different volume + ensure(new_volume != primitive.getVolume()); + } +} + +#include "llmessagesystem_stub.cpp" diff --git a/linden/indra/newview/llselectmgr.cpp b/linden/indra/newview/llselectmgr.cpp index 558d278..b2904b9 100644 --- a/linden/indra/newview/llselectmgr.cpp +++ b/linden/indra/newview/llselectmgr.cpp @@ -1715,7 +1715,7 @@ void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& U8 media_flags = LLTextureEntry::MF_NONE; if (media_type == LLViewerObject::MEDIA_TYPE_WEB_PAGE) { - media_flags = LLTextureEntry::MF_WEB_PAGE; + media_flags = LLTextureEntry::MF_HAS_MEDIA; } struct f : public LLSelectedTEFunctor -- cgit v1.1 From c791570b8f7704dd3af382ab1d6ad446af1fa671 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Mon, 14 Jun 2010 14:29:10 +0200 Subject: make it compile and run. TODO: llpanellandmedia.cpp and llviewermedia.cpp need a proper fix --- linden/indra/llprimitive/llprimitive.cpp | 96 +------------------------------ linden/indra/newview/CMakeLists.txt | 1 - linden/indra/newview/llpanellandmedia.cpp | 51 ---------------- 3 files changed, 1 insertion(+), 147 deletions(-) (limited to 'linden') diff --git a/linden/indra/llprimitive/llprimitive.cpp b/linden/indra/llprimitive/llprimitive.cpp index 7546764..0ad9f79 100755 --- a/linden/indra/llprimitive/llprimitive.cpp +++ b/linden/indra/llprimitive/llprimitive.cpp @@ -247,50 +247,22 @@ void LLPrimitive::setTE(const U8 index, const LLTextureEntry& te) S32 LLPrimitive::setTETexture(const U8 index, const LLUUID &id) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "setting non-existent te " << te << llendl; - return 0; - } - return mTextureList.setID(index, id); } S32 LLPrimitive::setTEColor(const U8 index, const LLColor4 &color) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "setting non-existent te " << te << llendl; - return 0; - } - return mTextureList.setColor(index, color); } S32 LLPrimitive::setTEColor(const U8 index, const LLColor3 &color) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "setting non-existent te " << te << llendl; - return 0; - } - return mTextureList.setColor(index, color); } S32 LLPrimitive::setTEAlpha(const U8 index, const F32 alpha) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "setting non-existent te " << te << llendl; - return 0; - } - return mTextureList.setAlpha(index, alpha); } @@ -350,111 +322,46 @@ S32 LLPrimitive::setTERotation(const U8 index, const F32 r) //=============================================================== S32 LLPrimitive::setTEBumpShinyFullbright(const U8 index, const U8 bump) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "setting non-existent te " << te << llendl; - return 0; - } - - return mTextureList.setBumpShinyFullbright(index, bump); + return mTextureList.setBumpShinyFullbright(index, bump); } S32 LLPrimitive::setTEMediaTexGen(const U8 index, const U8 media) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "setting non-existent te " << te << llendl; - return 0; - } - return mTextureList.setMediaTexGen(index, media); } S32 LLPrimitive::setTEBumpmap(const U8 index, const U8 bump) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "setting non-existent te " << te << llendl; - return 0; - } - return mTextureList.setBumpMap(index, bump); } S32 LLPrimitive::setTEBumpShiny(const U8 index, const U8 bump_shiny) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "setting non-existent te " << te << llendl; - return 0; - } - return mTextureList.setBumpShiny(index, bump_shiny); } S32 LLPrimitive::setTETexGen(const U8 index, const U8 texgen) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "setting non-existent te " << te << llendl; - return 0; - } - return mTextureList.setTexGen(index, texgen); } S32 LLPrimitive::setTEShiny(const U8 index, const U8 shiny) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "setting non-existent te " << te << llendl; - return 0; - } - - return mTextureList.setShiny(index, shiny); } S32 LLPrimitive::setTEFullbright(const U8 index, const U8 fullbright) { - - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "setting non-existent te " << te << llendl; - return 0; - } - return mTextureList.setFullbright(index, fullbright); } S32 LLPrimitive::setTEMediaFlags(const U8 index, const U8 media_flags) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "setting non-existent te " << te << llendl; - return 0; - } - return mTextureList.setMediaFlags(index, media_flags); } S32 LLPrimitive::setTEGlow(const U8 index, const F32 glow) { - // if we're asking for a non-existent face, return null - if (te >= mNumTEs) - { - llwarns << "setting non-existent te " << te << llendl; - return 0; - } - return mTextureList.setGlow(index, glow); } @@ -1029,7 +936,6 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit]))); } } ->>>>>>> 5faaca1... port llprimitive from SG2.0 return TRUE; } diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index b576ccd..75ba977 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt @@ -1174,7 +1174,6 @@ set(viewer_APPSETTINGS_FILES ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg ) - source_group("App Settings" FILES ${viewer_APPSETTINGS_FILES}) set_source_files_properties(${viewer_APPSETTINGS_FILES} diff --git a/linden/indra/newview/llpanellandmedia.cpp b/linden/indra/newview/llpanellandmedia.cpp index fc84bb5..db68c42 100644 --- a/linden/indra/newview/llpanellandmedia.cpp +++ b/linden/indra/newview/llpanellandmedia.cpp @@ -172,57 +172,6 @@ void LLPanelLandMedia::refresh() BOOL can_change_media = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_CHANGE_MEDIA); mCheckSoundLocal->set( parcel->getSoundLocal() ); - mCheckSoundLocal->setEnabled( can_change_media ); - - LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); - if (!region) - { - // never seen this happen, but log it - llwarns << "Couldn't get selected region." << llendl; - } - - // We need to do this differently for OpenSim because it doesn't include - // REGION_FLAGS_ALLOW_VOICE in the "RegionInfo" message as of 0.6.9 PF -- MC - bool allow_voice = parcel->getParcelFlagAllowVoice(); - if (gHippoGridManager->getConnectedGrid()->isSecondLife()) - { - if (region && region->isVoiceEnabled()) // estate-wide voice-disable overrides all - { - mCheckEnableVoiceChatIsEstateDisabled->setVisible(false); - - mCheckEnableVoiceChat->setVisible(true); - mCheckEnableVoiceChat->setEnabled( can_change_media ); - mCheckEnableVoiceChat->set(allow_voice); - - mCheckEnableVoiceChatParcel->setEnabled( can_change_media && allow_voice ); - } - else // disabled at region level - { - mCheckEnableVoiceChatIsEstateDisabled->setVisible(true); // always disabled - mCheckEnableVoiceChat->setVisible(false); - mCheckEnableVoiceChat->setEnabled(false); - mCheckEnableVoiceChat->set(false); - - mCheckEnableVoiceChatParcel->setEnabled(false); - } - } - else - { - mCheckEnableVoiceChatIsEstateDisabled->setVisible(true); - - mCheckEnableVoiceChat->setVisible(true); - mCheckEnableVoiceChat->setEnabled( can_change_media ); - mCheckEnableVoiceChat->set(allow_voice); - - mCheckEnableVoiceChatParcel->setEnabled( can_change_media && allow_voice ); - } - - mCheckEnableVoiceChatParcel->set(!parcel->getParcelFlagUseEstateVoiceChannel()); - - mMusicURLEdit->setText(parcel->getMusicURL()); - mMusicURLEdit->setEnabled( can_change_media ); - - childSetText("current_url", parcel->getMediaCurrentURL()); -- cgit v1.1 From 3069d8886241b2d9deaadfbf8823d463b469ec6b Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Mon, 14 Jun 2010 16:27:25 +0200 Subject: update to latest SG2 media_plugins --- linden/indra/media_plugins/base/CMakeLists.txt | 4 +- .../indra/media_plugins/base/media_plugin_base.cpp | 5 +- .../indra/media_plugins/base/media_plugin_base.h | 5 +- linden/indra/media_plugins/example/CMakeLists.txt | 6 +- .../media_plugins/example/media_plugin_example.cpp | 31 +- .../media_plugins/gstreamer010/CMakeLists.txt | 15 +- .../gstreamer010/llmediaimplgstreamer.h | 5 +- .../gstreamer010/llmediaimplgstreamer_syms.cpp | 5 +- .../gstreamer010/llmediaimplgstreamer_syms.h | 5 +- .../llmediaimplgstreamertriviallogging.h | 5 +- .../gstreamer010/llmediaimplgstreamervidplug.cpp | 25 +- .../gstreamer010/llmediaimplgstreamervidplug.h | 5 +- .../gstreamer010/media_plugin_gstreamer010.cpp | 63 +-- .../quicktime/media_plugin_quicktime.cpp | 71 +-- linden/indra/media_plugins/webkit/CMakeLists.txt | 10 +- .../media_plugins/webkit/linux_volume_catcher.cpp | 490 +++++++++++++++++++++ .../media_plugins/webkit/linux_volume_catcher.h | 56 +++ .../webkit/linux_volume_catcher_pa_syms.inc | 21 + .../webkit/linux_volume_catcher_paglib_syms.inc | 6 + .../media_plugins/webkit/media_plugin_webkit.cpp | 352 ++++++++++----- 20 files changed, 956 insertions(+), 229 deletions(-) create mode 100755 linden/indra/media_plugins/webkit/linux_volume_catcher.cpp create mode 100755 linden/indra/media_plugins/webkit/linux_volume_catcher.h create mode 100755 linden/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc create mode 100755 linden/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc (limited to 'linden') diff --git a/linden/indra/media_plugins/base/CMakeLists.txt b/linden/indra/media_plugins/base/CMakeLists.txt index a3ee02e..8d62043 100755 --- a/linden/indra/media_plugins/base/CMakeLists.txt +++ b/linden/indra/media_plugins/base/CMakeLists.txt @@ -25,13 +25,13 @@ include_directories( ### media_plugin_base -if(WORD_SIZE EQUAL 64) +if(NOT CMAKE_SIZEOF_VOID_P MATCHES 4) if(WINDOWS) add_definitions(/FIXED:NO) else(WINDOWS) # not windows therefore gcc LINUX and DARWIN add_definitions(-fPIC) endif(WINDOWS) -endif (WORD_SIZE EQUAL 64) +endif (NOT CMAKE_SIZEOF_VOID_P MATCHES 4) set(media_plugin_base_SOURCE_FILES media_plugin_base.cpp diff --git a/linden/indra/media_plugins/base/media_plugin_base.cpp b/linden/indra/media_plugins/base/media_plugin_base.cpp index baae68c..47acdfd 100755 --- a/linden/indra/media_plugins/base/media_plugin_base.cpp +++ b/linden/indra/media_plugins/base/media_plugin_base.cpp @@ -15,13 +15,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -31,6 +31,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/media_plugins/base/media_plugin_base.h b/linden/indra/media_plugins/base/media_plugin_base.h index 8311e66..efb0629 100755 --- a/linden/indra/media_plugins/base/media_plugin_base.h +++ b/linden/indra/media_plugins/base/media_plugin_base.h @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/media_plugins/example/CMakeLists.txt b/linden/indra/media_plugins/example/CMakeLists.txt index 6d14c1b..7822300 100755 --- a/linden/indra/media_plugins/example/CMakeLists.txt +++ b/linden/indra/media_plugins/example/CMakeLists.txt @@ -14,7 +14,7 @@ include(PluginAPI) include(MediaPluginBase) include(FindOpenGL) -#awfixme include(ExamplePlugin) +#include(ExamplePlugin) include_directories( ${LLPLUGIN_INCLUDE_DIRS} @@ -29,13 +29,13 @@ include_directories( ### media_plugin_example -if(WORD_SIZE EQUAL 64) +if(NOT CMAKE_SIZEOF_VOID_P MATCHES 4) if(WINDOWS) add_definitions(/FIXED:NO) else(WINDOWS) # not windows therefore gcc LINUX and DARWIN add_definitions(-fPIC) endif(WINDOWS) -endif (WORD_SIZE EQUAL 64) +endif (NOT CMAKE_SIZEOF_VOID_P MATCHES 4) set(media_plugin_example_SOURCE_FILES media_plugin_example.cpp diff --git a/linden/indra/media_plugins/example/media_plugin_example.cpp b/linden/indra/media_plugins/example/media_plugin_example.cpp index 83abae0..1eabe6c 100755 --- a/linden/indra/media_plugins/example/media_plugin_example.cpp +++ b/linden/indra/media_plugins/example/media_plugin_example.cpp @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ @@ -120,17 +121,6 @@ void MediaPluginExample::receiveMessage( const char* message_string ) std::string plugin_version = "Example media plugin, Example Version 1.0.0.0"; message.setValue( "plugin_version", plugin_version ); sendMessage( message ); - - // Plugin gets to decide the texture parameters to use. - message.setMessage( LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params" ); - message.setValueS32( "default_width", mWidth ); - message.setValueS32( "default_height", mHeight ); - message.setValueS32( "depth", mDepth ); - message.setValueU32( "internalformat", GL_RGBA ); - message.setValueU32( "format", GL_RGBA ); - message.setValueU32( "type", GL_UNSIGNED_BYTE ); - message.setValueBoolean( "coords_opengl", false ); - sendMessage( message ); } else if ( message_name == "idle" ) @@ -192,7 +182,20 @@ void MediaPluginExample::receiveMessage( const char* message_string ) else if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA ) { - if ( message_name == "size_change" ) + if ( message_name == "init" ) + { + // Plugin gets to decide the texture parameters to use. + LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params" ); + message.setValueS32( "default_width", mWidth ); + message.setValueS32( "default_height", mHeight ); + message.setValueS32( "depth", mDepth ); + message.setValueU32( "internalformat", GL_RGBA ); + message.setValueU32( "format", GL_RGBA ); + message.setValueU32( "type", GL_UNSIGNED_BYTE ); + message.setValueBoolean( "coords_opengl", false ); + sendMessage( message ); + } + else if ( message_name == "size_change" ) { std::string name = message_in.getValue( "name" ); S32 width = message_in.getValueS32( "width" ); diff --git a/linden/indra/media_plugins/gstreamer010/CMakeLists.txt b/linden/indra/media_plugins/gstreamer010/CMakeLists.txt index 3b73e04..ee16849 100755 --- a/linden/indra/media_plugins/gstreamer010/CMakeLists.txt +++ b/linden/indra/media_plugins/gstreamer010/CMakeLists.txt @@ -30,6 +30,14 @@ include_directories( ### media_plugin_gstreamer010 +if(NOT CMAKE_SIZEOF_VOID_P MATCHES 4) + if(WINDOWS) + add_definitions(/FIXED:NO) + else(WINDOWS) # not windows therefore gcc LINUX and DARWIN + add_definitions(-fPIC) + endif(WINDOWS) +endif (NOT CMAKE_SIZEOF_VOID_P MATCHES 4) + set(media_plugin_gstreamer010_SOURCE_FILES media_plugin_gstreamer010.cpp llmediaimplgstreamer_syms.cpp @@ -42,13 +50,6 @@ set(media_plugin_gstreamer010_HEADER_FILES llmediaimplgstreamertriviallogging.h ) -if (${CXX_VERSION_NUMBER} MATCHES "4[23].") - # Work around a bad interaction between broken gstreamer headers and - # g++ 4.3's increased strictness. - set_source_files_properties(llmediaimplgstreamervidplug.cpp PROPERTIES - COMPILE_FLAGS -Wno-write-strings) -endif (${CXX_VERSION_NUMBER} MATCHES "4[23].") - add_library(media_plugin_gstreamer010 SHARED ${media_plugin_gstreamer010_SOURCE_FILES} diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h index 6920c3b..bfc443b 100755 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h @@ -14,13 +14,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -30,6 +30,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp index 28960ac..82978ad 100755 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h index 7955898..c309043 100755 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h index 27f0eed..f5da637 100755 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp index 2b10a2a..9242830 100755 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ @@ -54,7 +55,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug); #define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ( - "sink", + (gchar*)"sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS (SLV_ALLCAPS) @@ -514,18 +515,18 @@ plugin_init (GstPlugin * plugin) some g++ versions buggily avoid __attribute__((constructor)) functions - so we provide an explicit plugin init function. */ -void gst_slvideo_init_class (void) -{ -#define PACKAGE "packagehack" +#define PACKAGE (gchar*)"packagehack" // this macro quietly refers to PACKAGE internally - static GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, - "private-slvideoplugin", - "SL Video sink plugin", - plugin_init, "0.1", GST_LICENSE_UNKNOWN, - "Second Life", - "http://www.secondlife.com/"); + (gchar*)"private-slvideoplugin", + (gchar*)"SL Video sink plugin", + plugin_init, (gchar*)"0.1", (gchar*)GST_LICENSE_UNKNOWN, + (gchar*)"Second Life", + (gchar*)"http://www.secondlife.com/"); #undef PACKAGE +void gst_slvideo_init_class (void) +{ ll_gst_plugin_register_static (&gst_plugin_desc); DEBUGMSG("CLASS INIT"); } diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h index fad80cb..56f6db9 100755 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp index 82e6fdc..7d34a1e 100755 --- a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp +++ b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ @@ -947,33 +948,6 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string) message.setValue("plugin_version", getVersion()); sendMessage(message); - - // Plugin gets to decide the texture parameters to use. - message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - // lame to have to decide this now, it depends on the movie. Oh well. - mDepth = 4; - - mCurrentWidth = 1; - mCurrentHeight = 1; - mPreviousWidth = 1; - mPreviousHeight = 1; - mNaturalWidth = 1; - mNaturalHeight = 1; - mWidth = 1; - mHeight = 1; - mTextureWidth = 1; - mTextureHeight = 1; - - message.setValueU32("format", GL_RGBA); - message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV); - - message.setValueS32("depth", mDepth); - message.setValueS32("default_width", mWidth); - message.setValueS32("default_height", mHeight); - message.setValueU32("internalformat", GL_RGBA8); - message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. - message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale - sendMessage(message); } else if(message_name == "idle") { @@ -1038,7 +1012,36 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string) } else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) { - if(message_name == "size_change") + if(message_name == "init") + { + // Plugin gets to decide the texture parameters to use. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + // lame to have to decide this now, it depends on the movie. Oh well. + mDepth = 4; + + mCurrentWidth = 1; + mCurrentHeight = 1; + mPreviousWidth = 1; + mPreviousHeight = 1; + mNaturalWidth = 1; + mNaturalHeight = 1; + mWidth = 1; + mHeight = 1; + mTextureWidth = 1; + mTextureHeight = 1; + + message.setValueU32("format", GL_RGBA); + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV); + + message.setValueS32("depth", mDepth); + message.setValueS32("default_width", mWidth); + message.setValueS32("default_height", mHeight); + message.setValueU32("internalformat", GL_RGBA8); + message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. + message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale + sendMessage(message); + } + else if(message_name == "size_change") { std::string name = message_in.getValue("name"); S32 width = message_in.getValueS32("width"); diff --git a/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index 9b4c531..68b9679 100755 --- a/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/linden/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ @@ -860,36 +861,6 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) plugin_version += codec.str(); message.setValue("plugin_version", plugin_version); sendMessage(message); - - // Plugin gets to decide the texture parameters to use. - message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - #if defined(LL_WINDOWS) - // Values for Windows - mDepth = 3; - message.setValueU32("format", GL_RGB); - message.setValueU32("type", GL_UNSIGNED_BYTE); - - // We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even. - // Padding to a multiple of 3*32 guarantees it'll divide out properly. - message.setValueU32("padding", 32 * 3); - #else - // Values for Mac - mDepth = 4; - message.setValueU32("format", GL_BGRA_EXT); - #ifdef __BIG_ENDIAN__ - message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV ); - #else - message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8); - #endif - - // Pad texture width to a multiple of 32 bytes, to line up with cache lines. - message.setValueU32("padding", 32); - #endif - message.setValueS32("depth", mDepth); - message.setValueU32("internalformat", GL_RGB); - message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. - message.setValueBoolean("allow_downsample", true); - sendMessage(message); } else if(message_name == "idle") { @@ -954,7 +925,41 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string) } else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) { - if(message_name == "size_change") + if(message_name == "init") + { + // This is the media init message -- all necessary data for initialization should have been received. + + // Plugin gets to decide the texture parameters to use. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + #if defined(LL_WINDOWS) + // Values for Windows + mDepth = 3; + message.setValueU32("format", GL_RGB); + message.setValueU32("type", GL_UNSIGNED_BYTE); + + // We really want to pad the texture width to a multiple of 32 bytes, but since we're using 3-byte pixels, it doesn't come out even. + // Padding to a multiple of 3*32 guarantees it'll divide out properly. + message.setValueU32("padding", 32 * 3); + #else + // Values for Mac + mDepth = 4; + message.setValueU32("format", GL_BGRA_EXT); + #ifdef __BIG_ENDIAN__ + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV ); + #else + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8); + #endif + + // Pad texture width to a multiple of 32 bytes, to line up with cache lines. + message.setValueU32("padding", 32); + #endif + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGB); + message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. + message.setValueBoolean("allow_downsample", true); + sendMessage(message); + } + else if(message_name == "size_change") { std::string name = message_in.getValue("name"); S32 width = message_in.getValueS32("width"); diff --git a/linden/indra/media_plugins/webkit/CMakeLists.txt b/linden/indra/media_plugins/webkit/CMakeLists.txt index 1c999ba..be02781 100644 --- a/linden/indra/media_plugins/webkit/CMakeLists.txt +++ b/linden/indra/media_plugins/webkit/CMakeLists.txt @@ -14,10 +14,12 @@ include(Linking) include(PluginAPI) include(MediaPluginBase) include(FindOpenGL) +#include(PulseAudio) include(WebKitLibPlugin) include_directories( + ${PULSEAUDIO_INCLUDE_DIRS} ${LLPLUGIN_INCLUDE_DIRS} ${MEDIA_PLUGIN_BASE_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS} @@ -35,13 +37,13 @@ set(media_plugin_webkit_SOURCE_FILES media_plugin_webkit.cpp ) -if(WORD_SIZE EQUAL 64) +if(NOT CMAKE_SIZEOF_VOID_P MATCHES 4) if(WINDOWS) add_definitions(/FIXED:NO) else(WINDOWS) # not windows therefore gcc LINUX and DARWIN add_definitions(-fPIC) endif(WINDOWS) -endif (WORD_SIZE EQUAL 64) +endif (NOT CMAKE_SIZEOF_VOID_P MATCHES 4) set(media_plugin_webkit_LINK_LIBRARIES ${LLPLUGIN_LIBRARIES} @@ -49,9 +51,11 @@ set(media_plugin_webkit_LINK_LIBRARIES ${LLCOMMON_LIBRARIES} ${WEBKIT_PLUGIN_LIBRARIES} ${PLUGIN_API_WINDOWS_LIBRARIES} + ${PULSEAUDIO_LIBRARIES} ) -if(LINUX) +if (LINUX) + list(APPEND media_plugin_webkit_SOURCE_FILES linux_volume_catcher.cpp) list(APPEND media_plugin_webkit_LINK_LIBRARIES ${UI_LIBRARIES} # for glib/GTK ) diff --git a/linden/indra/media_plugins/webkit/linux_volume_catcher.cpp b/linden/indra/media_plugins/webkit/linux_volume_catcher.cpp new file mode 100755 index 0000000..15a2dfb --- /dev/null +++ b/linden/indra/media_plugins/webkit/linux_volume_catcher.cpp @@ -0,0 +1,490 @@ +/** + * @file linux_volume_catcher.cpp + * @brief A Linux-specific, PulseAudio-specific hack to detect and volume-adjust new audio sources + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +/* + The high-level design is as follows: + 1) Connect to the PulseAudio daemon + 2) Watch for the creation of new audio players connecting to the daemon (this includes ALSA clients running on the PulseAudio emulation layer, such as Flash plugins) + 3) Examine any new audio player's PID to see if it belongs to our own process + 4) If so, tell PA to adjust the volume of that audio player ('sink input' in PA parlance) + 5) Keep a list of all living audio players that we care about, adjust the volumes of all of them when we get a new setVolume() call + */ + +#include "linden_common.h" + +#include "linux_volume_catcher.h" + + +#if LL_PULSEAUDIO_ENABLED + +extern "C" { +#include <glib.h> + +#include <pulse/introspect.h> +#include <pulse/context.h> +#include <pulse/subscribe.h> +#include <pulse/glib-mainloop.h> // There's no special reason why we want the *glib* PA mainloop, but the generic polling implementation seems broken. + +#include "apr_pools.h" +#include "apr_dso.h" +} + +//////////////////////////////////////////////////// + +#define DEBUGMSG(...) do {} while(0) +#define INFOMSG(...) do {} while(0) +#define WARNMSG(...) do {} while(0) + +#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) RTN (*ll##PASYM)(__VA_ARGS__) = NULL +#include "linux_volume_catcher_pa_syms.inc" +#include "linux_volume_catcher_paglib_syms.inc" +#undef LL_PA_SYM + +static bool sSymsGrabbed = false; +static apr_pool_t *sSymPADSOMemoryPool = NULL; +static apr_dso_handle_t *sSymPADSOHandleG = NULL; + +bool grab_pa_syms(std::string pulse_dso_name) +{ + if (sSymsGrabbed) + { + // already have grabbed good syms + return true; + } + + bool sym_error = false; + bool rtn = false; + apr_status_t rv; + apr_dso_handle_t *sSymPADSOHandle = NULL; + +#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##PASYM, sSymPADSOHandle, #PASYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #PASYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #PASYM, (void*)ll##PASYM);}while(0) + + //attempt to load the shared library + apr_pool_create(&sSymPADSOMemoryPool, NULL); + + if ( APR_SUCCESS == (rv = apr_dso_load(&sSymPADSOHandle, + pulse_dso_name.c_str(), + sSymPADSOMemoryPool) )) + { + INFOMSG("Found DSO: %s", pulse_dso_name.c_str()); + +#include "linux_volume_catcher_pa_syms.inc" +#include "linux_volume_catcher_paglib_syms.inc" + + if ( sSymPADSOHandle ) + { + sSymPADSOHandleG = sSymPADSOHandle; + sSymPADSOHandle = NULL; + } + + rtn = !sym_error; + } + else + { + INFOMSG("Couldn't load DSO: %s", pulse_dso_name.c_str()); + rtn = false; // failure + } + + if (sym_error) + { + WARNMSG("Failed to find necessary symbols in PulseAudio libraries."); + } +#undef LL_PA_SYM + + sSymsGrabbed = rtn; + return rtn; +} + + +void ungrab_pa_syms() +{ + // should be safe to call regardless of whether we've + // actually grabbed syms. + + if ( sSymPADSOHandleG ) + { + apr_dso_unload(sSymPADSOHandleG); + sSymPADSOHandleG = NULL; + } + + if ( sSymPADSOMemoryPool ) + { + apr_pool_destroy(sSymPADSOMemoryPool); + sSymPADSOMemoryPool = NULL; + } + + // NULL-out all of the symbols we'd grabbed +#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{ll##PASYM = NULL;}while(0) +#include "linux_volume_catcher_pa_syms.inc" +#include "linux_volume_catcher_paglib_syms.inc" +#undef LL_PA_SYM + + sSymsGrabbed = false; +} +//////////////////////////////////////////////////// + +// PulseAudio requires a chain of callbacks with C linkage +extern "C" { + void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *i, int eol, void *userdata); + void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata); + void callback_context_state(pa_context *context, void *userdata); +} + + +class LinuxVolumeCatcherImpl +{ +public: + LinuxVolumeCatcherImpl(); + ~LinuxVolumeCatcherImpl(); + + void setVolume(F32 volume); + void pump(void); + + // for internal use - can't be private because used from our C callbacks + + bool loadsyms(std::string pulse_dso_name); + void init(); + void cleanup(); + + void update_all_volumes(F32 volume); + void update_index_volume(U32 index, F32 volume); + void connected_okay(); + + std::set<U32> mSinkInputIndices; + std::map<U32,U32> mSinkInputNumChannels; + F32 mDesiredVolume; + pa_glib_mainloop *mMainloop; + pa_context *mPAContext; + bool mConnected; + bool mGotSyms; +}; + +LinuxVolumeCatcherImpl::LinuxVolumeCatcherImpl() + : mDesiredVolume(0.0f), + mMainloop(NULL), + mPAContext(NULL), + mConnected(false), + mGotSyms(false) +{ + init(); +} + +LinuxVolumeCatcherImpl::~LinuxVolumeCatcherImpl() +{ + cleanup(); +} + +bool LinuxVolumeCatcherImpl::loadsyms(std::string pulse_dso_name) +{ + return grab_pa_syms(pulse_dso_name); +} + +void LinuxVolumeCatcherImpl::init() +{ + // try to be as defensive as possible because PA's interface is a + // bit fragile and (for our purposes) we'd rather simply not function + // than crash + + // we cheat and rely upon libpulse-mainloop-glib.so.0 to pull-in + // libpulse.so.0 - this isn't a great assumption, and the two DSOs should + // probably be loaded separately. Our Linux DSO framework needs refactoring, + // we do this sort of thing a lot with practically identical logic... + mGotSyms = loadsyms("libpulse-mainloop-glib.so.0"); + if (!mGotSyms) return; + + mMainloop = llpa_glib_mainloop_new(g_main_context_default()); + if (mMainloop) + { + pa_mainloop_api *api = llpa_glib_mainloop_get_api(mMainloop); + if (api) + { + pa_proplist *proplist = llpa_proplist_new(); + if (proplist) + { + llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "multimedia-player"); + llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "com.secondlife.viewer.mediaplugvoladjust"); + llpa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "SL Plugin Volume Adjuster"); + llpa_proplist_sets(proplist, PA_PROP_APPLICATION_VERSION, "1"); + + // plain old pa_context_new() is broken! + mPAContext = llpa_context_new_with_proplist(api, NULL, proplist); + llpa_proplist_free(proplist); + } + } + } + + // Now we've set up a PA context and mainloop, try connecting the + // PA context to a PA daemon. + if (mPAContext) + { + llpa_context_set_state_callback(mPAContext, callback_context_state, this); + pa_context_flags_t cflags = (pa_context_flags)0; // maybe add PA_CONTEXT_NOAUTOSPAWN? + if (llpa_context_connect(mPAContext, NULL, cflags, NULL) >= 0) + { + // Okay! We haven't definitely connected, but we + // haven't definitely failed yet. + } + else + { + // Failed to connect to PA manager... we'll leave + // things like that. Perhaps we should try again later. + } + } +} + +void LinuxVolumeCatcherImpl::cleanup() +{ + mConnected = false; + + if (mGotSyms && mPAContext) + { + llpa_context_disconnect(mPAContext); + llpa_context_unref(mPAContext); + } + mPAContext = NULL; + + if (mGotSyms && mMainloop) + { + llpa_glib_mainloop_free(mMainloop); + } + mMainloop = NULL; +} + +void LinuxVolumeCatcherImpl::setVolume(F32 volume) +{ + mDesiredVolume = volume; + + if (!mGotSyms) return; + + if (mConnected && mPAContext) + { + update_all_volumes(mDesiredVolume); + } + + pump(); +} + +void LinuxVolumeCatcherImpl::pump() +{ + gboolean may_block = FALSE; + g_main_context_iteration(g_main_context_default(), may_block); +} + +void LinuxVolumeCatcherImpl::connected_okay() +{ + pa_operation *op; + + // fetch global list of existing sinkinputs + if ((op = llpa_context_get_sink_input_info_list(mPAContext, + callback_discovered_sinkinput, + this))) + { + llpa_operation_unref(op); + } + + // subscribe to future global sinkinput changes + llpa_context_set_subscribe_callback(mPAContext, + callback_subscription_alert, + this); + if ((op = llpa_context_subscribe(mPAContext, (pa_subscription_mask_t) + (PA_SUBSCRIPTION_MASK_SINK_INPUT), + NULL, NULL))) + { + llpa_operation_unref(op); + } +} + +void LinuxVolumeCatcherImpl::update_all_volumes(F32 volume) +{ + for (std::set<U32>::iterator it = mSinkInputIndices.begin(); + it != mSinkInputIndices.end(); ++it) + { + update_index_volume(*it, volume); + } +} + +void LinuxVolumeCatcherImpl::update_index_volume(U32 index, F32 volume) +{ + static pa_cvolume cvol; + llpa_cvolume_set(&cvol, mSinkInputNumChannels[index], + llpa_sw_volume_from_linear(volume)); + + pa_context *c = mPAContext; + uint32_t idx = index; + const pa_cvolume *cvolumep = &cvol; + pa_context_success_cb_t cb = NULL; // okay as null + void *userdata = NULL; // okay as null + + pa_operation *op; + if ((op = llpa_context_set_sink_input_volume(c, idx, cvolumep, cb, userdata))) + { + llpa_operation_unref(op); + } +} + + +void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *sii, int eol, void *userdata) +{ + LinuxVolumeCatcherImpl *impl = dynamic_cast<LinuxVolumeCatcherImpl*>((LinuxVolumeCatcherImpl*)userdata); + llassert(impl); + + if (0 == eol) + { + pa_proplist *proplist = sii->proplist; + pid_t sinkpid = atoll(llpa_proplist_gets(proplist, PA_PROP_APPLICATION_PROCESS_ID)); + + if (sinkpid == getpid()) // does the discovered sinkinput belong to this process? + { + bool is_new = (impl->mSinkInputIndices.find(sii->index) == + impl->mSinkInputIndices.end()); + + impl->mSinkInputIndices.insert(sii->index); + impl->mSinkInputNumChannels[sii->index] = sii->channel_map.channels; + + if (is_new) + { + // new! + impl->update_index_volume(sii->index, impl->mDesiredVolume); + } + else + { + // seen it already, do nothing. + } + } + } +} + +void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata) +{ + LinuxVolumeCatcherImpl *impl = dynamic_cast<LinuxVolumeCatcherImpl*>((LinuxVolumeCatcherImpl*)userdata); + llassert(impl); + + switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { + case PA_SUBSCRIPTION_EVENT_SINK_INPUT: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == + PA_SUBSCRIPTION_EVENT_REMOVE) + { + // forget this sinkinput, if we were caring about it + impl->mSinkInputIndices.erase(index); + impl->mSinkInputNumChannels.erase(index); + } + else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == + PA_SUBSCRIPTION_EVENT_NEW) + { + // ask for more info about this new sinkinput + pa_operation *op; + if ((op = llpa_context_get_sink_input_info(impl->mPAContext, index, callback_discovered_sinkinput, impl))) + { + llpa_operation_unref(op); + } + } + else + { + // property change on this sinkinput - we don't care. + } + break; + + default:; + } +} + +void callback_context_state(pa_context *context, void *userdata) +{ + LinuxVolumeCatcherImpl *impl = dynamic_cast<LinuxVolumeCatcherImpl*>((LinuxVolumeCatcherImpl*)userdata); + llassert(impl); + + switch (llpa_context_get_state(context)) + { + case PA_CONTEXT_READY: + impl->mConnected = true; + impl->connected_okay(); + break; + case PA_CONTEXT_TERMINATED: + impl->mConnected = false; + break; + case PA_CONTEXT_FAILED: + impl->mConnected = false; + break; + default:; + } +} + +///////////////////////////////////////////////////// + +LinuxVolumeCatcher::LinuxVolumeCatcher() +{ + pimpl = new LinuxVolumeCatcherImpl(); +} + +LinuxVolumeCatcher::~LinuxVolumeCatcher() +{ + delete pimpl; + pimpl = NULL; +} + +void LinuxVolumeCatcher::setVolume(F32 volume) +{ + llassert(pimpl); + pimpl->setVolume(volume); +} + +void LinuxVolumeCatcher::pump() +{ + llassert(pimpl); + pimpl->pump(); +} + +#else // !LL_PULSEAUDIO_ENABLED + +// stub. + +LinuxVolumeCatcher::LinuxVolumeCatcher() +{ + pimpl = NULL; +} + +LinuxVolumeCatcher::~LinuxVolumeCatcher() +{ +} + +void LinuxVolumeCatcher::setVolume(F32 volume) +{ +} + +void LinuxVolumeCatcher::pump() +{ +} + +#endif // LL_PULSEAUDIO_ENABLED diff --git a/linden/indra/media_plugins/webkit/linux_volume_catcher.h b/linden/indra/media_plugins/webkit/linux_volume_catcher.h new file mode 100755 index 0000000..d4a1b38 --- /dev/null +++ b/linden/indra/media_plugins/webkit/linux_volume_catcher.h @@ -0,0 +1,56 @@ +/** + * @file linux_volume_catcher.h + * @brief A Linux-specific, PulseAudio-specific hack to detect and volume-adjust new audio sources + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#ifndef LINUX_VOLUME_CATCHER_H +#define LINUX_VOLUME_CATCHER_H + +#include "linden_common.h" + +class LinuxVolumeCatcherImpl; + +class LinuxVolumeCatcher +{ + public: + LinuxVolumeCatcher(); + ~LinuxVolumeCatcher(); + + void setVolume(F32 volume); // 0.0 - 1.0 + void pump(); // call this at least a few times a second if you can - it affects how quickly we can 'catch' a new audio source and adjust its volume + + private: + LinuxVolumeCatcherImpl *pimpl; +}; + +#endif // LINUX_VOLUME_CATCHER_H diff --git a/linden/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc b/linden/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc new file mode 100755 index 0000000..d806b48 --- /dev/null +++ b/linden/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc @@ -0,0 +1,21 @@ +// required symbols to grab +LL_PA_SYM(true, pa_context_connect, int, pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api); +LL_PA_SYM(true, pa_context_disconnect, void, pa_context *c); +LL_PA_SYM(true, pa_context_get_sink_input_info, pa_operation*, pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata); +LL_PA_SYM(true, pa_context_get_sink_input_info_list, pa_operation*, pa_context *c, pa_sink_input_info_cb_t cb, void *userdata); +LL_PA_SYM(true, pa_context_get_state, pa_context_state_t, pa_context *c); +LL_PA_SYM(true, pa_context_new_with_proplist, pa_context*, pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist); +LL_PA_SYM(true, pa_context_set_sink_input_volume, pa_operation*, pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); +LL_PA_SYM(true, pa_context_set_state_callback, void, pa_context *c, pa_context_notify_cb_t cb, void *userdata); +LL_PA_SYM(true, pa_context_set_subscribe_callback, void, pa_context *c, pa_context_subscribe_cb_t cb, void *userdata); +LL_PA_SYM(true, pa_context_subscribe, pa_operation*, pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata); +LL_PA_SYM(true, pa_context_unref, void, pa_context *c); +LL_PA_SYM(true, pa_cvolume_set, pa_cvolume*, pa_cvolume *a, unsigned channels, pa_volume_t v); +LL_PA_SYM(true, pa_operation_unref, void, pa_operation *o); +LL_PA_SYM(true, pa_proplist_free, void, pa_proplist* p); +LL_PA_SYM(true, pa_proplist_gets, const char*, pa_proplist *p, const char *key); +LL_PA_SYM(true, pa_proplist_new, pa_proplist*, void); +LL_PA_SYM(true, pa_proplist_sets, int, pa_proplist *p, const char *key, const char *value); +LL_PA_SYM(true, pa_sw_volume_from_linear, pa_volume_t, double v); + +// optional symbols to grab diff --git a/linden/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc b/linden/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc new file mode 100755 index 0000000..abf628c --- /dev/null +++ b/linden/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc @@ -0,0 +1,6 @@ +// required symbols to grab +LL_PA_SYM(true, pa_glib_mainloop_free, void, pa_glib_mainloop* g); +LL_PA_SYM(true, pa_glib_mainloop_get_api, pa_mainloop_api*, pa_glib_mainloop* g); +LL_PA_SYM(true, pa_glib_mainloop_new, pa_glib_mainloop *, GMainContext *c); + +// optional symbols to grab diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp index 2e3f06d..28c6e98 100755 --- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,9 +29,10 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ -#include <iomanip>//FIXME: This is included from elsewhere in SG2.0 + #include "llqtwebkit.h" #include "linden_common.h" @@ -44,11 +45,22 @@ #include "llpluginmessageclasses.h" #include "media_plugin_base.h" +// set to 1 if you're using the version of llqtwebkit that's QPixmap-ified +#if LL_LINUX +# define LL_QTWEBKIT_USES_PIXMAPS 0 +#else +# define LL_QTWEBKIT_USES_PIXMAPS 0 +#endif // LL_LINUX + +#if LL_LINUX +# include "linux_volume_catcher.h" +#endif // LL_LINUX + #if LL_WINDOWS -#include <direct.h> +# include <direct.h> #else -#include <unistd.h> -#include <stdlib.h> +# include <unistd.h> +# include <stdlib.h> #endif #if LL_WINDOWS @@ -78,10 +90,16 @@ public: private: std::string mProfileDir; + std::string mHostLanguage; + std::string mUserAgent; + bool mCookiesEnabled; + bool mJavascriptEnabled; + bool mPluginsEnabled; enum { - INIT_STATE_UNINITIALIZED, // Browser instance hasn't been set up yet + INIT_STATE_UNINITIALIZED, // LLQtWebkit hasn't been set up yet + INIT_STATE_INITIALIZED, // LLQtWebkit has been set up, but no browser window has been created yet. INIT_STATE_NAVIGATING, // Browser instance has been set up and initial navigate to about:blank has been issued INIT_STATE_NAVIGATE_COMPLETE, // initial navigate to about:blank has completed INIT_STATE_WAIT_REDRAW, // First real navigate begin has been received, waiting for page changed event to start handling redraws @@ -103,6 +121,10 @@ private: F32 mBackgroundG; F32 mBackgroundB; +#if LL_LINUX + LinuxVolumeCatcher mLinuxVolumeCatcher; +#endif // LL_LINUX + void setInitState(int state) { // std::cerr << "changing init state to " << state << std::endl; @@ -115,6 +137,10 @@ private: { LLQtWebKit::getInstance()->pump( milliseconds ); +#if LL_LINUX + mLinuxVolumeCatcher.pump(); +#endif // LL_LINUX + checkEditState(); if(mInitState == INIT_STATE_NAVIGATE_COMPLETE) @@ -131,7 +157,11 @@ private: { const unsigned char* browser_pixels = LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId ); - unsigned int buffer_size = LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId ) * LLQtWebKit::getInstance()->getBrowserHeight( mBrowserWindowId ); + unsigned int rowspan = LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId ); + unsigned int height = LLQtWebKit::getInstance()->getBrowserHeight( mBrowserWindowId ); +#if !LL_QTWEBKIT_USES_PIXMAPS + unsigned int buffer_size = rowspan * height; +#endif // !LL_QTWEBKIT_USES_PIXMAPS // std::cerr << "webkit plugin: updating" << std::endl; @@ -139,7 +169,16 @@ private: if ( mPixels && browser_pixels ) { // std::cerr << " memcopy of " << buffer_size << " bytes" << std::endl; + +#if LL_QTWEBKIT_USES_PIXMAPS + // copy the pixel data upside-down because of the co-ord system + for (int y=0; y<height; ++y) + { + memcpy( &mPixels[(height-y-1)*rowspan], &browser_pixels[y*rowspan], rowspan ); + } +#else memcpy( mPixels, browser_pixels, buffer_size ); +#endif // LL_QTWEBKIT_USES_PIXMAPS } if ( mWidth > 0 && mHeight > 0 ) @@ -160,13 +199,6 @@ private: if ( mInitState > INIT_STATE_UNINITIALIZED ) return true; - // not enough information to initialize the browser yet. - if ( mWidth < 0 || mHeight < 0 || mDepth < 0 || - mTextureWidth < 0 || mTextureHeight < 0 ) - { - return false; - }; - // set up directories char cwd[ FILENAME_MAX ]; // I *think* this is defined on all platforms we use if (NULL == getcwd( cwd, FILENAME_MAX - 1 )) @@ -177,12 +209,12 @@ private: std::string application_dir = std::string( cwd ); #if LL_DARWIN - // When running under the Xcode debugger, there's a setting called "Break on Debugger()/DebugStr()" which defaults to being turned on. - // This causes the environment variable USERBREAK to be set to 1, which causes these legacy calls to break into the debugger. - // This wouldn't cause any problems except for the fact that the current release version of the Flash plugin has a call to Debugger() in it - // which gets hit when the plugin is probed by webkit. - // Unsetting the environment variable here works around this issue. - unsetenv("USERBREAK"); + // When running under the Xcode debugger, there's a setting called "Break on Debugger()/DebugStr()" which defaults to being turned on. + // This causes the environment variable USERBREAK to be set to 1, which causes these legacy calls to break into the debugger. + // This wouldn't cause any problems except for the fact that the current release version of the Flash plugin has a call to Debugger() in it + // which gets hit when the plugin is probed by webkit. + // Unsetting the environment variable here works around this issue. + unsetenv("USERBREAK"); #endif #if LL_WINDOWS @@ -223,65 +255,91 @@ private: bool result = LLQtWebKit::getInstance()->init( application_dir, component_dir, mProfileDir, native_window_handle ); if ( result ) { - // create single browser window - mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight ); -#if LL_WINDOWS - // Enable plugins - LLQtWebKit::getInstance()->enablePlugins(true); -#elif LL_DARWIN - // Enable plugins - LLQtWebKit::getInstance()->enablePlugins(true); -#elif LL_LINUX - // Enable plugins - LLQtWebKit::getInstance()->enablePlugins(true); -#endif - // Enable cookies - LLQtWebKit::getInstance()->enableCookies( true ); - - // tell LLQtWebKit about the size of the browser window - LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); - - // observer events that LLQtWebKit emits - LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this ); - - // append details to agent string - LLQtWebKit::getInstance()->setBrowserAgentId( "LLPluginMedia Web Browser" ); - - // don't flip bitmap - LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true ); - - // set background color - // convert background color channels from [0.0, 1.0] to [0, 255]; - LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, int(mBackgroundR * 255.0f), int(mBackgroundG * 255.0f), int(mBackgroundB * 255.0f) ); - - // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns. - setInitState(INIT_STATE_NAVIGATING); - - // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance. - // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially - // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date. - // Build a data URL like this: "data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#RRGGBB%22%3E%3C/body%3E%3C/html%3E" - // where RRGGBB is the background color in HTML style - std::stringstream url; + mInitState = INIT_STATE_INITIALIZED; - url << "data:text/html,%3Chtml%3E%3Cbody%20bgcolor=%22#"; - // convert background color channels from [0.0, 1.0] to [0, 255]; - url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundR * 255.0f); - url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundG * 255.0f); - url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f); - url << "%22%3E%3C/body%3E%3C/html%3E"; - - lldebugs << "data url is: " << url.str() << llendl; - - LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() ); -// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" ); - return true; }; return false; }; + //////////////////////////////////////////////////////////////////////////////// + // + bool initBrowserWindow() + { + // already initialized + if ( mInitState > INIT_STATE_INITIALIZED ) + return true; + + // not enough information to initialize the browser yet. + if ( mWidth < 0 || mHeight < 0 || mDepth < 0 || + mTextureWidth < 0 || mTextureHeight < 0 ) + { + return false; + }; + + // Set up host language before creating browser window + if(!mHostLanguage.empty()) + { + LLQtWebKit::getInstance()->setHostLanguage(mHostLanguage); + } + + // turn on/off cookies based on what host app tells us + LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled ); + + // turn on/off plugins based on what host app tells us + LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled ); + + // turn on/off Javascript based on what host app tells us + LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled ); + + // create single browser window + mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight ); + + // tell LLQtWebKit about the size of the browser window + LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); + + // observer events that LLQtWebKit emits + LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this ); + + // append details to agent string + LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent ); + +#if !LL_QTWEBKIT_USES_PIXMAPS + // don't flip bitmap + LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true ); +#endif // !LL_QTWEBKIT_USES_PIXMAPS + + // set background color + // convert background color channels from [0.0, 1.0] to [0, 255]; + LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, int(mBackgroundR * 255.0f), int(mBackgroundG * 255.0f), int(mBackgroundB * 255.0f) ); + + // Set state _before_ starting the navigate, since onNavigateBegin might get called before this call returns. + setInitState(INIT_STATE_NAVIGATING); + + // Don't do this here -- it causes the dreaded "white flash" when loading a browser instance. + // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially + // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date. + // Build a data URL like this: "data:text/html,%3Chtml%3E%3Cbody bgcolor=%22#RRGGBB%22%3E%3C/body%3E%3C/html%3E" + // where RRGGBB is the background color in HTML style + std::stringstream url; + + url << "data:text/html,%3Chtml%3E%3Cbody%20bgcolor=%22#"; + // convert background color channels from [0.0, 1.0] to [0, 255]; + url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundR * 255.0f); + url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundG * 255.0f); + url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f); + url << "%22%3E%3C/body%3E%3C/html%3E"; + + lldebugs << "data url is: " << url.str() << llendl; + + LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() ); +// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" ); + + return true; + } + + void setVolume(F32 vol); //////////////////////////////////////////////////////////////////////////////// // virtual @@ -616,6 +674,11 @@ MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_ mBackgroundR = 0.0f; mBackgroundG = 0.0f; mBackgroundB = 0.0f; + + mHostLanguage = "en"; // default to english + mJavascriptEnabled = true; // default to on + mPluginsEnabled = true; // default to on + mUserAgent = "LLPluginMedia Web Browser"; } MediaPluginWebKit::~MediaPluginWebKit() @@ -642,9 +705,6 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) { if(message_name == "init") { - std::string user_data_path = message_in.getValue("user_data_path"); // n.b. always has trailing platform-specific dir-delimiter - mProfileDir = user_data_path + "browser_profile"; - LLPluginMessage message("base", "init_response"); LLSD versions = LLSD::emptyMap(); versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; @@ -656,19 +716,6 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) plugin_version += LLQtWebKit::getInstance()->getVersion(); message.setValue("plugin_version", plugin_version); sendMessage(message); - - // Plugin gets to decide the texture parameters to use. - mDepth = 4; - - message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - message.setValueS32("default_width", 1024); - message.setValueS32("default_height", 1024); - message.setValueS32("depth", mDepth); - message.setValueU32("internalformat", GL_RGBA); - message.setValueU32("format", GL_RGBA); - message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", true); - sendMessage(message); } else if(message_name == "idle") { @@ -733,9 +780,68 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) // std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; } } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) + { + if(message_name == "set_volume") + { + F32 volume = message_in.getValueReal("volume"); + setVolume(volume); + } + } else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) { - if(message_name == "size_change") + if(message_name == "init") + { + // This is the media init message -- all necessary data for initialization should have been received. + if(initBrowser()) + { + + // Plugin gets to decide the texture parameters to use. + mDepth = 4; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("default_width", 1024); + message.setValueS32("default_height", 1024); + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGBA); + #if LL_QTWEBKIT_USES_PIXMAPS + message.setValueU32("format", GL_BGRA_EXT); // I hope this isn't system-dependant... is it? If so, we'll have to check the root window's pixel layout or something... yuck. + #else + message.setValueU32("format", GL_RGBA); + #endif // LL_QTWEBKIT_USES_PIXMAPS + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", true); + sendMessage(message); + } + else + { + // if initialization failed, we're done. + mDeleteMe = true; + } + + } + else if(message_name == "set_user_data_path") + { + std::string user_data_path = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter + mProfileDir = user_data_path + "browser_profile"; + + // FIXME: Should we do anything with this if it comes in after the browser has been initialized? + } + else if(message_name == "set_language_code") + { + mHostLanguage = message_in.getValue("language"); + + // FIXME: Should we do anything with this if it comes in after the browser has been initialized? + } + else if(message_name == "plugins_enabled") + { + mPluginsEnabled = message_in.getValueBoolean("enable"); + } + else if(message_name == "javascript_enabled") + { + mJavascriptEnabled = message_in.getValueBoolean("enable"); + } + else if(message_name == "size_change") { std::string name = message_in.getValue("name"); S32 width = message_in.getValueS32("width"); @@ -757,29 +863,36 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) mWidth = width; mHeight = height; - // initialize (only gets called once) - initBrowser(); - - // size changed so tell the browser - LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); - -// std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight -// << ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl; - - S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId); - - // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response. - if(real_width <= texture_width) + if(initBrowserWindow()) { - texture_width = real_width; + + // size changed so tell the browser + LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); + + // std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight + // << ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl; + + S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId); + + // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response. + if(real_width <= texture_width) + { + texture_width = real_width; + } + else + { + // This won't work -- it'll be bigger than the allocated memory. This is a fatal error. + // std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl; + mDeleteMe = true; + return; + } } else { - // This won't work -- it'll be bigger than the allocated memory. This is a fatal error. -// std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl; + // Setting up the browser window failed. This is a fatal error. mDeleteMe = true; - return; } + mTextureWidth = texture_width; mTextureHeight = texture_height; @@ -929,8 +1042,18 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) } else if(message_name == "enable_cookies") { - bool val = message_in.getValueBoolean("enable"); - LLQtWebKit::getInstance()->enableCookies( val ); + mCookiesEnabled = message_in.getValueBoolean("enable"); + LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled ); + } + else if(message_name == "enable_plugins") + { + mPluginsEnabled = message_in.getValueBoolean("enable"); + LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled ); + } + else if(message_name == "enable_javascript") + { + mJavascriptEnabled = message_in.getValueBoolean("enable"); + //LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled ); } else if(message_name == "proxy_setup") { @@ -967,8 +1090,8 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) } else if(message_name == "set_user_agent") { - std::string user_agent = message_in.getValue("user_agent"); - LLQtWebKit::getInstance()->setBrowserAgentId( user_agent ); + mUserAgent = message_in.getValue("user_agent"); + LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent ); } else if(message_name == "init_history") { @@ -999,6 +1122,13 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) } } +void MediaPluginWebKit::setVolume(F32 volume) +{ +#if LL_LINUX + mLinuxVolumeCatcher.setVolume(volume); +#endif // LL_LINUX +} + int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) { MediaPluginWebKit *self = new MediaPluginWebKit(host_send_func, host_user_data); -- cgit v1.1 From 093b99196f27b518b183953cade1077fa6d7c5ed Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Mon, 14 Jun 2010 17:51:51 +0200 Subject: update llplugin to latest version of SG2, pull latest webkit --- linden/indra/llplugin/CMakeLists.txt | 4 +- linden/indra/llplugin/llpluginclassmedia.cpp | 48 ++++++++++++++++++---- linden/indra/llplugin/llpluginclassmedia.h | 15 +++++-- linden/indra/llplugin/llpluginclassmediaowner.h | 5 ++- linden/indra/llplugin/llplugininstance.cpp | 5 ++- linden/indra/llplugin/llplugininstance.h | 5 ++- linden/indra/llplugin/llpluginmessage.cpp | 5 ++- linden/indra/llplugin/llpluginmessage.h | 5 ++- linden/indra/llplugin/llpluginmessageclasses.h | 5 ++- linden/indra/llplugin/llpluginmessagepipe.cpp | 5 ++- linden/indra/llplugin/llpluginmessagepipe.h | 5 ++- linden/indra/llplugin/llpluginprocesschild.cpp | 7 ++-- linden/indra/llplugin/llpluginprocesschild.h | 7 ++-- linden/indra/llplugin/llpluginprocessparent.cpp | 12 +++--- linden/indra/llplugin/llpluginprocessparent.h | 12 +++--- linden/indra/llplugin/llpluginsharedmemory.cpp | 5 ++- linden/indra/llplugin/llpluginsharedmemory.h | 5 ++- linden/indra/llplugin/slplugin/slplugin.cpp | 16 ++++++-- .../media_plugins/webkit/media_plugin_webkit.cpp | 1 + linden/indra/newview/llviewermedia.cpp | 2 +- linden/indra/newview/viewer_manifest.py | 3 +- linden/install.xml | 19 ++++++--- 22 files changed, 132 insertions(+), 64 deletions(-) (limited to 'linden') diff --git a/linden/indra/llplugin/CMakeLists.txt b/linden/indra/llplugin/CMakeLists.txt index e41cdf7..d9b623d 100755 --- a/linden/indra/llplugin/CMakeLists.txt +++ b/linden/indra/llplugin/CMakeLists.txt @@ -48,13 +48,13 @@ set(llplugin_HEADER_FILES set_source_files_properties(${llplugin_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) -if(WORD_SIZE EQUAL 64) +if(NOT CMAKE_SIZEOF_VOID_P MATCHES 4) if(WINDOWS) add_definitions(/FIXED:NO) else(WINDOWS) # not windows therefore gcc LINUX and DARWIN add_definitions(-fPIC) endif(WINDOWS) -endif (WORD_SIZE EQUAL 64) +endif (NOT CMAKE_SIZEOF_VOID_P MATCHES 4) list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES}) diff --git a/linden/indra/llplugin/llpluginclassmedia.cpp b/linden/indra/llplugin/llpluginclassmedia.cpp index 2e8bf3f..b958f0c 100755 --- a/linden/indra/llplugin/llpluginclassmedia.cpp +++ b/linden/indra/llplugin/llpluginclassmedia.cpp @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ @@ -66,15 +67,19 @@ LLPluginClassMedia::~LLPluginClassMedia() reset(); } -bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug, const std::string &user_data_path) +bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug) { LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL; LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL; - LL_DEBUGS("Plugin") << "user_data_path: " << user_data_path << LL_ENDL; mPlugin = new LLPluginProcessParent(this); mPlugin->setSleepTime(mSleepTime); - mPlugin->init(launcher_filename, plugin_filename, debug, user_data_path); + + // Queue up the media init message -- it will be sent after all the currently queued messages. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init"); + sendMessage(message); + + mPlugin->init(launcher_filename, plugin_filename, debug); return true; } @@ -384,7 +389,7 @@ bool LLPluginClassMedia::textureValid(void) bool LLPluginClassMedia::getDirty(LLRect *dirty_rect) { - bool result = !mDirtyRect.isNull();//awfixme isEmpty(); + bool result = !mDirtyRect.isNull(); if(dirty_rect != NULL) { @@ -679,6 +684,34 @@ void LLPluginClassMedia::paste() sendMessage(message); } +void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path"); + message.setValue("path", user_data_path); + sendMessage(message); +} + +void LLPluginClassMedia::setLanguageCode(const std::string &language_code) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code"); + message.setValue("language", language_code); + sendMessage(message); +} + +void LLPluginClassMedia::setPluginsEnabled(const bool enabled) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled"); + message.setValueBoolean("enable", enabled); + sendMessage(message); +} + +void LLPluginClassMedia::setJavascriptEnabled(const bool enabled) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled"); + message.setValueBoolean("enable", enabled); + sendMessage(message); +} + LLPluginClassMedia::ETargetType getTargetTypeFromLLQtWebkit(int target_type) { // convert a LinkTargetType value from llqtwebkit to an ETargetType @@ -746,7 +779,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) newDirtyRect.mBottom = temp; } - if(mDirtyRect.isNull())//awfixme isEmpty()) + if(mDirtyRect.isNull()) { mDirtyRect = newDirtyRect; } @@ -1048,6 +1081,7 @@ void LLPluginClassMedia::clear_cookies() void LLPluginClassMedia::enable_cookies(bool enable) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies"); + message.setValueBoolean("enable", enable); sendMessage(message); } diff --git a/linden/indra/llplugin/llpluginclassmedia.h b/linden/indra/llplugin/llpluginclassmedia.h index ab54348..fc94563 100755 --- a/linden/indra/llplugin/llpluginclassmedia.h +++ b/linden/indra/llplugin/llpluginclassmedia.h @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ @@ -50,7 +51,9 @@ public: virtual ~LLPluginClassMedia(); // local initialization, called by the media manager when creating a source - virtual bool init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug, const std::string &user_data_path); + virtual bool init(const std::string &launcher_filename, + const std::string &plugin_filename, + bool debug); // undoes everything init() didm called by the media manager when destroying a source virtual void reset(); @@ -174,6 +177,12 @@ public: void paste(); bool canPaste() const { return mCanPaste; }; + + // These can be called before init(), and they will be queued and sent before the media init message. + void setUserDataPath(const std::string &user_data_path); + void setLanguageCode(const std::string &language_code); + void setPluginsEnabled(const bool enabled); + void setJavascriptEnabled(const bool enabled); /////////////////////////////////// // media browser class functions diff --git a/linden/indra/llplugin/llpluginclassmediaowner.h b/linden/indra/llplugin/llpluginclassmediaowner.h index 239f692..c1f6ae1 100755 --- a/linden/indra/llplugin/llpluginclassmediaowner.h +++ b/linden/indra/llplugin/llpluginclassmediaowner.h @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/llplugin/llplugininstance.cpp b/linden/indra/llplugin/llplugininstance.cpp index ce10cb6..b822b9e 100755 --- a/linden/indra/llplugin/llplugininstance.cpp +++ b/linden/indra/llplugin/llplugininstance.cpp @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/llplugin/llplugininstance.h b/linden/indra/llplugin/llplugininstance.h index baa51cc..9cf6075 100755 --- a/linden/indra/llplugin/llplugininstance.h +++ b/linden/indra/llplugin/llplugininstance.h @@ -12,13 +12,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -28,6 +28,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/llplugin/llpluginmessage.cpp b/linden/indra/llplugin/llpluginmessage.cpp index 8efc774..6452f4a 100755 --- a/linden/indra/llplugin/llpluginmessage.cpp +++ b/linden/indra/llplugin/llpluginmessage.cpp @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/llplugin/llpluginmessage.h b/linden/indra/llplugin/llpluginmessage.h index 82eb89f..fe504c8 100755 --- a/linden/indra/llplugin/llpluginmessage.h +++ b/linden/indra/llplugin/llpluginmessage.h @@ -12,13 +12,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -28,6 +28,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/llplugin/llpluginmessageclasses.h b/linden/indra/llplugin/llpluginmessageclasses.h index 9a39e98..8812a16 100755 --- a/linden/indra/llplugin/llpluginmessageclasses.h +++ b/linden/indra/llplugin/llpluginmessageclasses.h @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/llplugin/llpluginmessagepipe.cpp b/linden/indra/llplugin/llpluginmessagepipe.cpp index 85ed227..b16381c 100755 --- a/linden/indra/llplugin/llpluginmessagepipe.cpp +++ b/linden/indra/llplugin/llpluginmessagepipe.cpp @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/llplugin/llpluginmessagepipe.h b/linden/indra/llplugin/llpluginmessagepipe.h index 63fd569..8f74f38 100755 --- a/linden/indra/llplugin/llpluginmessagepipe.h +++ b/linden/indra/llplugin/llpluginmessagepipe.h @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/llplugin/llpluginprocesschild.cpp b/linden/indra/llplugin/llpluginprocesschild.cpp index e13376f..0b7ce3d 100755 --- a/linden/indra/llplugin/llpluginprocesschild.cpp +++ b/linden/indra/llplugin/llpluginprocesschild.cpp @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ @@ -156,7 +157,6 @@ void LLPluginProcessChild::idle(void) { setState(STATE_PLUGIN_INITIALIZING); LLPluginMessage message("base", "init"); - message.setValue("user_data_path", mUserDataPath); sendMessageToPlugin(message); } break; @@ -329,7 +329,6 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) if(message_name == "load_plugin") { mPluginFile = parsed.getValue("file"); - mUserDataPath = parsed.getValue("user_data_path"); } else if(message_name == "shm_add") { diff --git a/linden/indra/llplugin/llpluginprocesschild.h b/linden/indra/llplugin/llpluginprocesschild.h index 8e9579e..96ae7b4 100755 --- a/linden/indra/llplugin/llpluginprocesschild.h +++ b/linden/indra/llplugin/llpluginprocesschild.h @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ @@ -99,8 +100,6 @@ private: std::string mPluginFile; - std::string mUserDataPath; - LLPluginInstance *mInstance; typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType; diff --git a/linden/indra/llplugin/llpluginprocessparent.cpp b/linden/indra/llplugin/llpluginprocessparent.cpp index 9b8ea8b..8ea28f1 100755 --- a/linden/indra/llplugin/llpluginprocessparent.cpp +++ b/linden/indra/llplugin/llpluginprocessparent.cpp @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ @@ -99,14 +100,12 @@ void LLPluginProcessParent::errorState(void) setState(STATE_ERROR); } -void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug, const std::string &user_data_path) +void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug) { mProcess.setExecutable(launcher_filename); mPluginFile = plugin_filename; mCPUUsage = 0.0f; - mDebug = debug; - mUserDataPath = user_data_path; - + mDebug = debug; setState(STATE_INITIALIZED); } @@ -363,7 +362,6 @@ void LLPluginProcessParent::idle(void) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin"); message.setValue("file", mPluginFile); - message.setValue("user_data_path", mUserDataPath); sendMessage(message); } diff --git a/linden/indra/llplugin/llpluginprocessparent.h b/linden/indra/llplugin/llpluginprocessparent.h index 6dbe0c1..523ce51 100755 --- a/linden/indra/llplugin/llpluginprocessparent.h +++ b/linden/indra/llplugin/llpluginprocessparent.h @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ @@ -60,7 +61,10 @@ public: LLPluginProcessParent(LLPluginProcessParentOwner *owner); ~LLPluginProcessParent(); - void init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug, const std::string &user_data_path); + void init(const std::string &launcher_filename, + const std::string &plugin_filename, + bool debug); + void idle(void); // returns true if the plugin is on its way to steady state @@ -144,8 +148,6 @@ private: std::string mPluginFile; - std::string mUserDataPath; - LLPluginProcessParentOwner *mOwner; typedef std::map<std::string, LLPluginSharedMemory*> sharedMemoryRegionsType; diff --git a/linden/indra/llplugin/llpluginsharedmemory.cpp b/linden/indra/llplugin/llpluginsharedmemory.cpp index a475f12..e8a411a 100755 --- a/linden/indra/llplugin/llpluginsharedmemory.cpp +++ b/linden/indra/llplugin/llpluginsharedmemory.cpp @@ -13,13 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -29,6 +29,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/llplugin/llpluginsharedmemory.h b/linden/indra/llplugin/llpluginsharedmemory.h index 1d23cbe..081d311 100755 --- a/linden/indra/llplugin/llpluginsharedmemory.h +++ b/linden/indra/llplugin/llpluginsharedmemory.h @@ -12,13 +12,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -28,6 +28,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * @endcond */ diff --git a/linden/indra/llplugin/slplugin/slplugin.cpp b/linden/indra/llplugin/slplugin/slplugin.cpp index 526734a..649d568 100755 --- a/linden/indra/llplugin/slplugin/slplugin.cpp +++ b/linden/indra/llplugin/slplugin/slplugin.cpp @@ -14,13 +14,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -30,6 +30,7 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * * * @endcond */ @@ -240,6 +241,9 @@ int main(int argc, char **argv) checkExceptionHandler(); #endif +#if LL_DARWIN + EventTargetRef event_target = GetEventDispatcherTarget(); +#endif while(!plugin->isDone()) { timer.reset(); @@ -247,8 +251,12 @@ int main(int argc, char **argv) #if LL_DARWIN { // Some plugins (webkit at least) will want an event loop. This qualifies. - EventRecord evt; - WaitNextEvent(0, &evt, 0, NULL); + EventRef event; + if(ReceiveNextEvent(0, 0, kEventDurationNoWait, true, &event) == noErr) + { + SendEventToEventTarget (event, event_target); + ReleaseEvent(event); + } } #endif F64 elapsed = timer.getElapsedTimeF64(); diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp index 28c6e98..09ba8dc 100755 --- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -47,6 +47,7 @@ // set to 1 if you're using the version of llqtwebkit that's QPixmap-ified #if LL_LINUX +# include <iomanip> # define LL_QTWEBKIT_USES_PIXMAPS 0 #else # define LL_QTWEBKIT_USES_PIXMAPS 0 diff --git a/linden/indra/newview/llviewermedia.cpp b/linden/indra/newview/llviewermedia.cpp index c0d1460..8c5cf6a 100644 --- a/linden/indra/newview/llviewermedia.cpp +++ b/linden/indra/newview/llviewermedia.cpp @@ -480,7 +480,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ { LLPluginClassMedia* media_source = new LLPluginClassMedia(owner); media_source->setSize(default_width, default_height); - if (media_source->init(launcher_name, plugin_name, false, user_data_path)) + if (media_source->init(launcher_name, plugin_name, false)) { return media_source; } diff --git a/linden/indra/newview/viewer_manifest.py b/linden/indra/newview/viewer_manifest.py index fcebda9..0c00995 100755 --- a/linden/indra/newview/viewer_manifest.py +++ b/linden/indra/newview/viewer_manifest.py @@ -1092,7 +1092,8 @@ class Linux_x86_64Manifest(LinuxManifest): self.path("libcairo.so.2") self.path("libfontconfig.so.1") self.path("libfreetype.so.6") -# self.path("libgdk_pixbuf-2.0.so.0") # use systems gdk pixbufs instead + self.path("libgdk_pixbuf-2.0.so.0") # was commented to use systems gdk pixbufs instead - + # but seems webkit needs it o_O . Packaging for testing now. self.path("libgdk-x11-2.0.so.0") self.path("libgtk-x11-2.0.so.0") # self.path("libpango-1.0.so.0") # use systems pango instead diff --git a/linden/install.xml b/linden/install.xml index d9f400a..07e7498 100644 --- a/linden/install.xml +++ b/linden/install.xml @@ -1144,23 +1144,30 @@ Portions copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura <key>darwin</key> <map> <key>md5sum</key> - <string>95f44f0023dddc80be4398fc4f213861</string> + <string>38a31c64cbb021320c6f8c0296933f2b</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20100208.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20100402.tar.bz2</uri> </map> <key>linux</key> <map> <key>md5sum</key> - <string>4c75b2f1e8524c7844ee3ea1cd59a3db</string> + <string>78e22d53c84c8642fbaa027fed20cc48</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-20100209b.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-20100407.tar.bz2</uri> + </map> + <key>linux64</key> + <map> + <key>md5sum</key> + <string>d602324a827be7e0a8c90f85d27d6151</string> + <key>url</key> + <uri>http://imprudenceviewer.org/download/libs/llqtwebkit-linux64-20100617.tar.bz2</uri> </map> <key>windows</key> <map> <key>md5sum</key> - <string>1e9798dc424a6f6c2bea50649bbcc7ae</string> + <string>b6ec5fe296b8ad9097b182b5c09a9589</string> <key>url</key> - <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.6-20100210.tar.bz2</uri> + <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.6-20100402.tar.bz2</uri> </map> </map> </map> -- cgit v1.1 From c4891694b7c8fcc469dfa057ebf397ee28fc44b1 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Thu, 17 Jun 2010 11:15:54 +0200 Subject: Robin Cornelius: fixes for building plugins on Linux 64bit --- linden/indra/cmake/00-Common.cmake | 8 ++++++++ linden/indra/cmake/LLCommon.cmake | 13 ++++++++++++- linden/indra/llcommon/CMakeLists.txt | 20 ++++++++++++++++++++ linden/indra/llplugin/CMakeLists.txt | 4 ++++ linden/indra/media_plugins/base/CMakeLists.txt | 4 ++++ linden/indra/media_plugins/example/CMakeLists.txt | 4 ++++ .../indra/media_plugins/gstreamer010/CMakeLists.txt | 4 ++++ linden/indra/media_plugins/webkit/CMakeLists.txt | 4 ++++ linden/indra/newview/CMakeLists.txt | 2 ++ 9 files changed, 62 insertions(+), 1 deletion(-) mode change 100755 => 100644 linden/indra/llplugin/CMakeLists.txt mode change 100755 => 100644 linden/indra/media_plugins/base/CMakeLists.txt mode change 100755 => 100644 linden/indra/media_plugins/example/CMakeLists.txt mode change 100755 => 100644 linden/indra/media_plugins/gstreamer010/CMakeLists.txt (limited to 'linden') diff --git a/linden/indra/cmake/00-Common.cmake b/linden/indra/cmake/00-Common.cmake index d335cb0..6403d49 100644 --- a/linden/indra/cmake/00-Common.cmake +++ b/linden/indra/cmake/00-Common.cmake @@ -20,6 +20,14 @@ set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release;Debug" CACHE STRING "Supported build types." FORCE) +# Determine the number of bits of this processor + +if(CMAKE_SIZEOF_VOID_P MATCHES 4) + set( HAVE_64_BIT 0 ) +else(CMAKE_SIZEOF_VOID_P MATCHES 4) + set( HAVE_64_BIT 1 ) +endif(CMAKE_SIZEOF_VOID_P MATCHES 4) + # Platform-specific compilation flags. if (WINDOWS) diff --git a/linden/indra/cmake/LLCommon.cmake b/linden/indra/cmake/LLCommon.cmake index 410766e..9158e98 100644 --- a/linden/indra/cmake/LLCommon.cmake +++ b/linden/indra/cmake/LLCommon.cmake @@ -12,4 +12,15 @@ set(LLCOMMON_INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ) -set(LLCOMMON_LIBRARIES llcommon) +# Files that need PIC code (pluginAPI) need to set REQUIRE_PIC on 64bit systems +# this will link against a llcommon built with Position Independent Code +# this is a requirment to link a static library (.a) to a DSO on 64 bit systems + +if(REQUIRE_PIC) + set(LLCOMMON_LIBRARIES llcommonPIC) +else(REQUIRE_PIC) + set(LLCOMMON_LIBRARIES llcommon) +endif(REQUIRE_PIC) + +#force clear the flag, files that need this must explicity set it themselves +set(REQUIRE_PIC 0) \ No newline at end of file diff --git a/linden/indra/llcommon/CMakeLists.txt b/linden/indra/llcommon/CMakeLists.txt index 1c12e55..ae961a3 100644 --- a/linden/indra/llcommon/CMakeLists.txt +++ b/linden/indra/llcommon/CMakeLists.txt @@ -198,3 +198,23 @@ target_link_libraries( ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES} ) + +if(HAVE_64_BIT) + add_library (llcommonPIC ${llcommon_SOURCE_FILES}) + add_dependencies(llcommonPIC prepare) + + if(WINDOWS) + add_definitions(/FIXED:NO) + else(WINDOWS) # not windows therefore gcc LINUX and DARWIN + add_definitions(-fPIC) + endif(WINDOWS) + + target_link_libraries( + llcommonPIC + ${APRUTIL_LIBRARIES} + ${APR_LIBRARIES} + ${EXPAT_LIBRARIES} + ${ZLIB_LIBRARIES} + ) +endif(HAVE_64_BIT) + diff --git a/linden/indra/llplugin/CMakeLists.txt b/linden/indra/llplugin/CMakeLists.txt old mode 100755 new mode 100644 index d9b623d..8a2eff8 --- a/linden/indra/llplugin/CMakeLists.txt +++ b/linden/indra/llplugin/CMakeLists.txt @@ -2,6 +2,10 @@ project(llplugin) +if(HAVE_64_BIT) + set(REQUIRE_PIC) +endif(HAVE_64_BIT) + include(00-Common) include(LLCommon) include(LLImage) diff --git a/linden/indra/media_plugins/base/CMakeLists.txt b/linden/indra/media_plugins/base/CMakeLists.txt old mode 100755 new mode 100644 index 8d62043..dd0b0a0 --- a/linden/indra/media_plugins/base/CMakeLists.txt +++ b/linden/indra/media_plugins/base/CMakeLists.txt @@ -2,6 +2,10 @@ project(media_plugin_base) +if(HAVE_64_BIT) + set(REQUIRE_PIC) +endif(HAVE_64_BIT) + include(00-Common) include(LLCommon) include(LLImage) diff --git a/linden/indra/media_plugins/example/CMakeLists.txt b/linden/indra/media_plugins/example/CMakeLists.txt old mode 100755 new mode 100644 index 7822300..bac5fa2 --- a/linden/indra/media_plugins/example/CMakeLists.txt +++ b/linden/indra/media_plugins/example/CMakeLists.txt @@ -2,6 +2,10 @@ project(media_plugin_example) +if(HAVE_64_BIT) + set(REQUIRE_PIC) +endif(HAVE_64_BIT) + include(00-Common) include(LLCommon) include(LLImage) diff --git a/linden/indra/media_plugins/gstreamer010/CMakeLists.txt b/linden/indra/media_plugins/gstreamer010/CMakeLists.txt old mode 100755 new mode 100644 index ee16849..6eab49c --- a/linden/indra/media_plugins/gstreamer010/CMakeLists.txt +++ b/linden/indra/media_plugins/gstreamer010/CMakeLists.txt @@ -2,6 +2,10 @@ project(media_plugin_gstreamer010) +if(HAVE_64_BIT) + set(REQUIRE_PIC) +endif(HAVE_64_BIT) + include(00-Common) include(LLCommon) include(LLImage) diff --git a/linden/indra/media_plugins/webkit/CMakeLists.txt b/linden/indra/media_plugins/webkit/CMakeLists.txt index be02781..a47d5e0 100644 --- a/linden/indra/media_plugins/webkit/CMakeLists.txt +++ b/linden/indra/media_plugins/webkit/CMakeLists.txt @@ -2,6 +2,10 @@ project(media_plugin_webkit) +if(HAVE_64_BIT) + set(REQUIRE_PIC) +endif(HAVE_64_BIT) + include(00-Common) include(LLCommon) include(LLImage) diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index 75ba977..e0c6c61 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt @@ -1472,10 +1472,12 @@ if (DARWIN) --build=${CMAKE_CURRENT_BINARY_DIR} --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) add_custom_command( TARGET package POST_BUILD COMMAND ${PYTHON_EXECUTABLE} -- cgit v1.1 From 087e15e89930d51c3964329befb273ae3b2d330d Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Tue, 7 Sep 2010 13:41:02 +0200 Subject: port of LL renderpipeline/Kirstens S19 pipeline for bridging to Viewer 2 texture system --- linden/indra/llmath/llbbox.cpp | 162 + linden/indra/llmath/llbbox.h | 103 + linden/indra/llmath/llcamera.cpp | 24 + linden/indra/llmath/llcamera.h | 16 +- linden/indra/llmath/llmath.h | 2 +- linden/indra/llmath/llmodularmath.cpp | 36 + linden/indra/llmath/llvolume.cpp | 14 +- linden/indra/llprimitive/CMakeLists.txt | 1 + linden/indra/llrender/CMakeLists.txt | 6 +- linden/indra/llrender/llcubemap.cpp | 17 +- linden/indra/llrender/llfont.cpp | 2 +- linden/indra/llrender/llfontgl.cpp | 6 +- linden/indra/llrender/llgl.cpp | 8 +- linden/indra/llrender/llgl.h | 31 + linden/indra/llrender/llglslshader.cpp | 2 +- linden/indra/llrender/llimagegl.cpp | 451 +-- linden/indra/llrender/llimagegl.h | 117 +- linden/indra/llrender/llrender.cpp | 64 +- linden/indra/llrender/llrendertarget.cpp | 57 +- linden/indra/llrender/llrendertarget.h | 1 + linden/indra/llrender/lltextureatlas.cpp | 411 +++ linden/indra/llrender/lltextureatlas.h | 92 + linden/indra/llrender/llvertexbuffer.cpp | 72 +- linden/indra/newview/CMakeLists.txt | 4 + linden/indra/newview/app_settings/settings.xml | 735 ++++- .../shaders/class1/deferred/alphaF.glsl | 24 +- .../shaders/class1/deferred/alphaV.glsl | 10 +- .../shaders/class1/deferred/avatarAlphaF.glsl | 2 +- .../shaders/class1/deferred/avatarF.glsl | 13 +- .../shaders/class1/deferred/avatarShadowF.glsl | 3 +- .../shaders/class1/deferred/avatarShadowV.glsl | 3 +- .../shaders/class1/deferred/avatarV.glsl | 2 - .../shaders/class1/deferred/blurLightF.glsl | 41 +- .../shaders/class1/deferred/bumpF.glsl | 8 +- .../shaders/class1/deferred/bumpV.glsl | 3 - .../shaders/class1/deferred/diffuseF.glsl | 6 +- .../shaders/class1/deferred/diffuseV.glsl | 5 +- .../shaders/class1/deferred/fullbrightF.glsl | 28 +- .../shaders/class1/deferred/fullbrightV.glsl | 2 +- .../app_settings/shaders/class1/deferred/giF.glsl | 165 + .../app_settings/shaders/class1/deferred/giV.glsl | 22 + .../shaders/class1/deferred/luminanceF.glsl | 15 + .../shaders/class1/deferred/luminanceV.glsl | 20 + .../shaders/class1/deferred/multiPointLightF.glsl | 62 +- .../shaders/class1/deferred/multiSpotLightF.glsl | 184 ++ .../shaders/class1/deferred/pointLightF.glsl | 61 +- .../shaders/class1/deferred/pointLightV.glsl | 6 +- .../shaders/class1/deferred/postDeferredF.glsl | 57 + .../shaders/class1/deferred/postDeferredV.glsl | 17 + .../shaders/class1/deferred/postgiF.glsl | 107 + .../shaders/class1/deferred/postgiV.glsl | 16 + .../shaders/class1/deferred/shadowF.glsl | 3 + .../shaders/class1/deferred/shadowV.glsl | 10 +- .../shaders/class1/deferred/softenLightF.glsl | 4 - .../shaders/class1/deferred/spotLightF.glsl | 199 ++ .../shaders/class1/deferred/sunLightF.glsl | 111 +- .../shaders/class1/deferred/terrainF.glsl | 6 +- .../shaders/class1/deferred/terrainV.glsl | 2 - .../shaders/class1/deferred/treeF.glsl | 4 +- .../shaders/class1/deferred/treeV.glsl | 3 - .../shaders/class1/deferred/waterF.glsl | 2 +- .../shaders/class1/effects/colorFilterF.glsl | 31 + .../shaders/class1/effects/drawQuadV.glsl | 14 + .../shaders/class1/effects/nightVisionF.glsl | 42 + .../shaders/class2/deferred/alphaF.glsl | 112 + .../shaders/class2/deferred/alphaV.glsl | 75 + .../shaders/class2/deferred/avatarAlphaF.glsl | 77 + .../shaders/class2/deferred/avatarAlphaV.glsl | 78 + .../shaders/class2/deferred/blurLightF.glsl | 71 + .../shaders/class2/deferred/blurLightV.glsl | 17 + .../shaders/class2/deferred/multiSpotLightF.glsl | 188 ++ .../shaders/class2/deferred/postDeferredF.glsl | 59 + .../shaders/class2/deferred/postDeferredV.glsl | 17 + .../shaders/class2/deferred/softenLightF.glsl | 294 ++ .../shaders/class2/deferred/softenLightV.glsl | 24 + .../shaders/class2/deferred/spotLightF.glsl | 199 ++ .../shaders/class2/deferred/sunLightF.glsl | 203 ++ .../shaders/class2/deferred/sunLightV.glsl | 25 + .../shaders/class2/deferred/waterF.glsl | 139 + .../shaders/class2/deferred/waterV.glsl | 76 + .../shaders/class3/deferred/avatarF.glsl | 18 + .../shaders/class3/deferred/bumpF.glsl | 27 + .../shaders/class3/deferred/diffuseF.glsl | 18 + .../shaders/class3/deferred/giDownsampleF.glsl | 84 + .../shaders/class3/deferred/giDownsampleV.glsl | 17 + .../app_settings/shaders/class3/deferred/giF.glsl | 219 ++ .../app_settings/shaders/class3/deferred/giV.glsl | 22 + .../shaders/class3/deferred/luminanceF.glsl | 16 + .../shaders/class3/deferred/luminanceV.glsl | 20 + .../shaders/class3/deferred/postDeferredF.glsl | 76 + .../shaders/class3/deferred/postDeferredV.glsl | 17 + .../shaders/class3/deferred/postgiF.glsl | 87 + .../shaders/class3/deferred/postgiV.glsl | 17 + .../shaders/class3/deferred/softenLightF.glsl | 312 ++ .../shaders/class3/deferred/softenLightV.glsl | 24 + .../shaders/class3/deferred/treeF.glsl | 18 + .../shaders/class3/deferred/waterF.glsl | 139 + .../app_settings/shaders/class3/effects/blurF.glsl | 31 + .../app_settings/shaders/class3/effects/blurV.glsl | 35 + .../shaders/class3/effects/colorFilterF.glsl | 31 + .../shaders/class3/effects/drawQuadV.glsl | 14 + .../shaders/class3/effects/extractF.glsl | 22 + .../shaders/class3/effects/nightVisionF.glsl | 42 + .../shaders/class3/effects/simpleF.glsl | 14 + linden/indra/newview/llagent.cpp | 3 +- linden/indra/newview/llagent.h | 1 + linden/indra/newview/llappviewer.cpp | 2 +- linden/indra/newview/llcolorswatch.cpp | 3 +- linden/indra/newview/llcompilequeue.cpp | 1 - linden/indra/newview/llconsole.cpp | 166 +- linden/indra/newview/llconsole.h | 47 +- linden/indra/newview/lldebugview.cpp | 24 +- linden/indra/newview/lldrawable.cpp | 76 +- linden/indra/newview/lldrawable.h | 3 +- linden/indra/newview/lldrawpool.h | 5 + linden/indra/newview/lldrawpoolalpha.cpp | 59 +- linden/indra/newview/lldrawpoolavatar.cpp | 69 +- linden/indra/newview/lldrawpoolbump.cpp | 25 +- linden/indra/newview/lldrawpoolsky.cpp | 68 +- linden/indra/newview/lldrawpoolsky.h | 4 + linden/indra/newview/lldrawpoolterrain.cpp | 6 +- linden/indra/newview/lldrawpooltree.cpp | 15 +- linden/indra/newview/lldrawpoolwater.cpp | 20 +- linden/indra/newview/lldynamictexture.cpp | 21 +- linden/indra/newview/lldynamictexture.h | 4 +- linden/indra/newview/llface.cpp | 445 +-- linden/indra/newview/llface.h | 38 +- linden/indra/newview/llfloaterassetbrowser.cpp | 18 +- linden/indra/newview/llfloaterchat.cpp | 3 +- linden/indra/newview/llfloaterhardwaresettings.cpp | 27 +- linden/indra/newview/llfloaterhardwaresettings.h | 4 + linden/indra/newview/llfloaterlagmeter.cpp | 2 +- linden/indra/newview/llfloaterpostprocess.cpp | 66 +- linden/indra/newview/llfloaterreporter.cpp | 3 +- linden/indra/newview/llhudeffect.cpp | 2 +- linden/indra/newview/llhudtext.cpp | 2 + linden/indra/newview/llmanip.cpp | 2 +- linden/indra/newview/llmaniptranslate.h | 2 +- linden/indra/newview/llmediactrl.cpp | 3 +- linden/indra/newview/lloverlaybar.cpp | 1 - linden/indra/newview/llpanelvolume.cpp | 117 + linden/indra/newview/llpanelvolume.h | 5 + linden/indra/newview/llpostprocess.cpp | 594 ++++ linden/indra/newview/llpostprocess.h | 274 ++ linden/indra/newview/llpreview.cpp | 1 + linden/indra/newview/llselectmgr.cpp | 22 +- linden/indra/newview/llselectmgr.h | 2 +- linden/indra/newview/llsky.cpp | 14 + linden/indra/newview/llspatialpartition.cpp | 390 ++- linden/indra/newview/llspatialpartition.h | 62 +- linden/indra/newview/llstartup.cpp | 2 +- linden/indra/newview/llsurface.cpp | 20 +- linden/indra/newview/llsurfacepatch.cpp | 34 +- linden/indra/newview/llsurfacepatch.h | 1 + linden/indra/newview/lltexlayer.cpp | 26 +- linden/indra/newview/lltexlayer.h | 4 +- linden/indra/newview/lltextureatlasmanager.cpp | 274 ++ linden/indra/newview/lltextureatlasmanager.h | 112 + linden/indra/newview/lltextureview.cpp | 238 +- linden/indra/newview/lltoolpie.h | 1 - linden/indra/newview/llviewercamera.cpp | 4 +- linden/indra/newview/llviewercontrol.cpp | 16 +- linden/indra/newview/llviewerdisplay.cpp | 27 +- linden/indra/newview/llviewerimage.cpp | 367 ++- linden/indra/newview/llviewerimage.h | 31 +- linden/indra/newview/llviewerimagelist.cpp | 50 +- linden/indra/newview/llviewerimagelist.h | 4 +- linden/indra/newview/llviewerjointmesh.cpp | 10 +- linden/indra/newview/llviewermedia.cpp | 4 +- linden/indra/newview/llviewermenu.cpp | 20 +- linden/indra/newview/llviewerobject.cpp | 35 +- linden/indra/newview/llviewerobject.h | 11 +- linden/indra/newview/llviewerobjectlist.cpp | 2 +- linden/indra/newview/llviewerobjectlist.h | 1 - linden/indra/newview/llviewerparceloverlay.cpp | 4 +- linden/indra/newview/llviewershadermgr.cpp | 106 +- linden/indra/newview/llviewershadermgr.h | 25 + linden/indra/newview/llviewerstats.h | 2 +- linden/indra/newview/llviewerwindow.cpp | 110 +- linden/indra/newview/llvlcomposition.cpp | 4 + linden/indra/newview/llvoavatar.cpp | 98 +- linden/indra/newview/llvoavatar.h | 10 +- linden/indra/newview/llvoclouds.cpp | 7 +- linden/indra/newview/llvoclouds.h | 2 +- linden/indra/newview/llvograss.cpp | 2 +- linden/indra/newview/llvograss.h | 2 +- linden/indra/newview/llvoground.cpp | 2 +- linden/indra/newview/llvoground.h | 2 +- linden/indra/newview/llvopartgroup.cpp | 20 +- linden/indra/newview/llvopartgroup.h | 2 +- linden/indra/newview/llvosky.cpp | 8 +- linden/indra/newview/llvosky.h | 4 +- linden/indra/newview/llvosurfacepatch.cpp | 18 +- linden/indra/newview/llvosurfacepatch.h | 3 +- linden/indra/newview/llvotextbubble.cpp | 2 +- linden/indra/newview/llvotextbubble.h | 2 +- linden/indra/newview/llvotree.cpp | 6 +- linden/indra/newview/llvotree.h | 2 +- linden/indra/newview/llvotreenew.h | 2 +- linden/indra/newview/llvovolume.cpp | 422 ++- linden/indra/newview/llvovolume.h | 23 +- linden/indra/newview/llvowater.cpp | 6 +- linden/indra/newview/llvowater.h | 2 +- linden/indra/newview/llwaterparammanager.cpp | 3 +- linden/indra/newview/llwlparammanager.cpp | 3 +- linden/indra/newview/llworld.h | 6 +- linden/indra/newview/pipeline.cpp | 3229 ++++++++++++++++---- linden/indra/newview/pipeline.h | 128 +- .../xui/en-us/floater_hardware_settings.xml | 30 +- .../skins/default/xui/en-us/floater_tools.xml | 44 +- 210 files changed, 12753 insertions(+), 2324 deletions(-) create mode 100644 linden/indra/llmath/llbbox.cpp create mode 100644 linden/indra/llmath/llbbox.h create mode 100644 linden/indra/llmath/llmodularmath.cpp create mode 100644 linden/indra/llrender/lltextureatlas.cpp create mode 100644 linden/indra/llrender/lltextureatlas.h create mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/giF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/giV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class1/effects/drawQuadV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class1/effects/nightVisionF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/waterV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/avatarF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/bumpF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/diffuseF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/giF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/giV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/blurF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/blurV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/colorFilterF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/drawQuadV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/extractF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/nightVisionF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/simpleF.glsl create mode 100644 linden/indra/newview/llpostprocess.cpp create mode 100644 linden/indra/newview/llpostprocess.h create mode 100644 linden/indra/newview/lltextureatlasmanager.cpp create mode 100644 linden/indra/newview/lltextureatlasmanager.h (limited to 'linden') diff --git a/linden/indra/llmath/llbbox.cpp b/linden/indra/llmath/llbbox.cpp new file mode 100644 index 0000000..f0ec010 --- /dev/null +++ b/linden/indra/llmath/llbbox.cpp @@ -0,0 +1,162 @@ +/** + * @file llbbox.cpp + * @brief General purpose bounding box class (Not axis aligned) + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2010, /linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by /linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and /linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL /linden LAB SOURCE CODE IS PROVIDED "AS IS." /linden LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +// self include +#include "llbbox.h" + +// library includes +#include "m4math.h" + +void LLBBox::addPointLocal(const LLVector3& p) +{ + if (mEmpty) + { + mMinLocal = p; + mMaxLocal = p; + mEmpty = FALSE; + } + else + { + mMinLocal.mV[VX] = llmin( p.mV[VX], mMinLocal.mV[VX] ); + mMinLocal.mV[VY] = llmin( p.mV[VY], mMinLocal.mV[VY] ); + mMinLocal.mV[VZ] = llmin( p.mV[VZ], mMinLocal.mV[VZ] ); + mMaxLocal.mV[VX] = llmax( p.mV[VX], mMaxLocal.mV[VX] ); + mMaxLocal.mV[VY] = llmax( p.mV[VY], mMaxLocal.mV[VY] ); + mMaxLocal.mV[VZ] = llmax( p.mV[VZ], mMaxLocal.mV[VZ] ); + } +} + +void LLBBox::addPointAgent( LLVector3 p) +{ + p -= mPosAgent; + p.rotVec( ~mRotation ); + addPointLocal( p ); +} + + +void LLBBox::addBBoxAgent(const LLBBox& b) +{ + if (mEmpty) + { + mPosAgent = b.mPosAgent; + mRotation = b.mRotation; + mMinLocal.clearVec(); + mMaxLocal.clearVec(); + } + LLVector3 vertex[8]; + vertex[0].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] ); + vertex[1].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] ); + vertex[2].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] ); + vertex[3].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] ); + vertex[4].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] ); + vertex[5].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] ); + vertex[6].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] ); + vertex[7].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] ); + + LLMatrix4 m( b.mRotation ); + m.translate( b.mPosAgent ); + m.translate( -mPosAgent ); + m.rotate( ~mRotation ); + + for( S32 i=0; i<8; i++ ) + { + addPointLocal( vertex[i] * m ); + } +} + + +void LLBBox::expand( F32 delta ) +{ + mMinLocal.mV[VX] -= delta; + mMinLocal.mV[VY] -= delta; + mMinLocal.mV[VZ] -= delta; + mMaxLocal.mV[VX] += delta; + mMaxLocal.mV[VY] += delta; + mMaxLocal.mV[VZ] += delta; +} + +LLVector3 LLBBox::localToAgent(const LLVector3& v) const +{ + LLMatrix4 m( mRotation ); + m.translate( mPosAgent ); + return v * m; +} + +LLVector3 LLBBox::agentToLocal(const LLVector3& v) const +{ + LLMatrix4 m; + m.translate( -mPosAgent ); + m.rotate( ~mRotation ); // inverse rotation + return v * m; +} + +LLVector3 LLBBox::localToAgentBasis(const LLVector3& v) const +{ + LLMatrix4 m( mRotation ); + return v * m; +} + +LLVector3 LLBBox::agentToLocalBasis(const LLVector3& v) const +{ + LLMatrix4 m( ~mRotation ); // inverse rotation + return v * m; +} + +BOOL LLBBox::containsPointLocal(const LLVector3& p) const +{ + if ( (p.mV[VX] < mMinLocal.mV[VX]) + ||(p.mV[VX] > mMaxLocal.mV[VX]) + ||(p.mV[VY] < mMinLocal.mV[VY]) + ||(p.mV[VY] > mMaxLocal.mV[VY]) + ||(p.mV[VZ] < mMinLocal.mV[VZ]) + ||(p.mV[VZ] > mMaxLocal.mV[VZ])) + { + return FALSE; + } + return TRUE; +} + +BOOL LLBBox::containsPointAgent(const LLVector3& p) const +{ + LLVector3 point_local = agentToLocal(p); + return containsPointLocal(point_local); +} + + +/* +LLBBox operator*(const LLBBox &a, const LLMatrix4 &b) +{ + return LLBBox( a.mMin * b, a.mMax * b ); +} +*/ diff --git a/linden/indra/llmath/llbbox.h b/linden/indra/llmath/llbbox.h new file mode 100644 index 0000000..3559284 --- /dev/null +++ b/linden/indra/llmath/llbbox.h @@ -0,0 +1,103 @@ +/** + * @file llbbox.h + * @brief General purpose bounding box class + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2010, /linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by /linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and /linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL /linden LAB SOURCE CODE IS PROVIDED "AS IS." /linden LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_BBOX_H +#define LL_BBOX_H + +#include "v3math.h" +#include "llquaternion.h" + +// Note: "local space" for an LLBBox is defined relative to agent space in terms of +// a translation followed by a rotation. There is no scale term since the LLBBox's min and +// max are not necessarily symetrical and define their own extents. + +class LLBBox +{ +public: + LLBBox() {mEmpty = TRUE;} + LLBBox( const LLVector3& pos_agent, + const LLQuaternion& rot, + const LLVector3& min_local, + const LLVector3& max_local ) + : + mMinLocal( min_local ), mMaxLocal( max_local ), mPosAgent(pos_agent), mRotation( rot), mEmpty( TRUE ) + {} + + // Default copy constructor is OK. + + const LLVector3& getPositionAgent() const { return mPosAgent; } + const LLQuaternion& getRotation() const { return mRotation; } + + const LLVector3& getMinLocal() const { return mMinLocal; } + void setMinLocal( const LLVector3& min ) { mMinLocal = min; } + + const LLVector3& getMaxLocal() const { return mMaxLocal; } + void setMaxLocal( const LLVector3& max ) { mMaxLocal = max; } + + LLVector3 getCenterLocal() const { return (mMaxLocal - mMinLocal) * 0.5f + mMinLocal; } + LLVector3 getCenterAgent() const { return localToAgent( getCenterLocal() ); } + + LLVector3 getExtentLocal() const { return mMaxLocal - mMinLocal; } + + BOOL containsPointLocal(const LLVector3& p) const; + BOOL containsPointAgent(const LLVector3& p) const; + + void addPointAgent(LLVector3 p); + void addBBoxAgent(const LLBBox& b); + + void addPointLocal(const LLVector3& p); + void addBBoxLocal(const LLBBox& b) { addPointLocal( b.mMinLocal ); addPointLocal( b.mMaxLocal ); } + + void expand( F32 delta ); + + LLVector3 localToAgent( const LLVector3& v ) const; + LLVector3 agentToLocal( const LLVector3& v ) const; + + // Changes rotation but not position + LLVector3 localToAgentBasis(const LLVector3& v) const; + LLVector3 agentToLocalBasis(const LLVector3& v) const; + + +// friend LLBBox operator*(const LLBBox& a, const LLMatrix4& b); + +private: + LLVector3 mMinLocal; + LLVector3 mMaxLocal; + LLVector3 mPosAgent; // Position relative to Agent's Region + LLQuaternion mRotation; + BOOL mEmpty; // Nothing has been added to this bbox yet +}; + +//LLBBox operator*(const LLBBox &a, const LLMatrix4 &b); + + +#endif // LL_BBOX_H diff --git a/linden/indra/llmath/llcamera.cpp b/linden/indra/llmath/llcamera.cpp index 0f343bc..0609e2f 100644 --- a/linden/indra/llmath/llcamera.cpp +++ b/linden/indra/llmath/llcamera.cpp @@ -246,6 +246,10 @@ S32 LLCamera::AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius) for (U32 i = 0; i < mPlaneCount; i++) { mask = mAgentPlanes[i].mask; + if (mask == 0xff) + { + continue; + } LLPlane p = mAgentPlanes[i].p; LLVector3 n = LLVector3(p); float d = p.mV[3]; @@ -294,6 +298,10 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector3 ¢er, const LLVector3& r } mask = mAgentPlanes[i].mask; + if (mask == 0xff) + { + continue; + } LLPlane p = mAgentPlanes[i].p; LLVector3 n = LLVector3(p); float d = p.mV[3]; @@ -437,6 +445,11 @@ int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius) int res = 2; for (int i = 0; i < 6; i++) { + if (mAgentPlanes[i].mask == 0xff) + { + continue; + } + float d = mAgentPlanes[i].p.dist(sphere_center); if (d > radius) @@ -622,6 +635,17 @@ U8 LLCamera::calcPlaneMask(const LLPlane& plane) return mask; } +void LLCamera::ignoreAgentFrustumPlane(S32 idx) +{ + if (idx < 0 || idx > (S32) mPlaneCount) + { + return; + } + + mAgentPlanes[idx].mask = 0xff; + mAgentPlanes[idx].p.clearVec(); +} + void LLCamera::calcAgentFrustumPlanes(LLVector3* frust) { diff --git a/linden/indra/llmath/llcamera.h b/linden/indra/llmath/llcamera.h index 23ee115..0c81067 100644 --- a/linden/indra/llmath/llcamera.h +++ b/linden/indra/llmath/llcamera.h @@ -93,6 +93,17 @@ public: PLANE_TOP_MASK = (1<<PLANE_TOP), PLANE_ALL_MASK = 0xf }; + + enum + { + AGENT_PLANE_LEFT = 0, + AGENT_PLANE_RIGHT, + AGENT_PLANE_NEAR, + AGENT_PLANE_BOTTOM, + AGENT_PLANE_TOP, + AGENT_PLANE_FAR, + }; + enum { HORIZ_PLANE_LEFT = 0, HORIZ_PLANE_RIGHT = 1, @@ -132,7 +143,8 @@ private: public: LLVector3 mAgentFrustum[8]; //8 corners of 6-plane frustum F32 mFrustumCornerDist; //distance to corner of frustum against far clip plane - + LLPlane getAgentPlane(U32 idx) { return mAgentPlanes[idx].p; } + public: LLCamera(); LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane); @@ -179,6 +191,8 @@ public: // Return number of bytes copied. size_t readFrustumFromBuffer(const char *buffer); void calcAgentFrustumPlanes(LLVector3* frust); + void ignoreAgentFrustumPlane(S32 idx); + // Returns 1 if partly in, 2 if fully in. // NOTE: 'center' is in absolute frame. S32 sphereInFrustumOld(const LLVector3 ¢er, const F32 radius) const; diff --git a/linden/indra/llmath/llmath.h b/linden/indra/llmath/llmath.h index 0de568c..ec1076d 100644 --- a/linden/indra/llmath/llmath.h +++ b/linden/indra/llmath/llmath.h @@ -203,7 +203,7 @@ inline S32 llfloor( F32 f ) } return result; #else - return (S32)floor(f); + return (S32)floorf(f); #endif } diff --git a/linden/indra/llmath/llmodularmath.cpp b/linden/indra/llmath/llmodularmath.cpp new file mode 100644 index 0000000..f0afeb7 --- /dev/null +++ b/linden/indra/llmath/llmodularmath.cpp @@ -0,0 +1,36 @@ +/** + * @file llmodularmath.cpp + * @brief LLModularMath class implementation + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2010, /linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by /linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and /linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL /linden LAB SOURCE CODE IS PROVIDED "AS IS." /linden LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes. +#include "llmodularmath.h" diff --git a/linden/indra/llmath/llvolume.cpp b/linden/indra/llmath/llvolume.cpp index b0b8a94..a1d891a 100644 --- a/linden/indra/llmath/llvolume.cpp +++ b/linden/indra/llmath/llvolume.cpp @@ -2208,16 +2208,10 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, S32 requested_sizeS = 0; S32 requested_sizeT = 0; - // create oblong sculpties with high LOD always - F32 sculpt_detail = mDetail; - if (sculpt_width != sculpt_height && sculpt_detail < 4.0) - { - sculpt_detail = 4.0; - } - sculpt_calc_mesh_resolution(sculpt_width, sculpt_height, sculpt_type, sculpt_detail, requested_sizeS, requested_sizeT); + sculpt_calc_mesh_resolution(sculpt_width, sculpt_height, sculpt_type, mDetail, requested_sizeS, requested_sizeT); - mPathp->generate(mParams.getPathParams(), sculpt_detail, 0, TRUE, requested_sizeS); - mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), sculpt_detail, 0, TRUE, requested_sizeT); + mPathp->generate(mParams.getPathParams(), mDetail, 0, TRUE, requested_sizeS); + mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), mDetail, 0, TRUE, requested_sizeT); S32 sizeS = mPathp->mPath.size(); // we requested a specific size, now see what we really got S32 sizeT = mProfilep->mProfile.size(); // we requested a specific size, now see what we really got @@ -4274,7 +4268,7 @@ LLFaceID LLVolume::generateFaceMask() } break; default: - llerrs << "Unknown profile!" << llendl + llerrs << "Unknown profile!" << llendl; break; } diff --git a/linden/indra/llprimitive/CMakeLists.txt b/linden/indra/llprimitive/CMakeLists.txt index e7ee811..716b247 100755 --- a/linden/indra/llprimitive/CMakeLists.txt +++ b/linden/indra/llprimitive/CMakeLists.txt @@ -52,6 +52,7 @@ set_source_files_properties(${llprimitive_HEADER_FILES} list(APPEND llprimitive_SOURCE_FILES ${llprimitive_HEADER_FILES}) add_library (llprimitive ${llprimitive_SOURCE_FILES}) +add_dependencies(llprimitive prepare) #add unit tests INCLUDE(LLAddBuildTest) diff --git a/linden/indra/llrender/CMakeLists.txt b/linden/indra/llrender/CMakeLists.txt index 0bdb55f..e42f9ab 100644 --- a/linden/indra/llrender/CMakeLists.txt +++ b/linden/indra/llrender/CMakeLists.txt @@ -32,9 +32,9 @@ set(llrender_SOURCE_FILES llgldbg.cpp llglslshader.cpp llimagegl.cpp - llpostprocess.cpp llrendersphere.cpp llshadermgr.cpp + lltextureatlas.cpp llvertexbuffer.cpp ) @@ -53,10 +53,10 @@ set(llrender_HEADER_FILES llglstates.h llgltypes.h llimagegl.h - llpostprocess.h llrender.h llrendersphere.h llshadermgr.h + lltextureatlas.h llvertexbuffer.h ) @@ -81,6 +81,7 @@ if (SERVER AND NOT WINDOWS AND NOT DARWIN) ${llrender_SOURCE_FILES} ${server_SOURCE_FILES} ) + add_dependencies(llrenderheadless prepare) else (SERVER AND NOT WINDOWS AND NOT DARWIN) list(APPEND llrender_SOURCE_FILES llgl.cpp @@ -89,3 +90,4 @@ else (SERVER AND NOT WINDOWS AND NOT DARWIN) ) endif (SERVER AND NOT WINDOWS AND NOT DARWIN) add_library (llrender ${llrender_SOURCE_FILES}) +add_dependencies(llrender prepare) diff --git a/linden/indra/llrender/llcubemap.cpp b/linden/indra/llrender/llcubemap.cpp index a5c677d..e0923e4 100644 --- a/linden/indra/llrender/llcubemap.cpp +++ b/linden/indra/llrender/llcubemap.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2002&license=viewergpl$ * - * Copyright (c) 2002-2009, Linden Research, Inc. + * Copyright (c) 2002-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -63,6 +63,12 @@ LLCubeMap::LLCubeMap() mTextureCoordStage(0), mMatrixStage(0) { + mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB; + mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; + mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB; + mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB; + mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB; + mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB; } LLCubeMap::~LLCubeMap() @@ -75,13 +81,6 @@ void LLCubeMap::initGL() if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) { - mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB; - mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; - mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB; - mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB; - mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB; - mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB; - // Not initialized, do stuff. if (mImages[0].isNull()) { @@ -94,7 +93,7 @@ void LLCubeMap::initGL() mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE)); mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP); mRawImages[i] = new LLImageRaw(64, 64, 4); - mImages[i]->createGLTexture(0, mRawImages[i], texname, TRUE); + mImages[i]->createGLTexture(0, mRawImages[i], texname); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/linden/indra/llrender/llfont.cpp b/linden/indra/llrender/llfont.cpp index dd33128..da5eda0 100644 --- a/linden/indra/llrender/llfont.cpp +++ b/linden/indra/llrender/llfont.cpp @@ -81,7 +81,7 @@ LLFontManager::LLFontManager() if (error) { // Clean up freetype libs. - llerrs << "Freetype initialization failure!" << llendl; + llwarns << "Freetype initialization failure!" << llendl; FT_Done_FreeType(gFTLibrary); } } diff --git a/linden/indra/llrender/llfontgl.cpp b/linden/indra/llrender/llfontgl.cpp index 5d3d6a7..9d1f1d4 100644 --- a/linden/indra/llrender/llfontgl.cpp +++ b/linden/indra/llrender/llfontgl.cpp @@ -121,7 +121,7 @@ LLFontGL::LLFontGL() LLFontGL::LLFontGL(const LLFontGL &source) { - llerrs << "Not implemented!" << llendl; + llwarns << "Not implemented!" << llendl; } LLFontGL::~LLFontGL() @@ -278,7 +278,7 @@ void LLFontGL::destroyGL() LLFontGL &LLFontGL::operator=(const LLFontGL &source) { - llerrs << "Not implemented" << llendl; + llwarns << "Not implemented" << llendl; return *this; } @@ -584,7 +584,7 @@ S32 LLFontGL::render(const LLWString &wstr, const LLFontGlyphInfo* fgi= getGlyphInfo(wch); if (!fgi) { - llerrs << "Missing Glyph Info" << llendl; + llwarns << "Missing Glyph Info" << llendl; break; } // Per-glyph bitmap texture. diff --git a/linden/indra/llrender/llgl.cpp b/linden/indra/llrender/llgl.cpp index 61194c4..be3ed96 100644 --- a/linden/indra/llrender/llgl.cpp +++ b/linden/indra/llrender/llgl.cpp @@ -59,11 +59,13 @@ BOOL gDebugGL = FALSE; BOOL gClothRipple = FALSE; BOOL gNoRender = FALSE; +BOOL gGLActive = FALSE; LLMatrix4 gGLObliqueProjectionInverse; #define LL_GL_NAME_POOLING 0 LLGLNamePool::pool_list_t LLGLNamePool::sInstances; +std::list<LLGLUpdate*> LLGLUpdate::sGLQ; #if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS // ATI prototypes @@ -1001,7 +1003,7 @@ void assert_glerror() if (quit) { - llerrs << "One or more unhandled GL errors." << llendl; + llwarns << "One or more unhandled GL errors." << llendl; } } @@ -1695,11 +1697,11 @@ void LLGLNamePool::release(GLuint name) } else { - llerrs << "Attempted to release a pooled name that is not in use!" << llendl; + llwarns << "Attempted to release a pooled name that is not in use!" << llendl; } } } - llerrs << "Attempted to release a non pooled name!" << llendl; + llwarns << "Attempted to release a non pooled name!" << llendl; #else releaseName(name); #endif diff --git a/linden/indra/llrender/llgl.h b/linden/indra/llrender/llgl.h index 00ff1e2..88552ce 100644 --- a/linden/indra/llrender/llgl.h +++ b/linden/indra/llrender/llgl.h @@ -358,6 +358,35 @@ protected: virtual void releaseName(GLuint name) = 0; }; +/* + Interface for objects that need periodic GL updates applied to them. + Used to synchronize GL updates with GL thread. +*/ +class LLGLUpdate +{ +public: + + static std::list<LLGLUpdate*> sGLQ; + + BOOL mInQ; + LLGLUpdate() + : mInQ(FALSE) + { + } + virtual ~LLGLUpdate() + { + if (mInQ) + { + std::list<LLGLUpdate*>::iterator iter = std::find(sGLQ.begin(), sGLQ.end(), this); + if (iter != sGLQ.end()) + { + sGLQ.erase(iter); + } + } + } + virtual void updateGL() = 0; +}; + extern LLMatrix4 gGLObliqueProjectionInverse; #include "llglstates.h" @@ -376,4 +405,6 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor extern BOOL gClothRipple; extern BOOL gNoRender; +extern BOOL gGLActive; + #endif // LL_LLGL_H diff --git a/linden/indra/llrender/llglslshader.cpp b/linden/indra/llrender/llglslshader.cpp index 08d6548..18974a7 100644 --- a/linden/indra/llrender/llglslshader.cpp +++ b/linden/indra/llrender/llglslshader.cpp @@ -408,7 +408,7 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode) { if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode) { - llerrs << "Texture channel " << index << " texture type corrupted." << llendl; + llwarns << "Texture channel " << index << " texture type corrupted." << llendl; } gGL.getTexUnit(index)->disable(); } diff --git a/linden/indra/llrender/llimagegl.cpp b/linden/indra/llrender/llimagegl.cpp index 7cd4dd7..1bddd49 100644 --- a/linden/indra/llrender/llimagegl.cpp +++ b/linden/indra/llrender/llimagegl.cpp @@ -43,6 +43,8 @@ #include "llmath.h" #include "llgl.h" #include "llrender.h" +#include "lltextureatlas.h" + //---------------------------------------------------------------------------- const F32 MIN_TEXTURE_LIFETIME = 10.f; @@ -56,19 +58,17 @@ S32 LLImageGL::sGlobalTextureMemoryInBytes = 0; S32 LLImageGL::sBoundTextureMemoryInBytes = 0; S32 LLImageGL::sCurBoundTextureMemory = 0; S32 LLImageGL::sCount = 0; +std::list<U32> LLImageGL::sDeadTextureList; BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; F32 LLImageGL::sLastFrameTime = 0.f; -BOOL LLImageGL::sAllowReadBackRaw = FALSE ; +BOOL LLImageGL::sUseTextureAtlas = FALSE ; // render-pipeline KL std::set<LLImageGL*> LLImageGL::sImageList; -//**************************************************************************************************** -//The below for texture auditing use only -//**************************************************************************************************** +#if !LL_RELEASE_FOR_DOWNLOAD //----------------------- //debug use -BOOL gAuditTexture = FALSE ; #define MAX_TEXTURE_LOG_SIZE 22 //2048 * 2048 std::vector<S32> LLImageGL::sTextureLoadedCounter(MAX_TEXTURE_LOG_SIZE + 1) ; std::vector<S32> LLImageGL::sTextureBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ; @@ -76,15 +76,8 @@ std::vector<S32> LLImageGL::sTextureCurBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ; S32 LLImageGL::sCurTexSizeBar = -1 ; S32 LLImageGL::sCurTexPickSize = -1 ; LLPointer<LLImageGL> LLImageGL::sDefaultTexturep = NULL; -S32 LLImageGL::sMaxCatagories = 1 ; - -std::vector<S32> LLImageGL::sTextureMemByCategory; -std::vector<S32> LLImageGL::sTextureMemByCategoryBound ; -std::vector<S32> LLImageGL::sTextureCurMemByCategoryBound ; //------------------------ -//**************************************************************************************************** -//End for texture auditing use only -//**************************************************************************************************** +#endif //************************************************************************************** //below are functions for debug use @@ -110,9 +103,12 @@ void LLImageGL::checkTexSize() const { GLint texname; glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname); + BOOL error = FALSE; if (texname != mTexName) { - llerrs << "Invalid texture bound!" << llendl; + + llwarns << "Invalid texture bound!" << llendl; + } stop_glerror() ; LLGLint x = 0, y = 0 ; @@ -125,7 +121,15 @@ void LLImageGL::checkTexSize() const } if(x != (mWidth >> mCurrentDiscardLevel) || y != (mHeight >> mCurrentDiscardLevel)) { - llerrs << "wrong texture size and discard level!" << llendl ; + error = TRUE; + + llwarns << "wrong texture size and discard level!" << llendl; + + } + + if (error) + { + llwarns << "LLImageGL::checkTexSize failed." << llendl; } } } @@ -133,20 +137,6 @@ void LLImageGL::checkTexSize() const //************************************************************************************** //---------------------------------------------------------------------------- -//static -void LLImageGL::initClass(S32 num_catagories) -{ - sMaxCatagories = num_catagories ; - - sTextureMemByCategory.resize(sMaxCatagories); - sTextureMemByCategoryBound.resize(sMaxCatagories) ; - sTextureCurMemByCategoryBound.resize(sMaxCatagories) ; -} - -//static -void LLImageGL::cleanupClass() -{ -} //static S32 LLImageGL::dataFormatBits(S32 dataformat) @@ -165,7 +155,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) case GL_RGBA: return 32; case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac default: - llerrs << "LLImageGL::Unknown format: " << dataformat << llendl; + llwarns << "LLImageGL::Unknown format: " << dataformat << llendl; return 0; } } @@ -200,7 +190,7 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat) case GL_RGBA: return 4; case GL_BGRA: return 4; // Used for QuickTime media textures on the Mac default: - llerrs << "LLImageGL::Unknown format: " << dataformat << llendl; + llwarns << "LLImageGL::Unknown format: " << dataformat << llendl; return 0; } } @@ -214,43 +204,25 @@ void LLImageGL::updateStats(F32 current_time) sBoundTextureMemoryInBytes = sCurBoundTextureMemory; sCurBoundTextureMemory = 0; - if(gAuditTexture) +#if !LL_RELEASE_FOR_DOWNLOAD + for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++) { - for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++) - { - sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ; - sTextureCurBoundCounter[i] = 0 ; - } - for(U32 i = 0 ; i < sTextureCurMemByCategoryBound.size() ; i++) - { - sTextureMemByCategoryBound[i] = sTextureCurMemByCategoryBound[i] ; - sTextureCurMemByCategoryBound[i] = 0 ; - } + sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ; + sTextureCurBoundCounter[i] = 0 ; } +#endif } //static -S32 LLImageGL::updateBoundTexMemStatic(const S32 delta, const S32 size, S32 category) -{ - if(gAuditTexture) - { - sTextureCurBoundCounter[getTextureCounterIndex(size)]++ ; - sTextureCurMemByCategoryBound[category] += delta ; - } - - LLImageGL::sCurBoundTextureMemory += delta ; - return LLImageGL::sCurBoundTextureMemory; -} - -S32 LLImageGL::updateBoundTexMem()const -{ - if(gAuditTexture) - { - sTextureCurBoundCounter[getTextureCounterIndex(mTextureMemory / mComponents)]++ ; - sTextureCurMemByCategoryBound[mCategory] += mTextureMemory ; - } - - LLImageGL::sCurBoundTextureMemory += mTextureMemory ; +//#if !LL_RELEASE_FOR_DOWNLOAD +//S32 LLImageGL::updateBoundTexMem(const S32 delta, const S32 size) +//{ +// sTextureCurBoundCounter[getTextureCounterIndex(size)]++ ; +//#else +S32 LLImageGL::updateBoundTexMem(const S32 delta) +{ +//#endif + LLImageGL::sCurBoundTextureMemory += delta; return LLImageGL::sCurBoundTextureMemory; } @@ -264,7 +236,6 @@ void LLImageGL::destroyGL(BOOL save_state) gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE); } - sAllowReadBackRaw = true ; for (std::set<LLImageGL*>::iterator iter = sImageList.begin(); iter != sImageList.end(); iter++) { @@ -284,7 +255,7 @@ void LLImageGL::destroyGL(BOOL save_state) stop_glerror(); } } - sAllowReadBackRaw = false ; +// sAllowReadBackRaw = false ; } //static @@ -296,13 +267,13 @@ void LLImageGL::restoreGL() LLImageGL* glimage = *iter; if(glimage->getTexName()) { - llerrs << "tex name is not 0." << llendl ; + llwarns << "tex name is not 0." << llendl ; } if (glimage->mSaveData.notNull()) { if (glimage->getComponents() && glimage->mSaveData->getComponents()) { - glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData, 0, TRUE, glimage->getCategory()); + glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData); stop_glerror(); } glimage->mSaveData = NULL; // deletes data @@ -384,7 +355,7 @@ void LLImageGL::init(BOOL usemipmaps) mTextureState = NO_DELETE ; mTextureMemory = 0; mLastBindTime = 0.f; - + mTarget = GL_TEXTURE_2D; mBindTarget = LLTexUnit::TT_TEXTURE; mUseMipMaps = usemipmaps; @@ -411,9 +382,12 @@ void LLImageGL::init(BOOL usemipmaps) mHasExplicitFormat = FALSE; mGLTextureCreated = FALSE ; - mIsMask = FALSE; - mCategory = -1 ; +// mCategory = -1 ; + mCanAddToAtlas = TRUE ; + mDiscardLevelInAtlas = -1 ; + mTexelsInAtlas = 0 ; + mTexelsInGLTexture = 0 ; } void LLImageGL::cleanup() @@ -455,7 +429,7 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents) // Check if dimensions are a power of two! if (!checkSize(width,height)) { - llerrs << llformat("Texture has non power of two dimention: %dx%d",width,height) << llendl; + llwarns << llformat("Texture has non power of two dimention: %dx%d",width,height) << llendl; } if (mTexName) @@ -513,10 +487,6 @@ void LLImageGL::dump() } //---------------------------------------------------------------------------- -void LLImageGL::forceUpdateBindStats(void) const -{ - mLastBindTime = sLastFrameTime; -} void LLImageGL::updateBindStats(void) const { @@ -530,8 +500,12 @@ void LLImageGL::updateBindStats(void) const { // we haven't accounted for this texture yet this frame sUniqueCount++; - - updateBoundTexMem(); + +//#if !LL_RELEASE_FOR_DOWNLOAD +// updateBoundTexMem(mTextureMemory, getWidth(mCurrentDiscardLevel) * getHeight(mCurrentDiscardLevel)) ; +//#else + updateBoundTexMem(mTextureMemory); +//#endif mLastBindTime = sLastFrameTime; } } @@ -544,7 +518,7 @@ bool LLImageGL::bindError(const S32 stage) const } //virtual -bool LLImageGL::bindDefaultImage(const S32 stage) +bool LLImageGL::bindDefaultImage(const S32 stage) const { return false; } @@ -583,6 +557,7 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { // LLFastTimer t1(LLFastTimer::FTM_TEMP1); + llpushcallstacks ; bool is_compressed = false; if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) { @@ -590,7 +565,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } // LLFastTimer t2(LLFastTimer::FTM_TEMP2); - gGL.getTexUnit(0)->bind(this); + llverify(gGL.getTexUnit(0)->bind(this, false, true)); if (mUseMipMaps) { @@ -753,7 +728,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } else { - llerrs << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << llendl; + llwarns << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << llendl; } mHasMipMaps = true; } @@ -795,10 +770,63 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } stop_glerror(); mGLTextureCreated = true; + llpushcallstacks ; +} + +BOOL LLImageGL::canAddToAtlas() +{ + return sUseTextureAtlas && mCanAddToAtlas ; +} + +BOOL LLImageGL::addToAtlas(const LLImageRaw* raw_image, LLTextureAtlas* atlasp, S16 slot_col, S16 slot_row) +{ + if(!atlasp) + { + return FALSE ; + } + + preAddToAtlas(raw_image->getWidth()) ; + LLGLuint tex_name = atlasp->insertSubTexture(raw_image, slot_col, slot_row); + postAddToAtlas() ; + + if(tex_name > 0) //successfully added to atlas + { + //gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); + //gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); + gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); + return TRUE ; + } + + return FALSE ; +} + +void LLImageGL::preAddToAtlas(S32 data_width) +{ + glPixelStorei(GL_UNPACK_ROW_LENGTH, data_width); + stop_glerror(); + + if(mFormatSwapBytes) + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); + stop_glerror(); + } } -BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) +void LLImageGL::postAddToAtlas() { + if(mFormatSwapBytes) + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); + stop_glerror(); + } + + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + stop_glerror(); +} + +BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) +{ + llpushcallstacks ; if (!width || !height) { return TRUE; @@ -814,8 +842,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 return FALSE; } - // HACK: allow the caller to explicitly force the fast path (i.e. using glTexSubImage2D here instead of calling setImage) even when updating the full texture. - if (!force_fast_update && x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height) + if (x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height) { setImage(datap, FALSE); } @@ -824,7 +851,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 if (mUseMipMaps) { dump(); - llerrs << "setSubImage called with mipmapped image (not supported)" << llendl; + llwarns << "setSubImage called with mipmapped image (not supported)" << llendl; } llassert_always(mCurrentDiscardLevel == 0); llassert_always(x_pos >= 0 && y_pos >= 0); @@ -833,7 +860,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 (y_pos + height) > getHeight()) { dump(); - llerrs << "Subimage not wholly in target image!" + llwarns << "Subimage not wholly in target image!" << " x_pos " << x_pos << " y_pos " << y_pos << " width " << width @@ -847,7 +874,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 (y_pos + height) > data_height) { dump(); - llerrs << "Subimage not wholly in source image!" + llwarns << "Subimage not wholly in source image!" << " x_pos " << x_pos << " y_pos " << y_pos << " width " << width @@ -870,7 +897,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 datap += (y_pos * data_width + x_pos) * getComponents(); // Update the GL texture BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName); - if (!res) llerrs << "LLImageGL::setSubImage(): bindTexture failed" << llendl; + if (!res) llwarns << "LLImageGL::setSubImage(): bindTexture failed" << llendl; stop_glerror(); glTexSubImage2D(mTarget, 0, x_pos, y_pos, @@ -888,12 +915,13 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 stop_glerror(); mGLTextureCreated = true; } + llpushcallstacks ; return TRUE; } -BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) +BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height) { - return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update); + return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height); } // Copy sub image from frame buffer @@ -901,7 +929,6 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ { if (gGL.getTexUnit(0)->bind(this, false, true)) { - //checkTexSize() ; glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height); mGLTextureCreated = true; stop_glerror(); @@ -922,13 +949,17 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures) // static void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) { - glDeleteTextures(numTextures, (GLuint*)textures); + for (S32 i = 0; i < numTextures; i++) + { + sDeadTextureList.push_back(textures[i]); + } } // static void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels) { glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels); + stop_glerror(); } //create an empty GL texture: just create a texture name @@ -955,21 +986,26 @@ BOOL LLImageGL::createGLTexture() stop_glerror(); if (!mTexName) { - llerrs << "LLImageGL::createGLTexture failed to make an empty texture" << llendl; + llwarns << "LLImageGL::createGLTexture failed to make an empty texture" << llendl; } return TRUE ; } -BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category) +BOOL LLImageGL::createGLTextureInAtlas(S32 discard_level, const LLImageRaw* imageraw, LLTextureAtlas* atlasp, S16 slot_col, S16 slot_row) { + if(!sUseTextureAtlas) + { + return FALSE ; + } + if (gGLManager.mIsDisabled) { llwarns << "Trying to create a texture while GL is disabled!" << llendl; return FALSE; } - mGLTextureCreated = false ; + // mGLTextureCreated = false ; // KL not in SD llassert(gGLManager.mInited); stop_glerror(); @@ -981,10 +1017,8 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); // Actual image width/height = raw image width/height * 2^discard_level - S32 raw_w = imageraw->getWidth() ; - S32 raw_h = imageraw->getHeight() ; - S32 w = raw_w << discard_level; - S32 h = raw_h << discard_level; + S32 w = imageraw->getWidth() << discard_level; + S32 h = imageraw->getHeight() << discard_level; // setSize may call destroyGLTexture if the size does not match setSize(w, h, imageraw->getComponents()); @@ -1016,27 +1050,87 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S mFormatType = GL_UNSIGNED_BYTE; break; default: - LL_DEBUGS("Openjpeg") << "Bad number of components for texture: " << (U32)getComponents() << LL_ENDL; - to_create = false; - break; + llwarns << "Bad number of components for texture: " << (U32)getComponents() << llendl; } } - if(!to_create) //not create a gl texture + if(addToAtlas(imageraw, atlasp, slot_col, slot_row)) { - destroyGLTexture(); + // destroyGLTexture(); mCurrentDiscardLevel = discard_level; + mDiscardLevelInAtlas = discard_level; + mTexelsInAtlas = imageraw->getWidth() * imageraw->getHeight() ; mLastBindTime = sLastFrameTime; + mGLTextureCreated = false ; return TRUE ; } + return FALSE ; +} + +BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) +{ + if (gGLManager.mIsDisabled) + { + llwarns << "Trying to create a texture while GL is disabled!" << llendl; + return FALSE; + } + + mGLTextureCreated = false ; + llassert(gGLManager.mInited); + stop_glerror(); + + if (discard_level < 0) + { + llassert(mCurrentDiscardLevel >= 0); + discard_level = mCurrentDiscardLevel; + } + discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); + + // Actual image width/height = raw image width/height * 2^discard_level + S32 w = imageraw->getWidth() << discard_level; + S32 h = imageraw->getHeight() << discard_level; + + // setSize may call destroyGLTexture if the size does not match + setSize(w, h, imageraw->getComponents()); + + if( !mHasExplicitFormat ) + { + switch (mComponents) + { + case 1: + // Use luminance alpha (for fonts) + mFormatInternal = GL_LUMINANCE8; + mFormatPrimary = GL_LUMINANCE; + mFormatType = GL_UNSIGNED_BYTE; + break; + case 2: + // Use luminance alpha (for fonts) + mFormatInternal = GL_LUMINANCE8_ALPHA8; + mFormatPrimary = GL_LUMINANCE_ALPHA; + mFormatType = GL_UNSIGNED_BYTE; + break; + case 3: + mFormatInternal = GL_RGB8; + mFormatPrimary = GL_RGB; + mFormatType = GL_UNSIGNED_BYTE; + break; + case 4: + mFormatInternal = GL_RGBA8; + mFormatPrimary = GL_RGBA; + mFormatType = GL_UNSIGNED_BYTE; + break; + default: + llwarns << "Bad number of components for texture: " << (U32)getComponents() << llendl; + } + } - mCategory = category ; const U8* rawdata = imageraw->getData(); return createGLTexture(discard_level, rawdata, FALSE, usename); } BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) { + llpushcallstacks ; llassert(data_in); if (discard_level < 0) @@ -1073,7 +1167,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } if (!mTexName) { - llerrs << "LLImageGL::createGLTexture failed to make texture" << llendl; + llwarns << "LLImageGL::createGLTexture failed to make texture" << llendl; } if (mUseMipMaps) @@ -1104,30 +1198,30 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ if (old_name != 0) { sGlobalTextureMemoryInBytes -= mTextureMemory; - - if(gAuditTexture) - { - decTextureCounter() ; - } +#if !LL_RELEASE_FOR_DOWNLOAD + decTextureCounter(mTextureMemory / mComponents) ; +#endif LLImageGL::deleteTextures(1, &old_name); - stop_glerror(); } mTextureMemory = getMipBytes(discard_level); sGlobalTextureMemoryInBytes += mTextureMemory; + mTexelsInGLTexture = getWidth() * getHeight() ; + +#if !LL_RELEASE_FOR_DOWNLOAD + incTextureCounter(mTextureMemory / mComponents) ; +#endif setActive() ; - if(gAuditTexture) - { - incTextureCounter() ; - } // mark this as bound at this point, so we don't throw it out immediately mLastBindTime = sLastFrameTime; + + llpushcallstacks ; return TRUE; } -#if 0 + BOOL LLImageGL::setDiscardLevel(S32 discard_level) { llassert(discard_level >= 0); @@ -1149,7 +1243,7 @@ BOOL LLImageGL::setDiscardLevel(S32 discard_level) { // larger image dump(); - llerrs << "LLImageGL::setDiscardLevel() called with larger discard level; use createGLTexture()" << llendl; + llwarns << "LLImageGL::setDiscardLevel() called with larger discard level; use createGLTexture()" << llendl; return FALSE; } else if (mUseMipMaps) @@ -1174,19 +1268,30 @@ BOOL LLImageGL::setDiscardLevel(S32 discard_level) { #if !LL_LINUX && !LL_SOLARIS // *FIX: This should not be skipped for the linux client. - llerrs << "LLImageGL::setDiscardLevel() called on image without mipmaps" << llendl; + llwarns << "LLImageGL::setDiscardLevel() called on image without mipmaps" << llendl; #endif return FALSE; } } -#endif + +BOOL LLImageGL::isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) +{ + assert_glerror(); + S32 gl_discard = discard_level - mCurrentDiscardLevel; + LLGLint glwidth = 0; + glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth); + LLGLint glheight = 0; + glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_HEIGHT, (GLint*)&glheight); + LLGLint glcomponents = 0 ; + glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&glcomponents); + assert_glerror(); + + return glwidth >= image_width && glheight >= image_height && (GL_RGB8 == glcomponents || GL_RGBA8 == glcomponents) ; +} BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) { - // VWR-13505 : Merov : Allow gl texture read back so save texture works again (temporary) - //llassert_always(sAllowReadBackRaw) ; - //llerrs << "should not call this function!" << llendl ; - + llpushcallstacks ; if (discard_level < 0) { discard_level = mCurrentDiscardLevel; @@ -1291,41 +1396,48 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre return FALSE ; } //----------------------------------------------------------------------------------------------- - + llpushcallstacks ; return TRUE ; } -void LLImageGL::destroyGLTexture() +void LLImageGL::deleteDeadTextures() { - if (mTexName != 0) + while (!sDeadTextureList.empty()) { - stop_glerror(); - + GLuint tex = sDeadTextureList.front(); + sDeadTextureList.pop_front(); for (int i = 0; i < gGLManager.mNumTextureUnits; i++) { - if (sCurrentBoundTextures[i] == mTexName) + if (sCurrentBoundTextures[i] == tex) { gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE); stop_glerror(); } } - + + glDeleteTextures(1, &tex); + stop_glerror(); + } +} + +void LLImageGL::destroyGLTexture() +{ + if (mTexName != 0) + { if(mTextureMemory) { - if(gAuditTexture) - { - decTextureCounter() ; - } +#if !LL_RELEASE_FOR_DOWNLOAD + decTextureCounter(mTextureMemory / mComponents) ; +#endif sGlobalTextureMemoryInBytes -= mTextureMemory; mTextureMemory = 0; } - + LLImageGL::deleteTextures(1, &mTexName); - mTextureState = DELETED ; + mTextureState = DELETED ; mTexName = 0; mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. mGLTextureCreated = FALSE ; - stop_glerror(); } } @@ -1354,12 +1466,12 @@ void LLImageGL::setFilteringOption(LLTexUnit::eTextureFilterOptions option) mFilterOption = option; } - if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName) + if (mTexName != 0 && gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName) { gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureFilteringOption(option); mTexOptionsDirty = false; + stop_glerror(); } - stop_glerror(); } BOOL LLImageGL::getIsResident(BOOL test_now) @@ -1435,11 +1547,6 @@ S32 LLImageGL::getMipBytes(S32 discard_level) const return res; } -BOOL LLImageGL::isJustBound() const -{ - return (BOOL)(sLastFrameTime - mLastBindTime < 0.5f); -} - BOOL LLImageGL::getBoundRecently() const { return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME); @@ -1601,7 +1708,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) U32 pick_offset = pick_bit%8; if (pick_idx >= mPickMaskSize) { - llerrs << "WTF?" << llendl; + llwarns << "WTF?" << llendl; } mPickMask[pick_idx] |= 1 << pick_offset; @@ -1627,7 +1734,7 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) if (u < 0.f || u > 1.f || v < 0.f || v > 1.f) { - llerrs << "WTF?" << llendl; + llwarns << "WTF?" << llendl; // WTF really useful info NOT } S32 x = (S32)(u * width); @@ -1650,24 +1757,8 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) return res; } -void LLImageGL::setCategory(S32 category) -{ - if(!gAuditTexture) - { - return ; - } - if(mCategory != category) - { - if(mCategory > -1) - { - sTextureMemByCategory[mCategory] -= mTextureMemory ; - } - sTextureMemByCategory[category] += mTextureMemory ; - - mCategory = category; - } -} - +//---------------------------------------------------------------------------- +#if !LL_RELEASE_FOR_DOWNLOAD //for debug use //val is a "power of two" number S32 LLImageGL::getTextureCounterIndex(U32 val) @@ -1691,38 +1782,18 @@ S32 LLImageGL::getTextureCounterIndex(U32 val) return ret ; } } -void LLImageGL::incTextureCounterStatic(U32 val, S32 ncomponents, S32 category) +void LLImageGL::incTextureCounter(U32 val) { sTextureLoadedCounter[getTextureCounterIndex(val)]++ ; - sTextureMemByCategory[category] += (S32)val * ncomponents ; } -void LLImageGL::decTextureCounterStatic(U32 val, S32 ncomponents, S32 category) +void LLImageGL::decTextureCounter(U32 val) { sTextureLoadedCounter[getTextureCounterIndex(val)]-- ; - sTextureMemByCategory[category] += (S32)val * ncomponents ; -} -void LLImageGL::incTextureCounter() -{ - sTextureLoadedCounter[getTextureCounterIndex(mTextureMemory / mComponents)]++ ; - sTextureMemByCategory[mCategory] += mTextureMemory ; -} -void LLImageGL::decTextureCounter() -{ - sTextureLoadedCounter[getTextureCounterIndex(mTextureMemory / mComponents)]-- ; - sTextureMemByCategory[mCategory] -= mTextureMemory ; } -void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size) +void LLImageGL::setCurTexSizebar(S32 index) { sCurTexSizeBar = index ; - - if(set_pick_size) - { - sCurTexPickSize = (1 << index) ; - } - else - { - sCurTexPickSize = -1 ; - } + sCurTexPickSize = (1 << index) ; } void LLImageGL::resetCurTexSizebar() { @@ -1730,9 +1801,7 @@ void LLImageGL::resetCurTexSizebar() sCurTexPickSize = -1 ; } //---------------------------------------------------------------------------- - -//---------------------------------------------------------------------------- - +#endif // Manual Mip Generation /* diff --git a/linden/indra/llrender/llimagegl.h b/linden/indra/llrender/llimagegl.h index c7114c3..56f79ff 100644 --- a/linden/indra/llrender/llimagegl.h +++ b/linden/indra/llrender/llimagegl.h @@ -45,18 +45,23 @@ #define BYTES_TO_MEGA_BYTES(x) ((x) >> 20) #define MEGA_BYTES_TO_BYTES(x) ((x) << 20) +class LLTextureAtlas ; //============================================================================ + class LLImageGL : public LLRefCount { friend class LLTexUnit; public: + static std::list<U32> sDeadTextureList; + + static void deleteDeadTextures(); + // Size calculation static S32 dataFormatBits(S32 dataformat); static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height); static S32 dataFormatComponents(S32 dataformat); void updateBindStats(void) const; - void forceUpdateBindStats(void) const; // needs to be called every frame static void updateStats(F32 current_time); @@ -65,10 +70,12 @@ public: static void destroyGL(BOOL save_state = TRUE); static void restoreGL(); - // Sometimes called externally for textures not using LLImageGL (should go away...) - static S32 updateBoundTexMemStatic(const S32 delta, const S32 size, S32 category) ; - S32 updateBoundTexMem()const; - + // Sometimes called externally for textures not using LLImageGL (should go away...) +//#if !LL_RELEASE_FOR_DOWNLOAD +// static S32 updateBoundTexMem(const S32 delta, const S32 size) ; +//#else + static S32 updateBoundTexMem(const S32 delta); +//#endif static bool checkSize(S32 width, S32 height); // Not currently necessary for LLImageGL, but required in some derived classes, @@ -90,7 +97,7 @@ protected: public: virtual void dump(); // debugging info to llinfos virtual bool bindError(const S32 stage = 0) const; - virtual bool bindDefaultImage(const S32 stage = 0) ; + virtual bool bindDefaultImage(const S32 stage = 0) const; virtual void forceImmediateUpdate() ; void setSize(S32 width, S32 height, S32 ncomponents); @@ -102,15 +109,14 @@ public: static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels); BOOL createGLTexture() ; - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, - S32 category = sMaxCatagories - 1); + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0); BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); void setImage(const LLImageRaw* imageraw); void setImage(const U8* data_in, BOOL data_hasmips = FALSE); - BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); - BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); + BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height); + BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height); BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); - + BOOL setDiscardLevel(S32 discard_level); // Read back a raw image for this discard level, if it exists BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok); void destroyGLTexture(); @@ -130,7 +136,7 @@ public: S32 getBytes(S32 discard_level = -1) const; S32 getMipBytes(S32 discard_level = -1) const; BOOL getBoundRecently() const; - BOOL isJustBound() const; + //BOOL isJustBound() const; LLGLenum getPrimaryFormat() const { return mFormatPrimary; } BOOL getHasGLTexture() const { return mTexName != 0; } @@ -151,6 +157,8 @@ public: BOOL getUseDiscard() const { return mUseMipMaps && !mDontDiscard; } BOOL getDontDiscard() const { return mDontDiscard; } + BOOL isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) ; + void updatePickMask(S32 width, S32 height, const U8* data_in); BOOL getMask(const LLVector2 &tc); @@ -176,8 +184,20 @@ public: void setActive() ; void forceActive() ; void setNoDelete() ; + + BOOL canAddToAtlas() ; + BOOL createGLTextureInAtlas(S32 discard_level, const LLImageRaw* imageraw, LLTextureAtlas* atlasp, S16 slot_col, S16 slot_row); + BOOL addToAtlas(const LLImageRaw* raw_image, LLTextureAtlas* atlasp, S16 slot_col, S16 slot_row) ; + + LLGLenum getTexTarget()const { return mTarget ;} + S8 getDiscardLevelInAtlas()const {return mDiscardLevelInAtlas;} + U32 getTexelsInAtlas()const { return mTexelsInAtlas ;} + U32 getTexelsInGLTexture()const {return mTexelsInGLTexture;} - void setTextureSize(S32 size) {mTextureMemory = size;} +private: + void preAddToAtlas(S32 data_width) ; + void postAddToAtlas() ; + protected: void init(BOOL usemipmaps); virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors @@ -186,7 +206,7 @@ public: // Various GL/Rendering options S32 mTextureMemory; mutable F32 mLastBindTime; // last time this was bound, by discard level - + private: LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel @@ -202,8 +222,15 @@ private: U16 mWidth; U16 mHeight; S8 mCurrentDiscardLevel; - + + S8 mDiscardLevelInAtlas; + U32 mTexelsInAtlas ; + U32 mTexelsInGLTexture; + protected: + + BOOL mCanAddToAtlas ; + LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps) bool mHasMipMaps; @@ -241,42 +268,18 @@ public: static S32 sCount; static F32 sLastFrameTime; - + static LLGLuint sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS]; // Currently bound texture ID // Global memory statistics static S32 sGlobalTextureMemoryInBytes; // Tracks main memory texmem - static S32 sBoundTextureMemoryInBytes; // Tracks bound texmem for last completed frame + static S32 sBoundTextureMemoryInBytes; // Tracks bound texmem for last completed frame static S32 sCurBoundTextureMemory; // Tracks bound texmem for current frame static U32 sBindCount; // Tracks number of texture binds for current frame static U32 sUniqueCount; // Tracks number of unique texture binds for current frame static BOOL sGlobalUseAnisotropic; -#if DEBUG_MISS - BOOL mMissed; // Missed on last bind? - BOOL getMissed() const { return mMissed; }; -#else - BOOL getMissed() const { return FALSE; }; -#endif - -public: - static void initClass(S32 num_catagories) ; - static void cleanupClass() ; -private: - static S32 sMaxCatagories ; - - //the flag to allow to call readBackRaw(...). - //can be removed if we do not use that function at all. - static BOOL sAllowReadBackRaw ; -// -//**************************************************************************************************** -//The below for texture auditing use only -//**************************************************************************************************** -private: - S32 mCategory ; -public: - void setCategory(S32 category) ; - S32 getCategory()const {return mCategory ;} - + static BOOL sUseTextureAtlas ; +#if !LL_RELEASE_FOR_DOWNLOAD //for debug use: show texture size distribution //---------------------------------------- static LLPointer<LLImageGL> sDefaultTexturep; //default texture to replace normal textures @@ -287,27 +290,19 @@ public: static S32 sCurTexPickSize ; static S32 getTextureCounterIndex(U32 val) ; - static void incTextureCounterStatic(U32 val, S32 ncomponents, S32 category) ; - static void decTextureCounterStatic(U32 val, S32 ncomponents, S32 category) ; - static void setCurTexSizebar(S32 index, BOOL set_pick_size = TRUE) ; + static void incTextureCounter(U32 val) ; + static void decTextureCounter(U32 val) ; + static void setCurTexSizebar(S32 index) ; static void resetCurTexSizebar(); - - void incTextureCounter() ; - void decTextureCounter() ; //---------------------------------------- +#endif - //for debug use: show texture category distribution - //---------------------------------------- - - static std::vector<S32> sTextureMemByCategory; - static std::vector<S32> sTextureMemByCategoryBound ; - static std::vector<S32> sTextureCurMemByCategoryBound ; - //---------------------------------------- -//**************************************************************************************************** -//End of definitions for texture auditing use only -//**************************************************************************************************** - +#if DEBUG_MISS + BOOL mMissed; // Missed on last bind? + BOOL getMissed() const { return mMissed; }; +#else + BOOL getMissed() const { return FALSE; }; +#endif }; -extern BOOL gAuditTexture; #endif // LL_LLIMAGEGL_H diff --git a/linden/indra/llrender/llrender.cpp b/linden/indra/llrender/llrender.cpp index b1fe153..07ba9f1 100644 --- a/linden/indra/llrender/llrender.cpp +++ b/linden/indra/llrender/llrender.cpp @@ -47,7 +47,7 @@ F64 gGLLastModelView[16]; F64 gGLProjection[16]; S32 gGLViewport[4]; -static const U32 LL_NUM_TEXTURE_LAYERS = 8; +static const U32 LL_NUM_TEXTURE_LAYERS = 16; // KL was 8 ( keep a track on this ) 16 in render-pipeline static GLenum sGLTextureType[] = { @@ -192,24 +192,25 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) if (!texture->getTexName()) //if texture does not exist { - if (texture->isDeleted()) - { - // This will re-generate the texture immediately. - texture->forceImmediateUpdate() ; - } + //if deleted, will re-generate it immediately + texture->forceImmediateUpdate() ; - texture->forceUpdateBindStats() ; return texture->bindDefaultImage(mIndex); } - if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0) +#if !LL_RELEASE_FOR_DOWNLOAD + if(for_rendering) { - if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize) + int w = texture->getWidth(texture->getDiscardLevel()) ; + int h = texture->getHeight(texture->getDiscardLevel()) ; + + if(w * h == LLImageGL::sCurTexPickSize) { texture->updateBindStats(); return bind(LLImageGL::sDefaultTexturep.get()); } } +#endif if ((mCurrTexture != texture->getTexName()) || forceBind) { @@ -227,7 +228,6 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) setTextureFilteringOption(texture->mFilterOption); } } - return true; } @@ -280,6 +280,11 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) if (bindDepth) { + if (renderTarget->hasStencil()) + { + llwarns << "Cannot bind a render buffer for sampling. Allocate render target without a stencil buffer if sampling of depth buffer is required." << llendl; + } + bindManual(renderTarget->getUsage(), renderTarget->getDepth()); } else @@ -293,15 +298,18 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips) { - if (mIndex < 0 || mCurrTexture == texture) return false; - - gGL.flush(); + if (mIndex < 0) return false; - activate(); - enable(type); - mCurrTexture = texture; - glBindTexture(sGLTextureType[type], texture); - mHasMipMaps = hasMips; + if(mCurrTexture != texture) + { + gGL.flush(); + + activate(); + enable(type); + mCurrTexture = texture; + glBindTexture(sGLTextureType[type], texture); + mHasMipMaps = hasMips; + } return true; } @@ -414,7 +422,7 @@ void LLTexUnit::setTextureBlendType(eTextureBlendType type) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); break; default: - llerrs << "Unknown Texture Blend Type: " << type << llendl; + llwarns << "Unknown Texture Blend Type: " << type << llendl; break; } setColorScale(scale_amount); @@ -809,7 +817,7 @@ void LLRender::setSceneBlendType(eBlendType type) glBlendFunc(GL_ONE, GL_ZERO); break; default: - llerrs << "Unknown Scene Blend Type: " << type << llendl; + llwarns << "Unknown Scene Blend Type: " << type << llendl; break; } } @@ -883,7 +891,7 @@ void LLRender::begin(const GLuint& mode) } else if (mCount != 0) { - llerrs << "gGL.begin() called redundantly." << llendl; + llwarns << "gGL.begin() called redundantly." << llendl; } mMode = mode; @@ -914,22 +922,22 @@ void LLRender::flush() #if 0 if (!glIsEnabled(GL_VERTEX_ARRAY)) { - llerrs << "foo 1" << llendl; + llwarns << "foo 1" << llendl; } if (!glIsEnabled(GL_COLOR_ARRAY)) { - llerrs << "foo 2" << llendl; + llwarns << "foo 2" << llendl; } if (!glIsEnabled(GL_TEXTURE_COORD_ARRAY)) { - llerrs << "foo 3" << llendl; + llwarns << "foo 3" << llendl; } if (glIsEnabled(GL_NORMAL_ARRAY)) { - llerrs << "foo 7" << llendl; + llwarns << "foo 7" << llendl; } GLvoid* pointer; @@ -937,19 +945,19 @@ void LLRender::flush() glGetPointerv(GL_VERTEX_ARRAY_POINTER, &pointer); if (pointer != &(mBuffer[0].v)) { - llerrs << "foo 4" << llendl; + llwarns << "foo 4" << llendl; } glGetPointerv(GL_COLOR_ARRAY_POINTER, &pointer); if (pointer != &(mBuffer[0].c)) { - llerrs << "foo 5" << llendl; + llwarns << "foo 5" << llendl; } glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &pointer); if (pointer != &(mBuffer[0].uv)) { - llerrs << "foo 6" << llendl; + llwarns << "foo 6" << llendl; } #endif diff --git a/linden/indra/llrender/llrendertarget.cpp b/linden/indra/llrender/llrendertarget.cpp index 4cf8451..151b761 100644 --- a/linden/indra/llrender/llrendertarget.cpp +++ b/linden/indra/llrender/llrendertarget.cpp @@ -47,10 +47,10 @@ void check_framebuffer_status() case GL_FRAMEBUFFER_COMPLETE_EXT: break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - llerrs << "WTF?" << llendl; + llwarns << "WTF?" << llendl; break; default: - llerrs << "WTF?" << llendl; + llwarns << "WTF?" << llendl; } } } @@ -139,9 +139,9 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt) U32 offset = mTex.size(); if (offset >= 4 || - (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) + offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)) { - llerrs << "Too many color attachments!" << llendl; + llwarns << "Too many color attachments!" << llendl; // KL } U32 tex; @@ -203,7 +203,7 @@ void LLRenderTarget::allocateDepth() gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH24_STENCIL8_EXT, mResX, mResY, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); } } @@ -211,7 +211,7 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) { if (!mFBO || !target.mFBO) { - llerrs << "Cannot share depth buffer between non FBO render targets." << llendl; + llwarns << "Cannot share depth buffer between non FBO render targets." << llendl; } if (mDepth) @@ -349,16 +349,16 @@ U32 LLRenderTarget::getTexture(U32 attachment) const { if (attachment > mTex.size()-1) { - llerrs << "Invalid attachment index." << llendl; + llwarns << "Invalid attachment index [getTexture]." << llendl; // lets not crash KL its a pain in the ass! } return mTex[attachment]; } void LLRenderTarget::bindTexture(U32 index, S32 channel) { - if (index > mTex.size()-1) + if (index > 6)//mTex.size()-1) // KL yeah i know its a bit arbitary but make the number big enough as some unused render defer elements cause this to go wild { - llerrs << "Invalid attachment index." << llendl; + llwarns << "Invalid attachment index [bindtexture]." << llendl; } gGL.getTexUnit(channel)->bindManual(mUsage, mTex[index]); } @@ -440,7 +440,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, #if !LL_DARWIN if (!source.mFBO || !mFBO) { - llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; + llwarns << "Cannot copy framebuffer contents for non FBO render targets." << llendl; } if (mSampleBuffer) @@ -449,12 +449,27 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, } else { - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO); - - glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil) + { + source.bindTarget(); + gGL.getTexUnit(0)->bind(this, true); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1); + source.flush(); + } + else + { + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO); + stop_glerror(); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO); + stop_glerror(); + check_framebuffer_status(); + stop_glerror(); + glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + stop_glerror(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + stop_glerror(); + } } #endif } @@ -553,14 +568,14 @@ void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth if (!gGLManager.mHasFramebufferMultisample) { - llerrs << "Attempting to allocate unsupported render target type!" << llendl; + llwarns << "Attempting to allocate unsupported render target type!" << llendl; } mSamples = samples; if (mSamples <= 1) { - llerrs << "Cannot create a multisample buffer with less than 2 samples." << llendl; + llwarns << "Cannot create a multisample buffer with less than 2 samples." << llendl; } stop_glerror(); @@ -608,9 +623,9 @@ void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) U32 offset = mTex.size(); if (offset >= 4 || - (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) + offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)) { - llerrs << "Too many color attachments!" << llendl; + llwarns << "Too many color attachments!" << llendl; } U32 tex; @@ -631,10 +646,10 @@ void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) case GL_FRAMEBUFFER_COMPLETE_EXT: break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - llerrs << "WTF?" << llendl; + llwarns << "WTF?" << llendl; break; default: - llerrs << "WTF?" << llendl; + llwarns << "WTF?" << llendl; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); diff --git a/linden/indra/llrender/llrendertarget.h b/linden/indra/llrender/llrendertarget.h index d5d809b..69af1ea 100644 --- a/linden/indra/llrender/llrendertarget.h +++ b/linden/indra/llrender/llrendertarget.h @@ -121,6 +121,7 @@ public: U32 getTexture(U32 attachment = 0) const; U32 getDepth(void) const { return mDepth; } + BOOL hasStencil() const { return mStencil; } void bindTexture(U32 index, S32 channel); diff --git a/linden/indra/llrender/lltextureatlas.cpp b/linden/indra/llrender/lltextureatlas.cpp new file mode 100644 index 0000000..c0f5419 --- /dev/null +++ b/linden/indra/llrender/lltextureatlas.cpp @@ -0,0 +1,411 @@ +/** + * @file lltextureatlas.cpp + * @brief LLTextureAtlas class implementation. + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "linden_common.h" +#include "llerror.h" +#include "llimage.h" +#include "llmath.h" +#include "llgl.h" +#include "llrender.h" +#include "lltextureatlas.h" + +//------------------- +S16 LLTextureAtlas::sMaxSubTextureSize = 64 ; +S16 LLTextureAtlas::sSlotSize = 32 ; + +#ifndef DEBUG_ATLAS +#define DEBUG_ATLAS 0 +#endif + +#ifndef DEBUG_USAGE_BITS +#define DEBUG_USAGE_BITS 0 +#endif +//************************************************************************************************************** +LLTextureAtlas::LLTextureAtlas(U8 ncomponents, S16 atlas_dim) : LLImageGL(), + mAtlasDim(atlas_dim) +{ + setComponents(ncomponents) ; + + mCanAddToAtlas = FALSE ;//do not add one atlas to another. + mNumSlotsReserved = 0 ; + mMaxSlotsInAtlas = mAtlasDim * mAtlasDim ; + + generateEmptyUsageBits() ; + + //generate an empty texture + S32 dim = mAtlasDim * sSlotSize ; //number of pixels per dimension + LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim, dim, getComponents()); + createGLTexture(0, image_raw, 0); + image_raw = NULL; + dontDiscard(); +} + +LLTextureAtlas::~LLTextureAtlas() +{ + if(mSpatialGroupList.size() > 0) + { + llwarns << "Not clean up the spatial groups!" << llendl ; + } + releaseUsageBits() ; +} + +void LLTextureAtlas::getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yoffset) +{ +#if !DEBUG_ATLAS + xoffset = (F32)col / mAtlasDim ; + yoffset = (F32)row / mAtlasDim ; +#endif +} + +void LLTextureAtlas::getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale) +{ +#if !DEBUG_ATLAS + xscale = (F32)w / (mAtlasDim * sSlotSize) ; + yscale = (F32)h / (mAtlasDim * sSlotSize) ; +#endif +} + +//insert a texture piece into the atlas +LLGLuint LLTextureAtlas::insertSubTexture(const LLImageRaw* raw_image, S16 slot_col, S16 slot_row) +{ + S32 w = raw_image->getWidth() ; + S32 h = raw_image->getHeight() ; + if(w < 8 || w > sMaxSubTextureSize || h < 8 || h > sMaxSubTextureSize) + { + //size overflow + return 0 ; + } + + BOOL res = gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getTexName()); + if (!res) llwarns << "bindTexture failed" << llendl; + stop_glerror(); + + GLint xoffset = sSlotSize * slot_col ; + GLint yoffset = sSlotSize * slot_row ; + + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, TRUE); + glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, + w, h, mFormatPrimary, mFormatType, raw_image->getData()); + + return getTexName(); +} + +//release a sub-texture slot from the atlas +void LLTextureAtlas::releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width) +{ + unmarkUsageBits(slot_width, slot_col, slot_row) ; + mNumSlotsReserved -= slot_width * slot_width ; +} + +BOOL LLTextureAtlas::isEmpty() const +{ + return !mNumSlotsReserved ; +} + +BOOL LLTextureAtlas::isFull(S8 to_be_reserved) const +{ + return mNumSlotsReserved + to_be_reserved > mMaxSlotsInAtlas ; +} +F32 LLTextureAtlas::getFullness() const +{ + return (F32)mNumSlotsReserved / mMaxSlotsInAtlas ; +} + +void LLTextureAtlas::addSpatialGroup(LLSpatialGroup* groupp) +{ + if(groupp && !hasSpatialGroup(groupp)) + { + mSpatialGroupList.push_back(groupp); + } +} + +void LLTextureAtlas::removeSpatialGroup(LLSpatialGroup* groupp) +{ + if(groupp) + { + mSpatialGroupList.remove(groupp); + } +} + +void LLTextureAtlas::clearSpatialGroup() +{ + mSpatialGroupList.clear(); +} +void LLTextureAtlas::removeLastSpatialGroup() +{ + mSpatialGroupList.pop_back() ; +} + +LLSpatialGroup* LLTextureAtlas::getLastSpatialGroup() +{ + if(mSpatialGroupList.size() > 0) + { + return mSpatialGroupList.back() ; + } + return NULL ; +} + +BOOL LLTextureAtlas::hasSpatialGroup(LLSpatialGroup* groupp) +{ + for(std::list<LLSpatialGroup*>::iterator iter = mSpatialGroupList.begin(); iter != mSpatialGroupList.end() ; ++iter) + { + if(*iter == groupp) + { + return TRUE ; + } + } + return FALSE ; +} + +//-------------------------------------------------------------------------------------- +//private +void LLTextureAtlas::generateEmptyUsageBits() +{ + S32 col_len = (mAtlasDim + 7) >> 3 ; + mUsageBits = new U8*[mAtlasDim] ; + *mUsageBits = new U8[mAtlasDim * col_len] ; + + mUsageBits[0] = *mUsageBits ; + for(S32 i = 1 ; i < mAtlasDim ; i++) + { + mUsageBits[i] = mUsageBits[i-1] + col_len ; + + for(S32 j = 0 ; j < col_len ; j++) + { + //init by 0 for all bits. + mUsageBits[i][j] = 0 ; + } + } + + //do not forget mUsageBits[0]! + for(S32 j = 0 ; j < col_len ; j++) + { + //init by 0 for all bits. + mUsageBits[0][j] = 0 ; + } + + mTestBits = NULL ; +#if DEBUG_USAGE_BITS + //------------ + //test + mTestBits = new U8*[mAtlasDim] ; + *mTestBits = new U8[mAtlasDim * mAtlasDim] ; + mTestBits[0] = *mTestBits ; + for(S32 i = 1 ; i < mAtlasDim ; i++) + { + mTestBits[i] = mTestBits[i-1] + mAtlasDim ; + + for(S32 j = 0 ; j < mAtlasDim ; j++) + { + //init by 0 for all bits. + mTestBits[i][j] = 0 ; + } + } + + for(S32 j = 0 ; j < mAtlasDim ; j++) + { + //init by 0 for all bits. + mTestBits[0][j] = 0 ; + } +#endif +} + +void LLTextureAtlas::releaseUsageBits() +{ + if(mUsageBits) + { + delete[] *mUsageBits ; + delete[] mUsageBits ; + } + mUsageBits = NULL ; + + //test + if( mTestBits) + { + delete[] *mTestBits; + delete[] mTestBits; + } + mTestBits = NULL ; +} + +void LLTextureAtlas::markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row) +{ + S16 x = col >> 3 ; + + for(S8 i = 0 ; i < bits_len ; i++) + { + mUsageBits[row + i][x] |= mask ; + } + +#if DEBUG_USAGE_BITS + //test + for(S8 i = row ; i < row + bits_len ; i++) + { + for(S8 j = col ; j < col + bits_len ; j++) + { + mTestBits[i][j] = 1 ; + } + } +#endif +} + +void LLTextureAtlas::unmarkUsageBits(S8 bits_len, S16 col, S16 row) +{ + S16 x = col >> 3 ; + U8 mask = 1 ; + for(S8 i = 1 ; i < bits_len ; i++) + { + mask |= (1 << i) ; + } + mask <<= (col & 7) ; + mask = ~mask ; + + for(S8 i = 0 ; i < bits_len ; i++) + { + mUsageBits[row + i][x] &= mask ; + } + +#if DEBUG_USAGE_BITS + //test + for(S8 i = row ; i < row + bits_len ; i++) + { + for(S8 j = col ; j < col + bits_len ; j++) + { + mTestBits[i][j] = 0 ; + } + } +#endif +} + +//return true if any of bits in the range marked. +BOOL LLTextureAtlas::areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row) +{ + BOOL ret = FALSE ; + S16 x = col >> 3 ; + + for(S8 i = 0 ; i < bits_len ; i++) + { + if(mUsageBits[row + i][x] & mask) + { + ret = TRUE ; + break ; + //return TRUE ; + } + } + +#if DEBUG_USAGE_BITS + //test + BOOL ret2 = FALSE ; + for(S8 i = row ; i < row + bits_len ; i++) + { + for(S8 j = col ; j < col + bits_len ; j++) + { + if(mTestBits[i][j]) + { + ret2 = TRUE ; + } + } + } + + if(ret != ret2) + { + llwarns << "bits map corrupted." << llendl ; + } +#endif + return ret ;//FALSE ; +} + +//---------------------------------------------------------------------- +// +//index order: Z order, i.e.: +// |-----|-----|-----|-----| +// | 10 | 11 | 14 | 15 | +// |-----|-----|-----|-----| +// | 8 | 9 | 12 | 13 | +// |-----|-----|-----|-----| +// | 2 | 3 | 6 | 7 | +// |-----|-----|-----|-----| +// | 0 | 1 | 4 | 5 | +// |-----|-----|-----|-----| +void LLTextureAtlas::getPositionFromIndex(S16 index, S16& col, S16& row) +{ + col = 0 ; + row = 0 ; + + S16 index_copy = index ; + for(S16 i = 0 ; index_copy && i < 16 ; i += 2) + { + col |= ((index & (1 << i)) >> i) << (i >> 1) ; + row |= ((index & (1 << (i + 1))) >> (i + 1)) << (i >> 1) ; + index_copy >>= 2 ; + } +} +void LLTextureAtlas::getIndexFromPosition(S16 col, S16 row, S16& index) +{ + index = 0 ; + S16 col_copy = col ; + S16 row_copy = row ; + for(S16 i = 0 ; (col_copy || row_copy) && i < 16 ; i++) + { + index |= ((col & 1 << i) << i) | ((row & 1 << i) << ( i + 1)) ; + col_copy >>= 1 ; + row_copy >>= 1 ; + } +} +//---------------------------------------------------------------------- +//return TRUE if succeeds. +BOOL LLTextureAtlas::getNextAvailableSlot(S8 bits_len, S16& col, S16& row) +{ + S16 index_step = bits_len * bits_len ; + + U8 mask = 1 ; + for(S8 i = 1 ; i < bits_len ; i++) + { + mask |= (1 << i) ; + } + + U8 cur_mask ; + for(S16 index = 0 ; index < mMaxSlotsInAtlas ; index += index_step) + { + getPositionFromIndex(index, col, row) ; + + cur_mask = mask << (col & 7) ; + if(!areUsageBitsMarked(bits_len, cur_mask, col, row)) + { + markUsageBits(bits_len, cur_mask, col, row) ; + mNumSlotsReserved += bits_len * bits_len ; + + return TRUE ; + } + } + + return FALSE ; +} diff --git a/linden/indra/llrender/lltextureatlas.h b/linden/indra/llrender/lltextureatlas.h new file mode 100644 index 0000000..4922175 --- /dev/null +++ b/linden/indra/llrender/lltextureatlas.h @@ -0,0 +1,92 @@ +/** + * @file lltextureatlas.h + * @brief LLTextureAtlas base class. + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#ifndef LL_TEXTUREATLAS_H +#define LL_TEXTUREATLAS_H + +#include "llimagegl.h" +class LLSpatialGroup ; + +class LLTextureAtlas : public LLImageGL +{ +public: + LLTextureAtlas(U8 ncomponents, S16 atlas_dim = 16) ; + ~LLTextureAtlas() ; + + LLGLuint insertSubTexture(const LLImageRaw* raw_image, S16 slot_col, S16 slot_row) ; + void releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width); + + BOOL getNextAvailableSlot(S8 bits_len, S16& col, S16& row) ; + void getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yOffset) ; + void getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale) ; + + BOOL isEmpty() const ; + BOOL isFull(S8 to_be_reserved = 1) const ; + F32 getFullness() const ; + + void addSpatialGroup(LLSpatialGroup* groupp) ; + void removeSpatialGroup(LLSpatialGroup* groupp) ; + LLSpatialGroup* getLastSpatialGroup() ; + void removeLastSpatialGroup() ; + BOOL hasSpatialGroup(LLSpatialGroup* groupp) ; + void clearSpatialGroup() ; + std::list<LLSpatialGroup*>* getSpatialGroupList() {return &mSpatialGroupList;} +private: + void generateEmptyUsageBits() ; + void releaseUsageBits() ; + + void markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row) ; + void unmarkUsageBits(S8 bits_len, S16 col, S16 row) ; + + void getPositionFromIndex(S16 index, S16& col, S16& row) ; + void getIndexFromPosition(S16 col, S16 row, S16& index) ; + BOOL areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row) ; + +private: + S16 mAtlasDim ; //number of slots per edge, i.e, there are "mAtlasDim * mAtlasDim" total slots in the atlas. + S16 mNumSlotsReserved ; + S16 mMaxSlotsInAtlas ; + U8 **mUsageBits ; + std::list<LLSpatialGroup*> mSpatialGroupList ; + +public: + //debug use only + U8 **mTestBits ; + +public: + static S16 sMaxSubTextureSize ; + static S16 sSlotSize ; +}; + +#endif + diff --git a/linden/indra/llrender/llvertexbuffer.cpp b/linden/indra/llrender/llvertexbuffer.cpp index 461edbe..31c2d75 100644 --- a/linden/indra/llrender/llvertexbuffer.cpp +++ b/linden/indra/llrender/llvertexbuffer.cpp @@ -96,7 +96,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { /*if (LLGLImmediate::sStarted) { - llerrs << "Cannot use LLGLImmediate and LLVertexBuffer simultaneously!" << llendl; + llwarns << "Cannot use LLGLImmediate and LLVertexBuffer simultaneously!" << llendl; }*/ if (sLastMask != data_mask) @@ -129,7 +129,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { //needs to be enabled, make sure it was (DEBUG TEMPORARY) if (i > 0 && !glIsEnabled(array[i])) { - llerrs << "Bad client state! " << array[i] << " disabled." << llendl; + llwarns << "Bad client state! " << array[i] << " disabled." << llendl; } } } @@ -141,7 +141,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) } else if (gDebugGL && glIsEnabled(array[i])) { //needs to be disabled, make sure it was (DEBUG TEMPORARY) - llerrs << "Bad client state! " << array[i] << " enabled." << llendl; + llwarns << "Bad client state! " << array[i] << " enabled." << llendl; } } } @@ -197,28 +197,28 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi if (start >= (U32) mRequestedNumVerts || end >= (U32) mRequestedNumVerts) { - llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl; + llwarns << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl; } if (indices_offset >= (U32) mRequestedNumIndices || indices_offset + count > (U32) mRequestedNumIndices) { - llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; + llwarns << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; } if (mGLIndices != sGLRenderIndices) { - llerrs << "Wrong index buffer bound." << llendl; + llwarns << "Wrong index buffer bound." << llendl; } if (mGLBuffer != sGLRenderBuffer) { - llerrs << "Wrong vertex buffer bound." << llendl; + llwarns << "Wrong vertex buffer bound." << llendl; } if (mode > LLRender::NUM_MODES) { - llerrs << "Invalid draw mode: " << mode << llendl; + llwarns << "Invalid draw mode: " << mode << llendl; return; } @@ -233,22 +233,22 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const if (indices_offset >= (U32) mRequestedNumIndices || indices_offset + count > (U32) mRequestedNumIndices) { - llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; + llwarns << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; } if (mGLIndices != sGLRenderIndices) { - llerrs << "Wrong index buffer bound." << llendl; + llwarns << "Wrong index buffer bound." << llendl; } if (mGLBuffer != sGLRenderBuffer) { - llerrs << "Wrong vertex buffer bound." << llendl; + llwarns << "Wrong vertex buffer bound." << llendl; } if (mode > LLRender::NUM_MODES) { - llerrs << "Invalid draw mode: " << mode << llendl; + llwarns << "Invalid draw mode: " << mode << llendl; return; } @@ -263,17 +263,17 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const if (first >= (U32) mRequestedNumVerts || first + count > (U32) mRequestedNumVerts) { - llerrs << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl; + llwarns << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl; } if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive) { - llerrs << "Wrong vertex buffer bound." << llendl; + llwarns << "Wrong vertex buffer bound." << llendl; } if (mode > LLRender::NUM_MODES) { - llerrs << "Invalid draw mode: " << mode << llendl; + llwarns << "Invalid draw mode: " << mode << llendl; return; } @@ -530,7 +530,7 @@ void LLVertexBuffer::destroyGLBuffer() { if (mMappedData || mMappedIndexData) { - llerrs << "Vertex buffer destroyed while mapped!" << llendl; + llwarns << "Vertex buffer destroyed while mapped!" << llendl; } releaseBuffer(); } @@ -557,7 +557,7 @@ void LLVertexBuffer::destroyGLIndices() { if (mMappedData || mMappedIndexData) { - llerrs << "Vertex buffer destroyed while mapped." << llendl; + llwarns << "Vertex buffer destroyed while mapped." << llendl; } releaseIndices(); } @@ -634,7 +634,7 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) if (mMappedData) { - llerrs << "LLVertexBuffer::allocateBuffer() called redundantly." << llendl; + llwarns << "LLVertexBuffer::allocateBuffer() called redundantly." << llendl; } if (create && (nverts || nindices)) { @@ -782,11 +782,11 @@ U8* LLVertexBuffer::mapBuffer(S32 access) LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mFinal) { - llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl; + llwarns << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl; } if (!useVBOs() && !mMappedData && !mMappedIndexData) { - llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl; + llwarns << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl; } if (!mLocked && useVBOs()) @@ -813,11 +813,11 @@ U8* LLVertexBuffer::mapBuffer(S32 access) glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); if (buff != mGLBuffer) { - llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + llwarns << "Invalid GL vertex buffer bound: " << buff << llendl; } - llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl; + llwarns << "glMapBuffer returned NULL (no vertex data)" << llendl; } if (!mMappedIndexData) @@ -826,10 +826,10 @@ U8* LLVertexBuffer::mapBuffer(S32 access) glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if (buff != mGLIndices) { - llerrs << "Invalid GL index buffer bound: " << buff << llendl; + llwarns << "Invalid GL index buffer bound: " << buff << llendl; } - llerrs << "glMapBuffer returned NULL (no index data)" << llendl; + llwarns << "glMapBuffer returned NULL (no index data)" << llendl; } sMappedCount++; @@ -908,7 +908,7 @@ template <class T,S32 type> struct VertexBufferStrider } else { - llerrs << "VertexBufferStrider could not find valid vertex data." << llendl; + llwarns << "VertexBufferStrider could not find valid vertex data." << llendl; } return FALSE; } @@ -965,7 +965,7 @@ void LLVertexBuffer::setStride(S32 type, S32 new_stride) LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mNumVerts) { - llerrs << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl; + llwarns << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl; } // This code assumes that setStride() will only be called once per VBO per type. S32 delta = new_stride - sTypeOffsets[type]; @@ -1020,15 +1020,15 @@ void LLVertexBuffer::setBuffer(U32 data_mask) { GLint buff; glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); - if (buff != mGLBuffer) + if ((GLuint)buff != mGLBuffer) { - llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + llwarns << "Invalid GL vertex buffer bound: " << buff << llendl; } glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); - if (buff != mGLIndices) + if ((GLuint)buff != mGLIndices) { - llerrs << "Invalid GL index buffer bound: " << buff << llendl; + llwarns << "Invalid GL index buffer bound: " << buff << llendl; } } @@ -1038,15 +1038,15 @@ void LLVertexBuffer::setBuffer(U32 data_mask) { GLint buff; glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); - if (buff != mGLBuffer) + if ((GLuint)buff != mGLBuffer) { - llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + llwarns << "Invalid GL vertex buffer bound: " << buff << llendl; } glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); - if (buff != mGLIndices) + if ((GLuint)buff != mGLIndices) { - llerrs << "Invalid GL index buffer bound: " << buff << llendl; + llwarns << "Invalid GL index buffer bound: " << buff << llendl; } } @@ -1068,7 +1068,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask) if (data_mask != 0) { - llerrs << "Buffer set for rendering before being filled after resize." << llendl; + llwarns << "Buffer set for rendering before being filled after resize." << llendl; } } @@ -1129,7 +1129,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const if ((data_mask & mTypeMask) != data_mask) { - llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; + llwarns << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; } if (data_mask & MAP_NORMAL) diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index e0c6c61..6fd259a 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt @@ -329,6 +329,7 @@ set(viewer_SOURCE_FILES llpolymesh.cpp llpolymorph.cpp llprefsadvanced.cpp + llpostprocess.cpp llprefschat.cpp llprefsim.cpp llprefsvoice.cpp @@ -359,6 +360,7 @@ set(viewer_SOURCE_FILES llsurface.cpp llsurfacepatch.cpp lltexlayer.cpp + lltextureatlasmanager.cpp lltexturecache.cpp lltexturectrl.cpp lltexturefetch.cpp @@ -777,6 +779,7 @@ set(viewer_HEADER_FILES llpolymesh.h llpolymorph.h llprefsadvanced.h + llpostprocess.h llprefschat.h llprefsim.h llprefsvoice.h @@ -809,6 +812,7 @@ set(viewer_HEADER_FILES llsurfacepatch.h lltable.h lltexlayer.h + lltextureatlasmanager.h lltexturecache.h lltexturectrl.h lltexturefetch.h diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml index f70c0fc..c7f8d36 100644 --- a/linden/indra/newview/app_settings/settings.xml +++ b/linden/indra/newview/app_settings/settings.xml @@ -5097,6 +5097,21 @@ <key>Value</key> <integer>1</integer> </map> + +<!--KL port --> + <key>EnableTextureAtlas</key> + <map> + <key>Comment</key> + <string>Whether to use texture atlas or not</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> +<!--/KL port --> + <key>EnableVoiceChat</key> <map> <key>Comment</key> @@ -8928,11 +8943,74 @@ <string>Vector3</string> <key>Value</key> <array> + <real>1.0</real> + <real>12.0</real> + <real>32.0</real> + </array> + </map> + <key>RenderShadowSplitExponent</key> + <map> + <key>Comment</key> + <string>Near clip plane split distances for shadow map frusta (x=perspective, y=ortho, z=transition rate).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>3.0</real> + <real>3.0</real> + <real>2.0</real> + </array> + </map> + <key>RenderShadowOrthoClipPlanes</key> + <map> + <key>Comment</key> + <string>Near clip plane split distances for orthographic shadow map frusta.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> <real>4.0</real> <real>8.0</real> <real>24.0</real> </array> </map> + <key>RenderShadowProjOffset</key> + <map> + <key>Comment</key> + <string>Amount to scale distance to virtual origin of shadow perspective projection.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>2.0</real> + </map> + <key>RenderShadowSlopeThreshold</key> + <map> + <key>Comment</key> + <string>Cutoff slope value for points to affect perspective shadow generation</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.0</real> + </map> + <key>RenderShadowProjExponent</key> + <map> + <key>Comment</key> + <string>Exponent applied to transition between ortho and perspective shadow projections based on viewing angle and light vector.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.5</real> + </map> <key>RenderSSAOScale</key> <map> <key>Comment</key> @@ -9092,6 +9170,184 @@ <key>Value</key> <integer>0</integer> </map> + + <key>RenderGILightRadius</key> + <map> + <key>Comment</key> + <string>Distance of ambiant bounce lighting from sun.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>8</real> + </map> + + <key>RenderGISamples</key> + <map> + <key>Comment</key> + <string>Number of samples to take for GI.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <real>64</real> + </map> + + <key>RenderGIRange</key> + <map> + <key>Comment</key> + <string>Distance to cut off GI effect.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>128</real> + </map> + + + <key>RenderGIDirectionWeight</key> + <map> + <key>Comment</key> + <string>Weight of reflected light vector in GI angular attenuation.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.5</real> + </map> + + <key>RenderGILightOffset</key> + <map> + <key>Comment</key> + <string>Amount to offset light from point of impact in gi map (scaled by light radius).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.0</real> + </map> + + <key>RenderGIColorCurve</key> + <map> + <key>Comment</key> + <string>Global illumination color correction curve parameters.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>0.0</real> + <real>0.2</real> + <real>0.02</real> + </array> + </map> + + <key>RenderLuminanceColorCurve</key> + <map> + <key>Comment</key> + <string>Luminance color correction curve parameters.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>0.30</real> + <real>0.0</real> + <real>0.04</real> + </array> + </map> + + <key>RenderGILuminanceColorCurve</key> + <map> + <key>Comment</key> + <string>Luminance color correction curve parameters.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>0.4</real> + <real>0.0</real> + <real>0.05</real> + </array> + </map> + + <key>RenderSunLuminanceColorCurve</key> + <map> + <key>Comment</key> + <string>Luminance color correction curve parameters.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>0.6</real> + <real>0.0</real> + <real>-0.3</real> + </array> + </map> + + <key>RenderLuminanceDetail</key> + <map> + <key>Comment</key> + <string>Mipmap level to use for luminance</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>8.0</real> + </map> + + <key>RenderLuminanceFade</key> + <map> + <key>Comment</key> + <string>Scaler for speed of luminance adjustment</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.05</real> + </map> + + <key>RenderGISpecularCurve</key> + <map> + <key>Comment</key> + <string>Global illumination specular color correction curve parameters.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>0.1</real> + <real>0.0</real> + <real>0.9</real> + </array> + </map> + + <key>RenderGIIntensity</key> + <map> + <key>Comment</key> + <string>Distance of ambiant bounce lighting from sun.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.2f</real> + </map> + <key>RenderDeferredAlphaSoften</key> <map> <key>Comment</key> @@ -9114,89 +9370,472 @@ <key>Value</key> <real>4</real> </map> - <key>RenderDeferred</key> + <key>RenderDeferredSpotShadowBias</key> <map> <key>Comment</key> - <string>Use deferred rendering pipeline.</string> + <string>Bias value for spot shadows (prevent shadow acne).</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Boolean</string> + <string>F32</string> <key>Value</key> - <integer>0</integer> + <real>-64.0</real> </map> - <key>RenderDeferredSunShadow</key> + <key>RenderDeferredSpotShadowOffset</key> <map> <key>Comment</key> - <string>Generate shadows from the sun.</string> + <string>Offset value for spot shadows (prevent shadow acne).</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Boolean</string> + <string>F32</string> <key>Value</key> + <real>0.8</real> + </map> + + <key>RenderShadowBias</key> + <map> + <key>Comment</key> + <string>Bias value for shadows (prevent shadow acne).</string> + <key>Persist</key> <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.001</real> </map> - <key>RenderDeferredSunWash</key> + <key>RenderShadowOffset</key> <map> <key>Comment</key> - <string>Amount local lights are washed out by sun.</string> + <string>Offset value for shadows (prevent shadow acne).</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>F32</string> <key>Value</key> - <real>0.5</real> + <real>0.6</real> </map> - <key>RenderShadowNoise</key> + + <key>RenderShadowResolutionScale</key> <map> <key>Comment</key> - <string>Magnitude of noise on shadow samples.</string> + <string>Scale of shadow map resolution vs. screen resolution</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>F32</string> <key>Value</key> - <real>-0.0001</real> + <real>1.0</real> </map> - <key>RenderShadowBlurSize</key> + + + + <key>RenderDeferredTreeShadowBias</key> <map> <key>Comment</key> - <string>Scale of shadow softening kernel.</string> + <string>Bias value for tree shadows (prevent shadow acne).</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>F32</string> <key>Value</key> - <real>0.7</real> + <real>1.0</real> </map> - <key>RenderShadowBlurSamples</key> + <key>RenderDeferredTreeShadowOffset</key> <map> <key>Comment</key> - <string>Number of samples to take for each pass of shadow blur (value range 1-16). Actual number of samples is value * 2 - 1.</string> + <string>Offset value for tree shadows (prevent shadow acne).</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>U32</string> + <string>F32</string> <key>Value</key> - <real>5</real> + <real>1.0</real> </map> - <key>RenderDynamicLOD</key> - <map> - <key>Comment</key> - <string>Dynamically adjust level of detail.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>RenderFSAASamples</key> - <map> - <key>Comment</key> - <string>Number of samples to use for FSAA (0 = no AA).</string> - <key>Persist</key> - <integer>1</integer> + + <key>RenderHighlightFadeTime</key> + <map> + <key>Comment</key> + <string>Transition time for mouseover highlights.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.2</real> + </map> + + <key>RenderHighlightBrightness</key> + <map> + <key>Comment</key> + <string>Brightness of mouseover highlights.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>4.0</real> + </map> + + <key>RenderHighlightThickness</key> + <map> + <key>Comment</key> + <string>Thickness of mouseover highlights.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.6</real> + </map> + + <key>RenderHighlightColor</key> + <map> + <key>Comment</key> + <string>Brightness of mouseover highlights.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Color4</string> + <key>Value</key> + <array> + <real>0.4</real> + <real>0.98</real> + <real>0.93</real> + <real>1.0</real> + </array> + </map> + + <key>RenderSpecularResX</key> + <map> + <key>Comment</key> + <string>Spec map resolution.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <real>128</real> + </map> + + <key>RenderSpecularResY</key> + <map> + <key>Comment</key> + <string>Spec map resolution.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <real>128</real> + </map> + + <key>RenderSpecularExponent</key> + <map> + <key>Comment</key> + <string>Specular exponent for generating spec map</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1</real> + </map> + + <key>RenderDeferred</key> + <map> + <key>Comment</key> + <string>Use deferred rendering pipeline.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + + <key>RenderDeferredShadow</key> + <map> + <key>Comment</key> + <string>Enable shadows in deferred renderer.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + + <key>RenderDeferredGI</key> + <map> + <key>Comment</key> + <string>Enable GI in deferred renderer.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + + <key>RenderDeferredSunShadow</key> + <map> + <key>Comment</key> + <string>Generate shadows from the sun.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + + <key>RenderDeferredSun</key> + <map> + <key>Comment</key> + <string>Execute sunlight shader in deferred renderer.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + + <key>RenderDeferredAtmospheric</key> + <map> + <key>Comment</key> + <string>Execute atmospheric shader in deferred renderer.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + + <key>RenderDeferredBlurLight</key> + <map> + <key>Comment</key> + <string>Execute shadow softening shader in deferred renderer.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + + <key>RenderDeferredLocalLights</key> + <map> + <key>Comment</key> + <string>Execute local lighting shader in deferred renderer.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + + <key>RenderDeferredFullscreenLights</key> + <map> + <key>Comment</key> + <string>Execute local lighting shader in deferred renderer.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + + <key>RenderDeferredSunWash</key> + <map> + <key>Comment</key> + <string>Amount local lights are washed out by sun.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.5</real> + </map> + <key>RenderShadowNoise</key> + <map> + <key>Comment</key> + <string>Magnitude of noise on shadow samples.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>-0.0001</real> + </map> + <key>RenderShadowErrorCutoff</key> + <map> + <key>Comment</key> + <string>Cutoff error value to use ortho instead of perspective projection.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>5.0</real> + </map> + <key>RenderShadowFOVCutoff</key> + <map> + <key>Comment</key> + <string>Cutoff FOV to use ortho instead of perspective projection.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.1</real> + </map> + + <key>RenderShadowGaussian</key> + <map> + <key>Comment</key> + <string>Gaussian coefficients for the two shadow/SSAO blurring passes (z component unused).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>3.0</real> + <real>2.0</real> + <real>0.0</real> + </array> + </map> + + <key>RenderShadowBlurSize</key> + <map> + <key>Comment</key> + <string>Scale of shadow softening kernel.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.8</real> + </map> + <key>RenderShadowBlurSamples</key> + <map> + <key>Comment</key> + <string>Number of samples to take for each pass of shadow blur (value range 1-16). Actual number of samples is value * 2 - 1.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <real>4</real> + </map> + <key>RenderShadowBlurDistFactor</key> + <map> + <key>Comment</key> + <string>Distance scaler for shadow blur.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.1</real> + </map> + + <key>RenderGIBlurColorCurve</key> + <map> + <key>Comment</key> + <string>Color curve for GI softening kernel</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>1.0</real> + <real>0.6</real> + <real>0.1</real> + </array> + </map> + + <key>RenderGIGaussian</key> + <map> + <key>Comment</key> + <string>Gaussian coefficient for the two GI blurring passes.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>64</real> + </map> + + <key>RenderGIBlurPasses</key> + <map> + <key>Comment</key> + <string>Scale of GI softening kernel.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <real>2</real> + </map> + + <key>RenderGIBlurSize</key> + <map> + <key>Comment</key> + <string>Scale of GI softening kernel.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>3.0</real> + </map> + <key>RenderGIBlurSamples</key> + <map> + <key>Comment</key> + <string>Number of samples to take for each pass of GI blur (value range 1-16). Actual number of samples is value * 2 - 1.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <real>6</real> + </map> + <key>RenderGIBlurDistFactor</key> + <map> + <key>Comment</key> + <string>Distance scaler for GI blur.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.0</real> + </map> + + <key>RenderDynamicLOD</key> + <map> + <key>Comment</key> + <string>Dynamically adjust level of detail.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>RenderFSAASamples</key> + <map> + <key>Comment</key> + <string>Number of samples to use for FSAA (0 = no AA).</string> + <key>Persist</key> + <integer>1</integer> <key>Type</key> <string>U32</string> <key>Value</key> @@ -9430,6 +10069,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>RenderHighlightSelections</key> + <map> + <key>Comment</key> + <string>Show selection outlines on objects</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>RenderHiddenSelections</key> <map> <key>Comment</key> @@ -9738,6 +10388,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>RenderUIBuffer</key> + <map> + <key>Comment</key> + <string>Cache ui render in a screen aligned buffer.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RenderUnloadedAvatar</key> <map> <key>Comment</key> diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index a91e9fa..f90d91f 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -13,9 +13,9 @@ uniform sampler2DShadow shadowMap1; uniform sampler2DShadow shadowMap2; uniform sampler2DShadow shadowMap3; uniform sampler2D noiseMap; -uniform sampler2DRect positionMap; +uniform sampler2DRect depthMap; -uniform mat4 shadow_matrix[4]; +uniform mat4 shadow_matrix[6]; uniform vec4 shadow_clip; uniform vec2 screen_res; @@ -26,15 +26,31 @@ varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_fragcoord; varying vec3 vary_position; +varying vec3 vary_light; uniform float alpha_soften; +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + void main() { vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; frag *= screen_res; - vec3 samp_pos = texture2DRect(positionMap, frag).xyz; + vec3 samp_pos = getPosition(frag).xyz; float shadow = 1.0; vec4 pos = vec4(vary_position, 1.0); @@ -82,7 +98,7 @@ void main() //gl_FragColor = gl_Color; gl_FragColor = color; - //gl_FragColor = vec4(1,0,1,1); + //gl_FragColor = vec4(1,0,1,1)*shadow; } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index b496bd6..48baf77 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -20,8 +20,11 @@ varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_fragcoord; varying vec3 vary_position; +varying vec3 vary_light; uniform float near_clip; +uniform float shadow_offset; +uniform float shadow_bias; void main() { @@ -32,8 +35,9 @@ void main() vec4 pos = (gl_ModelViewMatrix * gl_Vertex); vec3 norm = normalize(gl_NormalMatrix * gl_Normal); - vary_position = pos.xyz; - + // KL this works around ATI not compiling the shader but maintains shadow offset and bias vec3 not vec4 + vary_position = pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias); + calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); @@ -54,6 +58,8 @@ void main() col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); + vary_light = gl_LightSource[0].position.xyz; + vary_ambient = col.rgb*gl_Color.rgb; vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl index 6c94f5c..ff64a6b 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl @@ -12,7 +12,7 @@ uniform sampler2DShadow shadowMap2; uniform sampler2DShadow shadowMap3; uniform sampler2D noiseMap; -uniform mat4 shadow_matrix[4]; +uniform mat4 shadow_matrix[6]; uniform vec4 shadow_clip; vec3 atmosLighting(vec3 light); diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index 58aa5a9..4b9cca2 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -8,13 +8,18 @@ uniform sampler2D diffuseMap; varying vec3 vary_normal; -varying vec4 vary_position; void main() { - gl_FragData[0] = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy); + vec4 diff = gl_Color*texture2D(diffuseMap, gl_TexCoord[0].xy); + // Viewer 2.0 uses 0.2 but for KL's viewer if i want a complete avatar need this to be 0.0 for now. + if (diff.a < 0.0) + { + discard; + } + + gl_FragData[0] = vec4(diff.rgb, 1.0); gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal), 0.0); - gl_FragData[3] = vary_position; + gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl index 27c09db..00083eb 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl @@ -10,6 +10,7 @@ uniform sampler2D diffuseMap; void main() { - gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy)); + gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a); + //gl_FragColor = vec4(1,1,1,1); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl index 14da6b1..8c8489d 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl @@ -28,8 +28,7 @@ void main() norm = normalize(norm); pos = gl_ProjectionMatrix * pos; - //smash geometry against near clip plane - pos.z = max(pos.z, -1.0); + pos.z = max(pos.z, -pos.w+0.01); gl_Position = pos; gl_FrontColor = gl_Color; diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl index 12a7ff7..471a1f0 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl @@ -10,7 +10,6 @@ mat4 getSkinnedTransform(); attribute vec4 weight; varying vec3 vary_normal; -varying vec4 vary_position; void main() { @@ -30,7 +29,6 @@ void main() norm.z = dot(trans[2].xyz, gl_Normal); norm = normalize(norm); - vary_position = pos; vary_normal = norm; gl_Position = gl_ProjectionMatrix * pos; diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index 3c6700a..1713fe9 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -7,10 +7,11 @@ #extension GL_ARB_texture_rectangle : enable -uniform sampler2DRect positionMap; +uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; uniform sampler2DRect lightMap; +uniform float dist_factor; uniform float blur_size; uniform vec2 delta; uniform vec3 kern[32]; @@ -19,30 +20,52 @@ uniform float kern_scale; varying vec2 vary_fragcoord; +uniform mat4 inv_proj; +uniform vec2 screen_res; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; - vec3 pos = texture2DRect(positionMap, vary_fragcoord.xy).xyz; - vec2 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rg; + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + vec3 pos = getPosition(vary_fragcoord.xy).xyz; + vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba; vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); + dlt /= max(-pos.z*dist_factor, 1.0); + vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' - vec2 col = defined_weight * ccol; + vec4 col = defined_weight.xyxx * ccol; for (int i = 1; i < kern_length; i++) { vec2 tc = vary_fragcoord.xy + kern[i].z*dlt; - vec3 samppos = texture2DRect(positionMap, tc).xyz; + vec3 samppos = getPosition(tc).xyz; float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane if (d*d <= 0.003) { - col += texture2DRect(lightMap, tc).rg*kern[i].xy; + col += texture2DRect(lightMap, tc)*kern[i].xyxx; defined_weight += kern[i].xy; } } - col /= defined_weight; - gl_FragColor = vec4(col.r, col.g, 0.0, 1.0); + + col /= defined_weight.xyxx; + + gl_FragColor = col; + + //gl_FragColor = ccol; } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index a8712bc..1c29dae 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -11,7 +11,6 @@ uniform sampler2D bumpMap; varying vec3 vary_mat0; varying vec3 vary_mat1; varying vec3 vary_mat2; -varying vec4 vary_position; void main() { @@ -22,8 +21,7 @@ void main() dot(norm,vary_mat1), dot(norm,vary_mat2)); - gl_FragData[0].rgb = gl_Color.rgb*col; - gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a); - gl_FragData[2] = vec4(normalize(tnorm), 0.0); - gl_FragData[3] = vary_position; + gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0); + gl_FragData[1] = vec4(col*gl_Color.a, gl_Color.a); + gl_FragData[2] = vec4(normalize(tnorm)*0.5+0.5, 0.0); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl index ba18092..9589912 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl @@ -8,7 +8,6 @@ varying vec3 vary_mat0; varying vec3 vary_mat1; varying vec3 vary_mat2; -varying vec4 vary_position; void main() { @@ -16,8 +15,6 @@ void main() gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vary_position = gl_ModelViewMatrix * gl_Vertex; - vec3 n = normalize(gl_NormalMatrix * gl_Normal); vec3 b = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz); vec3 t = cross(b, n); diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index f2ba2df..919dd5d 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -8,13 +8,11 @@ uniform sampler2D diffuseMap; varying vec3 vary_normal; -varying vec4 vary_position; void main() { vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; - gl_FragData[0] = vec4(gl_Color.rgb*col, 1.0); + gl_FragData[0] = vec4(gl_Color.rgb*col, 1.0); // KL viewer 2.0 has 0.0 but this is not working right yet besides i like to see my eyes :) gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a); - gl_FragData[2] = vec4(normalize(vary_normal), 0.0); - gl_FragData[3] = vary_position; + gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index 3413a7f..44468cd 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -6,16 +6,13 @@ */ varying vec3 vary_normal; -varying vec4 vary_position; void main() { //transform vertex - gl_Position = ftransform(); + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vary_position = gl_ModelViewMatrix * gl_Vertex; - vary_normal = normalize(gl_NormalMatrix * gl_Normal); gl_FrontColor = gl_Color; diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl index 2a811c5..e518bdd 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -8,14 +8,9 @@ #extension GL_ARB_texture_rectangle : enable uniform sampler2D diffuseMap; -uniform sampler2DShadow shadowMap0; -uniform sampler2DShadow shadowMap1; -uniform sampler2DShadow shadowMap2; -uniform sampler2DShadow shadowMap3; +uniform sampler2DRect depthMap; uniform sampler2D noiseMap; -uniform sampler2DRect positionMap; -uniform mat4 shadow_matrix[4]; uniform vec4 shadow_clip; uniform vec2 screen_res; @@ -30,12 +25,27 @@ varying vec3 vary_fragcoord; uniform float alpha_soften; +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + void main() { vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; frag *= screen_res; - vec3 samp_pos = texture2DRect(positionMap, frag).xyz; + vec3 samp_pos = getPosition(frag).xyz; float shadow = 1.0; vec4 pos = vary_position; @@ -46,10 +56,10 @@ void main() color.rgb = fullbrightScaleSoftClip(color.rgb); - if (samp_pos.z != 0.0) + if (samp_pos.z != 0.0 && color.a < 1.0) { float dist_factor = alpha_soften; - float a = gl_Color.a; + float a = color.a; a *= a; dist_factor *= 1.0/(1.0-a); color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl index 6381a1c..aff5117 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl @@ -12,12 +12,12 @@ vec3 atmosAffectDirectionalLight(float lightIntensity); vec3 scaleDownLight(vec3 light); vec3 scaleUpLight(vec3 light); -varying vec4 vary_position; varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_normal; varying vec3 vary_fragcoord; uniform float near_clip; +varying vec4 vary_position; void main() { diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/giF.glsl new file mode 100644 index 0000000..b351eec --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/giF.glsl @@ -0,0 +1,165 @@ +/** + * @file giF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2D noiseMap; + +uniform sampler2D diffuseGIMap; +uniform sampler2D normalGIMap; +uniform sampler2D depthGIMap; + +uniform sampler2D lightFunc; + +// Inputs +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +uniform mat4 inv_proj; +uniform mat4 gi_mat; //gPipeline.mGIMatrix - eye space to sun space +uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space +uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix +uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space +uniform float gi_radius; +uniform float gi_intensity; +uniform int gi_samples; +uniform vec2 gi_kern[25]; +uniform vec2 gi_scale; +uniform vec3 gi_quad; +uniform vec3 gi_spec; +uniform float gi_direction_weight; +uniform float gi_light_offset; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +vec4 getGIPosition(vec2 gi_tc) +{ + float depth = texture2D(depthGIMap, gi_tc).a; + vec2 sc = gi_tc*2.0; + sc -= vec2(1.0, 1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = gi_inv_proj*ndc; + pos.xyz /= pos.w; + pos.w = 1.0; + return pos; +} + +vec3 giAmbient(vec3 pos, vec3 norm) +{ + vec4 gi_c = gi_mat_proj * vec4(pos, 1.0); + gi_c.xyz /= gi_c.w; + + vec4 gi_pos = gi_mat*vec4(pos,1.0); + vec3 gi_norm = (gi_norm_mat*vec4(norm,1.0)).xyz; + gi_norm = normalize(gi_norm); + + vec2 tcx = gi_norm.xy; + vec2 tcy = gi_norm.yx; + + vec4 eye_pos = gi_mat*vec4(0,0,0,1.0); + + vec3 eye_dir = normalize(gi_pos.xyz-eye_pos.xyz/eye_pos.w); + + //vec3 eye_dir = vec3(0,0,-1); + //eye_dir = (gi_norm_mat*vec4(eye_dir, 1.0)).xyz; + //eye_dir = normalize(eye_dir); + + //float round_x = gi_scale.x; + //float round_y = gi_scale.y; + + vec3 debug = texture2D(normalGIMap, gi_c.xy).rgb*0.5+0.5; + debug.xz = vec2(0.0,0.0); + //debug = fract(debug); + + float round_x = 1.0/64.0; + float round_y = 1.0/64.0; + + //gi_c.x = floor(gi_c.x/round_x+0.5)*round_x; + //gi_c.y = floor(gi_c.y/round_y+0.5)*round_y; + + float fda = 0.0; + vec3 fdiff = vec3(0,0,0); + + vec3 rcol = vec3(0,0,0); + + float fsa = 0.0; + + for (int i = -1; i < 2; i+=2 ) + { + for (int j = -1; j < 2; j+=2) + { + vec2 tc = vec2(i, j)*0.75; + vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0+tc*0.5).xyz; + //tc += gi_norm.xy*nz.z; + tc += nz.xy*2.0; + tc /= gi_samples; + tc += gi_c.xy; + + vec3 lnorm = -normalize(texture2D(normalGIMap, tc.xy).xyz*2.0-1.0); + vec3 lpos = getGIPosition(tc.xy).xyz; + + vec3 at = lpos-gi_pos.xyz; + float dist = dot(at,at); + float da = clamp(1.0/(gi_spec.x*dist), 0.0, 1.0); + + if (da > 0.0) + { + //add angular attenuation + vec3 ldir = at; + float ang_atten = clamp(dot(ldir, gi_norm), 0.0, 1.0); + + float ld = -dot(ldir, lnorm); + + if (ang_atten > 0.0 && ld < 0.0) + { + vec3 diff = texture2D(diffuseGIMap, tc.xy).xyz; + da = da*ang_atten; + fda += da; + fdiff += diff*da; + } + } + } + } + + fdiff /= max(gi_spec.y*fda, gi_quad.z); + fdiff = clamp(fdiff, vec3(0), vec3(1)); + + vec3 ret = fda*fdiff; + //ret = ret*ret*gi_quad.x+ret*gi_quad.y+gi_quad.z; + + //fda *= nz.z; + + //rcol.rgb *= gi_intensity; + //return rcol.rgb+vary_AmblitColor.rgb*0.25; + //return vec4(debug, 0.0); + //return vec4(fda*fdiff, 0.0); + return clamp(ret,vec3(0.0), vec3(1.0)); + //return debug.xyz; +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + vec4 pos = getPosition(pos_screen); + vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; + + gl_FragData[0].xyz = giAmbient(pos, norm); +} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/giV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/giV.glsl new file mode 100644 index 0000000..71dcea9 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/giV.glsl @@ -0,0 +1,22 @@ +/** + * @file giV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + gl_FrontColor = gl_Color; +} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl new file mode 100644 index 0000000..e8b53b0 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl @@ -0,0 +1,15 @@ +/** + * @file luminanceF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2DRect diffuseMap; + +varying vec2 vary_fragcoord; + +void main() +{ + gl_FragColor = texture2DRect(diffuseMap, vary_fragcoord.xy); +} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl new file mode 100644 index 0000000..db8775f --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl @@ -0,0 +1,20 @@ +/** + * @file giV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; + + gl_FrontColor = gl_Color; +} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index 3689d12..ce0494c 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -7,13 +7,15 @@ #extension GL_ARB_texture_rectangle : enable +uniform sampler2DRect depthMap; uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; -uniform sampler2DRect positionMap; uniform sampler2DRect normalMap; uniform samplerCube environmentMap; uniform sampler2DRect lightMap; uniform sampler2D noiseMap; +uniform sampler2D lightFunc; + uniform vec3 env_mat[3]; uniform float sun_wash; @@ -23,24 +25,48 @@ uniform int light_count; uniform vec4 light[16]; uniform vec4 light_col[16]; -varying vec3 vary_fragcoord; +varying vec4 vary_fragcoord; uniform vec2 screen_res; +uniform float far_z; + +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + void main() { vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res; - vec3 pos = texture2DRect(positionMap, frag.xy).xyz; - vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz); + vec3 pos = getPosition(frag.xy).xyz; + if (pos.z < far_z) + { + discard; + } + + vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz*2.0-1.0); vec4 spec = texture2DRect(specularRect, frag.xy); vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb; float noise = texture2D(noiseMap, frag.xy/128.0).b; vec3 out_col = vec3(0,0,0); + vec3 npos = normalize(-pos); for (int i = 0; i < light_count; ++i) { vec3 lv = light[i].xyz-pos; float dist2 = dot(lv,lv); - if (dist2 > light[i].w) + dist2 /= light[i].w; + if (dist2 > 1.0) { continue; } @@ -55,29 +81,41 @@ void main() da = dot(norm, lv); float fa = light_col[i].a+1.0; - float dist_atten = clamp(1.0-(dist2-light[i].w*(1.0-fa))/(light[i].w*fa), 0.0, 1.0); + float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); dist_atten *= noise; float lit = da * dist_atten; vec3 col = light_col[i].rgb*lit*diff; + //vec3 col = vec3(dist2, light_col[i].a, lit); if (spec.a > 0.0) { - vec3 ref = reflect(normalize(pos), norm); - float sa = dot(ref,lv); - sa = max(sa, 0.0); - sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*light_col[i].rgb*spec.rgb; + //vec3 ref = dot(pos+lv, norm); + + float sa = dot(normalize(lv+npos),norm); + + if (sa > 0) + { + sa = texture2D(lightFunc,vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); + sa *= noise; + col += da*sa*light_col[i].rgb*spec.rgb; + } } out_col += col; } + if (dot(out_col, out_col) <= 0.0) + { + discard; + } + //attenuate point light contribution by SSAO component out_col *= texture2DRect(lightMap, frag.xy).g; gl_FragColor.rgb = out_col; gl_FragColor.a = 0.0; + + //gl_FragColor = vec4(0.1, 0.025, 0.025/4.0, 0.0); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl new file mode 100644 index 0000000..021e8a2 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -0,0 +1,184 @@ +/** + * @file multiSpotLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; +uniform sampler2DRect lightMap; +uniform sampler2D noiseMap; +uniform sampler2D lightFunc; +uniform sampler2D projectionMap; + +uniform mat4 proj_mat; //screen space to light space +uniform float proj_near; //near clip for projection +uniform vec3 proj_p; //plane projection is emitting from (in screen space) +uniform vec3 proj_n; +uniform float proj_focus; //distance from plane to begin blurring +uniform float proj_lod; //(number of mips in proj map) +uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambient_lod; +uniform float proj_ambiance; +uniform float near_clip; +uniform float far_clip; + +uniform vec3 proj_origin; //origin of projection to be used for angular attenuation +uniform float sun_wash; +uniform int proj_shadow_idx; +uniform float shadow_fade; + +varying vec4 vary_light; + +varying vec4 vary_fragcoord; +uniform vec2 screen_res; + +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +void main() +{ + vec4 frag = vary_fragcoord; + frag.xyz /= frag.w; + frag.xyz = frag.xyz*0.5+0.5; + frag.xy *= screen_res; + + vec3 pos = getPosition(frag.xy).xyz; + vec3 lv = vary_light.xyz-pos.xyz; + float dist2 = dot(lv,lv); + dist2 /= vary_light.w; + if (dist2 > 1.0) + { + discard; + } + + float shadow = 1.0; + + if (proj_shadow_idx >= 0) + { + vec4 shd = texture2DRect(lightMap, frag.xy); + float sh[2]; + sh[0] = shd.b; + sh[1] = shd.a; + shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); + } + + vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + + norm = normalize(norm); + float l_dist = -dot(lv, proj_n); + + vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); + if (proj_tc.z < 0.0) + { + discard; + } + + proj_tc.xyz /= proj_tc.w; + + float fa = gl_Color.a+1.0; + float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + lv = proj_origin-pos.xyz; + lv = normalize(lv); + float da = dot(norm, lv); + + vec3 col = vec3(0,0,0); + + vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; + + float noise = texture2D(noiseMap, frag.xy/128.0).b; + if (proj_tc.z > 0.0 && + proj_tc.x < 1.0 && + proj_tc.y < 1.0 && + proj_tc.x > 0.0 && + proj_tc.y > 0.0) + { + float lit = 0.0; + float amb_da = proj_ambiance; + + if (da > 0.0) + { + float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); + float lod = diff * proj_lod; + + vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + + vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; + + lit = da * dist_atten * noise; + + col = lcol*lit*diff_tex*shadow; + amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; + } + + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_ambient_lod); + + amb_da += (da*da*0.5+0.5)*proj_ambiance; + + amb_da *= dist_atten * noise; + + amb_da = min(amb_da, 1.0-lit); + + col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + } + + + vec4 spec = texture2DRect(specularRect, frag.xy); + if (spec.a > 0.0) + { + vec3 ref = reflect(normalize(pos), norm); + + //project from point pos in direction ref to plane proj_p, proj_n + vec3 pdelta = proj_p-pos; + float ds = dot(ref, proj_n); + + if (ds < 0.0) + { + vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; + + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); + + if (stc.z > 0.0) + { + stc.xy /= stc.w; + + if (stc.x < 1.0 && + stc.y < 1.0 && + stc.x > 0.0 && + stc.y > 0.0) + { + vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow; + } + } + } + } + + //attenuate point light contribution by SSAO component + col *= texture2DRect(lightMap, frag.xy).g; + + gl_FragColor.rgb = col; + gl_FragColor.a = 0.0; +} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 52bad1f..d8ccfd4 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -9,33 +9,54 @@ uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; -uniform sampler2DRect positionMap; uniform sampler2DRect normalMap; uniform samplerCube environmentMap; uniform sampler2DRect lightMap; uniform sampler2D noiseMap; +uniform sampler2D lightFunc; +uniform sampler2DRect depthMap; uniform vec3 env_mat[3]; uniform float sun_wash; varying vec4 vary_light; -varying vec3 vary_fragcoord; +varying vec4 vary_fragcoord; uniform vec2 screen_res; +uniform mat4 inv_proj; +uniform vec4 viewport; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = (pos_screen.xy-viewport.xy)*2.0; + sc /= viewport.zw; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + void main() { - vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - frag *= screen_res; - vec3 pos = texture2DRect(positionMap, frag).xyz; + vec4 frag = vary_fragcoord; + frag.xyz /= frag.w; + frag.xyz = frag.xyz*0.5+0.5; + frag.xy *= screen_res; + + vec3 pos = getPosition(frag.xy).xyz; vec3 lv = vary_light.xyz-pos; float dist2 = dot(lv,lv); - if (dist2 > vary_light.w) + dist2 /= vary_light.w; + if (dist2 > 1.0) { discard; } - vec3 norm = texture2DRect(normalMap, frag).xyz; + vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; float da = dot(norm, lv); if (da < 0.0) { @@ -46,24 +67,30 @@ void main() lv = normalize(lv); da = dot(norm, lv); - float noise = texture2D(noiseMap, frag/128.0).b; + float noise = texture2D(noiseMap, frag.xy/128.0).b; - vec3 col = texture2DRect(diffuseRect, frag).rgb; + vec3 col = texture2DRect(diffuseRect, frag.xy).rgb; float fa = gl_Color.a+1.0; - float dist_atten = clamp(1.0-(dist2-vary_light.w*(1.0-fa))/(vary_light.w*fa), 0.0, 1.0); + float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); float lit = da * dist_atten * noise; col = gl_Color.rgb*lit*col; - vec4 spec = texture2DRect(specularRect, frag); + vec4 spec = texture2DRect(specularRect, frag.xy); if (spec.a > 0.0) { - vec3 ref = reflect(normalize(pos), norm); - float sa = dot(ref,lv); - sa = max(sa, 0.0); - sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*gl_Color.rgb*spec.rgb; + float sa = dot(normalize(lv-normalize(pos)),norm); + if (sa > 0.0) + { + sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); + sa *= noise; + col += da*sa*gl_Color.rgb*spec.rgb; + } + } + + if (dot(col, col) <= 0.0) + { + discard; } //attenuate point light contribution by SSAO component diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl index a4edb88..e815ca2 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl @@ -6,7 +6,7 @@ */ varying vec4 vary_light; -varying vec3 vary_fragcoord; +varying vec4 vary_fragcoord; uniform vec2 screen_res; uniform float near_clip; @@ -14,10 +14,10 @@ uniform float near_clip; void main() { //transform vertex - gl_Position = ftransform(); + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); + vary_fragcoord = pos; vec4 tex = gl_MultiTexCoord0; tex.w = 1.0; diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl new file mode 100644 index 0000000..71de036 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl @@ -0,0 +1,57 @@ +/** + * @file postDeferredF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect localLightMap; +uniform sampler2DRect sunLightMap; +uniform sampler2DRect giLightMap; +uniform sampler2D luminanceMap; +uniform sampler2DRect lightMap; + +uniform vec3 lum_quad; +uniform float lum_lod; +uniform vec4 ambient; + +uniform vec3 gi_quad; + +uniform vec2 screen_res; +varying vec2 vary_fragcoord; + +void main() +{ + vec2 tc = vary_fragcoord.xy; + vec3 lum = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb; + float luminance = lum.r; + luminance = luminance*lum_quad.y+lum_quad.z; + + vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); + + float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g; + + vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; + gi_col = gi_col*gi_col*gi_quad.x + gi_col*gi_quad.y+gi_quad.z*ambocc*ambient.rgb; + gi_col *= diff; + + vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy); + + vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb; + + + sun_col *= 1.0/min(luminance, 1.0); + gi_col *= 1.0/luminance; + + vec3 col = sun_col.rgb+gi_col+local_col; + + gl_FragColor.rgb = col.rgb; + col.rgb = max(col.rgb-vec3(1.0,1.0,1.0), vec3(0.0, 0.0, 0.0)); + + gl_FragColor.a = 0.0; // max(dot(col.rgb,col.rgb)*lum_quad.x, sun_col.a); + + //gl_FragColor.rgb = vec3(lum_lod); +} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl new file mode 100644 index 0000000..9819232 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl @@ -0,0 +1,17 @@ +/** + * @file postDeferredV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl new file mode 100644 index 0000000..3556c7b --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl @@ -0,0 +1,107 @@ +/** + * @file postgiF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseGIMap; +uniform sampler2D normalGIMap; +uniform sampler2D depthGIMap; +uniform sampler2D diffuseMap; + +uniform sampler2D lastDiffuseGIMap; +uniform sampler2D lastNormalGIMap; +uniform sampler2D lastMinpGIMap; +uniform sampler2D lastMaxpGIMap; + +uniform float gi_blend; + +uniform mat4 gi_mat; //gPipeline.mGIMatrix - eye space to sun space +uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space +uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix +uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space +uniform float gi_radius; +uniform float gi_intensity; +uniform vec2 gi_kern[16]; +uniform vec2 gi_scale; + + +vec4 getGIPosition(vec2 gi_tc) +{ + float depth = texture2D(depthGIMap, gi_tc).a; + vec2 sc = gi_tc*2.0; + sc -= vec2(1.0, 1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = gi_inv_proj*ndc; + pos.xyz /= pos.w; + pos.w = 1.0; + return pos; +} + + +void main() +{ + vec2 c_tc = gl_TexCoord[0].xy; + + vec3 diff = vec3(0,0,0); + vec3 minp = vec3(1024,1024,1024); + vec3 maxp = vec3(-1024,-1024,-1024); + vec3 norm = vec3(0,0,0); + + float dweight = 0.0; + + vec3 cnorm = normalize(texture2D(normalGIMap, c_tc).rgb*2.0-1.0); + + vec3 cpos = vec3(0,0,0); + float tweight = 0.0; + + for (int i = 0; i < 8; ++i) + { + for (int j = 0; j < 8; ++j) + { + vec2 tc = vec2(i-4+0.5, j-4+0.5); + float weight = 1.0-length(tc)/6.0; + tc *= 1.0/(256.0); + tc += c_tc; + + vec3 n = texture2D(normalGIMap, tc).rgb*2.0-1.0; + tweight += weight; + + diff += weight*texture2D(diffuseGIMap, tc).rgb; + + norm += n*weight; + + dweight += dot(n, cnorm); + + vec3 pos = getGIPosition(tc).xyz; + cpos += pos*weight; + + minp = min(pos, minp); + maxp = max(pos, maxp); + } + } + + dweight = abs(1.0-dweight/64.0); + float mind = min(sqrt(dweight+0.5), 1.0); + + dweight *= dweight; + + cpos /= tweight; + + diff = clamp(diff/tweight, vec3(1.0/2.2), vec3(1,1,1)); + norm = normalize(norm); + maxp = cpos; + minp = vec3(dweight, mind, cpos.z-minp.z); + + //float blend = 1.0; + //diff = mix(texture2D(lastDiffuseGIMap, c_tc).rgb, diff, blend); + //norm = mix(texture2D(lastNormalGIMap, c_tc).rgb, norm, blend); + //maxp = mix(texture2D(lastMaxpGIMap, c_tc).rgb, maxp, blend); + //minp = mix(texture2D(lastMinpGIMap, c_tc).rgb, minp, blend); + + gl_FragData[0].rgb = diff; + gl_FragData[2].xyz = normalize(norm); + gl_FragData[1].xyz = maxp; + gl_FragData[3].xyz = minp; +} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl new file mode 100644 index 0000000..5a8eb65 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl @@ -0,0 +1,16 @@ +/** + * @file postgiV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec3 vary_normal; + +void main() +{ + //transform vertex + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_Position = pos; + gl_TexCoord[0].xy = pos.xy*0.5+0.5; +} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl index b3758c3..b0b31fd 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl @@ -7,8 +7,11 @@ uniform sampler2D diffuseMap; +varying vec4 post_pos; void main() { gl_FragColor = vec4(1,1,1,texture2D(diffuseMap, gl_TexCoord[0].xy).a * gl_Color.a); + + gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl index aae1bee..7214d24 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl @@ -5,13 +5,17 @@ * $License$ */ +varying vec4 post_pos; + void main() { //transform vertex vec4 pos = gl_ModelViewProjectionMatrix*gl_Vertex; - //smash geometry against the near clip plane (great for ortho projections) - pos.z = max(pos.z, -1.0); - gl_Position = pos; + + post_pos = pos; + + gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; gl_FrontColor = gl_Color; } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index d5671a6..64e263a 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -272,8 +272,4 @@ void main() gl_FragColor.rgb = col; gl_FragColor.a = 0.0; - //gl_FragColor.rg = scol_ambocc.rg; - //gl_FragColor.rgb = norm.rgb*0.5+0.5; - //gl_FragColor.rgb = vec3(ambocc); - //gl_FragColor.rgb = vec3(scol); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl new file mode 100644 index 0000000..d653408 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -0,0 +1,199 @@ +/** + * @file spotLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; +uniform sampler2DRect lightMap; +uniform sampler2D noiseMap; +uniform sampler2D lightFunc; +uniform sampler2D projectionMap; + +uniform mat4 proj_mat; //screen space to light space +uniform float proj_near; //near clip for projection +uniform vec3 proj_p; //plane projection is emitting from (in screen space) +uniform vec3 proj_n; +uniform float proj_focus; //distance from plane to begin blurring +uniform float proj_lod; //(number of mips in proj map) +uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambiance; +uniform float near_clip; +uniform float far_clip; + +uniform vec3 proj_origin; //origin of projection to be used for angular attenuation +uniform float sun_wash; +uniform int proj_shadow_idx; +uniform float shadow_fade; + +varying vec4 vary_light; + +varying vec4 vary_fragcoord; +uniform vec2 screen_res; + +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +void main() +{ + vec4 frag = vary_fragcoord; + frag.xyz /= frag.w; + frag.xyz = frag.xyz*0.5+0.5; + frag.xy *= screen_res; + + float shadow = 1.0; + + if (proj_shadow_idx >= 0) + { + vec4 shd = texture2DRect(lightMap, frag.xy); + float sh[2]; + sh[0] = shd.b; + sh[1] = shd.a; + shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); + } + + vec3 pos = getPosition(frag.xy).xyz; + vec3 lv = vary_light.xyz-pos.xyz; + float dist2 = dot(lv,lv); + dist2 /= vary_light.w; + if (dist2 > 1.0) + { + discard; + } + + vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + + norm = normalize(norm); + float l_dist = -dot(lv, proj_n); + + vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); + if (proj_tc.z < 0.0) + { + discard; + } + + proj_tc.xyz /= proj_tc.w; + + float fa = gl_Color.a+1.0; + float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + lv = proj_origin-pos.xyz; + lv = normalize(lv); + float da = dot(norm, lv); + + vec3 col = vec3(0,0,0); + + vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; + + float noise = texture2D(noiseMap, frag.xy/128.0).b; + if (proj_tc.z > 0.0 && + proj_tc.x < 1.0 && + proj_tc.y < 1.0 && + proj_tc.x > 0.0 && + proj_tc.y > 0.0) + { + float lit = 0.0; + if (da > 0.0) + { + float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); + float lod = diff * proj_lod; + + vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + + vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; + + lit = da * dist_atten * noise; + + col = lcol*lit*diff_tex*shadow; + } + + float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + float lod = diff * proj_lod; + vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); + float amb_da = proj_ambiance; + if (da > 0.0) + { + amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; + } + + amb_da += (da*da*0.5+0.5)*proj_ambiance; + + amb_da *= dist_atten * noise; + + amb_da = min(amb_da, 1.0-lit); + + col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + } + + + vec4 spec = texture2DRect(specularRect, frag.xy); + if (spec.a > 0.0) + { + vec3 ref = reflect(normalize(pos), norm); + + //project from point pos in direction ref to plane proj_p, proj_n + vec3 pdelta = proj_p-pos; + float ds = dot(ref, proj_n); + + if (ds < 0.0) + { + vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; + + vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; + + if (stc.z > 0.0) + { + stc.xy /= stc.z+proj_near; + + if (stc.x < 1.0 && + stc.y < 1.0 && + stc.x > 0.0 && + stc.y > 0.0) + { + vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow; + } + } + } + } + + /*if (spec.a > 0.0) + { + //vec3 ref = reflect(normalize(pos), norm); + float sa = dot(normalize(lv-normalize(pos)),norm);; + //sa = max(sa, 0.0); + //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); + sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); + sa *= noise; + col += da*sa*lcol*spec.rgb; + }*/ + + //attenuate point light contribution by SSAO component + col *= texture2DRect(lightMap, frag.xy).g; + + + gl_FragColor.rgb = col; + gl_FragColor.a = 0.0; +} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl index d43fe6c..22bdd2c 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl @@ -7,17 +7,21 @@ #extension GL_ARB_texture_rectangle : enable -uniform sampler2DRect positionMap; -uniform sampler2DRect normalMap; uniform sampler2DRect depthMap; -uniform sampler2DShadow shadowMap0; -uniform sampler2DShadow shadowMap1; -uniform sampler2DShadow shadowMap2; -uniform sampler2DShadow shadowMap3; +uniform sampler2DRect normalMap; +uniform sampler2DRectShadow shadowMap0; +uniform sampler2DRectShadow shadowMap1; +uniform sampler2DRectShadow shadowMap2; +uniform sampler2DRectShadow shadowMap3; +uniform sampler2DRectShadow shadowMap4; +uniform sampler2DRectShadow shadowMap5; uniform sampler2D noiseMap; +uniform sampler2D lightFunc; + + // Inputs -uniform mat4 shadow_matrix[4]; +uniform mat4 shadow_matrix[6]; uniform vec4 shadow_clip; uniform float ssao_radius; uniform float ssao_max_radius; @@ -27,6 +31,25 @@ uniform float ssao_factor_inv; varying vec2 vary_fragcoord; varying vec4 vary_light; +uniform mat4 inv_proj; +uniform vec2 screen_res; + +uniform float shadow_bias; +uniform float shadow_offset; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + //calculate decreases in ambient lighting when crowded out (SSAO) float calcAmbientOcclusion(vec4 pos, vec3 norm) { @@ -54,7 +77,7 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) for (int i = 0; i < 8; i++) { vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); - vec3 samppos_world = texture2DRect(positionMap, samppos_screen).xyz; + vec3 samppos_world = getPosition(samppos_screen).xyz; vec3 diff = pos_world - samppos_world; float dist2 = dot(diff, diff); @@ -74,14 +97,18 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); - return 1.0 - (float(points != 0) * angle_hidden); + return (1.0 - (float(points != 0) * angle_hidden)); } void main() { vec2 pos_screen = vary_fragcoord.xy; - vec4 pos = vec4(texture2DRect(positionMap, pos_screen).xyz, 1.0); - vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + + //try doing an unproject here + + vec4 pos = getPosition(pos_screen); + + vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL { @@ -90,35 +117,45 @@ void main() }*/ float shadow = 1.0; - float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); + float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); + vec4 spos = vec4(pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias), 1.0); + + //vec3 debug = vec3(0,0,0); + if (dp_directional_light == 0.0) { // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup shadow = 0.0; } - else if (pos.z > -shadow_clip.w) + else if (spos.z > -shadow_clip.w) { - if (pos.z < -shadow_clip.z) + vec4 lpos; + + if (spos.z < -shadow_clip.z) { - vec4 lpos = shadow_matrix[3]*pos; - shadow = shadow2DProj(shadowMap3, lpos).x; + lpos = shadow_matrix[3]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap3, lpos).x; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } - else if (pos.z < -shadow_clip.y) + else if (spos.z < -shadow_clip.y) { - vec4 lpos = shadow_matrix[2]*pos; - shadow = shadow2DProj(shadowMap2, lpos).x; + lpos = shadow_matrix[2]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap2, lpos).x; } - else if (pos.z < -shadow_clip.x) + else if (spos.z < -shadow_clip.x) { - vec4 lpos = shadow_matrix[1]*pos; - shadow = shadow2DProj(shadowMap1, lpos).x; + lpos = shadow_matrix[1]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap1, lpos).x; } else { - vec4 lpos = shadow_matrix[0]*pos; - shadow = shadow2DProj(shadowMap0, lpos).x; + lpos = shadow_matrix[0]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap0, lpos).x; } // take the most-shadowed value out of these two: @@ -126,6 +163,17 @@ void main() // * an unblurred dot product between the sun and this norm // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting shadow = min(shadow, dp_directional_light); + + /*debug.r = lpos.y / (lpos.w*screen_res.y); + + lpos.xy /= lpos.w*32.0; + if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1) + { + debug.gb = vec2(0.5, 0.5); + } + + debug += (1.0-shadow)*0.5;*/ + } else { @@ -135,5 +183,18 @@ void main() gl_FragColor[0] = shadow; gl_FragColor[1] = calcAmbientOcclusion(pos, norm); - //gl_FragColor[2] is unused as of August 2008, may be used for debugging + + //spotlight shadow 1 + vec4 lpos = shadow_matrix[4]*spos; + lpos.xy *= screen_res; + gl_FragColor[2] = shadow2DRectProj(shadowMap4, lpos).x; + + //spotlight shadow 2 + lpos = shadow_matrix[5]*spos; + lpos.xy *= screen_res; + gl_FragColor[3] = shadow2DRectProj(shadowMap5, lpos).x; + + //gl_FragColor.rgb = pos.xyz; + //gl_FragColor.b = shadow; + //gl_FragColor.rgb = debug; } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index 211b2e0..308b9b1 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -12,7 +12,6 @@ uniform sampler2D detail_3; uniform sampler2D alpha_ramp; varying vec3 vary_normal; -varying vec4 vary_position; void main() { @@ -28,9 +27,8 @@ void main() float alphaFinal = texture2D(alpha_ramp, gl_TexCoord[1].zw).a; vec4 outColor = mix( mix(color3, color2, alpha2), mix(color1, color0, alpha1), alphaFinal ); - gl_FragData[0] = vec4(outColor.rgb, 1.0); + gl_FragData[0] = vec4(outColor.rgb, 0.0); // Kl 0.0 looks fine atm however check grass above waterline when GI enabled in future releases! gl_FragData[1] = vec4(outColor.rgb*0.2, 0.2); - gl_FragData[2] = vec4(normalize(vary_normal), 0.0); - gl_FragData[3] = vary_position; + gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl index e9d6dca..3038b14 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl @@ -6,7 +6,6 @@ */ varying vec3 vary_normal; -varying vec4 vary_position; vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1) { @@ -27,7 +26,6 @@ void main() //transform vertex gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_position = gl_ModelViewMatrix * gl_Vertex; vary_normal = normalize(gl_NormalMatrix * gl_Normal); // Transform and pass tex coords diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index bc2c981..49c65f1 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -8,13 +8,11 @@ uniform sampler2D diffuseMap; varying vec3 vary_normal; -varying vec4 vary_position; void main() { vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); gl_FragData[0] = gl_Color*col; gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal), 0.0); - gl_FragData[3] = vary_position; + gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl index 9131d7c..6b9dc2d 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl @@ -6,7 +6,6 @@ */ varying vec3 vary_normal; -varying vec4 vary_position; void main() { @@ -14,8 +13,6 @@ void main() gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vary_position = gl_ModelViewMatrix * gl_Vertex; - vary_normal = normalize(gl_NormalMatrix * gl_Normal); gl_FrontColor = gl_Color; diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index 0a1f019..6eea656 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -17,7 +17,7 @@ uniform sampler2DShadow shadowMap2; uniform sampler2DShadow shadowMap3; uniform sampler2D noiseMap; -uniform mat4 shadow_matrix[4]; +uniform mat4 shadow_matrix[6]; uniform vec4 shadow_clip; uniform float sunAngle; diff --git a/linden/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl b/linden/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl new file mode 100644 index 0000000..623ef7a --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl @@ -0,0 +1,31 @@ +/** + * @file colorFilterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2DRect RenderTexture; +uniform float brightness; +uniform float contrast; +uniform vec3 contrastBase; +uniform float saturation; +uniform vec3 lumWeights; + +const float gamma = 2.0; + +void main(void) +{ + vec3 color = vec3(texture2DRect(RenderTexture, gl_TexCoord[0].st)); + + /// Modulate brightness + color *= brightness; + + /// Modulate contrast + color = mix(contrastBase, color, contrast); + + /// Modulate saturation + color = mix(vec3(dot(color, lumWeights)), color, saturation); + + gl_FragColor = vec4(color, 1.0); +} diff --git a/linden/indra/newview/app_settings/shaders/class1/effects/drawQuadV.glsl b/linden/indra/newview/app_settings/shaders/class1/effects/drawQuadV.glsl new file mode 100644 index 0000000..29c2a09 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/effects/drawQuadV.glsl @@ -0,0 +1,14 @@ +/** + * @file drawQuadV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +void main(void) +{ + //transform vertex + gl_Position = ftransform(); + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[1] = gl_MultiTexCoord1; +} diff --git a/linden/indra/newview/app_settings/shaders/class1/effects/nightVisionF.glsl b/linden/indra/newview/app_settings/shaders/class1/effects/nightVisionF.glsl new file mode 100644 index 0000000..271d5cf --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/effects/nightVisionF.glsl @@ -0,0 +1,42 @@ +/** + * @file nightVisionF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2DRect RenderTexture; +uniform sampler2D NoiseTexture; +uniform float brightMult; +uniform float noiseStrength; + +float luminance(vec3 color) +{ + /// CALCULATING LUMINANCE (Using NTSC lum weights) + /// http://en.wikipedia.org/wiki/Luma_%28video%29 + return dot(color, vec3(0.299, 0.587, 0.114)); +} + +void main(void) +{ + /// Get scene color + vec3 color = vec3(texture2DRect(RenderTexture, gl_TexCoord[0].st)); + + /// Extract luminance and scale up by night vision brightness + float lum = luminance(color) * brightMult; + + /// Convert into night vision color space + /// Newer NVG colors (crisper and more saturated) + vec3 outColor = (lum * vec3(0.91, 1.21, 0.9)) + vec3(-0.07, 0.1, -0.12); + + /// Add noise + float noiseValue = texture2D(NoiseTexture, gl_TexCoord[1].st).r; + noiseValue = (noiseValue - 0.5) * noiseStrength; + + /// Older NVG colors (more muted) + // vec3 outColor = (lum * vec3(0.82, 0.75, 0.83)) + vec3(0.05, 0.32, -0.11); + + outColor += noiseValue; + + gl_FragColor = vec4(outColor, 1.0); +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl new file mode 100644 index 0000000..0055a73 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -0,0 +1,112 @@ +/** + * @file alphaF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2D diffuseMap; +uniform sampler2DRectShadow shadowMap0; +uniform sampler2DRectShadow shadowMap1; +uniform sampler2DRectShadow shadowMap2; +uniform sampler2DRectShadow shadowMap3; +uniform sampler2D noiseMap; +uniform sampler2DRect depthMap; + +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform vec2 screen_res; + +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_fragcoord; +varying vec3 vary_position; +varying vec3 vary_light; + +uniform float alpha_soften; + +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +void main() +{ + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; + frag *= screen_res; + + vec3 samp_pos = getPosition(frag).xyz; + + float shadow = 1.0; + vec4 pos = vec4(vary_position, 1.0); + + vec4 spos = pos; + + if (spos.z > -shadow_clip.w) + { + vec4 lpos; + + if (spos.z < -shadow_clip.z) + { + lpos = shadow_matrix[3]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap3, lpos).x; + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + else if (spos.z < -shadow_clip.y) + { + lpos = shadow_matrix[2]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap2, lpos).x; + } + else if (spos.z < -shadow_clip.x) + { + lpos = shadow_matrix[1]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap1, lpos).x; + } + else + { + lpos = shadow_matrix[0]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap0, lpos).x; + } + } + + vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a); + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col; + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + if (samp_pos.z != 0.0) + { + float dist_factor = alpha_soften; + float a = gl_Color.a; + a *= a; + dist_factor *= 1.0/(1.0-a); + color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); + } + + //gl_FragColor = gl_Color; + gl_FragColor = color; + //gl_FragColor = vec4(1,0,1,1)*shadow; + +} + diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl new file mode 100644 index 0000000..ab60b65 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl @@ -0,0 +1,75 @@ +/** + * @file alphaV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +void calcAtmospherics(vec3 inPositionEye); + +float calcDirectionalLight(vec3 n, vec3 l); +float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); + +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_fragcoord; +varying vec3 vary_position; +varying vec3 vary_light; + +uniform float near_clip; +uniform float shadow_offset; +uniform float shadow_bias; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vec4 pos = (gl_ModelViewMatrix * gl_Vertex); + vec3 norm = normalize(gl_NormalMatrix * gl_Normal); + + vary_position = vec4(pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias), 1.0); + + calcAtmospherics(pos.xyz); + + //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); + vec4 col; + col.a = gl_Color.a; + + // Add windlight lights + col.rgb = atmosAmbient(vec3(0.)); + col.rgb = scaleUpLight(col.rgb); + + // Collect normal lights (need to be divided by two, as we later multiply by 2) + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); + col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); + col.rgb = scaleDownLight(col.rgb); + + vary_light = gl_LightSource[0].position.xyz; + + vary_ambient = col.rgb*gl_Color.rgb; + vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); + + col.rgb = min(col.rgb*gl_Color.rgb, 1.0); + + gl_FrontColor = col; + + gl_FogFragCoord = pos.z; + + pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); + +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl new file mode 100644 index 0000000..fe83c3c --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl @@ -0,0 +1,77 @@ +/** + * @file avatarAlphaF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; +uniform sampler2DRectShadow shadowMap0; +uniform sampler2DRectShadow shadowMap1; +uniform sampler2DRectShadow shadowMap2; +uniform sampler2DRectShadow shadowMap3; +uniform sampler2D noiseMap; + +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform vec2 screen_res; + +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec4 vary_position; +varying vec3 vary_normal; + +void main() +{ + float shadow = 1.0; + vec4 pos = vary_position; + vec3 norm = normalize(vary_normal); + + vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; + + vec4 spos = pos; + + if (spos.z > -shadow_clip.w) + { + vec4 lpos; + + if (spos.z < -shadow_clip.z) + { + lpos = shadow_matrix[3]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap3, lpos).x; + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + else if (spos.z < -shadow_clip.y) + { + lpos = shadow_matrix[2]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap2, lpos).x; + } + else if (spos.z < -shadow_clip.x) + { + lpos = shadow_matrix[1]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap1, lpos).x; + } + else + { + lpos = shadow_matrix[0]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap0, lpos).x; + } + } + + + vec4 col = vec4(vary_ambient + vary_directional*shadow, gl_Color.a); + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col; + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + gl_FragColor = color; +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl new file mode 100644 index 0000000..c1988d3 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -0,0 +1,78 @@ +/** + * @file avatarAlphaV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +mat4 getSkinnedTransform(); +void calcAtmospherics(vec3 inPositionEye); + +float calcDirectionalLight(vec3 n, vec3 l); +float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); + +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +varying vec4 vary_position; +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_normal; + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + + vec4 pos; + vec3 norm; + + mat4 trans = getSkinnedTransform(); + pos.x = dot(trans[0], gl_Vertex); + pos.y = dot(trans[1], gl_Vertex); + pos.z = dot(trans[2], gl_Vertex); + pos.w = 1.0; + + norm.x = dot(trans[0].xyz, gl_Normal); + norm.y = dot(trans[1].xyz, gl_Normal); + norm.z = dot(trans[2].xyz, gl_Normal); + norm = normalize(norm); + + gl_Position = gl_ProjectionMatrix * pos; + vary_position = pos; + vary_normal = norm; + + calcAtmospherics(pos.xyz); + + //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); + vec4 col; + col.a = gl_Color.a; + + // Add windlight lights + col.rgb = atmosAmbient(vec3(0.)); + col.rgb = scaleUpLight(col.rgb); + + // Collect normal lights (need to be divided by two, as we later multiply by 2) + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); + col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); + col.rgb = scaleDownLight(col.rgb); + + vary_ambient = col.rgb*gl_Color.rgb; + vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); + + col.rgb = min(col.rgb*gl_Color.rgb, 1.0); + + gl_FrontColor = col; + + gl_FogFragCoord = pos.z; + +} + + diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl new file mode 100644 index 0000000..1713fe9 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl @@ -0,0 +1,71 @@ +/** + * @file blurLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2DRect lightMap; + +uniform float dist_factor; +uniform float blur_size; +uniform vec2 delta; +uniform vec3 kern[32]; +uniform int kern_length; +uniform float kern_scale; + +varying vec2 vary_fragcoord; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +void main() +{ + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + vec3 pos = getPosition(vary_fragcoord.xy).xyz; + vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba; + + vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); + + dlt /= max(-pos.z*dist_factor, 1.0); + + vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' + vec4 col = defined_weight.xyxx * ccol; + + for (int i = 1; i < kern_length; i++) + { + vec2 tc = vary_fragcoord.xy + kern[i].z*dlt; + vec3 samppos = getPosition(tc).xyz; + float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane + if (d*d <= 0.003) + { + col += texture2DRect(lightMap, tc)*kern[i].xyxx; + defined_weight += kern[i].xy; + } + } + + + + col /= defined_weight.xyxx; + + gl_FragColor = col; + + //gl_FragColor = ccol; +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl new file mode 100644 index 0000000..b7f07e5 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl @@ -0,0 +1,17 @@ +/** + * @file blurLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl new file mode 100644 index 0000000..6519594 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -0,0 +1,188 @@ +/** + * @file multiSpotLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; +uniform sampler2DRect lightMap; +uniform sampler2D noiseMap; +uniform sampler2D lightFunc; +uniform sampler2D projectionMap; + +uniform mat4 proj_mat; //screen space to light space +uniform float proj_near; //near clip for projection +uniform vec3 proj_p; //plane projection is emitting from (in screen space) +uniform vec3 proj_n; +uniform float proj_focus; //distance from plane to begin blurring +uniform float proj_lod; //(number of mips in proj map) +uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambient_lod; +uniform float proj_ambiance; +uniform float near_clip; +uniform float far_clip; + +uniform vec3 proj_origin; //origin of projection to be used for angular attenuation +uniform float sun_wash; +uniform int proj_shadow_idx; +uniform float shadow_fade; + +varying vec4 vary_light; + +varying vec4 vary_fragcoord; +uniform vec2 screen_res; + +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +void main() +{ + vec4 frag = vary_fragcoord; + frag.xyz /= frag.w; + frag.xyz = frag.xyz*0.5+0.5; + frag.xy *= screen_res; + + vec3 pos = getPosition(frag.xy).xyz; + vec3 lv = vary_light.xyz-pos.xyz; + float dist2 = dot(lv,lv); + dist2 /= vary_light.w; + if (dist2 > 1.0) + { + discard; + } + + float shadow = 1.0; + + if (proj_shadow_idx >= 0) + { + vec4 shd = texture2DRect(lightMap, frag.xy); + float sh[2]; + sh[0] = shd.b; + sh[1] = shd.a; + shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); + } + + vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + + norm = normalize(norm); + float l_dist = -dot(lv, proj_n); + + vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); + if (proj_tc.z < 0.0) + { + discard; + } + + proj_tc.xyz /= proj_tc.w; + + float fa = gl_Color.a+1.0; + float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); + if (dist_atten <= 0.0) + { + discard; + } + + lv = proj_origin-pos.xyz; + lv = normalize(lv); + float da = dot(norm, lv); + + vec3 col = vec3(0,0,0); + + vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; + + float noise = texture2D(noiseMap, frag.xy/128.0).b; + if (proj_tc.z > 0.0 && + proj_tc.x < 1.0 && + proj_tc.y < 1.0 && + proj_tc.x > 0.0 && + proj_tc.y > 0.0) + { + float lit = 0.0; + float amb_da = proj_ambiance; + + if (da > 0.0) + { + float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); + float lod = diff * proj_lod; + + vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + + vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; + + lit = da * dist_atten * noise; + + col = lcol*lit*diff_tex*shadow; + amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; + } + + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_ambient_lod); + + amb_da += (da*da*0.5+0.5)*proj_ambiance; + + amb_da *= dist_atten * noise; + + amb_da = min(amb_da, 1.0-lit); + + col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + } + + + vec4 spec = texture2DRect(specularRect, frag.xy); + if (spec.a > 0.0) + { + vec3 ref = reflect(normalize(pos), norm); + + //project from point pos in direction ref to plane proj_p, proj_n + vec3 pdelta = proj_p-pos; + float ds = dot(ref, proj_n); + + if (ds < 0.0) + { + vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; + + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); + + if (stc.z > 0.0) + { + stc.xy /= stc.w; + + if (stc.x < 1.0 && + stc.y < 1.0 && + stc.x > 0.0 && + stc.y > 0.0) + { + vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow; + } + } + } + } + + //attenuate point light contribution by SSAO component + col *= texture2DRect(lightMap, frag.xy).g; + + gl_FragColor.rgb = col; + gl_FragColor.a = 0.0; +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl new file mode 100644 index 0000000..ee0e9d6 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl @@ -0,0 +1,59 @@ +/** + * @file postDeferredF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect localLightMap; +uniform sampler2DRect sunLightMap; +uniform sampler2DRect giLightMap; +uniform sampler2D luminanceMap; +uniform sampler2DRect lightMap; + +uniform vec3 gi_lum_quad; +uniform vec3 sun_lum_quad; +uniform vec3 lum_quad; +uniform float lum_lod; +uniform vec4 ambient; + +uniform vec3 gi_quad; + +uniform vec2 screen_res; +varying vec2 vary_fragcoord; + +void main() +{ + vec2 tc = vary_fragcoord.xy; + vec3 lcol = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb; + + float lum = sqrt(lcol.r)*lum_quad.x+lcol.r*lcol.r*lum_quad.y+lcol.r*lum_quad.z; + + vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); + + float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g; + + vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; + gi_col = gi_col*gi_col*gi_quad.x + gi_col*gi_quad.y+gi_quad.z*ambocc*ambient.rgb; + gi_col *= diff; + + vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy); + + vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb; + + + float sun_lum = 1.0-lum; + sun_lum = sun_lum*sun_lum*sun_lum_quad.x + sun_lum*sun_lum_quad.y+sun_lum_quad.z; + + float gi_lum = lum; + gi_lum = gi_lum*gi_lum*gi_lum_quad.x+gi_lum*gi_lum_quad.y+gi_lum_quad.z; + gi_col *= 1.0/gi_lum; + + vec3 col = sun_col.rgb*(1.0+max(sun_lum,0.0))+gi_col+local_col; + + gl_FragColor.rgb = col.rgb; + gl_FragColor.a = max(sun_lum*min(sun_col.r+sun_col.g+sun_col.b, 1.0), sun_col.a); + + //gl_FragColor.rgb = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl new file mode 100644 index 0000000..9819232 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl @@ -0,0 +1,17 @@ +/** + * @file postDeferredV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl new file mode 100644 index 0000000..52b79e3 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -0,0 +1,294 @@ +/** + * @file softenLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect normalMap; +uniform sampler2DRect lightMap; +uniform sampler2D noiseMap; +uniform samplerCube environmentMap; +uniform sampler2D lightFunc; +uniform vec3 gi_quad; + +uniform float blur_size; +uniform float blur_fidelity; + +// Inputs +uniform vec4 morphFactor; +uniform vec3 camPosLocal; +//uniform vec4 camPosWorld; +uniform vec4 gamma; +uniform vec4 lightnorm; +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 vec4 glow; +uniform float scene_light_strength; +uniform vec3 env_mat[3]; +uniform vec4 shadow_clip; +uniform mat3 ssao_effect_mat; + +uniform sampler2DRect depthMap; +uniform mat4 inv_proj; +uniform vec2 screen_res; + +varying vec4 vary_light; +varying vec2 vary_fragcoord; + +vec3 vary_PositionEye; + +vec3 vary_SunlitColor; +vec3 vary_AmblitColor; +vec3 vary_AdditiveColor; +vec3 vary_AtmosAttenuation; + +vec4 getPosition(vec2 pos_screen) +{ //get position in screen space (world units) given window coordinate and depth map + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +vec3 getPositionEye() +{ + return vary_PositionEye; +} +vec3 getSunlitColor() +{ + return vary_SunlitColor; +} +vec3 getAmblitColor() +{ + return vary_AmblitColor; +} +vec3 getAdditiveColor() +{ + return vary_AdditiveColor; +} +vec3 getAtmosAttenuation() +{ + return vary_AtmosAttenuation; +} + + +void setPositionEye(vec3 v) +{ + vary_PositionEye = v; +} + +void setSunlitColor(vec3 v) +{ + vary_SunlitColor = v; +} + +void setAmblitColor(vec3 v) +{ + vary_AmblitColor = v; +} + +void setAdditiveColor(vec3 v) +{ + vary_AdditiveColor = v; +} + +void setAtmosAttenuation(vec3 v) +{ + vary_AtmosAttenuation = v; +} + +void calcAtmospherics(vec3 inPositionEye, float ambFactor) { + + vec3 P = 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); + + vec3 tmpLightnorm = lightnorm.xyz; + + vec3 Pn = normalize(P); + float Plen = length(P); + + vec4 temp1 = vec4(0); + vec3 temp2 = vec3(0); + vec4 blue_weight; + vec4 haze_weight; + 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 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); + //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); + blue_weight = blue_density / temp1; + haze_weight = vec4(haze_density.r) / temp1; + + //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain) + temp2.y = max(0.0, tmpLightnorm.y); + temp2.y = 1. / temp2.y; + sunlight *= exp( - light_atten * temp2.y); + + // main atmospheric scattering line integral + temp2.z = Plen * density_multiplier.x; + + // Transparency (-> temp1) + // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati + // compiler gets confused. + temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); + + //final atmosphere attenuation factor + setAtmosAttenuation(temp1.rgb); + + //compute haze glow + //(can use temp2.x as temp because we haven't used it yet) + temp2.x = dot(Pn, tmpLightnorm.xyz); + temp2.x = 1. - temp2.x; + //temp2.x is 0 at the sun and increases away from sun + temp2.x = max(temp2.x, .03); //was glow.y + //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) + temp2.x *= glow.x; + //higher glow.x gives dimmer glow (because next step is 1 / "angle") + temp2.x = pow(temp2.x, glow.z); + //glow.z should be negative, so we're doing a sort of (1 / "angle") function + + //add "minimum anti-solar illumination" + temp2.x += .25; + + //increase ambient when there are more clouds + vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 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 + * // The following line of code performs the equivalent of: + * float ambAlpha = tmpAmbient.a; + * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis + * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); + * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); + */ + tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); + + //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 + + tmpAmbient))); + + //brightness of surface both sunlight and ambient + setSunlitColor(vec3(sunlight * .5)); + setAmblitColor(vec3(tmpAmbient * .25)); + setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1)); +} + +vec3 atmosLighting(vec3 light) +{ + light *= getAtmosAttenuation().r; + light += getAdditiveColor(); + return (2.0 * light); +} + +vec3 atmosTransport(vec3 light) { + light *= getAtmosAttenuation().r; + light += getAdditiveColor() * 2.0; + return light; +} +vec3 atmosGetDiffuseSunlightColor() +{ + return getSunlitColor(); +} + +vec3 scaleDownLight(vec3 light) +{ + return (light / scene_light_strength ); +} + +vec3 scaleUpLight(vec3 light) +{ + return (light * scene_light_strength); +} + +vec3 atmosAmbient(vec3 light) +{ + return getAmblitColor() + light / 2.0; +} + +vec3 atmosAffectDirectionalLight(float lightIntensity) +{ + return getSunlitColor() * lightIntensity; +} + +vec3 scaleSoftClip(vec3 light) +{ + //soft clip effect: + light = 1. - clamp(light, vec3(0.), vec3(1.)); + light = 1. - pow(light, gamma.xxx); + + return light; +} + +void main() +{ + vec2 tc = vary_fragcoord.xy; + vec3 pos = getPosition(tc).xyz; + vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0; + vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; + + float da = max(dot(norm.xyz, vary_light.xyz), 0.0); + + vec4 diffuse = texture2DRect(diffuseRect, tc); + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + + vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; + float scol = max(scol_ambocc.r, diffuse.a); + float ambocc = scol_ambocc.g; + + calcAtmospherics(pos.xyz, ambocc); + + vec3 col = atmosAmbient(vec3(0)); + col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a)); + + col *= diffuse.rgb; + + if (spec.a > 0.0) + { + vec3 ref = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(ref, vary_light.xyz); + col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; + } + + col = atmosLighting(col); + col = scaleSoftClip(col); + + gl_FragColor.rgb = col; + + //gl_FragColor.rgb = gi_col.rgb; + gl_FragColor.a = 0.0; + + //gl_FragColor.rg = scol_ambocc.rg; + //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb; + //gl_FragColor.rgb = norm.rgb*0.5+0.5; + //gl_FragColor.rgb = vec3(ambocc); + //gl_FragColor.rgb = vec3(scol); +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl new file mode 100644 index 0000000..ad8af47 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl @@ -0,0 +1,24 @@ +/** + * @file softenLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform vec2 screen_res; + +varying vec4 vary_light; +varying vec2 vary_fragcoord; +void main() +{ + //transform vertex + gl_Position = ftransform(); + + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; + + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + vary_light = gl_MultiTexCoord0; +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl new file mode 100644 index 0000000..d653408 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -0,0 +1,199 @@ +/** + * @file spotLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; +uniform sampler2DRect lightMap; +uniform sampler2D noiseMap; +uniform sampler2D lightFunc; +uniform sampler2D projectionMap; + +uniform mat4 proj_mat; //screen space to light space +uniform float proj_near; //near clip for projection +uniform vec3 proj_p; //plane projection is emitting from (in screen space) +uniform vec3 proj_n; +uniform float proj_focus; //distance from plane to begin blurring +uniform float proj_lod; //(number of mips in proj map) +uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambiance; +uniform float near_clip; +uniform float far_clip; + +uniform vec3 proj_origin; //origin of projection to be used for angular attenuation +uniform float sun_wash; +uniform int proj_shadow_idx; +uniform float shadow_fade; + +varying vec4 vary_light; + +varying vec4 vary_fragcoord; +uniform vec2 screen_res; + +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +void main() +{ + vec4 frag = vary_fragcoord; + frag.xyz /= frag.w; + frag.xyz = frag.xyz*0.5+0.5; + frag.xy *= screen_res; + + float shadow = 1.0; + + if (proj_shadow_idx >= 0) + { + vec4 shd = texture2DRect(lightMap, frag.xy); + float sh[2]; + sh[0] = shd.b; + sh[1] = shd.a; + shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); + } + + vec3 pos = getPosition(frag.xy).xyz; + vec3 lv = vary_light.xyz-pos.xyz; + float dist2 = dot(lv,lv); + dist2 /= vary_light.w; + if (dist2 > 1.0) + { + discard; + } + + vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + + norm = normalize(norm); + float l_dist = -dot(lv, proj_n); + + vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); + if (proj_tc.z < 0.0) + { + discard; + } + + proj_tc.xyz /= proj_tc.w; + + float fa = gl_Color.a+1.0; + float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + lv = proj_origin-pos.xyz; + lv = normalize(lv); + float da = dot(norm, lv); + + vec3 col = vec3(0,0,0); + + vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; + + float noise = texture2D(noiseMap, frag.xy/128.0).b; + if (proj_tc.z > 0.0 && + proj_tc.x < 1.0 && + proj_tc.y < 1.0 && + proj_tc.x > 0.0 && + proj_tc.y > 0.0) + { + float lit = 0.0; + if (da > 0.0) + { + float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); + float lod = diff * proj_lod; + + vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + + vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; + + lit = da * dist_atten * noise; + + col = lcol*lit*diff_tex*shadow; + } + + float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + float lod = diff * proj_lod; + vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); + float amb_da = proj_ambiance; + if (da > 0.0) + { + amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; + } + + amb_da += (da*da*0.5+0.5)*proj_ambiance; + + amb_da *= dist_atten * noise; + + amb_da = min(amb_da, 1.0-lit); + + col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + } + + + vec4 spec = texture2DRect(specularRect, frag.xy); + if (spec.a > 0.0) + { + vec3 ref = reflect(normalize(pos), norm); + + //project from point pos in direction ref to plane proj_p, proj_n + vec3 pdelta = proj_p-pos; + float ds = dot(ref, proj_n); + + if (ds < 0.0) + { + vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; + + vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; + + if (stc.z > 0.0) + { + stc.xy /= stc.z+proj_near; + + if (stc.x < 1.0 && + stc.y < 1.0 && + stc.x > 0.0 && + stc.y > 0.0) + { + vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow; + } + } + } + } + + /*if (spec.a > 0.0) + { + //vec3 ref = reflect(normalize(pos), norm); + float sa = dot(normalize(lv-normalize(pos)),norm);; + //sa = max(sa, 0.0); + //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); + sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); + sa *= noise; + col += da*sa*lcol*spec.rgb; + }*/ + + //attenuate point light contribution by SSAO component + col *= texture2DRect(lightMap, frag.xy).g; + + + gl_FragColor.rgb = col; + gl_FragColor.a = 0.0; +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl new file mode 100644 index 0000000..8ced94e --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -0,0 +1,203 @@ +/** + * @file sunLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2DRectShadow shadowMap0; +uniform sampler2DRectShadow shadowMap1; +uniform sampler2DRectShadow shadowMap2; +uniform sampler2DRectShadow shadowMap3; +uniform sampler2DRectShadow shadowMap4; +uniform sampler2DRectShadow shadowMap5; +uniform sampler2D noiseMap; + +uniform sampler2D lightFunc; + + +// Inputs +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform float ssao_radius; +uniform float ssao_max_radius; +uniform float ssao_factor; +uniform float ssao_factor_inv; + +varying vec2 vary_fragcoord; +varying vec4 vary_light; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +uniform float shadow_bias; +uniform float shadow_offset; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +//calculate decreases in ambient lighting when crowded out (SSAO) +float calcAmbientOcclusion(vec4 pos, vec3 norm) +{ + vec2 kern[8]; + // exponentially (^2) distant occlusion samples spread around origin + kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; + kern[1] = vec2(1.0, 0.0) * 0.250*0.250; + kern[2] = vec2(0.0, 1.0) * 0.375*0.375; + kern[3] = vec2(0.0, -1.0) * 0.500*0.500; + kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; + kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; + kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; + kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; + + vec2 pos_screen = vary_fragcoord.xy; + vec3 pos_world = pos.xyz; + vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; + + float angle_hidden = 0.0; + int points = 0; + + float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); + + // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) + for (int i = 0; i < 8; i++) + { + vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); + vec3 samppos_world = getPosition(samppos_screen).xyz; + + vec3 diff = pos_world - samppos_world; + float dist2 = dot(diff, diff); + + // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area + // --> solid angle shrinking by the square of distance + //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 + //(k should vary inversely with # of samples, but this is taken care of later) + + //if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces + // angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor) + angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv); + + // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" + points = points + int(diff.z > -1.0); + } + + angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); + + return (1.0 - (float(points != 0) * angle_hidden)); +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + + //try doing an unproject here + + vec4 pos = getPosition(pos_screen); + + vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; + + /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL + { + gl_FragColor = vec4(0.0); // doesn't matter + return; + }*/ + + float shadow = 1.0; + float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); + + vec4 spos = vec4(pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias), 1.0); + + //vec3 debug = vec3(0,0,0); + + if (spos.z > -shadow_clip.w) + { + if (dp_directional_light == 0.0) + { + // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup + shadow = 0.0; + } + else + { + vec4 lpos; + + if (spos.z < -shadow_clip.z) + { + lpos = shadow_matrix[3]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap3, lpos).x; + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + else if (spos.z < -shadow_clip.y) + { + lpos = shadow_matrix[2]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap2, lpos).x; + } + else if (spos.z < -shadow_clip.x) + { + lpos = shadow_matrix[1]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap1, lpos).x; + } + else + { + lpos = shadow_matrix[0]*spos; + lpos.xy *= screen_res; + shadow = shadow2DRectProj(shadowMap0, lpos).x; + } + + // take the most-shadowed value out of these two: + // * the blurred sun shadow in the light (shadow) map + // * an unblurred dot product between the sun and this norm + // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting + shadow = min(shadow, dp_directional_light); + } + + /*debug.r = lpos.y / (lpos.w*screen_res.y); + + lpos.xy /= lpos.w*32.0; + if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1) + { + debug.gb = vec2(0.5, 0.5); + } + + debug += (1.0-shadow)*0.5;*/ + + } + else + { + // more distant than the shadow map covers + shadow = 1.0; + } + + gl_FragColor[0] = shadow; + gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + + //spotlight shadow 1 + vec4 lpos = shadow_matrix[4]*spos; + lpos.xy *= screen_res; + gl_FragColor[2] = shadow2DRectProj(shadowMap4, lpos).x; + + //spotlight shadow 2 + lpos = shadow_matrix[5]*spos; + lpos.xy *= screen_res; + gl_FragColor[3] = shadow2DRectProj(shadowMap5, lpos).x; + + //gl_FragColor.rgb = pos.xyz; + //gl_FragColor.b = shadow; + //gl_FragColor.rgb = debug; +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl new file mode 100644 index 0000000..5081485 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl @@ -0,0 +1,25 @@ +/** + * @file sunLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec4 vary_light; +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + vary_light = gl_MultiTexCoord0; + + gl_FrontColor = gl_Color; +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl new file mode 100644 index 0000000..7342186 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl @@ -0,0 +1,139 @@ +/** + * @file waterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +vec3 scaleSoftClip(vec3 inColor); +vec3 atmosTransport(vec3 inColor); + +uniform sampler2D bumpMap; +uniform sampler2D screenTex; +uniform sampler2D refTex; +uniform sampler2DRectShadow shadowMap0; +uniform sampler2DRectShadow shadowMap1; +uniform sampler2DRectShadow shadowMap2; +uniform sampler2DRectShadow shadowMap3; +uniform sampler2D noiseMap; + +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; + +uniform float sunAngle; +uniform float sunAngle2; +uniform vec3 lightDir; +uniform vec3 specular; +uniform float lightExp; +uniform float refScale; +uniform float kd; +uniform vec2 screenRes; +uniform vec3 normScale; +uniform float fresnelScale; +uniform float fresnelOffset; +uniform float blurMultiplier; +uniform vec2 screen_res; +uniform mat4 norm_mat; //region space to screen space + +//bigWave is (refCoord.w, view.w); +varying vec4 refCoord; +varying vec4 littleWave; +varying vec4 view; +varying vec4 vary_position; + +void main() +{ + vec4 color; + float dist = length(view.xy); + + //normalize view vector + vec3 viewVec = normalize(view.xyz); + + //get wave normals + vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0; + vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0; + vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0; + //get base fresnel components + + vec3 df = vec3( + dot(viewVec, wave1), + dot(viewVec, (wave2 + wave3) * 0.5), + dot(viewVec, wave3) + ) * fresnelScale + fresnelOffset; + df *= df; + + vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; + + float dist2 = dist; + dist = max(dist, 5.0); + + float dmod = sqrt(dist); + + vec2 dmod_scale = vec2(dmod*dmod, dmod); + + //get reflected color + vec2 refdistort1 = wave1.xy*normScale.x; + vec2 refvec1 = distort+refdistort1/dmod_scale; + vec4 refcol1 = texture2D(refTex, refvec1); + + vec2 refdistort2 = wave2.xy*normScale.y; + vec2 refvec2 = distort+refdistort2/dmod_scale; + vec4 refcol2 = texture2D(refTex, refvec2); + + vec2 refdistort3 = wave3.xy*normScale.z; + vec2 refvec3 = distort+refdistort3/dmod_scale; + vec4 refcol3 = texture2D(refTex, refvec3); + + vec4 refcol = refcol1 + refcol2 + refcol3; + float df1 = df.x + df.y + df.z; + refcol *= df1 * 0.333; + + vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5; + //wavef.z *= max(-viewVec.z, 0.1); + wavef = normalize(wavef); + + float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset; + + vec2 refdistort4 = wavef.xy*0.125; + refdistort4.y -= abs(refdistort4.y); + vec2 refvec4 = distort+refdistort4/dmod; + float dweight = min(dist2*blurMultiplier, 1.0); + vec4 baseCol = texture2D(refTex, refvec4); + refcol = mix(baseCol*df2, refcol, dweight); + + //get specular component + //float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0); + + //harden specular + //spec = pow(spec, 128.0); + + //figure out distortion vector (ripply) + vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0); + + vec4 fb = texture2D(screenTex, distort2); + + //mix with reflection + // Note we actually want to use just df1, but multiplying by 0.999999 gets around and nvidia compiler bug + color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999); + + float shadow = 1.0; + vec4 pos = vary_position; + + vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; + vec4 spos = pos; + + //spec *= shadow; + //color.rgb += spec * specular; + + //color.rgb = atmosTransport(color.rgb); + //color.rgb = scaleSoftClip(color.rgb); + //color.a = spec * sunAngle2; + + //wavef.z *= 0.1f; + wavef = normalize(wavef); + wavef = (norm_mat*vec4(wavef, 1.0)).xyz; + + gl_FragData[0] = vec4(color.rgb, 0.75); + gl_FragData[1] = vec4(1,1,1, 0.8); + gl_FragData[2] = vec4(wavef*0.5+0.5, 0.f); +} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/waterV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/waterV.glsl new file mode 100644 index 0000000..b45e5c5 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class2/deferred/waterV.glsl @@ -0,0 +1,76 @@ +/** + * @file waterV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +void calcAtmospherics(vec3 inPositionEye); + +uniform vec2 d1; +uniform vec2 d2; +uniform float time; +uniform vec3 eyeVec; +uniform float waterHeight; + +varying vec4 refCoord; +varying vec4 littleWave; +varying vec4 view; + +varying vec4 vary_position; + +float wave(vec2 v, float t, float f, vec2 d, float s) +{ + return (dot(d, v)*f + t*s)*f; +} + +void main() +{ + //transform vertex + vec4 position = gl_Vertex; + mat4 modelViewProj = gl_ModelViewProjectionMatrix; + + vec4 oPosition; + + //get view vector + vec3 oEyeVec; + oEyeVec.xyz = position.xyz-eyeVec; + + float d = length(oEyeVec.xy); + float ld = min(d, 2560.0); + + position.xy = eyeVec.xy + oEyeVec.xy/d*ld; + view.xyz = oEyeVec; + + d = clamp(ld/1536.0-0.5, 0.0, 1.0); + d *= d; + + oPosition = position; + oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d); + vary_position = gl_ModelViewMatrix * oPosition; + oPosition = modelViewProj * oPosition; + + refCoord.xyz = oPosition.xyz + vec3(0,0,0.2); + + //get wave position parameter (create sweeping horizontal waves) + vec3 v = position.xyz; + v.x += (cos(v.x*0.08/*+time*0.01*/)+sin(v.y*0.02))*6.0; + + //push position for further horizon effect. + position.xyz = oEyeVec.xyz*(waterHeight/oEyeVec.z); + position.w = 1.0; + position = position*gl_ModelViewMatrix; + + calcAtmospherics((gl_ModelViewMatrix * gl_Vertex).xyz); + + + //pass wave parameters to pixel shader + vec2 bigWave = (v.xy) * vec2(0.04,0.04) + d1 * time * 0.055; + //get two normal map (detail map) texture coordinates + littleWave.xy = (v.xy) * vec2(0.45, 0.9) + d2 * time * 0.13; + littleWave.zw = (v.xy) * vec2(0.1, 0.2) + d1 * time * 0.1; + view.w = bigWave.y; + refCoord.w = bigWave.x; + + gl_Position = oPosition; +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/avatarF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/avatarF.glsl new file mode 100644 index 0000000..9cc71a7 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/avatarF.glsl @@ -0,0 +1,18 @@ +/** + * @file avatarF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; + +varying vec3 vary_normal; + +void main() +{ + gl_FragData[0] = vec4(gl_Color.rgb * texture2D(diffuseMap, gl_TexCoord[0].xy).rgb, 0.0); + gl_FragData[1] = vec4(0,0,0,0); + gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); +} + diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/bumpF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/bumpF.glsl new file mode 100644 index 0000000..6eb4a51 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/bumpF.glsl @@ -0,0 +1,27 @@ +/** + * @file bumpF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; +uniform sampler2D bumpMap; + +varying vec3 vary_mat0; +varying vec3 vary_mat1; +varying vec3 vary_mat2; + +void main() +{ + vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; + vec3 norm = texture2D(bumpMap, gl_TexCoord[0].xy).rgb * 2.0 - 1.0; + + vec3 tnorm = vec3(dot(norm,vary_mat0), + dot(norm,vary_mat1), + dot(norm,vary_mat2)); + + gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0); + gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); + gl_FragData[2] = vec4(normalize(tnorm)*0.5+0.5, 0.0); +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/diffuseF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/diffuseF.glsl new file mode 100644 index 0000000..c9f75f7 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/diffuseF.glsl @@ -0,0 +1,18 @@ +/** + * @file diffuseF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; + +varying vec3 vary_normal; + +void main() +{ + vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; + gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0); + gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); + gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl new file mode 100644 index 0000000..7325825 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl @@ -0,0 +1,84 @@ +/** + * @file giDownsampleF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2DRect giLightMap; + +uniform vec2 kern[32]; +uniform float dist_factor; +uniform float blur_size; +uniform vec2 delta; +uniform int kern_length; +uniform float kern_scale; +uniform vec3 blur_quad; + +varying vec2 vary_fragcoord; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +float getDepth(vec2 pos_screen) +{ + float z = texture2DRect(depthMap, pos_screen.xy).a; + z = z*2.0-1.0; + vec4 ndc = vec4(0.0, 0.0, z, 1.0); + vec4 p = inv_proj*ndc; + return p.z/p.w; +} + +void main() +{ + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + float depth = getDepth(vary_fragcoord.xy); + + vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; + vec2 dlt = kern_scale * delta/(vec2(1.0,1.0)+norm.xy*norm.xy); + dlt /= clamp(-depth*blur_quad.x, 1.0, 3.0); + float defined_weight = kern[0].x; + vec3 col = ccol*kern[0].x; + + for (int i = 0; i < kern_length; i++) + { + vec2 tc = vary_fragcoord.xy + kern[i].y*dlt; + vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0; + + float d = dot(norm.xyz, sampNorm); + + if (d > 0.5) + { + float sampdepth = getDepth(tc.xy); + sampdepth -= depth; + if (sampdepth*sampdepth < blur_quad.z) + { + col += texture2DRect(giLightMap, tc).rgb*kern[i].x; + defined_weight += kern[i].x; + } + } + } + + col /= defined_weight; + + //col = ccol; + + col = col*blur_quad.y; + + gl_FragData[0].xyz = col; + + //gl_FragColor = ccol; +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl new file mode 100644 index 0000000..6adcda8 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl @@ -0,0 +1,17 @@ +/** + * @file postgiV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/giF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/giF.glsl new file mode 100644 index 0000000..43da836 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/giF.glsl @@ -0,0 +1,219 @@ +/** + * @file giF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2DRect lightMap; +uniform sampler2DRect specularRect; + +uniform sampler2D noiseMap; + +uniform sampler2D diffuseGIMap; +uniform sampler2D specularGIMap; +uniform sampler2D normalGIMap; +uniform sampler2D depthGIMap; + +uniform sampler2D lightFunc; + +// Inputs +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +uniform vec4 sunlight_color; + +uniform mat4 inv_proj; +uniform mat4 gi_mat; //gPipeline.mGIMatrix - eye space to sun space +uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space +uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix +uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space +uniform float gi_radius; +uniform float gi_intensity; +uniform int gi_samples; +uniform vec2 gi_kern[25]; +uniform vec2 gi_scale; +uniform vec3 gi_quad; +uniform vec3 gi_spec; +uniform float gi_direction_weight; +uniform float gi_light_offset; +uniform float gi_range; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +vec4 getGIPosition(vec2 gi_tc) +{ + float depth = texture2D(depthGIMap, gi_tc).a; + vec2 sc = gi_tc*2.0; + sc -= vec2(1.0, 1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = gi_inv_proj*ndc; + pos.xyz /= pos.w; + pos.w = 1.0; + return pos; +} + +vec3 giAmbient(vec3 pos, vec3 norm) +{ + vec4 gi_c = gi_mat_proj * vec4(pos, 1.0); + gi_c.xyz /= gi_c.w; + + vec4 gi_pos = gi_mat*vec4(pos,1.0); + vec3 gi_norm = (gi_norm_mat*vec4(norm,1.0)).xyz; + gi_norm = normalize(gi_norm); + + vec4 c_spec = texture2DRect(specularRect, vary_fragcoord.xy); + gi_pos.xyz += (texture2D(noiseMap, vary_fragcoord.xy/128.0).x)*gi_spec.z*gi_norm.xyz; + vec2 tcx = gi_norm.xy; + vec2 tcy = gi_norm.yx; + + vec4 eye_pos = gi_mat*vec4(0,0,0,1.0); + + vec3 eye_dir = normalize(gi_pos.xyz-eye_pos.xyz); + vec3 eye_ref = reflect(eye_dir, gi_norm); + + //vec3 eye_dir = vec3(0,0,-1); + //eye_dir = (gi_norm_mat*vec4(eye_dir, 1.0)).xyz; + //eye_dir = normalize(eye_dir); + + //float round_x = gi_scale.x; + //float round_y = gi_scale.y; + + vec3 debug = texture2D(normalGIMap, gi_c.xy).rgb; + //debug.xz = vec2(0.0,0.0); + //debug = fract(debug); + + float round_x = 1.0/64.0; + float round_y = 1.0/64.0; + + //gi_c.x = floor(gi_c.x/round_x+0.5)*round_x; + //gi_c.y = floor(gi_c.y/round_y+0.5)*round_y; + + float da = texture2DRect(lightMap, vary_fragcoord.xy).r; + + vec3 fdiff = vec3(da); + + if (da > 0.0) + { + vec3 ha = -eye_dir; + ha.z += 1.0; + ha = normalize(ha); + + float sa = dot(ha,gi_norm); + da = min(da, texture2D(lightFunc, vec2(sa, c_spec.a)).a); + fdiff += da*(c_spec.rgb*c_spec.a*2.0); + } + + float fda = da; + + vec3 rcol = vec3(0,0,0); + + float fsa = 0.0; + + + for (int i = -1; i <= 1; i += 1 ) + { + for (int j = -1; j <= 1; j+= 1) + { + vec2 tc = vec2(i, j)*0.75+gi_norm.xy; + vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0+tc*0.5).xyz; + tc += gi_norm.xy*nz.z; + tc += nz.xy*2.0; + tc /= gi_samples; + tc += gi_c.xy; + + vec3 lnorm = -normalize(texture2D(normalGIMap, tc.xy).xyz*2.0-1.0); + vec3 lpos = getGIPosition(tc.xy).xyz; + + vec3 at = lpos-gi_pos.xyz; + float dist = dot(at,at); + float da = clamp(1.0/(gi_spec.x*dist), 0.0, 1.0); + + + if (da > 0.01) + { //possible contribution of indirect light to this surface + vec3 ldir = at; + + float ld = -dot(ldir, lnorm); + + if (ld < 0.0) + { + float ang_atten = dot(ldir, gi_norm); + + if (ang_atten > 0.0) + { + vec4 spec = texture2D(specularGIMap, tc.xy); + at = normalize(at); + vec3 diff; + + { //contribution from indirect source to visible pixel + vec3 ha = at; + ha.z -= 1.0; + ha = normalize(ha); + float sa = dot(ha,lnorm); + da = min(da, texture2D(lightFunc, vec2(sa, spec.a)).a); + + diff = texture2D(diffuseGIMap, tc.xy).rgb+spec.rgb*spec.a*2.0; + } + + if (da > 0.0) + { //contribution from visible pixel to eye + vec3 ha = normalize(at-eye_dir); + float sa = dot(ha, gi_norm); + da = min(da, texture2D(lightFunc, vec2(sa, c_spec.a)).a); + fda += da; + fdiff += da*(c_spec.rgb*c_spec.a*2.0+vec3(1,1,1))*diff.rgb; + } + } + } + } + } + } + + //fdiff /= max(gi_spec.y*fda, gi_quad.z); + //fdiff = clamp(fdiff, vec3(0), vec3(1)); + fdiff *= 64.0; + fdiff *= sunlight_color.rgb; + + vec3 ret = fda*fdiff; + //ret = ret*ret*gi_quad.x+ret*gi_quad.y+gi_quad.z; + + //fda *= nz.z; + + //rcol.rgb *= gi_intensity; + //return rcol.rgb+vary_AmblitColor.rgb*0.25; + //return vec4(debug, 0.0); + //return vec4(fda*fdiff, 0.0); + return clamp(ret,vec3(0.0), vec3(1.0)); + //return debug.xyz; +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + vec4 pos = getPosition(pos_screen); + + float rad = gi_range*0.5; + + vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; + float dist = max(length(pos.xyz)-rad, 0.0); + + float da = clamp(1.0-dist/rad, 0.0, 1.0); + gl_FragData[0].xyz = da > 0.0 ? giAmbient(pos, norm)*da : vec3(0,0,0); +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/giV.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/giV.glsl new file mode 100644 index 0000000..71dcea9 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/giV.glsl @@ -0,0 +1,22 @@ +/** + * @file giV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + gl_FrontColor = gl_Color; +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl new file mode 100644 index 0000000..0de0d11 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl @@ -0,0 +1,16 @@ +/** + * @file luminanceF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2DRect diffuseMap; + +varying vec2 vary_fragcoord; +uniform float fade; +void main() +{ + gl_FragColor.rgb = texture2DRect(diffuseMap, vary_fragcoord.xy).rgb; + gl_FragColor.a = fade; +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl new file mode 100644 index 0000000..db8775f --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl @@ -0,0 +1,20 @@ +/** + * @file giV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; + + gl_FrontColor = gl_Color; +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl new file mode 100644 index 0000000..609fb1d --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl @@ -0,0 +1,76 @@ +/** + * @file postDeferredF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect localLightMap; +uniform sampler2DRect sunLightMap; +uniform sampler2DRect giLightMap; +uniform sampler2D luminanceMap; +uniform sampler2DRect lightMap; +uniform sampler2D lightFunc; + + +uniform vec3 gi_lum_quad; +uniform vec3 sun_lum_quad; +uniform vec3 lum_quad; +uniform float lum_lod; +uniform vec4 ambient; + +uniform vec3 gi_quad; + +uniform vec2 screen_res; +varying vec2 vary_fragcoord; + +void main() +{ + vec2 tc = vary_fragcoord.xy; + vec3 lcol = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb; + + float lum = sqrt(lcol.r)*lum_quad.x+lcol.r*lcol.r*lum_quad.y+lcol.r*lum_quad.z; + + vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + + float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g; + + vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; + vec3 gi_col = ccol; + /*for (int i = -1; i <= 1; i+=1) + { + for (int j = -1; j <= 1; j+=1) + { + vec2 tc = vec2(i,j); + float wght = 1.0/(length(tc)+1.0); + gi_col += texture2DRect(giLightMap, vary_fragcoord.xy+vec2(i,j)).rgb * wght; + } + }*/ + + //gi_col *= 1.0+spec.a*4.0; + gi_col = (sqrt(gi_col)*gi_quad.x + gi_col*gi_quad.y)*(diff.rgb+spec.rgb*spec.a)+gi_quad.z*ambocc*ambient.rgb*diff.rgb; + + vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy); + + vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb; + + + float sun_lum = 1.0-lum; + sun_lum = sun_lum*sun_lum*sun_lum_quad.x + sun_lum*sun_lum_quad.y+sun_lum_quad.z; + + float gi_lum = lum; + gi_lum = gi_lum*gi_lum*gi_lum_quad.x+gi_lum*gi_lum_quad.y+gi_lum_quad.z; + gi_col *= 1.0/gi_lum; + + + vec3 col = sun_col.rgb*(1.0+max(sun_lum,0.0))+gi_col+local_col; + + gl_FragColor.rgb = col.rgb; + gl_FragColor.a = max(sun_lum*min(sun_col.r+sun_col.g+sun_col.b, 1.0), sun_col.a); + + //gl_FragColor.rgb = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; + //gl_FragColor.rgb = vec3(texture2D(lightFunc, vary_fragcoord.xy/512.0-vec2(0.5, 0.5)).a); +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl new file mode 100644 index 0000000..9819232 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl @@ -0,0 +1,17 @@ +/** + * @file postDeferredV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl new file mode 100644 index 0000000..12a5f39 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl @@ -0,0 +1,87 @@ +/** + * @file postgiF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2DRect giLightMap; +uniform sampler2D noiseMap; + +uniform vec2 kern[32]; +uniform float dist_factor; +uniform float blur_size; +uniform vec2 delta; +uniform int kern_length; +uniform float kern_scale; +uniform vec3 blur_quad; + +varying vec2 vary_fragcoord; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +float getDepth(vec2 pos_screen) +{ + float z = texture2DRect(depthMap, pos_screen.xy).a; + z = z*2.0-1.0; + vec4 ndc = vec4(0.0, 0.0, z, 1.0); + vec4 p = inv_proj*ndc; + return p.z/p.w; +} + +void main() +{ + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + float depth = getDepth(vary_fragcoord.xy); + + vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; + vec2 dlt = kern_scale * delta/(vec2(1.0,1.0)+norm.xy*norm.xy); + dlt /= clamp(-depth*blur_quad.x, 1.0, 3.0); + float defined_weight = kern[0].x; + vec3 col = ccol*kern[0].x; + + for (int i = 0; i < kern_length; i++) + { + vec2 tc = vary_fragcoord.xy + kern[i].y*dlt; + vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0; + + float d = dot(norm.xyz, sampNorm); + + if (d > 0.5) + { + float sampdepth = getDepth(tc.xy); + sampdepth -= depth; + if (sampdepth*sampdepth < blur_quad.z) + { + col += texture2DRect(giLightMap, tc).rgb*kern[i].x; + defined_weight += kern[i].x; + } + } + } + + col /= defined_weight; + + //col = ccol; + + col = col*blur_quad.y; + + gl_FragData[0].xyz = col; + + //gl_FragColor = ccol; +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl new file mode 100644 index 0000000..6adcda8 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl @@ -0,0 +1,17 @@ +/** + * @file postgiV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl new file mode 100644 index 0000000..654b182 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -0,0 +1,312 @@ +/** + * @file softenLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect normalMap; +uniform sampler2DRect lightMap; +uniform sampler2DRect giLightMap; +uniform sampler2D noiseMap; +uniform samplerCube environmentMap; +uniform sampler2D lightFunc; +uniform sampler2D luminanceMap; + +uniform vec3 gi_quad; +uniform vec3 lum_quad; +uniform float lum_lod; + +uniform float blur_size; +uniform float blur_fidelity; + +// Inputs +uniform vec4 morphFactor; +uniform vec3 camPosLocal; +//uniform vec4 camPosWorld; +uniform vec4 gamma; +uniform vec4 lightnorm; +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 vec4 glow; +uniform float scene_light_strength; +uniform vec3 env_mat[3]; +uniform vec4 shadow_clip; +uniform mat3 ssao_effect_mat; + +uniform sampler2DRect depthMap; +uniform mat4 inv_proj; +uniform vec2 screen_res; + +varying vec4 vary_light; +varying vec2 vary_fragcoord; + +vec3 vary_PositionEye; + +vec3 vary_SunlitColor; +vec3 vary_AmblitColor; +vec3 vary_AdditiveColor; +vec3 vary_AtmosAttenuation; + +vec4 getPosition(vec2 pos_screen) +{ //get position in screen space (world units) given window coordinate and depth map + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +vec3 getPositionEye() +{ + return vary_PositionEye; +} +vec3 getSunlitColor() +{ + return vary_SunlitColor; +} +vec3 getAmblitColor() +{ + return vary_AmblitColor; +} +vec3 getAdditiveColor() +{ + return vary_AdditiveColor; +} +vec3 getAtmosAttenuation() +{ + return vary_AtmosAttenuation; +} + + +void setPositionEye(vec3 v) +{ + vary_PositionEye = v; +} + +void setSunlitColor(vec3 v) +{ + vary_SunlitColor = v; +} + +void setAmblitColor(vec3 v) +{ + vary_AmblitColor = v; +} + +void setAdditiveColor(vec3 v) +{ + vary_AdditiveColor = v; +} + +void setAtmosAttenuation(vec3 v) +{ + vary_AtmosAttenuation = v; +} + +void calcAtmospherics(vec3 inPositionEye, float ambFactor) { + + vec3 P = 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); + + vec3 tmpLightnorm = lightnorm.xyz; + + vec3 Pn = normalize(P); + float Plen = length(P); + + vec4 temp1 = vec4(0); + vec3 temp2 = vec3(0); + vec4 blue_weight; + vec4 haze_weight; + 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 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); + //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); + blue_weight = blue_density / temp1; + haze_weight = vec4(haze_density.r) / temp1; + + //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain) + temp2.y = max(0.0, tmpLightnorm.y); + temp2.y = 1. / temp2.y; + sunlight *= exp( - light_atten * temp2.y); + + // main atmospheric scattering line integral + temp2.z = Plen * density_multiplier.x; + + // Transparency (-> temp1) + // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati + // compiler gets confused. + temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); + + //final atmosphere attenuation factor + setAtmosAttenuation(temp1.rgb); + + //compute haze glow + //(can use temp2.x as temp because we haven't used it yet) + temp2.x = dot(Pn, tmpLightnorm.xyz); + temp2.x = 1. - temp2.x; + //temp2.x is 0 at the sun and increases away from sun + temp2.x = max(temp2.x, .03); //was glow.y + //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) + temp2.x *= glow.x; + //higher glow.x gives dimmer glow (because next step is 1 / "angle") + temp2.x = pow(temp2.x, glow.z); + //glow.z should be negative, so we're doing a sort of (1 / "angle") function + + //add "minimum anti-solar illumination" + temp2.x += .25; + + //increase ambient when there are more clouds + vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 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 + * // The following line of code performs the equivalent of: + * float ambAlpha = tmpAmbient.a; + * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis + * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); + * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); + */ + tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); + + //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 + + tmpAmbient))); + + //brightness of surface both sunlight and ambient + setSunlitColor(vec3(sunlight * .5)); + setAmblitColor(vec3(tmpAmbient * .25)); + setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1)); +} + +vec3 atmosLighting(vec3 light) +{ + light *= getAtmosAttenuation().r; + light += getAdditiveColor(); + return (2.0 * light); +} + +vec3 atmosTransport(vec3 light) { + light *= getAtmosAttenuation().r; + light += getAdditiveColor() * 2.0; + return light; +} +vec3 atmosGetDiffuseSunlightColor() +{ + return getSunlitColor(); +} + +vec3 scaleDownLight(vec3 light) +{ + return (light / scene_light_strength ); +} + +vec3 scaleUpLight(vec3 light) +{ + return (light * scene_light_strength); +} + +vec3 atmosAmbient(vec3 light) +{ + return getAmblitColor() + light / 2.0; +} + +vec3 atmosAffectDirectionalLight(float lightIntensity) +{ + return getSunlitColor() * lightIntensity; +} + +vec3 scaleSoftClip(vec3 light) +{ + //soft clip effect: + light = 1. - clamp(light, vec3(0.), vec3(1.)); + light = 1. - pow(light, gamma.xxx); + + return light; +} + +void main() +{ + vec2 tc = vary_fragcoord.xy; + vec3 pos = getPosition(tc).xyz; + vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0; + vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; + + vec3 at = normalize(pos); + + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + + vec3 lum = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb; + + vec3 ha = normalize(vary_light.xyz-at); + + float da = dot(ha, norm.xyz); + da = texture2D(lightFunc, vec2(da, spec.a)).a; + + vec4 diffuse = texture2DRect(diffuseRect, tc); + + vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; + float scol = max(scol_ambocc.r, diffuse.a); + float ambocc = scol_ambocc.g; + + calcAtmospherics(pos.xyz, ambocc); + + vec3 col = vec3(0,0,0); + + col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a)*(1.0+spec.a)); + + col *= diffuse.rgb; + + col += da*spec.rgb*spec.a*vary_SunlitColor*scol_ambocc.r; + + /*if (spec.a > 0.0) + { + vec3 ref = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(ref, vary_light.xyz); + col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; + }*/ + + col = atmosLighting(col); + col = scaleSoftClip(col); + + col = col*vec3(1.0+1.0/2.2); + + gl_FragColor.rgb = col; + //gl_FragColor.rgb = lum; + + gl_FragColor.a = 0.0; + + //gl_FragColor.rg = scol_ambocc.rg; + //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb; + //gl_FragColor.rgb = norm.rgb*0.5+0.5; + //gl_FragColor.rgb = vec3(ambocc); + //gl_FragColor.rgb = vec3(scol); +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl new file mode 100644 index 0000000..ad8af47 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl @@ -0,0 +1,24 @@ +/** + * @file softenLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform vec2 screen_res; + +varying vec4 vary_light; +varying vec2 vary_fragcoord; +void main() +{ + //transform vertex + gl_Position = ftransform(); + + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; + + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + vary_light = gl_MultiTexCoord0; +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl new file mode 100644 index 0000000..258acee --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl @@ -0,0 +1,18 @@ +/** + * @file treeF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; + +varying vec3 vary_normal; + +void main() +{ + vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); + gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005); + gl_FragData[1] = vec4(0,0,0,0); + gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); +} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl new file mode 100644 index 0000000..bea1515 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl @@ -0,0 +1,139 @@ +/** + * @file waterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +vec3 scaleSoftClip(vec3 inColor); +vec3 atmosTransport(vec3 inColor); + +uniform sampler2D bumpMap; +uniform sampler2D screenTex; +uniform sampler2D refTex; +uniform sampler2DRectShadow shadowMap0; +uniform sampler2DRectShadow shadowMap1; +uniform sampler2DRectShadow shadowMap2; +uniform sampler2DRectShadow shadowMap3; +uniform sampler2D noiseMap; + +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; + +uniform float sunAngle; +uniform float sunAngle2; +uniform vec3 lightDir; +uniform vec3 specular; +uniform float lightExp; +uniform float refScale; +uniform float kd; +uniform vec2 screenRes; +uniform vec3 normScale; +uniform float fresnelScale; +uniform float fresnelOffset; +uniform float blurMultiplier; +uniform vec2 screen_res; +uniform mat4 norm_mat; //region space to screen space + +//bigWave is (refCoord.w, view.w); +varying vec4 refCoord; +varying vec4 littleWave; +varying vec4 view; +varying vec4 vary_position; + +void main() +{ + vec4 color; + float dist = length(view.xy); + + //normalize view vector + vec3 viewVec = normalize(view.xyz); + + //get wave normals + vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0; + vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0; + vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0; + //get base fresnel components + + vec3 df = vec3( + dot(viewVec, wave1), + dot(viewVec, (wave2 + wave3) * 0.5), + dot(viewVec, wave3) + ) * fresnelScale + fresnelOffset; + df *= df; + + vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; + + float dist2 = dist; + dist = max(dist, 5.0); + + float dmod = sqrt(dist); + + vec2 dmod_scale = vec2(dmod*dmod, dmod); + + //get reflected color + vec2 refdistort1 = wave1.xy*normScale.x; + vec2 refvec1 = distort+refdistort1/dmod_scale; + vec4 refcol1 = texture2D(refTex, refvec1); + + vec2 refdistort2 = wave2.xy*normScale.y; + vec2 refvec2 = distort+refdistort2/dmod_scale; + vec4 refcol2 = texture2D(refTex, refvec2); + + vec2 refdistort3 = wave3.xy*normScale.z; + vec2 refvec3 = distort+refdistort3/dmod_scale; + vec4 refcol3 = texture2D(refTex, refvec3); + + vec4 refcol = refcol1 + refcol2 + refcol3; + float df1 = df.x + df.y + df.z; + refcol *= df1 * 0.333; + + vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5; + //wavef.z *= max(-viewVec.z, 0.1); + wavef = normalize(wavef); + + float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset; + + vec2 refdistort4 = wavef.xy*0.125; + refdistort4.y -= abs(refdistort4.y); + vec2 refvec4 = distort+refdistort4/dmod; + float dweight = min(dist2*blurMultiplier, 1.0); + vec4 baseCol = texture2D(refTex, refvec4); + refcol = mix(baseCol*df2, refcol, dweight); + + //get specular component + //float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0); + + //harden specular + //spec = pow(spec, 128.0); + + //figure out distortion vector (ripply) + vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0); + + vec4 fb = texture2D(screenTex, distort2); + + //mix with reflection + // Note we actually want to use just df1, but multiplying by 0.999999 gets around and nvidia compiler bug + color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999); + + float shadow = 1.0; + vec4 pos = vary_position; + + vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; + vec4 spos = pos; + + //spec *= shadow; + //color.rgb += spec * specular; + + //color.rgb = atmosTransport(color.rgb); + //color.rgb = scaleSoftClip(color.rgb); + //color.a = spec * sunAngle2; + + //wavef.z *= 0.1f; + wavef = normalize(wavef); + wavef = (norm_mat*vec4(wavef, 1.0)).xyz; + + gl_FragData[0] = vec4(color.rgb, 0.5); + gl_FragData[1] = vec4(0.5,0.5,0.5, 0.95); + gl_FragData[2] = vec4(wavef*0.5+0.5, 0.f); +} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/blurF.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/blurF.glsl new file mode 100644 index 0000000..9443320 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/effects/blurF.glsl @@ -0,0 +1,31 @@ +/** + * @file blurf.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2DRect RenderTexture; +uniform float bloomStrength; + +varying vec4 gl_TexCoord[gl_MaxTextureCoords]; +void main(void) +{ + float blurWeights[7]; + blurWeights[0] = 0.05; + blurWeights[1] = 0.1; + blurWeights[2] = 0.2; + blurWeights[3] = 0.3; + blurWeights[4] = 0.2; + blurWeights[5] = 0.1; + blurWeights[6] = 0.05; + + vec3 color = vec3(0,0,0); + for (int i = 0; i < 7; i++){ + color += vec3(texture2DRect(RenderTexture, gl_TexCoord[i].st)) * blurWeights[i]; + } + + color *= bloomStrength; + + gl_FragColor = vec4(color, 1.0); +} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/blurV.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/blurV.glsl new file mode 100644 index 0000000..ba65b16 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/effects/blurV.glsl @@ -0,0 +1,35 @@ +/** + * @file blurV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform vec2 texelSize; +uniform vec2 blurDirection; +uniform float blurWidth; + +void main(void) +{ + // Transform vertex + gl_Position = ftransform(); + + vec2 blurDelta = texelSize * blurDirection * vec2(blurWidth, blurWidth); + vec2 s = gl_MultiTexCoord0.st - (blurDelta * 3.0); + + // for (int i = 0; i < 7; i++) { + // gl_TexCoord[i].st = s + (i * blurDelta); + // } + + // MANUALLY UNROLL + gl_TexCoord[0].st = s; + gl_TexCoord[1].st = s + blurDelta; + gl_TexCoord[2].st = s + (2. * blurDelta); + gl_TexCoord[3].st = s + (3. * blurDelta); + gl_TexCoord[4].st = s + (4. * blurDelta); + gl_TexCoord[5].st = s + (5. * blurDelta); + gl_TexCoord[6].st = s + (6. * blurDelta); + + // gl_TexCoord[0].st = s; + // gl_TexCoord[1].st = blurDelta; +} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/colorFilterF.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/colorFilterF.glsl new file mode 100644 index 0000000..623ef7a --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/effects/colorFilterF.glsl @@ -0,0 +1,31 @@ +/** + * @file colorFilterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2DRect RenderTexture; +uniform float brightness; +uniform float contrast; +uniform vec3 contrastBase; +uniform float saturation; +uniform vec3 lumWeights; + +const float gamma = 2.0; + +void main(void) +{ + vec3 color = vec3(texture2DRect(RenderTexture, gl_TexCoord[0].st)); + + /// Modulate brightness + color *= brightness; + + /// Modulate contrast + color = mix(contrastBase, color, contrast); + + /// Modulate saturation + color = mix(vec3(dot(color, lumWeights)), color, saturation); + + gl_FragColor = vec4(color, 1.0); +} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/drawQuadV.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/drawQuadV.glsl new file mode 100644 index 0000000..29c2a09 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/effects/drawQuadV.glsl @@ -0,0 +1,14 @@ +/** + * @file drawQuadV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +void main(void) +{ + //transform vertex + gl_Position = ftransform(); + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[1] = gl_MultiTexCoord1; +} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/extractF.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/extractF.glsl new file mode 100644 index 0000000..a1583b1 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/effects/extractF.glsl @@ -0,0 +1,22 @@ +/** + * @file extractF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2DRect RenderTexture; +uniform float extractLow; +uniform float extractHigh; +uniform vec3 lumWeights; + +void main(void) +{ + /// Get scene color + vec3 color = vec3(texture2DRect(RenderTexture, gl_TexCoord[0].st)); + + /// Extract luminance and scale up by night vision brightness + float lum = smoothstep(extractLow, extractHigh, dot(color, lumWeights)); + + gl_FragColor = vec4(vec3(lum), 1.0); +} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/nightVisionF.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/nightVisionF.glsl new file mode 100644 index 0000000..271d5cf --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/effects/nightVisionF.glsl @@ -0,0 +1,42 @@ +/** + * @file nightVisionF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2DRect RenderTexture; +uniform sampler2D NoiseTexture; +uniform float brightMult; +uniform float noiseStrength; + +float luminance(vec3 color) +{ + /// CALCULATING LUMINANCE (Using NTSC lum weights) + /// http://en.wikipedia.org/wiki/Luma_%28video%29 + return dot(color, vec3(0.299, 0.587, 0.114)); +} + +void main(void) +{ + /// Get scene color + vec3 color = vec3(texture2DRect(RenderTexture, gl_TexCoord[0].st)); + + /// Extract luminance and scale up by night vision brightness + float lum = luminance(color) * brightMult; + + /// Convert into night vision color space + /// Newer NVG colors (crisper and more saturated) + vec3 outColor = (lum * vec3(0.91, 1.21, 0.9)) + vec3(-0.07, 0.1, -0.12); + + /// Add noise + float noiseValue = texture2D(NoiseTexture, gl_TexCoord[1].st).r; + noiseValue = (noiseValue - 0.5) * noiseStrength; + + /// Older NVG colors (more muted) + // vec3 outColor = (lum * vec3(0.82, 0.75, 0.83)) + vec3(0.05, 0.32, -0.11); + + outColor += noiseValue; + + gl_FragColor = vec4(outColor, 1.0); +} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/simpleF.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/simpleF.glsl new file mode 100644 index 0000000..e55d278 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/effects/simpleF.glsl @@ -0,0 +1,14 @@ +/** + * @file simpleF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2DRect RenderTexture; + +void main(void) +{ + vec3 color = vec3(texture2DRect(RenderTexture, gl_TexCoord[0].st)); + gl_FragColor = vec4(1.0 - color, 1.0); +} diff --git a/linden/indra/newview/llagent.cpp b/linden/indra/newview/llagent.cpp index 5bcffdb..4342e60 100644 --- a/linden/indra/newview/llagent.cpp +++ b/linden/indra/newview/llagent.cpp @@ -223,6 +223,7 @@ LLAgent gAgent; // Statics // BOOL LLAgent::sPhantom = FALSE; +BOOL LLAgent::sDebugDisplayTarget = FALSE; const F32 LLAgent::TYPING_TIMEOUT_SECS = 5.f; @@ -6618,7 +6619,7 @@ void LLAgent::saveWearable( EWearableType type, BOOL send_update ) return; } - getAvatarObject()->wearableUpdated( type ); + // getAvatarObject()->wearableUpdated( type ); if( send_update ) { diff --git a/linden/indra/newview/llagent.h b/linden/indra/newview/llagent.h index 3a39448..d3c16c5 100644 --- a/linden/indra/newview/llagent.h +++ b/linden/indra/newview/llagent.h @@ -765,6 +765,7 @@ public: BOOL mInitialized; + static BOOL sDebugDisplayTarget; S32 mNumPendingQueries; S32* mActiveCacheQueries; diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp index 86c83b9..a9a6052 100644 --- a/linden/indra/newview/llappviewer.cpp +++ b/linden/indra/newview/llappviewer.cpp @@ -447,7 +447,7 @@ static void settings_modify() LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4] gDebugGL = gSavedSettings.getBOOL("RenderDebugGL"); gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline"); - gAuditTexture = gSavedSettings.getBOOL("AuditTexture"); +// gAuditTexture = gSavedSettings.getBOOL("AuditTexture"); #if LL_VECTORIZE if (gSysCPU.hasAltivec()) { diff --git a/linden/indra/newview/llcolorswatch.cpp b/linden/indra/newview/llcolorswatch.cpp index 5905bb0..3222c0d 100644 --- a/linden/indra/newview/llcolorswatch.cpp +++ b/linden/indra/newview/llcolorswatch.cpp @@ -219,11 +219,12 @@ void LLColorSwatchCtrl::draw() gl_rect_2d(interior, mColor, TRUE); LLColor4 opaque_color = mColor; opaque_color.mV[VALPHA] = 1.f; + gGL.color4fv(opaque_color.mV); if (mAlphaGradientImage.notNull()) { gGL.pushMatrix(); { - mAlphaGradientImage->draw(interior, opaque_color); + mAlphaGradientImage->draw(interior, mColor); } gGL.popMatrix(); } diff --git a/linden/indra/newview/llcompilequeue.cpp b/linden/indra/newview/llcompilequeue.cpp index ed18a10..a81972d 100644 --- a/linden/indra/newview/llcompilequeue.cpp +++ b/linden/indra/newview/llcompilequeue.cpp @@ -58,7 +58,6 @@ #include "llfloaterchat.h" #include "llviewerstats.h" #include "lluictrlfactory.h" -#include "llselectmgr.h" ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs diff --git a/linden/indra/newview/llconsole.cpp b/linden/indra/newview/llconsole.cpp index 2379da3..a8554a0 100644 --- a/linden/indra/newview/llconsole.cpp +++ b/linden/indra/newview/llconsole.cpp @@ -63,17 +63,25 @@ const S32 CONSOLE_GUTTER_LEFT = 14; const S32 CONSOLE_GUTTER_RIGHT = 15; -LLConsole::LLConsole(const std::string& name, const U32 max_lines, const LLRect &rect, +LLConsole::LLConsole(const std::string& name, const LLRect &rect, S32 font_size_index, F32 persist_time ) - : - LLFixedBuffer(max_lines), - LLView(name, rect, FALSE) + : LLFixedBuffer(), + LLView(name, rect, FALSE), + mLinePersistTime(persist_time), + mFadeTime(persist_time - FADE_DURATION), + mFont(LLFontGL::getFontSansSerif()), + mConsoleWidth(0), + mConsoleHeight(0), + mQueueMutex(NULL) { - mLinePersistTime = persist_time; // seconds - mFadeTime = persist_time - FADE_DURATION; + mTimer.reset(); - setFontSize( font_size_index ); - setMaxLines(gSavedSettings.getS32("ConsoleMaxLines")); + setFontSize( font_size_index ); +} + +LLConsole::~LLConsole() +{ + clear(); } void LLConsole::setLinePersistTime(F32 seconds) @@ -98,10 +106,10 @@ void LLConsole::reshape(S32 width, S32 height, BOOL called_from_parent) mConsoleHeight= new_height; LLView::reshape(new_width, new_height, called_from_parent); - + for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++) { - (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true); + (*paragraph_it)->updateLines((F32)getRect().getWidth(), mFont, true); } } @@ -126,7 +134,7 @@ void LLConsole::setFontSize(S32 size_index) for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++) { - (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true); + (*paragraph_it)->updateLines((F32)getRect().getWidth(), mFont, true); } } @@ -134,35 +142,49 @@ void LLConsole::draw() { LLGLSUIDefault gls_ui; - // skip lines added more than mLinePersistTime ago - F32 cur_time = mTimer.getElapsedTimeF32(); - - F32 skip_time = cur_time - mLinePersistTime; - F32 fade_time = cur_time - mFadeTime; - - updateBuffer() ; + { + LLMutexLock lock(&mQueueMutex); + for(paragraph_t::iterator paragraph_it = mNewParagraphs.begin(); paragraph_it != mNewParagraphs.end(); paragraph_it++) + { + Paragraph* paragraph = *paragraph_it; + mParagraphs.push_back(paragraph); + paragraph->updateLines((F32)getRect().getWidth(), mFont); + } + mNewParagraphs.clear(); + } if (mParagraphs.empty()) //No text to draw. { return; } + // skip lines added more than mLinePersistTime ago + F32 cur_time = mTimer.getElapsedTimeF32(); + + F32 skip_time = cur_time - mLinePersistTime; + F32 fade_time = cur_time - mFadeTime; + + U32 max_lines = gSavedSettings.getS32("ConsoleMaxLines"); U32 num_lines=0; paragraph_t::reverse_iterator paragraph_it; paragraph_it = mParagraphs.rbegin(); U32 paragraph_num=mParagraphs.size(); - + while (!mParagraphs.empty() && paragraph_it != mParagraphs.rend()) { - num_lines += (*paragraph_it).mLines.size(); - if(num_lines > mMaxLines - || ( (mLinePersistTime > (F32)0.f) && ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime) <= (F32)0.f)) + num_lines += (*paragraph_it)->mLines.size(); + if(num_lines > max_lines + || ( (mLinePersistTime > (F32)0.f) && ((*paragraph_it)->mAddTime - skip_time)/(mLinePersistTime - mFadeTime) <= (F32)0.f)) { //All lines above here are done. Lose them. for (U32 i=0;i<paragraph_num;i++) { if (!mParagraphs.empty()) + { + Paragraph* paragraph = mParagraphs.front(); mParagraphs.pop_front(); + delete paragraph; + } } break; } @@ -193,8 +215,8 @@ void LLConsole::draw() S32 bkg_width=0; for(paragraph_it = mParagraphs.rbegin(); paragraph_it != mParagraphs.rend(); paragraph_it++) { - S32 target_height = llfloor( (*paragraph_it).mLines.size() * line_height + message_spacing); - S32 target_width = llfloor( (*paragraph_it).mMaxWidth + CONSOLE_GUTTER_RIGHT); + S32 target_height = llfloor( (*paragraph_it)->mLines.size() * line_height + message_spacing); + S32 target_width = llfloor( (*paragraph_it)->mMaxWidth + CONSOLE_GUTTER_RIGHT); bkg_height+= target_height; if (target_width > bkg_width) @@ -203,7 +225,7 @@ void LLConsole::draw() } // Why is this not using llfloor as above? - y_pos += ((*paragraph_it).mLines.size()) * line_height; + y_pos += ((*paragraph_it)->mLines.size()) * line_height; y_pos += message_spacing; //Extra spacing between messages. } imagep->drawSolid(-CONSOLE_GUTTER_LEFT, (S32)(y_pos + line_height - bkg_height - message_spacing), bkg_width, bkg_height, color); @@ -213,10 +235,10 @@ void LLConsole::draw() for(paragraph_it = mParagraphs.rbegin(); paragraph_it != mParagraphs.rend(); paragraph_it++) { //080813 Spatters: Dainty per-message block boxes -// S32 target_height = llfloor( (*paragraph_it).mLines.size() * line_height + 8); - S32 target_width = llfloor( (*paragraph_it).mMaxWidth + CONSOLE_GUTTER_RIGHT); +// S32 target_height = llfloor( (*paragraph_it)->mLines.size() * line_height + 8); + S32 target_width = llfloor( (*paragraph_it)->mMaxWidth + CONSOLE_GUTTER_RIGHT); - y_pos += ((*paragraph_it).mLines.size()) * line_height; + y_pos += ((*paragraph_it)->mLines.size()) * line_height; //080813 Spatters: Dainty per-message block boxes // imagep->drawSolid(-14, (S32)(y_pos + line_height - target_height), target_width, target_height, color); @@ -224,9 +246,9 @@ void LLConsole::draw() F32 alpha; - if ((mLinePersistTime > 0.f) && ((*paragraph_it).mAddTime < fade_time)) + if ((mLinePersistTime > 0.f) && ((*paragraph_it)->mAddTime < fade_time)) { - alpha = ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime); + alpha = ((*paragraph_it)->mAddTime - skip_time)/(mLinePersistTime - mFadeTime); } else { @@ -235,12 +257,12 @@ void LLConsole::draw() if( alpha > 0.f ) { - for (lines_t::iterator line_it=(*paragraph_it).mLines.begin(); - line_it != (*paragraph_it).mLines.end(); + for (lines_t::iterator line_it=(*paragraph_it)->mLines.begin(); + line_it != (*paragraph_it)->mLines.end(); line_it ++) { - for (line_color_segments_t::iterator seg_it = (*line_it).mLineColorSegments.begin(); - seg_it != (*line_it).mLineColorSegments.end(); + for (line_color_segments_t::iterator seg_it = (*line_it).begin(); + seg_it != (*line_it).end(); seg_it++) { mFont->render((*seg_it).mText, 0, (*seg_it).mXPosition - 8, y_pos - y_off, @@ -263,21 +285,34 @@ void LLConsole::draw() } } -void LLConsole::addLine(const std::string& utf8line) +//virtual +void LLConsole::clear() { - LLWString wline = utf8str_to_wstring(utf8line); - addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f)); + mTimer.reset(); + LLMutexLock lock(&mQueueMutex); + std::for_each(mParagraphs.begin(), mParagraphs.end(), DeletePointer()); + mParagraphs.clear(); + std::for_each(mNewParagraphs.begin(), mNewParagraphs.end(), DeletePointer()); + mNewParagraphs.clear(); } -void LLConsole::addLine(const LLWString& wline) +//virtual +void LLConsole::addLine(const std::string& utf8line) { - addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f)); + addConsoleLine(utf8line, LLColor4(1.f, 1.f, 1.f, 1.f)); } -void LLConsole::addLine(const std::string& utf8line, F32 size, const LLColor4 &color) +void LLConsole::addConsoleLine(const std::string& utf8line, const LLColor4 &color) { LLWString wline = utf8str_to_wstring(utf8line); - addLine(wline, size, color); + addConsoleLine(wline, color); +} + +void LLConsole::addConsoleLine(const LLWString& wline, const LLColor4 &color) +{ + Paragraph* paragraph = new Paragraph(wline, color, mTimer.getElapsedTimeF32()); + LLMutexLock lock(&mQueueMutex); + mNewParagraphs.push_back ( paragraph ); } //Generate highlight color segments for this paragraph. Pass in default color of paragraph. @@ -359,7 +394,7 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, LLFontGL* font, bool fo F32 x_position = 0; //Screen X position of text. mMaxWidth = llmax( mMaxWidth, (F32)font->getWidth( mParagraphText.substr( paragraph_offset, drawable ).c_str() ) ); - Line line; + line_color_segments_t line; U32 left_to_draw = drawable; U32 drawn = 0; @@ -368,7 +403,7 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, LLFontGL* font, bool fo && current_color != mParagraphColorSegments.end() ) { LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, current_color_length ); - line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line. + line.push_back( LineColorSegment( color_text, //Append segment to line. (*current_color).mColor, x_position ) ); @@ -389,7 +424,7 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, LLFontGL* font, bool fo { LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, left_to_draw ); - line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line. + line.push_back( LineColorSegment( color_text, //Append segment to line. (*current_color).mColor, x_position ) ); @@ -407,50 +442,9 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, LLFontGL* font, bool fo } //Pass in the string and the default color for this block of text. -LLConsole::Paragraph::Paragraph (LLWString str, const LLColor4 &color, F32 add_time, LLFontGL* font, F32 screen_width) +LLConsole::Paragraph::Paragraph (LLWString str, const LLColor4 &color, F32 add_time) : mParagraphText(str), mAddTime(add_time), mMaxWidth(-1) { makeParagraphColorSegments(color); - updateLines( screen_width, font ); } -void LLConsole::addLine(const LLWString& wline, F32 size, const LLColor4 &color) -{ - Paragraph paragraph(wline, color, mTimer.getElapsedTimeF32(), mFont, (F32)getRect().getWidth() ); - - mParagraphs.push_back ( paragraph ); - -#if LL_WINDOWS && LL_LCD_COMPILE - // add to LCD screen - AddNewDebugConsoleToLCD(wline); -#endif -} - -// -//check if there are some messages stored in the buffer -//if yes, output them. -// -void LLConsole::updateBuffer() -{ - BOOL need_clear = FALSE ; - - mMutex.lock() ; - if(!mLines.empty()) - { - S32 end = mLines.size() ; - LLColor4 color(1.f, 1.f, 1.f, 1.f) ; - for(S32 i = 0 ; i < end ; i++) - { - Paragraph paragraph(mLines[i], color, mAddTimes[i], mFont, (F32)getRect().getWidth() ); - mParagraphs.push_back ( paragraph ); - } - - need_clear = TRUE ; - } - mMutex.unlock() ; - - if(need_clear) - { - clear() ; - } -} diff --git a/linden/indra/newview/llconsole.h b/linden/indra/newview/llconsole.h index 2915c48..578670e 100644 --- a/linden/indra/newview/llconsole.h +++ b/linden/indra/newview/llconsole.h @@ -33,7 +33,8 @@ #ifndef LL_LLCONSOLE_H #define LL_LLCONSOLE_H -#include "llfixedbuffer.h" +#include "llerrorcontrol.h" // For LLLineBuffer +#include "llthread.h" #include "llview.h" #include "v4color.h" #include <deque> @@ -47,10 +48,10 @@ private: F32 mLinePersistTime; // Age at which to stop drawing. F32 mFadeTime; // Age at which to start fading LLFontGL* mFont; - S32 mLastBoxHeight; - S32 mLastBoxWidth; S32 mConsoleWidth; S32 mConsoleHeight; + LLMutex mQueueMutex; + LLTimer mTimer; public: //A paragraph color segment defines the color of text in a line @@ -80,14 +81,7 @@ public: typedef std::list<LineColorSegment> line_color_segments_t; - //A line is composed of one or more color segments. - class Line - { - public: - line_color_segments_t mLineColorSegments; - }; - - typedef std::list<Line> lines_t; + typedef std::list<line_color_segments_t> lines_t; typedef std::list<ParagraphColorSegment> paragraph_color_segments_t; //A paragraph is a processed element containing the entire text of the @@ -98,7 +92,7 @@ public: class Paragraph { public: - Paragraph (LLWString str, const LLColor4 &color, F32 add_time, LLFontGL* font, F32 screen_width); + Paragraph (LLWString str, const LLColor4 &color, F32 add_time); void makeParagraphColorSegments ( const LLColor4 &color); void updateLines ( F32 screen_width, LLFontGL* font, bool force_resize=false ); public: @@ -111,35 +105,32 @@ public: }; //The console contains a deque of paragraphs which represent the individual messages. - typedef std::deque<Paragraph> paragraph_t; + typedef std::deque<Paragraph*> paragraph_t; paragraph_t mParagraphs; + paragraph_t mNewParagraphs; // Font size: // -1 = monospace, 0 means small, font size = 1 means big - LLConsole(const std::string& name, const U32 max_lines, const LLRect &rect, - S32 font_size_index, F32 persist_time ); - ~LLConsole(){}; + LLConsole(const std::string& name, const LLRect &rect, + S32 font_size_index, F32 persist_time ); + ~LLConsole(); // each line lasts this long after being added - void setLinePersistTime(F32 seconds); + void setLinePersistTime(F32 seconds); - void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); // -1 = monospace, 0 means small, font size = 1 means big - void setFontSize(S32 size_index); + void setFontSize(S32 size_index); - void addLine(const std::string& utf8line, F32 size, const LLColor4 &color); - void addLine(const LLWString& wline, F32 size, const LLColor4 &color); + // From LLLineBuffer + /*virtual*/ void clear(); + /*virtual*/ void addLine(const std::string& utf8line); + void addConsoleLine(const std::string& utf8line, const LLColor4 &color); + void addConsoleLine(const LLWString& wline, const LLColor4 &color); // Overrides /*virtual*/ void draw(); - - //do not make these two "virtual" - void addLine(const std::string& utf8line); - void addLine(const LLWString& line); - -private: - void updateBuffer() ; }; extern LLConsole* gConsole; diff --git a/linden/indra/newview/lldebugview.cpp b/linden/indra/newview/lldebugview.cpp index 40f5202..a6d6f2d 100644 --- a/linden/indra/newview/lldebugview.cpp +++ b/linden/indra/newview/lldebugview.cpp @@ -62,7 +62,7 @@ LLDebugView::LLDebugView(const std::string& name, const LLRect &rect) LLRect r; r.set(10, rect.getHeight() - 100, rect.getWidth()/2, 100); - mDebugConsolep = new LLConsole("debug console", 20, r, -1, 0.f ); + mDebugConsolep = new LLConsole("debug console", r, -1, 0.f ); mDebugConsolep->setFollowsBottom(); mDebugConsolep->setFollowsLeft(); mDebugConsolep->setVisible( FALSE ); @@ -98,6 +98,27 @@ LLDebugView::LLDebugView(const std::string& name, const LLRect &rect) addChild(gTextureView); //gTextureView->reshape(r.getWidth(), r.getHeight(), TRUE); +/* +//there seems to be some debug code, we don't have +#if !LL_RELEASE_FOR_DOWNLOAD + r.set(150, rect.getHeight() - 50, 900 + LLImageGL::sTextureLoadedCounter.size() * 30, 100); + gTextureSizeView = new LLTextureSizeView("gTextureSizeView"); + gTextureSizeView->setRect(r); + gTextureSizeView->setFollowsBottom(); + gTextureSizeView->setFollowsLeft(); + addChild(gTextureSizeView); + + + r.set(150, rect.getHeight() - 50, 900 + LLImageGL::sTextureMemByCategory.size() * 30, 100); + gTextureCategoryView = new LLTextureSizeView("gTextureCategoryView"); + gTextureCategoryView->setRect(r); + gTextureCategoryView->setFollowsBottom(); + gTextureCategoryView->setFollowsLeft(); + gTextureCategoryView->setType(LLTextureSizeView::TEXTURE_MEM_OVER_CATEGORY); + addChild(gTextureCategoryView); +#endif +*/ + const S32 VELOCITY_LEFT = 10; // 370; const S32 VELOCITY_WIDTH = 500; const S32 VELOCITY_TOP = 140; @@ -115,5 +136,6 @@ LLDebugView::~LLDebugView() // These have already been deleted. Fix the globals appropriately. gDebugView = NULL; gTextureView = NULL; + gTextureSizeView = NULL; } diff --git a/linden/indra/newview/lldrawable.cpp b/linden/indra/newview/lldrawable.cpp index 14aa38a..99577e3 100644 --- a/linden/indra/newview/lldrawable.cpp +++ b/linden/indra/newview/lldrawable.cpp @@ -102,7 +102,7 @@ void LLDrawable::init() mVObjp = NULL; // mFaces mSpatialGroupp = NULL; - mVisible = sCurVisible - 2;//invisible for the current frame and the last frame. + mVisible = 0; mRadius = 0.f; mGeneration = -1; @@ -125,7 +125,7 @@ void LLDrawable::destroy() if (LLSpatialGroup::sNoDelete) { - llerrs << "Illegal deletion of LLDrawable!" << llendl; + llwarns << "Illegal deletion of LLDrawable!" << llendl; } std::for_each(mFaces.begin(), mFaces.end(), DeletePointer()); @@ -234,7 +234,7 @@ LLFace* LLDrawable::addFace(LLFacePool *poolp, LLViewerImage *texturep) LLMemType mt(LLMemType::MTYPE_DRAWABLE); LLFace *face = new LLFace(this, mVObjp); - if (!face) llerrs << "Allocating new Face: " << mFaces.size() << llendl; + if (!face) llwarns << "Allocating new Face: " << mFaces.size() << llendl; if (face) { @@ -346,7 +346,7 @@ void LLDrawable::deleteFaces(S32 offset, S32 count) void LLDrawable::update() { - llerrs << "Shouldn't be called!" << llendl; + llwarns << "Shouldn't be called!" << llendl; } @@ -368,7 +368,7 @@ void LLDrawable::makeActive() pcode == LLViewerObject::LL_VO_GROUND || pcode == LLViewerObject::LL_VO_SKY) { - llerrs << "Static viewer object has active drawable!" << llendl; + llwarns << "Static viewer object has active drawable!" << llendl; } } #endif @@ -692,19 +692,22 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) pos += volume->getRegion()->getOriginAgent(); } - for (S32 i = 0; i < getNumFaces(); i++) + if (isState(LLDrawable::HAS_ALPHA)) { - LLFace* facep = getFace(i); - if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA) + for (S32 i = 0; i < getNumFaces(); i++) { - LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f; - LLVector3 v = (facep->mCenterLocal-camera.getOrigin()); - LLVector3 at = camera.getAtAxis(); - for (U32 j = 0; j < 3; j++) + LLFace* facep = getFace(i); + if (facep->getPoolType() == LLDrawPool::POOL_ALPHA) { - v.mV[j] -= box.mV[j] * at.mV[j]; + LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f; + LLVector3 v = (facep->mCenterLocal-camera.getOrigin()); + const LLVector3& at = camera.getAtAxis(); + for (U32 j = 0; j < 3; j++) + { + v.mV[j] -= box.mV[j] * at.mV[j]; + } + facep->mDistance = v * camera.getAtAxis(); } - facep->mDistance = v * camera.getAtAxis(); } } } @@ -736,7 +739,11 @@ void LLDrawable::updateTexture() if (getVOVolume()) { - if (isActive()) + if (!isActive()) + { + //gPipeline.markMoved(this); + } + else { if (isRoot()) { @@ -1003,8 +1010,8 @@ BOOL LLDrawable::isVisible() const // Spatial Partition Bridging Drawable //======================================= -LLSpatialBridge::LLSpatialBridge(LLDrawable* root, U32 data_mask) -: LLSpatialPartition(data_mask, FALSE) +LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask) // KL Sd version +: LLSpatialPartition(data_mask, render_by_group, FALSE) { mDrawable = root; root->setSpatialBridge(this); @@ -1134,26 +1141,26 @@ void LLDrawable::setVisible(LLCamera& camera, std::vector<LLDrawable*>* results, { if (isActive() && !mParent->isActive()) { - llerrs << "Active drawable has static parent!" << llendl; + llwarns << "Active drawable has static parent!" << llendl; } if (isStatic() && !mParent->isStatic()) { - llerrs << "Static drawable has active parent!" << llendl; + llwarns << "Static drawable has active parent!" << llendl; } if (mSpatialBridge) { - llerrs << "Child drawable has spatial bridge!" << llendl; + llwarns << "Child drawable has spatial bridge!" << llendl; } } else if (isActive() && !mSpatialBridge) { - llerrs << "Active root drawable has no spatial bridge!" << llendl; + llwarns << "Active root drawable has no spatial bridge!" << llendl; } else if (isStatic() && mSpatialBridge.notNull()) { - llerrs << "Static drawable has spatial bridge!" << llendl; + llwarns << "Static drawable has spatial bridge!" << llendl; } } #endif @@ -1277,12 +1284,25 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update) return; } - LLCamera camera = transformCamera(camera_in); + if (mDrawable->getVObj()) + { + if (mDrawable->getVObj()->isAttachment()) + { + LLDrawable* parent = mDrawable->getParent(); + if (parent && parent->getVObj()) + { + LLVOAvatar* av = parent->getVObj()->asAvatar(); + if (av && av->isImpostor()) + { + return; + } + } + } + + LLCamera camera = transformCamera(camera_in); mDrawable->updateDistance(camera, force_update); - if (mDrawable->getVObj()) - { LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); iter++) @@ -1304,7 +1324,7 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update) void LLSpatialBridge::makeActive() { //it is an error to make a spatial bridge active (it's already active) - llerrs << "makeActive called on spatial bridge" << llendl; + llwarns << "makeActive called on spatial bridge" << llendl; } void LLSpatialBridge::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate) @@ -1420,9 +1440,9 @@ void LLDrawable::updateFaceSize(S32 idx) } LLBridgePartition::LLBridgePartition() -: LLSpatialPartition(0, TRUE) +: LLSpatialPartition(0, FALSE, 0) { - mRenderByGroup = FALSE; + //mRenderByGroup = FALSE; // KL mDrawableType = LLPipeline::RENDER_TYPE_AVATAR; mPartitionType = LLViewerRegion::PARTITION_BRIDGE; mLODPeriod = 16; diff --git a/linden/indra/newview/lldrawable.h b/linden/indra/newview/lldrawable.h index 71b75dc..e6753b5 100644 --- a/linden/indra/newview/lldrawable.h +++ b/linden/indra/newview/lldrawable.h @@ -267,7 +267,8 @@ public: BUILT = 0x08000000, FORCE_INVISIBLE = 0x10000000, // stay invis until CLEAR_INVISIBLE is set (set of orphaned) CLEAR_INVISIBLE = 0x20000000, // clear FORCE_INVISIBLE next draw frame - REBUILD_SHADOW = 0x40000000 + REBUILD_SHADOW = 0x40000000, + HAS_ALPHA = 0x80000000, } EDrawableFlags; LLXformMatrix mXform; diff --git a/linden/indra/newview/lldrawpool.h b/linden/indra/newview/lldrawpool.h index 87c3cca..9052710 100644 --- a/linden/indra/newview/lldrawpool.h +++ b/linden/indra/newview/lldrawpool.h @@ -67,6 +67,11 @@ public: POOL_GLOW, POOL_ALPHA, NUM_POOL_TYPES, + // * invisiprims work by rendering to the depth buffer but not the color buffer, occluding anything rendered after them + // - and the LLDrawPool types enum controls what order things are rendered in + // - so, it has absolute control over what invisprims block + // ...invisiprims being rendered in pool_invisible + // ...shiny/bump mapped objects in rendered in POOL_BUMP }; LLDrawPool(const U32 type); diff --git a/linden/indra/newview/lldrawpoolalpha.cpp b/linden/indra/newview/lldrawpoolalpha.cpp index 4b552ac..c9c06f4 100644 --- a/linden/indra/newview/lldrawpoolalpha.cpp +++ b/linden/indra/newview/lldrawpoolalpha.cpp @@ -88,7 +88,12 @@ void LLDrawPoolAlpha::beginDeferredPass(S32 pass) void LLDrawPoolAlpha::endDeferredPass(S32 pass) { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.4f); + +} + +void LLDrawPoolAlpha::renderDeferred(S32 pass) +{ + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); { LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); gDeferredTreeProgram.bind(); @@ -99,11 +104,6 @@ void LLDrawPoolAlpha::endDeferredPass(S32 pass) gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } -void LLDrawPoolAlpha::renderDeferred(S32 pass) -{ - -} - S32 LLDrawPoolAlpha::getNumPostDeferredPasses() { @@ -261,6 +261,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) { BOOL initialized_lighting = FALSE; BOOL light_enabled = TRUE; + S32 diffuse_channel = 0; + //BOOL is_particle = FALSE; BOOL use_shaders = (LLPipeline::sUnderWaterRender && gPipeline.canUseVertexShaders()) || gPipeline.canUseWindLightShadersOnObjects(); @@ -291,19 +293,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) LLRenderPass::applyModelMatrix(params); - if (params.mTexture.notNull()) - { - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->bind(params.mTexture.get()); - - if (params.mTextureMatrix) - { - glMatrixMode(GL_TEXTURE); - glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; - } - } - if (params.mFullbright) { // Turn off lighting if it hasn't already been so. @@ -344,11 +333,13 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) if (deferred_render && current_shader != NULL) { gPipeline.unbindDeferredShader(*current_shader); + diffuse_channel = 0; } current_shader = target_shader; if (deferred_render) { gPipeline.bindDeferredShader(*current_shader); + diffuse_channel = current_shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } else { @@ -357,11 +348,12 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) } else if (!use_shaders && current_shader != NULL) { - LLGLSLShader::bindNoShader(); if (deferred_render) { gPipeline.unbindDeferredShader(*current_shader); + diffuse_channel = 0; } + LLGLSLShader::bindNoShader(); current_shader = NULL; } @@ -369,6 +361,24 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) { params.mGroup->rebuildMesh(); } + + + if (params.mTexture.notNull()) + { + gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get(), TRUE, TRUE); + if(params.mViewerTexture.notNull()) + { + params.mViewerTexture->addTextureStats(params.mVSize); + } + if (params.mTextureMatrix) + { + gGL.getTexUnit(0)->activate(); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + } + } + params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount/3); @@ -383,6 +393,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) } } + if (deferred_render && current_shader != NULL) + { + gPipeline.unbindDeferredShader(*current_shader); + LLVertexBuffer::unbind(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + } + if (!light_enabled) { gPipeline.enableLightsDynamic(); diff --git a/linden/indra/newview/lldrawpoolavatar.cpp b/linden/indra/newview/lldrawpoolavatar.cpp index 80c7d73..af7b5e3 100644 --- a/linden/indra/newview/lldrawpoolavatar.cpp +++ b/linden/indra/newview/lldrawpoolavatar.cpp @@ -94,6 +94,7 @@ BOOL gAvatarEmbossBumpMap = FALSE; static BOOL sRenderingSkinned = FALSE; S32 normal_channel = -1; S32 specular_channel = -1; +S32 diffuse_channel = -1; LLDrawPoolAvatar::LLDrawPoolAvatar() : LLFacePool(POOL_AVATAR) @@ -447,7 +448,8 @@ void LLDrawPoolAvatar::beginDeferredImpostor() normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); - + diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); // KL SD + sVertexProgram->bind(); } @@ -456,6 +458,7 @@ void LLDrawPoolAvatar::endDeferredImpostor() sShaderLevel = mVertexShaderLevel; sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); + sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); // KL SD sVertexProgram->unbind(); gGL.getTexUnit(0)->activate(); } @@ -699,7 +702,8 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) avatarp->mImpostor.bindTexture(1, specular_channel); } } - avatarp->renderImpostor(); + // avatarp->renderImpostor(LLColor4U(255,255,255,255), diffuse_channel); // KL SD + avatarp->renderImpostor(); } else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred) { @@ -752,6 +756,67 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if( !single_avatar || (avatarp == single_avatar) ) { + if (LLVOAvatar::sShowCollisionVolumes) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + avatarp->renderCollisionVolumes(); + } + + if (avatarp->isSelf() && LLAgent::sDebugDisplayTarget) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLVector3 pos = avatarp->getPositionAgent(); + + gGL.color4f(1.0f, 0.0f, 0.0f, 0.8f); + gGL.begin(LLRender::LINES); + { + gGL.vertex3fv((pos - LLVector3(0.2f, 0.f, 0.f)).mV); + gGL.vertex3fv((pos + LLVector3(0.2f, 0.f, 0.f)).mV); + gGL.vertex3fv((pos - LLVector3(0.f, 0.2f, 0.f)).mV); + gGL.vertex3fv((pos + LLVector3(0.f, 0.2f, 0.f)).mV); + gGL.vertex3fv((pos - LLVector3(0.f, 0.f, 0.2f)).mV); + gGL.vertex3fv((pos + LLVector3(0.f, 0.f, 0.2f)).mV); + }gGL.end(); + + pos = avatarp->mDrawable->getPositionAgent(); + gGL.color4f(1.0f, 0.0f, 0.0f, 0.8f); + gGL.begin(LLRender::LINES); + { + gGL.vertex3fv((pos - LLVector3(0.2f, 0.f, 0.f)).mV); + gGL.vertex3fv((pos + LLVector3(0.2f, 0.f, 0.f)).mV); + gGL.vertex3fv((pos - LLVector3(0.f, 0.2f, 0.f)).mV); + gGL.vertex3fv((pos + LLVector3(0.f, 0.2f, 0.f)).mV); + gGL.vertex3fv((pos - LLVector3(0.f, 0.f, 0.2f)).mV); + gGL.vertex3fv((pos + LLVector3(0.f, 0.f, 0.2f)).mV); + }gGL.end(); + + pos = avatarp->mRoot.getWorldPosition(); + gGL.color4f(1.0f, 1.0f, 1.0f, 0.8f); + gGL.begin(LLRender::LINES); + { + gGL.vertex3fv((pos - LLVector3(0.2f, 0.f, 0.f)).mV); + gGL.vertex3fv((pos + LLVector3(0.2f, 0.f, 0.f)).mV); + gGL.vertex3fv((pos - LLVector3(0.f, 0.2f, 0.f)).mV); + gGL.vertex3fv((pos + LLVector3(0.f, 0.2f, 0.f)).mV); + gGL.vertex3fv((pos - LLVector3(0.f, 0.f, 0.2f)).mV); + gGL.vertex3fv((pos + LLVector3(0.f, 0.f, 0.2f)).mV); + }gGL.end(); + + pos = avatarp->mPelvisp->getWorldPosition(); + gGL.color4f(0.0f, 0.0f, 1.0f, 0.8f); + gGL.begin(LLRender::LINES); + { + gGL.vertex3fv((pos - LLVector3(0.2f, 0.f, 0.f)).mV); + gGL.vertex3fv((pos + LLVector3(0.2f, 0.f, 0.f)).mV); + gGL.vertex3fv((pos - LLVector3(0.f, 0.2f, 0.f)).mV); + gGL.vertex3fv((pos + LLVector3(0.f, 0.2f, 0.f)).mV); + gGL.vertex3fv((pos - LLVector3(0.f, 0.f, 0.2f)).mV); + gGL.vertex3fv((pos + LLVector3(0.f, 0.f, 0.2f)).mV); + }gGL.end(); + + color.setColor(1.0f, 1.0f, 1.0f, 1.0f); + } + avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); } } diff --git a/linden/indra/newview/lldrawpoolbump.cpp b/linden/indra/newview/lldrawpoolbump.cpp index fb7a213..dcaa742 100644 --- a/linden/indra/newview/lldrawpoolbump.cpp +++ b/linden/indra/newview/lldrawpoolbump.cpp @@ -140,7 +140,7 @@ void LLStandardBumpmap::restoreGL() return; } - llinfos << "Loading bumpmap: " << bump_file << " from viewerart" << llendl; +// llinfos << "Loading bumpmap: " << bump_file << " from viewerart" << llendl; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage = gImageList.getImageFromFile(bump_file, @@ -309,8 +309,8 @@ void LLDrawPoolBump::endRenderPass(S32 pass) void LLDrawPoolBump::beginShiny(bool invisible) { LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); - if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| - (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) + if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| + invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) { return; } @@ -384,8 +384,8 @@ void LLDrawPoolBump::beginShiny(bool invisible) void LLDrawPoolBump::renderShiny(bool invisible) { LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); - if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| - (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) + if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| + invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) { return; } @@ -411,8 +411,8 @@ void LLDrawPoolBump::renderShiny(bool invisible) void LLDrawPoolBump::endShiny(bool invisible) { LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); - if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| - (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) + if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| + invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) { return; } @@ -572,7 +572,11 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) LLImageGL* bump = NULL; U8 bump_code = params.mBump; - LLViewerImage* tex = params.mTexture; + LLViewerImage* tex = params.mViewerTexture; + if(!tex) + { + return FALSE ; + } switch( bump_code ) { @@ -1226,7 +1230,10 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) if (params.mTexture.notNull()) { gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get()); - //params.mTexture->addTextureStats(params.mVSize); + if(params.mViewerTexture.notNull()) + { + params.mViewerTexture->addTextureStats(params.mVSize); + } } else { diff --git a/linden/indra/newview/lldrawpoolsky.cpp b/linden/indra/newview/lldrawpoolsky.cpp index f0ed380..7f21adc 100644 --- a/linden/indra/newview/lldrawpoolsky.cpp +++ b/linden/indra/newview/lldrawpoolsky.cpp @@ -61,8 +61,8 @@ LLDrawPool *LLDrawPoolSky::instancePool() void LLDrawPoolSky::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); - gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable); + mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); +// gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable); } void LLDrawPoolSky::render(S32 pass) @@ -97,6 +97,7 @@ void LLDrawPoolSky::render(S32 pass) } + LLVOSky *voskyp = gSky.mVOSkyp; LLGLSPipelineSkyBox gls_skybox; LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); @@ -119,9 +120,43 @@ void LLDrawPoolSky::render(S32 pass) { renderSkyCubeFace(i); } + + LLFace *hbfaces[3]; + hbfaces[0] = NULL; + hbfaces[1] = NULL; + hbfaces[2] = NULL; + for (S32 curr_face = 0; curr_face < face_count; curr_face++) + { + LLFace* facep = mDrawFace[curr_face]; + if (voskyp->isSameFace(LLVOSky::FACE_SUN, facep)) + { + hbfaces[0] = facep; + } + if (voskyp->isSameFace(LLVOSky::FACE_MOON, facep)) + { + hbfaces[1] = facep; + } + if (voskyp->isSameFace(LLVOSky::FACE_BLOOM, facep)) + { + hbfaces[2] = facep; + } + } LLGLEnable blend(GL_BLEND); + if (hbfaces[2]) + { + // renderSunHalo(hbfaces[2]); + } + if (hbfaces[0]) + { + // renderHeavenlyBody(0, hbfaces[0]); + } + if (hbfaces[1]) + { + // renderHeavenlyBody(1, hbfaces[1]); + } + glPopMatrix(); } @@ -146,6 +181,35 @@ void LLDrawPoolSky::renderSkyCubeFace(U8 side) } } +void LLDrawPoolSky::renderHeavenlyBody(U8 hb, LLFace* face) +{ + if ( !mHB[hb]->getDraw() ) return; + if (! face->getGeomCount()) return; + + LLImageGL* tex = face->getTexture(); + gGL.getTexUnit(0)->bind(tex); + LLColor4 color(mHB[hb]->getInterpColor()); + LLOverrideFaceColor override(this, color); + face->renderIndexed(); +} + + + +void LLDrawPoolSky::renderSunHalo(LLFace* face) +{ + if (! mHB[0]->getDraw()) return; + if (! face->getGeomCount()) return; + + LLImageGL* tex = face->getTexture(); + gGL.getTexUnit(0)->bind(tex); + LLColor4 color(mHB[0]->getInterpColor()); + color.mV[3] = llclamp(mHB[0]->getHaloBrighness(), 0.f, 1.f); + + LLOverrideFaceColor override(this, color); + face->renderIndexed(); +} + + void LLDrawPoolSky::renderForSelect() { } diff --git a/linden/indra/newview/lldrawpoolsky.h b/linden/indra/newview/lldrawpoolsky.h index 8595d73..f35b114 100644 --- a/linden/indra/newview/lldrawpoolsky.h +++ b/linden/indra/newview/lldrawpoolsky.h @@ -36,12 +36,14 @@ #include "lldrawpool.h" class LLSkyTex; +class LLHeavenBody; class LLGLSLShader; class LLDrawPoolSky : public LLFacePool { private: LLSkyTex *mSkyTex; + LLHeavenBody *mHB[2]; // Sun and Moon LLGLSLShader *mShader; public: @@ -67,6 +69,8 @@ public: /*virtual*/ void renderForSelect(); /*virtual*/ void endRenderPass(S32 pass); void setSkyTex(LLSkyTex* const st) { mSkyTex = st; } + void setSun(LLHeavenBody* sun_flag) { mHB[0] = sun_flag; } + void setMoon(LLHeavenBody* moon) { mHB[1] = moon; } void renderSkyCubeFace(U8 side); void renderHeavenlyBody(U8 hb, LLFace* face); diff --git a/linden/indra/newview/lldrawpoolterrain.cpp b/linden/indra/newview/lldrawpoolterrain.cpp index cac5162..3ee955a 100644 --- a/linden/indra/newview/lldrawpoolterrain.cpp +++ b/linden/indra/newview/lldrawpoolterrain.cpp @@ -73,19 +73,19 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerImage *texturep) : TRUE, TRUE, GL_ALPHA8, GL_ALPHA, LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb")); - gGL.getTexUnit(0)->bind(mAlphaRampImagep.get()); + //gGL.getTexUnit(0)->bind(mAlphaRampImagep.get()); mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); m2DAlphaRampImagep = gImageList.getImageFromFile("alpha_gradient_2d.j2c", TRUE, TRUE, GL_ALPHA8, GL_ALPHA, LLUUID("38b86f85-2575-52a9-a531-23108d8da837")); - gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); + //gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_TERRAIN); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } LLDrawPoolTerrain::~LLDrawPoolTerrain() diff --git a/linden/indra/newview/lldrawpooltree.cpp b/linden/indra/newview/lldrawpooltree.cpp index 46cd2d5..873f0f6 100644 --- a/linden/indra/newview/lldrawpooltree.cpp +++ b/linden/indra/newview/lldrawpooltree.cpp @@ -52,7 +52,7 @@ LLDrawPoolTree::LLDrawPoolTree(LLViewerImage *texturep) : LLFacePool(POOL_TREE), mTexturep(texturep) { - gGL.getTexUnit(0)->bind(mTexturep.get()); +// gGL.getTexUnit(0)->bind(mTexturep.get()); mTexturep->setAddressMode(LLTexUnit::TAM_WRAP); } @@ -108,7 +108,7 @@ void LLDrawPoolTree::render(S32 pass) } else { - gGL.getTexUnit(sDiffTex)->bind(mTexturep); + gGL.getTexUnit(sDiffTex)->bind(mTexturep, TRUE); for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) @@ -138,7 +138,7 @@ void LLDrawPoolTree::endRenderPass(S32 pass) void LLDrawPoolTree::beginDeferredPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); // KL Render-pipeline has this set at 0.f ... NOOOOOO! make shitty trees :) shader = &gDeferredTreeProgram; shader->bind(); @@ -164,6 +164,9 @@ void LLDrawPoolTree::beginShadowPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + glPolygonOffset(gSavedSettings.getF32("RenderDeferredTreeShadowOffset"), + gSavedSettings.getF32("RenderDeferredTreeShadowBias")); + gDeferredShadowProgram.bind(); } @@ -176,7 +179,11 @@ void LLDrawPoolTree::endShadowPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - gDeferredShadowProgram.unbind(); + + glPolygonOffset(gSavedSettings.getF32("RenderDeferredSpotShadowOffset"), + gSavedSettings.getF32("RenderDeferredSpotShadowBias")); + + //gDeferredShadowProgram.unbind(); } diff --git a/linden/indra/newview/lldrawpoolwater.cpp b/linden/indra/newview/lldrawpoolwater.cpp index ce3425d..5c0363e 100644 --- a/linden/indra/newview/lldrawpoolwater.cpp +++ b/linden/indra/newview/lldrawpoolwater.cpp @@ -98,7 +98,7 @@ void LLDrawPoolWater::restoreGL() LLDrawPool *LLDrawPoolWater::instancePool() { - llerrs << "Should never be calling instancePool on a water pool!" << llendl; + llwarns << "Should never be calling instancePool on a water pool!" << llendl; return NULL; } @@ -401,6 +401,15 @@ void LLDrawPoolWater::shade() shader = &gWaterProgram; } + if (deferred_render) + { + gPipeline.bindDeferredShader(*shader); + } + else + { + shader->bind(); + } + sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f; S32 reftex = shader->enableTexture(LLViewerShaderMgr::WATER_REFTEX); @@ -436,15 +445,6 @@ void LLDrawPoolWater::shade() S32 screentex = shader->enableTexture(LLViewerShaderMgr::WATER_SCREENTEX); - if (deferred_render) - { - gPipeline.bindDeferredShader(*shader); - } - else - { - shader->bind(); - } - if (screentex > -1) { shader->uniform4fv(LLViewerShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV); diff --git a/linden/indra/newview/lldynamictexture.cpp b/linden/indra/newview/lldynamictexture.cpp index 61f5a89..e219d4b 100644 --- a/linden/indra/newview/lldynamictexture.cpp +++ b/linden/indra/newview/lldynamictexture.cpp @@ -41,6 +41,7 @@ #include "llvertexbuffer.h" #include "llviewerdisplay.h" #include "llrender.h" +#include "pipeline.h" // static LLDynamicTexture::instance_list_t LLDynamicTexture::sInstances[ LLDynamicTexture::ORDER_COUNT ]; @@ -58,9 +59,14 @@ LLDynamicTexture::LLDynamicTexture(S32 width, S32 height, S32 components, EOrder mClamp(clamp) { llassert((1 <= components) && (components <= 4)); - - generateGLTexture(); - + if(!LLPipeline::sRenderDeferred) + { + generateGLTexture(); + } + else + { + gPipeline.markGLRebuild(this); // KL SD well for this to work its either gotta be one or the other so lets slap in the if/else can't do any harm. + } llassert( 0 <= order && order < ORDER_COUNT ); LLDynamicTexture::sInstances[ order ].insert(this); } @@ -77,6 +83,11 @@ LLDynamicTexture::~LLDynamicTexture() } } +void LLDynamicTexture::updateGL() +{ + generateGLTexture(); +} + //----------------------------------------------------------------------------- // releaseGLTexture() //----------------------------------------------------------------------------- @@ -101,7 +112,7 @@ void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum prima { if (mComponents < 1 || mComponents > 4) { - llerrs << "Bad number of components in dynamic texture: " << mComponents << llendl; + llwarns << "Bad number of components in dynamic texture: " << mComponents << llendl; } releaseGLTexture(); LLPointer<LLImageRaw> raw_image = new LLImageRaw(mWidth, mHeight, mComponents); @@ -111,7 +122,7 @@ void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum prima mTexture->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes); } // llinfos << "ALLOCATING " << (mWidth*mHeight*mComponents)/1024 << "K" << llendl; - mTexture->createGLTexture(0, raw_image, 0, TRUE, LLViewerImageBoostLevel::DYNAMIC_TEX); + mTexture->createGLTexture(0, raw_image); mTexture->setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP); mTexture->setGLTextureCreated(false); } diff --git a/linden/indra/newview/lldynamictexture.h b/linden/indra/newview/lldynamictexture.h index 5a20eae..1480799 100644 --- a/linden/indra/newview/lldynamictexture.h +++ b/linden/indra/newview/lldynamictexture.h @@ -37,7 +37,7 @@ #include "llcoord.h" #include "llimagegl.h" -class LLDynamicTexture +class LLDynamicTexture : public LLGLUpdate { public: enum EOrder { ORDER_FIRST = 0, ORDER_MIDDLE = 1, ORDER_LAST = 2, ORDER_RESET = 3, ORDER_COUNT = 4 }; @@ -49,6 +49,8 @@ public: BOOL clamp); virtual ~LLDynamicTexture(); + void updateGL(); + S32 getOriginX() { return mOrigin.mX; } S32 getOriginY() { return mOrigin.mY; } S32 getWidth() { return mWidth; } diff --git a/linden/indra/newview/llface.cpp b/linden/indra/newview/llface.cpp index aa8cd15..ae57a3c 100644 --- a/linden/indra/newview/llface.cpp +++ b/linden/indra/newview/llface.cpp @@ -176,8 +176,8 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mLastIndicesCount = mIndicesCount; mLastIndicesIndex = mIndicesIndex; - mImportanceToCamera = 0.f ; - mBoundingSphereRadius = 0.0f ; + mAtlasInfop = NULL ; + mUsingAtlas = FALSE ; } @@ -205,12 +205,14 @@ void LLFace::destroy() if (group) { group->dirtyGeom(); + gPipeline.markRebuild(group, TRUE); } } } setDrawInfo(NULL); + removeAtlas(); mDrawablep = NULL; mVObjp = NULL; } @@ -223,7 +225,7 @@ void LLFace::initClass() void LLFace::setWorldMatrix(const LLMatrix4 &mat) { - llerrs << "Faces on this drawable are not independently modifiable\n" << llendl; + llwarns << "Faces on this drawable are not independently modifiable\n" << llendl; } void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep) @@ -232,7 +234,7 @@ void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep) if (!new_pool) { - llerrs << "Setting pool to null!" << llendl; + llwarns << "Setting pool to null!" << llendl; } if (new_pool != mDrawPoolp) @@ -270,6 +272,7 @@ void LLFace::setTexture(LLViewerImage* tex) if(mTexture.notNull()) { mTexture->removeFace(this) ; + removeAtlas() ; } mTexture = tex ; @@ -453,8 +456,15 @@ void LLFace::renderForSelect(U32 data_mask) void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) { - if(mDrawablep.isNull() || mVertexBuffer.isNull() || mDrawablep->getSpatialGroup() == NULL || - mDrawablep->getSpatialGroup()->isState(LLSpatialGroup::GEOM_DIRTY)) + if (mDrawablep->getSpatialGroup() == NULL) + { + return; + } + + mDrawablep->getSpatialGroup()->rebuildGeom(); + mDrawablep->getSpatialGroup()->rebuildMesh(); + + if(mDrawablep.isNull() || mVertexBuffer.isNull()) { return; } @@ -473,17 +483,10 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) glMultMatrixf((GLfloat*)mDrawablep->getRegion()->mRenderMatrix.mMatrix); } - setFaceColor(color); - renderSetColor(); - + glColor4fv(color.mV); mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); -#if !LL_RELEASE_FOR_DOWNLOAD - LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); -#endif mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); - unsetFaceColor(); - unsetFaceColor(); gGL.popMatrix(); } } @@ -727,8 +730,8 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, } mCenterLocal = (newMin+newMax)*0.5f; - LLVector3 tmp = (newMin - newMax) ; - mBoundingSphereRadius = tmp.length() * 0.5f ; + // LLVector3 tmp = (newMin - newMax) ; + // mBoundingSphereRadius = tmp.length() * 0.5f ; updateCenterAgent(); } @@ -963,6 +966,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, mVertexBuffer->getBinormalStrider(binormals, mGeomIndex); } + F32 tcoord_xoffset = 0.f ; + F32 tcoord_yoffset = 0.f ; + F32 tcoord_xscale = 1.f ; + F32 tcoord_yscale = 1.f ; + BOOL in_atlas = FALSE ; + if (rebuild_tcoord) { mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); @@ -970,6 +979,18 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex); } + + in_atlas = isAtlasInUse() ; + if(in_atlas) + { + const LLVector2* tmp = getTexCoordOffset() ; + tcoord_xoffset = tmp->mV[0] ; + tcoord_yoffset = tmp->mV[1] ; + + tmp = getTexCoordScale() ; + tcoord_xscale = tmp->mV[0] ; + tcoord_yscale = tmp->mV[1] ; + } } if (rebuild_color) { @@ -1057,7 +1078,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, 0.75f }; - if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || (LLPipeline::sRenderBump && tep->getShiny()))) + if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || LLPipeline::sRenderBump && tep->getShiny())) { color.mV[3] = U8 (alpha[tep->getShiny()] * 255); } @@ -1179,6 +1200,93 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, xform(tc, cos_ang, sin_ang, os, ot, ms, mt); } + if(in_atlas) + { + // + //manually calculate tex-coord per vertex for varying address modes. + //should be removed if shader can handle this. + // + + S32 int_part = 0 ; + switch(mTexture->getAddressMode()) + { + case LLTexUnit::TAM_CLAMP: + if(tc.mV[0] < 0.f) + { + tc.mV[0] = 0.f ; + } + else if(tc.mV[0] > 1.f) + { + tc.mV[0] = 1.f; + } + + if(tc.mV[1] < 0.f) + { + tc.mV[1] = 0.f ; + } + else if(tc.mV[1] > 1.f) + { + tc.mV[1] = 1.f; + } + break; + case LLTexUnit::TAM_MIRROR: + if(tc.mV[0] < 0.f) + { + tc.mV[0] = -tc.mV[0] ; + } + int_part = (S32)tc.mV[0] ; + if(int_part & 1) //odd number + { + tc.mV[0] = int_part + 1 - tc.mV[0] ; + } + else //even number + { + tc.mV[0] -= int_part ; + } + + if(tc.mV[1] < 0.f) + { + tc.mV[1] = -tc.mV[1] ; + } + int_part = (S32)tc.mV[1] ; + if(int_part & 1) //odd number + { + tc.mV[1] = int_part + 1 - tc.mV[1] ; + } + else //even number + { + tc.mV[1] -= int_part ; + } + break; + case LLTexUnit::TAM_WRAP: + if(tc.mV[0] > 1.f) + tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ; + else if(tc.mV[0] < -1.f) + tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ; + + if(tc.mV[1] > 1.f) + tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ; + else if(tc.mV[1] < -1.f) + tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ; + + if(tc.mV[0] < 0.f) + { + tc.mV[0] = 1.0f + tc.mV[0] ; + } + if(tc.mV[1] < 0.f) + { + tc.mV[1] = 1.0f + tc.mV[1] ; + } + break; + default: + break; + } + + tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ; + tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ; + } + + *tex_coords++ = tc; if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) @@ -1245,159 +1353,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, return TRUE; } -const F32 LEAST_IMPORTANCE = 0.05f ; -const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ; - -F32 LLFace::getTextureVirtualSize() -{ - F32 radius; - F32 cos_angle_to_view_dir; - mPixelArea = calcPixelArea(cos_angle_to_view_dir, radius); - - if (mPixelArea <= 0) - { - return 0.f; - } - - //get area of circle in texture space - LLVector2 tdim = mTexExtents[1] - mTexExtents[0]; - F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f; - if (texel_area <= 0) - { - // Probably animated, use default - texel_area = 1.f; - } - - F32 face_area; - if (mVObjp->isSculpted() && texel_area > 1.f) - { - //sculpts can break assumptions about texel area - face_area = mPixelArea; - } - else - { - //apply texel area to face area to get accurate ratio - //face_area /= llclamp(texel_area, 1.f/64.f, 16.f); - face_area = mPixelArea / llclamp(texel_area, 0.015625f, 1024.f); - } - - if(face_area > LLViewerImage::sMaxSmallImageSize) - { - if(mImportanceToCamera < LEAST_IMPORTANCE) //if the face is not important, do not load hi-res. - { - face_area = LLViewerImage::sMaxSmallImageSize ; - } - else if(face_area > LLViewerImage::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping. - { - if(mImportanceToCamera < LEAST_IMPORTANCE_FOR_LARGE_IMAGE)//if the face is not important, do not load hi-res. - { - face_area = LLViewerImage::sMinLargeImageSize ; - } - else if(mTexture.notNull() && mTexture->isLargeImage()) - { - face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius ); - } - } - } - - return face_area; -} - -F32 LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) -{ - //get area of circle around face - LLVector3 center = getPositionAgent(); - LLVector3 size = (mExtents[1] - mExtents[0]) * 0.5f; - - LLVector3 lookAt = center - LLViewerCamera::getInstance()->getOrigin(); - F32 dist = lookAt.normVec() ; - - //get area of circle around node - F32 app_angle = atanf(size.length()/dist); - radius = app_angle*LLDrawable::sCurPixelAngle; - F32 face_area = radius*radius * 3.14159f; - - if(dist < mBoundingSphereRadius) //camera is very close - { - cos_angle_to_view_dir = 1.0f ; - mImportanceToCamera = 1.0f ; - } - else - { - cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ; - mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ; - } - - return face_area ; -} - -//the projection of the face partially overlaps with the screen -F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ) -{ - F32 screen_radius = (F32)llmax(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()) ; - F32 center_angle = acosf(cos_angle_to_view_dir) ; - F32 d = center_angle * LLDrawable::sCurPixelAngle ; - - if(d + radius > screen_radius + 5.f) - { - //---------------------------------------------- - //calculate the intersection area of two circles - //F32 radius_square = radius * radius ; - //F32 d_square = d * d ; - //F32 screen_radius_square = screen_radius * screen_radius ; - //face_area = - // radius_square * acosf((d_square + radius_square - screen_radius_square)/(2 * d * radius)) + - // screen_radius_square * acosf((d_square + screen_radius_square - radius_square)/(2 * d * screen_radius)) - - // 0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ; - //---------------------------------------------- - - //the above calculation is too expensive - //the below is a good estimation: bounding box of the bounding sphere: - F32 alpha = 0.5f * (radius + screen_radius - d) / radius ; - alpha = llclamp(alpha, 0.f, 1.f) ; - return alpha * alpha ; - } - return 1.0f ; -} - -const S8 FACE_IMPORTANCE_LEVEL = 4 ; -const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL][2] = //{distance, importance_weight} - {{16.1f, 1.0f}, {32.1f, 0.5f}, {48.1f, 0.2f}, {96.1f, 0.05f} } ; -const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[FACE_IMPORTANCE_LEVEL][2] = //{cos(angle), importance_weight} - {{0.985f /*cos(10 degrees)*/, 1.0f}, {0.94f /*cos(20 degrees)*/, 0.8f}, {0.866f /*cos(30 degrees)*/, 0.64f}, {0.0f, 0.36f}} ; - -//static -F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist) -{ - F32 importance = 0.f ; - - if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() && - dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0]) - { - F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; - F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); - - if(camera_moving_speed > 10.0f || camera_angular_speed > 1.0f) - { - //if camera moves or rotates too fast, ignore the importance factor - return 0.f ; - } - - //F32 camera_relative_speed = camera_moving_speed * (lookAt * LLViewerCamera::getInstance()->getVelocityDir()) ; - - S32 i = 0 ; - for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i); - i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; - F32 dist_factor = FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][1] ; - - for(i = 0; i < FACE_IMPORTANCE_LEVEL && cos_angle_to_view_dir < FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][0] ; ++i) ; - i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; - importance = dist_factor * FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][1] ; - } - - return importance ; -} - BOOL LLFace::verify(const U32* indices_array) const { BOOL ok = TRUE; @@ -1586,3 +1541,153 @@ LLVector3 LLFace::getPositionAgent() const return mCenterLocal * getRenderMatrix(); } } + +// +//atlas +// +void LLFace::removeAtlas() +{ + setAtlasInUse(FALSE) ; + mAtlasInfop = NULL ; +} + +const LLTextureAtlas* LLFace::getAtlas()const +{ + if(mAtlasInfop) + { + return mAtlasInfop->getAtlas() ; + } + return NULL ; +} + +const LLVector2* LLFace::getTexCoordOffset()const +{ + if(isAtlasInUse()) + { + return mAtlasInfop->getTexCoordOffset() ; + } + return NULL ; +} +const LLVector2* LLFace::getTexCoordScale() const +{ + if(isAtlasInUse()) + { + return mAtlasInfop->getTexCoordScale() ; + } + return NULL ; +} + +BOOL LLFace::isAtlasInUse()const +{ + return mUsingAtlas ; +} + +BOOL LLFace::canUseAtlas()const +{ + //no drawable or no spatial group, do not use atlas + if(!mDrawablep || !mDrawablep->getSpatialGroup()) + { + return FALSE ; + } + + //if bump face, do not use atlas + if(getTextureEntry() && getTextureEntry()->getBumpmap()) + { + return FALSE ; + } + + //if animated texture, do not use atlas + if(isState(TEXTURE_ANIM)) + { + return FALSE ; + } + + return TRUE ; +} + +void LLFace::setAtlasInUse(BOOL flag) +{ + //no valid atlas to use. + if(flag && (!mAtlasInfop || !mAtlasInfop->isValid())) + { + flag = FALSE ; + } + + if(!flag && !mUsingAtlas) + { + return ; + } + + // + //at this stage (flag || mUsingAtlas) is always true. + // + + //rebuild the tex coords + if(mDrawablep) + { + gPipeline.markRebuild(mDrawablep, LLDrawable::REBUILD_TCOORD); + mUsingAtlas = flag ; + } + else + { + mUsingAtlas = FALSE ; + } +} + +LLTextureAtlasSlot* LLFace::getAtlasInfo() +{ + return mAtlasInfop ; +} + +void LLFace::setAtlasInfo(LLTextureAtlasSlot* atlasp) +{ + if(mAtlasInfop != atlasp) + { + if(mAtlasInfop) + { + //llwarns << "Atlas slot changed!" << llendl ; + } + mAtlasInfop = atlasp ; + } +} + +LLImageGL* LLFace::getGLTexture() const +{ + if(isAtlasInUse()) + { + return (LLImageGL*)mAtlasInfop->getAtlas() ; + } + + return (LLImageGL*)mTexture ; +} + +//switch to atlas or switch back to gl texture +//return TRUE if using atlas. +BOOL LLFace::switchTexture() +{ + //no valid atlas or texture + if(!mAtlasInfop || !mAtlasInfop->isValid() || !mTexture) + { + return FALSE ; + } + + if(mTexture->getTexelsInAtlas() >= (U32)mVSize || mTexture->getTexelsInAtlas() >= mTexture->getTexelsInGLTexture()) + { + //switch to use atlas + //atlas resolution is qualified, use it. + if(!mUsingAtlas) + { + setAtlasInUse(TRUE) ; + } + } + else //if atlas not qualified. + { + //switch back to GL texture + if(mUsingAtlas && mTexture->isGLTextureCreated() && mTexture->getDiscardLevel() < mTexture->getDiscardLevelInAtlas()) + { + setAtlasInUse(FALSE) ; + } + } + + return mUsingAtlas ; +} diff --git a/linden/indra/newview/llface.h b/linden/indra/newview/llface.h index 4893e82..9f76d6b 100644 --- a/linden/indra/newview/llface.h +++ b/linden/indra/newview/llface.h @@ -48,6 +48,7 @@ #include "llviewerimage.h" #include "llstat.h" #include "lldrawable.h" +#include "lltextureatlasmanager.h" class LLFacePool; class LLVolume; @@ -56,6 +57,7 @@ class LLTextureEntry; class LLVertexProgram; class LLViewerImage; class LLGeometryManager; +class LLTextureAtlasSlot; const F32 MIN_ALPHA_SIZE = 1024.f; const F32 MIN_TEX_ANIM_SIZE = 512.f; @@ -189,14 +191,18 @@ public: void setIndicesIndex(S32 idx) { mIndicesIndex = idx; } void setDrawInfo(LLDrawInfo* draw_info); - F32 getTextureVirtualSize() ; - F32 getImportanceToCamera()const {return mImportanceToCamera ;} - -private: - F32 adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ); - F32 calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) ; -public: - static F32 calcImportanceToCamera(F32 to_view_dir, F32 dist); + // KL was atlas S19 + LLImageGL* getGLTexture() const; + LLTextureAtlasSlot* getAtlasInfo() ; + void setAtlasInUse(BOOL flag); + void setAtlasInfo(LLTextureAtlasSlot* atlasp); + BOOL isAtlasInUse()const; + BOOL canUseAtlas() const; + const LLVector2* getTexCoordScale() const ; + const LLVector2* getTexCoordOffset()const; + const LLTextureAtlas* getAtlas()const ; + void removeAtlas() ; + BOOL switchTexture() ; public: @@ -212,7 +218,7 @@ public: LLMatrix4* mTextureMatrix; LLDrawInfo* mDrawInfo; -private: +protected: friend class LLGeometryManager; friend class LLVolumeGeometryManager; @@ -242,12 +248,10 @@ private: F32 mVSize; F32 mPixelArea; - //importance factor, in the range [0, 1.0]. - //1.0: the most important. - //based on the distance from the face to the view point and the angle from the face center to the view direction. - F32 mImportanceToCamera ; - F32 mBoundingSphereRadius ; - + //atlas + LLPointer<LLTextureAtlasSlot> mAtlasInfop ; + BOOL mUsingAtlas ; + protected: static BOOL sSafeRenderSelect; @@ -275,9 +279,9 @@ public: const LLTextureEntry* lte = lhs->getTextureEntry(); const LLTextureEntry* rte = rhs->getTextureEntry(); - if (lhs->getTexture() != rhs->getTexture()) + if(lhs->getGLTexture() != rhs->getGLTexture()) // KL SD get GL { - return lhs->getTexture() < rhs->getTexture(); + return lhs->getGLTexture() < rhs->getGLTexture(); // not getTexture? } else if (lte->getBumpShinyFullbright() != rte->getBumpShinyFullbright()) { diff --git a/linden/indra/newview/llfloaterassetbrowser.cpp b/linden/indra/newview/llfloaterassetbrowser.cpp index af81c4a..9b41390 100644 --- a/linden/indra/newview/llfloaterassetbrowser.cpp +++ b/linden/indra/newview/llfloaterassetbrowser.cpp @@ -63,7 +63,7 @@ LLFloaterAssetBrowser::~LLFloaterAssetBrowser() mTextureAssets.clear(); mMaxIndex = 0; mFirstIndex = 0; - mMouseOverIndex = 0; + mMouseOverIndex = NULL; mMouseOverUUID = LLUUID::null; mMouseOverAssetUUID = LLUUID::null; mFloaterTitle = ""; @@ -79,7 +79,7 @@ void LLFloaterAssetBrowser::initialize() mAssetInfoIndex = 0; mFloaterHeight = getRect().getHeight(); mFloaterWidth = getRect().getWidth(); - mMouseOverIndex = 0; + mMouseOverIndex = NULL; mMouseOverUUID = LLUUID::null; mMouseOverAssetUUID = LLUUID::null; mFloaterTitle = ""; @@ -122,7 +122,7 @@ void LLFloaterAssetBrowser::createThumbnails() temp.mUUID = itemp->getUUID(); temp.mName = itemp->getName(); temp.mTexturep = NULL; - temp.mAssetRect = LLRect::null; + temp.mAssetRect = NULL; mTextureAssets.push_back(temp); } @@ -131,14 +131,14 @@ void LLFloaterAssetBrowser::createThumbnails() { mTextureAssets[i].mTexturep = gImageList.getImage(mTextureAssets[i].mAssetUUID, MIPMAP_YES, IMMEDIATE_NO); mTextureAssets[i].mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_PREVIEW); - //mTextureAssets[i].mTexturep->processTextureStats(); + mTextureAssets[i].mTexturep->processTextureStats(); } //Generate the asset info text - /*for(S32 i = 0; i < items.count(); i++) + for(S32 i = 0; i < items.count(); i++) { - LLString asset_info; - LLString dimensions; + std::string asset_info; + std::string dimensions; asset_info.append(mTextureAssets[i].mName); @@ -151,7 +151,7 @@ void LLFloaterAssetBrowser::createThumbnails() asset_info.append(dimensions); mTextureAssets[i].mAssetInfo = asset_info; - }*/ + } mFloaterTitle = llformat("Asset Browser (%d assets fetched)", mTextureAssets.size()); setTitle(mFloaterTitle); @@ -288,7 +288,7 @@ void LLFloaterAssetBrowser::draw() if(mImageAssetID.notNull()) { mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO); - //mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); + mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_PREVIEW); mTexturep->processTextureStats(); mTextureAssets[i].mWidth = mTexturep->mFullWidth; mTextureAssets[i].mHeight = mTexturep->mFullHeight; diff --git a/linden/indra/newview/llfloaterchat.cpp b/linden/indra/newview/llfloaterchat.cpp index 2daa5aa..5f43406 100644 --- a/linden/indra/newview/llfloaterchat.cpp +++ b/linden/indra/newview/llfloaterchat.cpp @@ -582,7 +582,8 @@ void LLFloaterChat::addChat(const LLChat& chat, // We display anything if it's not an IM. If it's an IM, check pref... if ( !from_instant_message || gSavedSettings.getBOOL("IMInChatConsole") ) { - gConsole->addLine(chat.mText, size, text_color); + gConsole->addConsoleLine(chat.mText, text_color); + } } diff --git a/linden/indra/newview/llfloaterhardwaresettings.cpp b/linden/indra/newview/llfloaterhardwaresettings.cpp index 7886e39..8c91f5a 100644 --- a/linden/indra/newview/llfloaterhardwaresettings.cpp +++ b/linden/indra/newview/llfloaterhardwaresettings.cpp @@ -68,6 +68,7 @@ void LLFloaterHardwareSettings::onClickHelp(void* data) void LLFloaterHardwareSettings::initCallbacks(void) { + childSetCommitCallback("fbo", refreshState); } // menu maintenance functions @@ -83,7 +84,8 @@ void LLFloaterHardwareSettings::refresh() mVideoCardMem = gSavedSettings.getS32("TextureMemory"); mFogRatio = gSavedSettings.getF32("RenderFogRatio"); mProbeHardwareOnStartup = gSavedSettings.getBOOL("ProbeHardwareOnStartup"); - + mRenderDeferred = gSavedSettings.getBOOL("RenderDeferred"); + mRenderUseFBO = gSavedSettings.getBOOL("RenderUseFBO"); childSetValue("fsaa", (LLSD::Integer) mFSAASamples); refreshEnabledState(); } @@ -101,6 +103,20 @@ void LLFloaterHardwareSettings::refreshEnabledState() childSetEnabled("vbo", FALSE); } + if (!gGLManager.mHasFramebufferObject) + { + childSetEnabled("fbo", FALSE); + } + + if (!gGLManager.mHasDrawBuffers || !gSavedSettings.getBOOL("RenderUseFBO")) + { + childSetEnabled("deferred", FALSE); + } + else + { + childSetEnabled("deferred", TRUE); + } + // if no windlight shaders, turn off nighttime brightness, gamma, and fog distance childSetEnabled("gamma", !gPipeline.canUseWindLightShaders()); childSetEnabled("(brightness, lower is brighter)", !gPipeline.canUseWindLightShaders()); @@ -108,6 +124,12 @@ void LLFloaterHardwareSettings::refreshEnabledState() } +//static +void LLFloaterHardwareSettings::refreshState(LLUICtrl*, void*) +{ + LLFloaterHardwareSettings::instance()->refreshEnabledState(); +} + // static instance of it LLFloaterHardwareSettings* LLFloaterHardwareSettings::instance() { @@ -202,7 +224,8 @@ void LLFloaterHardwareSettings::cancel() gSavedSettings.setS32("TextureMemory", mVideoCardMem); gSavedSettings.setF32("RenderFogRatio", mFogRatio); gSavedSettings.setBOOL("ProbeHardwareOnStartup", mProbeHardwareOnStartup ); - + gSavedSettings.setBOOL("RenderUseFBO", mRenderUseFBO); + gSavedSettings.setBOOL("RenderDeferred", mRenderDeferred); close(); } diff --git a/linden/indra/newview/llfloaterhardwaresettings.h b/linden/indra/newview/llfloaterhardwaresettings.h index 04a33f6..e564e1c 100644 --- a/linden/indra/newview/llfloaterhardwaresettings.h +++ b/linden/indra/newview/llfloaterhardwaresettings.h @@ -61,6 +61,8 @@ public: /// OK button static void onBtnOK( void* userdata ); + static void refreshState(LLUICtrl*, void*); + //// menu management /// show off our menu @@ -88,6 +90,8 @@ protected: LLSliderCtrl* mCtrlVideoCardMem; BOOL mUseVBO; + BOOL mRenderUseFBO; + BOOL mRenderDeferred; BOOL mUseAniso; U32 mFSAASamples; F32 mGamma; diff --git a/linden/indra/newview/llfloaterlagmeter.cpp b/linden/indra/newview/llfloaterlagmeter.cpp index 8fe455f..2ae2e32 100644 --- a/linden/indra/newview/llfloaterlagmeter.cpp +++ b/linden/indra/newview/llfloaterlagmeter.cpp @@ -180,7 +180,7 @@ void LLFloaterLagMeter::determineClient() { mClientCause->setText( getString("client_texture_loading_cause_msg", mStringArgs) ); } - else if((BYTES_TO_MEGA_BYTES(LLViewerImage::sBoundTextureMemoryInBytes)) > LLViewerImage::sMaxBoundTextureMemInMegaBytes) + else if((LLViewerImage::sBoundTextureMemoryInBytes >> 20) > LLViewerImage::sMaxBoundTextureMemInMegaBytes) { mClientCause->setText( getString("client_texture_memory_cause_msg", mStringArgs) ); } diff --git a/linden/indra/newview/llfloaterpostprocess.cpp b/linden/indra/newview/llfloaterpostprocess.cpp index de9b598..c5b2018 100644 --- a/linden/indra/newview/llfloaterpostprocess.cpp +++ b/linden/indra/newview/llfloaterpostprocess.cpp @@ -52,28 +52,29 @@ LLFloaterPostProcess::LLFloaterPostProcess() : LLFloater(std::string("Post-Proce LLUICtrlFactory::getInstance()->buildFloater(this, "floater_post_process.xml"); /// Color Filter Callbacks - childSetCommitCallback("ColorFilterToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_color_filter"); + //childSetCommitCallback("ColorFilterToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_color_filter"); + childSetCommitCallback("wmiColorFilterToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_color_filter"); //childSetCommitCallback("ColorFilterGamma", &LLFloaterPostProcess::onFloatControlMoved, &(gPostProcess->tweaks.gamma())); - childSetCommitCallback("ColorFilterBrightness", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness"); - childSetCommitCallback("ColorFilterSaturation", &LLFloaterPostProcess::onFloatControlMoved, (char*)"saturation"); - childSetCommitCallback("ColorFilterContrast", &LLFloaterPostProcess::onFloatControlMoved, (char*)"contrast"); + childSetCommitCallback("wmiColorFilterBrightness", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness"); + childSetCommitCallback("wmiColorFilterSaturation", &LLFloaterPostProcess::onFloatControlMoved, (char*)"saturation"); + childSetCommitCallback("wmiColorFilterContrast", &LLFloaterPostProcess::onFloatControlMoved, (char*)"contrast"); - childSetCommitCallback("ColorFilterBaseR", &LLFloaterPostProcess::onColorControlRMoved, (char*)"contrast_base"); - childSetCommitCallback("ColorFilterBaseG", &LLFloaterPostProcess::onColorControlGMoved, (char*)"contrast_base"); - childSetCommitCallback("ColorFilterBaseB", &LLFloaterPostProcess::onColorControlBMoved, (char*)"contrast_base"); - childSetCommitCallback("ColorFilterBaseI", &LLFloaterPostProcess::onColorControlIMoved, (char*)"contrast_base"); + childSetCommitCallback("wmiColorFilterBaseR", &LLFloaterPostProcess::onColorControlRMoved, (char*)"contrast_base"); + childSetCommitCallback("wmiColorFilterBaseG", &LLFloaterPostProcess::onColorControlGMoved, (char*)"contrast_base"); + childSetCommitCallback("wmiColorFilterBaseB", &LLFloaterPostProcess::onColorControlBMoved, (char*)"contrast_base"); + childSetCommitCallback("wmiColorFilterBaseI", &LLFloaterPostProcess::onColorControlIMoved, (char*)"contrast_base"); /// Night Vision Callbacks - childSetCommitCallback("NightVisionToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_night_vision"); - childSetCommitCallback("NightVisionBrightMult", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness_multiplier"); - childSetCommitCallback("NightVisionNoiseSize", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_size"); - childSetCommitCallback("NightVisionNoiseStrength", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_strength"); + childSetCommitCallback("wmiNightVisionToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_night_vision"); + childSetCommitCallback("wmiNightVisionBrightMult", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness_multiplier"); + childSetCommitCallback("wmiNightVisionNoiseSize", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_size"); + childSetCommitCallback("wmiNightVisionNoiseStrength", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_strength"); /// Bloom Callbacks - childSetCommitCallback("BloomToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_bloom"); - childSetCommitCallback("BloomExtract", &LLFloaterPostProcess::onFloatControlMoved, (char*)"extract_low"); - childSetCommitCallback("BloomSize", &LLFloaterPostProcess::onFloatControlMoved, (char*)"bloom_width"); - childSetCommitCallback("BloomStrength", &LLFloaterPostProcess::onFloatControlMoved, (char*)"bloom_strength"); + childSetCommitCallback("wmiBloomToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_bloom"); + childSetCommitCallback("wmiBloomExtract", &LLFloaterPostProcess::onFloatControlMoved, (char*)"extract_low"); + childSetCommitCallback("wmiBloomSize", &LLFloaterPostProcess::onFloatControlMoved, (char*)"bloom_width"); + childSetCommitCallback("wmiBloomStrength", &LLFloaterPostProcess::onFloatControlMoved, (char*)"bloom_strength"); // Effect loading and saving. LLComboBox* comboBox = getChild<LLComboBox>("PPEffectsCombo"); @@ -113,6 +114,7 @@ void LLFloaterPostProcess::onBoolToggle(LLUICtrl* ctrl, void* userData) // check the bool LLCheckBoxCtrl* cbCtrl = static_cast<LLCheckBoxCtrl*>(ctrl); gPostProcess->tweaks[boolVariableName] = cbCtrl->getValue(); + } // Float Moved @@ -247,25 +249,25 @@ void LLFloaterPostProcess::syncMenu() comboBox->selectByValue(gPostProcess->getSelectedEffect()); /// Sync Color Filter Menu - childSetValue("ColorFilterToggle", gPostProcess->tweaks.useColorFilter()); + childSetValue("wmiColorFilterToggle", gPostProcess->tweaks.useColorFilter()); //childSetValue("ColorFilterGamma", gPostProcess->tweaks.gamma()); - childSetValue("ColorFilterBrightness", gPostProcess->tweaks.brightness()); - childSetValue("ColorFilterSaturation", gPostProcess->tweaks.saturation()); - childSetValue("ColorFilterContrast", gPostProcess->tweaks.contrast()); - childSetValue("ColorFilterBaseR", gPostProcess->tweaks.contrastBaseR()); - childSetValue("ColorFilterBaseG", gPostProcess->tweaks.contrastBaseG()); - childSetValue("ColorFilterBaseB", gPostProcess->tweaks.contrastBaseB()); - childSetValue("ColorFilterBaseI", gPostProcess->tweaks.contrastBaseIntensity()); + childSetValue("wmiColorFilterBrightness", gPostProcess->tweaks.brightness()); + childSetValue("wmiColorFilterSaturation", gPostProcess->tweaks.saturation()); + childSetValue("wmiColorFilterContrast", gPostProcess->tweaks.contrast()); + childSetValue("wmiColorFilterBaseR", gPostProcess->tweaks.contrastBaseR()); + childSetValue("wmiColorFilterBaseG", gPostProcess->tweaks.contrastBaseG()); + childSetValue("wmiColorFilterBaseB", gPostProcess->tweaks.contrastBaseB()); + childSetValue("wmiColorFilterBaseI", gPostProcess->tweaks.contrastBaseIntensity()); /// Sync Night Vision Menu - childSetValue("NightVisionToggle", gPostProcess->tweaks.useNightVisionShader()); - childSetValue("NightVisionBrightMult", gPostProcess->tweaks.brightMult()); - childSetValue("NightVisionNoiseSize", gPostProcess->tweaks.noiseSize()); - childSetValue("NightVisionNoiseStrength", gPostProcess->tweaks.noiseStrength()); + childSetValue("wmiNightVisionToggle", gPostProcess->tweaks.useNightVisionShader()); + childSetValue("wmiNightVisionBrightMult", gPostProcess->tweaks.brightMult()); + childSetValue("wmiNightVisionNoiseSize", gPostProcess->tweaks.noiseSize()); + childSetValue("wmiNightVisionNoiseStrength", gPostProcess->tweaks.noiseStrength()); /// Sync Bloom Menu - childSetValue("BloomToggle", LLSD(gPostProcess->tweaks.useBloomShader())); - childSetValue("BloomExtract", gPostProcess->tweaks.extractLow()); - childSetValue("BloomSize", gPostProcess->tweaks.bloomWidth()); - childSetValue("BloomStrength", gPostProcess->tweaks.bloomStrength()); + childSetValue("wmiBloomToggle", LLSD(gPostProcess->tweaks.useBloomShader())); + childSetValue("wmiBloomExtract", gPostProcess->tweaks.extractLow()); + childSetValue("wmiBloomSize", gPostProcess->tweaks.bloomWidth()); + childSetValue("wmiBloomStrength", gPostProcess->tweaks.bloomStrength()); } diff --git a/linden/indra/newview/llfloaterreporter.cpp b/linden/indra/newview/llfloaterreporter.cpp index a7f41ea..9209f41 100644 --- a/linden/indra/newview/llfloaterreporter.cpp +++ b/linden/indra/newview/llfloaterreporter.cpp @@ -952,7 +952,8 @@ void LLFloaterReporter::takeScreenshot() // store in the image list so it doesn't try to fetch from the server LLPointer<LLViewerImage> image_in_list = new LLViewerImage(mResourceDatap->mAssetInfo.mUuid); - image_in_list->createGLTexture(0, raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); + image_in_list->createGLTexture(0, raw); + gImageList.addImage(image_in_list); // the texture picker then uses that texture diff --git a/linden/indra/newview/llhudeffect.cpp b/linden/indra/newview/llhudeffect.cpp index c1d46f9..20bbb32 100644 --- a/linden/indra/newview/llhudeffect.cpp +++ b/linden/indra/newview/llhudeffect.cpp @@ -78,7 +78,7 @@ void LLHUDEffect::unpackData(LLMessageSystem *mesgsys, S32 blocknum) void LLHUDEffect::render() { - llerrs << "Never call this!" << llendl; + llwarns << "Never call this!" << llendl; // Then why the &*^&*^ is it here? } void LLHUDEffect::setID(const LLUUID &id) diff --git a/linden/indra/newview/llhudtext.cpp b/linden/indra/newview/llhudtext.cpp index 661a786..b170337 100644 --- a/linden/indra/newview/llhudtext.cpp +++ b/linden/indra/newview/llhudtext.cpp @@ -1111,6 +1111,8 @@ void LLHUDText::renderAllHUD() LLVertexBuffer::unbind(); + LLVertexBuffer::unbind(); // KL not entirely sure why but render pipeline has this twice? + LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); diff --git a/linden/indra/newview/llmanip.cpp b/linden/indra/newview/llmanip.cpp index 45550fc..0c88c47 100644 --- a/linden/indra/newview/llmanip.cpp +++ b/linden/indra/newview/llmanip.cpp @@ -60,7 +60,7 @@ #include "llglheaders.h" // Local constants... -const S32 VERTICAL_OFFSET = 50; +const S32 VERTICAL_OFFSET = 100; // KL adjusted to compensate for toolbars move to the top of the screen! F32 LLManip::sHelpTextVisibleTime = 2.f; F32 LLManip::sHelpTextFadeTime = 2.f; diff --git a/linden/indra/newview/llmaniptranslate.h b/linden/indra/newview/llmaniptranslate.h index 77f12ff..25ff35c 100644 --- a/linden/indra/newview/llmaniptranslate.h +++ b/linden/indra/newview/llmaniptranslate.h @@ -116,7 +116,7 @@ private: LLVector3d mDragCursorStartGlobal; LLVector3d mDragSelectionStartGlobal; LLTimer mUpdateTimer; - typedef std::multiset<ManipulatorHandle*, compare_manipulators> minpulator_list_t; + typedef std::set<ManipulatorHandle*, compare_manipulators> minpulator_list_t; minpulator_list_t mProjectedManipulators; LLVector4 mManipulatorVertices[18]; F32 mSnapOffsetMeters; diff --git a/linden/indra/newview/llmediactrl.cpp b/linden/indra/newview/llmediactrl.cpp index 1530598..a517332 100644 --- a/linden/indra/newview/llmediactrl.cpp +++ b/linden/indra/newview/llmediactrl.cpp @@ -1012,8 +1012,7 @@ BOOL LLWebBrowserTexture::render() x_pos, y_pos, width, - height, - TRUE); // force a fast update (i.e. don't call analyzeAlpha, etc.) + height); } media_plugin->resetDirty(); diff --git a/linden/indra/newview/lloverlaybar.cpp b/linden/indra/newview/lloverlaybar.cpp index db4422d..e903df7 100644 --- a/linden/indra/newview/lloverlaybar.cpp +++ b/linden/indra/newview/lloverlaybar.cpp @@ -491,7 +491,6 @@ void LLOverlayBar::toggleMusicPlay(void*) // if ( gAudiop->isInternetStreamPlaying() == 0 ) { gAudiop->startInternetStream(parcel->getMusicURL()); -//awfixme sTitleObserver.init(parcel->getMusicURL()); } } } diff --git a/linden/indra/newview/llpanelvolume.cpp b/linden/indra/newview/llpanelvolume.cpp index 6d014a2..4270f0b 100644 --- a/linden/indra/newview/llpanelvolume.cpp +++ b/linden/indra/newview/llpanelvolume.cpp @@ -53,6 +53,7 @@ #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcolorswatch.h" +#include "lltexturectrl.h" #include "llcombobox.h" #include "llfirstuse.h" #include "llfocusmgr.h" @@ -111,12 +112,28 @@ BOOL LLPanelVolume::postBuild() LightColorSwatch->setOnSelectCallback(onLightSelectColor); childSetCommitCallback("colorswatch",onCommitLight,this); } + + LLTextureCtrl* LightTexPicker = getChild<LLTextureCtrl>("light texture control"); + if (LightTexPicker) + { + LightTexPicker->setOnCancelCallback(onLightCancelTexture); + LightTexPicker->setOnSelectCallback(onLightSelectTexture); + childSetCommitCallback("light texture control", onCommitLight, this); + } + childSetCommitCallback("Light Intensity",onCommitLight,this); childSetValidate("Light Intensity",precommitValidate); childSetCommitCallback("Light Radius",onCommitLight,this); childSetValidate("Light Radius",precommitValidate); childSetCommitCallback("Light Falloff",onCommitLight,this); childSetValidate("Light Falloff",precommitValidate); + + childSetCommitCallback("Light FOV", onCommitLight, this); + childSetValidate("Light FOV", precommitValidate); + childSetCommitCallback("Light Focus", onCommitLight, this); + childSetValidate("Light Focus", precommitValidate); + childSetCommitCallback("Light Ambiance", onCommitLight, this); + childSetValidate("Light Ambiance", precommitValidate); } // Start with everyone disabled @@ -221,14 +238,32 @@ void LLPanelVolume::getState( ) LightColorSwatch->setValid( TRUE ); LightColorSwatch->set(volobjp->getLightBaseColor()); } + + LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control"); + if (LightTextureCtrl) + { + LightTextureCtrl->setEnabled(TRUE); + LightTextureCtrl->setValid(TRUE); + LightTextureCtrl->setImageAssetID(volobjp->getLightTextureID()); + } + childSetEnabled("Light Intensity",true); childSetEnabled("Light Radius",true); childSetEnabled("Light Falloff",true); + childSetEnabled("Light FOV", true); + childSetEnabled("Light Focus", true); + childSetEnabled("Light Ambiance", true); + childSetValue("Light Intensity",volobjp->getLightIntensity()); childSetValue("Light Radius",volobjp->getLightRadius()); childSetValue("Light Falloff",volobjp->getLightFalloff()); + LLVector3 params = volobjp->getSpotLightParams(); + childSetValue("Light FOV", params.mV[0]); + childSetValue("Light Focus", params.mV[1]); + childSetValue("Light Ambiance", params.mV[2]); + mLightSavedColor = volobjp->getLightColor(); } else @@ -244,9 +279,20 @@ void LLPanelVolume::getState( ) LightColorSwatch->setEnabled( FALSE ); LightColorSwatch->setValid( FALSE ); } + LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control"); + if (LightTextureCtrl) + { + LightTextureCtrl->setEnabled(FALSE); + LightTextureCtrl->setValid(FALSE); + } + childSetEnabled("Light Intensity",false); childSetEnabled("Light Radius",false); childSetEnabled("Light Falloff",false); + + childSetEnabled("Light FOV",false); + childSetEnabled("Light Focus",false); + childSetEnabled("Light Ambiance",false); } // Flexible properties @@ -362,6 +408,13 @@ void LLPanelVolume::clearCtrls() LightColorSwatch->setEnabled( FALSE ); LightColorSwatch->setValid( FALSE ); } + LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control"); + if(LightTextureCtrl) + { + LightTextureCtrl->setEnabled( FALSE ); + LightTextureCtrl->setValid( FALSE ); + } + childSetEnabled("Light Intensity",false); childSetEnabled("Light Radius",false); childSetEnabled("Light Falloff",false); @@ -438,6 +491,16 @@ void LLPanelVolume::onLightCancelColor(LLUICtrl* ctrl, void* userdata) onLightSelectColor(NULL, userdata); } +void LLPanelVolume::onLightCancelTexture(LLUICtrl* ctrl, void* userdata) +{ + LLPanelVolume* self = (LLPanelVolume*) userdata; + LLTextureCtrl* LightTextureCtrl = self->getChild<LLTextureCtrl>("light texture control"); + if (LightTextureCtrl) + { + LightTextureCtrl->setImageAssetID(self->mLightSavedTexture); + } +} + void LLPanelVolume::onLightSelectColor(LLUICtrl* ctrl, void* userdata) { LLPanelVolume* self = (LLPanelVolume*) userdata; @@ -459,6 +522,25 @@ void LLPanelVolume::onLightSelectColor(LLUICtrl* ctrl, void* userdata) } } +void LLPanelVolume::onLightSelectTexture(LLUICtrl* ctrl, void* userdata) +{ + LLPanelVolume* self = (LLPanelVolume*) userdata; + LLViewerObject* objectp = self->mObject; + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; + } + LLVOVolume *volobjp = (LLVOVolume *)objectp; + + + LLTextureCtrl* LightTextureCtrl = self->getChild<LLTextureCtrl>("light texture control"); + if(LightTextureCtrl) + { + LLUUID id = LightTextureCtrl->getImageAssetID(); + volobjp->setLightTextureID(id); + self->mLightSavedTexture = id; + } +} // static void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata ) { @@ -474,12 +556,47 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata ) volobjp->setLightIntensity((F32)self->childGetValue("Light Intensity").asReal()); volobjp->setLightRadius((F32)self->childGetValue("Light Radius").asReal()); volobjp->setLightFalloff((F32)self->childGetValue("Light Falloff").asReal()); + LLColorSwatchCtrl* LightColorSwatch = self->getChild<LLColorSwatchCtrl>("colorswatch"); if(LightColorSwatch) { LLColor4 clr = LightColorSwatch->get(); volobjp->setLightColor(LLColor3(clr)); } + + LLTextureCtrl* LightTextureCtrl = self->getChild<LLTextureCtrl>("light texture control"); + if(LightTextureCtrl) + { + LLUUID id = LightTextureCtrl->getImageAssetID(); + if (id.notNull()) + { + if (volobjp->getLightTextureID().isNull()) + { //this commit is making this a spot light, set UI to default params + volobjp->setLightTextureID(id); + LLVector3 spot_params = volobjp->getSpotLightParams(); + self->childSetValue("Light FOV", spot_params.mV[0]); + self->childSetValue("Light Focus", spot_params.mV[1]); + self->childSetValue("Light Ambiance", spot_params.mV[2]); + } + else + { //modifying existing params + LLVector3 spot_params; + spot_params.mV[0] = (F32) self->childGetValue("Light FOV").asReal(); + spot_params.mV[1] = (F32) self->childGetValue("Light Focus").asReal(); + spot_params.mV[2] = (F32) self->childGetValue("Light Ambiance").asReal(); + volobjp->setSpotLightParams(spot_params); + } + } + else if (volobjp->getLightTextureID().notNull()) + { //no longer a spot light + volobjp->setLightTextureID(id); + //self->childDisable("Light FOV"); + //self->childDisable("Light Focus"); + //self->childDisable("Light Ambiance"); + } + } + + } // static diff --git a/linden/indra/newview/llpanelvolume.h b/linden/indra/newview/llpanelvolume.h index 841880b..5d206fc 100644 --- a/linden/indra/newview/llpanelvolume.h +++ b/linden/indra/newview/llpanelvolume.h @@ -74,6 +74,10 @@ public: static void onLightCancelColor(LLUICtrl* ctrl, void* userdata); static void onLightSelectColor(LLUICtrl* ctrl, void* userdata); + static void onLightCancelTexture(LLUICtrl* ctrl, void* userdata); + static void onLightSelectTexture(LLUICtrl* ctrl, void* userdata); + + protected: void getState(); @@ -99,6 +103,7 @@ protected: */ LLColor4 mLightSavedColor; + LLUUID mLightSavedTexture; LLPointer<LLViewerObject> mObject; LLPointer<LLViewerObject> mRootObject; }; diff --git a/linden/indra/newview/llpostprocess.cpp b/linden/indra/newview/llpostprocess.cpp new file mode 100644 index 0000000..c7d5dad --- /dev/null +++ b/linden/indra/newview/llpostprocess.cpp @@ -0,0 +1,594 @@ +/** + * @file llpostprocess.cpp + * @brief LLPostProcess class implementation + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "linden_common.h" + +#include "llpostprocess.h" +#include "llglslshader.h" +#include "llsdserialize.h" +#include "llrender.h" + +#include "llviewershadermgr.h" // KL throwing some includes at postprocess see if we can get the bastard working! +#include "pipeline.h" +#include "llimagegl.h" + + + +LLPostProcess * gPostProcess = NULL; + + +static const unsigned int NOISE_SIZE = 512; + +/// CALCULATING LUMINANCE (Using NTSC lum weights) +/// http://en.wikipedia.org/wiki/Luma_%28video%29 +static const float LUMINANCE_R = 0.299f; +static const float LUMINANCE_G = 0.587f; +static const float LUMINANCE_B = 0.114f; + +static const char * const XML_FILENAME = "postprocesseffects.xml"; + +LLPostProcess::LLPostProcess(void) : + initialized(false), + mAllEffects(LLSD::emptyMap()), + screenW(1), screenH(1) +{ + mSceneRenderTexture = NULL ; + mNoiseTexture = NULL ; + mTempBloomTexture = NULL ; + + // Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender. + std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME)); + LL_DEBUGS2("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL; + + llifstream effectsXML(pathName); + + if (effectsXML) + { + LLPointer<LLSDParser> parser = new LLSDXMLParser(); + + parser->parse(effectsXML, mAllEffects, LLSDSerialize::SIZE_UNLIMITED); + } + + if (!mAllEffects.has("default")) + { + LLSD & defaultEffect = (mAllEffects["default"] = LLSD::emptyMap()); + + defaultEffect["enable_night_vision"] = LLSD::Boolean(false); + defaultEffect["enable_bloom"] = LLSD::Boolean(false); + defaultEffect["enable_color_filter"] = LLSD::Boolean(false); + + /// NVG Defaults + defaultEffect["brightness_multiplier"] = 3.0; + defaultEffect["noise_size"] = 25.0; + defaultEffect["noise_strength"] = 0.4; + + // TODO BTest potentially add this to tweaks? + noiseTextureScale = 1.0f; + + /// Bloom Defaults + defaultEffect["extract_low"] = 0.95; + defaultEffect["extract_high"] = 1.0; + defaultEffect["bloom_width"] = 2.25; + defaultEffect["bloom_strength"] = 1.5; + + /// Color Filter Defaults + defaultEffect["brightness"] = 1.0; + defaultEffect["contrast"] = 1.0; + defaultEffect["saturation"] = 1.0; + + LLSD& contrastBase = (defaultEffect["contrast_base"] = LLSD::emptyArray()); + contrastBase.append(1.0); + contrastBase.append(1.0); + contrastBase.append(1.0); + contrastBase.append(0.5); + } + + setSelectedEffect("default"); + +} + +LLPostProcess::~LLPostProcess(void) +{ + invalidate() ; +} + +// static +void LLPostProcess::initClass(void) +{ + //this will cause system to crash at second time login + //if first time login fails due to network connection --- bao + //***llassert_always(gPostProcess == NULL); + //replaced by the following line: + if(gPostProcess) + return ; + + + gPostProcess = new LLPostProcess(); +} + +// static +void LLPostProcess::cleanupClass() +{ + delete gPostProcess; + gPostProcess = NULL; +} + +void LLPostProcess::setSelectedEffect(std::string const & effectName) +{ + mSelectedEffectName = effectName; + static_cast<LLSD &>(tweaks) = mAllEffects[effectName]; +} + +void LLPostProcess::saveEffect(std::string const & effectName) +{ + // Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender. + mAllEffects[effectName] = tweaks; + + std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME)); + //llinfos << "Saving PostProcess Effects settings to " << pathName << llendl; + + llofstream effectsXML(pathName); + + LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter(); + + formatter->format(mAllEffects, effectsXML); + +} +void LLPostProcess::invalidate() +{ + mSceneRenderTexture = NULL ; + mNoiseTexture = NULL ; + mTempBloomTexture = NULL ; + initialized = FALSE ; +} + +void LLPostProcess::apply(unsigned int width, unsigned int height) +{ + if (!initialized || width != screenW || height != screenH){ + initialize(width, height); + } + if (shadersEnabled()){ + doEffects(); + } +} + +void LLPostProcess::initialize(unsigned int width, unsigned int height) +{ + screenW = width; + screenH = height; + createTexture(mSceneRenderTexture, screenW, screenH); + initialized = true; + + checkError(); + createNightVisionShader(); + createBloomShader(); + createColorFilterShader(); + checkError(); +} + +inline bool LLPostProcess::shadersEnabled(void) +{ + return (tweaks.useColorFilter().asBoolean() || + tweaks.useNightVisionShader().asBoolean() || + tweaks.useBloomShader().asBoolean() ); + +} + +void LLPostProcess::applyShaders(void) +{ + if (tweaks.useColorFilter()){ + applyColorFilterShader(); + checkError(); + } + if (tweaks.useNightVisionShader()){ + /// If any of the above shaders have been called update the frame buffer; + if (tweaks.useColorFilter()) + { + U32 tex = mSceneRenderTexture->getTexName() ; + copyFrameBuffer(tex, screenW, screenH); + } + applyNightVisionShader(); + checkError(); + } + if (tweaks.useBloomShader()){ + /// If any of the above shaders have been called update the frame buffer; + if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean()) + { + U32 tex = mSceneRenderTexture->getTexName() ; + copyFrameBuffer(tex, screenW, screenH); + } + applyBloomShader(); + checkError(); + } +} + +void LLPostProcess::applyColorFilterShader(void) +{ + // Do nothing. moved back to newview work in progress KL + gPostColorFilterProgram.bind(); + + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE); + + U32 tex = mSceneRenderTexture->getTexName() ; // KL + + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, tex); + + getShaderUniforms(colorFilterUniforms, gPostColorFilterProgram.mProgramObject); + glUniform1iARB(colorFilterUniforms["RenderTexture"], 0); + glUniform1fARB(colorFilterUniforms["brightness"], tweaks.getBrightness()); + glUniform1fARB(colorFilterUniforms["contrast"], tweaks.getContrast()); + float baseI = (tweaks.getContrastBaseR() + tweaks.getContrastBaseG() + tweaks.getContrastBaseB()) / 3.0f; + baseI = tweaks.getContrastBaseIntensity() / ((baseI < 0.001f) ? 0.001f : baseI); + float baseR = tweaks.getContrastBaseR() * baseI; + float baseG = tweaks.getContrastBaseG() * baseI; + float baseB = tweaks.getContrastBaseB() * baseI; + glUniform3fARB(colorFilterUniforms["contrastBase"], baseR, baseG, baseB); + glUniform1fARB(colorFilterUniforms["saturation"], tweaks.getSaturation()); + glUniform3fARB(colorFilterUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B); + + LLGLEnable blend(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_REPLACE); + LLGLDepthTest depth(GL_FALSE); + + /// Draw a screen space quad + drawOrthoQuad(screenW, screenH, QUAD_NORMAL); + gPostColorFilterProgram.unbind(); + +} + +void LLPostProcess::createColorFilterShader(void) +{ + /// Define uniform names + colorFilterUniforms["RenderTexture"] = 0; + colorFilterUniforms["brightness"] = 0; + colorFilterUniforms["contrast"] = 0; + colorFilterUniforms["contrastBase"] = 0; + colorFilterUniforms["saturation"] = 0; + colorFilterUniforms["lumWeights"] = 0; +} + +void LLPostProcess::applyNightVisionShader(void) +{ + // KL re-enabled and moved back to newview + gPostNightVisionProgram.bind(); + + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE); + + getShaderUniforms(nightVisionUniforms, gPostNightVisionProgram.mProgramObject); + U32 sceneRenderTexture = mSceneRenderTexture->getTexName() ; // KL + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, sceneRenderTexture); + glUniform1iARB(nightVisionUniforms["RenderTexture"], 0); + + gGL.getTexUnit(1)->activate(); + gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); + U32 noiseTexture = mNoiseTexture->getTexName(); //KL + gGL.getTexUnit(1)->bindManual(LLTexUnit::TT_TEXTURE, noiseTexture); + glUniform1iARB(nightVisionUniforms["NoiseTexture"], 1); + + + glUniform1fARB(nightVisionUniforms["brightMult"], tweaks.getBrightMult()); + glUniform1fARB(nightVisionUniforms["noiseStrength"], tweaks.getNoiseStrength()); + noiseTextureScale = 0.01f + ((101.f - tweaks.getNoiseSize()) / 100.f); + noiseTextureScale *= (screenH / NOISE_SIZE); + + + glUniform3fARB(nightVisionUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B); + + LLGLEnable blend(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_REPLACE); + LLGLDepthTest depth(GL_FALSE); + + /// Draw a screen space quad + drawOrthoQuad(screenW, screenH, QUAD_NOISE); + gPostNightVisionProgram.unbind(); + gGL.getTexUnit(0)->activate(); + +} + +void LLPostProcess::createNightVisionShader(void) +{ + /// Define uniform names + nightVisionUniforms["RenderTexture"] = 0; + nightVisionUniforms["NoiseTexture"] = 0; + nightVisionUniforms["brightMult"] = 0; + nightVisionUniforms["noiseStrength"] = 0; + nightVisionUniforms["lumWeights"] = 0; + + createNoiseTexture(mNoiseTexture); +} + +void LLPostProcess::applyBloomShader(void) +{ + +} + +void LLPostProcess::createBloomShader(void) +{ + createTexture(mTempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5)); + + /// Create Bloom Extract Shader + bloomExtractUniforms["RenderTexture"] = 0; + bloomExtractUniforms["extractLow"] = 0; + bloomExtractUniforms["extractHigh"] = 0; + bloomExtractUniforms["lumWeights"] = 0; + + /// Create Bloom Blur Shader + bloomBlurUniforms["RenderTexture"] = 0; + bloomBlurUniforms["bloomStrength"] = 0; + bloomBlurUniforms["texelSize"] = 0; + bloomBlurUniforms["blurDirection"] = 0; + bloomBlurUniforms["blurWidth"] = 0; +} + +void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog) +{ + /// Find uniform locations and insert into map + std::map<const char *, GLuint>::iterator i; + for (i = uniforms.begin(); i != uniforms.end(); ++i){ + i->second = glGetUniformLocationARB(prog, i->first); + } +} + +void LLPostProcess::doEffects(void) +{ + /// Save GL State + glPushAttrib(GL_ALL_ATTRIB_BITS); + glPushClientAttrib(GL_ALL_ATTRIB_BITS); + + /// Copy the screen buffer to the render texture + { + U32 tex = mSceneRenderTexture->getTexName() ; + copyFrameBuffer(tex, screenW, screenH); + } + + /// Clear the frame buffer. + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + /// Change to an orthogonal view + viewOrthogonal(screenW, screenH); + + checkError(); + applyShaders(); + + LLGLSLShader::bindNoShader(); + checkError(); + + /// Change to a perspective view + viewPerspective(); + + /// Reset GL State + glPopClientAttrib(); + glPopAttrib(); + checkError(); +} + +void LLPostProcess::copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height) +{ + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture); + glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0); +} + +void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadType type) +{ + + float noiseX = 0.f; + float noiseY = 0.f; + float screenRatio = 1.0f; + + if (type == QUAD_NOISE){ + noiseX = ((float) rand() / (float) RAND_MAX); + noiseY = ((float) rand() / (float) RAND_MAX); + screenRatio = (float) width / (float) height; + } + + + glBegin(GL_QUADS); + if (type != QUAD_BLOOM_EXTRACT){ + glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height); + } else { + glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height * 2.0f); + } + if (type == QUAD_NOISE){ + glMultiTexCoord2fARB(GL_TEXTURE1_ARB, + noiseX, + noiseTextureScale + noiseY); + } else if (type == QUAD_BLOOM_COMBINE){ + glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, (GLfloat) height * 0.5f); + } + glVertex2f(0.f, (GLfloat) screenH - height); + + if (type != QUAD_BLOOM_EXTRACT){ + glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f); + } else { + glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f); + } + if (type == QUAD_NOISE){ + glMultiTexCoord2fARB(GL_TEXTURE1_ARB, + noiseX, + noiseY); + } else if (type == QUAD_BLOOM_COMBINE){ + glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, 0.f); + } + glVertex2f(0.f, (GLfloat) height + (screenH - height)); + + + if (type != QUAD_BLOOM_EXTRACT){ + glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, 0.f); + } else { + glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, 0.f); + } + if (type == QUAD_NOISE){ + glMultiTexCoord2fARB(GL_TEXTURE1_ARB, + screenRatio * noiseTextureScale + noiseX, + noiseY); + } else if (type == QUAD_BLOOM_COMBINE){ + glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, 0.f); + } + glVertex2f((GLfloat) width, (GLfloat) height + (screenH - height)); + + + if (type != QUAD_BLOOM_EXTRACT){ + glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, (GLfloat) height); + } else { + glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, (GLfloat) height * 2.0f); + } + if (type == QUAD_NOISE){ + glMultiTexCoord2fARB(GL_TEXTURE1_ARB, + screenRatio * noiseTextureScale + noiseX, + noiseTextureScale + noiseY); + } else if (type == QUAD_BLOOM_COMBINE){ + glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, (GLfloat) height * 0.5f); + } + glVertex2f((GLfloat) width, (GLfloat) screenH - height); + glEnd(); + +} + +void LLPostProcess::viewOrthogonal(unsigned int width, unsigned int height) +{ + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho( 0.f, (GLdouble) width , (GLdouble) height , 0.f, -1.f, 1.f ); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); +} + +void LLPostProcess::viewPerspective(void) +{ + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); +} + +void LLPostProcess::changeOrthogonal(unsigned int width, unsigned int height) +{ + viewPerspective(); + viewOrthogonal(width, height); +} + +void LLPostProcess::createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height) +{ + std::vector<GLubyte> data(width * height * 4, 0) ; + + texture = new LLImageGL(FALSE) ; + if(texture->createGLTexture()) + { + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture->getTexName()); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + } +} + +void LLPostProcess::createNoiseTexture(LLPointer<LLImageGL>& texture) +{ + std::vector<GLubyte> buffer(NOISE_SIZE * NOISE_SIZE); + for (unsigned int i = 0; i < NOISE_SIZE; i++){ + for (unsigned int k = 0; k < NOISE_SIZE; k++){ + buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f); + } + } + + texture = new LLImageGL(FALSE) ; + if(texture->createGLTexture()) + { + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName()); + LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); + } +} + +bool LLPostProcess::checkError(void) +{ + GLenum glErr; + bool retCode = false; + + glErr = glGetError(); + while (glErr != GL_NO_ERROR) + { + // shaderErrorLog << (const char *) gluErrorString(glErr) << std::endl; + char const * err_str_raw = (const char *) gluErrorString(glErr); + + if(err_str_raw == NULL) + { + std::ostringstream err_builder; + err_builder << "unknown error number " << glErr; + mShaderErrorString = err_builder.str(); + } + else + { + mShaderErrorString = err_str_raw; + } + + retCode = true; + glErr = glGetError(); + } + return retCode; +} + +void LLPostProcess::checkShaderError(GLhandleARB shader) +{ + GLint infologLength = 0; + GLint charsWritten = 0; + GLchar *infoLog; + + checkError(); // Check for OpenGL errors + + glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength); + + checkError(); // Check for OpenGL errors + + if (infologLength > 0) + { + infoLog = (GLchar *)malloc(infologLength); + if (infoLog == NULL) + { + /// Could not allocate infolog buffer + return; + } + glGetInfoLogARB(shader, infologLength, &charsWritten, infoLog); + // shaderErrorLog << (char *) infoLog << std::endl; + mShaderErrorString = (char *) infoLog; + free(infoLog); + } + checkError(); // Check for OpenGL errors +} \ No newline at end of file diff --git a/linden/indra/newview/llpostprocess.h b/linden/indra/newview/llpostprocess.h new file mode 100644 index 0000000..d6926e4 --- /dev/null +++ b/linden/indra/newview/llpostprocess.h @@ -0,0 +1,274 @@ +/** + * @file llpostprocess.h + * @brief LLPostProcess class definition + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_POSTPROCESS_H +#define LL_POSTPROCESS_H + +#include <map> +#include <fstream> +#include "llgl.h" +#include "llglheaders.h" + +class LLPostProcess +{ +public: + + typedef enum _QuadType { + QUAD_NORMAL, + QUAD_NOISE, + QUAD_BLOOM_EXTRACT, + QUAD_BLOOM_COMBINE + } QuadType; + + /// GLSL Shader Encapsulation Struct + typedef std::map<const char *, GLuint> glslUniforms; + + struct PostProcessTweaks : public LLSD { + inline PostProcessTweaks() : LLSD(LLSD::emptyMap()) + { + } + + inline LLSD & brightMult() { + return (*this)["brightness_multiplier"]; + } + + inline LLSD & noiseStrength() { + return (*this)["noise_strength"]; + } + + inline LLSD & noiseSize() { + return (*this)["noise_size"]; + } + + inline LLSD & extractLow() { + return (*this)["extract_low"]; + } + + inline LLSD & extractHigh() { + return (*this)["extract_high"]; + } + + inline LLSD & bloomWidth() { + return (*this)["bloom_width"]; + } + + inline LLSD & bloomStrength() { + return (*this)["bloom_strength"]; + } + + inline LLSD & brightness() { + return (*this)["brightness"]; + } + + inline LLSD & contrast() { + return (*this)["contrast"]; + } + + inline LLSD & contrastBaseR() { + return (*this)["contrast_base"][0]; + } + + inline LLSD & contrastBaseG() { + return (*this)["contrast_base"][1]; + } + + inline LLSD & contrastBaseB() { + return (*this)["contrast_base"][2]; + } + + inline LLSD & contrastBaseIntensity() { + return (*this)["contrast_base"][3]; + } + + inline LLSD & saturation() { + return (*this)["saturation"]; + } + + inline LLSD & useNightVisionShader() { + return (*this)["enable_night_vision"]; + } + + inline LLSD & useBloomShader() { + return (*this)["enable_bloom"]; + } + + inline LLSD & useColorFilter() { + return (*this)["enable_color_filter"]; + } + + + inline F32 getBrightMult() const { + return F32((*this)["brightness_multiplier"].asReal()); + } + + inline F32 getNoiseStrength() const { + return F32((*this)["noise_strength"].asReal()); + } + + inline F32 getNoiseSize() const { + return F32((*this)["noise_size"].asReal()); + } + + inline F32 getExtractLow() const { + return F32((*this)["extract_low"].asReal()); + } + + inline F32 getExtractHigh() const { + return F32((*this)["extract_high"].asReal()); + } + + inline F32 getBloomWidth() const { + return F32((*this)["bloom_width"].asReal()); + } + + inline F32 getBloomStrength() const { + return F32((*this)["bloom_strength"].asReal()); + } + + inline F32 getBrightness() const { + return F32((*this)["brightness"].asReal()); + } + + inline F32 getContrast() const { + return F32((*this)["contrast"].asReal()); + } + + inline F32 getContrastBaseR() const { + return F32((*this)["contrast_base"][0].asReal()); + } + + inline F32 getContrastBaseG() const { + return F32((*this)["contrast_base"][1].asReal()); + } + + inline F32 getContrastBaseB() const { + return F32((*this)["contrast_base"][2].asReal()); + } + + inline F32 getContrastBaseIntensity() const { + return F32((*this)["contrast_base"][3].asReal()); + } + + inline F32 getSaturation() const { + return F32((*this)["saturation"].asReal()); + } + + }; + + bool initialized; + PostProcessTweaks tweaks; + + // the map of all availible effects + LLSD mAllEffects; + +private: + LLPointer<LLImageGL> mSceneRenderTexture ; + LLPointer<LLImageGL> mNoiseTexture ; + LLPointer<LLImageGL> mTempBloomTexture ; + + + +public: + LLPostProcess(void); + + ~LLPostProcess(void); + + void apply(unsigned int width, unsigned int height); + void invalidate() ; + + /// Perform global initialization for this class. + static void initClass(void); + + // Cleanup of global data that's only inited once per class. + static void cleanupClass(); + + void setSelectedEffect(std::string const & effectName); + + inline std::string const & getSelectedEffect(void) const { + return mSelectedEffectName; + } + + void saveEffect(std::string const & effectName); + +private: + /// read in from file + std::string mShaderErrorString; + unsigned int screenW; + unsigned int screenH; + + float noiseTextureScale; + + /// Shader Uniforms + glslUniforms nightVisionUniforms; + glslUniforms bloomExtractUniforms; + glslUniforms bloomBlurUniforms; + glslUniforms colorFilterUniforms; + + // the name of currently selected effect in mAllEffects + //invariant: tweaks == mAllEffects[mSelectedEffectName] + std::string mSelectedEffectName; + + /// General functions + void initialize(unsigned int width, unsigned int height); + void doEffects(void); + void applyShaders(void); + bool shadersEnabled(void); + + /// Night Vision Functions + void createNightVisionShader(void); + void applyNightVisionShader(void); + + /// Bloom Functions + void createBloomShader(void); + void applyBloomShader(void); + + /// Color Filter Functions + void createColorFilterShader(void); + void applyColorFilterShader(void); + + /// OpenGL Helper Functions + void getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog); + void createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height); + void copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height); + void createNoiseTexture(LLPointer<LLImageGL>& texture); + bool checkError(void); + void checkShaderError(GLhandleARB shader); + void drawOrthoQuad(unsigned int width, unsigned int height, QuadType type); + void viewOrthogonal(unsigned int width, unsigned int height); + void changeOrthogonal(unsigned int width, unsigned int height); + void viewPerspective(void); +}; + +extern LLPostProcess * gPostProcess; + + +#endif // LL_POSTPROCESS_H diff --git a/linden/indra/newview/llpreview.cpp b/linden/indra/newview/llpreview.cpp index f679a75..019bd5f 100644 --- a/linden/indra/newview/llpreview.cpp +++ b/linden/indra/newview/llpreview.cpp @@ -641,6 +641,7 @@ void LLPreview::setAssetId(const LLUUID& asset_id) LLViewerObject* object = gObjectList.findObject(mObjectUUID); if(NULL == object) { + llwarns << "LLPreview::setAssetId() called on unrecognized object, UUID : " << mObjectUUID << llendl; return; } object->updateViewerInventoryAsset(item, asset_id); diff --git a/linden/indra/newview/llselectmgr.cpp b/linden/indra/newview/llselectmgr.cpp index b2904b9..0fa8285 100644 --- a/linden/indra/newview/llselectmgr.cpp +++ b/linden/indra/newview/llselectmgr.cpp @@ -764,7 +764,7 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab } else { - llerrs << "LLSelectMgr::add face " << face << " out-of-range" << llendl; + llwarns << "LLSelectMgr::add face " << face << " out-of-range" << llendl; return; } @@ -1187,7 +1187,7 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable) } else { - llerrs << "LLSelectMgr::remove - tried to remove TE " << te << " that wasn't selected" << llendl; + llwarns << "LLSelectMgr::remove - tried to remove TE " << te << " that wasn't selected" << llendl; return; } @@ -1210,7 +1210,7 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable) else { // ...out of range face - llerrs << "LLSelectMgr::remove - TE " << te << " out of range" << llendl; + llwarns << "LLSelectMgr::remove - TE " << te << " out of range" << llendl; } updateSelectionCenter(); @@ -1709,7 +1709,7 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright) } sendfunc(fullbright); getSelection()->applyToObjects(&sendfunc); } - +/* void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url) { U8 media_flags = LLTextureEntry::MF_NONE; @@ -1752,7 +1752,7 @@ void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& } sendfunc(media_type, media_url); getSelection()->applyToObjects(&sendfunc); } - +*/ void LLSelectMgr::selectionSetGlow(F32 glow) { struct f1 : public LLSelectedTEFunctor @@ -3344,7 +3344,7 @@ void LLSelectMgr::packPermissionsHead(void* user_data) /* void LLSelectMgr::sendSelect() { - llerrs << "Not implemented" << llendl; + llwarns << "Not implemented" << llendl; } */ @@ -4156,7 +4156,7 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name, break; default: - llerrs << "Bad send type " << send_type << " passed to SendListToRegions()" << llendl; + llwarns << "Bad send type " << send_type << " passed to SendListToRegions()" << llendl; } // bail if nothing selected @@ -4563,11 +4563,6 @@ extern LLGLdouble gGLModelView[16]; void LLSelectMgr::updateSilhouettes() { - if (!mRenderSilhouettes || !LLSelectMgr::sRenderSelectionHighlights) - { - return; - } - S32 num_sils_genned = 0; LLVector3d cameraPos = gAgent.getCameraPositionGlobal(); @@ -5781,8 +5776,7 @@ BOOL LLSelectMgr::canSelectObject(LLViewerObject* object) } if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !object->permYouOwner()) || - (gSavedSettings.getBOOL("SelectMovableOnly") && !object->permMove()) || - (gSavedSettings.getBOOL("SelectCopyableOnly") && !object->permCopy())) + (gSavedSettings.getBOOL("SelectMovableOnly") && !object->permMove())) { // only select my own objects return FALSE; diff --git a/linden/indra/newview/llselectmgr.h b/linden/indra/newview/llselectmgr.h index 6278049..b565770 100644 --- a/linden/indra/newview/llselectmgr.h +++ b/linden/indra/newview/llselectmgr.h @@ -503,7 +503,7 @@ public: void selectionSetTexGen( U8 texgen ); void selectionSetShiny( U8 shiny ); void selectionSetFullbright( U8 fullbright ); - void selectionSetMediaTypeAndURL( U8 media_type, const std::string& media_url ); +// void selectionSetMediaTypeAndURL( U8 media_type, const std::string& media_url ); void selectionSetClickAction(U8 action); void selectionSetIncludeInSearch(bool include_in_search); void selectionSetGlow(const F32 glow); diff --git a/linden/indra/newview/llsky.cpp b/linden/indra/newview/llsky.cpp index ac7e865..b779aa0 100644 --- a/linden/indra/newview/llsky.cpp +++ b/linden/indra/newview/llsky.cpp @@ -422,6 +422,20 @@ void LLSky::updateFog(const F32 distance) void LLSky::updateCull() { + /*if (mVOSkyp.notNull() && mVOSkyp->mDrawable.notNull()) + { + gPipeline.markVisible(mVOSkyp->mDrawable); + } + else + { + llinfos << "No sky drawable!" << llendl; + }*/ + + /*if (mVOGroundp.notNull() && mVOGroundp->mDrawable.notNull()) + { + gPipeline.markVisible(mVOGroundp->mDrawable); + }*/ + // *TODO: do culling for wl sky properly -Brad } diff --git a/linden/indra/newview/llspatialpartition.cpp b/linden/indra/newview/llspatialpartition.cpp index 31b537c..114d3b5 100644 --- a/linden/indra/newview/llspatialpartition.cpp +++ b/linden/indra/newview/llspatialpartition.cpp @@ -48,6 +48,7 @@ #include "llrender.h" #include "lloctree.h" #include "llvoavatar.h" +#include "lltextureatlas.h" const F32 SG_OCCLUSION_FUDGE = 0.25f; #define SG_DISCARD_TOLERANCE 0.01f @@ -95,7 +96,7 @@ void sg_assert(BOOL expr) #if LL_OCTREE_PARANOIA_CHECK if (!expr) { - llerrs << "Octree invalid!" << llendl; + llwarns << "Octree invalid!" << llendl; } #endif } @@ -281,10 +282,10 @@ S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3 LLSpatialGroup::~LLSpatialGroup() { - if (sNoDelete) + /*if (sNoDelete) { - llerrs << "Illegal deletion of LLSpatialGroup!" << llendl; - } + llwarns << "Illegal deletion of LLSpatialGroup!" << llendl; + }*/ if (isState(DEAD)) { @@ -302,6 +303,129 @@ LLSpatialGroup::~LLSpatialGroup() LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); clearDrawMap(); + clearAtlasList() ; +} + +BOOL LLSpatialGroup::hasAtlas(LLTextureAtlas* atlasp) +{ + S8 type = atlasp->getComponents() - 1 ; + for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter) + { + if(atlasp == *iter) + { + return TRUE ; + } + } + return FALSE ; +} + +void LLSpatialGroup::addAtlas(LLTextureAtlas* atlasp, S8 recursive_level) +{ + if(!hasAtlas(atlasp)) + { + mAtlasList[atlasp->getComponents() - 1].push_back(atlasp) ; + atlasp->addSpatialGroup(this) ; + } + + --recursive_level; + if(recursive_level)//levels propagating up. + { + LLSpatialGroup* parent = getParent() ; + if(parent) + { + parent->addAtlas(atlasp, recursive_level) ; + } + } +} + +void LLSpatialGroup::removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group, S8 recursive_level) +{ + mAtlasList[atlasp->getComponents() - 1].remove(atlasp) ; + if(remove_group) + { + atlasp->removeSpatialGroup(this) ; + } + + --recursive_level; + if(recursive_level)//levels propagating up. + { + LLSpatialGroup* parent = getParent() ; + if(parent) + { + parent->removeAtlas(atlasp, recursive_level) ; + } + } +} + +void LLSpatialGroup::clearAtlasList() +{ + std::list<LLTextureAtlas*>::iterator iter ; + for(S8 i = 0 ; i < 4 ; i++) + { + if(mAtlasList[i].size() > 0) + { + for(iter = mAtlasList[i].begin(); iter != mAtlasList[i].end() ; ++iter) + { + ((LLTextureAtlas*)*iter)->removeSpatialGroup(this) ; + } + mAtlasList[i].clear() ; + } + } +} + +LLTextureAtlas* LLSpatialGroup::getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level) +{ + S8 type = ncomponents - 1 ; + if(mAtlasList[type].size() > 0) + { + for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter) + { + if(!((LLTextureAtlas*)*iter)->isFull(to_be_reserved)) + { + return *iter ; + } + } + } + + --recursive_level; + if(recursive_level) + { + LLSpatialGroup* parent = getParent() ; + if(parent) + { + return parent->getAtlas(ncomponents, to_be_reserved, recursive_level) ; + } + } + return NULL ; +} + +void LLSpatialGroup::setCurUpdatingSlot(LLTextureAtlasSlot* slotp) +{ + mCurUpdatingSlotp = slotp; + + //if(!hasAtlas(mCurUpdatingSlotp->getAtlas())) + //{ + // addAtlas(mCurUpdatingSlotp->getAtlas()) ; + //} +} + +LLTextureAtlasSlot* LLSpatialGroup::getCurUpdatingSlot(LLViewerImage* imagep, S8 recursive_level) +{ + if(gFrameCount && mCurUpdatingTime == gFrameCount && mCurUpdatingTexture == imagep) + { + return mCurUpdatingSlotp ; + } + + //--recursive_level ; + //if(recursive_level) + //{ + // LLSpatialGroup* parent = getParent() ; + // if(parent) + // { + // return parent->getCurUpdatingSlot(imagep, recursive_level) ; + // } + //} + return NULL ; } void LLSpatialGroup::clearDrawMap() @@ -348,7 +472,7 @@ void LLSpatialGroup::validate() LLSpatialPartition* part = drawable->asPartition(); if (!part) { - llerrs << "Drawable reports it is a spatial bridge but not a partition." << llendl; + llwarns << "Drawable reports it is a spatial bridge but not a partition." << llendl; } LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); group->validate(); @@ -411,7 +535,7 @@ public: if (mInheritedMask && !group->isState(mInheritedMask)) { - llerrs << "Spatial group failed inherited mask test." << llendl; + llwarns << "Spatial group failed inherited mask test." << llendl; } if (group->isState(LLSpatialGroup::DIRTY)) @@ -427,7 +551,7 @@ public: { if (!parent->isState(state)) { - llerrs << "Spatial group failed parent state check." << llendl; + llwarns << "Spatial group failed parent state check." << llendl; } parent = parent->getParent(); } @@ -448,39 +572,39 @@ void validate_draw_info(LLDrawInfo& params) #if LL_OCTREE_PARANOIA_CHECK if (params.mVertexBuffer.isNull()) { - llerrs << "Draw batch has no vertex buffer." << llendl; + llwarns << "Draw batch has no vertex buffer." << llendl; } //bad range if (params.mStart >= params.mEnd) { - llerrs << "Draw batch has invalid range." << llendl; + llwarns << "Draw batch has invalid range." << llendl; } if (params.mEnd >= (U32) params.mVertexBuffer->getNumVerts()) { - llerrs << "Draw batch has buffer overrun error." << llendl; + llwarns << "Draw batch has buffer overrun error." << llendl; } if (params.mOffset + params.mCount > (U32) params.mVertexBuffer->getNumIndices()) { - llerrs << "Draw batch has index buffer ovverrun error." << llendl; + llwarns << "Draw batch has index buffer ovverrun error." << llendl; } //bad indices - U32* indicesp = (U32*) params.mVertexBuffer->getIndicesPointer(); + U16* indicesp = (U16*) params.mVertexBuffer->getIndicesPointer(); // KL 16 indices for SD not 32 if (indicesp) { for (U32 i = params.mOffset; i < params.mOffset+params.mCount; i++) { - if (indicesp[i] < params.mStart) + if (indicesp[i] < (U16)params.mStart) //KL { - llerrs << "Draw batch has vertex buffer index out of range error (index too low)." << llendl; + llwarns << "Draw batch has vertex buffer index out of range error (index too low)." << llendl; } - if (indicesp[i] > params.mEnd) + if (indicesp[i] > (U16)params.mEnd) // KL { - llerrs << "Draw batch has vertex buffer index out of range error (index too high)." << llendl; + llwarns << "Draw batch has vertex buffer index out of range error (index too high)." << llendl; } } } @@ -540,6 +664,7 @@ BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_oc drawablep->setSpatialGroup(this); validate_drawable(drawablep); setState(OBJECT_DIRTY | GEOM_DIRTY | DISCARD_QUERY); + gPipeline.markRebuild(this, TRUE); if (drawablep->isSpatialBridge()) { mBridgeList.push_back((LLSpatialBridge*) drawablep); @@ -572,22 +697,23 @@ void LLSpatialGroup::rebuildMesh() void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) { - if (!gPipeline.hasRenderType(mDrawableType)) + /*if (!gPipeline.hasRenderType(mDrawableType)) { return; - } - - if (!LLPipeline::sSkipUpdate && group->changeLOD()) - { - group->mLastUpdateDistance = group->mDistance; - group->mLastUpdateViewAngle = group->mViewAngle; - } + }*/ if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) { + /*if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && mRenderByGroup) + { + llwarns << "WTF?" << llendl; + }*/ return; } + group->mLastUpdateDistance = group->mDistance; + group->mLastUpdateViewAngle = group->mViewAngle; + LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO); group->clearDrawMap(); @@ -625,6 +751,7 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) group->clearState(LLSpatialGroup::GEOM_DIRTY); } + void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group) { @@ -663,8 +790,11 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO drawablep = *i; minMax = drawablep->getSpatialExtents(); + update_min_max(newMin, newMax, minMax[0]); + update_min_max(newMin, newMax, minMax[1]); + //bin up the object - for (U32 i = 0; i < 3; i++) + /*for (U32 i = 0; i < 3; i++) { if (minMax[0].mV[i] < newMin.mV[i]) { @@ -674,7 +804,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO { newMax.mV[i] = minMax[1].mV[i]; } - } + }*/ } mObjectBounds[0] = (newMin + newMax) * 0.5f; @@ -738,6 +868,10 @@ LLSpatialGroup* LLSpatialGroup::getParent() return NULL; } + if(!mOctreeNode) + { + return NULL; + } OctreeNode* parent = mOctreeNode->getOctParent(); if (parent) @@ -763,6 +897,8 @@ BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) { drawablep->setSpatialGroup(NULL); setState(GEOM_DIRTY); + gPipeline.markRebuild(this, TRUE); + if (drawablep->isSpatialBridge()) { for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i) @@ -799,6 +935,7 @@ void LLSpatialGroup::shift(const LLVector3 &offset) //if (!mSpatialPartition->mRenderByGroup) { setState(GEOM_DIRTY); + gPipeline.markRebuild(this, TRUE); } if (mOcclusionVerts) @@ -948,7 +1085,11 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mLastUpdateDistance(-1.f), mLastUpdateTime(gFrameTimeSeconds), mViewAngle(0.f), - mLastUpdateViewAngle(-1.f) + mLastUpdateViewAngle(-1.f), + mAtlasList(4), + mCurUpdatingTime(0), + mCurUpdatingSlotp(NULL), + mCurUpdatingTexture (NULL) { sNodeCount++; LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -956,6 +1097,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : sg_assert(mOctreeNode->getListenerCount() == 0); mOctreeNode->addListener(this); setState(SG_INITIAL_STATE_MASK); + gPipeline.markRebuild(this, TRUE); mBounds[0] = LLVector3(node->getCenter()); mBounds[1] = LLVector3(node->getSize()); @@ -975,7 +1117,7 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) #if !LL_RELEASE_FOR_DOWNLOAD if (isState(LLSpatialGroup::OBJECT_DIRTY)) { - llerrs << "Spatial group dirty on distance update." << llendl; + llwarns << "Spatial group dirty on distance update." << llendl; } #endif if (!getData().empty() && !LLSpatialPartition::sFreezeState) @@ -1014,6 +1156,7 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order, //not setting this node to dirty would be a very good thing group->setState(LLSpatialGroup::ALPHA_DIRTY); + gPipeline.markRebuild(group, FALSE); } } } @@ -1050,6 +1193,18 @@ F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera) return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera); } +F32 LLSpatialGroup::getUpdateUrgency() const +{ + if (!isVisible()) + { + return 0.f; + } + else + { + return (gFrameTimeSeconds - mLastUpdateTime+4.f)/mDistance; + } +} + BOOL LLSpatialGroup::needsUpdate() { return (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE; @@ -1157,6 +1312,8 @@ void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNo void LLSpatialGroup::destroyGL() { setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); + gPipeline.markRebuild(this, TRUE); + mLastUpdateTime = gFrameTimeSeconds; mVertexBuffer = NULL; mBufferMap.clear(); @@ -1339,7 +1496,8 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) //============================================== -LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage) +LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage) +: mRenderByGroup(render_by_group) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); mOcclusionEnabled = TRUE; @@ -1351,7 +1509,7 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage) mBufferUsage = buffer_usage; mDepthMask = FALSE; mSlopRatio = 0.25f; - mRenderByGroup = TRUE; + //mRenderByGroup = TRUE; mInfiniteFarClip = FALSE; LLGLNamePool::registerPool(&sQueryPool); @@ -1647,13 +1805,76 @@ public: return false; } + virtual void traverse(const LLSpatialGroup::TreeNode* n) + { + LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); + + if (earlyFail(group)) + { + return; + } + + if (mRes == 2) + { + //fully in, don't traverse further (won't effect extents + } + else if (mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) + { //don't need to do frustum check + LLSpatialGroup::OctreeTraveler::traverse(n); + } + else + { + mRes = frustumCheck(group); + + if (mRes) + { //at least partially in, run on down + LLSpatialGroup::OctreeTraveler::traverse(n); + } + + mRes = 0; + } + } + virtual void processGroup(LLSpatialGroup* group) { - if (group->mObjectBounds[1].magVecSquared() < 256.f * 256.f) - { //megaprims and water edge patches be damned! + if (group->isState(LLSpatialGroup::DIRTY) || group->getData().empty()) + { + llwarns << "WTF?" << llendl; + } + + if (mRes < 2) + { + + if (mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]) == 2) + { + mEmpty = FALSE; + update_min_max(mMin, mMax, group->mObjectExtents[0]); + update_min_max(mMin, mMax, group->mObjectExtents[1]); + } + else + { + if (group->mObjectBounds[1].magVecSquared() < 256.f * 256.f) + { //megaprims and water edge patches be damned! + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + { + LLDrawable* drawable = i->get(); + const LLVector3* ext = drawable->getSpatialExtents(); + + if (mCamera->AABBInFrustum((ext[1]+ext[0])*0.5f, (ext[1]-ext[0])*0.5f)) + { + mEmpty = FALSE; + update_min_max(mMin, mMax, ext[0]); + update_min_max(mMin, mMax, ext[1]); + } + } + } + } + } + else + { mEmpty = FALSE; - update_min_max(mMin, mMax, group->mObjectExtents[0]); - update_min_max(mMin, mMax, group->mObjectExtents[1]); + update_min_max(mMin, mMax, group->mExtents[0]); + update_min_max(mMin, mMax, group->mExtents[1]); } } @@ -2431,6 +2652,39 @@ void renderBatchSize(LLDrawInfo* params) pushVerts(params, LLVertexBuffer::MAP_VERTEX); } +void renderShadowFrusta(LLDrawInfo* params) +{ + LLGLEnable blend(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_ADD); + + LLVector3 center = (params->mExtents[1]+params->mExtents[0])*0.5f; + LLVector3 size = (params->mExtents[1]-params->mExtents[0])*0.5f; + + if (gPipeline.mShadowCamera[4].AABBInFrustum(center, size)) + { + glColor3f(1,0,0); + pushVerts(params, LLVertexBuffer::MAP_VERTEX); + } + if (gPipeline.mShadowCamera[5].AABBInFrustum(center, size)) + { + glColor3f(0,1,0); + pushVerts(params, LLVertexBuffer::MAP_VERTEX); + } + if (gPipeline.mShadowCamera[6].AABBInFrustum(center, size)) + { + glColor3f(0,0,1); + pushVerts(params, LLVertexBuffer::MAP_VERTEX); + } + if (gPipeline.mShadowCamera[7].AABBInFrustum(center, size)) + { + glColor3f(1,0,1); + pushVerts(params, LLVertexBuffer::MAP_VERTEX); + } + + gGL.setSceneBlendType(LLRender::BT_ALPHA); +} + + void renderLights(LLDrawable* drawablep) { if (!drawablep->isLight()) @@ -2566,6 +2820,9 @@ public: //draw tight fit bounding boxes for spatial group if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE)) { + group->rebuildGeom(); + group->rebuildMesh(); + renderOctree(group); stop_glerror(); } @@ -2573,6 +2830,9 @@ public: //render visibility wireframe if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) { + group->rebuildGeom(); + group->rebuildMesh(); + gGL.flush(); glPushMatrix(); gGLLastMatrix = NULL; @@ -2598,6 +2858,19 @@ public: LLVector3 nodeCenter = group->mBounds[0]; LLVector3 octCenter = LLVector3(group->mOctreeNode->getCenter()); + group->rebuildGeom(); + group->rebuildMesh(); + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) + { + if (!group->getData().empty()) + { + gGL.color3f(0,0,1); + drawBoxOutline(group->mObjectBounds[0], + group->mObjectBounds[1]); + } + } + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) { LLDrawable* drawable = *i; @@ -2607,6 +2880,16 @@ public: renderBoundingBox(drawable); } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BUILD_QUEUE)) + { + if (drawable->isState(LLDrawable::IN_REBUILD_Q2)) + { + gGL.color4f(0.6f, 0.6f, 0.1f, 1.f); + const LLVector3* ext = drawable->getSpatialExtents(); + drawBoxOutline((ext[0]+ext[1])*0.5f, (ext[1]-ext[0])*0.5f); + } + } + if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) { renderTexturePriority(drawable); @@ -2627,9 +2910,9 @@ public: renderRaycast(drawable); } - LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get()); + // LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get()); - if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_VOLUME)) + /* if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_VOLUME)) { renderAvatarCollisionVolumes(avatar); } @@ -2637,7 +2920,7 @@ public: if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AGENT_TARGET)) { renderAgentTarget(avatar); - } + } */ } @@ -2655,6 +2938,10 @@ public: { renderBatchSize(draw_info); } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + renderShadowFrusta(draw_info); + } } } } @@ -2705,7 +2992,7 @@ void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera) pusher.traverse(mOctree); } -void LLSpatialPartition::renderDebug() +void LLSpatialPartition::renderDebug() // KL SD version { if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | LLPipeline::RENDER_DEBUG_OCCLUSION | @@ -2716,8 +3003,8 @@ void LLSpatialPartition::renderDebug() LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY | LLPipeline::RENDER_DEBUG_TEXTURE_ANIM | LLPipeline::RENDER_DEBUG_RAYCAST | - LLPipeline::RENDER_DEBUG_AVATAR_VOLUME | - LLPipeline::RENDER_DEBUG_AGENT_TARGET)) + LLPipeline::RENDER_DEBUG_BUILD_QUEUE | + LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) { return; } @@ -2752,6 +3039,12 @@ void LLSpatialPartition::renderDebug() render_debug.traverse(mOctree); } +void LLSpatialGroup::drawObjectBox(LLColor4 col) +{ + gGL.color4fv(col.mV); + drawBox(mObjectBounds[0], mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); +} + BOOL LLSpatialPartition::isVisible(const LLVector3& v) { @@ -2896,11 +3189,12 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector3& start, con } LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, - LLViewerImage* texture, LLVertexBuffer* buffer, + LLImageGL* gl_texture, LLViewerImage* texture, LLVertexBuffer* buffer, BOOL fullbright, U8 bump, BOOL particle, F32 part_size) : mVertexBuffer(buffer), - mTexture(texture), + mTexture(gl_texture), + mViewerTexture(texture), mTextureMatrix(NULL), mModelMatrix(NULL), mStart(start), @@ -2920,22 +3214,22 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, if (mStart >= mVertexBuffer->getRequestedVerts() || mEnd >= mVertexBuffer->getRequestedVerts()) { - llerrs << "Invalid draw info vertex range." << llendl; + llwarns << "Invalid draw info vertex range." << llendl; } if (mOffset >= (U32) mVertexBuffer->getRequestedIndices() || mOffset + mCount > (U32) mVertexBuffer->getRequestedIndices()) { - llerrs << "Invalid draw info index range." << llendl; + llwarns << "Invalid draw info index range." << llendl; } } LLDrawInfo::~LLDrawInfo() { - if (LLSpatialGroup::sNoDelete) + /*if (LLSpatialGroup::sNoDelete) { - llerrs << "LLDrawInfo deleted illegally!" << llendl; - } + llwarns << "LLDrawInfo deleted illegally!" << llendl; + }*/ if (mFace) { @@ -3140,7 +3434,7 @@ void LLCullResult::assertDrawMapsEmpty() { if (mRenderMapSize[i] != 0) { - llerrs << "Stale LLDrawInfo's in LLCullResult!" << llendl; + llwarns << "Stale LLDrawInfo's in LLCullResult!" << llendl; } } } diff --git a/linden/indra/newview/llspatialpartition.h b/linden/indra/newview/llspatialpartition.h index df96152..8af5222 100644 --- a/linden/indra/newview/llspatialpartition.h +++ b/linden/indra/newview/llspatialpartition.h @@ -52,6 +52,8 @@ class LLSpatialPartition; class LLSpatialBridge; class LLSpatialGroup; +class LLTextureAtlas; +class LLTextureAtlasSlot; S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad); S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &radius_squared); @@ -66,12 +68,13 @@ protected: public: LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, - LLViewerImage* image, LLVertexBuffer* buffer, + LLImageGL* gl_image, LLViewerImage* image, LLVertexBuffer* buffer, BOOL fullbright = FALSE, U8 bump = 0, BOOL particle = FALSE, F32 part_size = 0); LLPointer<LLVertexBuffer> mVertexBuffer; - LLPointer<LLViewerImage> mTexture; + LLPointer<LLImageGL> mTexture; + LLPointer<LLViewerImage> mViewerTexture; LLColor4U mGlowColor; S32 mDebugColor; const LLMatrix4* mTextureMatrix; @@ -159,11 +162,13 @@ public: typedef std::vector<LLPointer<LLSpatialGroup> > sg_vector_t; typedef std::set<LLPointer<LLSpatialGroup> > sg_set_t; + typedef std::list<LLPointer<LLSpatialGroup> > sg_list_t; typedef std::vector<LLPointer<LLSpatialBridge> > bridge_list_t; typedef std::vector<LLPointer<LLDrawInfo> > drawmap_elem_t; typedef std::map<U32, drawmap_elem_t > draw_map_t; typedef std::vector<LLPointer<LLVertexBuffer> > buffer_list_t; - typedef std::map<LLPointer<LLViewerImage>, buffer_list_t> buffer_texture_map_t; + typedef std::map<LLPointer<LLImageGL>, buffer_list_t> buffer_texture_map_t; // KL render-pipeline +// typedef std::map<LLPointer<LLViewerImage>, buffer_list_t> buffer_texture_map_t; // KL standard typedef std::map<U32, buffer_texture_map_t> buffer_map_t; typedef LLOctreeListener<LLDrawable> BaseType; @@ -183,6 +188,14 @@ public: } }; + struct CompareUpdateUrgency + { + bool operator()(const LLPointer<LLSpatialGroup> lhs, const LLPointer<LLSpatialGroup> rhs) + { + return lhs->getUpdateUrgency() > rhs->getUpdateUrgency(); + } + }; + struct CompareDepthGreater { bool operator()(const LLSpatialGroup* const& lhs, const LLSpatialGroup* const& rhs) @@ -209,6 +222,10 @@ public: IMAGE_DIRTY = 0x00004000, OCCLUSION_DIRTY = 0x00008000, MESH_DIRTY = 0x00010000, + NEW_DRAWINFO = 0x00020000, + IN_BUILD_Q1 = 0x00040000, + IN_BUILD_Q2 = 0x00080000, + } eSpatialState; typedef enum @@ -252,6 +269,7 @@ public: void updateDistance(LLCamera& camera); BOOL needsUpdate(); + F32 getUpdateUrgency() const; BOOL changeLOD(); void rebuildGeom(); void rebuildMesh(); @@ -261,6 +279,8 @@ public: element_list& getData() { return mOctreeNode->getData(); } U32 getElementCount() const { return mOctreeNode->getElementCount(); } + void drawObjectBox(LLColor4 col); + //LISTENER FUNCTIONS virtual void handleInsertion(const TreeNode* node, LLDrawable* face); virtual void handleRemoval(const TreeNode* node, LLDrawable* face); @@ -269,6 +289,36 @@ public: virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child); virtual void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child); +//------------------- +//for atlas use +//------------------- + //atlas + void setCurUpdatingTime(U32 t) {mCurUpdatingTime = t ;} + U32 getCurUpdatingTime() const { return mCurUpdatingTime ;} + + void setCurUpdatingSlot(LLTextureAtlasSlot* slotp) ; + LLTextureAtlasSlot* getCurUpdatingSlot(LLViewerImage* imagep, S8 recursive_level = 3) ; + + void setCurUpdatingTexture(LLViewerImage* tex){ mCurUpdatingTexture = tex ;} + LLViewerImage* getCurUpdatingTexture() const { return mCurUpdatingTexture ;} + + BOOL hasAtlas(LLTextureAtlas* atlasp) ; + LLTextureAtlas* getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level = 3) ; + void addAtlas(LLTextureAtlas* atlasp, S8 recursive_level = 3) ; + void removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group = TRUE, S8 recursive_level = 3) ; + void clearAtlasList() ; +private: + U32 mCurUpdatingTime ; + //do not make the below two to use LLPointer + //because mCurUpdatingTime invalidates them automatically. + LLTextureAtlasSlot* mCurUpdatingSlotp ; + LLViewerImage* mCurUpdatingTexture ; + + std::vector< std::list<LLTextureAtlas*> > mAtlasList ; +//------------------- +//end for atlas use +//------------------- + protected: virtual ~LLSpatialGroup(); @@ -327,7 +377,7 @@ class LLSpatialPartition: public LLGeometryManager public: static BOOL sFreezeState; //if true, no spatialgroup state updates will be made - LLSpatialPartition(U32 data_mask, U32 mBufferUsage = GL_STATIC_DRAW_ARB); + LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage); virtual ~LLSpatialPartition(); LLSpatialGroup *put(LLDrawable *drawablep, BOOL was_visible = FALSE); @@ -373,7 +423,7 @@ public: BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed BOOL mInfiniteFarClip; // if TRUE, frustum culling ignores far clip plane U32 mBufferUsage; - BOOL mRenderByGroup; + const BOOL mRenderByGroup; U32 mLODSeed; U32 mLODPeriod; //number of frames between LOD updates for a given spatial group (staggered by mLODSeed) U32 mVertexDataMask; @@ -392,7 +442,7 @@ protected: public: typedef std::vector<LLPointer<LLSpatialBridge> > bridge_vector_t; - LLSpatialBridge(LLDrawable* root, U32 data_mask); + LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask); virtual BOOL isSpatialBridge() const { return TRUE; } diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index 87d48c8..237a967 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp @@ -3723,7 +3723,7 @@ void init_start_screen(S32 location_id) } raw->expandToPowerOfTwo(); - gStartImageGL->createGLTexture(0, raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); + gStartImageGL->createGLTexture(0, raw); } diff --git a/linden/indra/newview/llsurface.cpp b/linden/indra/newview/llsurface.cpp index a27f0e2..2e20ace 100644 --- a/linden/indra/newview/llsurface.cpp +++ b/linden/indra/newview/llsurface.cpp @@ -149,7 +149,7 @@ LLSurface::~LLSurface() } else { - llerrs << "Terrain pool not empty!" << llendl; + llwarns << "Terrain pool not empty!" << llendl; } } @@ -238,6 +238,7 @@ void LLSurface::createSTexture() if (!mSTexturep) { // Fill with dummy gray data. + // GL NOT ACTIVE HERE LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize, sTextureSize, 3); U8 *default_texture = raw->getData(); for (S32 i = 0; i < sTextureSize; i++) @@ -255,6 +256,7 @@ void LLSurface::createSTexture() gGL.getTexUnit(0)->bind(mSTexturep.get()); mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); gImageList.addImage(mSTexturep); + } } @@ -275,9 +277,10 @@ void LLSurface::createWaterTexture() *(default_texture + (i*sTextureSize/2 + j)*4 + 3) = MAX_WATER_COLOR.mV[3]; } } - mWaterTexturep = new LLViewerImage(raw, FALSE); + + mWaterTexturep = new LLViewerImage(sTextureSize/2, sTextureSize/2, 4, FALSE); mWaterTexturep->dontDiscard(); - gGL.getTexUnit(0)->bind(mWaterTexturep.get()); + gGL.getTexUnit(0)->bind(mWaterTexturep); mWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); gImageList.addImage(mWaterTexturep); } @@ -629,6 +632,8 @@ void LLSurface::updatePatchVisibilities(LLAgent &agent) BOOL LLSurface::idleUpdate(F32 max_update_time) { +//SG2: LLMemType mt_ius(LLMemType::MTYPE_IDLE_UPDATE_SURFACE); + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TERRAIN)) { return FALSE; @@ -1133,12 +1138,12 @@ LLSurfacePatch *LLSurface::getPatch(const S32 x, const S32 y) const { if ((x < 0) || (x >= mPatchesPerEdge)) { - llerrs << "Asking for patch out of bounds" << llendl; + llwarns << "Asking for patch out of bounds" << llendl; return NULL; } if ((y < 0) || (y >= mPatchesPerEdge)) { - llerrs << "Asking for patch out of bounds" << llendl; + llwarns << "Asking for patch out of bounds" << llendl; return NULL; } @@ -1277,6 +1282,11 @@ BOOL LLSurface::generateWaterTexture(const F32 x, const F32 y, } } + if (!mWaterTexturep->getHasGLTexture()) + { + mWaterTexturep->createGLTexture(0, raw); + } + mWaterTexturep->setSubImage(raw, x_begin, y_begin, x_end - x_begin, y_end - y_begin); return TRUE; } diff --git a/linden/indra/newview/llsurfacepatch.cpp b/linden/indra/newview/llsurfacepatch.cpp index 5fac5fd..04b732a 100644 --- a/linden/indra/newview/llsurfacepatch.cpp +++ b/linden/indra/newview/llsurfacepatch.cpp @@ -712,17 +712,7 @@ BOOL LLSurfacePatch::updateTexture() if (mVObjp) { mVObjp->dirtyGeom(); - } - updateCompositionStats(); - F32 tex_patch_size = meters_per_grid*grids_per_patch_edge; - if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY], - tex_patch_size, tex_patch_size)) - { - mSTexUpdate = FALSE; - - // Also generate the water texture - mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY], - tex_patch_size, tex_patch_size); + gPipeline.markGLRebuild(mVObjp); return TRUE; } } @@ -735,6 +725,28 @@ BOOL LLSurfacePatch::updateTexture() } } +void LLSurfacePatch::updateGL() // KL SD +{ + F32 meters_per_grid = getSurface()->getMetersPerGrid(); + F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge(); + + LLViewerRegion *regionp = getSurface()->getRegion(); + LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal(); + + LLVLComposition* comp = regionp->getComposition(); + + updateCompositionStats(); + F32 tex_patch_size = meters_per_grid*grids_per_patch_edge; + if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY], + tex_patch_size, tex_patch_size)) + { + mSTexUpdate = FALSE; + + // Also generate the water texture + mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY], + tex_patch_size, tex_patch_size); + } +} // KL void LLSurfacePatch::dirtyZ() { diff --git a/linden/indra/newview/llsurfacepatch.h b/linden/indra/newview/llsurfacepatch.h index 7e84f7f..1f9658d 100644 --- a/linden/indra/newview/llsurfacepatch.h +++ b/linden/indra/newview/llsurfacepatch.h @@ -90,6 +90,7 @@ public: void updateCameraDistanceRegion( const LLVector3 &pos_region); void updateVisibility(); + void updateGL(); void dirtyZ(); // Dirty the z values of this patch void setHasReceivedData(); diff --git a/linden/indra/newview/lltexlayer.cpp b/linden/indra/newview/lltexlayer.cpp index 5175cbb..fb5be84 100644 --- a/linden/indra/newview/lltexlayer.cpp +++ b/linden/indra/newview/lltexlayer.cpp @@ -813,14 +813,19 @@ void LLTexLayerSet::requestUpdate() if( mUpdatesEnabled ) { createComposite(); - mComposite->requestUpdate(); + if (mComposite) + { + mComposite->requestUpdate(); + } } } void LLTexLayerSet::requestUpload() { - createComposite(); - mComposite->requestUpload(); + if (mComposite) + { + mComposite->requestUpload(); + } } void LLTexLayerSet::cancelUpload() @@ -835,6 +840,15 @@ void LLTexLayerSet::createComposite() { if( !mComposite ) { + gPipeline.markGLRebuild(this); + } + //updateGL(); // KL +} + +void LLTexLayerSet::updateGL() +{ + if (!mComposite) + { S32 width = mInfo->mWidth; S32 height = mInfo->mHeight; // Composite other avatars at reduced resolution @@ -865,7 +879,7 @@ void LLTexLayerSet::setUpdatesEnabled( BOOL b ) void LLTexLayerSet::updateComposite() { createComposite(); - mComposite->updateImmediate(); + //mComposite->updateImmediate(); //KL exception here this needs fixing for S19 } LLTexLayerSetBuffer* LLTexLayerSet::getComposite() @@ -2104,7 +2118,7 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) // Create the GL texture, and then hang onto it for future use. if( mNeedsCreateTexture ) { - mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw, 0, TRUE, LLViewerImageBoostLevel::TEXLAYER_CACHE); + mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw, 0); mNeedsCreateTexture = FALSE; gGL.getTexUnit(0)->bind(mCachedProcessedImageGL); mCachedProcessedImageGL->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -2560,7 +2574,7 @@ LLImageGL* LLTexStaticImageList::getImageGL(const std::string& file_name, BOOL i image_gl->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); } - image_gl->createGLTexture(0, image_raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); + image_gl->createGLTexture(0, image_raw, 0); gGL.getTexUnit(0)->bind(image_gl); image_gl->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/linden/indra/newview/lltexlayer.h b/linden/indra/newview/lltexlayer.h index 020ba86..b841fa3 100644 --- a/linden/indra/newview/lltexlayer.h +++ b/linden/indra/newview/lltexlayer.h @@ -249,7 +249,7 @@ private: // LLTexLayerSet // An ordered set of texture layers that get composited into a single texture. //----------------------------------------------------------------------------- -class LLTexLayerSet +class LLTexLayerSet : public LLGLUpdate { friend class LLTexLayerSetBuffer; public: @@ -284,7 +284,7 @@ public: LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; } void setBakedTexIndex(LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } BOOL isVisible() const { return mIsVisible; } - + /*virtual*/ void updateGL(); public: static BOOL sHasCaches; diff --git a/linden/indra/newview/lltextureatlasmanager.cpp b/linden/indra/newview/lltextureatlasmanager.cpp new file mode 100644 index 0000000..df6a39d --- /dev/null +++ b/linden/indra/newview/lltextureatlasmanager.cpp @@ -0,0 +1,274 @@ +/** + * @file lltextureatlasmanager.cpp + * @brief LLTextureAtlasManager class implementation. + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "llviewerprecompiledheaders.h" +#include "linden_common.h" +#include "llerror.h" +#include "llmath.h" +#include "lltextureatlas.h" +#include "lltextureatlasmanager.h" +#include "llspatialpartition.h" + +const S8 MAX_NUM_EMPTY_ATLAS = 2 ; +const F32 MIN_ATLAS_FULLNESS = 0.6f ; + +//********************************************************************************************* +//implementation of class LLTextureAtlasInfo +//********************************************************************************************* +LLTextureAtlasSlot::LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) : + mAtlasp(atlasp), + mGroupp(groupp), + mCol(col), + mRow(row), + mReservedSlotWidth(slot_width), + mValid(FALSE), + mUpdatedTime(0), + mTexCoordOffset(xoffset, yoffset), + mTexCoordScale(1.f, 1.f) +{ + llassert_always(mAtlasp || mGroupp || mReservedSlotWidth) ; +} + +LLTextureAtlasSlot::~LLTextureAtlasSlot() +{ + if(mAtlasp) + { + mAtlasp->releaseSlot(mCol, mRow, mReservedSlotWidth) ; + if(mAtlasp->isEmpty()) + { + LLTextureAtlasManager::getInstance()->releaseAtlas(mAtlasp) ; + } + mAtlasp = NULL ; + } +} + +//void LLTextureAtlasSlot::setAtlas(LLTextureAtlas* atlasp) +//{ +// mAtlasp = atlasp ; +//} +//void LLTextureAtlasSlot::setSlotPos(S16 col, S16 row) +//{ +// mCol = col ; +// mRow = row ; +//} +//void LLTextureAtlasSlot::setSlotWidth(S8 width) +//{ +// //slot is a square with each edge length a power-of-two number +// mReservedSlotWidth = width ; +//} +//void LLTextureAtlasSlot::setTexCoordOffset(F32 xoffset, F32 yoffset) +//{ +// mTexCoordOffset.mV[0] = xoffset ; +// mTexCoordOffset.mV[1] = yoffset ; +//} + +void LLTextureAtlasSlot::setSpatialGroup(LLSpatialGroup* groupp) +{ + mGroupp = groupp ; +} +void LLTextureAtlasSlot::setTexCoordScale(F32 xscale, F32 yscale) +{ + mTexCoordScale.mV[0] = xscale ; + mTexCoordScale.mV[1] = yscale ; +} +//********************************************************************************************* +//END of implementation of class LLTextureAtlasInfo +//********************************************************************************************* + +//********************************************************************************************* +//implementation of class LLTextureAtlasManager +//********************************************************************************************* +LLTextureAtlasManager::LLTextureAtlasManager() : + mAtlasMap(4), + mEmptyAtlasMap(4) +{ +} + +LLTextureAtlasManager::~LLTextureAtlasManager() +{ + for(S32 i = 0 ; i < 4 ; i++) + { + for(ll_texture_atlas_list_t::iterator j = mAtlasMap[i].begin() ; j != mAtlasMap[i].end() ; ++j) + { + *j = NULL ; + } + for(ll_texture_atlas_list_t::iterator j = mEmptyAtlasMap[i].begin() ; j != mEmptyAtlasMap[i].end() ; ++j) + { + *j = NULL ; + } + + mAtlasMap[i].clear() ; + mEmptyAtlasMap[i].clear() ; + } + mAtlasMap.clear() ; + mEmptyAtlasMap.clear() ; +} + +//return TRUE if qualified +BOOL LLTextureAtlasManager::canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target) +{ + if(ncomponents < 1 || ncomponents > 4) + { + return FALSE ; + } + //only support GL_TEXTURE_2D + if(GL_TEXTURE_2D != target) + { + return FALSE ; + } + //real image size overflows + if(w < 8 || w > LLTextureAtlas::sMaxSubTextureSize || h < 8 || h > LLTextureAtlas::sMaxSubTextureSize) + { + return FALSE ; + } + + //if non-power-of-two number + if((w & (w - 1)) || (h & (h - 1))) + { + return FALSE ; + } + + return TRUE ; +} + +void LLTextureAtlasManager::releaseAtlas(LLTextureAtlas* atlasp) +{ + LLSpatialGroup* groupp = atlasp->getLastSpatialGroup() ; + while(groupp) + { + groupp->removeAtlas(atlasp, FALSE) ; + atlasp->removeLastSpatialGroup() ; + + groupp = atlasp->getLastSpatialGroup() ; + } + + S8 type = atlasp->getComponents() - 1 ; + //insert to the empty list + if(mEmptyAtlasMap[type].size() < MAX_NUM_EMPTY_ATLAS) + { + mEmptyAtlasMap[type].push_back(atlasp) ; + } + + //delete the atlasp + mAtlasMap[type].remove(atlasp) ; +} + +// +//this function reserves an appropriate slot from atlas pool for an image. +//return non-NULL if succeeds. +//Note: +//1, this function does not check if the image this slot assigned for qualifies for atlas or not, +// call LLTextureAtlasManager::canAddToAtlas(...) to do the check before calling this function. +//2, this function also dose not check if the image is already in atlas. It always assigns a new slot anyway. +//3, this function tries to group sub-textures from same spatial group into ONE atlas to improve render batching. +// +LLPointer<LLTextureAtlasSlot> LLTextureAtlasManager::reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents, + LLSpatialGroup* groupp, LLViewerImage* imagep) +{ + if(!groupp) + { + //do not insert to atlas if does not have a group. + return NULL ; + } + + //bits_len must <= 8 and is a power of two number, i.e.: must be one of these numbers: 1, 2, 4, 8. + if(sub_texture_size > LLTextureAtlas::sMaxSubTextureSize) + { + sub_texture_size = LLTextureAtlas::sMaxSubTextureSize ; + } + S8 bits_len = sub_texture_size / LLTextureAtlas::sSlotSize ; + if(bits_len < 1) + { + bits_len = 1 ; + } + + S16 col = -1, row = -1; + S8 total_bits = bits_len * bits_len ; + + //insert to the atlas reserved by the same spatial group + LLPointer<LLTextureAtlas> atlasp = groupp->getAtlas(ncomponents, total_bits) ; + if(atlasp.notNull()) + { + if(!atlasp->getNextAvailableSlot(bits_len, col, row)) + { + //failed + atlasp = NULL ; + } + } + + //search an atlas to fit for 'size' + if(!atlasp) + { + S8 atlas_index = ncomponents - 1 ; + ll_texture_atlas_list_t::iterator iter = mAtlasMap[atlas_index].begin() ; + for(; iter != mAtlasMap[atlas_index].end(); ++iter) + { + LLTextureAtlas* cur = (LLTextureAtlas*)*iter ; + if(cur->getFullness() < MIN_ATLAS_FULLNESS)//this atlas is empty enough for this group to insert more sub-textures later if necessary. + { + if(cur->getNextAvailableSlot(bits_len, col, row)) + { + atlasp = cur ; + groupp->addAtlas(atlasp) ; + break ; + } + } + } + } + + //create a new atlas if necessary + if(!atlasp) + { + if(mEmptyAtlasMap[ncomponents - 1].size() > 0) + { + //there is an empty one + atlasp = mEmptyAtlasMap[ncomponents - 1].back() ; + mEmptyAtlasMap[ncomponents - 1].pop_back() ; + } + else + { + atlasp = new LLTextureAtlas(ncomponents, 16) ; + } + mAtlasMap[ncomponents - 1].push_back(atlasp) ; + atlasp->getNextAvailableSlot(bits_len, col, row) ; + groupp->addAtlas(atlasp) ; + } + + F32 xoffset, yoffset ; + atlasp->getTexCoordOffset(col, row, xoffset, yoffset) ; + LLPointer<LLTextureAtlasSlot> slot_infop = new LLTextureAtlasSlot(atlasp, groupp, col, row, xoffset, yoffset, bits_len) ; + + return slot_infop ; +} + +//********************************************************************************************* +//END of implementation of class LLTextureAtlasManager +//********************************************************************************************* diff --git a/linden/indra/newview/lltextureatlasmanager.h b/linden/indra/newview/lltextureatlasmanager.h new file mode 100644 index 0000000..70689bf --- /dev/null +++ b/linden/indra/newview/lltextureatlasmanager.h @@ -0,0 +1,112 @@ +/** + * @file lltextureatlasmanager.h + * @brief LLTextureAtlasManager base class. + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#ifndef LL_TEXTUREATLASMANAGER_H +#define LL_TEXTUREATLASMANAGER_H + +#include "llmemory.h" + +class LLSpatialGroup ; +class LLViewerImage ; + +//just use it as a structure. +class LLTextureAtlasSlot : public LLRefCount +{ +public: + LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) ; + +protected: + virtual ~LLTextureAtlasSlot(); + +public: + + // + //do not allow to change those values + // + //void setAtlas(LLTextureAtlas* atlasp) ; + //void setSlotPos(S16 col, S16 row) ; + //void setSlotWidth(S8 width) ; + //void setTexCoordOffset(F32 xoffser, F32 yoffset) ; + // + + void setSpatialGroup(LLSpatialGroup* groupp) ; + void setTexCoordScale(F32 xscale, F32 yscale) ; + void setValid() {mValid = TRUE ;} + + LLTextureAtlas* getAtlas()const {return mAtlasp;} + LLSpatialGroup* getSpatialGroup() const {return mGroupp ;} + S16 getSlotCol()const {return mCol;} + S16 getSlotRow()const {return mRow;} + S8 getSlotWidth()const{return mReservedSlotWidth;} + BOOL isValid()const { return mValid;} + const LLVector2* getTexCoordOffset()const {return &mTexCoordOffset;} + const LLVector2* getTexCoordScale() const {return &mTexCoordScale;} + + void setUpdatedTime(U32 t) {mUpdatedTime = t;} + U32 getUpdatedTime()const {return mUpdatedTime;} + +private: + LLTextureAtlas* mAtlasp; + S16 mCol ;//col of the slot + S16 mRow ;//row of the slot + S8 mReservedSlotWidth ; //slot is a square with each edge length a power-of-two number + LLSpatialGroup* mGroupp ; + BOOL mValid ; + + LLVector2 mTexCoordOffset ; + LLVector2 mTexCoordScale ; + + U32 mUpdatedTime ; +} ; + +class LLTextureAtlasManager : public LLSingleton<LLTextureAtlasManager> +{ +private: + typedef std::list<LLPointer<LLTextureAtlas> > ll_texture_atlas_list_t ; + +public: + LLTextureAtlasManager(); + ~LLTextureAtlasManager(); + + LLPointer<LLTextureAtlasSlot> reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents, + LLSpatialGroup* groupp, LLViewerImage* imagep) ; + void releaseAtlas(LLTextureAtlas* atlasp); + + BOOL canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target) ; + +private: + std::vector<ll_texture_atlas_list_t> mAtlasMap ; + std::vector<ll_texture_atlas_list_t> mEmptyAtlasMap ; //delay some empty atlases deletion to avoid possible creation of new atlas immediately. +}; + +#endif diff --git a/linden/indra/newview/lltextureview.cpp b/linden/indra/newview/lltextureview.cpp index 04cebf5..903a6e5 100644 --- a/linden/indra/newview/lltextureview.cpp +++ b/linden/indra/newview/lltextureview.cpp @@ -57,14 +57,16 @@ extern F32 texmem_lower_bound_scale; LLTextureView *gTextureView = NULL; +LLTextureSizeView *gTextureSizeView = NULL; +LLTextureSizeView *gTextureCategoryView = NULL; //static std::set<LLViewerImage*> LLTextureView::sDebugImages; //////////////////////////////////////////////////////////////////////////// -static std::string title_string1a("Tex UUID Area DDis(Req) DecodePri(Fetch) [download] pk/max"); -static std::string title_string1b("Tex UUID Area DDis(Req) Fetch(DecodePri) [download] pk/max"); +static std::string title_string1a("Tex UUID Area DDis(Req) DecodePri(Fetch) [download]"); +static std::string title_string1b("Tex UUID Area DDis(Req) Fetch(DecodePri) [download]"); static std::string title_string2("State"); static std::string title_string3("Pkt Bnd"); static std::string title_string4(" W x H (Dis) Mem"); @@ -201,13 +203,14 @@ void LLTextureBar::draw() } else { - tex_str = llformat("%s %7.0f %d(%d) %8.0f(0x%08x)", + tex_str = llformat("%s %7.0f %d(%d) %8.0f(0x%08x) %1.2f", uuid_str.c_str(), mImagep->mMaxVirtualSize, mImagep->mDesiredDiscardLevel, mImagep->mRequestedDiscardLevel, mImagep->getDecodePriority(), - mImagep->mFetchPriority); + mImagep->mFetchPriority, + mImagep->mDownloadProgress); } LLFontGL::getFontMonospace()->renderUTF8(tex_str, 0, title_x1, getRect().getHeight(), @@ -253,7 +256,7 @@ void LLTextureBar::draw() // Draw the progress bar. S32 bar_width = 100; - S32 bar_left = 260; + S32 bar_left = 330; left = bar_left; right = left + bar_width; @@ -262,7 +265,7 @@ void LLTextureBar::draw() F32 data_progress = mImagep->mDownloadProgress; - if (data_progress > 0.0f) + if (data_progress > 0.0f && data_progress <= 1.0f) { // Downloaded bytes right = left + llfloor(data_progress * (F32)bar_width); @@ -272,6 +275,16 @@ void LLTextureBar::draw() gl_rect_2d(left, top, right, bottom); } } + else if (data_progress > 1.0f) + { + // Small cached textures generate this oddity. SNOW-168 + right = left + bar_width; + if (right > left) + { + gGL.color4f(0.f, 0.33f, 0.f, 0.75f); + gl_rect_2d(left, top, right, bottom); + } + } S32 pip_width = 6; S32 pip_space = 14; @@ -386,9 +399,9 @@ private: void LLGLTexMemBar::draw() { - S32 bound_mem = BYTES_TO_MEGA_BYTES(LLViewerImage::sBoundTextureMemoryInBytes); + S32 bound_mem = (LLViewerImage::sBoundTextureMemoryInBytes >> 20); S32 max_bound_mem = LLViewerImage::sMaxBoundTextureMemInMegaBytes; - S32 total_mem = BYTES_TO_MEGA_BYTES(LLViewerImage::sTotalTextureMemoryInBytes); + S32 total_mem = (LLViewerImage::sTotalTextureMemoryInBytes >> 20); S32 max_total_mem = LLViewerImage::sMaxTotalTextureMemInMegaBytes; F32 discard_bias = LLViewerImage::sDesiredDiscardBias; S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); @@ -478,28 +491,25 @@ void LLGLTexMemBar::draw() #endif //---------------------------------------------------------------------------- - text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d RAW:%d HTP:%d", + text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d RAW:%d HTP:%d BW: %.0f/%.0f", gImageList.getNumImages(), - LLAppViewer::getTextureFetch()->getNumRequests(), LLAppViewer::getTextureFetch()->getNumDeletes(), - LLAppViewer::getTextureFetch()->mPacketCount, LLAppViewer::getTextureFetch()->mBadPacketCount, - LLAppViewer::getTextureCache()->getNumReads(), LLAppViewer::getTextureCache()->getNumWrites(), + LLAppViewer::getTextureFetch()->getNumRequests(), + LLAppViewer::getTextureFetch()->getNumDeletes(), + LLAppViewer::getTextureFetch()->mPacketCount, + LLAppViewer::getTextureFetch()->mBadPacketCount, + LLAppViewer::getTextureCache()->getNumReads(), + LLAppViewer::getTextureCache()->getNumWrites(), LLLFSThread::sLocal->getPending(), LLAppViewer::getImageDecodeThread()->getPending(), LLImageRaw::sRawImageCount, - LLAppViewer::getTextureFetch()->getNumHTTPRequests()); + LLAppViewer::getTextureFetch()->getNumHTTPRequests(), + LLAppViewer::getTextureFetch()->getTextureBandwidth(), + gSavedSettings.getF32("ThrottleBandwidthKBPS")); LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, line_height*2, text_color, LLFontGL::LEFT, LLFontGL::TOP); - - left = 550; - F32 bandwidth = LLAppViewer::getTextureFetch()->getTextureBandwidth(); - F32 max_bandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); - color = bandwidth > max_bandwidth ? LLColor4::red : bandwidth > max_bandwidth*.75f ? LLColor4::yellow : text_color; - color[VALPHA] = text_color[VALPHA]; - text = llformat("BW:%.0f/%.0f",bandwidth, max_bandwidth); - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*2, - color, LLFontGL::LEFT, LLFontGL::TOP); + left = 600; S32 dx1 = 0; if (LLAppViewer::getTextureFetch()->mDebugPause) @@ -566,7 +576,7 @@ public: void setTop(S32 loaded, S32 bound, F32 scale) {mTopLoaded = loaded ; mTopBound = bound; mScale = scale ;} void draw(); - BOOL handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size) ; + BOOL handleHover(S32 x, S32 y, MASK mask) ; private: S32 mIndex ; @@ -579,16 +589,19 @@ private: F32 mScale ; }; -BOOL LLGLTexSizeBar::handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size) +BOOL LLGLTexSizeBar::handleHover(S32 x, S32 y, MASK mask) { +#if !LL_RELEASE_FOR_DOWNLOAD if(y > mBottom && (y < mBottom + (S32)(mTopLoaded * mScale) || y < mBottom + (S32)(mTopBound * mScale))) { - LLImageGL::setCurTexSizebar(mIndex, set_pick_size); + LLImageGL::setCurTexSizebar(mIndex); } +#endif return TRUE ; } void LLGLTexSizeBar::draw() { +#if !LL_RELEASE_FOR_DOWNLOAD LLGLSUIDefault gls_ui; if(LLImageGL::sCurTexSizeBar == mIndex) @@ -609,6 +622,7 @@ void LLGLTexSizeBar::draw() F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f}; gl_rect_2d(mLeft, mBottom + (S32)(mTopLoaded * mScale), (mLeft + mRight) / 2, mBottom, loaded_color) ; gl_rect_2d((mLeft + mRight) / 2, mBottom + (S32)(mTopBound * mScale), mRight, mBottom, bound_color) ; +#endif } //////////////////////////////////////////////////////////////////////////// @@ -913,31 +927,7 @@ LLTextureSizeView::~LLTextureSizeView() } void LLTextureSizeView::draw() { - if(mType == TEXTURE_MEM_OVER_SIZE) - { - drawTextureSizeGraph(); - } - else - { - drawTextureCategoryGraph() ; - } - - LLView::draw(); -} - -BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask) -{ - if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight) - { - mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask, (mType == TEXTURE_MEM_OVER_SIZE)) ; - } - - return TRUE ; -} - -//draw real-time texture mem bar over size -void LLTextureSizeView::drawTextureSizeGraph() -{ +#if !LL_RELEASE_FOR_DOWNLOAD if(mTextureSizeBar.size() == 0) { S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); @@ -958,16 +948,29 @@ void LLTextureSizeView::drawTextureSizeGraph() mTextureSizeBar[i]->draw() ; } LLImageGL::resetCurTexSizebar(); + + LLView::draw(); +#endif +} + +BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask) +{ + if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight) + { + mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask) ; + } + + return TRUE ; } //draw background of texture size bar graph F32 LLTextureSizeView::drawTextureSizeDistributionGraph() { - //scale F32 scale = 1.0f ; - +#if !LL_RELEASE_FOR_DOWNLOAD LLGLSUIDefault gls_ui; + //scale { S32 count = 0 ; for(U32 i = 0 ; i < LLImageGL::sTextureLoadedCounter.size() ; i++) @@ -1057,136 +1060,7 @@ F32 LLTextureSizeView::drawTextureSizeDistributionGraph() text = llformat("Texture Size Distribution") ; LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3, text_color, LLFontGL::LEFT, LLFontGL::TOP); - return scale ; -} - -//draw real-time texture mem bar over category -void LLTextureSizeView::drawTextureCategoryGraph() -{ - if(mTextureSizeBar.size() == 0) - { - S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); - mTextureSizeBar.resize(LLImageGL::sTextureMemByCategory.size()) ; - mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ; - - for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) - { - mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth , - line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ; - } - } - - F32 size_bar_scale = drawTextureCategoryDistributionGraph() ; - for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) - { - mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[i] >> 20, LLImageGL::sTextureMemByCategoryBound[i] >> 20, size_bar_scale) ; - mTextureSizeBar[i]->draw() ; - } - LLImageGL::resetCurTexSizebar(); -} - -//draw background for TEXTURE_MEM_OVER_CATEGORY -F32 LLTextureSizeView::drawTextureCategoryDistributionGraph() -{ - //scale - F32 scale = 4.0f ; - - LLGLSUIDefault gls_ui; - - { - S32 count = 0 ; - for(U32 i = 0 ; i < LLImageGL::sTextureMemByCategory.size() ; i++) - { - S32 tmp = LLImageGL::sTextureMemByCategory[i] >> 20 ; - if(tmp > count) - { - count = tmp ; - } - } - if(count > mTextureSizeBarRect.getHeight() * 0.25f) - { - scale = (F32)mTextureSizeBarRect.getHeight() * 0.25f / count ; - } - } - - S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); - S32 left = mTextureSizeBarRect.mLeft ; - S32 bottom = mTextureSizeBarRect.mBottom ; - S32 right = mTextureSizeBarRect.mRight ; - S32 top = mTextureSizeBarRect.mTop ; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - //background rect - gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ; - - //-------------------------------------------------- - gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f); - gl_line_2d(left, bottom, right, bottom) ; //x axis - gl_line_2d(left, bottom, left, top) ; //y axis - - //ruler - //-------------------------------------------------- - gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f); - for(S32 i = bottom + 50 ; i <= top ; i += 50) - { - gl_line_2d(left, i, right, i) ; - } - - //texts - //-------------------------------------------------- - F32 text_color[] = {1.f, 1.f, 1.f, 0.75f}; - std::string text; - - //------- - //x axis: size label - static char category[LLViewerImageBoostLevel::MAX_GL_IMAGE_CATEGORY][4] = - {"Non", "Bak", "Av", "Cld", "Scp", "Hi", "Trn", "Slt", "Hud", "Bsf", "UI", "Pvw", "Map", "Mvs", "Slf", "Tbp", "Scr", "Fnt", "Bmp", "Dyn", "Tlc", "Mdi", "ALT", "Oth" } ; - - text = llformat("%s", category[0]) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++) - { - text = llformat("%s", category[i]) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - } - //------- - - //y axis: number label - for(S32 i = bottom + 50 ; i <= top ; i += 50) - { - text = llformat("%d", (S32)((i - bottom) / scale)) ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 , - text_color, LLFontGL::LEFT, LLFontGL::TOP); - LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 , - text_color, LLFontGL::LEFT, LLFontGL::TOP); - } - - text = llformat("MB") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, top + line_height * 2 , - text_color, LLFontGL::LEFT, LLFontGL::TOP); - //-------------------------------------------------- - F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f}; - gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ; - text = llformat("Loaded") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2, - loaded_color, - LLFontGL::LEFT, LLFontGL::TOP); - - F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f}; - gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ; - text = llformat("Bound") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2, - bound_color, LLFontGL::LEFT, LLFontGL::TOP); - - //-------------------------------------------------- - - //title - text = llformat("Texture Category Distribution") ; - LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3, - text_color, LLFontGL::LEFT, LLFontGL::TOP); +#endif return scale ; } diff --git a/linden/indra/newview/lltoolpie.h b/linden/indra/newview/lltoolpie.h index 001886f..54bf409 100644 --- a/linden/indra/newview/lltoolpie.h +++ b/linden/indra/newview/lltoolpie.h @@ -86,7 +86,6 @@ private: LLPickInfo mPick; U8 mClickAction; LLSafeHandle<LLObjectSelection> mLeftClickSelection; -protected: LLPointer<LLViewerObject> mClickActionObject; }; diff --git a/linden/indra/newview/llviewercamera.cpp b/linden/indra/newview/llviewercamera.cpp index dade65f..6cef2af 100644 --- a/linden/indra/newview/llviewercamera.cpp +++ b/linden/indra/newview/llviewercamera.cpp @@ -769,8 +769,8 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts) BOOL in_frustum = pointInFrustum(LLVector3(vec)) > 0; - if (( !in_frustum && all_verts) || - (in_frustum && !all_verts)) + if ( !in_frustum && all_verts || + in_frustum && !all_verts) { return !all_verts; } diff --git a/linden/indra/newview/llviewercontrol.cpp b/linden/indra/newview/llviewercontrol.cpp index 1531e6c..4c9c098 100644 --- a/linden/indra/newview/llviewercontrol.cpp +++ b/linden/indra/newview/llviewercontrol.cpp @@ -90,7 +90,7 @@ std::string gCurrentVersion; extern BOOL gResizeScreenTexture; extern BOOL gDebugGL; -extern BOOL gAuditTexture; +//extern BOOL gAuditTexture; //////////////////////////////////////////////////////////////////////////// // Listeners @@ -418,12 +418,12 @@ static bool handleRenderUseImpostorsChanged(const LLSD& newvalue) LLVOAvatar::sUseImpostors = newvalue.asBoolean(); return true; } - +/* static bool handleAuditTextureChanged(const LLSD& newvalue) { gAuditTexture = newvalue.asBoolean(); return true; -} +}*/ static bool handleRenderDebugGLChanged(const LLSD& newvalue) { @@ -528,6 +528,11 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1)); gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); + + gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); + gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); + gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); + gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); gSavedSettings.getControl("EnableRippleWater")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); @@ -539,6 +544,9 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderAvatarInvisible")->getSignal()->connect(boost::bind(&handleSetSelfInvisible, _1)); gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _1)); gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _1)); + gSavedSettings.getControl("RenderDeferredShadow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); + gSavedSettings.getControl("RenderDeferredGI")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); + gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _1)); gSavedSettings.getControl("RenderTreeLODFactor")->getSignal()->connect(boost::bind(&handleTreeLODChanged, _1)); gSavedSettings.getControl("RenderFlexTimeFactor")->getSignal()->connect(boost::bind(&handleFlexLODChanged, _1)); @@ -584,7 +592,7 @@ void settings_setup_listeners() gSavedSettings.getControl("AudioLevelDoppler")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("AudioLevelRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("AudioStreamingMusic")->getSignal()->connect(boost::bind(&handleAudioStreamMusicChanged, _1)); - gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _1)); +// gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _1)); gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("MuteMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("MuteMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); diff --git a/linden/indra/newview/llviewerdisplay.cpp b/linden/indra/newview/llviewerdisplay.cpp index ad186d5..8e066c8 100644 --- a/linden/indra/newview/llviewerdisplay.cpp +++ b/linden/indra/newview/llviewerdisplay.cpp @@ -128,6 +128,11 @@ void display_startup() return; } + gPipeline.updateGL(); + + // Update images? + gImageList.updateImages(0.01f); + LLGLSDefault gls_default; // Required for HTML update in login screen @@ -599,6 +604,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gPipeline.updateGeom(max_geom_update_time); stop_glerror(); + gPipeline.updateGL(); + stop_glerror(); + gFrameStats.start(LLFrameStats::UPDATE_CULL); S32 water_clip = 0; if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) && @@ -688,6 +696,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gPipeline.generateSunShadow(*LLViewerCamera::getInstance()); } + LLVertexBuffer::unbind(); // KL + LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); @@ -718,6 +728,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery"); gPipeline.generateWaterReflection(*LLViewerCamera::getInstance()); + gPipeline.generateHighlight(*LLViewerCamera::getInstance()); } ////////////////////////////////////// @@ -742,6 +753,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) const F32 max_image_decode_time = llmin(0.005f, 0.005f*10.f*gFrameIntervalSeconds); // 50 ms/second decode time (no more than 5ms/frame) gImageList.updateImages(max_image_decode_time); + + //remove dead textures from GL KL is it req? + LLImageGL::deleteDeadTextures(); stop_glerror(); } llpushcallstacks ; @@ -896,7 +910,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) /// and then display it again with compositor effects. /// Using render to texture would be faster/better, but I don't have a /// grasp of their full display stack just yet. - // gPostProcess->apply(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()); + gPostProcess->apply(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()); // KL if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { @@ -912,6 +926,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) render_ui(); } + gPipeline.rebuildGroups(); + LLSpatialGroup::sNoDelete = FALSE; } @@ -998,6 +1014,15 @@ void render_hud_attachments() 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); diff --git a/linden/indra/newview/llviewerimage.cpp b/linden/indra/newview/llviewerimage.cpp index 400fb2f..93c17a2 100644 --- a/linden/indra/newview/llviewerimage.cpp +++ b/linden/indra/newview/llviewerimage.cpp @@ -60,6 +60,8 @@ #include "pipeline.h" #include "llappviewer.h" #include "llface.h" +#include "lltextureatlas.h" +#include "lltextureatlasmanager.h" #include "llviewercamera.h" /////////////////////////////////////////////////////////////////////////////// @@ -102,7 +104,7 @@ void LLViewerImage::initClass() sNullImagep = new LLImageGL(1,1,3,TRUE); LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3); raw->clear(0x77, 0x77, 0x77, 0xFF); - sNullImagep->createGLTexture(0, raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); + sNullImagep->createGLTexture(0, raw); #if 1 LLPointer<LLViewerImage> imagep = new LLViewerImage(IMG_DEFAULT); @@ -131,7 +133,7 @@ void LLViewerImage::initClass() } } } - imagep->createGLTexture(0, image_raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); + imagep->createGLTexture(0, image_raw); image_raw = NULL; gImageList.addImage(imagep); imagep->dontDiscard(); @@ -141,48 +143,48 @@ void LLViewerImage::initClass() sSmokeImagep = gImageList.getImage(IMG_SMOKE, TRUE, TRUE); sSmokeImagep->setNoDelete() ; - if(gAuditTexture) +#if !LL_RELEASE_FOR_DOWNLOAD + sDefaultTexturep = new LLImageGL() ; + image_raw = new LLImageRaw(dim,dim,3); + data = image_raw->getData(); + for (S32 i = 0; i<dim; i++) { - sDefaultTexturep = new LLImageGL() ; - image_raw = new LLImageRaw(dim,dim,3); - data = image_raw->getData(); - for (S32 i = 0; i<dim; i++) + for (S32 j = 0; j<dim; j++) { - for (S32 j = 0; j<dim; j++) + const S32 border = 2; + if (i<border || j<border || i>=(dim-border) || j>=(dim-border)) { - const S32 border = 2; - if (i<border || j<border || i>=(dim-border) || j>=(dim-border)) - { - *data++ = 0xff; - *data++ = 0xff; - *data++ = 0xff; - } - else - { - *data++ = 0xff; - *data++ = 0xff; - *data++ = 0x00; - } + *data++ = 0xff; + *data++ = 0xff; + *data++ = 0xff; + } + else + { + *data++ = 0xff; + *data++ = 0xff; + *data++ = 0x00; } } - sDefaultTexturep->createGLTexture(0, image_raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); - image_raw = NULL; - sDefaultTexturep->dontDiscard(); } + sDefaultTexturep->createGLTexture(0, image_raw); + image_raw = NULL; + sDefaultTexturep->dontDiscard(); +#endif } // static void LLViewerImage::cleanupClass() { stop_glerror(); - LLImageGL::cleanupClass() ; - sNullImagep = NULL; sDefaultImagep = NULL; sSmokeImagep = NULL; sMissingAssetImagep = NULL; - sWhiteImagep = NULL; - sDefaultTexturep = NULL ; + sWhiteImagep = NULL; + +#if !LL_RELEASE_FOR_DOWNLOAD + LLImageGL::sDefaultTexturep = NULL ; +#endif } // tuning params @@ -231,12 +233,7 @@ void LLViewerImage::updateClass(const F32 velocity, const F32 angular_velocity) } sDesiredDiscardBias = llclamp(sDesiredDiscardBias, sDesiredDiscardBiasMin, sDesiredDiscardBiasMax); - F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; - F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); - sCameraMovingDiscardBias = (S8)llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1) ; - - LLViewerImage::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) && - (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ; + LLImageGL::sUseTextureAtlas = gSavedSettings.getBOOL("EnableTextureAtlas") ; } // static @@ -382,6 +379,7 @@ LLViewerImage::~LLViewerImage() void LLViewerImage::cleanup() { mFaceList.clear() ; + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) { @@ -411,6 +409,192 @@ void LLViewerImage::reinit(BOOL usemipmaps /* = TRUE */) setSize(0,0,0); } +void LLViewerImage::resetFaceAtlas() +{ + //Nothing should be done here. +} + +//invalidate all atlas slots for this image. +void LLViewerImage::invalidateAtlas(BOOL rebuild_geom) +{ + for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + { + if(*iter) + { + LLFace* facep = (LLFace*)*iter ; + facep->removeAtlas() ; + if(rebuild_geom && facep->getDrawable() && facep->getDrawable()->getSpatialGroup()) + { + facep->getDrawable()->getSpatialGroup()->setState(LLSpatialGroup::GEOM_DIRTY); + } + } + } +} + +BOOL LLViewerImage::insertToAtlas() +{ + if(mFaceList.size() < 1) + { + return FALSE ; + } + if(!canAddToAtlas()) + { + return FALSE ; + } + if(getDiscardLevelInAtlas() > 0 && mRawDiscardLevel >= getDiscardLevelInAtlas()) + { + return FALSE ; + } + if(!LLTextureAtlasManager::getInstance()->canAddToAtlas(mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents(), getTexTarget())) + { + return FALSE ; + } + + BOOL ret = TRUE ;//if ret is set to false, will generate a gl texture for this image. + S32 raw_w = mRawImage->getWidth() ; + S32 raw_h = mRawImage->getHeight() ; + F32 xscale = 1.0f, yscale = 1.0f ; + LLPointer<LLTextureAtlasSlot> slot_infop; + LLTextureAtlasSlot* cur_slotp ;//no need to be smart pointer. + LLSpatialGroup* groupp ; + LLFace* facep; + + //if the atlas slot pointers for some faces are null, process them later. + ll_face_list_t waiting_list ; + + for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + { + if(*iter) + { + facep = (LLFace*)*iter ; + + //face can not use atlas. + if(!facep->canUseAtlas()) + { + if(facep->getAtlasInfo()) + { + facep->removeAtlas() ; + } + ret = FALSE ; + continue ; + } + + //the atlas slot is updated + slot_infop = facep->getAtlasInfo() ; + groupp = facep->getDrawable()->getSpatialGroup() ; + + if(slot_infop) + { + if(slot_infop->getSpatialGroup() != groupp) + { + if((cur_slotp = groupp->getCurUpdatingSlot(this))) //switch slot + { + facep->setAtlasInfo(cur_slotp) ; + facep->setAtlasInUse(TRUE) ; + continue ; + } + else //do not forget to update slot_infop->getSpatialGroup(). + { + LLSpatialGroup* gp = slot_infop->getSpatialGroup() ; + gp->setCurUpdatingTime(gFrameCount) ; + gp->setCurUpdatingTexture(this) ; + gp->setCurUpdatingSlot(slot_infop) ; + } + } + else //same group + { + if(gFrameCount && slot_infop->getUpdatedTime() == gFrameCount)//slot is just updated + { + facep->setAtlasInUse(TRUE) ; + continue ; + } + } + } + else + { + //if the slot is null, wait to process them later. + waiting_list.push_back(facep) ; + continue ; + } + + //---------- + //insert to atlas + if(!LLImageGL::createGLTextureInAtlas(mRawDiscardLevel, mRawImage, slot_infop->getAtlas(), slot_infop->getSlotCol(), slot_infop->getSlotRow())) + { + //the texture does not qualify to add to atlas, do not bother to try for other faces. + //invalidateAtlas(); + return FALSE ; + } + + //update texture scale + slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ; + slot_infop->setTexCoordScale(xscale, yscale) ; + slot_infop->setValid() ; + slot_infop->setUpdatedTime(gFrameCount) ; + + //update spatial group atlas info + groupp->setCurUpdatingTime(gFrameCount) ; + groupp->setCurUpdatingTexture(this) ; + groupp->setCurUpdatingSlot(slot_infop) ; + + //make the face to switch to the atlas. + facep->setAtlasInUse(TRUE) ; + } + } + + //process the waiting_list + for(ll_face_list_t::iterator iter = waiting_list.begin(); iter != waiting_list.end(); ++iter) + { + facep = (LLFace*)*iter ; + groupp = facep->getDrawable()->getSpatialGroup() ; + + //check if this texture already inserted to atlas for this group + if((cur_slotp = groupp->getCurUpdatingSlot(this))) + { + facep->setAtlasInfo(cur_slotp) ; + facep->setAtlasInUse(TRUE) ; + continue ; + } + + //need to reserve a slot from atlas + slot_infop = LLTextureAtlasManager::getInstance()->reserveAtlasSlot(llmax(mFullWidth, mFullHeight), getComponents(), groupp, this) ; + + facep->setAtlasInfo(slot_infop) ; + + groupp->setCurUpdatingTime(gFrameCount) ; + groupp->setCurUpdatingTexture(this) ; + groupp->setCurUpdatingSlot(slot_infop) ; + + //slot allocation failed. + if(!slot_infop || !slot_infop->getAtlas()) + { + ret = FALSE ; + facep->setAtlasInUse(FALSE) ; + continue ; + } + + //insert to atlas + if(!LLImageGL::createGLTextureInAtlas(mRawDiscardLevel, mRawImage, slot_infop->getAtlas(), slot_infop->getSlotCol(), slot_infop->getSlotRow())) + { + //the texture does not qualify to add to atlas, do not bother to try for other faces. + ret = FALSE ; + //invalidateAtlas(); + break ; + } + + //update texture scale + slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ; + slot_infop->setTexCoordScale(xscale, yscale) ; + slot_infop->setValid() ; + slot_infop->setUpdatedTime(gFrameCount) ; + + //make the face to switch to the atlas. + facep->setAtlasInUse(TRUE) ; + } + + return ret ; +} + /////////////////////////////////////////////////////////////////////////////// // ONLY called from LLViewerImageList void LLViewerImage::destroyTexture() @@ -432,7 +616,7 @@ void LLViewerImage::addToCreateTexture() if(isForSculptOnly()) { //just update some variables, not to create a real GL texture. - createGLTexture(mRawDiscardLevel, mRawImage, 0, FALSE) ; + createGLTexture(mRawDiscardLevel, mRawImage, 0) ; mNeedsCreateTexture = FALSE ; destroyRawImage(); } @@ -495,7 +679,7 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) mNeedsCreateTexture = FALSE; if (mRawImage.isNull()) { - llerrs << "LLViewerImage trying to create texture with no Raw Image" << llendl; + llwarns << "LLViewerImage trying to create texture with no Raw Image" << llendl; } // llinfos << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ", // mRawDiscardLevel, @@ -519,32 +703,25 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) mOrigHeight = mFullHeight; } - bool size_okay = true; - - U32 raw_width = mRawImage->getWidth() << mRawDiscardLevel; - U32 raw_height = mRawImage->getHeight() << mRawDiscardLevel; - if( raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE ) + if (LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight())) { - llinfos << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << llendl; - size_okay = false; + if(!(res = insertToAtlas())) + { + res = LLImageGL::createGLTexture(mRawDiscardLevel, mRawImage, usename); + resetFaceAtlas() ; + } } - if (!LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight())) + else { // A non power-of-two image was uploaded (through a non standard client) - llinfos << "Non power of two width or height: (" << mRawImage->getWidth() << "," << mRawImage->getHeight() << ")" << llendl; - size_okay = false; - } - - if( !size_okay ) - { - // An inappropriately-sized image was uploaded (through a non standard client) // We treat these images as missing assets which causes them to // be renderd as 'missing image' and to stop requesting data setIsMissingAsset(); destroyRawImage(); return FALSE; } + if (mRawImage->getComponents()>4) { LL_DEBUGS("Openjpeg")<<"broken raw image" << LL_ENDL; @@ -553,7 +730,6 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) return FALSE; } - res = LLImageGL::createGLTexture(mRawDiscardLevel, mRawImage, usename); } // @@ -655,6 +831,7 @@ void LLViewerImage::processTextureStats() S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT); S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT); mTexelsPerImage = (F32)fullwidth * fullheight; + F32 discard_level = 0.f; // If we know the output width and height, we can force the discard @@ -662,7 +839,8 @@ void LLViewerImage::processTextureStats() // data than we need to. if (mBoostLevel == LLViewerImageBoostLevel::BOOST_UI || mBoostLevel == LLViewerImageBoostLevel::BOOST_PREVIEW || - mBoostLevel == LLViewerImageBoostLevel::BOOST_AVATAR_SELF) // JAMESDEBUG what about AVATAR_BAKED_SELF? + mBoostLevel == LLViewerImageBoostLevel::BOOST_AVATAR_SELF || + mBoostLevel == LLViewerImageBoostLevel::BOOST_AVATAR_BAKED_SELF) { discard_level = 0; // full res } @@ -677,12 +855,6 @@ void LLViewerImage::processTextureStats() } else { - if(isLargeImage() && !isJustBound() && mAdditionalDecodePriority < 1.0f) - { - //if is a big image and not being used recently, nor close to the view point, do not load hi-res data. - mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)LLViewerImage::sMinLargeImageSize) ; - } - if ((mCalculatedDiscardLevel >= 0.f) && (llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f)) { @@ -705,6 +877,7 @@ void LLViewerImage::processTextureStats() discard_level += sCameraMovingDiscardBias ; } discard_level = floorf(discard_level); +// discard_level -= (gImageList.mVideoMemorySetting>>1); // more video ram = higher detail F32 min_discard = 0.f; if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) @@ -726,15 +899,12 @@ void LLViewerImage::processTextureStats() if ((sDesiredDiscardBias > 0.0f) && (current_discard >= 0 && mDesiredDiscardLevel >= current_discard)) { - // Limit the amount of GL memory bound each frame - if ( (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) && - (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) + if ( (sBoundTextureMemoryInBytes >> 20) > sMaxBoundTextureMemInMegaBytes*texmem_middle_bound_scale) { scaleDown() ; } // Only allow GL to have 2x the video card memory - else if ( (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale) && - (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) + else if (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel) { scaleDown() ; } @@ -756,7 +926,7 @@ void LLViewerImage::updateVirtualSize() if(facep->getDrawable()->isRecentlyVisible()) { addTextureStats(facep->getVirtualSize()) ; - setAdditionalDecodePriority(facep->getImportanceToCamera()) ; + //setAdditionalDecodePriority(facep->getImportanceToCamera()) ; } } } @@ -796,6 +966,7 @@ void LLViewerImage::switchToCachedImage() mNeedsCreateTexture = TRUE; } } + //============================================================================ F32 LLViewerImage::calcDecodePriority() @@ -817,13 +988,6 @@ F32 LLViewerImage::calcDecodePriority() } S32 cur_discard = getDiscardLevel(); - - //no need to update if the texture reaches its highest res and the memory is sufficient. - //if(LLViewerImage::sFreezeImageScalingDown && !cur_discard) - //{ - // return -5.0f ; - //} - bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); F32 pixel_priority = fsqrtf(mMaxVirtualSize); const S32 MIN_NOT_VISIBLE_FRAMES = 30; // NOTE: this function is not called every frame @@ -842,14 +1006,6 @@ F32 LLViewerImage::calcDecodePriority() { priority = -1.0f ; } - else if (!isJustBound() && mCachedRawImageReady) - { - priority = -1.0f; - } - else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel) - { - priority = -1.0f; - } else if (mDesiredDiscardLevel > mMaxDiscardLevel) { // Don't decode anything we don't need @@ -910,7 +1066,6 @@ F32 LLViewerImage::calcDecodePriority() ddiscard-=2; } ddiscard = llclamp(ddiscard, 0, 4); - priority = ddiscard*100000.f; } if (priority > 0.0f) @@ -942,7 +1097,7 @@ F32 LLViewerImage::calcDecodePriority() //static F32 LLViewerImage::maxDecodePriority() { - return 6000000.f; + return 6000000.f; // KL 2000000 in render pipeline } void LLViewerImage::setDecodePriority(F32 priority) @@ -969,10 +1124,7 @@ void LLViewerImage::setBoostLevel(S32 level) { mBoostLevel = level; - if(gAuditTexture) - { - setCategory(mBoostLevel); - } + if(mBoostLevel != LLViewerImageBoostLevel::BOOST_NONE) { @@ -1022,11 +1174,15 @@ bool LLViewerImage::updateFetch() return false; // process any raw image data in callbacks before replacing } + mFetchState = 0; + mFetchPriority = 0; + mFetchDeltaTime = 999999.f; + mRequestDeltaTime = 999999.f; S32 current_discard = getDiscardLevel(); S32 desired_discard = getDesiredDiscardLevel(); F32 decode_priority = getDecodePriority(); decode_priority = llmax(decode_priority, 0.0f); - decode_priority = llmin(decode_priority, maxDecodePriority()); + //decode_priority = llmin(decode_priority, maxDecodePriority()); if (mIsFetching) { @@ -1059,7 +1215,6 @@ bool LLViewerImage::updateFetch() if (mRawImage.notNull()) { mRawDiscardLevel = fetch_discard; - if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && (current_discard < 0 || mRawDiscardLevel < current_discard)) { @@ -1178,10 +1333,6 @@ bool LLViewerImage::updateFetch() { make_request = false; } - else if (!isJustBound() && mCachedRawImageReady) - { - make_request = false; - } else { if (mIsFetching) @@ -1216,14 +1367,13 @@ bool LLViewerImage::updateFetch() w, h, c, desired_discard, needsAux()); if (fetch_request_created) - { + { mHasFetcher = TRUE; mIsFetching = TRUE; mRequestedDiscardLevel = desired_discard; - mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, - mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); - } + mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); + } // if createRequest() failed, we're finishing up a request for this UUID, // wait for it to complete @@ -1295,12 +1445,12 @@ BOOL LLViewerImage::forceFetch() w, h, c, desired_discard, needsAux()); if (fetch_request_created) - { + { mHasFetcher = TRUE; mIsFetching = TRUE; // Set the image's decode priority to maxDecodePriority() too, or updateFetch() will set // the request priority to 0 and terminate the fetch before we even started (SNOW-203). - gImageList.bumpToMaxDecodePriority(this); + // gImageList.bumpToMaxDecodePriority(this); // Kl force immediate update?? mRequestedDiscardLevel = desired_discard ; mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, @@ -1473,8 +1623,8 @@ bool LLViewerImage::doLoadedCallbacks() destroyRawImage(); readBackRawImage(gl_discard); - llassert_always(mRawImage.notNull()); - llassert_always(!mNeedsAux || mAuxRawImage.notNull()); + //llassert_always(mRawImage.notNull()); + //llassert_always(!mNeedsAux || mAuxRawImage.notNull()); } // @@ -1636,7 +1786,18 @@ bool LLViewerImage::bindDefaultImage(S32 stage) //virtual void LLViewerImage::forceImmediateUpdate() { - gImageList.bumpToMaxDecodePriority(this) ; + //only immediately update a deleted texture which is now being re-used. + if(!isDeleted()) + { + return ; + } + //if already called forceImmediateUpdate() + if(mInImageList && mDecodePriority == LLViewerImage::maxDecodePriority()) + { + return ; + } + + gImageList.forceImmediateUpdate(this) ; return ; } @@ -1647,7 +1808,7 @@ LLImageRaw* LLViewerImage::readBackRawImage(S8 discard_level) llassert_always(mComponents > 0); if (mRawImage.notNull()) { - llerrs << "called with existing mRawImage" << llendl; + llwarns << "called with existing mRawImage" << llendl; mRawImage = NULL; } @@ -1665,7 +1826,7 @@ LLImageRaw* LLViewerImage::readBackRawImage(S8 discard_level) sRawCount++; mIsRawImageValid = TRUE; - + return mRawImage; } diff --git a/linden/indra/newview/llviewerimage.h b/linden/indra/newview/llviewerimage.h index c82b68b..7d646be 100644 --- a/linden/indra/newview/llviewerimage.h +++ b/linden/indra/newview/llviewerimage.h @@ -41,11 +41,13 @@ #include <map> #include <list> -class LLFace; + #define MIN_VIDEO_RAM_IN_MEGA_BYTES 32 #define MAX_VIDEO_RAM_IN_MEGA_BYTES 512 // 512MB max for performance reasons. class LLViewerImage; +class LLTextureAtlas ; +class LLFace ; typedef void (*loaded_callback_func)( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); @@ -261,8 +263,29 @@ public: void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); } // Host we think might have this image, used for baked av textures. + void setTargetHost(LLHost host) { mTargetHost = host; } LLHost getTargetHost() const { return mTargetHost; } + enum + { + BOOST_NONE = 0, + BOOST_AVATAR_BAKED = 1, + BOOST_AVATAR = 2, + BOOST_CLOUDS = 3, + BOOST_SCULPTED = 4, + + BOOST_HIGH = 10, + BOOST_TERRAIN = 11, // has to be high priority for minimap / low detail + BOOST_SELECTED = 12, + BOOST_HUD = 13, + BOOST_AVATAR_BAKED_SELF = 14, + BOOST_UI = 15, + BOOST_PREVIEW = 16, + BOOST_MAP = 17, + BOOST_MAP_LAYER = 18, + BOOST_AVATAR_SELF = 19, // needed for baking avatar + BOOST_MAX_LEVEL + }; void setBoostLevel(S32 level); S32 getBoostLevel() { return mBoostLevel; } @@ -295,6 +318,10 @@ public: S32 getOriginalWidth() { return mOrigWidth; } S32 getOriginalHeight() { return mOrigHeight; } + BOOL insertToAtlas() ; + void resetFaceAtlas() ; + void invalidateAtlas(BOOL rebuild_geom = FALSE); + BOOL isForSculptOnly() const ; void setForSculpt(); @@ -313,6 +340,7 @@ public: void addFace(LLFace* facep) ; void removeFace(LLFace* facep) ; + BOOL isReferenced()const {return mFaceList.size() > 0 ; } friend class LocalBitmap; // tag: vaa emerald local_asset_browser @@ -418,6 +446,7 @@ private: typedef std::list<LLFace*> ll_face_list_t ; ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture + BOOL mInCreationList ; public: static const U32 sCurrentFileVersion; // Default textures diff --git a/linden/indra/newview/llviewerimagelist.cpp b/linden/indra/newview/llviewerimagelist.cpp index 29c630b..f795de6 100644 --- a/linden/indra/newview/llviewerimagelist.cpp +++ b/linden/indra/newview/llviewerimagelist.cpp @@ -199,7 +199,6 @@ static std::string get_texture_list_name() void LLViewerImageList::doPrefetchImages() { -#if 1 if (LLAppViewer::instance()->getPurgeCache()) { // cache was purged, no point @@ -227,7 +226,7 @@ void LLViewerImageList::doPrefetchImages() image->addTextureStats((F32)pixel_area); } } -#endif + } @@ -486,7 +485,7 @@ void LLViewerImageList::removeImageFromList(LLViewerImage *image) { llinfos << "Image is not in mUUIDMap!" << llendl ; } - llerrs << "LLViewerImageList::removeImageFromList - Image not in list" << llendl; + llwarns << "LLViewerImageList::removeImageFromList - Image not in list" << llendl; } llverify(mImageList.erase(image) == 1); image->mInImageList = FALSE; @@ -535,7 +534,8 @@ void LLViewerImageList::deleteImage(LLViewerImage *image) void LLViewerImageList::dirtyImage(LLViewerImage *image) { - mDirtyTextureList.insert(image); + //mDirtyTextureList.insert(image); + image->invalidateAtlas(TRUE) ; // KL } //////////////////////////////////////////////////////////////////////////// @@ -547,25 +547,21 @@ void LLViewerImageList::updateImages(F32 max_time) sNumImagesStat.addValue(sNumImages); sNumRawImagesStat.addValue(LLImageRaw::sRawImageCount); - sGLTexMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sGlobalTextureMemoryInBytes)); - sGLBoundMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sBoundTextureMemoryInBytes)); - sRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageRaw::sGlobalRawMemory)); - sFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory)); - + sGLTexMemStat.addValue((F32)(LLImageGL::sGlobalTextureMemoryInBytes >> 20)); + sGLBoundMemStat.addValue((F32)(LLImageGL::sBoundTextureMemoryInBytes >> 20)); + sRawMemStat.addValue((F32)(LLImageRaw::sGlobalRawMemory >> 20)); + sFormattedMemStat.addValue((F32)(LLImageFormatted::sGlobalFormattedMemory >> 20)); + llpushcallstacks ; - updateImagesDecodePriorities(); - llpushcallstacks ; - F32 total_max_time = max_time; max_time -= updateImagesFetchTextures(max_time); - llpushcallstacks ; - max_time = llmax(max_time, total_max_time*.25f); // at least 25% of max_time + max_time = llmin(llmax(max_time, 0.001f*10.f*gFrameIntervalSeconds), 0.001f); max_time -= updateImagesCreateTextures(max_time); - llpushcallstacks ; - + max_time = llmin(llmax(max_time, 0.001f*10.f*gFrameIntervalSeconds), 0.001f); + llpushcallstacks ; if (!mDirtyTextureList.empty()) { LLFastTimer t(LLFastTimer::FTM_IMAGE_MARK_DIRTY); @@ -739,7 +735,7 @@ F32 LLViewerImageList::updateImagesCreateTextures(F32 max_time) return create_timer.getElapsedTimeF32(); } -void LLViewerImageList::bumpToMaxDecodePriority(LLViewerImage* imagep) +void LLViewerImageList::forceImmediateUpdate(LLViewerImage* imagep) { if(!imagep) { @@ -747,11 +743,6 @@ void LLViewerImageList::bumpToMaxDecodePriority(LLViewerImage* imagep) } if(imagep->mInImageList) { - if (imagep->getDecodePriority() == LLViewerImage::maxDecodePriority()) - { - // Already at maximum. - return; - } removeImageFromList(imagep); } @@ -1028,13 +1019,16 @@ LLPointer<LLImageJ2C> LLViewerImageList::convertToUploadFile(LLPointer<LLImageRa return compressedImage; } + +const S32 MIN_VIDEO_RAM = 32; +const S32 MAX_VIDEO_RAM = 512; // 512MB max for performance reasons. // Returns min setting for TextureMemory (in MB) S32 LLViewerImageList::getMinVideoRamSetting() { - S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); + S32 system_ram = (S32)(gSysMemory.getPhysicalMemoryClamped() >> 20); //min texture mem sets to 64M if total physical mem is more than 1.5GB - return (system_ram > 1500) ? 64 : MIN_VIDEO_RAM_IN_MEGA_BYTES ; + return (system_ram > 1500) ? 64 : MIN_VIDEO_RAM; } //static @@ -1061,14 +1055,14 @@ S32 LLViewerImageList::getMaxVideoRamSetting(bool get_recommended) llwarns << "VRAM amount not detected, defaulting to " << max_texmem << " MB" << llendl; } - S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); // In MB + S32 system_ram = (S32)(gSysMemory.getPhysicalMemoryClamped() >> 20); // In MB //llinfos << "*** DETECTED " << system_ram << " MB of system memory." << llendl; if (get_recommended) max_texmem = llmin(max_texmem, (S32)(system_ram/2)); else max_texmem = llmin(max_texmem, (S32)(system_ram)); - max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), MAX_VIDEO_RAM_IN_MEGA_BYTES); + max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), MAX_VIDEO_RAM); return max_texmem; } @@ -1113,9 +1107,9 @@ void LLViewerImageList::updateMaxResidentTexMem(S32 mem) mMaxTotalTextureMemInMegaBytes -= (mMaxResidentTexMemInMegaBytes >> 2); } - if (mMaxTotalTextureMemInMegaBytes > (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()) - 128) + if (mMaxTotalTextureMemInMegaBytes > (S32)(gSysMemory.getPhysicalMemoryClamped() >> 20) - 128) { - mMaxTotalTextureMemInMegaBytes = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()) - 128 ; + mMaxTotalTextureMemInMegaBytes = (gSysMemory.getPhysicalMemoryClamped() >> 20) - 128 ; } llinfos << "Total Video Memory set to: " << vb_mem << " MB" << llendl; diff --git a/linden/indra/newview/llviewerimagelist.h b/linden/indra/newview/llviewerimagelist.h index 561e8e5..f82d9f3 100644 --- a/linden/indra/newview/llviewerimagelist.h +++ b/linden/indra/newview/llviewerimagelist.h @@ -112,7 +112,7 @@ public: LLGLenum primary_format = 0, const LLUUID& force_id = LLUUID::null ); - + // Request image from a specific host, used for baked avatar textures. // Implemented in header in case someone changes default params above. JC LLViewerImage* getImageFromHost(const LLUUID& image_id, LLHost host) @@ -129,7 +129,7 @@ public: // Using image stats, determine what images are necessary, and perform image updates. void updateImages(F32 max_time); - void bumpToMaxDecodePriority(LLViewerImage* imagep) ; + void forceImmediateUpdate(LLViewerImage* imagep) ; // Decode and create textures for all images currently in list. void decodeAllImages(F32 max_decode_time); diff --git a/linden/indra/newview/llviewerjointmesh.cpp b/linden/indra/newview/llviewerjointmesh.cpp index b6f0daf..dc08bcd 100644 --- a/linden/indra/newview/llviewerjointmesh.cpp +++ b/linden/indra/newview/llviewerjointmesh.cpp @@ -523,9 +523,9 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) //---------------------------------------------------------------- if (!gRenderForSelect) { - if (is_dummy) + /* if (is_dummy) glColor4fv(LLVOAvatar::getDummyColor().mV); - else + else */ glColor4fv(mColor.mV); } @@ -557,7 +557,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) { if( mLayerSet->hasComposite() ) { - gGL.getTexUnit(0)->bind(mLayerSet->getComposite()->getTexture()); + gGL.getTexUnit(0)->bind(mLayerSet->getComposite()->getTexture(), TRUE); // KL SD } else { @@ -565,7 +565,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) // Ignore the warning if that's the case. if (!gSavedSettings.getBOOL("RenderUnloadedAvatar")) { - llwarns << "Layerset without composite" << llendl; + //llwarns << "Layerset without composite" << llendl; } gGL.getTexUnit(0)->bind(gImageList.getImage(IMG_DEFAULT)); } @@ -574,7 +574,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) if ( !is_dummy && mTexture.notNull() ) { old_mode = mTexture->getAddressMode(); - gGL.getTexUnit(0)->bind(mTexture.get()); + gGL.getTexUnit(0)->bind(mTexture.get(), TRUE); // KL SD gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } else diff --git a/linden/indra/newview/llviewermedia.cpp b/linden/indra/newview/llviewermedia.cpp index 8c5cf6a..8857170 100644 --- a/linden/indra/newview/llviewermedia.cpp +++ b/linden/indra/newview/llviewermedia.cpp @@ -938,9 +938,7 @@ void LLViewerMediaImpl::update() x_pos, y_pos, width, - height, - TRUE); // force a fast update (i.e. don't call analyzeAlpha, etc.) - + height); } mMediaSource->resetDirty(); diff --git a/linden/indra/newview/llviewermenu.cpp b/linden/indra/newview/llviewermenu.cpp index 7266dbc..314fc94 100644 --- a/linden/indra/newview/llviewermenu.cpp +++ b/linden/indra/newview/llviewermenu.cpp @@ -1408,14 +1408,14 @@ void init_debug_avatar_menu(LLMenuGL* menu) //menu->append(new LLMenuItemToggleGL("Show Attachment Points", &LLVOAvatar::sShowAttachmentPoints)); //diabling collision plane due to DEV-14477 -brad //menu->append(new LLMenuItemToggleGL("Show Collision Plane", &LLVOAvatar::sShowFootPlane)); - menu->append(new LLMenuItemCheckGL("Show Collision Skeleton", + /*menu->append(new LLMenuItemCheckGL("Show Collision Skeleton", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_AVATAR_VOLUME)); menu->append(new LLMenuItemCheckGL("Display Agent Target", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, - (void*)LLPipeline::RENDER_DEBUG_AGENT_TARGET)); + (void*)LLPipeline::RENDER_DEBUG_AGENT_TARGET));*/ menu->append(new LLMenuItemToggleGL( "Debug Rotation", &LLVOAvatar::sDebugAvatarRotation)); menu->append(new LLMenuItemCallGL("Dump Attachments", handle_dump_attachments)); menu->append(new LLMenuItemCallGL("Refresh Appearance", handle_rebake_textures, NULL, NULL, 'R', MASK_ALT | MASK_CONTROL )); @@ -10436,7 +10436,7 @@ class LLAdvancedCheckShowCollisionPlane : public view_listener_t // SHOW COLLISION SKELETON // ///////////////////////////// - +/* class LLAdvancedToggleShowCollisionSkeleton : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) @@ -10457,13 +10457,13 @@ class LLAdvancedCheckShowCollisionSkeleton : public view_listener_t } }; - +*/ ////////////////////////// // DISPLAY AGENT TARGET // ////////////////////////// - +/* class LLAdvancedToggleDisplayAgentTarget : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) @@ -10484,7 +10484,7 @@ class LLAdvancedCheckDisplayAgentTarget : public view_listener_t } }; - +*/ /////////////////////////// // DEBUG AVATAR ROTATION // @@ -11350,10 +11350,10 @@ void initialize_menus() addMenu(new LLAdvancedCheckDebugCharacterVis(), "Advanced.CheckDebugCharacterVis"); // addMenu(new LLAdvancedToggleShowCollisionPlane(), "Advanced.ToggleShowCollisionPlane"); // addMenu(new LLAdvancedCheckShowCollisionPlane(), "Advanced.CheckShowCollisionPlane"); - addMenu(new LLAdvancedToggleShowCollisionSkeleton(), "Advanced.ToggleShowCollisionSkeleton"); - addMenu(new LLAdvancedCheckShowCollisionSkeleton(), "Advanced.CheckShowCollisionSkeleton"); - addMenu(new LLAdvancedToggleDisplayAgentTarget(), "Advanced.ToggleDisplayAgentTarget"); - addMenu(new LLAdvancedCheckDisplayAgentTarget(), "Advanced.CheckDisplayAgentTarget"); +// addMenu(new LLAdvancedToggleShowCollisionSkeleton(), "Advanced.ToggleShowCollisionSkeleton"); +// addMenu(new LLAdvancedCheckShowCollisionSkeleton(), "Advanced.CheckShowCollisionSkeleton"); +// addMenu(new LLAdvancedToggleDisplayAgentTarget(), "Advanced.ToggleDisplayAgentTarget"); +// addMenu(new LLAdvancedCheckDisplayAgentTarget(), "Advanced.CheckDisplayAgentTarget"); addMenu(new LLAdvancedToggleDebugAvatarRotation(), "Advanced.ToggleDebugAvatarRotation"); addMenu(new LLAdvancedCheckDebugAvatarRotation(), "Advanced.CheckDebugAvatarRotation"); addMenu(new LLAdvancedDumpAttachments(), "Advanced.DumpAttachments"); diff --git a/linden/indra/newview/llviewerobject.cpp b/linden/indra/newview/llviewerobject.cpp index b40d4e0..2a6fafa 100644 --- a/linden/indra/newview/llviewerobject.cpp +++ b/linden/indra/newview/llviewerobject.cpp @@ -2785,6 +2785,11 @@ BOOL LLViewerObject::updateGeometry(LLDrawable *drawable) return TRUE; } +void LLViewerObject::updateGL() +{ + +} + void LLViewerObject::updateFaceSize(S32 idx) { @@ -2889,7 +2894,7 @@ F32 LLViewerObject::getMidScale() const } -void LLViewerObject::updateTextures() +void LLViewerObject::updateTextures(LLAgent &agent) { } @@ -3734,6 +3739,7 @@ S32 LLViewerObject::setTEColor(const U8 te, const LLColor4& color) else if (color != tep->getColor()) { retval = LLPrimitive::setTEColor(te, color); + //setChanged(TEXTURE); if (mDrawable.notNull() && retval) { // These should only happen on updates which are not the initial update. @@ -3972,7 +3978,7 @@ LLViewerImage *LLViewerObject::getTEImage(const U8 face) const } } - llerrs << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << llendl; + llwarns << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << llendl; return NULL; } @@ -4158,6 +4164,11 @@ void LLViewerObject::updateText() } } +LLVOAvatar* LLViewerObject::asAvatar() +{ + return NULL; +} + BOOL LLViewerObject::isParticleSource() const { return !mPartSourcep.isNull() && !mPartSourcep->isDead(); @@ -4372,7 +4383,14 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow gAudiop->cleanupAudioSource(mAudioSourcep); mAudioSourcep = NULL; } - +/* + if (mAudioSourcep && mAudioSourcep->isMuted() && + mAudioSourcep->getCurrentData() && mAudioSourcep->getCurrentData()->getID() == audio_uuid) + { + //llinfos << "Already having this sound as muted sound, ignoring" << llendl; + return; + } +*/ getAudioSource(owner_id); if (mAudioSourcep) @@ -4466,7 +4484,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para new_block = new LLSculptParams(); break; } - + case LLNetworkData::PARAMS_LIGHT_IMAGE: + { + new_block = new LLLightImageParams(); + break; + } default: { llinfos << "Unknown param type." << llendl; @@ -4557,7 +4579,7 @@ bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_ bool LLViewerObject::setParameterEntryInUse(U16 param_type, BOOL in_use, bool local_origin) { ExtraParameter* param = getExtraParameterEntryCreate(param_type); - if (param->in_use != in_use) + if (param && param->in_use != in_use) { param->in_use = in_use; parameterChanged(param_type, param->data, in_use, local_origin); @@ -4973,7 +4995,7 @@ U32 LLViewerObject::getPartitionType() const return LLViewerRegion::PARTITION_NONE; } -void LLViewerObject::dirtySpatialGroup() const +void LLViewerObject::dirtySpatialGroup(BOOL priority) const { if (mDrawable) { @@ -4981,6 +5003,7 @@ void LLViewerObject::dirtySpatialGroup() const if (group) { group->dirtyGeom(); + gPipeline.markRebuild(group, priority); } } } diff --git a/linden/indra/newview/llviewerobject.h b/linden/indra/newview/llviewerobject.h index 7f8bd63..41c406a 100644 --- a/linden/indra/newview/llviewerobject.h +++ b/linden/indra/newview/llviewerobject.h @@ -74,6 +74,7 @@ class LLViewerPartSourceScript; class LLViewerRegion; class LLViewerObjectMedia; class LLVOInventoryListener; +class LLVOAvatar; typedef enum e_object_update_type { @@ -116,7 +117,7 @@ public: //============================================================================ -class LLViewerObject : public LLPrimitive, public LLRefCount +class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate { protected: ~LLViewerObject(); // use unref() @@ -143,6 +144,8 @@ public: BOOL isOrphaned() const { return mOrphaned; } BOOL isParticleSource() const; + virtual LLVOAvatar* asAvatar(); + static void initVOClasses(); static void cleanupVOClasses(); @@ -189,11 +192,12 @@ public: S32 getNumFaces() const { return mNumFaces; } // Graphical stuff for objects - maybe broken out into render class later? - virtual void updateTextures(); + virtual void updateTextures(LLAgent &agent); virtual void boostTexturePriority(BOOL boost_children = TRUE); // When you just want to boost priority of this object virtual LLDrawable* createDrawable(LLPipeline *pipeline); virtual BOOL updateGeometry(LLDrawable *drawable); + virtual void updateGL(); virtual void updateFaceSize(S32 idx); virtual BOOL updateLOD(); virtual BOOL setDrawableParent(LLDrawable* parentp); @@ -218,6 +222,7 @@ public: virtual BOOL isFlexible() const { return FALSE; } virtual BOOL isSculpted() const { return FALSE; } + virtual BOOL hasLightTexture() const { return FALSE; } // This method returns true if the object is over land owned by // the agent. @@ -468,7 +473,7 @@ public: virtual S32 getLOD() const { return 3; } virtual U32 getPartitionType() const; - virtual void dirtySpatialGroup() const; + virtual void dirtySpatialGroup(BOOL priority = FALSE) const; virtual void dirtyMesh(); virtual LLNetworkData* getParameterEntry(U16 param_type) const; diff --git a/linden/indra/newview/llviewerobjectlist.cpp b/linden/indra/newview/llviewerobjectlist.cpp index bfb248b..a289570 100644 --- a/linden/indra/newview/llviewerobjectlist.cpp +++ b/linden/indra/newview/llviewerobjectlist.cpp @@ -629,7 +629,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) // Update distance & gpw objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area - objectp->updateTextures(); // Update the image levels of textures for this object. + objectp->updateTextures(agent); // Update the image levels of textures for this object. } } diff --git a/linden/indra/newview/llviewerobjectlist.h b/linden/indra/newview/llviewerobjectlist.h index 07920cb..a77c33d 100644 --- a/linden/indra/newview/llviewerobjectlist.h +++ b/linden/indra/newview/llviewerobjectlist.h @@ -44,7 +44,6 @@ // project includes #include "llviewerobject.h" -class LLCamera; class LLNetMap; class LLDebugBeacon; diff --git a/linden/indra/newview/llviewerparceloverlay.cpp b/linden/indra/newview/llviewerparceloverlay.cpp index 0bcd8f3..935e3e6 100644 --- a/linden/indra/newview/llviewerparceloverlay.cpp +++ b/linden/indra/newview/llviewerparceloverlay.cpp @@ -71,7 +71,7 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_ // Use mipmaps = FALSE, clamped, NEAREST filter, for sharp edges mTexture = new LLImageGL(FALSE); mImageRaw = new LLImageRaw(mParcelGridsPerEdge, mParcelGridsPerEdge, OVERLAY_IMG_COMPONENTS); - mTexture->createGLTexture(0, mImageRaw, 0, TRUE, LLViewerImageBoostLevel::OTHER); + mTexture->createGLTexture(0, mImageRaw, 0); gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->bind(mTexture); mTexture->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -593,7 +593,7 @@ void LLViewerParcelOverlay::addPropertyLine( break; default: - llerrs << "Invalid edge in addPropertyLine" << llendl; + llwarns << "Invalid edge in addPropertyLine" << llendl; return; } diff --git a/linden/indra/newview/llviewershadermgr.cpp b/linden/indra/newview/llviewershadermgr.cpp index 69f7bd8..8648271 100644 --- a/linden/indra/newview/llviewershadermgr.cpp +++ b/linden/indra/newview/llviewershadermgr.cpp @@ -113,6 +113,8 @@ LLGLSLShader gDeferredAvatarProgram; LLGLSLShader gDeferredAvatarAlphaProgram; LLGLSLShader gDeferredLightProgram; LLGLSLShader gDeferredMultiLightProgram; +LLGLSLShader gDeferredSpotLightProgram; +LLGLSLShader gDeferredMultiSpotLightProgram; LLGLSLShader gDeferredSunProgram; LLGLSLShader gDeferredBlurLightProgram; LLGLSLShader gDeferredSoftenProgram; @@ -120,6 +122,12 @@ LLGLSLShader gDeferredShadowProgram; LLGLSLShader gDeferredAvatarShadowProgram; LLGLSLShader gDeferredAlphaProgram; LLGLSLShader gDeferredFullbrightProgram; +LLGLSLShader gDeferredGIProgram; +LLGLSLShader gDeferredPostGIProgram; +LLGLSLShader gDeferredPostProgram; + +LLGLSLShader gLuminanceGatherProgram; + //current avatar shader parameter pointer GLint gAvatarMatrixParam; @@ -151,6 +159,9 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gDeferredMultiLightProgram); mShaderList.push_back(&gDeferredAlphaProgram); mShaderList.push_back(&gDeferredFullbrightProgram); + mShaderList.push_back(&gDeferredPostGIProgram); + mShaderList.push_back(&gDeferredPostProgram); + mShaderList.push_back(&gDeferredGIProgram); mShaderList.push_back(&gDeferredWaterProgram); mShaderList.push_back(&gDeferredAvatarAlphaProgram); } @@ -220,13 +231,32 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void) mReservedUniforms.push_back("shadowMap1"); mReservedUniforms.push_back("shadowMap2"); mReservedUniforms.push_back("shadowMap3"); + mReservedUniforms.push_back("shadowMap4"); + mReservedUniforms.push_back("shadowMap5"); + mReservedUniforms.push_back("normalMap"); mReservedUniforms.push_back("positionMap"); mReservedUniforms.push_back("diffuseRect"); mReservedUniforms.push_back("specularRect"); mReservedUniforms.push_back("noiseMap"); + mReservedUniforms.push_back("lightFunc"); mReservedUniforms.push_back("lightMap"); - + mReservedUniforms.push_back("luminanceMap"); + mReservedUniforms.push_back("giLightMap"); + mReservedUniforms.push_back("sunLightMap"); + mReservedUniforms.push_back("localLightMap"); + mReservedUniforms.push_back("projectionMap"); + mReservedUniforms.push_back("diffuseGIMap"); + mReservedUniforms.push_back("specularGIMap"); + mReservedUniforms.push_back("normalGIMap"); + mReservedUniforms.push_back("minpGIMap"); + mReservedUniforms.push_back("maxpGIMap"); + mReservedUniforms.push_back("depthGIMap"); + mReservedUniforms.push_back("lastDiffuseGIMap"); + mReservedUniforms.push_back("lastNormalGIMap"); + mReservedUniforms.push_back("lastMinpGIMap"); + mReservedUniforms.push_back("lastMaxpGIMap"); + mWLUniforms.push_back("camPosLocal"); mTerrainUniforms.reserve(5); @@ -754,9 +784,9 @@ BOOL LLViewerShaderMgr::loadShadersEffects() } } -#if 0 - // disabling loading of postprocess shaders until we fix - // ATI sampler2DRect compatibility. + + // KL enabling loading of postprocess shaders until we fix + // ATI may still have issues //load Color Filter Shader if (success) @@ -797,7 +827,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects() gPostNightVisionProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT]; success = gPostNightVisionProgram.createShader(NULL, &shaderUniforms); } - #endif + return success; @@ -814,6 +844,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredTerrainProgram.unload(); gDeferredLightProgram.unload(); gDeferredMultiLightProgram.unload(); + gDeferredSpotLightProgram.unload(); + gDeferredMultiSpotLightProgram.unload(); gDeferredSunProgram.unload(); gDeferredBlurLightProgram.unload(); gDeferredSoftenProgram.unload(); @@ -823,6 +855,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAvatarAlphaProgram.unload(); gDeferredAlphaProgram.unload(); gDeferredFullbrightProgram.unload(); + gDeferredPostGIProgram.unload(); + gDeferredPostProgram.unload(); + gLuminanceGatherProgram.unload(); + gDeferredGIProgram.unload(); gDeferredWaterProgram.unload(); return FALSE; } @@ -893,6 +929,26 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { + gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader"; + gDeferredSpotLightProgram.mShaderFiles.clear(); + gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSpotLightProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader"; + gDeferredMultiSpotLightProgram.mShaderFiles.clear(); + gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredMultiSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL); + } + + if (success) + { gDeferredSunProgram.mName = "Deferred Sun Shader"; gDeferredSunProgram.mShaderFiles.clear(); gDeferredSunProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB)); @@ -942,6 +998,36 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { + gDeferredPostGIProgram.mName = "Deferred Post GI Shader"; + gDeferredPostGIProgram.mShaderFiles.clear(); + gDeferredPostGIProgram.mShaderFiles.push_back(make_pair("deferred/postgiV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredPostGIProgram.mShaderFiles.push_back(make_pair("deferred/postgiF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredPostGIProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredPostGIProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredPostProgram.mName = "Deferred Post Shader"; + gDeferredPostProgram.mShaderFiles.clear(); + gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredPostProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredGIProgram.mName = "Deferred GI Shader"; + gDeferredGIProgram.mShaderFiles.clear(); + gDeferredGIProgram.mShaderFiles.push_back(make_pair("deferred/giV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredGIProgram.mShaderFiles.push_back(make_pair("deferred/giF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredGIProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredGIProgram.createShader(NULL, NULL); + } + + if (success) + { // load water shader gDeferredWaterProgram.mName = "Deferred Water Shader"; gDeferredWaterProgram.mFeatures.calculatesAtmospherics = true; @@ -1022,6 +1108,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); } + if (success) + { + gLuminanceGatherProgram.mName = "Luminance Gather Shader"; + gLuminanceGatherProgram.mShaderFiles.clear(); + gLuminanceGatherProgram.mShaderFiles.push_back(make_pair("deferred/luminanceV.glsl", GL_VERTEX_SHADER_ARB)); + gLuminanceGatherProgram.mShaderFiles.push_back(make_pair("deferred/luminanceF.glsl", GL_FRAGMENT_SHADER_ARB)); + gLuminanceGatherProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gLuminanceGatherProgram.createShader(NULL, NULL); + } + return success; } diff --git a/linden/indra/newview/llviewershadermgr.h b/linden/indra/newview/llviewershadermgr.h index a743966..bb50779 100644 --- a/linden/indra/newview/llviewershadermgr.h +++ b/linden/indra/newview/llviewershadermgr.h @@ -116,12 +116,30 @@ public: DEFERRED_SHADOW1, DEFERRED_SHADOW2, DEFERRED_SHADOW3, + DEFERRED_SHADOW4, + DEFERRED_SHADOW5, DEFERRED_NORMAL, DEFERRED_POSITION, DEFERRED_DIFFUSE, DEFERRED_SPECULAR, DEFERRED_NOISE, + DEFERRED_LIGHTFUNC, DEFERRED_LIGHT, + DEFERRED_LUMINANCE, + DEFERRED_GI_LIGHT, + DEFERRED_SUN_LIGHT, + DEFERRED_LOCAL_LIGHT, + DEFERRED_PROJECTION, + DEFERRED_GI_DIFFUSE, + DEFERRED_GI_SPECULAR, + DEFERRED_GI_NORMAL, + DEFERRED_GI_MIN_POS, + DEFERRED_GI_MAX_POS, + DEFERRED_GI_DEPTH, + DEFERRED_GI_LAST_DIFFUSE, + DEFERRED_GI_LAST_NORMAL, + DEFERRED_GI_LAST_MIN_POS, + DEFERRED_GI_LAST_MAX_POS, END_RESERVED_UNIFORMS } eGLSLReservedUniforms; @@ -326,16 +344,23 @@ extern LLGLSLShader gDeferredTerrainProgram; extern LLGLSLShader gDeferredTreeProgram; extern LLGLSLShader gDeferredLightProgram; extern LLGLSLShader gDeferredMultiLightProgram; +extern LLGLSLShader gDeferredSpotLightProgram; +extern LLGLSLShader gDeferredMultiSpotLightProgram; extern LLGLSLShader gDeferredSunProgram; +extern LLGLSLShader gDeferredGIProgram; extern LLGLSLShader gDeferredBlurLightProgram; extern LLGLSLShader gDeferredAvatarProgram; extern LLGLSLShader gDeferredSoftenProgram; extern LLGLSLShader gDeferredShadowProgram; +extern LLGLSLShader gDeferredPostGIProgram; +extern LLGLSLShader gDeferredPostProgram; extern LLGLSLShader gDeferredAvatarShadowProgram; extern LLGLSLShader gDeferredAlphaProgram; extern LLGLSLShader gDeferredFullbrightProgram; extern LLGLSLShader gDeferredAvatarAlphaProgram; +extern LLGLSLShader gLuminanceGatherProgram; + //current avatar shader parameter pointer extern GLint gAvatarMatrixParam; diff --git a/linden/indra/newview/llviewerstats.h b/linden/indra/newview/llviewerstats.h index b176632..9107ad6 100644 --- a/linden/indra/newview/llviewerstats.h +++ b/linden/indra/newview/llviewerstats.h @@ -196,7 +196,7 @@ private: F64 mLastTimeDiff; // used for time stat updates }; -static const F32 SEND_STATS_PERIOD = 300.0f; +static const F32 SEND_STATS_PERIOD = 3000.0f; // The following are from (older?) statistics code found in appviewer. void init_statistics(); diff --git a/linden/indra/newview/llviewerwindow.cpp b/linden/indra/newview/llviewerwindow.cpp index f7713c2..6f1b54c 100644 --- a/linden/indra/newview/llviewerwindow.cpp +++ b/linden/indra/newview/llviewerwindow.cpp @@ -471,6 +471,27 @@ public: ypos += y_inc; + { + std::ostringstream ostr; + ostr << "Shadow error: " << gPipeline.mShadowError; + addText(xpos, ypos, ostr.str()); + ypos += y_inc; + } + + { + std::ostringstream ostr; + ostr << "Shadow FOV: " << gPipeline.mShadowFOV; + addText(xpos, ypos, ostr.str()); + ypos += y_inc; + } + + { + std::ostringstream ostr; + ostr << "Shadow Splits: " << gPipeline.mSunClipPlanes; + addText(xpos, ypos, ostr.str()); + ypos += y_inc; + } + LLVertexBuffer::sBindCount = LLImageGL::sBindCount = LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0; @@ -1321,7 +1342,6 @@ LLViewerWindow::LLViewerWindow( // Init the image list. Must happen after GL is initialized and before the images that // LLViewerWindow needs are requested. - LLImageGL::initClass(LLViewerImageBoostLevel::MAX_GL_IMAGE_CATEGORY) ; gImageList.init(); LLViewerImage::initClass(); gBumpImageList.init(); @@ -1434,7 +1454,7 @@ void LLViewerWindow::initBase() llassert( !gConsole ); gConsole = new LLConsole( "console", - gSavedSettings.getS32("ConsoleBufferSize"), + //gSavedSettings.getS32("ConsoleBufferSize"), getChatConsoleRect(), gSavedSettings.getS32("ChatFontSize"), gSavedSettings.getF32("ChatPersistTime") ); @@ -2515,7 +2535,6 @@ BOOL LLViewerWindow::handlePerFrameHover() mMouseInWindow = TRUE; } - S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]); S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]); @@ -2538,7 +2557,7 @@ BOOL LLViewerWindow::handlePerFrameHover() mCurrentMouseDelta.set(dx, dy); mouse_vel.setVec((F32) dx, (F32) dy); } - + mMouseVelocityStat.addValue(mouse_vel.magVec()); if (gNoRender) @@ -2727,8 +2746,8 @@ BOOL LLViewerWindow::handlePerFrameHover() { mToolTip->setVisible( tooltip_vis ); } - } - + } + if (tool && tool != gToolNull && tool != LLToolCompInspect::getInstance() && tool != LLToolDragAndDrop::getInstance() && !gSavedSettings.getBOOL("FreezeTime")) { LLMouseHandler *captor = gFocusMgr.getMouseCapture(); @@ -2798,37 +2817,41 @@ BOOL LLViewerWindow::handlePerFrameHover() gFloaterView->setRect(floater_rect); } - // snap floaters to top of chat bar/button strip - LLView* chatbar_and_buttons = gOverlayBar->getChild<LLView>("chatbar_and_buttons", TRUE); - // find top of chatbar and state buttons, if either are visible - if (chatbar_and_buttons && !chatbar_and_buttons->getLocalBoundingRect().isNull()) { - // convert top/left corner of chatbar/buttons container to gFloaterView-relative coordinates + // snap floaters to top of chat bar/button strip + LLView* chatbar_and_buttons = gOverlayBar->getChild<LLView>("chatbar_and_buttons", TRUE); S32 top, left; - chatbar_and_buttons->localPointToOtherView( - chatbar_and_buttons->getLocalBoundingRect().mLeft, - chatbar_and_buttons->getLocalBoundingRect().mTop, - &left, - &top, - gFloaterView); - gFloaterView->setSnapOffsetBottom(top); - } - else if (gToolBar->getVisible()) - { - S32 top, left; - gToolBar->localPointToOtherView( - gToolBar->getLocalBoundingRect().mLeft, - gToolBar->getLocalBoundingRect().mTop, - &left, - &top, - gFloaterView); - gFloaterView->setSnapOffsetBottom(top); - } - else - { - gFloaterView->setSnapOffsetBottom(0); + S32 chatbar_and_buttons_x = chatbar_and_buttons->getLocalBoundingRect().mLeft; + S32 chatbar_and_buttons_y = chatbar_and_buttons->getLocalBoundingRect().mTop; + + // find top of chatbar and state buttons, if either are visible + if (chatbar_and_buttons && !chatbar_and_buttons->getLocalBoundingRect().isNull()) + { + // convert top/left corner of chatbar/buttons container to + // gFloaterView-relative coordinates + chatbar_and_buttons->localPointToOtherView( + chatbar_and_buttons_x, + chatbar_and_buttons_y, + &left, + &top, + gFloaterView); + gFloaterView->setSnapOffsetBottom(top); + } + else if (gToolBar->getVisible()) + { + gToolBar->localPointToOtherView( + chatbar_and_buttons_x, + chatbar_and_buttons_y, + &left, + &top, + gFloaterView); + gFloaterView->setSnapOffsetBottom(top); + } + else + { + gFloaterView->setSnapOffsetBottom(0); + } } - // Always update console LLRect console_rect = getChatConsoleRect(); console_rect.mBottom = gHUDView->getRect().mBottom + getChatConsoleBottomPad(); @@ -2836,8 +2859,8 @@ BOOL LLViewerWindow::handlePerFrameHover() gConsole->setRect(console_rect); } - mLastMousePoint = mCurrentMousePoint; + mLastMousePoint = mCurrentMousePoint; // last ditch force of edit menu to selection manager if (LLEditMenuHandler::gEditMenuHandler == NULL && LLSelectMgr::getInstance()->getSelection()->getObjectCount()) { @@ -2900,7 +2923,6 @@ BOOL LLViewerWindow::handlePerFrameHover() &gDebugRaycastBinormal); } - // per frame picking - for tooltips and changing cursor over interactive objects static S32 previous_x = -1; static S32 previous_y = -1; @@ -2943,7 +2965,6 @@ BOOL LLViewerWindow::handlePerFrameHover() previous_x = x; previous_y = y; - return handled; } @@ -4041,7 +4062,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei { if(image_width > window_width || image_height > window_height) //need to enlarge the scene { - if (gGLManager.mHasFramebufferObject && !show_ui) + if (!LLPipeline::sRenderDeferred && gGLManager.mHasFramebufferObject && !show_ui) { GLint max_size = 0; glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &max_size); @@ -4130,9 +4151,16 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei else { const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor)); - display(do_rebuild, scale_factor, subfield, TRUE); - // Required for showing the GUI in snapshots? See DEV-16350 for details. JC - render_ui(scale_factor, subfield); + if (LLPipeline::sRenderDeferred) + { + display(do_rebuild, scale_factor, subfield, FALSE); + } + else + { + display(do_rebuild, scale_factor, subfield, TRUE); + // Required for showing the GUI in snapshots? See DEV-16350 for details. JC + render_ui(scale_factor, subfield); + } } S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width); diff --git a/linden/indra/newview/llvlcomposition.cpp b/linden/indra/newview/llvlcomposition.cpp index 535c504..f96665b 100644 --- a/linden/indra/newview/llvlcomposition.cpp +++ b/linden/indra/newview/llvlcomposition.cpp @@ -460,6 +460,10 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, } } + if (!texturep->getHasGLTexture()) + { + texturep->createGLTexture(0, raw); + } texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin); LLSurface::sTextureUpdateTime += gen_timer.getElapsedTimeF32(); LLSurface::sTexelsUpdated += (tex_x_end - tex_x_begin) * (tex_y_end - tex_y_begin); diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp index 14b8d3e..3b62c63 100644 --- a/linden/indra/newview/llvoavatar.cpp +++ b/linden/indra/newview/llvoavatar.cpp @@ -704,6 +704,7 @@ BOOL LLVOAvatar::sDebugInvisible = FALSE; BOOL LLVOAvatar::sShowAttachmentPoints = FALSE; BOOL LLVOAvatar::sShowAnimationDebug = FALSE; BOOL LLVOAvatar::sShowFootPlane = FALSE; +BOOL LLVOAvatar::sShowCollisionVolumes = FALSE; BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE; F32 LLVOAvatar::sLODFactor = 1.f; BOOL LLVOAvatar::sUseImpostors = FALSE; @@ -740,6 +741,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mTyping(FALSE), mMeshValid(FALSE), mVisible(FALSE), + mMeshTexturesDirty(FALSE), mWindFreq(0.f), mRipplePhase( 0.f ), mBelowWater(FALSE), @@ -800,7 +802,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mBakedTextureData[i].mLastTextureIndex = IMG_DEFAULT_AVATAR; mBakedTextureData[i].mTexLayerSet = NULL; mBakedTextureData[i].mIsLoaded = false; - mBakedTextureData[i].mIsUsed = false; + //mBakedTextureData[i].mIsUsed = false; // KL SG mBakedTextureData[i].mMaskTexName = 0; mBakedTextureData[i].mTextureIndex = getTextureIndex((EBakedTextureIndex)i); } @@ -856,9 +858,11 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mRippleTimeLast = 0.f; mShadowImagep = gImageList.getImageFromFile("foot_shadow.j2c"); - gGL.getTexUnit(0)->bind(mShadowImagep.get()); - mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP); - + + // GL NOT ACTIVE HERE + //gGL.getTexUnit(0)->bind(mShadowImagep.get()); + //mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP); + mInAir = FALSE; mStepOnLand = TRUE; @@ -1295,7 +1299,7 @@ void LLVOAvatar::resetImpostors() // static void LLVOAvatar::deleteCachedImages(bool clearAll) { -if(gAuditTexture) +/* if(gAuditTexture) { S32 total_tex_size = sScratchTexBytes ; S32 tex_size = SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT ; @@ -1337,7 +1341,7 @@ if(gAuditTexture) total_tex_size -= 4 * tex_size ; } } - +*/ if (LLTexLayerSet::sHasCaches) { lldebugs << "Deleting layer set caches" << llendl; @@ -1862,6 +1866,11 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) return TRUE; } +LLVOAvatar* LLVOAvatar::asAvatar() // KL SD +{ + return this; +} + //----------------------------------------------------------------------------- // LLVOAvatar::startDefaultMotions() //----------------------------------------------------------------------------- @@ -1924,7 +1933,7 @@ void LLVOAvatar::buildCharacter() LLTimer timer; BOOL status = loadAvatar(); - stop_glerror(); + // stop_glerror(); if (gNoRender) { @@ -2034,7 +2043,7 @@ void LLVOAvatar::buildCharacter() processAnimationStateChanges(); mIsBuilt = TRUE; - stop_glerror(); +// stop_glerror(); //------------------------------------------------------------------------- // build the attach and detach menus @@ -5022,7 +5031,7 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color) //------------------------------------------------------------------------ // LLVOAvatar::updateTextures() //------------------------------------------------------------------------ -void LLVOAvatar::updateTextures() +void LLVOAvatar::updateTextures(LLAgent &agent) // KL SD version { BOOL render_avatar = TRUE; @@ -5041,6 +5050,7 @@ void LLVOAvatar::updateTextures() } std::vector<bool> layer_baked; + // GL NOT ACTIVE HERE - *TODO for (U32 i = 0; i < mBakedTextureData.size(); i++) { layer_baked.push_back(isTextureDefined(mBakedTextureData[i].mTextureIndex)); @@ -5123,12 +5133,6 @@ void LLVOAvatar::updateTextures() if (texture_dict->mIsLocalTexture) { addLocalTextureStats((ETextureIndex)index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]); - // SNOW-8 : temporary snowglobe1.0 fix for baked textures - if (render_avatar && !gGLManager.mIsDisabled ) - { - // bind the texture so that its boost level won't be slammed - gGL.getTexUnit(0)->bind(imagep); - } } else if (texture_dict->mIsBakedTexture) { @@ -5375,7 +5379,7 @@ void LLVOAvatar::processAnimationStateChanges() } } - stop_glerror(); + //stop_glerror(); } @@ -6360,6 +6364,15 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline) } +void LLVOAvatar::updateGL() +{ + if (mMeshTexturesDirty) + { + updateMeshTextures(); + mMeshTexturesDirty = FALSE; + } +} + //----------------------------------------------------------------------------- // updateGeometry() //----------------------------------------------------------------------------- @@ -7396,12 +7409,20 @@ BOOL LLVOAvatar::bindScratchTexture( LLGLenum format ) if( *last_bind_time != LLImageGL::sLastFrameTime ) { *last_bind_time = LLImageGL::sLastFrameTime; - LLImageGL::updateBoundTexMemStatic(texture_bytes, SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; +// #if !LL_RELEASE_FOR_DOWNLOAD +// LLImageGL::updateBoundTexMem(texture_bytes, SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT) ; +// #else + LLImageGL::updateBoundTexMem(texture_bytes); +// #endif } } else { - LLImageGL::updateBoundTexMemStatic(texture_bytes, SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; +// #if !LL_RELEASE_FOR_DOWNLOAD +// LLImageGL::updateBoundTexMem(texture_bytes, SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT) ; +// #else + LLImageGL::updateBoundTexMem(texture_bytes); +// #endif LLVOAvatar::sScratchTexLastBindTime.addData( format, new F32(LLImageGL::sLastFrameTime) ); } @@ -7423,7 +7444,8 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes ) { case GL_LUMINANCE: components = 1; internal_format = GL_LUMINANCE8; break; case GL_ALPHA: components = 1; internal_format = GL_ALPHA8; break; - case GL_COLOR_INDEX: components = 1; internal_format = GL_COLOR_INDEX8_EXT; break; +// Support for GL_EXT_paletted_texture is deprecated +// case GL_COLOR_INDEX: components = 1; internal_format = GL_COLOR_INDEX8_EXT; break; case GL_LUMINANCE_ALPHA: components = 2; internal_format = GL_LUMINANCE8_ALPHA8; break; case GL_RGB: components = 3; internal_format = GL_RGB8; break; case GL_RGBA: components = 4; internal_format = GL_RGBA8; break; @@ -7465,11 +7487,11 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes ) LLVOAvatar::sScratchTexBytes += *texture_bytes; LLImageGL::sGlobalTextureMemoryInBytes += *texture_bytes; - +/* if(gAuditTexture) { LLImageGL::incTextureCounterStatic(SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT, components, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; - } + }*/ return name; } @@ -7572,6 +7594,7 @@ void LLVOAvatar::updateMeshTextures() use_lkg_baked_layer[i] = (!is_layer_baked[i] && (mBakedTextureData[i].mLastTextureIndex != IMG_DEFAULT_AVATAR) && mBakedTextureData[i].mTexLayerSet + && mBakedTextureData[i].mTexLayerSet->getComposite() // KL SD && !mBakedTextureData[i].mTexLayerSet->getComposite()->isInitialized()); if (use_lkg_baked_layer[i]) { @@ -7605,7 +7628,7 @@ void LLVOAvatar::updateMeshTextures() if (use_lkg_baked_layer[i] && !self_customizing ) { LLViewerImage* baked_img = gImageList.getImageFromHost( mBakedTextureData[i].mLastTextureIndex, target_host ); - mBakedTextureData[i].mIsUsed = TRUE; + //mBakedTextureData[i].mIsUsed = TRUE; for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++) { mBakedTextureData[i].mMeshes[k]->setTexture( baked_img ); @@ -7635,7 +7658,7 @@ void LLVOAvatar::updateMeshTextures() { mBakedTextureData[i].mTexLayerSet->createComposite(); mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( TRUE ); - mBakedTextureData[i].mIsUsed = FALSE; + // mBakedTextureData[i].mIsUsed = FALSE; for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++) { mBakedTextureData[i].mMeshes[k]->setLayerSet( mBakedTextureData[i].mTexLayerSet ); @@ -7656,9 +7679,13 @@ void LLVOAvatar::updateMeshTextures() mBakedTextureData[BAKED_HAIR].mMeshes[i]->setTexture( hair_img ); } mHasBakedHair = FALSE; - } - else + } + else { + for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++) + { + mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( 1.f, 1.f, 1.f, 1.f ); + } mHasBakedHair = TRUE; } @@ -7790,7 +7817,7 @@ void LLVOAvatar::clearChat() S32 LLVOAvatar::getLocalDiscardLevel( ETextureIndex index ) { // If the texture is not local, we don't care and treat it as fully loaded - if (!isIndexLocalTexture(index)) return 0; + if (!isIndexLocalTexture(index)) return FALSE; // KL SD version LocalTextureData &local_tex_data = mLocalTextureData[index]; if (index >= 0 @@ -7932,7 +7959,7 @@ bool LLVOAvatar::hasPendingBakedUploads() { for (U32 i = 0; i < mBakedTextureData.size(); i++) { - bool upload_pending = (mBakedTextureData[i].mTexLayerSet && mBakedTextureData[i].mTexLayerSet->getComposite()->uploadPending()); + bool upload_pending = (mBakedTextureData[i].mTexLayerSet && mBakedTextureData[i].mTexLayerSet->getComposite() && mBakedTextureData[i].mTexLayerSet->getComposite()->uploadPending()); if (upload_pending) { return true; @@ -8467,7 +8494,8 @@ void LLVOAvatar::onFirstTEMessageReceived() } } - updateMeshTextures(); + mMeshTexturesDirty = TRUE; // updateMeshTextures(); + gPipeline.markGLRebuild(this); } } @@ -8530,20 +8558,22 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // (isTextureDefined(TEX_SKIRT_BAKED) ? "SKIRT " : "skirt " ) << (getTEImage(TEX_SKIRT_BAKED)->getID()) << std::endl << // (isTextureDefined(TEX_HAIR_BAKED) ? "HAIR" : "hair " ) << (getTEImage(TEX_HAIR_BAKED)->getID()) << std::endl << // (isTextureDefined(TEX_EYES_BAKED) ? "EYES" : "eyes" ) << (getTEImage(TEX_EYES_BAKED)->getID()) << llendl ; - + if( !mFirstTEMessageReceived ) { onFirstTEMessageReceived(); } setCompositeUpdatesEnabled( FALSE ); + mMeshTexturesDirty = TRUE; + gPipeline.markGLRebuild(this); // KL SD needing work in S19? if (!mIsSelf) { releaseUnnecessaryTextures(); } - - updateMeshTextures(); // enables updates for laysets without baked textures. + + //updateMeshTextures(); // enables updates for laysets without baked textures. // parse visual params S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam); @@ -8829,7 +8859,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) if (id == image_baked->getID()) { mBakedTextureData[i].mIsLoaded = true; - mBakedTextureData[i].mIsUsed = true; + //mBakedTextureData[i].mIsUsed = true; mBakedTextureData[i].mLastTextureIndex = id; for (U32 k = 0; k < mBakedTextureData[i].mMeshes.size(); k++) { @@ -9738,9 +9768,9 @@ BOOL LLVOAvatar::updateLOD() LLFace* facep = mDrawable->getFace(0); if (facep->mVertexBuffer.isNull() || - LLVertexBuffer::sEnableVBOs && + (LLVertexBuffer::sEnableVBOs && ((facep->mVertexBuffer->getUsage() == GL_STATIC_DRAW ? TRUE : FALSE) != - (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE))) + (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE)))) { mDirtyMesh = TRUE; } diff --git a/linden/indra/newview/llvoavatar.h b/linden/indra/newview/llvoavatar.h index 0c32244..ff07d81 100644 --- a/linden/indra/newview/llvoavatar.h +++ b/linden/indra/newview/llvoavatar.h @@ -88,6 +88,8 @@ public: /*virtual*/ void markDead(); void startDefaultMotions(); + /*virtual*/ LLVOAvatar* asAvatar(); // KL SD + static void updateImpostors(); //-------------------------------------------------------------------- @@ -137,7 +139,7 @@ public: LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point ); - /*virtual*/ void updateTextures(); + /*virtual*/ void updateTextures(LLAgent &agent); // KL SD // If setting a baked texture, need to request it from a non-local sim. /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid); /*virtual*/ void onShift(const LLVector3& shift_vector); @@ -155,6 +157,8 @@ public: /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); + /*virtual*/ void updateGL(); + /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); BOOL updateJointLODs(); @@ -474,6 +478,7 @@ private: LLFrameTimer mTypingTimer; //-------------------------------------------------------------------- + BOOL mMeshTexturesDirty; // wind rippling in clothes //-------------------------------------------------------------------- public: @@ -570,6 +575,7 @@ public: static BOOL sShowAnimationDebug; // show animation debug info static BOOL sUseImpostors; //use impostors for far away avatars static BOOL sShowFootPlane; // show foot collision plane reported by server + static BOOL sShowCollisionVolumes; // show skeletal collision volumes // KL SD static BOOL sVisibleInFirstPerson; static S32 sNumLODChangesThisFrame; static S32 sNumVisibleChatBubbles; @@ -771,7 +777,7 @@ private: LLUUID mLastTextureIndex; LLTexLayerSet* mTexLayerSet; bool mIsLoaded; - bool mIsUsed; + //bool mIsUsed; // KL SG LLVOAvatarDefines::ETextureIndex mTextureIndex; U32 mMaskTexName; // Stores pointers to the joint meshes that this baked texture deals with diff --git a/linden/indra/newview/llvoclouds.cpp b/linden/indra/newview/llvoclouds.cpp index a489f91..019b6b4 100644 --- a/linden/indra/newview/llvoclouds.cpp +++ b/linden/indra/newview/llvoclouds.cpp @@ -101,7 +101,7 @@ void LLVOClouds::setPixelAreaAndAngle(LLAgent &agent) mPixelArea = 1500*100; } -void LLVOClouds::updateTextures() +void LLVOClouds::updateTextures(LLAgent &agent) { getTEImage(0)->addTextureStats(mPixelArea); } @@ -123,7 +123,10 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) return TRUE; } - dirtySpatialGroup(); + if (drawable->isVisible()) + { + dirtySpatialGroup(TRUE); + } LLFace *facep; diff --git a/linden/indra/newview/llvoclouds.h b/linden/indra/newview/llvoclouds.h index 52e5a68..f70ea5b 100644 --- a/linden/indra/newview/llvoclouds.h +++ b/linden/indra/newview/llvoclouds.h @@ -65,7 +65,7 @@ public: /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. F32 getPartSize(S32 idx); - /*virtual*/ void updateTextures(); + /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area void updateFaceSize(S32 idx) { } diff --git a/linden/indra/newview/llvograss.cpp b/linden/indra/newview/llvograss.cpp index 08f2717..c56d676 100644 --- a/linden/indra/newview/llvograss.cpp +++ b/linden/indra/newview/llvograss.cpp @@ -331,7 +331,7 @@ void LLVOGrass::setPixelAreaAndAngle(LLAgent &agent) // BUG could speed this up by caching the relative_position and range calculations -void LLVOGrass::updateTextures() +void LLVOGrass::updateTextures(LLAgent &agent) { if (getTEImage(0)) { diff --git a/linden/indra/newview/llvograss.h b/linden/indra/newview/llvograss.h index 682fbdb..c55c59b 100644 --- a/linden/indra/newview/llvograss.h +++ b/linden/indra/newview/llvograss.h @@ -72,7 +72,7 @@ public: LLStrider<U16>& indicesp); void updateFaceSize(S32 idx) { } - /*virtual*/ void updateTextures(); + /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ BOOL updateLOD(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area diff --git a/linden/indra/newview/llvoground.cpp b/linden/indra/newview/llvoground.cpp index 0ef0196..fe19e18 100644 --- a/linden/indra/newview/llvoground.cpp +++ b/linden/indra/newview/llvoground.cpp @@ -71,7 +71,7 @@ BOOL LLVOGround::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) } -void LLVOGround::updateTextures() +void LLVOGround::updateTextures(LLAgent &agent) { } diff --git a/linden/indra/newview/llvoground.h b/linden/indra/newview/llvoground.h index b58ebae..f485bd0 100644 --- a/linden/indra/newview/llvoground.h +++ b/linden/indra/newview/llvoground.h @@ -51,7 +51,7 @@ public: // Graphical stuff for objects - maybe broken out into render class // later? - /*virtual*/ void updateTextures(); + /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/linden/indra/newview/llvopartgroup.cpp b/linden/indra/newview/llvopartgroup.cpp index a0f8068..b040366 100644 --- a/linden/indra/newview/llvopartgroup.cpp +++ b/linden/indra/newview/llvopartgroup.cpp @@ -108,7 +108,7 @@ void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent) } } -void LLVOPartGroup::updateTextures() +void LLVOPartGroup::updateTextures(LLAgent &agent) { // Texture stats for particles need to be updated in a different way... } @@ -154,6 +154,11 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) group = drawable->getSpatialGroup(); } + if (group && group->isVisible()) + { + dirtySpatialGroup(TRUE); + } + if (!num_parts) { if (group && drawable->getNumFaces()) @@ -186,13 +191,12 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) S32 count=0; mDepth = 0.f; S32 i = 0 ; - LLVector3 camera_agent = getCameraPosition(); for (i = 0 ; i < (S32)mViewerPartGroupp->mParticles.size(); i++) { const LLViewerPart *part = mViewerPartGroupp->mParticles[i]; LLVector3 part_pos_agent(part->mPosAgent); - LLVector3 at(part_pos_agent - camera_agent); + LLVector3 at(part_pos_agent - LLViewerCamera::getInstance()->getOrigin()); F32 camera_dist_squared = at.lengthSquared(); F32 inv_camera_dist_squared; @@ -315,7 +319,7 @@ void LLVOPartGroup::getGeometry(S32 idx, up *= 0.5f*part.mScale.mV[1]; - LLVector3 normal = -LLViewerCamera::getInstance()->getXAxis(); + const LLVector3& normal = -LLViewerCamera::getInstance()->getXAxis(); *verticesp++ = part_pos_agent + up - right; *verticesp++ = part_pos_agent - up - right; @@ -352,12 +356,12 @@ U32 LLVOPartGroup::getPartitionType() const } LLParticlePartition::LLParticlePartition() -: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK) +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB) { mRenderPass = LLRenderPass::PASS_ALPHA; mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES; mPartitionType = LLViewerRegion::PARTITION_PARTICLE; - mBufferUsage = GL_DYNAMIC_DRAW_ARB; + // mBufferUsage = GL_DYNAMIC_DRAW_ARB; // KL SD hybrid code mSlopRatio = 0.f; mLODPeriod = 1; } @@ -481,7 +485,9 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) U32 end = start + facep->getGeomCount()-1; U32 offset = facep->getIndicesStart(); U32 count = facep->getIndicesCount(); - LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), buffer, fullbright); + LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), + facep->getTexture(), + buffer, fullbright); info->mExtents[0] = group->mObjectExtents[0]; info->mExtents[1] = group->mObjectExtents[1]; info->mVSize = vsize; diff --git a/linden/indra/newview/llvopartgroup.h b/linden/indra/newview/llvopartgroup.h index 18583b4..3dc3292 100644 --- a/linden/indra/newview/llvopartgroup.h +++ b/linden/indra/newview/llvopartgroup.h @@ -61,7 +61,7 @@ public: virtual U32 getPartitionType() const; /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); - /*virtual*/ void updateTextures(); + /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/linden/indra/newview/llvosky.cpp b/linden/indra/newview/llvosky.cpp index d15a2dc..2200c02 100644 --- a/linden/indra/newview/llvosky.cpp +++ b/linden/indra/newview/llvosky.cpp @@ -289,7 +289,7 @@ void LLSkyTex::create(const F32 brightness) void LLSkyTex::createGLImage(S32 which) { - mImageGL[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLViewerImageBoostLevel::OTHER); + mImageGL[which]->createGLTexture(0, mImageRaw[which]); mImageGL[which]->setAddressMode(LLTexUnit::TAM_CLAMP); } @@ -1095,10 +1095,10 @@ BOOL LLVOSky::updateSky() mLastTotalAmbient.mV[2] - mTotalAmbient.mV[2]); if ( mForceUpdate - || ((dot_lighting < LIGHT_DIRECTION_THRESHOLD) + || (((dot_lighting < LIGHT_DIRECTION_THRESHOLD) || (delta_color.length() > COLOR_CHANGE_THRESHOLD) || !mInitialized) - && !direction.isExactlyZero()) + && !direction.isExactlyZero())) { mLastLightingDirection = direction; mLastTotalAmbient = mTotalAmbient; @@ -1180,7 +1180,7 @@ BOOL LLVOSky::updateSky() return TRUE; } -void LLVOSky::updateTextures() +void LLVOSky::updateTextures(LLAgent &agent) { if (mSunTexturep) { diff --git a/linden/indra/newview/llvosky.h b/linden/indra/newview/llvosky.h index dabf5b1..5e23065 100644 --- a/linden/indra/newview/llvosky.h +++ b/linden/indra/newview/llvosky.h @@ -147,7 +147,7 @@ protected: static S32 getResolution() { return sResolution; } static S32 getCurrent() { return sCurrent; } - static S32 stepCurrent() { sCurrent++; sCurrent&=1; return sCurrent; } + static S32 stepCurrent() { return (sCurrent = ++sCurrent % 2); } static S32 getNext() { return ((sCurrent+1) % 2); } static S32 getWhich(const BOOL curr) { return curr ? sCurrent : getNext(); } @@ -492,7 +492,7 @@ public: // Graphical stuff for objects - maybe broken out into render class // later? - /*virtual*/ void updateTextures(); + /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/linden/indra/newview/llvosurfacepatch.cpp b/linden/indra/newview/llvosurfacepatch.cpp index d86f758..a6fc125 100644 --- a/linden/indra/newview/llvosurfacepatch.cpp +++ b/linden/indra/newview/llvosurfacepatch.cpp @@ -134,7 +134,7 @@ void LLVOSurfacePatch::setPixelAreaAndAngle(LLAgent &agent) } -void LLVOSurfacePatch::updateTextures() +void LLVOSurfacePatch::updateTextures(LLAgent &agent) { } @@ -177,11 +177,19 @@ LLDrawable *LLVOSurfacePatch::createDrawable(LLPipeline *pipeline) } +void LLVOSurfacePatch::updateGL() +{ + if (mPatchp) + { + mPatchp->updateGL(); + } +} + BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) { LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TERRAIN); - dirtySpatialGroup(); + dirtySpatialGroup(TRUE); S32 min_comp, max_comp, range; min_comp = lltrunc(mPatchp->getMinComposition()); @@ -1013,12 +1021,12 @@ U32 LLVOSurfacePatch::getPartitionType() const } LLTerrainPartition::LLTerrainPartition() -: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK) +: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, GL_DYNAMIC_DRAW_ARB) { mOcclusionEnabled = FALSE; - mRenderByGroup = FALSE; + //mRenderByGroup = FALSE; // KL not for SD hybrid code mInfiniteFarClip = TRUE; - mBufferUsage = GL_DYNAMIC_DRAW_ARB; + //mBufferUsage = GL_DYNAMIC_DRAW_ARB; // and here too! mDrawableType = LLPipeline::RENDER_TYPE_TERRAIN; mPartitionType = LLViewerRegion::PARTITION_TERRAIN; } diff --git a/linden/indra/newview/llvosurfacepatch.h b/linden/indra/newview/llvosurfacepatch.h index d3b1447..aaf4d41 100644 --- a/linden/indra/newview/llvosurfacepatch.h +++ b/linden/indra/newview/llvosurfacepatch.h @@ -64,6 +64,7 @@ public: virtual U32 getPartitionType() const; /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); + /*virtual*/ void updateGL(); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ BOOL updateLOD(); /*virtual*/ void updateFaceSize(S32 idx); @@ -74,7 +75,7 @@ public: LLStrider<LLVector2> &texCoords1p, LLStrider<U16> &indicesp); - /*virtual*/ void updateTextures(); + /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); diff --git a/linden/indra/newview/llvotextbubble.cpp b/linden/indra/newview/llvotextbubble.cpp index 5943f9b..de69aac 100644 --- a/linden/indra/newview/llvotextbubble.cpp +++ b/linden/indra/newview/llvotextbubble.cpp @@ -116,7 +116,7 @@ BOOL LLVOTextBubble::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) } -void LLVOTextBubble::updateTextures() +void LLVOTextBubble::updateTextures(LLAgent &agent) { // Update the image levels of all textures... diff --git a/linden/indra/newview/llvotextbubble.h b/linden/indra/newview/llvotextbubble.h index 7f84dbf..45d4df2 100644 --- a/linden/indra/newview/llvotextbubble.h +++ b/linden/indra/newview/llvotextbubble.h @@ -44,7 +44,7 @@ public: /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); - /*virtual*/ void updateTextures(); + /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ BOOL updateLOD(); diff --git a/linden/indra/newview/llvotree.cpp b/linden/indra/newview/llvotree.cpp index 208086f..89d6491 100644 --- a/linden/indra/newview/llvotree.cpp +++ b/linden/indra/newview/llvotree.cpp @@ -480,7 +480,7 @@ void LLVOTree::setPixelAreaAndAngle(LLAgent &agent) #endif } -void LLVOTree::updateTextures() +void LLVOTree::updateTextures(LLAgent &agent) { if (mTreeImagep) { @@ -1316,9 +1316,9 @@ U32 LLVOTree::getPartitionType() const } LLTreePartition::LLTreePartition() -: LLSpatialPartition(0) +: LLSpatialPartition(0, FALSE, 0) { - mRenderByGroup = FALSE; + // mRenderByGroup = FALSE; // SD hybrid mDrawableType = LLPipeline::RENDER_TYPE_TREE; mPartitionType = LLViewerRegion::PARTITION_TREE; mSlopRatio = 0.f; diff --git a/linden/indra/newview/llvotree.h b/linden/indra/newview/llvotree.h index 855c612..7804ab3 100644 --- a/linden/indra/newview/llvotree.h +++ b/linden/indra/newview/llvotree.h @@ -69,7 +69,7 @@ public: // Graphical stuff for objects - maybe broken out into render class later? /*virtual*/ void render(LLAgent &agent); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); - /*virtual*/ void updateTextures(); + /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/linden/indra/newview/llvotreenew.h b/linden/indra/newview/llvotreenew.h index 4960d90..02f6d3a 100644 --- a/linden/indra/newview/llvotreenew.h +++ b/linden/indra/newview/llvotreenew.h @@ -156,7 +156,7 @@ public: /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); /*virtual*/ void render(LLAgent &agent); - /*virtual*/ void updateTextures(); + /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/linden/indra/newview/llvovolume.cpp b/linden/indra/newview/llvovolume.cpp index 385dbe0..d4c4020 100644 --- a/linden/indra/newview/llvovolume.cpp +++ b/linden/indra/newview/llvovolume.cpp @@ -54,6 +54,7 @@ #include "llspatialpartition.h" #include "llhudmanager.h" #include "llflexibleobject.h" + #include "llsky.h" #include "lltexturefetch.h" #include "llviewercamera.h" @@ -67,6 +68,9 @@ const S32 MIN_QUIET_FRAMES_COALESCE = 30; const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; const F32 FORCE_CULL_AREA = 8.f; +const F32 MAX_LOD_DISTANCE = 24.f; +const S32 MAX_SCULPT_REZ = 128; + BOOL gAnimateTextures = TRUE; extern BOOL gHideSelectedObjects; @@ -91,6 +95,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mNumFaces = 0; mLODChanged = FALSE; mSculptChanged = FALSE; + mSpotLightPriority = 0.f; } LLVOVolume::~LLVOVolume() @@ -214,7 +219,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, std::string mask; mask = gDirUtilp->getDirDelimiter() + "*.slc"; gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), mask); -// llerrs << "Bogus TE data in " << getID() << ", crashing!" << llendl; +// llwarns << "Bogus TE data in " << getID() << ", crashing!" << llendl; llwarns << "Bogus TE data in " << getID() << llendl; } else if (res2 & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR)) @@ -314,11 +319,6 @@ void LLVOVolume::animateTextures() te->getScale(&scale_s, &scale_t); } - LLVector3 scale(scale_s, scale_t, 1.f); - LLVector3 trans(off_s+0.5f, off_t+0.5f, 0.f); - LLQuaternion quat; - quat.setQuat(rot, 0, 0, -1.f); - if (!facep->mTextureMatrix) { facep->mTextureMatrix = new LLMatrix4(); @@ -326,7 +326,43 @@ void LLVOVolume::animateTextures() LLMatrix4& tex_mat = *facep->mTextureMatrix; tex_mat.setIdentity(); - tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); + LLVector3 trans ; + + if(facep->isAtlasInUse()) + { + // + //if use atlas for animated texture + //apply the following transform to the animation matrix. + // + + F32 tcoord_xoffset = 0.f ; + F32 tcoord_yoffset = 0.f ; + F32 tcoord_xscale = 1.f ; + F32 tcoord_yscale = 1.f ; + if(facep->isAtlasInUse()) + { + const LLVector2* tmp = facep->getTexCoordOffset() ; + tcoord_xoffset = tmp->mV[0] ; + tcoord_yoffset = tmp->mV[1] ; + + tmp = facep->getTexCoordScale() ; + tcoord_xscale = tmp->mV[0] ; + tcoord_yscale = tmp->mV[1] ; + } + trans.set(LLVector3(tcoord_xoffset + tcoord_xscale * (off_s+0.5f), tcoord_yoffset + tcoord_yscale * (off_t+0.5f), 0.f)); + + tex_mat.translate(LLVector3(-(tcoord_xoffset + tcoord_xscale * 0.5f), -(tcoord_yoffset + tcoord_yscale * 0.5f), 0.f)); + } + else //non atlas + { + trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); + tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); + } + + LLVector3 scale(scale_s, scale_t, 1.f); + LLQuaternion quat; + quat.setQuat(rot, 0, 0, -1.f); + tex_mat.rotate(quat); LLMatrix4 mat; @@ -403,30 +439,28 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) return TRUE; } -void LLVOVolume::updateTextures() +void LLVOVolume::updateTextures(LLAgent &agent) // KL sd { const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds - if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) + if (mDrawable.notNull() && mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) { - updateTextureVirtualSize(); + if (mDrawable->isVisible()) + { + updateTextures(); + } } } -void LLVOVolume::updateTextureVirtualSize() +void LLVOVolume::updateTextures() { // Update the pixel area of all faces - if(mDrawable.isNull() || !mDrawable->isVisible()) - { - return ; - } - if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) { return; } - if (LLViewerImage::sDontLoadVolumeTextures || LLAppViewer::getTextureFetch()->mDebugPause) + if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull()) // || !mDrawable->isVisible()) { return; } @@ -443,15 +477,14 @@ void LLVOVolume::updateTextureVirtualSize() LLFace* face = mDrawable->getFace(i); const LLTextureEntry *te = face->getTextureEntry(); LLViewerImage *imagep = face->getTexture(); - if (!imagep || !te || + if (!imagep || !te || face->mExtents[0] == face->mExtents[1]) { continue; } F32 vsize; - F32 old_size = face->getVirtualSize(); - + if (isHUDAttachment()) { F32 area = (F32) LLViewerCamera::getInstance()->getScreenPixelArea(); @@ -461,21 +494,24 @@ void LLVOVolume::updateTextureVirtualSize() } else { - vsize = face->getTextureVirtualSize(); + vsize = getTextureVirtualSize(face); } - mPixelArea = llmax(mPixelArea, face->getPixelArea()); + mPixelArea = llmax(mPixelArea, face->getPixelArea()); + + F32 old_size = face->getVirtualSize(); if (face->mTextureMatrix != NULL) { - if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || - (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) + if (vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE || + vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE); } } face->setVirtualSize(vsize); + // imagep->addTextureStats(vsize); if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { if (vsize < min_vsize) min_vsize = vsize; @@ -503,46 +539,46 @@ void LLVOVolume::updateTextureVirtualSize() mSculptTexture = gImageList.getImage(id); if (mSculptTexture.notNull()) { + S32 lod = llmin(mLOD, 3); + F32 lodf = ((F32)(lod + 1.0f)/4.f); + F32 tex_size = lodf * MAX_SCULPT_REZ; + mSculptTexture->addTextureStats(2.f * tex_size * tex_size); mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), (S32)LLViewerImageBoostLevel::BOOST_SCULPTED)); - mSculptTexture->setForSculpt() ; - - if(!mSculptTexture->isCachedRawImageReady()) - { - S32 lod = llmin(mLOD, 3); - F32 lodf = ((F32)(lod + 1.0f)/4.f); - F32 tex_size = lodf * LLViewerImage::sMaxSculptRez ; - mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); - - //if the sculpty very close to the view point, load first - { - LLVector3 lookAt = getPositionAgent() - LLViewerCamera::getInstance()->getOrigin(); - F32 dist = lookAt.normVec() ; - F32 cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ; - mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ; - } - } - - S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture - S32 current_discard = mSculptLevel; + } - if (texture_discard >= 0 && //texture has some data available - (texture_discard < current_discard || //texture has more data than last rebuild - current_discard < 0)) //no previous rebuild - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - mSculptChanged = TRUE; - } + S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture + S32 current_discard = mSculptLevel; - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) + if (texture_discard >= 0 && //texture has some data available + (texture_discard < current_discard || //texture has more data than last rebuild + current_discard < 0)) //no previous rebuild + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + mSculptChanged = TRUE; + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) { setDebugText(llformat("T%d C%d V%d\n%dx%d", - texture_discard, current_discard, getVolume()->getSculptLevel(), - mSculptTexture->getHeight(), mSculptTexture->getWidth())); + texture_discard, current_discard, getVolume()->getSculptLevel(), + mSculptTexture->getHeight(), mSculptTexture->getWidth())); } - } } + if (getLightTextureID().notNull()) + { + LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + LLUUID id = params->getLightTexture(); + mLightTexture = gImageList.getImage(id); + if (mLightTexture.notNull()) + { + F32 rad = getLightRadius(); + mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(), + LLVector3(rad,rad,rad), + *LLViewerCamera::getInstance())); + } + } if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { @@ -563,6 +599,36 @@ void LLVOVolume::updateTextureVirtualSize() } } +F32 LLVOVolume::getTextureVirtualSize(LLFace* face) +{ + //get area of circle around face + LLVector3 center = face->getPositionAgent(); + LLVector3 size = (face->mExtents[1] - face->mExtents[0]) * 0.5f; + + F32 face_area = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance()); + + face->setPixelArea(face_area); + + if (face_area <= 0) + { + return 0.f; + } + + //get area of circle in texture space + LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0]; + F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f; + if (texel_area <= 0) + { + // Probably animated, use default + texel_area = 1.f; + } + + //apply texel area to face area to get accurate ratio + face_area /= llclamp(texel_area, 1.f/64.f, 16.f); + + return face_area; +} + BOOL LLVOVolume::isActive() const { return !mStatic || mTextureAnimp || (mVolumeImpl && mVolumeImpl->isActive()); @@ -699,21 +765,31 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail // sculpt replaces generate() for sculpted surfaces void LLVOVolume::sculpt() -{ +{ + U16 sculpt_height = 0; + U16 sculpt_width = 0; + S8 sculpt_components = 0; + const U8* sculpt_data = NULL; + if (mSculptTexture.notNull()) - { - U16 sculpt_height = 0; - U16 sculpt_width = 0; - S8 sculpt_components = 0; - const U8* sculpt_data = NULL; - - S32 discard_level = mSculptTexture->getCachedRawImageLevel() ; - LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; + { + S32 discard_level; + S32 desired_discard = 0; // lower discard levels have MUCH less resolution + + discard_level = desired_discard; S32 max_discard = mSculptTexture->getMaxDiscardLevel(); if (discard_level > max_discard) discard_level = max_discard; // clamp to the best we can do + S32 best_discard = mSculptTexture->getDiscardLevel(); + if (discard_level < best_discard) + discard_level = best_discard; // clamp to what we have + + if (best_discard == -1) + discard_level = -1; // and if we have nothing, set to nothing + + S32 current_discard = getVolume()->getSculptLevel(); if(current_discard < -2) { @@ -735,17 +811,28 @@ void LLVOVolume::sculpt() if (current_discard == discard_level) // no work to do here return; - if(!raw_image) + LLPointer<LLImageRaw> raw_image = new LLImageRaw(); + BOOL is_valid = mSculptTexture->readBackRaw(discard_level, raw_image, FALSE); + + sculpt_height = raw_image->getHeight(); + sculpt_width = raw_image->getWidth(); + sculpt_components = raw_image->getComponents(); + + if(is_valid) + { + is_valid = mSculptTexture->isValidForSculpt(discard_level, sculpt_width, sculpt_height, sculpt_components) ; + } + if(!is_valid) { sculpt_width = 0; sculpt_height = 0; sculpt_data = NULL ; } else - { - sculpt_height = raw_image->getHeight(); - sculpt_width = raw_image->getWidth(); - sculpt_components = raw_image->getComponents(); + { + if (raw_image->getDataSize() < sculpt_height * sculpt_width * sculpt_components) + llwarns << "Sculpt: image data size = " << raw_image->getDataSize() + << " < " << sculpt_height << " x " << sculpt_width << " x " <<sculpt_components << llendl; sculpt_data = raw_image->getData(); } @@ -777,7 +864,7 @@ BOOL LLVOVolume::calcLOD() } //update face texture sizes on lod calculation - updateTextureVirtualSize(); + // updateTextureVirtualSize(); S32 cur_detail = 0; @@ -1231,28 +1318,15 @@ S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color) S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) { - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) + S32 res = LLViewerObject::setTEColor(te, color); + if (res && mDrawable.notNull()) { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; + //gPipeline.markTextured(mDrawable); + mDrawable->setState(LLDrawable::REBUILD_COLOR); + dirtyMesh(); + //mFaceMappingChanged = TRUE; } - else if (color != tep->getColor()) - { - if (color.mV[3] != tep->getColor().mV[3]) - { - gPipeline.markTextured(mDrawable); - } - retval = LLPrimitive::setTEColor(te, color); - if (mDrawable.notNull() && retval) - { - // These should only happen on updates which are not the initial update. - mDrawable->setState(LLDrawable::REBUILD_COLOR); - dirtyMesh(); - } - } - - return retval; + return res; } S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap) @@ -1318,7 +1392,7 @@ S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump) gPipeline.markTextured(mDrawable); mFaceMappingChanged = TRUE; } - return res; + return res; } S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags) @@ -1387,6 +1461,40 @@ void LLVOVolume::updateTEData() //---------------------------------------------------------------------------- +void LLVOVolume::setLightTextureID(LLUUID id) +{ + if (id.notNull()) + { + if (!hasLightTexture()) + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true); + } + LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block && param_block->getLightTexture() != id) + { + param_block->setLightTexture(id); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + } + } + else + { + if (hasLightTexture()) + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); + } + } +} + +void LLVOVolume::setSpotLightParams(LLVector3 params) +{ + LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block && param_block->getParams() != params) + { + param_block->setParams(params); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + } +} + void LLVOVolume::setIsLight(BOOL is_light) { if (is_light != getIsLight()) @@ -1513,6 +1621,77 @@ LLColor3 LLVOVolume::getLightColor() const } } +LLUUID LLVOVolume::getLightTextureID() const +{ + const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block) + { + return param_block->getLightTexture(); + } + + return LLUUID::null; +} + + +LLVector3 LLVOVolume::getSpotLightParams() const +{ + const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block) + { + return param_block->getParams(); + } + + return LLVector3(); +} + +F32 LLVOVolume::getSpotLightPriority() const +{ + return mSpotLightPriority; +} + +void LLVOVolume::updateSpotLightPriority() +{ + LLVector3 pos = mDrawable->getPositionAgent(); + LLVector3 at(0,0,-1); + at *= getRenderRotation(); + + F32 r = getLightRadius()*0.5f; + + pos += at * r; + + at = LLViewerCamera::getInstance()->getAtAxis(); + + pos -= at * r; + + mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); + // KL needed for S19? + if (mLightTexture.notNull()) + { + mLightTexture->addTextureStats(mSpotLightPriority); + mLightTexture->setBoostLevel(LLViewerImageBoostLevel::BOOST_CLOUDS); + } +} + + +LLViewerImage* LLVOVolume::getLightTexture() +{ + LLUUID id = getLightTextureID(); + + if (id.notNull()) + { + if (mLightTexture.isNull() || id != mLightTexture->getID()) + { + mLightTexture = gImageList.getImage(id); + } + } + else + { + mLightTexture = NULL; + } + + return mLightTexture; +} + F32 LLVOVolume::getLightIntensity() const { const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); @@ -1604,6 +1783,16 @@ BOOL LLVOVolume::isSculpted() const return FALSE; } +BOOL LLVOVolume::hasLightTexture() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + return TRUE; + } + + return FALSE; +} + BOOL LLVOVolume::isVolumeGlobal() const { if (mVolumeImpl) @@ -2056,9 +2245,9 @@ U32 LLVOVolume::getPartitionType() const } LLVolumePartition::LLVolumePartition() -: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, FALSE) +: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB) // KL { - mLODPeriod = 16; + mLODPeriod = 32; // KL 32 in SD mDepthMask = FALSE; mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; mPartitionType = LLViewerRegion::PARTITION_VOLUME; @@ -2067,10 +2256,10 @@ LLVolumePartition::LLVolumePartition() } LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep) -: LLSpatialBridge(drawablep, LLVOVolume::VERTEX_DATA_MASK) +: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK) // KL SD { mDepthMask = FALSE; - mLODPeriod = 16; + mLODPeriod = 32; // KL 32 in SD mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; mPartitionType = LLViewerRegion::PARTITION_BRIDGE; @@ -2125,7 +2314,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U8 bump = (type == LLRenderPass::PASS_BUMP ? facep->getTextureEntry()->getBumpmap() : 0); - LLViewerImage* tex = facep->getTexture(); + LLImageGL* tex = facep->getGLTexture(); // LLViewerImage* tex = facep->getTexture(); // KL SD U8 glow = 0; @@ -2136,7 +2325,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, if (facep->mVertexBuffer.isNull()) { - llerrs << "WTF?" << llendl; + llwarns << "WTF?" << llendl; } if (idx >= 0 && @@ -2167,6 +2356,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 offset = facep->getIndicesStart(); U32 count = facep->getIndicesCount(); LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset,tex, + (LLImageGL*)facep->getTexture() == tex ? facep->getTexture() : NULL, facep->mVertexBuffer, fullbright, bump); draw_info->mGroup = group; draw_info->mVSize = facep->getVirtualSize(); @@ -2254,9 +2444,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) LLVOVolume* vobj = drawablep->getVOVolume(); llassert_always(vobj); - vobj->updateTextureVirtualSize(); + vobj->updateTextures(); vobj->preRebuild(); + drawablep->clearState(LLDrawable::HAS_ALPHA); // KL SD + //for each face for (S32 i = 0; i < drawablep->getNumFaces(); i++) { @@ -2325,6 +2517,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } else { + drawablep->setState(LLDrawable::HAS_ALPHA); // KL SD alpha_faces.push_back(facep); } } @@ -2348,7 +2541,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } else { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); + //facep->setState(LLFace::FULLBRIGHT); fullbright_faces.push_back(facep); } } @@ -2358,14 +2551,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //needs normal + binormal bump_faces.push_back(facep); } - else if ((te->getShiny() && LLPipeline::sRenderBump) || + else if (te->getShiny() && LLPipeline::sRenderBump || !te->getFullbright()) { //needs normal simple_faces.push_back(facep); } else { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); + // facep->setState(LLFace::FULLBRIGHT); fullbright_faces.push_back(facep); } } @@ -2413,7 +2606,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (LLPipeline::sDelayVBUpdate) { - group->setState(LLSpatialGroup::MESH_DIRTY); + group->setState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); // KL SD } mFaceList.clear(); @@ -2421,7 +2614,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { - if (group->isState(LLSpatialGroup::MESH_DIRTY)) + if (group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY)) // KL SD { S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ; @@ -2499,7 +2692,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) } } - group->clearState(LLSpatialGroup::MESH_DIRTY); + group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); // KL SD } } @@ -2524,7 +2717,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: LLSpatialGroup::buffer_map_t buffer_map; - LLViewerImage* last_tex = NULL; + LLImageGL* last_tex = NULL;// LLViewerImage* last_tex = NULL; // KL SD S32 buffer_index = 0; if (distance_sort) @@ -2536,7 +2729,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: { //pull off next face LLFace* facep = *face_iter; - LLViewerImage* tex = facep->getTexture(); + LLImageGL* tex = facep->getGLTexture(); // LLViewerImage* tex = facep->getTexture(); // KL SD if (distance_sort) { @@ -2561,7 +2754,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: ++i; while (i != faces.end() && - (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) + (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getGLTexture() == tex))) // KL SD getTexture { facep = *i; @@ -2644,6 +2837,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA; BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); + if ((mask & LLVertexBuffer::MAP_NORMAL) == 0) // KL SD + { //paranoia check to make sure GL doesn't try to read non-existant normals + fullbright = TRUE; + } + const LLTextureEntry* te = facep->getTextureEntry(); BOOL is_alpha = facep->getPoolType() == LLDrawPool::POOL_ALPHA ? TRUE : FALSE; @@ -2695,7 +2893,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } else { - llassert(mask & LLVertexBuffer::MAP_NORMAL); + // llassert(mask & LLVertexBuffer::MAP_NORMAL); registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } } @@ -2726,7 +2924,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } else { - llassert(mask & LLVertexBuffer::MAP_NORMAL); + // llassert(mask & LLVertexBuffer::MAP_NORMAL); registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } } @@ -2739,8 +2937,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: if (!is_alpha && !LLPipeline::sRenderDeferred) { - llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); - facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); + // llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); + facep->setPoolType(LLDrawPool::POOL_SIMPLE); // facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); if (!force_simple && te->getBumpmap()) { @@ -2819,7 +3017,7 @@ LLHUDPartition::LLHUDPartition() mPartitionType = LLViewerRegion::PARTITION_HUD; mDrawableType = LLPipeline::RENDER_TYPE_HUD; mSlopRatio = 0.f; - mLODPeriod = 1; + mLODPeriod = 32; // KL 32 in SD } void LLHUDPartition::shift(const LLVector3 &offset) diff --git a/linden/indra/newview/llvovolume.h b/linden/indra/newview/llvovolume.h index a78aa37..4c6ad9a 100644 --- a/linden/indra/newview/llvovolume.h +++ b/linden/indra/newview/llvovolume.h @@ -130,7 +130,7 @@ public: BOOL getVolumeChanged() const { return mVolumeChanged; } - + F32 getTextureVirtualSize(LLFace* face); /*virtual*/ F32 getRadius() const { return mVObjRadius; }; const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; @@ -158,14 +158,14 @@ public: /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump); /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny); /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright); - /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump); + /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump); // KL S19? /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags); /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t); /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s); /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t); /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen); - /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media); + /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media); // KL S19 /*virtual*/ BOOL setMaterial(const U8 material); void setTexture(const S32 face); @@ -177,8 +177,8 @@ public: /*virtual*/ void updateFaceSize(S32 idx); /*virtual*/ BOOL updateLOD(); void updateRadius(); - /*virtual*/ void updateTextures(); - void updateTextureVirtualSize(); + /*virtual*/ void updateTextures(LLAgent &agent); + void updateTextures(); void updateFaceFlags(); void regenFaces(); @@ -196,9 +196,18 @@ public: void setLightRadius(F32 radius); void setLightFalloff(F32 falloff); void setLightCutoff(F32 cutoff); + void setLightTextureID(LLUUID id); + void setSpotLightParams(LLVector3 params); + BOOL getIsLight() const; LLColor3 getLightBaseColor() const; // not scaled by intensity LLColor3 getLightColor() const; // scaled by intensity + LLUUID getLightTextureID() const; + LLVector3 getSpotLightParams() const; + void updateSpotLightPriority(); + F32 getSpotLightPriority() const; + + LLViewerImage* getLightTexture(); F32 getLightIntensity() const; F32 getLightRadius() const; F32 getLightFalloff() const; @@ -208,6 +217,8 @@ public: U32 getVolumeInterfaceID() const; virtual BOOL isFlexible() const; virtual BOOL isSculpted() const; + virtual BOOL hasLightTexture() const; + BOOL isVolumeGlobal() const; BOOL canBeFlexible() const; BOOL setIsFlexible(BOOL is_flexible); @@ -233,12 +244,14 @@ private: BOOL mLODChanged; S32 mSculptLevel; BOOL mSculptChanged; + F32 mSpotLightPriority; LLMatrix4 mRelativeXform; LLMatrix3 mRelativeXformInvTrans; BOOL mVolumeChanged; F32 mVObjRadius; LLVolumeInterface *mVolumeImpl; LLPointer<LLViewerImage> mSculptTexture; + LLPointer<LLViewerImage> mLightTexture; // statics public: diff --git a/linden/indra/newview/llvowater.cpp b/linden/indra/newview/llvowater.cpp index 5b6a949..25960de 100644 --- a/linden/indra/newview/llvowater.cpp +++ b/linden/indra/newview/llvowater.cpp @@ -101,7 +101,7 @@ void LLVOWater::setPixelAreaAndAngle(LLAgent &agent) // virtual -void LLVOWater::updateTextures() +void LLVOWater::updateTextures(LLAgent &agent) { } @@ -276,9 +276,9 @@ U32 LLVOWater::getPartitionType() const } LLWaterPartition::LLWaterPartition() -: LLSpatialPartition(0) +: LLSpatialPartition(0, FALSE, 0) { - mRenderByGroup = FALSE; + // mRenderByGroup = FALSE; // KL specified const SG branch not req here mInfiniteFarClip = TRUE; mDrawableType = LLPipeline::RENDER_TYPE_WATER; mPartitionType = LLViewerRegion::PARTITION_WATER; diff --git a/linden/indra/newview/llvowater.h b/linden/indra/newview/llvowater.h index 9c33e74..cdda48f 100644 --- a/linden/indra/newview/llvowater.h +++ b/linden/indra/newview/llvowater.h @@ -68,7 +68,7 @@ public: /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); - /*virtual*/ void updateTextures(); + /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area virtual U32 getPartitionType() const; diff --git a/linden/indra/newview/llwaterparammanager.cpp b/linden/indra/newview/llwaterparammanager.cpp index e01506e..8ef11be 100644 --- a/linden/indra/newview/llwaterparammanager.cpp +++ b/linden/indra/newview/llwaterparammanager.cpp @@ -407,8 +407,7 @@ void LLWaterParamManager::update(LLViewerCamera * cam) LLFloaterWater::instance()->syncMenu(); } - stop_glerror(); - + //stop_glerror(); // only do this if we're dealing with shaders if(gPipeline.canUseVertexShaders()) { diff --git a/linden/indra/newview/llwlparammanager.cpp b/linden/indra/newview/llwlparammanager.cpp index 31471d7..09f7d01 100644 --- a/linden/indra/newview/llwlparammanager.cpp +++ b/linden/indra/newview/llwlparammanager.cpp @@ -539,8 +539,7 @@ void LLWLParamManager::update(LLViewerCamera * cam) F32 camYaw = cam->getYaw(); - stop_glerror(); - + //stop_glerror(); // *TODO: potential optimization - this block may only need to be // executed some of the time. For example for water shaders only. { diff --git a/linden/indra/newview/llworld.h b/linden/indra/newview/llworld.h index 46aefd9..9abb565 100644 --- a/linden/indra/newview/llworld.h +++ b/linden/indra/newview/llworld.h @@ -2,7 +2,7 @@ * @file llworld.h * @brief Collection of viewer regions in the vacinity of the user. * - * Represents the whole world, so far as 3D functionality is conserned. + * Represents the whole world, so far as 3D functionality is concerned. * Always contains the region that the user's avatar is in along with * neighboring regions. As the user crosses region boundaries, new * regions are added to the world and distant ones are rolled up. @@ -151,7 +151,8 @@ public: public: typedef std::list<LLViewerRegion*> region_list_t; - const region_list_t& getRegionList() const { return mActiveRegionList; } + region_list_t mActiveRegionList; // KL SD branch public not private + region_list_t& getRegionList() { return mActiveRegionList; } // Returns lists of avatar IDs and their world-space positions within a given distance of a point. // All arguments are optional. Given containers will be emptied and then filled. @@ -162,7 +163,6 @@ public: const LLVector3d& relative_to = LLVector3d(), F32 radius = FLT_MAX) const; private: - region_list_t mActiveRegionList; region_list_t mRegionList; region_list_t mVisibleRegionList; region_list_t mCulledRegionList; diff --git a/linden/indra/newview/pipeline.cpp b/linden/indra/newview/pipeline.cpp index 72da3c6..4bf53af 100644 --- a/linden/indra/newview/pipeline.cpp +++ b/linden/indra/newview/pipeline.cpp @@ -159,6 +159,8 @@ std::string gPoolNames[] = "POOL_ALPHA", }; +void drawBox(const LLVector3& c, const LLVector3& r); + U32 nhpo2(U32 v) { U32 r = 1; @@ -267,11 +269,11 @@ static const U32 gl_cube_face[] = void validate_framebuffer_object(); + void addDeferredAttachments(LLRenderTarget& target) { - target.addColorAttachment(GL_RGBA16F_ARB); //specular - target.addColorAttachment(GL_RGBA16F_ARB); //normal+z - target.addColorAttachment(GL_RGBA16F_ARB); //position + target.addColorAttachment(GL_RGBA); //specular //target.addColorAttachment(GL_RGBA16F_ARB); //specular // KL + target.addColorAttachment(GL_RGBA); //normal+z //target.addColorAttachment(GL_RGBA16F_ARB); //normal+z } LLPipeline::LLPipeline() : @@ -313,6 +315,8 @@ LLPipeline::LLPipeline() : mLightingDetail(0) { mNoiseMap = 0; + //mTrueNoiseMap = 0; // KL SD + mLightFunc = 0; // KL SD } void LLPipeline::init() @@ -362,6 +366,11 @@ void LLPipeline::init() LLViewerShaderMgr::instance()->setShaders(); stop_glerror(); + + for (U32 i = 0; i < 2; ++i) + { + mSpotLightFade[i] = 1.f; + } } LLPipeline::~LLPipeline() @@ -373,6 +382,9 @@ void LLPipeline::cleanup() { assertInitialized(); + mGroupQ1.clear() ; + mGroupQ2.clear() ; + for(pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ) { @@ -469,33 +481,69 @@ void LLPipeline::resizeScreenTexture() GLuint resX = gViewerWindow->getWindowDisplayWidth(); GLuint resY = gViewerWindow->getWindowDisplayHeight(); - U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor"); - if (res_mod > 1 && res_mod < resX && res_mod < resY) - { - resX /= res_mod; - resY /= res_mod; - } - allocateScreenBuffer(resX,resY); - - llinfos << "RESIZED SCREEN TEXTURE: " << resX << "x" << resY << llendl; } } void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) { + U32 samples = gSavedSettings.getU32("RenderFSAASamples"); + U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor"); + + if (res_mod > 1 && res_mod < resX && res_mod < resY) + { + resX /= res_mod; + resY /= res_mod; + } + + if (gSavedSettings.getBOOL("RenderUIBuffer")) + { + //mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + } + if (LLPipeline::sRenderDeferred) { //allocate deferred rendering color buffers - mDeferredScreen.allocate(resX, resY, GL_RGBA16F_ARB, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); addDeferredAttachments(mDeferredScreen); - mScreen.allocate(resX, resY, GL_RGBA16F_ARB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); - + + // always set viewport to desired size, since allocate resets the viewport + + mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + + for (U32 i = 0; i < 3; i++) + { + mDeferredLight[i].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + } + for (U32 i = 0; i < 2; i++) { - mDeferredLight[i].allocate(resX, resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + } + + F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale"); + + for (U32 i = 0; i < 4; i++) + { + mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE); } + + + U32 width = nhpo2(U32(resX*scale))/2; + U32 height = width; + + for (U32 i = 4; i < 6; i++) + { + mShadow[i].allocate(width, height, 0, TRUE, FALSE); + } + + + + width = nhpo2(resX)/2; + height = nhpo2(resY)/2; + mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE); } else { @@ -505,25 +553,23 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) if (gGLManager.mHasFramebufferMultisample && samples > 1) { + mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); if (LLPipeline::sRenderDeferred) { - mSampleBuffer.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); addDeferredAttachments(mSampleBuffer); mDeferredScreen.setSampleBuffer(&mSampleBuffer); } - else - { - mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); - } mScreen.setSampleBuffer(&mSampleBuffer); + stop_glerror(); } - else if (LLPipeline::sRenderDeferred) + + if (LLPipeline::sRenderDeferred) { //share depth buffer between deferred targets mDeferredScreen.shareDepthBuffer(mScreen); - for (U32 i = 0; i < 2; i++) - { + for (U32 i = 0; i < 3; i++) + { //share stencil buffer with screen space lightmap to stencil out sky mDeferredScreen.shareDepthBuffer(mDeferredLight[i]); } } @@ -556,17 +602,40 @@ void LLPipeline::releaseGLBuffers() mNoiseMap = 0; } +/* if (mTrueNoiseMap) + { + LLImageGL::deleteTextures(1, &mTrueNoiseMap); + mTrueNoiseMap = 0; + } +*/ + if (mLightFunc) + { + LLImageGL::deleteTextures(1, &mLightFunc); + mLightFunc = 0; + } + mWaterRef.release(); mWaterDis.release(); mScreen.release(); mSampleBuffer.releaseSampleBuffer(); mDeferredScreen.release(); + mDeferredDepth.release(); + for (U32 i = 0; i < 3; i++) + { + mDeferredLight[i].release(); + } + + mGIMap.release(); + mGIMapPost[0].release(); + mGIMapPost[1].release(); + mHighlight.release(); +// mLuminanceMap.release(); - - for (U32 i = 0; i < 4; i++) + for (U32 i = 0; i < 6; i++) // KL 6 in SD { - mSunShadow[i].release(); + mShadow[i].release(); } + for (U32 i = 0; i < 3; i++) { mGlow[i].release(); @@ -589,9 +658,13 @@ void LLPipeline::createGLBuffers() mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE); } + mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE); stop_glerror(); + GLuint resX = gViewerWindow->getWindowDisplayWidth(); + GLuint resY = gViewerWindow->getWindowDisplayHeight(); + if (LLPipeline::sRenderGlow) { //screen space glow buffers const U32 glow_res = llmax(1, @@ -601,20 +674,13 @@ void LLPipeline::createGLBuffers() { mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE); } - } - GLuint resX = gViewerWindow->getWindowDisplayWidth(); - GLuint resY = gViewerWindow->getWindowDisplayHeight(); - - allocateScreenBuffer(resX,resY); + allocateScreenBuffer(resX,resY); + } + if (sRenderDeferred) { - mSunShadow[0].allocate(1024,1024, 0, TRUE, FALSE); - mSunShadow[1].allocate(1024,1024, 0, TRUE, FALSE); - mSunShadow[2].allocate(1024,1024, 0, TRUE, FALSE); - mSunShadow[3].allocate(1024,1024, 0, TRUE, FALSE); - if (!mNoiseMap) { const U32 noiseRes = 128; @@ -634,7 +700,83 @@ void LLPipeline::createGLBuffers() 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_ALPHA, lightResX, lightResY, GL_ALPHA, GL_UNSIGNED_BYTE, lg); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); + + delete [] lg; +/* } + + if (gSavedSettings.getBOOL("RenderDeferredGI")) + { */ + mGIMap.allocate(1024,1024,GL_RGBA, TRUE, FALSE); + addDeferredAttachments(mGIMap); + + { + LLGLDepthTest depth(GL_TRUE); + gGL.setColorMask(true, true); + for (U32 i = 0; i < 2; i++) + { + mGIMapPost[i].allocate(128,128,GL_RGB16F_ARB, FALSE, FALSE); + mGIMapPost[i].addColorAttachment(GL_RGB16F_ARB); + mGIMapPost[i].addColorAttachment(GL_RGB16F_ARB); + mGIMapPost[i].addColorAttachment(GL_RGB16F_ARB); + + mGIMapPost[i].bindTarget(); + mGIMapPost[i].clear(); + mGIMapPost[i].flush(); + } + } + } + } //mLuminanceMap.allocate(128,128, GL_RGBA, FALSE, FALSE); } void LLPipeline::restoreGL() @@ -646,7 +788,7 @@ void LLPipeline::restoreGL() LLViewerShaderMgr::instance()->setShaders(); } - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -700,7 +842,7 @@ void LLPipeline::unloadShaders() void LLPipeline::assertInitializedDoError() { - llerrs << "LLPipeline used when uninitialized." << llendl; + llwarns << "LLPipeline used when uninitialized." << llendl; } //============================================================================ @@ -763,7 +905,7 @@ public: for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) { LLDrawInfo* params = *j; - if (mTextures.find(params->mTexture) != mTextures.end()) + if (mTextures.find(params->mViewerTexture) != mTextures.end()) { group->setState(LLSpatialGroup::GEOM_DIRTY); } @@ -797,7 +939,7 @@ void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerImage*>& texture } LLOctreeDirtyTexture dirty(textures); - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -876,7 +1018,7 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0) default: llassert(0); - llerrs << "Invalid Pool Type in LLPipeline::findPool() type=" << type << llendl; + llwarns << "Invalid Pool Type in LLPipeline::findPool() type=" << type << llendl; break; } @@ -991,7 +1133,7 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) #ifdef LL_RELEASE_FOR_DOWNLOAD llwarns << "Couldn't remove object from spatial group!" << llendl; #else - llerrs << "Couldn't remove object from spatial group!" << llendl; + llwarns << "Couldn't remove object from spatial group!" << llendl; #endif } } @@ -1006,6 +1148,31 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) break; } } + + { + 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) @@ -1062,7 +1229,7 @@ void LLPipeline::createObject(LLViewerObject* vobj) } else { - llerrs << "Redundant drawable creation!" << llendl; + llwarns << "Redundant drawable creation!" << llendl; } llassert(drawablep); @@ -1123,7 +1290,7 @@ void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep) } if (!drawablep) { - llerrs << "updateMove called with NULL drawablep" << llendl; + llwarns << "updateMove called with NULL drawablep" << llendl; return; } if (drawablep->isState(LLDrawable::EARLY_MOVE)) @@ -1153,7 +1320,8 @@ void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep) } if (!drawablep) { - llerrs << "updateMove called with NULL drawablep" << llendl; + llwarns << "updateMove called with NULL drawablep" << llendl; + return; } if (drawablep->isState(LLDrawable::EARLY_MOVE)) { @@ -1245,7 +1413,7 @@ void LLPipeline::updateMove() { LLFastTimer ot(LLFastTimer::FTM_OCTREE_BALANCE); - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -1272,7 +1440,6 @@ F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera F32 dist = lookAt.length(); //ramp down distance for nearby objects - //shrink dist by dist/16. if (dist < 16.f) { dist /= 16.f; @@ -1293,7 +1460,7 @@ void LLPipeline::grabReferences(LLCullResult& result) BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera) { - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -1325,7 +1492,7 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& BOOL res = TRUE; - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -1388,7 +1555,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl LLGLDepthTest depth(GL_TRUE, GL_FALSE); - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -1465,7 +1632,7 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) group->setVisible(); - if (!sSkipUpdate) + if (!sSkipUpdate) // && !sShadowRender) KL? { group->updateDistance(camera); } @@ -1556,6 +1723,78 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) return update_complete; } +void LLPipeline::updateGL() // KL SD +{ + while (!LLGLUpdate::sGLQ.empty()) + { + LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); + glu->updateGL(); + glu->mInQ = FALSE; + LLGLUpdate::sGLQ.pop_front(); + } +} // KL updateGL SD + +void LLPipeline::rebuildPriorityGroups() +{ + LLTimer update_timer; + LLMemType mt(LLMemType::MTYPE_PIPELINE); + + assertInitialized(); + + // Iterate through all drawables on the priority build queue, + for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin(); + iter != mGroupQ1.end(); ++iter) + { + LLSpatialGroup* group = *iter; + group->rebuildGeom(); + group->clearState(LLSpatialGroup::IN_BUILD_Q1); + } + + mGroupQ1.clear(); +} + +void LLPipeline::rebuildGroups() +{ + // 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()); // KL + + LLSpatialGroup::sg_vector_t::iterator iter; + for (iter = mGroupQ2.begin(); + iter != mGroupQ2.end(); ++iter) + { + LLSpatialGroup* group = *iter; + + if (group->isDead()) + { + continue; + } + + group->rebuildGeom(); + + if (group->mSpatialPartition->mRenderByGroup) + { + count++; + } + + group->clearState(LLSpatialGroup::IN_BUILD_Q2); + + if (count > min_count) + { + ++iter; + break; + } + } + + mGroupQ2.erase(mGroupQ2.begin(), iter); + + updateMovedList(mMovedBridge); +} + void LLPipeline::updateGeom(F32 max_dtime) { LLTimer update_timer; @@ -1670,6 +1909,16 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera) if (drawablep->isSpatialBridge()) { + LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable; + + if (root && root->getParent() && root->getVObj() && root->getVObj()->isAttachment()) + { + LLVOAvatar* av = root->getParent()->getVObj()->asAvatar(); + if (av->isImpostor()) + { + return; + } + } sCull->pushBridge((LLSpatialBridge*) drawablep); } else @@ -1686,7 +1935,7 @@ void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion) if (!drawablep) { - //llerrs << "Sending null drawable to moved list!" << llendl; + //llwarns << "Sending null drawable to moved list!" << llendl; return; } @@ -1771,7 +2020,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) } mShiftList.resize(0); - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -1799,6 +2048,54 @@ void LLPipeline::markTextured(LLDrawable *drawablep) } } +void LLPipeline::markGLRebuild(LLGLUpdate* glu) +{ + if (glu && !glu->mInQ) + { + LLGLUpdate::sGLQ.push_back(glu); + glu->mInQ = TRUE; + } +} + +void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) +{ + LLMemType mt(LLMemType::MTYPE_PIPELINE); + //assert_main_thread(); + + if (group && !group->isDead() && group->mSpatialPartition) + { + if (priority) + { + if (!group->isState(LLSpatialGroup::IN_BUILD_Q1)) + { + 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)) + { + //llwarns << "Non-priority updates not yet supported!" << llendl; + if (std::find(mGroupQ2.begin(), mGroupQ2.end(), group) != mGroupQ2.end()) + { + llwarns << "WTF?" << llendl; + } + 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); @@ -1853,12 +2150,13 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) grabReferences(result); + //if (!LLPipeline::sShadowRender) { for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; group->checkOcclusion(); - if (sUseOcclusion && group->isState(LLSpatialGroup::OCCLUDED)) + if (sUseOcclusion > 1 && group->isState(LLSpatialGroup::OCCLUDED)) { markOccluder(group); } @@ -1871,12 +2169,15 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } } } + } + if (!LLPipeline::sShadowRender) + { for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; group->checkOcclusion(); - if (sUseOcclusion && group->isState(LLSpatialGroup::OCCLUDED)) + if (sUseOcclusion > 1 && group->isState(LLSpatialGroup::OCCLUDED)) { markOccluder(group); } @@ -1888,6 +2189,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } } + if (!LLPipeline::sShadowRender) { for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { @@ -1939,7 +2241,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera) { LLMemType mt(LLMemType::MTYPE_PIPELINE); - if (!sSkipUpdate && bridge->getSpatialGroup()->changeLOD()) + if (!sSkipUpdate && !sShadowRender && bridge->getSpatialGroup()->changeLOD()) { bool force_update = false; bridge->updateDistance(camera, force_update); @@ -2001,41 +2303,46 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) } } - LLSpatialGroup* group = drawablep->getSpatialGroup(); - if (!group || group->changeLOD()) + if (!sShadowRender) { - if (drawablep->isVisible() && !sSkipUpdate) + LLSpatialGroup* group = drawablep->getSpatialGroup(); + if (!group || group->changeLOD()) { - if (!drawablep->isActive()) + if (drawablep->isVisible() && !sSkipUpdate) { - bool force_update = false; - drawablep->updateDistance(camera, force_update); + if (!drawablep->isActive()) + { + drawablep->updateDistance(camera, TRUE); + } + else if (drawablep->isAvatar()) + { + drawablep->updateDistance(camera, TRUE); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility() + } } - else if (drawablep->isAvatar()) - { - bool force_update = false; - drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility() - } } } - for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin(); - iter != drawablep->mFaces.end(); iter++) + if (!drawablep->getVOVolume()) { - LLFace* facep = *iter; - - if (facep->hasGeometry()) + for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin(); + iter != drawablep->mFaces.end(); iter++) { - if (facep->getPool()) - { - facep->getPool()->enqueue(facep); - } - else + LLFace* facep = *iter; + + if (facep->hasGeometry()) { - break; + if (facep->getPool()) + { + facep->getPool()->enqueue(facep); + } + else + { + break; + } } } } + mNumVisibleFaces += drawablep->getNumFaces(); } @@ -2201,7 +2508,7 @@ void LLPipeline::postSort(LLCamera& camera) //rebuild groups sCull->assertDrawMapsEmpty(); - LLSpatialGroup::sNoDelete = FALSE; + /*LLSpatialGroup::sNoDelete = FALSE; for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { LLSpatialGroup* group = *i; @@ -2213,8 +2520,10 @@ void LLPipeline::postSort(LLCamera& camera) group->rebuildGeom(); } - LLSpatialGroup::sNoDelete = TRUE; + LLSpatialGroup::sNoDelete = TRUE;*/ + + rebuildPriorityGroups(); const S32 bin_count = 1024*8; @@ -2240,39 +2549,51 @@ void LLPipeline::postSort(LLCamera& camera) { 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) { sCull->pushDrawInfo(j->first, *k); } } - 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 (!sSkipUpdate) - { - if (bridge) + 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 (!sSkipUpdate) { - LLCamera trans_camera = bridge->transformCamera(camera); - group->updateDistance(trans_camera); + if (bridge) + { + LLCamera trans_camera = bridge->transformCamera(camera); + group->updateDistance(trans_camera); + } + else + { + group->updateDistance(camera); + } } - else + + if (hasRenderType(LLDrawPool::POOL_ALPHA)) { - group->updateDistance(camera); + sCull->pushAlphaGroup(group); } } - - if (hasRenderType(LLDrawPool::POOL_ALPHA)) - { - sCull->pushAlphaGroup(group); - } } } @@ -2370,7 +2691,7 @@ void LLPipeline::postSort(LLCamera& camera) } } - LLSpatialGroup::sNoDelete = FALSE; + //LLSpatialGroup::sNoDelete = FALSE; } @@ -2431,21 +2752,118 @@ void LLPipeline::renderHighlights() LLGLEnable color_mat(GL_COLOR_MATERIAL); disableLights(); - if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) - { - gHighlightProgram.bind(); - gHighlightProgram.vertexAttrib4f(LLViewerShaderMgr::MATERIAL_COLOR,1,1,1,0.5f); - } - - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) - { - // Make sure the selection image gets downloaded and decoded - if (!mFaceSelectImagep) + 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) { - // Load the select texture texture from file -- MC - mFaceSelectImagep = gImageList.getImageFromFile(IMG_FACE_SELECT.asString()+".j2c", TRUE, TRUE); /*gImageList.getImage(IMG_FACE_SELECT);*/ + renderHighlight(iter->mItem->getVObj(), 1.f); } - mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + 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(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + gGL.pushMatrix(); + glLoadIdentity(); + + gGL.getTexUnit(0)->bind(&mHighlight); + + LLVector2 tc1; + LLVector2 tc2; + + tc1.setVec(0,0); + tc2.setVec(2,2); + + gGL.begin(LLRender::TRIANGLES); + + F32 scale = gSavedSettings.getF32("RenderHighlightBrightness"); + LLColor4 color = gSavedSettings.getColor4("RenderHighlightColor"); + F32 thickness = gSavedSettings.getF32("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(); + glMatrixMode(GL_MODELVIEW); + gGL.popMatrix(); + + //gGL.setSceneBlendType(LLRender::BT_ALPHA); + } + + if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightProgram.bind(); + gHighlightProgram.vertexAttrib4f(LLViewerShaderMgr::MATERIAL_COLOR,1,1,1,0.5f); + } + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) + { + // Make sure the selection image gets downloaded and decoded + if (!mFaceSelectImagep) + { + // Load the select texture texture from file -- MC + mFaceSelectImagep = gImageList.getImageFromFile(IMG_FACE_SELECT.asString()+".j2c", TRUE, TRUE); /*gImageList.getImage(IMG_FACE_SELECT);*/ + } + mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); U32 count = mSelectedFaces.size(); for (U32 i = 0; i < count; i++) @@ -2453,7 +2871,7 @@ void LLPipeline::renderHighlights() LLFace *facep = mSelectedFaces[i]; if (!facep || facep->getDrawable()->isDead()) { - llerrs << "Bad face on selection" << llendl; + llwarns << "Bad face on selection" << llendl; return; } @@ -2526,7 +2944,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) { if (!verify()) { - llerrs << "Pipeline verification failed!" << llendl; + llwarns << "Pipeline verification failed!" << llendl; } } @@ -2575,6 +2993,9 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) stop_glerror(); LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools"); + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderForSelect"); + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDeferred"); + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) { LLDrawPool *poolp = *iter; @@ -2586,7 +3007,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING)) { - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderForSelect"); gObjectList.renderObjectsForSelect(camera, gViewerWindow->getVirtualWindowRect()); } else @@ -2650,7 +3070,8 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); if (depth > 3) { - llerrs << "GL matrix stack corrupted!" << llendl; + + llwarns << "GL matrix stack corrupted!" << llendl; } std::string msg = llformat("%s pass %d", gPoolNames[cur_type].c_str(), i); LLGLState::checkStates(msg); @@ -2721,20 +3142,12 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLVertexBuffer::unbind(); - if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred) + if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - // Render debugging beacons. - gObjectList.renderObjectBeacons(); - LLHUDObject::renderAll(); - gObjectList.resetObjectBeacons(); - } - else - { - // Make sure particle effects disappear - LLHUDObject::renderAllForTimer(); - } + // Render debugging beacons. + gObjectList.renderObjectBeacons(); + LLHUDObject::renderAll(); + gObjectList.resetObjectBeacons(); } LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd"); @@ -2758,7 +3171,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) void LLPipeline::renderGeomDeferred(LLCamera& camera) { - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred"); LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY); LLFastTimer t2(LLFastTimer::FTM_POOLS); @@ -2825,15 +3237,18 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) poolp->endDeferredPass(i); LLVertexBuffer::unbind(); - GLint depth; - glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); - if (depth > 3) + if (gDebugGL || gDebugPipeline) { - llerrs << "GL matrix stack corrupted!" << llendl; + GLint depth; + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); + if (depth > 3) + { + llwarns << "GL matrix stack corrupted!" << llendl; + } + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); } - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); } } else @@ -2915,15 +3330,18 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) poolp->endPostDeferredPass(i); LLVertexBuffer::unbind(); - GLint depth; - glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); - if (depth > 3) + if (gDebugGL || gDebugPipeline) { - llerrs << "GL matrix stack corrupted!" << llendl; + GLint depth; + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); + if (depth > 3) + { + llwarns << "GL matrix stack corrupted!" << llendl; + } + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); } - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); } } else @@ -2959,11 +3377,6 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) LLHUDObject::renderAll(); gObjectList.resetObjectBeacons(); } - else - { - // Make sure particle effects disappear - LLHUDObject::renderAllForTimer(); - } if (occlude) { @@ -3067,7 +3480,7 @@ void LLPipeline::renderDebug() gGL.setColorMask(true, false); // Debug stuff. - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -3084,7 +3497,7 @@ void LLPipeline::renderDebug() } } - for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { LLSpatialBridge* bridge = *i; if (!bridge->isDead() && !bridge->isState(LLSpatialGroup::OCCLUDED) && hasRenderType(bridge->mDrawableType)) @@ -3098,93 +3511,88 @@ void LLPipeline::renderDebug() if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) { + LLGLEnable blend(GL_BLEND); // kl sd + LLGLDepthTest depth(TRUE, FALSE); + LLGLDisable cull(GL_CULL_FACE); // kl + gGL.color4f(1,1,1,1); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + F32 a = 0.1f; + F32 col[] = { - 1,1,0, - 0,1,1, - 1,0,1, - 1,1,1, - 1,0,0, - 0,1,0, - 0,0,1, - 0,0,0 + 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++) { - gGL.color3fv(col+i*3); - - gGL.begin(LLRender::LINES); - - LLVector3* frust = mShadowCamera[i].mAgentFrustum; - - 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); + if (i > 3) + { + gGL.color4fv(col+(i-4)*4); + LLVector3* frust = mShadowCamera[i].mAgentFrustum; + + 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) { - LLVector3* ext = mShadowExtents[i]; + gGL.begin(LLRender::LINES); - LLVector3 box[] = + F32* c = col+i*4; + for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j) { - LLVector3(ext[0][0], ext[0][1], ext[0][2]), - LLVector3(ext[1][0], ext[0][1], ext[0][2]), - LLVector3(ext[1][0], ext[1][1], ext[0][2]), - LLVector3(ext[0][0], ext[1][1], ext[0][2]), - LLVector3(ext[0][0], ext[0][1], ext[1][2]), - LLVector3(ext[1][0], ext[0][1], ext[1][2]), - LLVector3(ext[1][0], ext[1][1], ext[1][2]), - LLVector3(ext[0][0], ext[1][1], ext[1][2]), - }; - gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[1].mV); - gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[2].mV); - gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[3].mV); - gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[0].mV); - - gGL.vertex3fv(box[4].mV); gGL.vertex3fv(box[5].mV); - gGL.vertex3fv(box[5].mV); gGL.vertex3fv(box[6].mV); - gGL.vertex3fv(box[6].mV); gGL.vertex3fv(box[7].mV); - gGL.vertex3fv(box[7].mV); gGL.vertex3fv(box[4].mV); - - gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[4].mV); - gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[5].mV); - gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[6].mV); - gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[7].mV); - } + gGL.color3fv(c); - gGL.end(); - - 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) + for (U32 k = 0; k < mShadowFrustPoints[i].size(); ++k) { - if (hasRenderType(part->mDrawableType)) + if (j != k) { - part->renderIntersectingBBoxes(&mShadowCamera[i]); + gGL.vertex3fv(mShadowFrustPoints[i][j].mV); + gGL.vertex3fv(mShadowFrustPoints[i][k].mV); } } + + if (!mShadowFrustOrigin[i].isExactlyZero()) + { + gGL.vertex3fv(mShadowFrustPoints[i][j].mV); + gGL.color4f(1,1,1,1); + gGL.vertex3fv(mShadowFrustOrigin[i].mV); + } } + gGL.end(); } } } @@ -3222,6 +3630,55 @@ void LLPipeline::renderDebug() } } + if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_BUILD_QUEUE) + { + U32 count = 0; + U32 size = mBuildQ2.size(); + LLColor4 col; + + LLGLEnable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + gGL.getTexUnit(0)->bind(LLViewerImage::sWhiteImagep); + + 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(); + glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); + } + + F32 alpha = (F32) (size-count)/size; + + + LLVector2 c(1.f-alpha, alpha); + c.normVec(); + + + ++count; + col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.1f); + group->drawObjectBox(col); + + if (bridge) + { + gGL.popMatrix(); + } + } + } + gGL.flush(); } @@ -4650,7 +5107,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, sPickAvatar = FALSE; //LLToolMgr::getInstance()->inBuildMode() ? FALSE : TRUE; - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -4707,7 +5164,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, //check against avatars sPickAvatar = TRUE; - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -4784,7 +5241,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector3& start, co { LLDrawable* drawable = NULL; - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -4847,7 +5304,7 @@ void LLPipeline::resetVertexBuffers() { sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -4958,18 +5415,18 @@ void validate_framebuffer_object() break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: // frame buffer not OK: probably means unsupported depth buffer format - llerrs << "Framebuffer Incomplete Dimensions." << llendl; + llwarns << "Framebuffer Incomplete Dimensions." << llendl; break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: // frame buffer not OK: probably means unsupported depth buffer format - llerrs << "Framebuffer Incomplete Attachment." << llendl; + llwarns << "Framebuffer Incomplete Attachment." << llendl; break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: /* choose different formats */ - llerrs << "Framebuffer unsupported." << llendl; + llwarns << "Framebuffer unsupported." << llendl; break; default: - llerrs << "Unknown framebuffer status." << llendl; + llwarns << "Unknown framebuffer status." << llendl; break; } } @@ -5287,46 +5744,202 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) } -void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) +void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRenderTarget* gi_source, LLRenderTarget* last_gi_post) //, U32 noise_map) { +/* if (noise_map == 0xFFFFFFFF) + { + noise_map = mNoiseMap; + } +*/ + LLFastTimer ftm(LLFastTimer::FTM_TEMP3); + LLGLState::checkTextureChannels(); + shader.bind(); S32 channel = 0; channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { mDeferredScreen.bindTexture(0,channel); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { mDeferredScreen.bindTexture(1, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { mDeferredScreen.bindTexture(2, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE); - if (channel > -1) + if (gi_source) { - mDeferredScreen.bindTexture(3, channel); + BOOL has_gi = FALSE; + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE); + if (channel > -1) + { + has_gi = TRUE; + gi_source->bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR); + if (channel > -1) + { + has_gi = TRUE; + gi_source->bindTexture(1, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL); + if (channel > -1) + { + has_gi = TRUE; + gi_source->bindTexture(2, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS); + if (channel > -1) + { + has_gi = TRUE; + gi_source->bindTexture(1, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS); + if (channel > -1) + { + has_gi = TRUE; + gi_source->bindTexture(3, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE); + if (channel > -1) + { + has_gi = TRUE; + last_gi_post->bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL); + if (channel > -1) + { + has_gi = TRUE; + last_gi_post->bindTexture(2, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS); + if (channel > -1) + { + has_gi = TRUE; + last_gi_post->bindTexture(1, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS); + if (channel > -1) + { + has_gi = TRUE; + last_gi_post->bindTexture(3, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH); + if (channel > -1) + { + has_gi = TRUE; + gGL.getTexUnit(channel)->bind(gi_source, TRUE); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + stop_glerror(); + + glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); + glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); + + stop_glerror(); + } + + if (has_gi) + { + U32 gi_samples = llclamp(gSavedSettings.getU32("RenderGISamples"), (U32) 1, (U32) 8); + + F32 range_x = llmin(mGIRange.mV[0], 1.f); + F32 range_y = llmin(mGIRange.mV[1], 1.f); + + LLVector2 scale(range_x,range_y); + + LLVector2 kern[25]; + + for (S32 i = 0; i < 5; ++i) + { + for (S32 j = 0; j < 5; ++j) + { + S32 idx = i*5+j; + kern[idx].mV[0] = (i-2)*0.5f; + kern[idx].mV[1] = (j-2)*0.5f; + kern[idx].scaleVec(scale); + } + } + + F32 gi_radius = mGILightRadius; //gSavedSettings.getF32("RenderGILightRadius"); + + shader.uniform2f("gi_scale", scale.mV[0], scale.mV[1]); + shader.uniform2fv("gi_kern", 25, (F32*) kern); + shader.uniformMatrix4fv("gi_mat", 1, FALSE, mGIMatrix.m); + shader.uniformMatrix4fv("gi_mat_proj", 1, FALSE, mGIMatrixProj.m); + shader.uniformMatrix4fv("gi_inv_proj", 1, FALSE, mGIInvProj.m); + shader.uniformMatrix4fv("gi_norm_mat", 1, FALSE, mGINormalMatrix.m); + shader.uniform1f("gi_radius", gi_radius); + shader.uniform1i("gi_samples", (GLint) gSavedSettings.getU32("RenderGISamples")); + shader.uniform1f("gi_intensity", gSavedSettings.getF32("RenderGIIntensity")/(gi_samples*gi_samples)); + shader.uniform3fv("gi_quad", 1, gSavedSettings.getVector3("RenderGIColorCurve").mV); + shader.uniform3fv("gi_spec", 1, gSavedSettings.getVector3("RenderGISpecularCurve").mV); + shader.uniform1f("gi_direction_weight", gSavedSettings.getF32("RenderGIDirectionWeight")); + shader.uniform1f("gi_light_offset", gSavedSettings.getF32("RenderGILightOffset")); + shader.uniform1f("gi_blend", gFrameIntervalSeconds); + } } channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { - gGL.getTexUnit(channel)->bind(&mDeferredScreen, TRUE); + gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + 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("inv_proj", 1, FALSE, inv_proj.m); + shader.uniform4f("viewport", (F32) gGLViewport[0], + (F32) gGLViewport[1], + (F32) gGLViewport[2], + (F32) gGLViewport[3]); } channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NOISE); if (channel > -1) { - gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); // was noise_map KL + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC); + if (channel > -1) + { + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); } stop_glerror(); @@ -5335,19 +5948,68 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) if (channel > -1) { mDeferredLight[light_index].bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE); + if (channel > -1) + { + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + gi_source->bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredLight[1].bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredLight[2].bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } + stop_glerror(); for (U32 i = 0; i < 4; i++) { + channel = shader.enableTexture(LLViewerShaderMgr::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(LLViewerShaderMgr::DEFERRED_SHADOW0+i); stop_glerror(); if (channel > -1) { stop_glerror(); - gGL.getTexUnit(channel)->bind(&mSunShadow[i], TRUE); + 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); @@ -5358,17 +6020,19 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) stop_glerror(); - F32 mat[64]; + 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("shadow_matrix[0]", 4, FALSE, mat); - shader.uniformMatrix4fv("shadow_matrix", 4, FALSE, mat); + shader.uniformMatrix4fv("shadow_matrix[0]", 6, FALSE, mat); + shader.uniformMatrix4fv("shadow_matrix", 6, FALSE, mat); stop_glerror(); @@ -5417,8 +6081,23 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); shader.uniform1f("near_clip", LLViewerCamera::getInstance()->getNear()*2.f); shader.uniform1f("alpha_soften", gSavedSettings.getF32("RenderDeferredAlphaSoften")); + shader.uniform1f ("shadow_offset", gSavedSettings.getF32("RenderShadowOffset")); + shader.uniform1f("shadow_bias", gSavedSettings.getF32("RenderShadowBias")); +/* shader.uniform3fv("gi_quad", 1, gSavedSettings.getVector3("RenderGIColorCurve").mV); + shader.uniform3fv("lum_quad", 1, gSavedSettings.getVector3("RenderLuminanceColorCurve").mV); + shader.uniform3fv("gi_lum_quad", 1, gSavedSettings.getVector3("RenderGILuminanceColorCurve").mV); + shader.uniform3fv("sun_lum_quad", 1, gSavedSettings.getVector3("RenderSunLuminanceColorCurve").mV); + shader.uniform1f("lum_lod", gSavedSettings.getF32("RenderLuminanceDetail")); + shader.uniform1f("gi_range", gSavedSettings.getF32("RenderGIRange")); + + 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); + } */ } +// KL The Deffered Pipeline begins here! void LLPipeline::renderDeferredLighting() { if (!sCull) @@ -5426,6 +6105,12 @@ void LLPipeline::renderDeferredLighting() return; } + { + 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(GL_MULTISAMPLE_ARB); if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) @@ -5439,16 +6124,10 @@ void LLPipeline::renderDeferredLighting() glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); gGL.setColorMask(true, true); - - mDeferredLight[0].bindTarget(); - - //mDeferredLight[0].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), - // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); //draw a cube around every light LLVertexBuffer::unbind(); - glBlendFunc(GL_ONE, GL_ONE); LLGLEnable cull(GL_CULL_FACE); LLGLEnable blend(GL_BLEND); @@ -5460,126 +6139,271 @@ void LLPipeline::renderDeferredLighting() -1,-3, 3,1, }; - - bindDeferredShader(gDeferredSunProgram); - - 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++) + glVertexPointer(2, GL_FLOAT, 0, vert); + glColor3f(1,1,1); + //Set mSunDir KL This makes sense to have it here. Still calculated EVEN if Deferred Sun is FALSE! { - 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]; - } + setupHWLights(NULL); //to set mSunDir; + LLVector4 dir(mSunDir, 0.f); + glh::vec4f tc(dir.mV); + mat.mult_matrix_vec(tc); + glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0); } - gDeferredSunProgram.uniform3fv("offset", slice, offset); - gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight()); - - setupHWLights(NULL); //to set mSunDir; - - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); + if (gSavedSettings.getBOOL("RenderDeferredShadow")) + { + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); - LLVector4 dir(mSunDir, 0.f); + mDeferredLight[0].bindTarget(); +// KL Bind to 0 next section Deferred Sun ! + if (gSavedSettings.getBOOL("RenderDeferredSun")) + { //paint shadow/SSAO light map (direct lighting lightmap) + bindDeferredShader(gDeferredSunProgram, 0); - glh::vec4f tc(dir.mV); - mat.mult_matrix_vec(tc); - glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0); - glColor3f(1,1,1); + glClearColor(1,1,1,1); + mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT); + glClearColor(0,0,0,0); - glVertexPointer(2, GL_FLOAT, 0, vert); + 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[0].getWidth(), mDeferredLight[0].getHeight()); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } + + unbindDeferredShader(gDeferredSunProgram); + } + else { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_FALSE); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - stop_glerror(); + mDeferredLight[0].clear(); } - - unbindDeferredShader(gDeferredSunProgram); - mDeferredLight[0].flush(); + mDeferredLight[0].flush(); + mDeferredLight[1].bindTarget(); + } +// KL Bind to 1 next section GI +/* if (gSavedSettings.getBOOL("RenderDeferredGI")) + { + { //get luminance map from previous frame's light map + LLGLEnable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + LLGLDepthTest depth(GL_FALSE); + LLGLDisable stencil(GL_STENCIL_TEST); - //blur lightmap - mDeferredLight[1].bindTarget(); + //static F32 fade = 1.f; - //mDeferredLight[1].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), - // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); - - bindDeferredShader(gDeferredBlurLightProgram); + F32 fade = gSavedSettings.getF32("RenderLuminanceFade"); + { + gGL.setSceneBlendType(LLRender::BT_ALPHA); + gLuminanceGatherProgram.bind(); + gLuminanceGatherProgram.uniform2f("screen_res", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight()); + gLuminanceGatherProgram.uniform1f("fade", llclamp(fade, 0.f, 1.f)); + mLuminanceMap.bindTarget(); + gGL.getTexUnit(0)->bind(&mDeferredLight[0]); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + gLuminanceGatherProgram.unbind(); + mLuminanceMap.flush(); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); + glGenerateMipmapEXT(GL_TEXTURE_2D); + } - LLVector3 gauss[32]; // xweight, yweight, offset + } - LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian"); - U32 kern_length = llclamp(gSavedSettings.getU32("RenderShadowBlurSamples"), (U32) 1, (U32) 16)*2 - 1; - F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize"); + { //paint noisy GI map (bounce lighting lightmap) + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + LLGLDisable test(GL_ALPHA_TEST); - // sample symmetrically with the middle sample falling exactly on 0.0 - F32 x = -(kern_length/2.0f) + 0.5f; + mGIMapPost[0].bindTarget(); - 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; - } - /* swap the x=0 position to the start of gauss[] so we can - treat it specially as an optimization. */ - LLVector3 swap; - swap = gauss[kern_length/2]; - gauss[kern_length/2] = gauss[0]; - gauss[0] = swap; - llassert(gauss[0].mV[2] == 0.0f); + bindDeferredShader(gDeferredGIProgram, 0, &mGIMap, 0);//, mTrueNoiseMap); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + unbindDeferredShader(gDeferredGIProgram); + mGIMapPost[0].flush(); - gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); - gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); - gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); - { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_FALSE); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - stop_glerror(); - } - - mDeferredLight[1].flush(); - unbindDeferredShader(gDeferredBlurLightProgram); + } - bindDeferredShader(gDeferredBlurLightProgram, 1); - mDeferredLight[0].bindTarget(); + U32 pass_count = 0; + if (gSavedSettings.getBOOL("RenderDeferredBlurLight")) + { + pass_count = llclamp(gSavedSettings.getU32("RenderGIBlurPasses"), (U32) 1, (U32) 128); + } - gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); - gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); - gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + for (U32 i = 0; i < pass_count; ++i) + { //gather/soften indirect lighting map + bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[0], NULL); //, mTrueNoiseMap); - { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_FALSE); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - stop_glerror(); - } + LLVector2 gauss[32]; // xweight, yweight, offset + + F32 sc = 1.f; + + F32 go = gSavedSettings.getF32("RenderGIGaussian"); + U32 kern_length = llclamp(gSavedSettings.getU32("RenderGIBlurSamples"), (U32) 1, (U32) 16)*2 - 1; + F32 blur_size = gSavedSettings.getF32("RenderGIBlurSize")*sc; + F32 dist_factor = gSavedSettings.getF32("RenderGIBlurDistFactor"); + + // sample symmetrically with the middle sample falling exactly on 0.0 + F32 x = -(kern_length/2.0f) + 0.5f; + + for (U32 i = 0; i < kern_length; i++) + { + gauss[i].mV[0] = llgaussian(x, go); + gauss[i].mV[1] = x; + x += 1.f; + } + // swap the x=0 position to the start of gauss[] so we can + // treat it specially as an optimization. + LLVector2 swap; + swap = gauss[kern_length/2]; + gauss[kern_length/2] = gauss[0]; + gauss[0] = swap; + llassert(gauss[0].mV[2] == 0.0f); + + gDeferredPostGIProgram.uniform2f("delta", 1.f, 0.f); + gDeferredPostGIProgram.uniform1f("dist_factor", dist_factor); + gDeferredPostGIProgram.uniform2fv("kern[0]", kern_length, gauss[0].mV); + gDeferredPostGIProgram.uniform2fv("kern", kern_length, gauss[0].mV); + gDeferredPostGIProgram.uniform1i("kern_length", kern_length); + gDeferredPostGIProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + gDeferredPostGIProgram.uniform3fv("blur_quad", 1, gSavedSettings.getVector3("RenderGIBlurColorCurve").mV); + + mGIMapPost[1].bindTarget(); + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } + + mGIMapPost[1].flush(); + unbindDeferredShader(gDeferredPostGIProgram); + + bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[1], NULL);//, mTrueNoiseMap); + mGIMapPost[0].bindTarget(); + + gDeferredPostGIProgram.uniform2f("delta", 0.f, 1.f); + gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor); + gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); + gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + stop_glerror(); + } + mGIMapPost[0].flush(); + unbindDeferredShader(gDeferredPostGIProgram); + } + } */ + + if (gSavedSettings.getBOOL("RenderDeferredBlurLight")) + { //soften direct lighting lightmap + //blur lightmap + mDeferredLight[1].bindTarget(); + + glClearColor(1,1,1,1); + mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT); + glClearColor(0,0,0,0); + + bindDeferredShader(gDeferredBlurLightProgram); + + LLVector3 gauss[32]; // xweight, yweight, offset + + LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian"); + U32 kern_length = llclamp(gSavedSettings.getU32("RenderShadowBlurSamples"), (U32) 1, (U32) 16)*2 - 1; + F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize"); + F32 dist_factor = gSavedSettings.getF32("RenderShadowBlurDistFactor"); + + // sample symmetrically with the middle sample falling exactly on 0.0 + F32 x = -(kern_length/2.0f) + 0.5f; + + 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; + } + /* swap the x=0 position to the start of gauss[] so we can + treat it specially as an optimization. */ + LLVector3 swap; + swap = gauss[kern_length/2]; + gauss[kern_length/2] = gauss[0]; + gauss[0] = swap; + llassert(gauss[0].mV[2] == 0.0f); + + gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); + gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor); + gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); + gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } + + mDeferredLight[1].flush(); + unbindDeferredShader(gDeferredBlurLightProgram); + + bindDeferredShader(gDeferredBlurLightProgram, 1); + mDeferredLight[0].bindTarget(); + + gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); + gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor); + gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); + gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); // KL 4? + stop_glerror(); + } mDeferredLight[0].flush(); unbindDeferredShader(gDeferredBlurLightProgram); + } stop_glerror(); glPopMatrix(); @@ -5588,15 +6412,26 @@ void LLPipeline::renderDeferredLighting() stop_glerror(); glPopMatrix(); 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(); - mScreen.clear(GL_COLOR_BUFFER_BIT); - - bindDeferredShader(gDeferredSoftenProgram); +/* if (gSavedSettings.getBOOL("RenderDeferredGI")) + { + mDeferredLight[1].bindTarget(); + mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT); + } + else + { */ + mScreen.bindTarget(); + mScreen.clear(GL_COLOR_BUFFER_BIT); +// } + + if (gSavedSettings.getBOOL("RenderDeferredAtmospheric")) + { //apply sunlight contribution + bindDeferredShader(gDeferredSoftenProgram, 0, &mGIMapPost[0]); // may not be using GI but still need this KL { LLGLDepthTest depth(GL_FALSE); LLGLDisable blend(GL_BLEND); @@ -5619,130 +6454,330 @@ void LLPipeline::renderDeferredLighting() } unbindDeferredShader(gDeferredSoftenProgram); + } +// KL this code is a tad buggered atm it obliterates local lights...... +/* { //render sky/water/hair/skirts + LLGLDisable blend(GL_BLEND); + LLGLDisable stencil(GL_STENCIL_TEST); + gGL.setSceneBlendType(LLRender::BT_ALPHA); - bindDeferredShader(gDeferredLightProgram); - - std::list<LLVector4> fullscreen_lights; - std::list<LLVector4> light_colors; + U32 render_mask = mRenderTypeMask; + mRenderTypeMask = mRenderTypeMask & + ((1 << LLPipeline::RENDER_TYPE_SKY) | + (1 << LLPipeline::RENDER_TYPE_CLOUDS) | + (1 << LLPipeline::RENDER_TYPE_WL_SKY) | + (1 << LLPipeline::RENDER_TYPE_AVATAR) | + (1 << LLPipeline::RENDER_TYPE_WATER)); + + renderGeomPostDeferred(*LLViewerCamera::getInstance()); + mRenderTypeMask = render_mask; + } */ - F32 v[24]; - glVertexPointer(3, GL_FLOAT, 0, v); + BOOL render_local = gSavedSettings.getBOOL("RenderDeferredLocalLights"); + BOOL render_fullscreen = gSavedSettings.getBOOL("RenderDeferredFullscreenLights"); + +/* + if (gSavedSettings.getBOOL("RenderDeferredGI")) { - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) + mDeferredLight[1].flush(); + mDeferredLight[2].bindTarget(); + mDeferredLight[2].clear(GL_COLOR_BUFFER_BIT); + } +*/ + if (render_local || render_fullscreen) + { + 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++) { - LLDrawable* drawablep = *iter; - - LLVOVolume* volume = drawablep->getVOVolume(); - if (!volume) + mTargetShadowSpotLight[i] = NULL; + } + + std::list<LLVector4> light_colors; + + F32 v[24]; + glVertexPointer(3, GL_FLOAT, 0, v); + BOOL render_local = gSavedSettings.getBOOL("RenderDeferredLocalLights"); + + { + bindDeferredShader(gDeferredLightProgram); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) { - continue; + LLDrawable* drawablep = *iter; + + LLVOVolume* volume = drawablep->getVOVolume(); + if (!volume) + { + continue; + } + + LLVector3 center = drawablep->getPositionAgent(); + F32* c = center.mV; + F32 s = volume->getLightRadius()*1.5f; + + LLColor3 col = volume->getLightColor(); + col *= volume->getLightIntensity(); + + if (col.magVecSquared() < 0.001f) + { + continue; + } + + if (s <= 0.001f) + { + continue; + } + + if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 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 + v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000 + v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001 + v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010 + v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011 + + v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100 + v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101 + v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110 + v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111 + + if (LLViewerCamera::getInstance()->getOrigin().mV[0] > c[0] + s + 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[0] < c[0] - s - 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[1] > c[1] + s + 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[1] < c[1] - s - 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[2] > c[2] + s + 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[2] < c[2] - s - 0.2f) + { //draw box if camera is outside box + if (render_local) + { + if (volume->getLightTexture()) + { + drawablep->getVOVolume()->updateSpotLightPriority(); + spot_lights.push_back(drawablep); + continue; + } + + glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); + glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, get_box_fan_indices(LLViewerCamera::getInstance(), center)); + } + } + else if (render_fullscreen) + { + if (volume->getLightTexture()) + { + 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); + } - LLVector3 center = drawablep->getPositionAgent(); - F32* c = center.mV; - F32 s = volume->getLightRadius()*1.5f; + if (!spot_lights.empty()) + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + bindDeferredShader(gDeferredSpotLightProgram); - if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0) + gDeferredSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); + + for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter) { - continue; - } + 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(gDeferredSpotLightProgram, drawablep); + + LLColor3 col = volume->getLightColor(); + col *= volume->getLightIntensity(); + + //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 + v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000 + v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001 + v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010 + v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011 + + v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100 + v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101 + v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110 + v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111 - sVisibleLightCount++; - glh::vec3f tc(c); - mat.mult_matrix_vec(tc); - - LLColor3 col = volume->getLightColor(); - col *= volume->getLightIntensity(); - - //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 - v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000 - v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001 - v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010 - v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011 - - v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100 - v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101 - v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110 - v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111 - - if (LLViewerCamera::getInstance()->getOrigin().mV[0] > c[0] + s + 0.2f || - LLViewerCamera::getInstance()->getOrigin().mV[0] < c[0] - s - 0.2f || - LLViewerCamera::getInstance()->getOrigin().mV[1] > c[1] + s + 0.2f || - LLViewerCamera::getInstance()->getOrigin().mV[1] < c[1] - s - 0.2f || - LLViewerCamera::getInstance()->getOrigin().mV[2] > c[2] + s + 0.2f || - LLViewerCamera::getInstance()->getOrigin().mV[2] < c[2] - s - 0.2f) - { //draw box if camera is outside box glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, get_box_fan_indices(LLViewerCamera::getInstance(), center)); - } - else - { - 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)); + GL_UNSIGNED_BYTE, get_box_fan_indices(LLViewerCamera::getInstance(), center)); } + gDeferredSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); + unbindDeferredShader(gDeferredSpotLightProgram); } - } - unbindDeferredShader(gDeferredLightProgram); + { + bindDeferredShader(gDeferredMultiLightProgram); + + LLGLDepthTest depth(GL_FALSE); - if (!fullscreen_lights.empty()) - { - bindDeferredShader(gDeferredMultiLightProgram); - LLGLDepthTest depth(GL_FALSE); + //full screen blit + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); - //full screen blit - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); + U32 count = 0; - U32 count = 0; + const U32 max_count = 8; // KL poss 16? + LLVector4 light[max_count]; + LLVector4 col[max_count]; - LLVector4 light[16]; - LLVector4 col[16]; + glVertexPointer(2, GL_FLOAT, 0, vert); - glVertexPointer(2, GL_FLOAT, 0, vert); + F32 far_z = 0.f; - while (!fullscreen_lights.empty()) - { - light[count] = fullscreen_lights.front(); - fullscreen_lights.pop_front(); - col[count] = light_colors.front(); - light_colors.pop_front(); + while (!fullscreen_lights.empty()) + { + light[count] = fullscreen_lights.front(); + fullscreen_lights.pop_front(); + col[count] = light_colors.front(); + light_colors.pop_front(); - count++; - if (count == 16 || fullscreen_lights.empty()) + far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z); + + count++; + if (count == max_count || fullscreen_lights.empty()) + { + gDeferredMultiLightProgram.uniform1i("light_count", count); + gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light); + gDeferredMultiLightProgram.uniform4fv("light", count, (GLfloat*) light); + gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col); + gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col); + gDeferredMultiLightProgram.uniform1f("far_z", far_z); + far_z = 0.f; + count = 0; + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + } + } + + unbindDeferredShader(gDeferredMultiLightProgram); + + bindDeferredShader(gDeferredMultiSpotLightProgram); + + gDeferredMultiSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); + + for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter) { - gDeferredMultiLightProgram.uniform1i("light_count", count); - gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light); - gDeferredMultiLightProgram.uniform4fv("light", count, (GLfloat*) light); - gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col); - gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col); - count = 0; + 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(); + col *= volume->getLightIntensity(); + + glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); + glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); } - } - - - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - unbindDeferredShader(gDeferredMultiLightProgram); + gDeferredMultiSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); + unbindDeferredShader(gDeferredMultiSpotLightProgram); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } } + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gGL.setColorMask(true, true); +/* + if (gSavedSettings.getBOOL("RenderDeferredGI")) + { + mDeferredLight[2].flush(); + mScreen.bindTarget(); + mScreen.clear(GL_COLOR_BUFFER_BIT); + + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + { //mix various light maps (local, sun, gi) + LLGLDisable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + LLGLDepthTest depth(GL_FALSE); + LLGLDisable stencil(GL_STENCIL_TEST); + + gViewerWindow->setupViewport(); + + bindDeferredShader(gDeferredPostProgram, 0, &mGIMapPost[0]); + + gDeferredPostProgram.bind(); + + LLVertexBuffer::unbind(); + + glVertexPointer(2, GL_FLOAT, 0, vert); + glColor3f(1,1,1); - { //render non-deferred geometry + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glDrawArrays(GL_TRIANGLES, 0, 3); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + unbindDeferredShader(gDeferredPostProgram); + } + } +*/ + { //render non-deferred geometry (alpha, fullbright, glow) KL issues with render pipeline merge needs work.. here LLGLDisable blend(GL_BLEND); LLGLDisable stencil(GL_STENCIL_TEST); - + gGL.setSceneBlendType(LLRender::BT_ALPHA); U32 render_mask = mRenderTypeMask; mRenderTypeMask = mRenderTypeMask & ((1 << LLPipeline::RENDER_TYPE_SKY) | @@ -5754,18 +6789,161 @@ void LLPipeline::renderDeferredLighting() (1 << LLPipeline::RENDER_TYPE_FULLBRIGHT) | (1 << LLPipeline::RENDER_TYPE_VOLUME) | (1 << LLPipeline::RENDER_TYPE_GLOW) | - (1 << LLPipeline::RENDER_TYPE_BUMP)); + (1 << LLPipeline::RENDER_TYPE_BUMP) | + (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) | + (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA) | + (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK) | + (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) | + (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) | + (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK) | + (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY) | + (1 << LLPipeline::RENDER_TYPE_PASS_GLOW) | + (1 << LLPipeline::RENDER_TYPE_PASS_GRASS) | + (1 << LLPipeline::RENDER_TYPE_PASS_SHINY) | + (1 << LLPipeline::RENDER_TYPE_PASS_INVISIBLE) | + (1 << LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY)); renderGeomPostDeferred(*LLViewerCamera::getInstance()); mRenderTypeMask = render_mask; } - mScreen.flush(); + mScreen.flush(); // We are FLUSHED alright ! end of deferred render YAY! } +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("proj_mat", 1, FALSE, screen_to_light.m); + shader.uniform1f("proj_near", near_clip); + shader.uniform3fv("proj_p", 1, p1.v); + shader.uniform3fv("proj_n", 1, n.v); + shader.uniform3fv("proj_origin", 1, screen_origin.v); + shader.uniform1f("proj_range", proj_range); + shader.uniform1f("proj_ambiance", params.mV[2]); + S32 s_idx = -1; + + for (U32 i = 0; i < 2; i++) + { + if (mShadowSpotLight[i] == drawablep) + { + s_idx = i; + } + } + + shader.uniform1i("proj_shadow_idx", s_idx); + + if (s_idx >= 0) + { + shader.uniform1f("shadow_fade", 1.f-mSpotLightFade[s_idx]); + } + else + { + shader.uniform1f("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; + } + } + } + + LLViewerImage* img = volume->getLightTexture(); + + S32 channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); + + if (channel > -1 && img) + { + gGL.getTexUnit(channel)->bind(img); + + F32 lod_range = logf(img->getWidth())/logf(2.f); + + shader.uniform1f("proj_focus", focus); + shader.uniform1f("proj_lod", lod_range); + shader.uniform1f("proj_ambient_lod", llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f)); + } +} + void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) { + LLFastTimer ftm(LLFastTimer::FTM_TEMP4); stop_glerror(); shader.disableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE); shader.disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE); @@ -5773,14 +6951,40 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE); shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE); shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE); + shader.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS); + for (U32 i = 0; i < 4; i++) { + if (shader.disableTexture(LLViewerShaderMgr::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(LLViewerShaderMgr::DEFERRED_SHADOW0+i) > -1) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); } } + shader.disableTexture(LLViewerShaderMgr::DEFERRED_NOISE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC); S32 channel = shader.disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); if (channel > -1) @@ -5794,6 +6998,8 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->activate(); shader.unbind(); + + LLGLState::checkTextureChannels(); } inline float sgn(float a) @@ -5932,15 +7138,15 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) } } - LLSpatialPartition::sFreezeState = TRUE; - LLPipeline::sSkipUpdate = TRUE; + //LLSpatialPartition::sFreezeState = TRUE; + //LLPipeline::sSkipUpdate = TRUE; LLGLUserClipPlane clip_plane(plane, mat, projection); static LLCullResult result; updateCull(camera, result, 1); stateSort(camera, result); renderGeom(camera); - LLSpatialPartition::sFreezeState = FALSE; - LLPipeline::sSkipUpdate = FALSE; + //LLSpatialPartition::sFreezeState = FALSE; + //LLPipeline::sSkipUpdate = FALSE; } } glCullFace(GL_BACK); @@ -6039,7 +7245,6 @@ glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up) dirN = dir; dirN.normVec(); - ret.m[ 0] = lftN[0]; ret.m[ 1] = upN[0]; @@ -6087,17 +7292,468 @@ glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max) ret.m[11] = 0; ret.m[15] = 1; - return ret; -} + return ret; +} + +void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, BOOL use_shader) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_RENDER); + + //clip out geometry on the same side of water as the camera + static LLCullResult result; + S32 occlude = LLPipeline::sUseOcclusion; + LLPipeline::sUseOcclusion = 1; + LLPipeline::sShadowRender = TRUE; + + updateCull(shadow_cam, result); + stateSort(shadow_cam, result); + + U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP }; + LLGLEnable cull(GL_CULL_FACE); + + //generate shadow map + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(proj.m); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf(view.m); + + stop_glerror(); + gGLLastMatrix = NULL; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + glColor4f(1,1,1,1); + + stop_glerror(); + + gGL.setColorMask(false, false); + + if (use_shader) + { + gDeferredShadowProgram.bind(); + } + + //glCullFace(GL_FRONT); + + { + LLFastTimer ftm(LLFastTimer::FTM_SHADOW_SIMPLE); + LLGLDisable test(GL_ALPHA_TEST); + 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) + { + gDeferredShadowProgram.unbind(); + renderGeomShadow(shadow_cam); + gDeferredShadowProgram.bind(); + } + else + { + renderGeomShadow(shadow_cam); + } + + { + LLFastTimer ftm(LLFastTimer::FTM_SHADOW_ALPHA); + LLGLEnable test(GL_ALPHA_TEST); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f); + renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE); + glColor4f(1,1,1,1); + renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } + + //glCullFace(GL_BACK); + + if (use_shader) + { + gDeferredShadowProgram.unbind(); + } + + gGL.setColorMask(true, true); + + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + gGLLastMatrix = NULL; + + LLPipeline::sUseOcclusion = occlude; + LLPipeline::sShadowRender = FALSE; +} + + +BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir) +{ + LLFastTimer ftm(LLFastTimer::FTM_TEMP2); + //get point cloud of intersection of frust and min, max + + //get set of planes + std::vector<LLPlane> ps; + + if (getVisibleExtents(camera, min, max)) + { + return FALSE; + } + + ps.push_back(LLPlane(min, LLVector3(-1,0,0))); + ps.push_back(LLPlane(min, LLVector3(0,-1,0))); + ps.push_back(LLPlane(min, LLVector3(0,0,-1))); + ps.push_back(LLPlane(max, LLVector3(1,0,0))); + ps.push_back(LLPlane(max, LLVector3(0,1,0))); + ps.push_back(LLPlane(max, LLVector3(0,0,1))); + + if (!light_dir.isExactlyZero()) + { + LLPlane ucp; + LLPlane mcp; + + F32 maxd = -1.f; + F32 mind = 1.f; + + for (U32 i = 0; i < ps.size(); ++i) + { //pick the plane most aligned to lightDir for user clip plane + LLVector3 n(ps[i].mV); + F32 da = n*light_dir; + if (da > maxd) + { + maxd = da; + ucp = ps[i]; + } + + if (da < mind) + { + mind = da; + mcp = ps[i]; + } + } + + camera.setUserClipPlane(ucp); + + ps.clear(); + ps.push_back(ucp); + ps.push_back(mcp); + } + + for (U32 i = 0; i < 6; i++) + { + ps.push_back(camera.getAgentPlane(i)); + } + + //get set of points where planes intersect and points are not above any plane + fp.clear(); + + for (U32 i = 0; i < ps.size(); ++i) + { + for (U32 j = 0; j < ps.size(); ++j) + { + for (U32 k = 0; k < ps.size(); ++k) + { + if (i == j || + i == k || + k == j) + { + continue; + } + + LLVector3 n1,n2,n3; + F32 d1,d2,d3; + + n1.setVec(ps[i].mV); + n2.setVec(ps[j].mV); + n3.setVec(ps[k].mV); + + d1 = ps[i].mV[3]; + d2 = ps[j].mV[3]; + d3 = ps[k].mV[3]; + + //get point of intersection of 3 planes "p" + LLVector3 p = (-d1*(n2%n3)-d2*(n3%n1)-d3*(n1%n2))/(n1*(n2%n3)); + + if (llround(p*n1+d1, 0.0001f) == 0.f && + llround(p*n2+d2, 0.0001f) == 0.f && + llround(p*n3+d3, 0.0001f) == 0.f) + { //point is on all three planes + BOOL found = TRUE; + for (U32 l = 0; l < ps.size() && found; ++l) + { + if (llround(ps[l].dist(p), 0.0001f) > 0.0f) + { //point is above some plane, not contained + found = FALSE; + } + } + + if (found) + { + fp.push_back(p); + } + } + } + } + } + + if (fp.empty()) + { + return FALSE; + } + + return TRUE; +} + +void LLPipeline::generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<LLVector3>& vpc) +{ +/* if (!gSavedSettings.getBOOL("RenderDeferredGI")) + { + return; + } */ + + LLVector3 up; + + if (lightDir.mV[2] > 0.5f) + { + up = LLVector3(1,0,0); + } + else + { + up = LLVector3(0, 0, 1); + } + + + F32 lrad = gSavedSettings.getF32("RenderGILightRadius"); + + F32 samples = (F32) gSavedSettings.getU32("RenderGISamples"); + + F32 gi_range = gSavedSettings.getF32("RenderGIRange"); + + U32 res = 1024; + + lrad = samples*gi_range/(res-samples)*0.5f; + + F32 lrange = lrad+gi_range*0.5f; + + LLVector3 pad(lrange,lrange,lrange); + + glh::matrix4f view = look(LLVector3(128.f,128.f,128.f), lightDir, up); + + LLVector3 cp = camera.getOrigin()+camera.getAtAxis()*(gi_range*0.5f); + + glh::vec3f scp(cp.mV); + view.mult_matrix_vec(scp); + cp.setVec(scp.v); + + F32 pix_width = lrange/(res*0.5f); + + //lrad = llround(lrad, pix_width); + + //move cp to the nearest pix_width + for (U32 i = 0; i < 3; i++) + { + cp.mV[i] = llround(cp.mV[i], pix_width); + } + + LLVector3 min = cp-pad; + LLVector3 max = cp+pad; + + //set mGIRange to range in tc space[0,1] that covers texture block of intersecting lights around a point + mGIRange.mV[0] = (max.mV[0]-min.mV[0])/res; + mGIRange.mV[1] = (max.mV[1]-min.mV[1])/res; + mGILightRadius = lrad; + + glh::matrix4f proj = gl_ortho(min.mV[0], max.mV[0], + min.mV[1], max.mV[1], + -max.mV[2], -min.mV[2]); + + LLCamera sun_cam = camera; + + glh::matrix4f eye_view = glh_get_current_modelview(); + + //get eye space to camera space matrix + mGIMatrix = view*eye_view.inverse(); + mGINormalMatrix = mGIMatrix.inverse().transpose(); + mGIInvProj = proj.inverse(); + mGIMatrixProj = proj*mGIMatrix; + + //translate and scale to [0,1] + glh::matrix4f trans(.5f, 0.f, 0.f, .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); + + mGIMatrixProj = trans*mGIMatrixProj; + + glh_set_current_modelview(view); + glh_set_current_projection(proj); + + LLViewerCamera::updateFrustumPlanes(sun_cam, TRUE, FALSE, TRUE); + + sun_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR); + static LLCullResult result; + + U32 type_mask = mRenderTypeMask; + + mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) | + (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | + (1<<LLPipeline::RENDER_TYPE_BUMP) | + (1<<LLPipeline::RENDER_TYPE_VOLUME) | + (1<<LLPipeline::RENDER_TYPE_TREE) | + (1<<LLPipeline::RENDER_TYPE_TERRAIN) | + (1<<LLPipeline::RENDER_TYPE_WATER) | + (1<<LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW) | + (1<<LLPipeline::RENDER_TYPE_AVATAR) | + (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) | + (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) | + (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) | + (1 << LLPipeline::RENDER_TYPE_PASS_SHINY)); + + + + S32 occlude = LLPipeline::sUseOcclusion; + LLPipeline::sUseOcclusion = 0; + LLPipeline::sShadowRender = TRUE; + + updateCull(sun_cam, result); + stateSort(sun_cam, result); + + LLGLEnable cull(GL_CULL_FACE); + + //generate GI map + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(proj.m); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf(view.m); + + stop_glerror(); + gGLLastMatrix = NULL; + + mGIMap.clear(); + + { + LLGLEnable enable(GL_DEPTH_CLAMP_NV); + renderGeomDeferred(camera); + } + + mGIMap.flush(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + gGLLastMatrix = NULL; + + LLPipeline::sUseOcclusion = occlude; + LLPipeline::sShadowRender = FALSE; + + + mRenderTypeMask = type_mask; + +} + +void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade) +{ + if (!gSavedSettings.getBOOL("renderhighlights")) // KL need this to make the mouseover Highlights toggle ^^ + { + return; + } + + 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(LLViewerImage::sNullImagep, LLColor4(1,1,1,fade)); + } + } + } + } +} + +void LLPipeline::generateHighlight(LLCamera& camera) +{ + if (!gSavedSettings.getBOOL("renderhighlights")) // KL need this to make the mouseover Highlights toggle ^^ + { + return; + } + //render highlighted object as white into offscreen render target + + if (mHighlightObject.notNull()) + { + mHighlightSet.insert(HighlightItem(mHighlightObject)); + } + + if (!mHighlightSet.empty()) + { + F32 transition = gFrameIntervalSeconds/gSavedSettings.getF32("RenderHighlightFadeTime"); + + LLGLDisable test(GL_ALPHA_TEST); + LLGLDepthTest depth(GL_FALSE); + mHighlight.bindTarget(); + disableLights(); + gGL.setColorMask(true, true); + mHighlight.clear(); + + gGL.getTexUnit(0)->bind(LLViewerImage::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->setupViewport(); + } +} + void LLPipeline::generateSunShadow(LLCamera& camera) { - if (!sRenderDeferred) { return; } + LLFastTimer ftm(LLFastTimer::FTM_TEMP1); + //temporary hack to disable shadows but keep local lights static BOOL clear = TRUE; BOOL gen_shadow = gSavedSettings.getBOOL("RenderDeferredSunShadow"); @@ -6106,98 +7762,162 @@ void LLPipeline::generateSunShadow(LLCamera& camera) if (clear) { clear = FALSE; - for (U32 i = 0; i < 4; i++) + for (U32 i = 0; i < 6; i++) { - mSunShadow[i].bindTarget(); - mSunShadow[i].clear(); - mSunShadow[i].flush(); + mShadow[i].bindTarget(); + mShadow[i].clear(); + mShadow[i].flush(); } } return; } clear = TRUE; + U32 type_mask = mRenderTypeMask; + mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) | + (1<<LLPipeline::RENDER_TYPE_ALPHA) | + (1<<LLPipeline::RENDER_TYPE_GRASS) | + (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | + (1<<LLPipeline::RENDER_TYPE_BUMP) | + (1<<LLPipeline::RENDER_TYPE_VOLUME) | + (1<<LLPipeline::RENDER_TYPE_AVATAR) | + (1<<LLPipeline::RENDER_TYPE_TREE) | + (1<<LLPipeline::RENDER_TYPE_TERRAIN) | + (1<<LLPipeline::RENDER_TYPE_WATER) | + (1<<LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW) | + (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) | + (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) | + (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) | + (1 << LLPipeline::RENDER_TYPE_PASS_SHINY)); + gGL.setColorMask(false, false); //get sun view matrix - F32 range = 128.f; - //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[4]; - glh::matrix4f proj[4]; - LLVector3 up; - + glh::matrix4f view[6]; + glh::matrix4f proj[6]; + //clip contains parallel split distances for 3 splits LLVector3 clip = gSavedSettings.getVector3("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]); - const LLPickInfo& pick_info = gViewerWindow->getLastPick(); - - if (!pick_info.mPosGlobal.isExactlyZero()) - { //squish nearest frustum based on alt-zoom (tighten up nearest frustum when focusing on tiny object - F32 focus_dist = (F32) (pick_info.mPosGlobal + LLVector3d(pick_info.mObjectOffset) - gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin())).magVec(); - mSunClipPlanes.mV[0] = llclamp(focus_dist*focus_dist, 2.f, mSunClipPlanes.mV[0]); - } - - // convenience array of 4 near clip plane distances - F32 dist[] = { 0.1f, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] }; + clip = gSavedSettings.getVector3("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 = gSavedSettings.getVector3("RenderShadowNearDist"); - F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] }; + //F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] }; - for (S32 j = 0; j < 4; j++) - { - //restore render matrices - glh_set_current_modelview(saved_view); - glh_set_current_projection(saved_proj); + LLVector3 lightDir = -mSunDir; + lightDir.normVec(); - //get center of far clip plane (for point of interest later) - LLVector3 center = camera.getOrigin() + camera.getAtAxis() * range; + glh::vec3f light_dir(lightDir.mV); - LLVector3 eye = camera.getOrigin(); + //create light space camera matrix + + LLVector3 at = lightDir; - //camera used for shadow cull/render - LLCamera shadow_cam; - - // perspective shadow map - glh::vec3f p[16]; //point cloud to be contained by shadow projection (light camera space) - glh::vec3f wp[16]; //point cloud to be contained by shadow projection (world space) - - LLVector3 lightDir = -mSunDir; - glh::vec3f light_dir(lightDir.mV); + LLVector3 up = camera.getAtAxis(); + + if (fabsf(up*lightDir) > 0.75f) + { + up = camera.getUpAxis(); + } - //create light space camera matrix - LLVector3 at; - F32 dl = camera.getLeftAxis() * lightDir; - F32 du = camera.getUpAxis() * lightDir; + /*LLVector3 left = up%at; + up = at%left;*/ - //choose an at axis such that up will be most aligned with lightDir - if (dl*dl < du*du) + up.normVec(); + at.normVec(); + + + F32 near_clip = 0.f; + { + //get visible point cloud + std::vector<LLVector3> fp; + + LLVector3 min,max; + getVisiblePointCloud(camera,min,max,fp); + + if (fp.empty()) { - at = lightDir%camera.getLeftAxis(); + mRenderTypeMask = type_mask; + return; } - else + + generateGI(camera, lightDir, fp); + + //get good split distances for frustum + for (U32 i = 0; i < fp.size(); ++i) { - at = lightDir%camera.getUpAxis(); + glh::vec3f v(fp[i].mV); + saved_view.mult_matrix_vec(v); + fp[i].setVec(v.v); } - if (at * camera.getAtAxis() < 0) + min = fp[0]; + max = fp[0]; + + //get camera space bounding box + for (U32 i = 1; i < fp.size(); ++i) { - at = -at; + 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 = gSavedSettings.getVector3("RenderShadowSplitExponent"); + + F32 da = 1.f-llmax( fabsf(lightDir*up), fabsf(lightDir*camera.getLeftAxis()) ); - LLVector3 left = lightDir%at; - up = left%lightDir; - up.normVec(); + 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] }; + + for (S32 j = 0; j < 4; j++) + { + if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA)) + { + mShadowFrustPoints[j].clear(); + } + + //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); @@ -6208,8 +7928,6 @@ void LLPipeline::generateSunShadow(LLCamera& camera) LLVector3 pn = shadow_cam.getAtAxis(); - LLVector3 frust_center; - LLVector3 min, max; //construct 8 corners of split frustum section @@ -6220,21 +7938,19 @@ void LLPipeline::generateSunShadow(LLCamera& camera) F32 dp = delta*pn; frust[i] = eye + (delta*dist[j])/dp; frust[i+4] = eye + (delta*dist[j+1])/dp; - frust_center += frust[i] + frust[i+4]; } - - //get frustum center - frust_center /= 8.f; shadow_cam.calcAgentFrustumPlanes(frust); - + shadow_cam.mFrustumCornerDist = 0.f; if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) { mShadowCamera[j] = shadow_cam; } - if (gPipeline.getVisibleExtents(shadow_cam, min, max)) + 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)) @@ -6244,6 +7960,16 @@ void LLPipeline::generateSunShadow(LLCamera& camera) 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; } @@ -6251,42 +7977,252 @@ void LLPipeline::generateSunShadow(LLCamera& camera) { mShadowExtents[j][0] = min; mShadowExtents[j][1] = max; + mShadowFrustPoints[j] = fp; } - view[j] = look(frust_center-lightDir*nearDist[j], lightDir, up); - F32 shadow_dist = nearDist[j]; - for (U32 i = 0; i < 8; i++) + //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++) { - //points in worldspace (wp) and light camera space (p) - //that must be included in shadow generation - wp[i] = glh::vec3f(frust[i].mV); - wp[i+8] = wp[i] - light_dir*shadow_dist; - view[j].mult_matrix_vec(wp[i], p[i]); - view[j].mult_matrix_vec(wp[i+8], p[i+8]); + glh::vec3f p = glh::vec3f(fp[i].mV); + view[j].mult_matrix_vec(p); + wpf.push_back(LLVector3(p.v)); } - - min = LLVector3(p[0].v); - max = LLVector3(p[0].v); - LLVector3 fmin = min; - LLVector3 fmax = max; + min = wpf[0]; + max = wpf[0]; - for (U32 i = 1; i < 16; i++) - { //find camera space AABB of frustum in light camera space - update_min_max(min, max, LLVector3(p[i].v)); - if (i < 8) - { - update_min_max(fmin, fmax, LLVector3(p[i].v)); + 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] > gSavedSettings.getF32("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(gSavedSettings.getF32("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]); + } - //generate perspective matrix that contains frustum - //proj[j] = matrix_perspective(min, max); - proj[j] = gl_ortho(min.mV[0], max.mV[0], + fovx = acos(fovx); + fovz = acos(fovz); + + if (fovx > cutoff || llround(fovz, 0.01f) > cutoff) + { + // llwarns << "WTF?" << llendl; + } + + 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); @@ -6295,9 +8231,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); - proj[j] = gl_ortho(fmin.mV[0], fmax.mV[0], - fmin.mV[1], fmax.mV[1], - -fmax.mV[2], -fmin.mV[2]); + shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR); //translate and scale to from [-1, 1] to [0, 1] glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, @@ -6310,111 +8244,155 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view; - U32 type_mask = mRenderTypeMask; - mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) | - (1<<LLPipeline::RENDER_TYPE_ALPHA) | - (1<<LLPipeline::RENDER_TYPE_GRASS) | - (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | - (1<<LLPipeline::RENDER_TYPE_BUMP) | - (1<<LLPipeline::RENDER_TYPE_VOLUME) | - (1<<LLPipeline::RENDER_TYPE_AVATAR) | - (1<<LLPipeline::RENDER_TYPE_TREE) | - (1<<LLPipeline::RENDER_TYPE_TERRAIN) | - 0); - - //clip out geometry on the same side of water as the camera - static LLCullResult result; - S32 occlude = LLPipeline::sUseOcclusion; - LLPipeline::sUseOcclusion = 1; - LLPipeline::sShadowRender = TRUE; //hack to prevent LOD updates from using sun camera origin shadow_cam.setOrigin(camera.getOrigin()); - updateCull(shadow_cam, result); - stateSort(shadow_cam, result); - - if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) - { - LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); - mShadowCamera[j+4] = shadow_cam; - } - - LLFastTimer t(LLFastTimer::FTM_SHADOW_RENDER); stop_glerror(); - mSunShadow[j].bindTarget(); - mSunShadow[j].getViewport(gGLViewport); + mShadow[j].bindTarget(); + mShadow[j].getViewport(gGLViewport); { LLGLDepthTest depth(GL_TRUE); - mSunShadow[j].clear(); + mShadow[j].clear(); } - U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP }; - LLGLEnable cull(GL_CULL_FACE); + { + LLGLEnable enable(GL_DEPTH_CLAMP_NV); + renderShadow(view[j], proj[j], shadow_cam, FALSE); + } - //generate sun shadow map - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadMatrixf(proj[j].m); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadMatrixf(view[j].m); + mShadow[j].flush(); + + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); + mShadowCamera[j+4] = shadow_cam; + } + } - stop_glerror(); - gGLLastMatrix = NULL; + //llinfos << "Shadow error: " << error << " Slope: " << best_fit_slope << llendl; + - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - glColor4f(1,1,1,1); - - glCullFace(GL_FRONT); + F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f); - stop_glerror(); + //update shadow targets + for (U32 i = 0; i < 2; i++) + { //for each current shadow + 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]; + } + } + } + } - gGL.setColorMask(false, false); + for (S32 i = 0; i < 2; i++) + { + glh_set_current_modelview(saved_view); + glh_set_current_projection(saved_proj); - gDeferredShadowProgram.bind(); + if (mShadowSpotLight[i].isNull()) { - LLFastTimer ftm(LLFastTimer::FTM_SHADOW_SIMPLE); - LLGLDisable test(GL_ALPHA_TEST); - 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); + continue; } - + + LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume(); + + if (!volume) { - LLFastTimer ftm(LLFastTimer::FTM_SHADOW_ALPHA); - LLGLEnable test(GL_ALPHA_TEST); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f); - renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE); - glColor4f(1,1,1,1); - renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + 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; - gDeferredShadowProgram.unbind(); + proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip); - renderGeomShadow(shadow_cam); + //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); - gGL.setColorMask(true, true); + glh_set_current_modelview(view[i+4]); + glh_set_current_projection(proj[i+4]); - glCullFace(GL_BACK); - LLPipeline::sUseOcclusion = occlude; - LLPipeline::sShadowRender = FALSE; - mRenderTypeMask = type_mask; + mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view; - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - gGLLastMatrix = NULL; + LLCamera shadow_cam = camera; + shadow_cam.setFar(far_clip); + shadow_cam.setOrigin(origin); - mSunShadow[j].flush(); - } + LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); + + shadow_cam.setOrigin(camera.getOrigin()); + + stop_glerror(); + + mShadow[i+4].bindTarget(); + mShadow[i+4].getViewport(gGLViewport); + + { + LLGLDepthTest depth(GL_TRUE); + mShadow[i+4].clear(); + } + + renderShadow(view[i+4], proj[i+4], shadow_cam, FALSE); + + mShadow[i+4].flush(); + } if (!gSavedSettings.getBOOL("CameraOffset")) { @@ -6431,6 +8409,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera) glMatrixMode(GL_MODELVIEW); } gGL.setColorMask(true, false); + + mRenderTypeMask = type_mask; } void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture) @@ -6470,7 +8450,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (muted) { - mask = 1 << LLPipeline::RENDER_TYPE_AVATAR; + mask = 1 << LLPipeline::RENDER_TYPE_INVISIBLE; // Peachy ;) } else { @@ -6481,7 +8461,16 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) (1<<LLPipeline::RENDER_TYPE_SIMPLE) | (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | (1<<LLPipeline::RENDER_TYPE_ALPHA) | - (1<<LLPipeline::RENDER_TYPE_INVISIBLE); + (1<<LLPipeline::RENDER_TYPE_INVISIBLE) | + (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) | + (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA) | + (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK) | + (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) | + (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK) | + (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY) | + (1 << LLPipeline::RENDER_TYPE_PASS_SHINY) | + (1 << LLPipeline::RENDER_TYPE_PASS_INVISIBLE) | + (1 << LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY); } mask = mask & gPipeline.getRenderTypeMask(); @@ -6491,6 +8480,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) S32 occlusion = sUseOcclusion; sUseOcclusion = 0; sReflectionRender = sRenderDeferred ? FALSE : TRUE; + sShadowRender = TRUE; sImpostorRender = TRUE; markVisible(avatar->mDrawable, *LLViewerCamera::getInstance()); @@ -6570,7 +8560,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (LLPipeline::sRenderDeferred) { avatar->mImpostor.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE); - addDeferredAttachments(avatar->mImpostor); + //addDeferredAttachments(avatar->mImpostor); } else { @@ -6649,6 +8639,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) sUseOcclusion = occlusion; sReflectionRender = FALSE; sImpostorRender = FALSE; + sShadowRender = FALSE; gPipeline.mRenderTypeMask = saved_mask; glMatrixMode(GL_PROJECTION); diff --git a/linden/indra/newview/pipeline.h b/linden/indra/newview/pipeline.h index 1a32b30..a85877d 100644 --- a/linden/indra/newview/pipeline.h +++ b/linden/indra/newview/pipeline.h @@ -129,6 +129,8 @@ public: void markMoved(LLDrawable *drawablep, BOOL damped_motion = FALSE); void markShift(LLDrawable *drawablep); void markTextured(LLDrawable *drawablep); + void markGLRebuild(LLGLUpdate* glu); + void markRebuild(LLSpatialGroup* group, BOOL priority = FALSE); void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE); //get the object between start and end that's closest to start. @@ -179,10 +181,14 @@ public: void updateMove(); BOOL visibleObjectsInFrustum(LLCamera& camera); BOOL getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max); + BOOL getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir = LLVector3(0,0,0)); void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane void createObjects(F32 max_dtime); void createObject(LLViewerObject* vobj); void updateGeom(F32 max_dtime); + void updateGL(); + void rebuildPriorityGroups(); + void rebuildGroups(); //calculate pixel area of given box from vantage point of given camera static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera); @@ -203,12 +209,21 @@ public: void renderGeomDeferred(LLCamera& camera); void renderGeomPostDeferred(LLCamera& camera); void renderGeomShadow(LLCamera& camera); - void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0); + void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0, LLRenderTarget* gi_source = NULL, LLRenderTarget* last_gi_post = NULL); + void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep); + void unbindDeferredShader(LLGLSLShader& shader); void renderDeferredLighting(); void generateWaterReflection(LLCamera& camera); void generateSunShadow(LLCamera& camera); + void generateHighlight(LLCamera& camera); + void renderHighlight(const LLViewerObject* obj, F32 fade); + void setHighlightObject(LLDrawable* obj) { mHighlightObject = obj; } + + + void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, BOOL use_shader = TRUE); + void generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<LLVector3>& vpc); // KL sd void renderHighlights(); void renderDebug(); @@ -303,27 +318,39 @@ public: enum LLRenderTypeMask { // Following are pool types (some are also object types) - RENDER_TYPE_SKY = LLDrawPool::POOL_SKY, - RENDER_TYPE_WL_SKY = LLDrawPool::POOL_WL_SKY, - RENDER_TYPE_GROUND = LLDrawPool::POOL_GROUND, - RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN, - RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE, - RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS, - RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT, - RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP, - RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, - RENDER_TYPE_TREE = LLDrawPool::POOL_TREE, - RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE, - RENDER_TYPE_WATER = LLDrawPool::POOL_WATER, - RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA, - RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW, - + RENDER_TYPE_SKY = LLDrawPool::POOL_SKY, + RENDER_TYPE_WL_SKY = LLDrawPool::POOL_WL_SKY, + RENDER_TYPE_GROUND = LLDrawPool::POOL_GROUND, + RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN, + RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE, + RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS, + RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT, + RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP, + RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, + RENDER_TYPE_TREE = LLDrawPool::POOL_TREE, + RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE, + RENDER_TYPE_WATER = LLDrawPool::POOL_WATER, + RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA, + RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW, + RENDER_TYPE_PASS_SIMPLE = LLRenderPass::PASS_SIMPLE, + RENDER_TYPE_PASS_GRASS = LLRenderPass::PASS_GRASS, + RENDER_TYPE_PASS_FULLBRIGHT = LLRenderPass::PASS_FULLBRIGHT, + RENDER_TYPE_PASS_INVISIBLE = LLRenderPass::PASS_INVISIBLE, + RENDER_TYPE_PASS_INVISI_SHINY = LLRenderPass::PASS_INVISI_SHINY, + RENDER_TYPE_PASS_FULLBRIGHT_SHINY = LLRenderPass::PASS_FULLBRIGHT_SHINY, + RENDER_TYPE_PASS_SHINY = LLRenderPass::PASS_SHINY, + RENDER_TYPE_PASS_BUMP = LLRenderPass::PASS_BUMP, + RENDER_TYPE_PASS_GLOW = LLRenderPass::PASS_GLOW, + RENDER_TYPE_PASS_ALPHA = LLRenderPass::PASS_ALPHA, + RENDER_TYPE_PASS_ALPHA_MASK = LLRenderPass::PASS_ALPHA_MASK, + RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, + RENDER_TYPE_PASS_ALPHA_SHADOW = LLRenderPass::PASS_ALPHA_SHADOW, // Following are object types (only used in drawable mRenderType) - RENDER_TYPE_HUD = LLDrawPool::NUM_POOL_TYPES, + RENDER_TYPE_HUD = LLRenderPass::NUM_RENDER_TYPES, RENDER_TYPE_VOLUME, RENDER_TYPE_PARTICLES, RENDER_TYPE_CLOUDS, - RENDER_TYPE_HUD_PARTICLES + RENDER_TYPE_HUD_PARTICLES // KL S19? }; enum LLRenderDebugFeatureMask @@ -361,8 +388,7 @@ public: RENDER_DEBUG_SHAME = 0x0020000, RENDER_DEBUG_SHADOW_FRUSTA = 0x0040000, RENDER_DEBUG_SCULPTED = 0x0080000, - RENDER_DEBUG_AVATAR_VOLUME = 0x0100000, - RENDER_DEBUG_AGENT_TARGET = 0x0200000, + RENDER_DEBUG_BUILD_QUEUE = 0x0100000, }; public: @@ -421,15 +447,36 @@ public: //screen texture LLRenderTarget mScreen; LLRenderTarget mDeferredScreen; - LLRenderTarget mDeferredLight[2]; + LLRenderTarget mDeferredDepth; + LLRenderTarget mDeferredLight[3]; LLMultisampleBuffer mSampleBuffer; + LLRenderTarget mGIMap; + LLRenderTarget mGIMapPost[2]; + LLRenderTarget mLuminanceMap; + LLRenderTarget mHighlight; //sun shadow map - LLRenderTarget mSunShadow[4]; + LLRenderTarget mShadow[6]; + std::vector<LLVector3> mShadowFrustPoints[4]; + LLVector4 mShadowError; + LLVector4 mShadowFOV; + LLVector3 mShadowFrustOrigin[4]; LLCamera mShadowCamera[8]; LLVector3 mShadowExtents[4][2]; - glh::matrix4f mSunShadowMatrix[4]; + glh::matrix4f mSunShadowMatrix[6]; + glh::matrix4f mGIMatrix; + glh::matrix4f mGIMatrixProj; + glh::matrix4f mGINormalMatrix; + glh::matrix4f mGIInvProj; + LLVector2 mGIRange; + F32 mGILightRadius; + + LLPointer<LLDrawable> mShadowSpotLight[2]; + F32 mSpotLightFade[2]; + LLPointer<LLDrawable> mTargetShadowSpotLight[2]; + LLVector4 mSunClipPlanes; + LLVector4 mSunOrthoClipPlanes; LLVector2 mScreenScale; @@ -444,6 +491,8 @@ public: //noise map U32 mNoiseMap; + U32 mTrueNoiseMap; + U32 mLightFunc; LLColor4 mSunDiffuse; LLVector3 mSunDir; @@ -504,12 +553,45 @@ protected: // LLDrawable::drawable_list_t mBuildQ1; // priority LLDrawable::drawable_list_t mBuildQ2; // non-priority + LLSpatialGroup::sg_list_t mGroupQ1; //priority + LLSpatialGroup::sg_vector_t mGroupQ2; // non-priority + LLViewerObject::vobj_list_t mCreateQ; LLDrawable::drawable_set_t mActiveQ; LLDrawable::drawable_set_t mRetexturedList; + class HighlightItem + { + public: + const LLPointer<LLDrawable> mItem; + mutable F32 mFade; + + HighlightItem(LLDrawable* item) + : mItem(item), mFade(0) + { + } + + bool operator<(const HighlightItem& rhs) const + { + return mItem < rhs.mItem; + } + + bool operator==(const HighlightItem& rhs) const + { + return mItem == rhs.mItem; + } + + void incrFade(F32 val) const + { + mFade = llclamp(mFade+val, 0.f, 1.f); + } + }; + + std::set<HighlightItem> mHighlightSet; + LLPointer<LLDrawable> mHighlightObject; + ////////////////////////////////////////////////// // // Draw pools are responsible for storing all rendered data, diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_hardware_settings.xml b/linden/indra/newview/skins/default/xui/en-us/floater_hardware_settings.xml index 24a895b..e85eaa8 100644 --- a/linden/indra/newview/skins/default/xui/en-us/floater_hardware_settings.xml +++ b/linden/indra/newview/skins/default/xui/en-us/floater_hardware_settings.xml @@ -64,7 +64,35 @@ tool_tip="Enabling this on modern hardware gives a performance gain. However, older hardware often has poor implementations of VBOs and you may get crashes when this is enabled." width="315" /> - <slider bottom_delta="-21" can_edit_text="false" control_name="TextureMemory" + <text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false" + bottom_delta="-20" drop_shadow_visible="true" enabled="true" follows="left|top" + font="SansSerifSmall" h_pad="0" halign="left" height="12" + left="10" mouse_opaque="true" name="Enable FBO:" v_pad="0" + width="128"> + Enable FBO: + </text> + <check_box bottom_delta="-5" control_name="RenderUseFBO" enabled="true" follows="left|top" + font="SansSerifSmall" height="16" initial_value="true" + label="Enable OpenGL Framebuffer Objects" left="148" + mouse_opaque="true" name="fbo" radio_style="false" + tool_tip="Enabling this will use OpenGL Framebuffer objects for some dynamic textures. Prerequisite for deferred rendering." + width="315" /> + + <text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false" + bottom_delta="-20" drop_shadow_visible="true" enabled="true" follows="left|top" + font="SansSerifSmall" h_pad="0" halign="left" height="12" + left="10" mouse_opaque="true" name="Deferred Rendering:" v_pad="0" + width="128"> + Deferred Rendering: + </text> + <check_box bottom_delta="-5" control_name="RenderDeferred" enabled="true" follows="left|top" + font="SansSerifSmall" height="16" initial_value="true" + label="Enable per-pixel lighting and shadows" left="148" + mouse_opaque="true" name="deferred" radio_style="false" + tool_tip="Enabling this will perform lighting calculations in screen space, enabling per pixel lighting for all lights and shadows from the sun/moon. Requires a fast graphics card. Might not be compatible with FSAA." + width="315" /> + + <slider bottom_delta="-21" can_edit_text="false" control_name="TextureMemory" decimal_digits="0" enabled="true" follows="left|top" height="16" increment="16" initial_val="32" label="Texture Memory (MB):" label_width="135" left="10" diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_tools.xml b/linden/indra/newview/skins/default/xui/en-us/floater_tools.xml index 0cb4a59..1be2e58 100644 --- a/linden/indra/newview/skins/default/xui/en-us/floater_tools.xml +++ b/linden/indra/newview/skins/default/xui/en-us/floater_tools.xml @@ -1036,25 +1036,47 @@ <text bg_visible="false" border_drop_shadow_visible="false" border_visible="false" bottom_delta="-21" drop_shadow_visible="true" follows="left|top" font="SansSerifSmall" h_pad="0" halign="left" height="10" left_delta="0" - mouse_opaque="true" name="label color" v_pad="0" width="58"> + mouse_opaque="true" name="label color" v_pad="0" width="57"> Color: </text> <color_swatch border_color="0.45098, 0.517647, 0.607843, 1" bottom_delta="-28" can_apply_immediately="true" color="0.5, 0.5, 0.5, 1" follows="left|top" - height="48" label="" left_delta="67" mouse_opaque="true" name="colorswatch" + height="48" label="" left_delta="57" mouse_opaque="true" name="colorswatch" tool_tip="Click to open Color Picker" width="32" /> + <text bg_visible="false" border_drop_shadow_visible="false" border_visible="false" + bottom_delta="28" drop_shadow_visible="true" follows="left|top" + font="SansSerifSmall" h_pad="0" height="10" left="144" + mouse_opaque="true" name="label texture" v_pad="0" width="58"> + Texture + </text> + <texture_picker allow_no_texture="true" bottom_delta="-28" can_apply_immediately="true" + default_image_name="Default" follows="left|top" height="48" label="" + left_delta="57" mouse_opaque="true" name="light texture control" + tool_tip="Click to choose a projection image (only has effect with deferred rendering enabled)" width="32" /> <spinner bottom_delta="-4" decimal_digits="3" follows="left|top" height="16" - increment="0.1" initial_val="0.5" label="Intensity:" label_width="65" - left="10" max_val="1" min_val="0" mouse_opaque="true" - name="Light Intensity" width="128" /> + increment="0.1" initial_val="0.5" label="Intensity:" label_width="55" + left="10" max_val="1" min_val="0" mouse_opaque="true" + name="Light Intensity" width="120" /> + <spinner bottom_delta="0" decimal_digits="3" follows="left|top" height="16" + increment="0.1" initial_val="0.5" label="FOV" label_width="55" + left="144" max_val="3" min_val="0" mouse_opaque="true" + name="Light FOV" width="120" /> <spinner bottom_delta="-20" decimal_digits="3" follows="left|top" height="16" - increment="0.1" initial_val="5" label="Radius:" label_width="65" - left_delta="0" max_val="20" min_val="0" mouse_opaque="true" - name="Light Radius" width="128" /> + increment="0.1" initial_val="5" label="Radius" label_width="55" + left="10" max_val="20" min_val="0" mouse_opaque="true" + name="Light Radius" width="120" /> + <spinner bottom_delta="0" decimal_digits="3" follows="left|top" height="16" + increment="0.5" initial_val="0.5" label="Focus" label_width="55" + left="144" max_val="20" min_val="-20" mouse_opaque="true" + name="Light Focus" width="120" /> <spinner bottom_delta="-20" decimal_digits="3" follows="left|top" height="16" - increment="0.25" initial_val="1" label="Falloff:" label_width="65" - left_delta="0" max_val="2" min_val="0" mouse_opaque="true" - name="Light Falloff" width="128" /> + increment="0.25" initial_val="1" label="Falloff" label_width="55" + left="10" max_val="2" min_val="0" mouse_opaque="true" + name="Light Falloff" width="120" /> + <spinner bottom_delta="0" decimal_digits="3" follows="left|top" height="16" + increment="0.05" initial_val="1" label="Ambiance" label_width="55" + left="144" max_val="1" min_val="0" mouse_opaque="true" + name="Light Ambiance" width="120" /> </panel> <!-- Texture sub-tab --> -- cgit v1.1 From a96260616070518acc70572dce4e74890ee8c529 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Tue, 7 Sep 2010 14:19:02 +0200 Subject: fix "about land" (actually llpanellandmedia) crashes --- linden/indra/newview/llpanellandmedia.cpp | 301 +++++++++++++----------------- linden/indra/newview/llpanellandmedia.h | 20 +- 2 files changed, 132 insertions(+), 189 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/llpanellandmedia.cpp b/linden/indra/newview/llpanellandmedia.cpp index db68c42..11f491c 100644 --- a/linden/indra/newview/llpanellandmedia.cpp +++ b/linden/indra/newview/llpanellandmedia.cpp @@ -39,8 +39,6 @@ #include "llmimetypes.h" #include "llviewerparcelmgr.h" #include "llviewerregion.h" -#include "llviewermedia.h" -#include "llviewerparcelmedia.h" #include "lluictrlfactory.h" // library includes @@ -56,7 +54,6 @@ #include "llsdutil.h" #include "lltexturectrl.h" #include "roles_constants.h" -#include "llscrolllistctrl.h" #include "hippoGridManager.h" @@ -65,8 +62,15 @@ //--------------------------------------------------------------------------- LLPanelLandMedia::LLPanelLandMedia(LLParcelSelectionHandle& parcel) -: LLPanel(), +: LLPanel(std::string("land_media_panel")), + mParcel(parcel), + mCheckSoundLocal(NULL), + mSoundHelpButton(NULL), + mCheckEnableVoiceChat(NULL), + mCheckEnableVoiceChatIsEstateDisabled(NULL), + mCheckEnableVoiceChatParcel(NULL), + mMusicURLEdit(NULL), mMediaURLEdit(NULL), mMediaDescEdit(NULL), mMediaTypeCombo(NULL), @@ -77,7 +81,8 @@ LLPanelLandMedia::LLPanelLandMedia(LLParcelSelectionHandle& parcel) mMediaTextureCtrl(NULL), mMediaAutoScaleCheck(NULL), mMediaLoopCheck(NULL), - mMediaUrlCheck(NULL) + mMediaUrlCheck(NULL), + mMusicUrlCheck(NULL) { } @@ -85,10 +90,34 @@ LLPanelLandMedia::LLPanelLandMedia(LLParcelSelectionHandle& parcel) // virtual LLPanelLandMedia::~LLPanelLandMedia() { + // close LLFloaterURLEntry? +} + + +// static +void LLPanelLandMedia::onClickSoundHelp(void*) +{ + LLNotifications::instance().add("ClickSoundHelpLand"); } + BOOL LLPanelLandMedia::postBuild() { + mCheckSoundLocal = getChild<LLCheckBoxCtrl>("check sound local"); + childSetCommitCallback("check sound local", onCommitAny, this); + + mSoundHelpButton = getChild<LLButton>("?"); + mSoundHelpButton->setClickedCallback(onClickSoundHelp, this); + + mCheckEnableVoiceChat = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel"); + childSetCommitCallback("parcel_enable_voice_channel", onCommitAny, this); + mCheckEnableVoiceChatIsEstateDisabled = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel_is_estate_disabled"); + childSetCommitCallback("parcel_enable_voice_channel_is_estate_disabled", onCommitAny, this); + mCheckEnableVoiceChatParcel = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel_parcel"); + childSetCommitCallback("parcel_enable_voice_channel_parcel", onCommitAny, this); + + mMusicURLEdit = getChild<LLLineEditor>("music_url"); + childSetCommitCallback("music_url", onCommitAny, this); mMediaTextureCtrl = getChild<LLTextureCtrl>("media texture"); mMediaTextureCtrl->setCommitCallback( onCommitAny ); @@ -101,13 +130,16 @@ BOOL LLPanelLandMedia::postBuild() childSetCommitCallback("media_auto_scale", onCommitAny, this); mMediaLoopCheck = getChild<LLCheckBoxCtrl>("media_loop"); - childSetCommitCallback("media_loop", onCommitAny, this ); + childSetCommitCallback("media_loop", onCommitAny, this); mMediaUrlCheck = getChild<LLCheckBoxCtrl>("hide_media_url"); - childSetCommitCallback("hide_media_url", onCommitAny, this ); + childSetCommitCallback("hide_media_url", onCommitAny, this); + + mMusicUrlCheck = getChild<LLCheckBoxCtrl>("hide_music_url"); + childSetCommitCallback("hide_music_url", onCommitAny, this); mMediaURLEdit = getChild<LLLineEditor>("media_url"); - childSetCommitCallback("media_url", onCommitAny, this ); + childSetCommitCallback("media_url", onCommitAny, this); mMediaDescEdit = getChild<LLLineEditor>("url_description"); childSetCommitCallback("url_description", onCommitAny, this); @@ -116,41 +148,15 @@ BOOL LLPanelLandMedia::postBuild() childSetCommitCallback("media type", onCommitType, this); populateMIMECombo(); - mMediaResetCtrl = getChild<LLSpinCtrl>("media_reset_time"); - childSetCommitCallback("media_reset_time", onCommitAny, this); - mMediaResetCtrlLabel = getChild<LLTextBox>("media_reset"); - mMediaWidthCtrl = getChild<LLSpinCtrl>("media_size_width"); childSetCommitCallback("media_size_width", onCommitAny, this); mMediaHeightCtrl = getChild<LLSpinCtrl>("media_size_height"); childSetCommitCallback("media_size_height", onCommitAny, this); mMediaSizeCtrlLabel = getChild<LLTextBox>("media_size"); - mMediaNavigateAllowCheck = getChild<LLCheckBoxCtrl>("check navigate allow"); - childSetCommitCallback("check navigate allow", onCommitAny, this); - mMediaURLFilterCheck = getChild<LLCheckBoxCtrl>("check navigate filter"); - childSetCommitCallback("check navigate filter", onCommitAny, this); - mSetURLButton = getChild<LLButton>("set_media_url"); childSetAction("set_media_url", onSetBtn, this); - mResetURLButton = getChild<LLButton>("reset_media_url"); - childSetAction("reset_media_url", onResetBtn, this); - - mURLFilterList = getChild<LLScrollListCtrl>("filter_list"); - - mMediaURLFilterDomainEdit = getChild<LLLineEditor>("navigate_filter_domain"); - - mMediaURLFilterAddButton = getChild<LLButton>("add_navigate_filter"); - childSetAction("add_navigate_filter", onClickAddURLFilter, this); - - mMediaURLFilterRemoveButton = getChild<LLButton>("remove_navigate_filter"); - childSetAction("remove_navigate_filter", onClickRemoveURLFilter, this); - - mRadioNavigateControl = getChild<LLRadioGroup>("radio_navigate_allow"); - childSetCommitCallback("radio_navigate_allow", onCommitAny, this); - - return TRUE; } @@ -171,9 +177,59 @@ void LLPanelLandMedia::refresh() // Display options BOOL can_change_media = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_CHANGE_MEDIA); - mCheckSoundLocal->set( parcel->getSoundLocal() ); + mCheckSoundLocal->set( parcel->getSoundLocal() ); + mCheckSoundLocal->setEnabled( can_change_media ); + + LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + if (!region) + { + // never seen this happen, but log it + llwarns << "Couldn't get selected region." << llendl; + } + + // We need to do this differently for OpenSim because it doesn't include + // REGION_FLAGS_ALLOW_VOICE in the "RegionInfo" message as of 0.6.9 PF -- MC + bool allow_voice = parcel->getParcelFlagAllowVoice(); + if (gHippoGridManager->getConnectedGrid()->isSecondLife()) + { + if (region && region->isVoiceEnabled()) // estate-wide voice-disable overrides all + { + mCheckEnableVoiceChatIsEstateDisabled->setVisible(false); + + mCheckEnableVoiceChat->setVisible(true); + mCheckEnableVoiceChat->setEnabled( can_change_media ); + mCheckEnableVoiceChat->set(allow_voice); + + mCheckEnableVoiceChatParcel->setEnabled( can_change_media && allow_voice ); + } + else // disabled at region level + { + mCheckEnableVoiceChatIsEstateDisabled->setVisible(true); // always disabled + mCheckEnableVoiceChat->setVisible(false); + mCheckEnableVoiceChat->setEnabled(false); + mCheckEnableVoiceChat->set(false); + + mCheckEnableVoiceChatParcel->setEnabled(false); + } + } + else + { + mCheckEnableVoiceChatIsEstateDisabled->setVisible(true); + + mCheckEnableVoiceChat->setVisible(true); + mCheckEnableVoiceChat->setEnabled( can_change_media ); + mCheckEnableVoiceChat->set(allow_voice); + + mCheckEnableVoiceChatParcel->setEnabled( can_change_media && allow_voice ); + } + + mCheckEnableVoiceChatParcel->set(!parcel->getParcelFlagUseEstateVoiceChannel()); + + mMusicURLEdit->setText(parcel->getMusicURL()); + mMusicURLEdit->setEnabled( can_change_media ); - childSetText("current_url", parcel->getMediaCurrentURL()); + mMediaURLEdit->setText(parcel->getMediaURL()); + mMediaURLEdit->setEnabled( FALSE ); mMediaDescEdit->setText(parcel->getMediaDesc()); mMediaDescEdit->setEnabled( can_change_media ); @@ -190,11 +246,15 @@ void LLPanelLandMedia::refresh() mMediaUrlCheck->set( parcel->getObscureMedia() ); mMediaUrlCheck->setEnabled( can_change_media ); + mMusicUrlCheck->set( parcel->getObscureMusic() ); + mMusicUrlCheck->setEnabled( can_change_media ); + // don't display urls if you're not able to change it // much requested change in forums so people can't 'steal' urls // NOTE: bug#2009 means this is still vunerable - however, bug // should be closed since this bug opens up major security issues elsewhere. bool obscure_media = ! can_change_media && parcel->getObscureMedia(); + bool obscure_music = ! can_change_media && parcel->getObscureMusic(); // Special code to disable asterixes for html type if(mime_type == "text/html") @@ -204,6 +264,7 @@ void LLPanelLandMedia::refresh() mMediaUrlCheck->setEnabled( false ); } + mMusicURLEdit->setDrawAsterixes( obscure_music ); mMediaURLEdit->setDrawAsterixes( obscure_media ); mMediaAutoScaleCheck->set( parcel->getMediaAutoScale () ); @@ -217,10 +278,6 @@ void LLPanelLandMedia::refresh() else mMediaLoopCheck->set( false ); mMediaLoopCheck->setEnabled ( can_change_media && allow_looping ); - - mMediaResetCtrl->set( parcel->getMediaURLTimeout() ); - mMediaResetCtrl->setEnabled( can_change_media ); - mMediaResetCtrlLabel->setEnabled( can_change_media ); // disallow media size change for mime types that don't allow it bool allow_resize = LLMIMETypes::findAllowResize( mime_type ); @@ -244,45 +301,28 @@ void LLPanelLandMedia::refresh() mMediaTextureCtrl->setEnabled( can_change_media ); mSetURLButton->setEnabled( can_change_media ); - mResetURLButton->setEnabled( can_change_media ); - mMediaURLFilterCheck->set( parcel->getMediaURLFilterEnable() ); - mMediaURLFilterCheck->setEnabled( can_change_media ); + #if 0 + // there is a media url and a media texture selected + if ( ( ! ( std::string ( parcel->getMediaURL() ).empty () ) ) && ( ! ( parcel->getMediaID ().isNull () ) ) ) + { + // turn on transport controls if allowed for this parcel + mMediaStopButton->setEnabled ( editable ); + mMediaStartButton->setEnabled ( editable ); + } + else + { + // no media url or no media texture + mMediaStopButton->setEnabled ( FALSE ); + mMediaStartButton->setEnabled ( FALSE ); + }; + #endif LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mURLEntryFloater.get(); if (floater_url_entry) { floater_url_entry->updateFromLandMediaPanel(); } - - // This radial control is really just an inverse mapping to the boolean allow_navigate value. - // It is set as a radial merely for user readability. - mRadioNavigateControl->setSelectedIndex(! parcel->getMediaAllowNavigate()); - mRadioNavigateControl->setEnabled( can_change_media ); - - mMediaURLFilterDomainEdit->setEnabled( can_change_media ); - mMediaURLFilterAddButton->setEnabled( can_change_media ); - mMediaURLFilterRemoveButton->setEnabled( can_change_media ); - - if (mURLFilterList) - { - mURLFilterList->setEnabled( can_change_media ); - - mURLFilterList->deleteAllItems(); - - LLSD list = parcel->getMediaURLFilterList(); - - for (LLSD::array_iterator i = list.beginArray(); i != list.endArray(); ++i) - { - std::string domain = (*i).asString(); - - LLSD element; - element["id"] = domain; - element["columns"][0]["value"] = domain; - - mURLFilterList->addElement(element); - } - } } } @@ -318,6 +358,7 @@ void LLPanelLandMedia::setMediaType(const std::string& mime_type) std::string media_key = LLMIMETypes::widgetType(mime_type); mMediaTypeCombo->setValue(media_key); + childSetText("mime_type", mime_type); } @@ -329,14 +370,14 @@ void LLPanelLandMedia::setMediaURL(const std::string& media_url) parcel->setMediaCurrentURL(media_url); // LLViewerMedia::navigateHome(); - mMediaURLEdit->onCommit(); - // LLViewerParcelMedia::sendMediaNavigateMessage(media_url); - childSetText("current_url", media_url); +// // LLViewerParcelMedia::sendMediaNavigateMessage(media_url); +// childSetText("current_url", media_url); } + std::string LLPanelLandMedia::getMediaURL() { - return mMediaURLEdit->getText(); + return mMediaURLEdit->getText(); } // static @@ -365,26 +406,33 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata) } // Extract data from UI + BOOL sound_local = self->mCheckSoundLocal->get(); + std::string music_url = self->mMusicURLEdit->getText(); std::string media_url = self->mMediaURLEdit->getText(); std::string media_desc = self->mMediaDescEdit->getText(); std::string mime_type = self->childGetText("mime_type"); U8 media_auto_scale = self->mMediaAutoScaleCheck->get(); U8 media_loop = self->mMediaLoopCheck->get(); U8 obscure_media = self->mMediaUrlCheck->get(); - F32 media_reset_time = (F32)self->mMediaResetCtrl->get(); + U8 obscure_music = self->mMusicUrlCheck->get(); S32 media_width = (S32)self->mMediaWidthCtrl->get(); S32 media_height = (S32)self->mMediaHeightCtrl->get(); LLUUID media_id = self->mMediaTextureCtrl->getImageAssetID(); - U8 navigate_allow = ! self->mRadioNavigateControl->getSelectedIndex(); - U8 navigate_filter = self->mMediaURLFilterCheck->get(); + BOOL voice_enabled = self->mCheckEnableVoiceChat->get(); + BOOL voice_estate_chan = ! self->mCheckEnableVoiceChatParcel->get(); self->childSetText("mime_type", mime_type); // Remove leading/trailing whitespace (common when copying/pasting) + LLStringUtil::trim(music_url); LLStringUtil::trim(media_url); // Push data into current parcel + parcel->setParcelFlag(PF_ALLOW_VOICE_CHAT, voice_enabled); + parcel->setParcelFlag(PF_USE_ESTATE_VOICE_CHAN, voice_estate_chan); + parcel->setParcelFlag(PF_SOUND_LOCAL, sound_local); + parcel->setMusicURL(music_url); parcel->setMediaURL(media_url); parcel->setMediaType(mime_type); parcel->setMediaDesc(media_desc); @@ -394,10 +442,7 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata) parcel->setMediaAutoScale ( media_auto_scale ); parcel->setMediaLoop ( media_loop ); parcel->setObscureMedia( obscure_media ); - parcel->setMediaURLFilterEnable(navigate_filter); - parcel->setMediaAllowNavigate(navigate_allow); - parcel->setMediaURLTimeout(media_reset_time); - + parcel->setObscureMusic( obscure_music ); // Send current parcel data upstream to server LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); @@ -415,92 +460,4 @@ void LLPanelLandMedia::onSetBtn(void *userdata) { parent_floater->addDependentFloater(self->mURLEntryFloater.get()); } -} - -// static -void LLPanelLandMedia::onResetBtn(void *userdata) -{ - LLPanelLandMedia *self = (LLPanelLandMedia *)userdata; - LLParcel* parcel = self->mParcel->getParcel(); - // LLViewerMedia::navigateHome(); - self->refresh(); - self->childSetText("current_url", parcel->getMediaURL()); - // LLViewerParcelMedia::sendMediaNavigateMessage(parcel->getMediaURL()); - -} -// static -void LLPanelLandMedia::onClickAddURLFilter(void *userdata) -{ - LLPanelLandMedia *panelp = (LLPanelLandMedia *)userdata; - LLParcel* parcel = panelp->mParcel->getParcel(); - - LLSD list = parcel->getMediaURLFilterList(); - - std::string domain = panelp->mMediaURLFilterDomainEdit->getText(); - LLStringUtil::trim(domain); - - BOOL add = TRUE; - if (domain == "") - { - add = FALSE; - } - - // check for dupes - for(S32 i = 0; i < list.size(); i++) - { - if (list[i].asString() == domain) - { - add = FALSE; - break; - } - } - - if (add) - { - list.append(domain); - parcel->setMediaURLFilterList(list); - - LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); - - panelp->mMediaURLFilterDomainEdit->setText(std::string("")); - - panelp->refresh(); - } - -} - -// static -void LLPanelLandMedia::onClickRemoveURLFilter(void *data) -{ - LLPanelLandMedia* panelp = (LLPanelLandMedia*)data; - if (panelp && panelp->mURLFilterList) - { - LLParcel* parcel = panelp->mParcel->getParcel(); - if (parcel) - { - LLSD list = parcel->getMediaURLFilterList(); - - std::vector<LLScrollListItem*> domains = panelp->mURLFilterList->getAllSelected(); - for (std::vector<LLScrollListItem*>::iterator iter = domains.begin(); iter != domains.end(); iter++) - { - LLScrollListItem* item = *iter; - const std::string domain = item->getValue().asString(); - - for(S32 i = 0; i < list.size(); i++) - { - if (list[i].asString() == domain) - { - list.erase(i); - break; - } - } - } - - parcel->setMediaURLFilterList(list); - LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); - - panelp->refresh(); - } - } - -} +} \ No newline at end of file diff --git a/linden/indra/newview/llpanellandmedia.h b/linden/indra/newview/llpanellandmedia.h index d63f0f6..845b953 100644 --- a/linden/indra/newview/llpanellandmedia.h +++ b/linden/indra/newview/llpanellandmedia.h @@ -56,10 +56,8 @@ private: static void onCommitAny(LLUICtrl* ctrl, void *userdata); static void onCommitType(LLUICtrl* ctrl, void *userdata); static void onSetBtn(void* userdata); - static void onResetBtn(void* userdata); - static void onClickAddURLFilter(void *userdata); - static void onClickRemoveURLFilter(void *userdata); - + static void onClickSoundHelp(void*); + private: LLCheckBoxCtrl* mCheckSoundLocal; LLButton* mSoundHelpButton; @@ -71,11 +69,8 @@ private: LLLineEditor* mMediaDescEdit; LLComboBox* mMediaTypeCombo; LLButton* mSetURLButton; - LLButton* mResetURLButton; - LLSpinCtrl* mMediaResetCtrl; LLSpinCtrl* mMediaHeightCtrl; LLSpinCtrl* mMediaWidthCtrl; - LLTextBox* mMediaResetCtrlLabel; LLTextBox* mMediaSizeCtrlLabel; LLTextureCtrl* mMediaTextureCtrl; LLCheckBoxCtrl* mMediaAutoScaleCheck; @@ -83,17 +78,8 @@ private: LLCheckBoxCtrl* mMediaUrlCheck; LLCheckBoxCtrl* mMusicUrlCheck; LLHandle<LLFloater> mURLEntryFloater; - LLCheckBoxCtrl* mMediaNavigateAllowCheck; - LLCheckBoxCtrl* mMediaURLFilterCheck; - LLLineEditor* mMediaURLFilterDomainEdit; - LLButton* mMediaURLFilterAddButton; - LLButton* mMediaURLFilterRemoveButton; - LLScrollListCtrl* mURLFilterList; - LLRadioGroup* mRadioNavigateControl; - - LLSafeHandle<LLParcelSelection>& mParcel; }; -#endif +#endif \ No newline at end of file -- cgit v1.1 From 106b42c9fc893c3172dc843a70b6e79a22eed985 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Mon, 9 Aug 2010 19:03:58 +0200 Subject: fix some mime type issues --- linden/indra/llinventory/llparcel.cpp | 13 ++-- .../newview/skins/default/xui/en-us/mime_types.xml | 31 +++++++++- .../skins/default/xui/en-us/mime_types_linux.xml | 71 ++++++++++++++++------ .../skins/default/xui/en-us/mime_types_mac.xml | 69 +++++++++++++++------ 4 files changed, 139 insertions(+), 45 deletions(-) mode change 100644 => 100755 linden/indra/newview/skins/default/xui/en-us/mime_types_linux.xml mode change 100644 => 100755 linden/indra/newview/skins/default/xui/en-us/mime_types_mac.xml (limited to 'linden') diff --git a/linden/indra/llinventory/llparcel.cpp b/linden/indra/llinventory/llparcel.cpp index 547862f..39605eb 100644 --- a/linden/indra/llinventory/llparcel.cpp +++ b/linden/indra/llinventory/llparcel.cpp @@ -306,11 +306,11 @@ void LLParcel::setMediaType(const std::string& type) mMediaType = type; mMediaType = rawstr_to_utf8(mMediaType); - // This code attempts to preserve legacy movie functioning - if(mMediaType.empty() && ! mMediaURL.empty()) - { - setMediaType(std::string("video/vnd.secondlife.qt.legacy")); - } +// // This legacy code prevents any media different from video from working on OpenSim +// if(mMediaType.empty() && ! mMediaURL.empty()) +// { +// setMediaType(std::string("video/vnd.secondlife.qt.legacy")); +// } } void LLParcel::setMediaWidth(S32 width) { @@ -762,7 +762,8 @@ void LLParcel::unpackMessage(LLMessageSystem* msg) } else { - setMediaType(std::string("video/vnd.secondlife.qt.legacy")); + setMediaType(std::string("")); //having mMediaType empty causes autodetect, + // thats what we want -- AW setMediaDesc(std::string("No Description available without Server Upgrade")); mMediaLoop = true; mObscureMedia = true; diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types.xml index 9f0c631..a585069 100644 --- a/linden/indra/newview/skins/default/xui/en-us/mime_types.xml +++ b/linden/indra/newview/skins/default/xui/en-us/mime_types.xml @@ -120,7 +120,7 @@ none </widgettype> <impl> - media_plugin_quicktime + media_plugin_webkit </impl> </mimetype> <mimetype name="none/none"> @@ -130,6 +130,9 @@ <widgettype> none </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="audio/*"> <label name="audio2_label"> @@ -160,6 +163,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> <label name="vnd.secondlife.qt.legacy_label"> @@ -179,6 +185,9 @@ <widgettype> web </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/ogg"> <label name="application/ogg_label"> @@ -187,6 +196,9 @@ <widgettype> audio </widgettype> + <impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="application/pdf"> <label name="application/pdf_label"> @@ -195,6 +207,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/postscript"> <label name="application/postscript_label"> @@ -203,6 +218,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/rtf"> <label name="application/rtf_label"> @@ -211,6 +229,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/smil"> <label name="application/smil_label"> @@ -220,7 +241,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_webkit </impl> </mimetype> <mimetype name="application/xhtml+xml"> @@ -230,6 +251,9 @@ <widgettype> web </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/x-director"> <label name="application/x-director_label"> @@ -238,6 +262,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="audio/mid"> <label name="audio/mid_label"> diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types_linux.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types_linux.xml old mode 100644 new mode 100755 index 2977d7a..e95b371 --- a/linden/indra/newview/skins/default/xui/en-us/mime_types_linux.xml +++ b/linden/indra/newview/skins/default/xui/en-us/mime_types_linux.xml @@ -120,7 +120,7 @@ none </widgettype> <impl> - media_plugin_gstreamer + media_plugin_webkit </impl> </mimetype> <mimetype name="none/none"> @@ -130,6 +130,9 @@ <widgettype> none </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="audio/*"> <label name="audio2_label"> @@ -138,6 +141,9 @@ <widgettype> audio </widgettype> + <impl> + media_plugin_gstreamer + </impl> </mimetype> <mimetype name="video/*"> <label name="video2_label"> @@ -146,6 +152,9 @@ <widgettype> movie </widgettype> + <impl> + media_plugin_gstreamer + </impl> </mimetype> <mimetype name="image/*"> <label name="image2_label"> @@ -154,6 +163,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> <label name="vnd.secondlife.qt.legacy_label"> @@ -163,8 +175,8 @@ movie </widgettype> <impl> - media_plugin_gstreamer - </impl> + media_plugin_gstreamer + </impl> </mimetype> <mimetype name="application/javascript"> <label name="application/javascript_label"> @@ -173,6 +185,9 @@ <widgettype> web </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/ogg"> <label name="application/ogg_label"> @@ -181,6 +196,9 @@ <widgettype> audio </widgettype> + <impl> + media_plugin_gstreamer + </impl> </mimetype> <mimetype name="application/pdf"> <label name="application/pdf_label"> @@ -189,6 +207,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/postscript"> <label name="application/postscript_label"> @@ -197,6 +218,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/rtf"> <label name="application/rtf_label"> @@ -205,16 +229,19 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/smil"> <label name="application/smil_label"> - Synchronized Multimedia Integration Language (SMIL) + Synchronized Multimedia Integration Language (SMIL) </label> <widgettype> movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_webkit </impl> </mimetype> <mimetype name="application/xhtml+xml"> @@ -224,6 +251,9 @@ <widgettype> web </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/x-director"> <label name="application/x-director_label"> @@ -232,6 +262,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="audio/mid"> <label name="audio/mid_label"> @@ -351,8 +384,8 @@ web </widgettype> <impl> - media_plugin_webkit - </impl> + media_plugin_webkit + </impl> </mimetype> <mimetype menu="1" name="text/plain"> <label name="text/plain_label"> @@ -384,8 +417,8 @@ movie </widgettype> <impl> - media_plugin_gstreamer - </impl> + media_plugin_gstreamer + </impl> </mimetype> <mimetype name="video/mp4"> <label name="video/mp4_label"> @@ -395,8 +428,8 @@ movie </widgettype> <impl> - media_plugin_gstreamer - </impl> + media_plugin_gstreamer + </impl> </mimetype> <mimetype menu="1" name="video/quicktime"> <label name="video/quicktime_label"> @@ -406,8 +439,8 @@ movie </widgettype> <impl> - media_plugin_gstreamer - </impl> + media_plugin_gstreamer + </impl> </mimetype> <mimetype name="video/x-ms-asf"> <label name="video/x-ms-asf_label"> @@ -417,8 +450,8 @@ movie </widgettype> <impl> - media_plugin_gstreamer - </impl> + media_plugin_gstreamer + </impl> </mimetype> <mimetype name="video/x-ms-wmv"> <label name="video/x-ms-wmv_label"> @@ -428,8 +461,8 @@ movie </widgettype> <impl> - media_plugin_gstreamer - </impl> + media_plugin_gstreamer + </impl> </mimetype> <mimetype menu="1" name="video/x-msvideo"> <label name="video/x-msvideo_label"> @@ -439,7 +472,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer - </impl> + media_plugin_gstreamer + </impl> </mimetype> </mimetypes> diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types_mac.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types_mac.xml old mode 100644 new mode 100755 index 4a7a6e1..7931e55 --- a/linden/indra/newview/skins/default/xui/en-us/mime_types_mac.xml +++ b/linden/indra/newview/skins/default/xui/en-us/mime_types_mac.xml @@ -130,6 +130,9 @@ <widgettype> none </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="audio/*"> <label name="audio2_label"> @@ -138,6 +141,9 @@ <widgettype> audio </widgettype> + <impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="video/*"> <label name="video2_label"> @@ -146,6 +152,9 @@ <widgettype> movie </widgettype> + <impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="image/*"> <label name="image2_label"> @@ -154,6 +163,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> <label name="vnd.secondlife.qt.legacy_label"> @@ -163,8 +175,8 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="application/javascript"> <label name="application/javascript_label"> @@ -173,6 +185,9 @@ <widgettype> web </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/ogg"> <label name="application/ogg_label"> @@ -181,6 +196,9 @@ <widgettype> audio </widgettype> + <impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="application/pdf"> <label name="application/pdf_label"> @@ -189,6 +207,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/postscript"> <label name="application/postscript_label"> @@ -197,6 +218,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/rtf"> <label name="application/rtf_label"> @@ -205,16 +229,19 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/smil"> <label name="application/smil_label"> - Synchronized Multimedia Integration Language (SMIL) + Synchronized Multimedia Integration Language (SMIL) </label> <widgettype> movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_webkit </impl> </mimetype> <mimetype name="application/xhtml+xml"> @@ -224,6 +251,9 @@ <widgettype> web </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/x-director"> <label name="application/x-director_label"> @@ -232,6 +262,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="audio/mid"> <label name="audio/mid_label"> @@ -351,8 +384,8 @@ web </widgettype> <impl> - media_plugin_webkit - </impl> + media_plugin_webkit + </impl> </mimetype> <mimetype menu="1" name="text/plain"> <label name="text/plain_label"> @@ -384,8 +417,8 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="video/mp4"> <label name="video/mp4_label"> @@ -395,8 +428,8 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype menu="1" name="video/quicktime"> <label name="video/quicktime_label"> @@ -406,8 +439,8 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="video/x-ms-asf"> <label name="video/x-ms-asf_label"> @@ -417,8 +450,8 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="video/x-ms-wmv"> <label name="video/x-ms-wmv_label"> @@ -428,8 +461,8 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype menu="1" name="video/x-msvideo"> <label name="video/x-msvideo_label"> @@ -439,7 +472,7 @@ movie </widgettype> <impl> - media_plugin_quicktime - </impl> + media_plugin_quicktime + </impl> </mimetype> </mimetypes> -- cgit v1.1 From 70800de39a3d942d2120abd926fbdb24577fb0f6 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Sat, 7 Aug 2010 19:17:13 +0200 Subject: update to viewer-external SLPlugin + webkit. Fixes (lots of) webpages not loading. Issue: llqtwebkit needs update for Linux 64bit --- linden/indra/cmake/PulseAudio.cmake | 28 + linden/indra/llplugin/CMakeLists.txt | 19 + linden/indra/llplugin/llpluginclassmedia.cpp | 26 +- linden/indra/llplugin/llpluginclassmedia.h | 9 + linden/indra/llplugin/llpluginclassmediaowner.h | 2 + linden/indra/llplugin/llplugincookiestore.cpp | 671 +++++++++++++++++++++ linden/indra/llplugin/llplugincookiestore.h | 127 ++++ linden/indra/llplugin/llpluginmessagepipe.cpp | 121 +++- linden/indra/llplugin/llpluginmessagepipe.h | 9 +- linden/indra/llplugin/llpluginprocesschild.cpp | 77 ++- linden/indra/llplugin/llpluginprocesschild.h | 7 + linden/indra/llplugin/llpluginprocessparent.cpp | 455 +++++++++++++- linden/indra/llplugin/llpluginprocessparent.h | 32 +- linden/indra/llplugin/slplugin/CMakeLists.txt | 39 +- linden/indra/llplugin/slplugin/slplugin-objc.h | 42 ++ linden/indra/llplugin/slplugin/slplugin-objc.mm | 89 +++ linden/indra/llplugin/slplugin/slplugin.cpp | 111 +++- linden/indra/llplugin/slplugin/slplugin_info.plist | 4 +- linden/indra/media_plugins/webkit/CMakeLists.txt | 35 +- .../media_plugins/webkit/dummy_volume_catcher.cpp | 65 ++ .../media_plugins/webkit/linux_volume_catcher.cpp | 79 +-- .../webkit/linux_volume_catcher_pa_syms.inc | 0 .../webkit/linux_volume_catcher_paglib_syms.inc | 0 .../media_plugins/webkit/mac_volume_catcher.cpp | 275 +++++++++ .../media_plugins/webkit/media_plugin_webkit.cpp | 62 +- linden/indra/media_plugins/webkit/volume_catcher.h | 61 ++ .../webkit/windows_volume_catcher.cpp | 124 ++++ linden/install.xml | 38 +- 28 files changed, 2445 insertions(+), 162 deletions(-) create mode 100644 linden/indra/cmake/PulseAudio.cmake create mode 100644 linden/indra/llplugin/llplugincookiestore.cpp create mode 100644 linden/indra/llplugin/llplugincookiestore.h create mode 100644 linden/indra/llplugin/slplugin/slplugin-objc.h create mode 100644 linden/indra/llplugin/slplugin/slplugin-objc.mm create mode 100644 linden/indra/media_plugins/webkit/dummy_volume_catcher.cpp mode change 100755 => 100644 linden/indra/media_plugins/webkit/linux_volume_catcher.cpp mode change 100755 => 100644 linden/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc mode change 100755 => 100644 linden/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc create mode 100644 linden/indra/media_plugins/webkit/mac_volume_catcher.cpp create mode 100644 linden/indra/media_plugins/webkit/volume_catcher.h create mode 100644 linden/indra/media_plugins/webkit/windows_volume_catcher.cpp (limited to 'linden') diff --git a/linden/indra/cmake/PulseAudio.cmake b/linden/indra/cmake/PulseAudio.cmake new file mode 100644 index 0000000..f8087a8 --- /dev/null +++ b/linden/indra/cmake/PulseAudio.cmake @@ -0,0 +1,28 @@ +# -*- cmake -*- +include(Prebuilt) + +if (STANDALONE) + include(FindPkgConfig) + + pkg_check_modules(PULSEAUDIO REQUIRED libpulse-mainloop-glib) + +elseif (LINUX) + use_prebuilt_binary(pulseaudio) + set(PULSEAUDIO_FOUND ON FORCE BOOL) + set(PULSEAUDIO_INCLUDE_DIRS + ${LIBS_PREBUILT_DIR}/include + ) + # We don't need to explicitly link against pulseaudio itself, because + # the viewer probes for the system's copy at runtime. + set(PULSEAUDIO_LIBRARIES + # none needed! + ) +endif (STANDALONE) + +if (PULSEAUDIO_FOUND) + set(PULSEAUDIO ON CACHE BOOL "Build with PulseAudio support, if available.") +endif (PULSEAUDIO_FOUND) + +if (PULSEAUDIO) + add_definitions(-DLL_PULSEAUDIO_ENABLED=1) +endif (PULSEAUDIO) diff --git a/linden/indra/llplugin/CMakeLists.txt b/linden/indra/llplugin/CMakeLists.txt index 8a2eff8..8eead94 100644 --- a/linden/indra/llplugin/CMakeLists.txt +++ b/linden/indra/llplugin/CMakeLists.txt @@ -7,6 +7,7 @@ if(HAVE_64_BIT) endif(HAVE_64_BIT) include(00-Common) +include(CURL) include(LLCommon) include(LLImage) include(LLMath) @@ -27,6 +28,7 @@ include_directories( set(llplugin_SOURCE_FILES llpluginclassmedia.cpp + llplugincookiestore.cpp llplugininstance.cpp llpluginmessage.cpp llpluginmessagepipe.cpp @@ -40,6 +42,7 @@ set(llplugin_HEADER_FILES llpluginclassmedia.h llpluginclassmediaowner.h + llplugincookiestore.h llplugininstance.h llpluginmessage.h llpluginmessageclasses.h @@ -65,3 +68,19 @@ list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES}) add_library (llplugin ${llplugin_SOURCE_FILES}) add_subdirectory(slplugin) + +# # Add tests +# include(LLAddBuildTest) +# # UNIT TESTS +# SET(llplugin_TEST_SOURCE_FILES +# llplugincookiestore.cpp +# ) +# +# # llplugincookiestore has a dependency on curl, so we need to link the curl library into the test. +# set_source_files_properties( +# llplugincookiestore.cpp +# PROPERTIES +# LL_TEST_ADDITIONAL_LIBRARIES "${CURL_LIBRARIES}" +# ) +# +# LL_ADD_PROJECT_UNIT_TESTS(llplugin "${llplugin_TEST_SOURCE_FILES}") \ No newline at end of file diff --git a/linden/indra/llplugin/llpluginclassmedia.cpp b/linden/indra/llplugin/llpluginclassmedia.cpp index b958f0c..8664524 100755 --- a/linden/indra/llplugin/llpluginclassmedia.cpp +++ b/linden/indra/llplugin/llpluginclassmedia.cpp @@ -59,11 +59,15 @@ LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner) mOwner = owner; mPlugin = NULL; reset(); + + //debug use + mDeleteOK = true ; } LLPluginClassMedia::~LLPluginClassMedia() { + llassert_always(mDeleteOK) ; reset(); } @@ -162,7 +166,7 @@ void LLPluginClassMedia::idle(void) mPlugin->idle(); } - if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL)) + if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked())) { // Can't process a size change at this time } @@ -439,6 +443,12 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int { if(type == MOUSE_EVENT_MOVE) { + if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked()) + { + // Don't queue up mouse move events that can't be delivered. + return; + } + if((x == mLastMouseX) && (y == mLastMouseY)) { // Don't spam unnecessary mouse move events. @@ -995,6 +1005,13 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mClickTargetType = TARGET_NONE; mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW); } + else if(message_name == "cookie_set") + { + if(mOwner) + { + mOwner->handleCookieSet(this, message.getValue("cookie")); + } + } else { LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; @@ -1078,6 +1095,13 @@ void LLPluginClassMedia::clear_cookies() sendMessage(message); } +void LLPluginClassMedia::set_cookies(const std::string &cookies) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies"); + message.setValue("cookies", cookies); + sendMessage(message); +} + void LLPluginClassMedia::enable_cookies(bool enable) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies"); diff --git a/linden/indra/llplugin/llpluginclassmedia.h b/linden/indra/llplugin/llpluginclassmedia.h index fc94563..abb7926 100755 --- a/linden/indra/llplugin/llpluginclassmedia.h +++ b/linden/indra/llplugin/llpluginclassmedia.h @@ -191,6 +191,7 @@ public: void focus(bool focused); void clear_cache(); void clear_cookies(); + void set_cookies(const std::string &cookies); void enable_cookies(bool enable); void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0); void browse_stop(); @@ -374,6 +375,14 @@ protected: F64 mCurrentRate; F64 mLoadedDuration; +//-------------------------------------- + //debug use only + // +private: + bool mDeleteOK ; +public: + void setDeleteOK(bool flag) { mDeleteOK = flag ;} +//-------------------------------------- }; #endif // LL_LLPLUGINCLASSMEDIA_H diff --git a/linden/indra/llplugin/llpluginclassmediaowner.h b/linden/indra/llplugin/llpluginclassmediaowner.h index c1f6ae1..9d1f352 100755 --- a/linden/indra/llplugin/llpluginclassmediaowner.h +++ b/linden/indra/llplugin/llpluginclassmediaowner.h @@ -41,6 +41,7 @@ #include <queue> class LLPluginClassMedia; +class LLPluginCookieStore; class LLPluginClassMediaOwner { @@ -80,6 +81,7 @@ public: virtual ~LLPluginClassMediaOwner() {}; virtual void handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent /*event*/) {}; + virtual void handleCookieSet(LLPluginClassMedia* /*self*/, const std::string &/*cookie*/) {}; }; #endif // LL_LLPLUGINCLASSMEDIAOWNER_H diff --git a/linden/indra/llplugin/llplugincookiestore.cpp b/linden/indra/llplugin/llplugincookiestore.cpp new file mode 100644 index 0000000..283ba35 --- /dev/null +++ b/linden/indra/llplugin/llplugincookiestore.cpp @@ -0,0 +1,671 @@ +/** + * @file llplugincookiestore.cpp + * @brief LLPluginCookieStore provides central storage for http cookies used by plugins + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#include "linden_common.h" +#include "indra_constants.h" + +#include "llplugincookiestore.h" +#include <iostream> + +// for curl_getdate() (apparently parsing RFC 1123 dates is hard) +#include <curl/curl.h> + +LLPluginCookieStore::LLPluginCookieStore(): + mHasChangedCookies(false) +{ +} + + +LLPluginCookieStore::~LLPluginCookieStore() +{ + clearCookies(); +} + + +LLPluginCookieStore::Cookie::Cookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end): + mCookie(s, cookie_start, cookie_end - cookie_start), + mNameStart(0), mNameEnd(0), + mValueStart(0), mValueEnd(0), + mDomainStart(0), mDomainEnd(0), + mPathStart(0), mPathEnd(0), + mDead(false), mChanged(true) +{ +} + +LLPluginCookieStore::Cookie *LLPluginCookieStore::Cookie::createFromString(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, const std::string &host) +{ + Cookie *result = new Cookie(s, cookie_start, cookie_end); + + if(!result->parse(host)) + { + delete result; + result = NULL; + } + + return result; +} + +std::string LLPluginCookieStore::Cookie::getKey() const +{ + std::string result; + if(mDomainEnd > mDomainStart) + { + result += mCookie.substr(mDomainStart, mDomainEnd - mDomainStart); + } + result += ';'; + if(mPathEnd > mPathStart) + { + result += mCookie.substr(mPathStart, mPathEnd - mPathStart); + } + result += ';'; + result += mCookie.substr(mNameStart, mNameEnd - mNameStart); + return result; +} + +bool LLPluginCookieStore::Cookie::parse(const std::string &host) +{ + bool first_field = true; + + std::string::size_type cookie_end = mCookie.size(); + std::string::size_type field_start = 0; + + LL_DEBUGS("CookieStoreParse") << "parsing cookie: " << mCookie << LL_ENDL; + while(field_start < cookie_end) + { + // Finding the start of the next field requires honoring special quoting rules + // see the definition of 'quoted-string' in rfc2616 for details + std::string::size_type next_field_start = findFieldEnd(field_start); + + // The end of this field should not include the terminating ';' or any trailing whitespace + std::string::size_type field_end = mCookie.find_last_not_of("; ", next_field_start); + if(field_end == std::string::npos || field_end < field_start) + { + // This field was empty or all whitespace. Set end = start so it shows as empty. + field_end = field_start; + } + else if (field_end < next_field_start) + { + // we actually want the index of the char _after_ what 'last not of' found + ++field_end; + } + + // find the start of the actual name (skip separator and possible whitespace) + std::string::size_type name_start = mCookie.find_first_not_of("; ", field_start); + if(name_start == std::string::npos || name_start > next_field_start) + { + // Again, nothing but whitespace. + name_start = field_start; + } + + // the name and value are separated by the first equals sign + std::string::size_type name_value_sep = mCookie.find_first_of("=", name_start); + if(name_value_sep == std::string::npos || name_value_sep > field_end) + { + // No separator found, so this is a field without an = + name_value_sep = field_end; + } + + // the name end is before the name-value separator + std::string::size_type name_end = mCookie.find_last_not_of("= ", name_value_sep); + if(name_end == std::string::npos || name_end < name_start) + { + // I'm not sure how we'd hit this case... it seems like it would have to be an empty name. + name_end = name_start; + } + else if (name_end < name_value_sep) + { + // we actually want the index of the char _after_ what 'last not of' found + ++name_end; + } + + // Value is between the name-value sep and the end of the field. + std::string::size_type value_start = mCookie.find_first_not_of("= ", name_value_sep); + if(value_start == std::string::npos || value_start > field_end) + { + // All whitespace or empty value + value_start = field_end; + } + std::string::size_type value_end = mCookie.find_last_not_of("; ", field_end); + if(value_end == std::string::npos || value_end < value_start) + { + // All whitespace or empty value + value_end = value_start; + } + else if (value_end < field_end) + { + // we actually want the index of the char _after_ what 'last not of' found + ++value_end; + } + + LL_DEBUGS("CookieStoreParse") + << " field name: \"" << mCookie.substr(name_start, name_end - name_start) + << "\", value: \"" << mCookie.substr(value_start, value_end - value_start) << "\"" + << LL_ENDL; + + // See whether this field is one we know + if(first_field) + { + // The first field is the name=value pair + mNameStart = name_start; + mNameEnd = name_end; + mValueStart = value_start; + mValueEnd = value_end; + first_field = false; + } + else + { + // Subsequent fields must come from the set in rfc2109 + if(matchName(name_start, name_end, "expires")) + { + std::string date_string(mCookie, value_start, value_end - value_start); + // If the cookie contains an "expires" field, it MUST contain a parsable date. + + // HACK: LLDate apparently can't PARSE an rfc1123-format date, even though it can GENERATE one. + // The curl function curl_getdate can do this, but I'm hesitant to unilaterally introduce a curl dependency in LLDate. +#if 1 + time_t date = curl_getdate(date_string.c_str(), NULL ); + mDate.secondsSinceEpoch((F64)date); + LL_DEBUGS("CookieStoreParse") << " expire date parsed to: " << mDate.asRFC1123() << LL_ENDL; +#else + // This doesn't work (rfc1123-format dates cause it to fail) + if(!mDate.fromString(date_string)) + { + // Date failed to parse. + LL_WARNS("CookieStoreParse") << "failed to parse cookie's expire date: " << date << LL_ENDL; + return false; + } +#endif + } + else if(matchName(name_start, name_end, "domain")) + { + mDomainStart = value_start; + mDomainEnd = value_end; + } + else if(matchName(name_start, name_end, "path")) + { + mPathStart = value_start; + mPathEnd = value_end; + } + else if(matchName(name_start, name_end, "max-age")) + { + // TODO: how should we handle this? + } + else if(matchName(name_start, name_end, "secure")) + { + // We don't care about the value of this field (yet) + } + else if(matchName(name_start, name_end, "version")) + { + // We don't care about the value of this field (yet) + } + else if(matchName(name_start, name_end, "comment")) + { + // We don't care about the value of this field (yet) + } + else if(matchName(name_start, name_end, "httponly")) + { + // We don't care about the value of this field (yet) + } + else + { + // An unknown field is a parse failure + LL_WARNS("CookieStoreParse") << "unexpected field name: " << mCookie.substr(name_start, name_end - name_start) << LL_ENDL; + return false; + } + + } + + + // move on to the next field, skipping this field's separator and any leading whitespace + field_start = mCookie.find_first_not_of("; ", next_field_start); + } + + // The cookie MUST have a name + if(mNameEnd <= mNameStart) + return false; + + // If the cookie doesn't have a domain, add the current host as the domain. + if(mDomainEnd <= mDomainStart) + { + if(host.empty()) + { + // no domain and no current host -- this is a parse failure. + return false; + } + + // Figure out whether this cookie ended with a ";" or not... + std::string::size_type last_char = mCookie.find_last_not_of(" "); + if((last_char != std::string::npos) && (mCookie[last_char] != ';')) + { + mCookie += ";"; + } + + mCookie += " domain="; + mDomainStart = mCookie.size(); + mCookie += host; + mDomainEnd = mCookie.size(); + + LL_DEBUGS("CookieStoreParse") << "added domain (" << mDomainStart << " to " << mDomainEnd << "), new cookie is: " << mCookie << LL_ENDL; + } + + // If the cookie doesn't have a path, add "/". + if(mPathEnd <= mPathStart) + { + // Figure out whether this cookie ended with a ";" or not... + std::string::size_type last_char = mCookie.find_last_not_of(" "); + if((last_char != std::string::npos) && (mCookie[last_char] != ';')) + { + mCookie += ";"; + } + + mCookie += " path="; + mPathStart = mCookie.size(); + mCookie += "/"; + mPathEnd = mCookie.size(); + + LL_DEBUGS("CookieStoreParse") << "added path (" << mPathStart << " to " << mPathEnd << "), new cookie is: " << mCookie << LL_ENDL; + } + + + return true; +} + +std::string::size_type LLPluginCookieStore::Cookie::findFieldEnd(std::string::size_type start, std::string::size_type end) +{ + std::string::size_type result = start; + + if(end == std::string::npos) + end = mCookie.size(); + + bool in_quotes = false; + for(; (result < end); result++) + { + switch(mCookie[result]) + { + case '\\': + if(in_quotes) + result++; // The next character is backslash-quoted. Skip over it. + break; + case '"': + in_quotes = !in_quotes; + break; + case ';': + if(!in_quotes) + return result; + break; + } + } + + // If we got here, no ';' was found. + return end; +} + +bool LLPluginCookieStore::Cookie::matchName(std::string::size_type start, std::string::size_type end, const char *name) +{ + // NOTE: this assumes 'name' is already in lowercase. The code which uses it should be able to arrange this... + + while((start < end) && (*name != '\0')) + { + if(tolower(mCookie[start]) != *name) + return false; + + start++; + name++; + } + + // iff both strings hit the end at the same time, they're equal. + return ((start == end) && (*name == '\0')); +} + +std::string LLPluginCookieStore::getAllCookies() +{ + std::stringstream result; + writeAllCookies(result); + return result.str(); +} + +void LLPluginCookieStore::writeAllCookies(std::ostream& s) +{ + cookie_map_t::iterator iter; + for(iter = mCookies.begin(); iter != mCookies.end(); iter++) + { + // Don't return expired cookies + if(!iter->second->isDead()) + { + s << (iter->second->getCookie()) << "\n"; + } + } + +} + +std::string LLPluginCookieStore::getPersistentCookies() +{ + std::stringstream result; + writePersistentCookies(result); + return result.str(); +} + +void LLPluginCookieStore::writePersistentCookies(std::ostream& s) +{ + cookie_map_t::iterator iter; + for(iter = mCookies.begin(); iter != mCookies.end(); iter++) + { + // Don't return expired cookies or session cookies + if(!iter->second->isDead() && !iter->second->isSessionCookie()) + { + s << iter->second->getCookie() << "\n"; + } + } +} + +std::string LLPluginCookieStore::getChangedCookies(bool clear_changed) +{ + std::stringstream result; + writeChangedCookies(result, clear_changed); + + return result.str(); +} + +void LLPluginCookieStore::writeChangedCookies(std::ostream& s, bool clear_changed) +{ + if(mHasChangedCookies) + { + lldebugs << "returning changed cookies: " << llendl; + cookie_map_t::iterator iter; + for(iter = mCookies.begin(); iter != mCookies.end(); ) + { + cookie_map_t::iterator next = iter; + next++; + + // Only return cookies marked as "changed" + if(iter->second->isChanged()) + { + s << iter->second->getCookie() << "\n"; + + lldebugs << " " << iter->second->getCookie() << llendl; + + // If requested, clear the changed mark + if(clear_changed) + { + if(iter->second->isDead()) + { + // If this cookie was previously marked dead, it needs to be removed entirely. + delete iter->second; + mCookies.erase(iter); + } + else + { + // Not dead, just mark as not changed. + iter->second->setChanged(false); + } + } + } + + iter = next; + } + } + + if(clear_changed) + mHasChangedCookies = false; +} + +void LLPluginCookieStore::setAllCookies(const std::string &cookies, bool mark_changed) +{ + clearCookies(); + setCookies(cookies, mark_changed); +} + +void LLPluginCookieStore::readAllCookies(std::istream& s, bool mark_changed) +{ + clearCookies(); + readCookies(s, mark_changed); +} + +void LLPluginCookieStore::setCookies(const std::string &cookies, bool mark_changed) +{ + std::string::size_type start = 0; + + while(start != std::string::npos) + { + std::string::size_type end = cookies.find_first_of("\r\n", start); + if(end > start) + { + // The line is non-empty. Try to create a cookie from it. + setOneCookie(cookies, start, end, mark_changed); + } + start = cookies.find_first_not_of("\r\n ", end); + } +} + +void LLPluginCookieStore::setCookiesFromHost(const std::string &cookies, const std::string &host, bool mark_changed) +{ + std::string::size_type start = 0; + + while(start != std::string::npos) + { + std::string::size_type end = cookies.find_first_of("\r\n", start); + if(end > start) + { + // The line is non-empty. Try to create a cookie from it. + setOneCookie(cookies, start, end, mark_changed, host); + } + start = cookies.find_first_not_of("\r\n ", end); + } +} + +void LLPluginCookieStore::readCookies(std::istream& s, bool mark_changed) +{ + std::string line; + while(s.good() && !s.eof()) + { + std::getline(s, line); + if(!line.empty()) + { + // Try to create a cookie from this line. + setOneCookie(line, 0, std::string::npos, mark_changed); + } + } +} + +std::string LLPluginCookieStore::quoteString(const std::string &s) +{ + std::stringstream result; + + result << '"'; + + for(std::string::size_type i = 0; i < s.size(); ++i) + { + char c = s[i]; + switch(c) + { + // All these separators need to be quoted in HTTP headers, according to section 2.2 of rfc 2616: + case '(': case ')': case '<': case '>': case '@': + case ',': case ';': case ':': case '\\': case '"': + case '/': case '[': case ']': case '?': case '=': + case '{': case '}': case ' ': case '\t': + result << '\\'; + break; + } + + result << c; + } + + result << '"'; + + return result.str(); +} + +std::string LLPluginCookieStore::unquoteString(const std::string &s) +{ + std::stringstream result; + + bool in_quotes = false; + + for(std::string::size_type i = 0; i < s.size(); ++i) + { + char c = s[i]; + switch(c) + { + case '\\': + if(in_quotes) + { + // The next character is backslash-quoted. Pass it through untouched. + ++i; + if(i < s.size()) + { + result << s[i]; + } + continue; + } + break; + case '"': + in_quotes = !in_quotes; + continue; + break; + } + + result << c; + } + + return result.str(); +} + +// The flow for deleting a cookie is non-obvious enough that I should call it out here... +// Deleting a cookie is done by setting a cookie with the same name, path, and domain, but with an expire timestamp in the past. +// (This is exactly how a web server tells a browser to delete a cookie.) +// When deleting with mark_changed set to true, this replaces the existing cookie in the list with an entry that's marked both dead and changed. +// Some time later when writeChangedCookies() is called with clear_changed set to true, the dead cookie is deleted from the list after being returned, so that the +// delete operation (in the form of the expired cookie) is passed along. +void LLPluginCookieStore::setOneCookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, bool mark_changed, const std::string &host) +{ + Cookie *cookie = Cookie::createFromString(s, cookie_start, cookie_end, host); + if(cookie) + { + LL_DEBUGS("CookieStoreUpdate") << "setting cookie: " << cookie->getCookie() << LL_ENDL; + + // Create a key for this cookie + std::string key = cookie->getKey(); + + // Check to see whether this cookie should have expired + if(!cookie->isSessionCookie() && (cookie->getDate() < LLDate::now())) + { + // This cookie has expired. + if(mark_changed) + { + // If we're marking cookies as changed, we should keep it anyway since we'll need to send it out with deltas. + cookie->setDead(true); + LL_DEBUGS("CookieStoreUpdate") << " marking dead" << LL_ENDL; + } + else + { + // If we're not marking cookies as changed, we don't need to keep this cookie at all. + // If the cookie was already in the list, delete it. + removeCookie(key); + + delete cookie; + cookie = NULL; + + LL_DEBUGS("CookieStoreUpdate") << " removing" << LL_ENDL; + } + } + + if(cookie) + { + // If it already exists in the map, replace it. + cookie_map_t::iterator iter = mCookies.find(key); + if(iter != mCookies.end()) + { + if(iter->second->getCookie() == cookie->getCookie()) + { + // The new cookie is identical to the old -- don't mark as changed. + // Just leave the old one in the map. + delete cookie; + cookie = NULL; + + LL_DEBUGS("CookieStoreUpdate") << " unchanged" << LL_ENDL; + } + else + { + // A matching cookie was already in the map. Replace it. + delete iter->second; + iter->second = cookie; + + cookie->setChanged(mark_changed); + if(mark_changed) + mHasChangedCookies = true; + + LL_DEBUGS("CookieStoreUpdate") << " replacing" << LL_ENDL; + } + } + else + { + // The cookie wasn't in the map. Insert it. + mCookies.insert(std::make_pair(key, cookie)); + + cookie->setChanged(mark_changed); + if(mark_changed) + mHasChangedCookies = true; + + LL_DEBUGS("CookieStoreUpdate") << " adding" << LL_ENDL; + } + } + } + else + { + LL_WARNS("CookieStoreUpdate") << "failed to parse cookie: " << s.substr(cookie_start, cookie_end - cookie_start) << LL_ENDL; + } + +} + +void LLPluginCookieStore::clearCookies() +{ + while(!mCookies.empty()) + { + cookie_map_t::iterator iter = mCookies.begin(); + delete iter->second; + mCookies.erase(iter); + } +} + +void LLPluginCookieStore::removeCookie(const std::string &key) +{ + cookie_map_t::iterator iter = mCookies.find(key); + if(iter != mCookies.end()) + { + delete iter->second; + mCookies.erase(iter); + } +} + diff --git a/linden/indra/llplugin/llplugincookiestore.h b/linden/indra/llplugin/llplugincookiestore.h new file mode 100644 index 0000000..69f0cf1 --- /dev/null +++ b/linden/indra/llplugin/llplugincookiestore.h @@ -0,0 +1,127 @@ +/** + * @file llplugincookiestore.h + * @brief LLPluginCookieStore provides central storage for http cookies used by plugins + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#ifndef LL_LLPLUGINCOOKIESTORE_H +#define LL_LLPLUGINCOOKIESTORE_H + +#include "lldate.h" +#include <map> +#include <string> +#include <iostream> + +class LLPluginCookieStore +{ + LOG_CLASS(LLPluginCookieStore); +public: + LLPluginCookieStore(); + ~LLPluginCookieStore(); + + // gets all cookies currently in storage -- use when initializing a plugin + std::string getAllCookies(); + void writeAllCookies(std::ostream& s); + + // gets only persistent cookies (i.e. not session cookies) -- use when writing cookies to a file + std::string getPersistentCookies(); + void writePersistentCookies(std::ostream& s); + + // gets cookies which are marked as "changed" -- use when sending periodic updates to plugins + std::string getChangedCookies(bool clear_changed = true); + void writeChangedCookies(std::ostream& s, bool clear_changed = true); + + // (re)initializes internal data structures and bulk-sets cookies -- use when reading cookies from a file + void setAllCookies(const std::string &cookies, bool mark_changed = false); + void readAllCookies(std::istream& s, bool mark_changed = false); + + // sets one or more cookies (without reinitializing anything) -- use when receiving cookies from a plugin + void setCookies(const std::string &cookies, bool mark_changed = true); + void readCookies(std::istream& s, bool mark_changed = true); + + // sets one or more cookies (without reinitializing anything), supplying a hostname the cookies came from -- use when setting a cookie manually + void setCookiesFromHost(const std::string &cookies, const std::string &host, bool mark_changed = true); + + // quote or unquote a string as per the definition of 'quoted-string' in rfc2616 + static std::string quoteString(const std::string &s); + static std::string unquoteString(const std::string &s); + +private: + + void setOneCookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, bool mark_changed, const std::string &host = LLStringUtil::null); + + class Cookie + { + public: + static Cookie *createFromString(const std::string &s, std::string::size_type cookie_start = 0, std::string::size_type cookie_end = std::string::npos, const std::string &host = LLStringUtil::null); + + // Construct a string from the cookie that uniquely represents it, to be used as a key in a std::map. + std::string getKey() const; + + const std::string &getCookie() const { return mCookie; }; + bool isSessionCookie() const { return mDate.isNull(); }; + + bool isDead() const { return mDead; }; + void setDead(bool dead) { mDead = dead; }; + + bool isChanged() const { return mChanged; }; + void setChanged(bool changed) { mChanged = changed; }; + + const LLDate &getDate() const { return mDate; }; + + private: + Cookie(const std::string &s, std::string::size_type cookie_start = 0, std::string::size_type cookie_end = std::string::npos); + bool parse(const std::string &host); + std::string::size_type findFieldEnd(std::string::size_type start = 0, std::string::size_type end = std::string::npos); + bool matchName(std::string::size_type start, std::string::size_type end, const char *name); + + std::string mCookie; // The full cookie, in RFC 2109 string format + LLDate mDate; // The expiration date of the cookie. For session cookies, this will be a null date (mDate.isNull() is true). + // Start/end indices of various parts of the cookie string. Stored as indices into the string to save space and time. + std::string::size_type mNameStart, mNameEnd; + std::string::size_type mValueStart, mValueEnd; + std::string::size_type mDomainStart, mDomainEnd; + std::string::size_type mPathStart, mPathEnd; + bool mDead; + bool mChanged; + }; + + typedef std::map<std::string, Cookie*> cookie_map_t; + + cookie_map_t mCookies; + bool mHasChangedCookies; + + void clearCookies(); + void removeCookie(const std::string &key); +}; + +#endif // LL_LLPLUGINCOOKIESTORE_H diff --git a/linden/indra/llplugin/llpluginmessagepipe.cpp b/linden/indra/llplugin/llpluginmessagepipe.cpp index b16381c..8168b32 100755 --- a/linden/indra/llplugin/llpluginmessagepipe.cpp +++ b/linden/indra/llplugin/llpluginmessagepipe.cpp @@ -98,11 +98,14 @@ void LLPluginMessagePipeOwner::killMessagePipe(void) } } -LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket) +LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket): + mInputMutex(gAPRPoolp), + mOutputMutex(gAPRPoolp), + mOwner(owner), + mSocket(socket) { - mOwner = owner; + mOwner->setMessagePipe(this); - mSocket = socket; } LLPluginMessagePipe::~LLPluginMessagePipe() @@ -116,6 +119,7 @@ LLPluginMessagePipe::~LLPluginMessagePipe() bool LLPluginMessagePipe::addMessage(const std::string &message) { // queue the message for later output + LLMutexLock lock(&mOutputMutex); mOutput += message; mOutput += MESSAGE_DELIMITER; // message separator @@ -151,6 +155,18 @@ void LLPluginMessagePipe::setSocketTimeout(apr_interval_time_t timeout_usec) bool LLPluginMessagePipe::pump(F64 timeout) { + bool result = pumpOutput(); + + if(result) + { + result = pumpInput(timeout); + } + + return result; +} + +bool LLPluginMessagePipe::pumpOutput() +{ bool result = true; if(mSocket) @@ -158,6 +174,7 @@ bool LLPluginMessagePipe::pump(F64 timeout) apr_status_t status; apr_size_t size; + LLMutexLock lock(&mOutputMutex); if(!mOutput.empty()) { // write any outgoing messages @@ -185,6 +202,17 @@ bool LLPluginMessagePipe::pump(F64 timeout) // remove the written part from the buffer and try again later. mOutput = mOutput.substr(size); } + else if(APR_STATUS_IS_EOF(status)) + { + // This is what we normally expect when a plugin exits. + llinfos << "Got EOF from plugin socket. " << llendl; + + if(mOwner) + { + mOwner->socketError(status); + } + result = false; + } else { // some other error @@ -198,6 +226,19 @@ bool LLPluginMessagePipe::pump(F64 timeout) result = false; } } + } + + return result; +} + +bool LLPluginMessagePipe::pumpInput(F64 timeout) +{ + bool result = true; + + if(mSocket) + { + apr_status_t status; + apr_size_t size; // FIXME: For some reason, the apr timeout stuff isn't working properly on windows. // Until such time as we figure out why, don't try to use the socket timeout -- just sleep here instead. @@ -218,8 +259,16 @@ bool LLPluginMessagePipe::pump(F64 timeout) char input_buf[1024]; apr_size_t request_size; - // Start out by reading one byte, so that any data received will wake us up. - request_size = 1; + if(timeout == 0.0f) + { + // If we have no timeout, start out with a full read. + request_size = sizeof(input_buf); + } + else + { + // Start out by reading one byte, so that any data received will wake us up. + request_size = 1; + } // and use the timeout so we'll sleep if no data is available. setSocketTimeout((apr_interval_time_t)(timeout * 1000000)); @@ -238,11 +287,14 @@ bool LLPluginMessagePipe::pump(F64 timeout) // LL_INFOS("Plugin") << "after apr_socket_recv, size = " << size << LL_ENDL; if(size > 0) + { + LLMutexLock lock(&mInputMutex); mInput.append(input_buf, size); + } if(status == APR_SUCCESS) { -// llinfos << "success, read " << size << llendl; + LL_DEBUGS("PluginSocket") << "success, read " << size << LL_ENDL; if(size != request_size) { @@ -252,16 +304,28 @@ bool LLPluginMessagePipe::pump(F64 timeout) } else if(APR_STATUS_IS_TIMEUP(status)) { -// llinfos << "TIMEUP, read " << size << llendl; + LL_DEBUGS("PluginSocket") << "TIMEUP, read " << size << LL_ENDL; // Timeout was hit. Since the initial read is 1 byte, this should never be a partial read. break; } else if(APR_STATUS_IS_EAGAIN(status)) { -// llinfos << "EAGAIN, read " << size << llendl; + LL_DEBUGS("PluginSocket") << "EAGAIN, read " << size << LL_ENDL; - // We've been doing partial reads, and we're done now. + // Non-blocking read returned immediately. + break; + } + else if(APR_STATUS_IS_EOF(status)) + { + // This is what we normally expect when a plugin exits. + LL_INFOS("PluginSocket") << "Got EOF from plugin socket. " << LL_ENDL; + + if(mOwner) + { + mOwner->socketError(status); + } + result = false; break; } else @@ -278,22 +342,18 @@ bool LLPluginMessagePipe::pump(F64 timeout) break; } - // Second and subsequent reads should not use the timeout - setSocketTimeout(0); - // and should try to fill the input buffer - request_size = sizeof(input_buf); + if(timeout != 0.0f) + { + // Second and subsequent reads should not use the timeout + setSocketTimeout(0); + // and should try to fill the input buffer + request_size = sizeof(input_buf); + } } processInput(); } } - - if(!result) - { - // If we got an error, we're done. - LL_INFOS("Plugin") << "Error from socket, cleaning up." << LL_ENDL; - delete this; - } return result; } @@ -301,26 +361,27 @@ bool LLPluginMessagePipe::pump(F64 timeout) void LLPluginMessagePipe::processInput(void) { // Look for input delimiter(s) in the input buffer. - int start = 0; int delim; - while((delim = mInput.find(MESSAGE_DELIMITER, start)) != std::string::npos) + mInputMutex.lock(); + while((delim = mInput.find(MESSAGE_DELIMITER)) != std::string::npos) { // Let the owner process this message if (mOwner) { - mOwner->receiveMessageRaw(mInput.substr(start, delim - start)); + // Pull the message out of the input buffer before calling receiveMessageRaw. + // It's now possible for this function to get called recursively (in the case where the plugin makes a blocking request) + // and this guarantees that the messages will get dequeued correctly. + std::string message(mInput, 0, delim); + mInput.erase(0, delim + 1); + mInputMutex.unlock(); + mOwner->receiveMessageRaw(message); + mInputMutex.lock(); } else { LL_WARNS("Plugin") << "!mOwner" << LL_ENDL; } - - start = delim + 1; } - - // Remove delivered messages from the input buffer. - if(start != 0) - mInput = mInput.substr(start); - + mInputMutex.unlock(); } diff --git a/linden/indra/llplugin/llpluginmessagepipe.h b/linden/indra/llplugin/llpluginmessagepipe.h index 8f74f38..6eedca2 100755 --- a/linden/indra/llplugin/llpluginmessagepipe.h +++ b/linden/indra/llplugin/llpluginmessagepipe.h @@ -37,6 +37,7 @@ #define LL_LLPLUGINMESSAGEPIPE_H #include "lliosocket.h" +#include "llthread.h" class LLPluginMessagePipe; @@ -53,7 +54,7 @@ public: virtual apr_status_t socketError(apr_status_t error); // called from LLPluginMessagePipe to manage the connection with LLPluginMessagePipeOwner -- do not use! - virtual void setMessagePipe(LLPluginMessagePipe *message_pipe) ; + virtual void setMessagePipe(LLPluginMessagePipe *message_pipe); protected: // returns false if writeMessageRaw() would drop the message @@ -78,14 +79,18 @@ public: void clearOwner(void); bool pump(F64 timeout = 0.0f); - + bool pumpOutput(); + bool pumpInput(F64 timeout = 0.0f); + protected: void processInput(void); // used internally by pump() void setSocketTimeout(apr_interval_time_t timeout_usec); + LLMutex mInputMutex; std::string mInput; + LLMutex mOutputMutex; std::string mOutput; LLPluginMessagePipeOwner *mOwner; diff --git a/linden/indra/llplugin/llpluginprocesschild.cpp b/linden/indra/llplugin/llpluginprocesschild.cpp index 0b7ce3d..8dbf2b3 100755 --- a/linden/indra/llplugin/llpluginprocesschild.cpp +++ b/linden/indra/llplugin/llpluginprocesschild.cpp @@ -50,6 +50,8 @@ LLPluginProcessChild::LLPluginProcessChild() mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz mCPUElapsed = 0.0f; + mBlockingRequest = false; + mBlockingResponseReceived = false; } LLPluginProcessChild::~LLPluginProcessChild() @@ -85,9 +87,14 @@ void LLPluginProcessChild::idle(void) bool idle_again; do { - if(mSocketError != APR_SUCCESS) + if(APR_STATUS_IS_EOF(mSocketError)) { - LL_INFOS("Plugin") << "message pipe is in error state, moving to STATE_ERROR"<< LL_ENDL; + // Plugin socket was closed. This covers both normal plugin termination and host crashes. + setState(STATE_ERROR); + } + else if(mSocketError != APR_SUCCESS) + { + LL_INFOS("Plugin") << "message pipe is in error state (" << mSocketError << "), moving to STATE_ERROR"<< LL_ENDL; setState(STATE_ERROR); } @@ -228,6 +235,7 @@ void LLPluginProcessChild::idle(void) void LLPluginProcessChild::sleep(F64 seconds) { + deliverQueuedMessages(); if(mMessagePipe) { mMessagePipe->pump(seconds); @@ -240,6 +248,7 @@ void LLPluginProcessChild::sleep(F64 seconds) void LLPluginProcessChild::pump(void) { + deliverQueuedMessages(); if(mMessagePipe) { mMessagePipe->pump(0.0f); @@ -311,15 +320,32 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) LL_DEBUGS("Plugin") << "Received from parent: " << message << LL_ENDL; + // Decode this message + LLPluginMessage parsed; + parsed.parse(message); + + if(mBlockingRequest) + { + // We're blocking the plugin waiting for a response. + + if(parsed.hasValue("blocking_response")) + { + // This is the message we've been waiting for -- fall through and send it immediately. + mBlockingResponseReceived = true; + } + else + { + // Still waiting. Queue this message and don't process it yet. + mMessageQueue.push(message); + return; + } + } + bool passMessage = true; // FIXME: how should we handle queueing here? { - // Decode this message - LLPluginMessage parsed; - parsed.parse(message); - std::string message_class = parsed.getClass(); if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) { @@ -427,7 +453,13 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) void LLPluginProcessChild::receivePluginMessage(const std::string &message) { LL_DEBUGS("Plugin") << "Received from plugin: " << message << LL_ENDL; - + + if(mBlockingRequest) + { + // + LL_ERRS("Plugin") << "Can't send a message while already waiting on a blocking request -- aborting!" << LL_ENDL; + } + // Incoming message from the plugin instance bool passMessage = true; @@ -438,6 +470,12 @@ void LLPluginProcessChild::receivePluginMessage(const std::string &message) // Decode this message LLPluginMessage parsed; parsed.parse(message); + + if(parsed.hasValue("blocking_request")) + { + mBlockingRequest = true; + } + std::string message_class = parsed.getClass(); if(message_class == "base") { @@ -496,6 +534,19 @@ void LLPluginProcessChild::receivePluginMessage(const std::string &message) LL_DEBUGS("Plugin") << "Passing through to parent: " << message << LL_ENDL; writeMessageRaw(message); } + + while(mBlockingRequest) + { + // The plugin wants to block and wait for a response to this message. + sleep(mSleepTime); // this will pump the message pipe and process messages + + if(mBlockingResponseReceived || mSocketError != APR_SUCCESS || (mMessagePipe == NULL)) + { + // Response has been received, or we've hit an error state. Stop waiting. + mBlockingRequest = false; + mBlockingResponseReceived = false; + } + } } @@ -504,3 +555,15 @@ void LLPluginProcessChild::setState(EState state) LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL; mState = state; }; + +void LLPluginProcessChild::deliverQueuedMessages() +{ + if(!mBlockingRequest) + { + while(!mMessageQueue.empty()) + { + receiveMessageRaw(mMessageQueue.front()); + mMessageQueue.pop(); + } + } +} diff --git a/linden/indra/llplugin/llpluginprocesschild.h b/linden/indra/llplugin/llpluginprocesschild.h index 96ae7b4..5d643d7 100755 --- a/linden/indra/llplugin/llpluginprocesschild.h +++ b/linden/indra/llplugin/llpluginprocesschild.h @@ -36,6 +36,8 @@ #ifndef LL_LLPLUGINPROCESSCHILD_H #define LL_LLPLUGINPROCESSCHILD_H +#include <queue> //imprudence + #include "llpluginmessage.h" #include "llpluginmessagepipe.h" #include "llplugininstance.h" @@ -108,6 +110,11 @@ private: LLTimer mHeartbeat; F64 mSleepTime; F64 mCPUElapsed; + bool mBlockingRequest; + bool mBlockingResponseReceived; + std::queue<std::string> mMessageQueue; + + void deliverQueuedMessages(); }; diff --git a/linden/indra/llplugin/llpluginprocessparent.cpp b/linden/indra/llplugin/llpluginprocessparent.cpp index 8ea28f1..1bf34c5 100755 --- a/linden/indra/llplugin/llpluginprocessparent.cpp +++ b/linden/indra/llplugin/llpluginprocessparent.cpp @@ -47,8 +47,51 @@ LLPluginProcessParentOwner::~LLPluginProcessParentOwner() } -LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner) +bool LLPluginProcessParent::sUseReadThread = false; +apr_pollset_t *LLPluginProcessParent::sPollSet = NULL; +bool LLPluginProcessParent::sPollsetNeedsRebuild = false; +LLMutex *LLPluginProcessParent::sInstancesMutex; +std::list<LLPluginProcessParent*> LLPluginProcessParent::sInstances; +LLThread *LLPluginProcessParent::sReadThread = NULL; + + +class LLPluginProcessParentPollThread: public LLThread { +public: + LLPluginProcessParentPollThread() : + LLThread("LLPluginProcessParentPollThread", gAPRPoolp) + { + } +protected: + // Inherited from LLThread + /*virtual*/ void run(void) + { + while(!isQuitting() && LLPluginProcessParent::getUseReadThread()) + { + LLPluginProcessParent::poll(0.1f); + checkPause(); + } + + // Final poll to clean up the pollset, etc. + LLPluginProcessParent::poll(0.0f); + } + + // Inherited from LLThread + /*virtual*/ bool runCondition(void) + { + return(LLPluginProcessParent::canPollThreadRun()); + } + +}; + +LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner): + mIncomingQueueMutex(gAPRPoolp) +{ + if(!sInstancesMutex) + { + sInstancesMutex = new LLMutex(gAPRPoolp); + } + mOwner = owner; mBoundPort = 0; mState = STATE_UNINITIALIZED; @@ -56,18 +99,38 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner) mCPUUsage = 0.0; mDisableTimeout = false; mDebug = false; + mBlocked = false; + mPolledInput = false; + mPollFD.client_data = NULL; mPluginLaunchTimeout = 60.0f; mPluginLockupTimeout = 15.0f; // Don't start the timer here -- start it when we actually launch the plugin process. mHeartbeat.stop(); + + + // Don't add to the global list until fully constructed. + { + LLMutexLock lock(sInstancesMutex); + sInstances.push_back(this); + } } LLPluginProcessParent::~LLPluginProcessParent() { LL_DEBUGS("Plugin") << "destructor" << LL_ENDL; + // Remove from the global list before beginning destruction. + { + // Make sure to get the global mutex _first_ here, to avoid a possible deadlock against LLPluginProcessParent::poll() + LLMutexLock lock(sInstancesMutex); + { + LLMutexLock lock2(&mIncomingQueueMutex); + sInstances.remove(this); + } + } + // Destroy any remaining shared memory regions sharedMemoryRegionsType::iterator iter; while((iter = mSharedMemoryRegions.begin()) != mSharedMemoryRegions.end()) @@ -79,15 +142,17 @@ LLPluginProcessParent::~LLPluginProcessParent() mSharedMemoryRegions.erase(iter); } - // orphaning the process means it won't be killed when the LLProcessLauncher is destructed. - // This is what we want -- it should exit cleanly once it notices the sockets have been closed. - mProcess.orphan(); + mProcess.kill(); killSockets(); } void LLPluginProcessParent::killSockets(void) { - killMessagePipe(); + { + LLMutexLock lock(&mIncomingQueueMutex); + killMessagePipe(); + } + mListenSocket.reset(); mSocket.reset(); } @@ -161,21 +226,47 @@ void LLPluginProcessParent::idle(void) do { + // process queued messages + mIncomingQueueMutex.lock(); + while(!mIncomingQueue.empty()) + { + LLPluginMessage message = mIncomingQueue.front(); + mIncomingQueue.pop(); + mIncomingQueueMutex.unlock(); + + receiveMessage(message); + + mIncomingQueueMutex.lock(); + } + + mIncomingQueueMutex.unlock(); + // Give time to network processing if(mMessagePipe) { - if(!mMessagePipe->pump()) + // Drain any queued outgoing messages + mMessagePipe->pumpOutput(); + + // Only do input processing here if this instance isn't in a pollset. + if(!mPolledInput) { -// LL_WARNS("Plugin") << "Message pipe hit an error state" << LL_ENDL; - errorState(); + mMessagePipe->pumpInput(); } } - - if((mSocketError != APR_SUCCESS) && (mState <= STATE_RUNNING)) + + if(mState <= STATE_RUNNING) { - // The socket is in an error state -- the plugin is gone. - LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL; - errorState(); + if(APR_STATUS_IS_EOF(mSocketError)) + { + // Plugin socket was closed. This covers both normal plugin termination and plugin crashes. + errorState(); + } + else if(mSocketError != APR_SUCCESS) + { + // The socket is in an error state -- the plugin is gone. + LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL; + errorState(); + } } // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState(). @@ -356,7 +447,7 @@ void LLPluginProcessParent::idle(void) break; case STATE_HELLO: - LL_DEBUGS("Plugin") << "received hello message" << llendl; + LL_DEBUGS("Plugin") << "received hello message" << LL_ENDL; // Send the message to load the plugin { @@ -390,7 +481,7 @@ void LLPluginProcessParent::idle(void) } else if(pluginLockedUp()) { - LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << llendl; + LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << LL_ENDL; errorState(); } break; @@ -412,8 +503,7 @@ void LLPluginProcessParent::idle(void) break; case STATE_CLEANUP: - // Don't do a kill here anymore -- closing the sockets is the new 'kill'. - mProcess.orphan(); + mProcess.kill(); killSockets(); setState(STATE_DONE); break; @@ -481,23 +571,323 @@ void LLPluginProcessParent::setSleepTime(F64 sleep_time, bool force_send) void LLPluginProcessParent::sendMessage(const LLPluginMessage &message) { + if(message.hasValue("blocking_response")) + { + mBlocked = false; + + // reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked. + mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); + } std::string buffer = message.generate(); LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL; writeMessageRaw(buffer); + + // Try to send message immediately. + if(mMessagePipe) + { + mMessagePipe->pumpOutput(); + } +} + +//virtual +void LLPluginProcessParent::setMessagePipe(LLPluginMessagePipe *message_pipe) +{ + bool update_pollset = false; + + if(mMessagePipe) + { + // Unsetting an existing message pipe -- remove from the pollset + mPollFD.client_data = NULL; + + // pollset needs an update + update_pollset = true; + } + if(message_pipe != NULL) + { + // Set up the apr_pollfd_t + mPollFD.p = gAPRPoolp; + mPollFD.desc_type = APR_POLL_SOCKET; + mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP; + mPollFD.rtnevents = 0; + mPollFD.desc.s = mSocket->getSocket(); + mPollFD.client_data = (void*)this; + + // pollset needs an update + update_pollset = true; + } + + mMessagePipe = message_pipe; + + if(update_pollset) + { + dirtyPollSet(); + } +} + +//static +void LLPluginProcessParent::dirtyPollSet() +{ + sPollsetNeedsRebuild = true; + + if(sReadThread) + { + LL_DEBUGS("PluginPoll") << "unpausing read thread " << LL_ENDL; + sReadThread->unpause(); + } +} + +void LLPluginProcessParent::updatePollset() +{ + if(!sInstancesMutex) + { + // No instances have been created yet. There's no work to do. + return; + } + + LLMutexLock lock(sInstancesMutex); + + if(sPollSet) + { + LL_DEBUGS("PluginPoll") << "destroying pollset " << sPollSet << LL_ENDL; + // delete the existing pollset. + apr_pollset_destroy(sPollSet); + sPollSet = NULL; + } + + std::list<LLPluginProcessParent*>::iterator iter; + int count = 0; + + // Count the number of instances that want to be in the pollset + for(iter = sInstances.begin(); iter != sInstances.end(); iter++) + { + (*iter)->mPolledInput = false; + if((*iter)->mPollFD.client_data) + { + // This instance has a socket that needs to be polled. + ++count; + } + } + + if(sUseReadThread && sReadThread && !sReadThread->isQuitting()) + { + if(!sPollSet && (count > 0)) + { +#ifdef APR_POLLSET_NOCOPY + // The pollset doesn't exist yet. Create it now. + apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY); + if(status != APR_SUCCESS) + { +#endif // APR_POLLSET_NOCOPY + LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL; + sPollSet = NULL; +#ifdef APR_POLLSET_NOCOPY + } + else + { + LL_DEBUGS("PluginPoll") << "created pollset " << sPollSet << LL_ENDL; + + // Pollset was created, add all instances to it. + for(iter = sInstances.begin(); iter != sInstances.end(); iter++) + { + if((*iter)->mPollFD.client_data) + { + status = apr_pollset_add(sPollSet, &((*iter)->mPollFD)); + if(status == APR_SUCCESS) + { + (*iter)->mPolledInput = true; + } + else + { + LL_WARNS("PluginPoll") << "apr_pollset_add failed with status " << status << LL_ENDL; + } + } + } + } +#endif // APR_POLLSET_NOCOPY + } + } +} + +void LLPluginProcessParent::setUseReadThread(bool use_read_thread) +{ + if(sUseReadThread != use_read_thread) + { + sUseReadThread = use_read_thread; + + if(sUseReadThread) + { + if(!sReadThread) + { + // start up the read thread + LL_INFOS("PluginPoll") << "creating read thread " << LL_ENDL; + + // make sure the pollset gets rebuilt. + sPollsetNeedsRebuild = true; + + sReadThread = new LLPluginProcessParentPollThread; + sReadThread->start(); + } + } + else + { + if(sReadThread) + { + // shut down the read thread + LL_INFOS("PluginPoll") << "destroying read thread " << LL_ENDL; + delete sReadThread; + sReadThread = NULL; + } + } + + } +} + +void LLPluginProcessParent::poll(F64 timeout) +{ + if(sPollsetNeedsRebuild || !sUseReadThread) + { + sPollsetNeedsRebuild = false; + updatePollset(); + } + + if(sPollSet) + { + apr_status_t status; + apr_int32_t count; + const apr_pollfd_t *descriptors; + status = apr_pollset_poll(sPollSet, (apr_interval_time_t)(timeout * 1000000), &count, &descriptors); + if(status == APR_SUCCESS) + { + // One or more of the descriptors signalled. Call them. + for(int i = 0; i < count; i++) + { + LLPluginProcessParent *self = (LLPluginProcessParent *)(descriptors[i].client_data); + // NOTE: the descriptor returned here is actually a COPY of the original (even though we create the pollset with APR_POLLSET_NOCOPY). + // This means that even if the parent has set its mPollFD.client_data to NULL, the old pointer may still there in this descriptor. + // It's even possible that the old pointer no longer points to a valid LLPluginProcessParent. + // This means that we can't safely dereference the 'self' pointer here without some extra steps... + if(self) + { + // Make sure this pointer is still in the instances list + bool valid = false; + { + LLMutexLock lock(sInstancesMutex); + for(std::list<LLPluginProcessParent*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + { + if(*iter == self) + { + // Lock the instance's mutex before unlocking the global mutex. + // This avoids a possible race condition where the instance gets deleted between this check and the servicePoll() call. + self->mIncomingQueueMutex.lock(); + valid = true; + break; + } + } + } + + if(valid) + { + // The instance is still valid. + // Pull incoming messages off the socket + self->servicePoll(); + self->mIncomingQueueMutex.unlock(); + } + else + { + LL_DEBUGS("PluginPoll") << "detected deleted instance " << self << LL_ENDL; + } + + } + } + } + else if(APR_STATUS_IS_TIMEUP(status)) + { + // timed out with no incoming data. Just return. + } + else if(status == EBADF) + { + // This happens when one of the file descriptors in the pollset is destroyed, which happens whenever a plugin's socket is closed. + // The pollset has been or will be recreated, so just return. + LL_DEBUGS("PluginPoll") << "apr_pollset_poll returned EBADF" << LL_ENDL; + } + else if(status != APR_SUCCESS) + { + LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL; + } + } } +void LLPluginProcessParent::servicePoll() +{ + bool result = true; + + // poll signalled on this object's socket. Try to process incoming messages. + if(mMessagePipe) + { + result = mMessagePipe->pumpInput(0.0f); + } + + if(!result) + { + // If we got a read error on input, remove this pipe from the pollset + apr_pollset_remove(sPollSet, &mPollFD); + + // and tell the code not to re-add it + mPollFD.client_data = NULL; + } +} void LLPluginProcessParent::receiveMessageRaw(const std::string &message) { LL_DEBUGS("Plugin") << "Received: " << message << LL_ENDL; - - // FIXME: should this go into a queue instead? LLPluginMessage parsed; if(parsed.parse(message) != -1) { - receiveMessage(parsed); + if(parsed.hasValue("blocking_request")) + { + mBlocked = true; + } + + if(mPolledInput) + { + // This is being called on the polling thread -- only do minimal processing/queueing. + receiveMessageEarly(parsed); + } + else + { + // This is not being called on the polling thread -- do full message processing at this time. + receiveMessage(parsed); + } + } +} + +void LLPluginProcessParent::receiveMessageEarly(const LLPluginMessage &message) +{ + // NOTE: this function will be called from the polling thread. It will be called with mIncomingQueueMutex _already locked_. + + bool handled = false; + + std::string message_class = message.getClass(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) + { + // no internal messages need to be handled early. + } + else + { + // Call out to the owner and see if they to reply + // TODO: Should this only happen when blocked? + if(mOwner != NULL) + { + handled = mOwner->receivePluginMessageEarly(message); + } + } + + if(!handled) + { + // any message that wasn't handled early needs to be queued. + mIncomingQueue.push(message); } } @@ -691,18 +1081,15 @@ bool LLPluginProcessParent::pluginLockedUpOrQuit() { bool result = false; - if(!mDisableTimeout && !mDebug) + if(!mProcess.isRunning()) { - if(!mProcess.isRunning()) - { - LL_WARNS("Plugin") << "child exited" << llendl; - result = true; - } - else if(pluginLockedUp()) - { - LL_WARNS("Plugin") << "timeout" << llendl; - result = true; - } + LL_WARNS("Plugin") << "child exited" << LL_ENDL; + result = true; + } + else if(pluginLockedUp()) + { + LL_WARNS("Plugin") << "timeout" << LL_ENDL; + result = true; } return result; @@ -710,6 +1097,12 @@ bool LLPluginProcessParent::pluginLockedUpOrQuit() bool LLPluginProcessParent::pluginLockedUp() { + if(mDisableTimeout || mDebug || mBlocked) + { + // Never time out a plugin process in these cases. + return false; + } + // If the timer is running and has expired, the plugin has locked up. return (mHeartbeat.getStarted() && mHeartbeat.hasExpired()); } diff --git a/linden/indra/llplugin/llpluginprocessparent.h b/linden/indra/llplugin/llpluginprocessparent.h index 523ce51..a8929b1 100755 --- a/linden/indra/llplugin/llpluginprocessparent.h +++ b/linden/indra/llplugin/llpluginprocessparent.h @@ -36,6 +36,8 @@ #ifndef LL_LLPLUGINPROCESSPARENT_H #define LL_LLPLUGINPROCESSPARENT_H +#include <queue> //imprudence + #include "llapr.h" #include "llprocesslauncher.h" #include "llpluginmessage.h" @@ -43,12 +45,14 @@ #include "llpluginsharedmemory.h" #include "lliosocket.h" +#include "llthread.h" class LLPluginProcessParentOwner { public: virtual ~LLPluginProcessParentOwner(); virtual void receivePluginMessage(const LLPluginMessage &message) = 0; + virtual bool receivePluginMessageEarly(const LLPluginMessage &message) {return false;}; // This will only be called when the plugin has died unexpectedly virtual void pluginLaunchFailed() {}; virtual void pluginDied() {}; @@ -76,6 +80,9 @@ public: // returns true if the process has exited or we've had a fatal error bool isDone(void); + // returns true if the process is currently waiting on a blocking request + bool isBlocked(void) { return mBlocked; }; + void killSockets(void); // Go to the proper error state @@ -89,7 +96,9 @@ public: void receiveMessage(const LLPluginMessage &message); // Inherited from LLPluginMessagePipeOwner - void receiveMessageRaw(const std::string &message); + /*virtual*/ void receiveMessageRaw(const std::string &message); + /*virtual*/ void receiveMessageEarly(const LLPluginMessage &message); + /*virtual*/ void setMessagePipe(LLPluginMessagePipe *message_pipe) ; // This adds a memory segment shared with the client, generating a name for the segment. The name generated is guaranteed to be unique on the host. // The caller must call removeSharedMemory first (and wait until getSharedMemorySize returns 0 for the indicated name) before re-adding a segment with the same name. @@ -112,7 +121,11 @@ public: void setLockupTimeout(F32 timeout) { mPluginLockupTimeout = timeout; }; F64 getCPUUsage() { return mCPUUsage; }; - + + static void poll(F64 timeout); + static bool canPollThreadRun() { return (sPollSet || sPollsetNeedsRebuild || sUseReadThread); }; + static void setUseReadThread(bool use_read_thread); + static bool getUseReadThread() { return sUseReadThread; }; private: enum EState @@ -162,12 +175,27 @@ private: bool mDisableTimeout; bool mDebug; + bool mBlocked; + bool mPolledInput; LLProcessLauncher mDebugger; F32 mPluginLaunchTimeout; // Somewhat longer timeout for initial launch. F32 mPluginLockupTimeout; // If we don't receive a heartbeat in this many seconds, we declare the plugin locked up. + static bool sUseReadThread; + apr_pollfd_t mPollFD; + static apr_pollset_t *sPollSet; + static bool sPollsetNeedsRebuild; + static LLMutex *sInstancesMutex; + static std::list<LLPluginProcessParent*> sInstances; + static void dirtyPollSet(); + static void updatePollset(); + void servicePoll(); + static LLThread *sReadThread; + + LLMutex mIncomingQueueMutex; + std::queue<LLPluginMessage> mIncomingQueue; }; #endif // LL_LLPLUGINPROCESSPARENT_H diff --git a/linden/indra/llplugin/slplugin/CMakeLists.txt b/linden/indra/llplugin/slplugin/CMakeLists.txt index 4a7d670..81d9299 100755 --- a/linden/indra/llplugin/slplugin/CMakeLists.txt +++ b/linden/indra/llplugin/slplugin/CMakeLists.txt @@ -16,6 +16,7 @@ include_directories( if (DARWIN) include(CMakeFindFrameworks) find_library(CARBON_LIBRARY Carbon) + find_library(COCOA_LIBRARY Cocoa) endif (DARWIN) @@ -25,11 +26,33 @@ set(SLPlugin_SOURCE_FILES slplugin.cpp ) +if (DARWIN) + list(APPEND SLPlugin_SOURCE_FILES + slplugin-objc.mm + ) + list(APPEND SLPlugin_HEADER_FILES + slplugin-objc.h + ) +endif (DARWIN) + +set_source_files_properties(${SLPlugin_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +if (SLPlugin_HEADER_FILES) + list(APPEND SLPlugin_SOURCE_FILES ${SLPlugin_HEADER_FILES}) +endif (SLPlugin_HEADER_FILES) + add_executable(SLPlugin WIN32 + MACOSX_BUNDLE ${SLPlugin_SOURCE_FILES} ) +set_target_properties(SLPlugin + PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/slplugin_info.plist + ) + target_link_libraries(SLPlugin ${LLPLUGIN_LIBRARIES} ${LLMESSAGE_LIBRARIES} @@ -44,12 +67,16 @@ add_dependencies(SLPlugin ) if (DARWIN) - # Mac version needs to link against carbon, and also needs an embedded plist (to set LSBackgroundOnly) - target_link_libraries(SLPlugin ${CARBON_LIBRARY}) - set_target_properties( - SLPlugin - PROPERTIES - LINK_FLAGS "-Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/slplugin_info.plist" + # Mac version needs to link against Carbon + target_link_libraries(SLPlugin ${CARBON_LIBRARY} ${COCOA_LIBRARY}) + # Make sure the app bundle has a Resources directory (it will get populated by viewer-manifest.py later) + add_custom_command( + TARGET SLPlugin POST_BUILD + COMMAND mkdir + ARGS + -p + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/SLPlugin.app/Contents/Resources ) endif (DARWIN) +#ll_deploy_sharedlibs_command(SLPlugin) diff --git a/linden/indra/llplugin/slplugin/slplugin-objc.h b/linden/indra/llplugin/slplugin/slplugin-objc.h new file mode 100644 index 0000000..42029e4 --- /dev/null +++ b/linden/indra/llplugin/slplugin/slplugin-objc.h @@ -0,0 +1,42 @@ +/** + * @file slplugin-objc.h + * @brief Header file for slplugin-objc.mm. + * + * @cond + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * + * @endcond + */ + + +/* Defined in slplugin-objc.mm: */ +void setupCocoa(); +void createAutoReleasePool(); +void deleteAutoReleasePool(); diff --git a/linden/indra/llplugin/slplugin/slplugin-objc.mm b/linden/indra/llplugin/slplugin/slplugin-objc.mm new file mode 100644 index 0000000..125b264 --- /dev/null +++ b/linden/indra/llplugin/slplugin/slplugin-objc.mm @@ -0,0 +1,89 @@ +/** + * @file slplugin-objc.mm + * @brief Objective-C++ file for use with the loader shell, so we can use a couple of Cocoa APIs. + * + * @cond + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * + * @endcond + */ + + +#include <AppKit/AppKit.h> + +#include "slplugin-objc.h" + + +void setupCocoa() +{ + static bool inited = false; + + if(!inited) + { + createAutoReleasePool(); + + // The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents. + // ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr' + // when init'ing the Cocoa App window. + [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"]; + + // This is a bit of voodoo taken from the Apple sample code "CarbonCocoa_PictureCursor": + // http://developer.apple.com/samplecode/CarbonCocoa_PictureCursor/index.html + + // Needed for Carbon based applications which call into Cocoa + NSApplicationLoad(); + + // Must first call [[[NSWindow alloc] init] release] to get the NSWindow machinery set up so that NSCursor can use a window to cache the cursor image + [[[NSWindow alloc] init] release]; + + deleteAutoReleasePool(); + + inited = true; + } +} + +static NSAutoreleasePool *sPool = NULL; + +void createAutoReleasePool() +{ + if(!sPool) + { + sPool = [[NSAutoreleasePool alloc] init]; + } +} + +void deleteAutoReleasePool() +{ + if(sPool) + { + [sPool release]; + sPool = NULL; + } +} diff --git a/linden/indra/llplugin/slplugin/slplugin.cpp b/linden/indra/llplugin/slplugin/slplugin.cpp index 649d568..64c087b 100755 --- a/linden/indra/llplugin/slplugin/slplugin.cpp +++ b/linden/indra/llplugin/slplugin/slplugin.cpp @@ -46,6 +46,7 @@ #if LL_DARWIN #include <Carbon/Carbon.h> + #include "slplugin-objc.h" #endif #if LL_DARWIN || LL_LINUX @@ -53,7 +54,7 @@ #endif /* - On Mac OS, since we call WaitNextEvent, this process will show up in the dock unless we set the LSBackgroundOnly flag in the Info.plist. + On Mac OS, since we call WaitNextEvent, this process will show up in the dock unless we set the LSBackgroundOnly or LSUIElement flag in the Info.plist. Normally non-bundled binaries don't have an info.plist file, but it's possible to embed one in the binary by adding this to the linker flags: @@ -62,7 +63,8 @@ which means adding this to the gcc flags: -Wl,-sectcreate,__TEXT,__info_plist,/path/to/slplugin_info.plist - + + Now that SLPlugin is a bundled app on the Mac, this is no longer necessary (it can just use a regular Info.plist file), but I'm leaving this comment in for posterity. */ #if LL_DARWIN || LL_LINUX @@ -230,10 +232,19 @@ int main(int argc, char **argv) signal(SIGSYS, &crash_handler); // non-existent system call invoked #endif +#if LL_DARWIN + setupCocoa(); + createAutoReleasePool(); +#endif + LLPluginProcessChild *plugin = new LLPluginProcessChild(); plugin->init(port); +#if LL_DARWIN + deleteAutoReleasePool(); +#endif + LLTimer timer; timer.start(); @@ -242,10 +253,28 @@ int main(int argc, char **argv) #endif #if LL_DARWIN + // If the plugin opens a new window (such as the Flash plugin's fullscreen player), we may need to bring this plugin process to the foreground. + // Use this to track the current frontmost window and bring this process to the front if it changes. + WindowRef front_window = NULL; + WindowGroupRef layer_group = NULL; + int window_hack_state = 0; + CreateWindowGroup(kWindowGroupAttrFixedLevel, &layer_group); + if(layer_group) + { + // Start out with a window layer that's way out in front (fixes the problem with the menubar not getting hidden on first switch to fullscreen youtube) + SetWindowGroupName(layer_group, CFSTR("SLPlugin Layer")); + SetWindowGroupLevel(layer_group, kCGOverlayWindowLevel); + } +#endif + +#if LL_DARWIN EventTargetRef event_target = GetEventDispatcherTarget(); #endif while(!plugin->isDone()) { +#if LL_DARWIN + createAutoReleasePool(); +#endif timer.reset(); plugin->idle(); #if LL_DARWIN @@ -257,6 +286,80 @@ int main(int argc, char **argv) SendEventToEventTarget (event, event_target); ReleaseEvent(event); } + + // Check for a change in this process's frontmost window. + if(FrontWindow() != front_window) + { + ProcessSerialNumber self = { 0, kCurrentProcess }; + ProcessSerialNumber parent = { 0, kNoProcess }; + ProcessSerialNumber front = { 0, kNoProcess }; + Boolean this_is_front_process = false; + Boolean parent_is_front_process = false; + { + // Get this process's parent + ProcessInfoRec info; + info.processInfoLength = sizeof(ProcessInfoRec); + info.processName = NULL; + info.processAppSpec = NULL; + if(GetProcessInformation( &self, &info ) == noErr) + { + parent = info.processLauncher; + } + + // and figure out whether this process or its parent are currently frontmost + if(GetFrontProcess(&front) == noErr) + { + (void) SameProcess(&self, &front, &this_is_front_process); + (void) SameProcess(&parent, &front, &parent_is_front_process); + } + } + + if((FrontWindow() != NULL) && (front_window == NULL)) + { + // Opening the first window + + if(window_hack_state == 0) + { + // Next time through the event loop, lower the window group layer + window_hack_state = 1; + } + + if(layer_group) + { + SetWindowGroup(FrontWindow(), layer_group); + } + + if(parent_is_front_process) + { + // Bring this process's windows to the front. + (void) SetFrontProcess( &self ); + } + + ActivateWindow(FrontWindow(), true); + } + else if((FrontWindow() == NULL) && (front_window != NULL)) + { + // Closing the last window + + if(this_is_front_process) + { + // Try to bring this process's parent to the front + (void) SetFrontProcess(&parent); + } + } + else if(window_hack_state == 1) + { + if(layer_group) + { + // Set the window group level back to something less extreme + SetWindowGroupLevel(layer_group, kCGNormalWindowLevel); + } + window_hack_state = 2; + } + + front_window = FrontWindow(); + + } } #endif F64 elapsed = timer.getElapsedTimeF64(); @@ -289,6 +392,10 @@ int main(int argc, char **argv) // exception handler such as QuickTime. //checkExceptionHandler(); #endif + +#if LL_DARWIN + deleteAutoReleasePool(); +#endif } delete plugin; diff --git a/linden/indra/llplugin/slplugin/slplugin_info.plist b/linden/indra/llplugin/slplugin/slplugin_info.plist index b1daf87..c459738 100755 --- a/linden/indra/llplugin/slplugin/slplugin_info.plist +++ b/linden/indra/llplugin/slplugin/slplugin_info.plist @@ -6,7 +6,7 @@ <string>English</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> - <key>LSBackgroundOnly</key> - <true/> + <key>LSUIElement</key> + <string>1</string> </dict> </plist> diff --git a/linden/indra/media_plugins/webkit/CMakeLists.txt b/linden/indra/media_plugins/webkit/CMakeLists.txt index a47d5e0..2ab4a95 100644 --- a/linden/indra/media_plugins/webkit/CMakeLists.txt +++ b/linden/indra/media_plugins/webkit/CMakeLists.txt @@ -18,7 +18,7 @@ include(Linking) include(PluginAPI) include(MediaPluginBase) include(FindOpenGL) -#include(PulseAudio) +include(PulseAudio) include(WebKitLibPlugin) @@ -48,6 +48,9 @@ if(NOT CMAKE_SIZEOF_VOID_P MATCHES 4) add_definitions(-fPIC) endif(WINDOWS) endif (NOT CMAKE_SIZEOF_VOID_P MATCHES 4) +set(media_plugin_webkit_HEADER_FILES + volume_catcher.h + ) set(media_plugin_webkit_LINK_LIBRARIES ${LLPLUGIN_LIBRARIES} @@ -58,13 +61,33 @@ set(media_plugin_webkit_LINK_LIBRARIES ${PULSEAUDIO_LIBRARIES} ) +# Select which VolumeCatcher implementation to use if (LINUX) - list(APPEND media_plugin_webkit_SOURCE_FILES linux_volume_catcher.cpp) + if (PULSEAUDIO) + list(APPEND media_plugin_webkit_SOURCE_FILES linux_volume_catcher.cpp) + endif (PULSEAUDIO) list(APPEND media_plugin_webkit_LINK_LIBRARIES - ${UI_LIBRARIES} # for glib/GTK - ) -endif(LINUX) - + ${UI_LIBRARIES} # for glib/GTK + ) +elseif (DARWIN) + list(APPEND media_plugin_webkit_SOURCE_FILES mac_volume_catcher.cpp) + find_library(CORESERVICES_LIBRARY CoreServices) + find_library(AUDIOUNIT_LIBRARY AudioUnit) + list(APPEND media_plugin_webkit_LINK_LIBRARIES + ${CORESERVICES_LIBRARY} # for Component Manager calls + ${AUDIOUNIT_LIBRARY} # for AudioUnit calls + ) +elseif (WINDOWS) + list(APPEND media_plugin_webkit_SOURCE_FILES windows_volume_catcher.cpp) +else (LINUX) + # All other platforms use the dummy volume catcher for now. + list(APPEND media_plugin_webkit_SOURCE_FILES dummy_volume_catcher.cpp) +endif (LINUX) + +set_source_files_properties(${media_plugin_webkit_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND media_plugin_webkit_SOURCE_FILES ${media_plugin_webkit_HEADER_FILES}) add_library(media_plugin_webkit SHARED diff --git a/linden/indra/media_plugins/webkit/dummy_volume_catcher.cpp b/linden/indra/media_plugins/webkit/dummy_volume_catcher.cpp new file mode 100644 index 0000000..4df9887 --- /dev/null +++ b/linden/indra/media_plugins/webkit/dummy_volume_catcher.cpp @@ -0,0 +1,65 @@ +/** + * @file dummy_volume_catcher.cpp + * @brief A null implementation of the "VolumeCatcher" class for platforms where it's not implemented yet. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#include "volume_catcher.h" + + +class VolumeCatcherImpl +{ +}; + +///////////////////////////////////////////////////// + +VolumeCatcher::VolumeCatcher() +{ + pimpl = NULL; +} + +VolumeCatcher::~VolumeCatcher() +{ +} + +void VolumeCatcher::setVolume(F32 volume) +{ +} + +void VolumeCatcher::setPan(F32 pan) +{ +} + +void VolumeCatcher::pump() +{ +} + diff --git a/linden/indra/media_plugins/webkit/linux_volume_catcher.cpp b/linden/indra/media_plugins/webkit/linux_volume_catcher.cpp old mode 100755 new mode 100644 index 15a2dfb..c4c4181 --- a/linden/indra/media_plugins/webkit/linux_volume_catcher.cpp +++ b/linden/indra/media_plugins/webkit/linux_volume_catcher.cpp @@ -42,15 +42,16 @@ 5) Keep a list of all living audio players that we care about, adjust the volumes of all of them when we get a new setVolume() call */ -#include "linden_common.h" +# include <set> //imprudence -#include "linux_volume_catcher.h" +#include "linden_common.h" +#include "volume_catcher.h" -#if LL_PULSEAUDIO_ENABLED extern "C" { #include <glib.h> +#include <glib-object.h> #include <pulse/introspect.h> #include <pulse/context.h> @@ -163,11 +164,11 @@ extern "C" { } -class LinuxVolumeCatcherImpl +class VolumeCatcherImpl { public: - LinuxVolumeCatcherImpl(); - ~LinuxVolumeCatcherImpl(); + VolumeCatcherImpl(); + ~VolumeCatcherImpl(); void setVolume(F32 volume); void pump(void); @@ -191,7 +192,7 @@ public: bool mGotSyms; }; -LinuxVolumeCatcherImpl::LinuxVolumeCatcherImpl() +VolumeCatcherImpl::VolumeCatcherImpl() : mDesiredVolume(0.0f), mMainloop(NULL), mPAContext(NULL), @@ -201,17 +202,17 @@ LinuxVolumeCatcherImpl::LinuxVolumeCatcherImpl() init(); } -LinuxVolumeCatcherImpl::~LinuxVolumeCatcherImpl() +VolumeCatcherImpl::~VolumeCatcherImpl() { cleanup(); } -bool LinuxVolumeCatcherImpl::loadsyms(std::string pulse_dso_name) +bool VolumeCatcherImpl::loadsyms(std::string pulse_dso_name) { return grab_pa_syms(pulse_dso_name); } -void LinuxVolumeCatcherImpl::init() +void VolumeCatcherImpl::init() { // try to be as defensive as possible because PA's interface is a // bit fragile and (for our purposes) we'd rather simply not function @@ -224,6 +225,10 @@ void LinuxVolumeCatcherImpl::init() mGotSyms = loadsyms("libpulse-mainloop-glib.so.0"); if (!mGotSyms) return; + // better make double-sure glib itself is initialized properly. + if (!g_thread_supported ()) g_thread_init (NULL); + g_type_init(); + mMainloop = llpa_glib_mainloop_new(g_main_context_default()); if (mMainloop) { @@ -264,7 +269,7 @@ void LinuxVolumeCatcherImpl::init() } } -void LinuxVolumeCatcherImpl::cleanup() +void VolumeCatcherImpl::cleanup() { mConnected = false; @@ -282,7 +287,7 @@ void LinuxVolumeCatcherImpl::cleanup() mMainloop = NULL; } -void LinuxVolumeCatcherImpl::setVolume(F32 volume) +void VolumeCatcherImpl::setVolume(F32 volume) { mDesiredVolume = volume; @@ -296,13 +301,13 @@ void LinuxVolumeCatcherImpl::setVolume(F32 volume) pump(); } -void LinuxVolumeCatcherImpl::pump() +void VolumeCatcherImpl::pump() { gboolean may_block = FALSE; g_main_context_iteration(g_main_context_default(), may_block); } -void LinuxVolumeCatcherImpl::connected_okay() +void VolumeCatcherImpl::connected_okay() { pa_operation *op; @@ -326,7 +331,7 @@ void LinuxVolumeCatcherImpl::connected_okay() } } -void LinuxVolumeCatcherImpl::update_all_volumes(F32 volume) +void VolumeCatcherImpl::update_all_volumes(F32 volume) { for (std::set<U32>::iterator it = mSinkInputIndices.begin(); it != mSinkInputIndices.end(); ++it) @@ -335,7 +340,7 @@ void LinuxVolumeCatcherImpl::update_all_volumes(F32 volume) } } -void LinuxVolumeCatcherImpl::update_index_volume(U32 index, F32 volume) +void VolumeCatcherImpl::update_index_volume(U32 index, F32 volume) { static pa_cvolume cvol; llpa_cvolume_set(&cvol, mSinkInputNumChannels[index], @@ -357,7 +362,7 @@ void LinuxVolumeCatcherImpl::update_index_volume(U32 index, F32 volume) void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *sii, int eol, void *userdata) { - LinuxVolumeCatcherImpl *impl = dynamic_cast<LinuxVolumeCatcherImpl*>((LinuxVolumeCatcherImpl*)userdata); + VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata); llassert(impl); if (0 == eol) @@ -388,7 +393,7 @@ void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata) { - LinuxVolumeCatcherImpl *impl = dynamic_cast<LinuxVolumeCatcherImpl*>((LinuxVolumeCatcherImpl*)userdata); + VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata); llassert(impl); switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { @@ -422,7 +427,7 @@ void callback_subscription_alert(pa_context *context, pa_subscription_event_type void callback_context_state(pa_context *context, void *userdata) { - LinuxVolumeCatcherImpl *impl = dynamic_cast<LinuxVolumeCatcherImpl*>((LinuxVolumeCatcherImpl*)userdata); + VolumeCatcherImpl *impl = dynamic_cast<VolumeCatcherImpl*>((VolumeCatcherImpl*)userdata); llassert(impl); switch (llpa_context_get_state(context)) @@ -443,48 +448,30 @@ void callback_context_state(pa_context *context, void *userdata) ///////////////////////////////////////////////////// -LinuxVolumeCatcher::LinuxVolumeCatcher() +VolumeCatcher::VolumeCatcher() { - pimpl = new LinuxVolumeCatcherImpl(); + pimpl = new VolumeCatcherImpl(); } -LinuxVolumeCatcher::~LinuxVolumeCatcher() +VolumeCatcher::~VolumeCatcher() { delete pimpl; pimpl = NULL; } -void LinuxVolumeCatcher::setVolume(F32 volume) +void VolumeCatcher::setVolume(F32 volume) { llassert(pimpl); pimpl->setVolume(volume); } -void LinuxVolumeCatcher::pump() -{ - llassert(pimpl); - pimpl->pump(); -} - -#else // !LL_PULSEAUDIO_ENABLED - -// stub. - -LinuxVolumeCatcher::LinuxVolumeCatcher() -{ - pimpl = NULL; -} - -LinuxVolumeCatcher::~LinuxVolumeCatcher() -{ -} - -void LinuxVolumeCatcher::setVolume(F32 volume) +void VolumeCatcher::setPan(F32 pan) { + // TODO: implement this (if possible) } -void LinuxVolumeCatcher::pump() +void VolumeCatcher::pump() { + llassert(pimpl); + pimpl->pump(); } - -#endif // LL_PULSEAUDIO_ENABLED diff --git a/linden/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc b/linden/indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc old mode 100755 new mode 100644 diff --git a/linden/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc b/linden/indra/media_plugins/webkit/linux_volume_catcher_paglib_syms.inc old mode 100755 new mode 100644 diff --git a/linden/indra/media_plugins/webkit/mac_volume_catcher.cpp b/linden/indra/media_plugins/webkit/mac_volume_catcher.cpp new file mode 100644 index 0000000..190823f --- /dev/null +++ b/linden/indra/media_plugins/webkit/mac_volume_catcher.cpp @@ -0,0 +1,275 @@ +/** + * @file mac_volume_catcher.cpp + * @brief A Mac OS X specific hack to control the volume level of all audio channels opened by a process. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +/************************************************************************************************************** + This code works by using CaptureComponent to capture the "Default Output" audio component + (kAudioUnitType_Output/kAudioUnitSubType_DefaultOutput) and delegating all calls to the original component. + It does this just to keep track of all instances of the default output component, so that it can set the + kHALOutputParam_Volume parameter on all of them to adjust the output volume. +**************************************************************************************************************/ + +#include "volume_catcher.h" + +#include <Carbon/Carbon.h> +#include <QuickTime/QuickTime.h> +#include <AudioUnit/AudioUnit.h> + +struct VolumeCatcherStorage; + +class VolumeCatcherImpl +{ +public: + + void setVolume(F32 volume); + void setPan(F32 pan); + + void setInstanceVolume(VolumeCatcherStorage *instance); + + std::list<VolumeCatcherStorage*> mComponentInstances; + Component mOriginalDefaultOutput; + Component mVolumeAdjuster; + + static VolumeCatcherImpl *getInstance(); +private: + // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. + VolumeCatcherImpl(); + static VolumeCatcherImpl *sInstance; + + // The singlar instance of this class is expected to last until the process exits. + // To ensure this, we declare the destructor here but never define it, so any code which attempts to destroy the instance will not link. + ~VolumeCatcherImpl(); + + F32 mVolume; + F32 mPan; +}; + +VolumeCatcherImpl *VolumeCatcherImpl::sInstance = NULL;; + +struct VolumeCatcherStorage +{ + ComponentInstance self; + ComponentInstance delegate; +}; + +static ComponentResult volume_catcher_component_entry(ComponentParameters *cp, Handle componentStorage); +static ComponentResult volume_catcher_component_open(VolumeCatcherStorage *storage, ComponentInstance self); +static ComponentResult volume_catcher_component_close(VolumeCatcherStorage *storage, ComponentInstance self); + +VolumeCatcherImpl *VolumeCatcherImpl::getInstance() +{ + if(!sInstance) + { + sInstance = new VolumeCatcherImpl; + } + + return sInstance; +} + +VolumeCatcherImpl::VolumeCatcherImpl() +{ + mVolume = 1.0; // default to full volume + mPan = 0.0; // and center pan + + ComponentDescription desc; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_DefaultOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + // Find the original default output component + mOriginalDefaultOutput = FindNextComponent(NULL, &desc); + + // Register our own output component with the same parameters + mVolumeAdjuster = RegisterComponent(&desc, NewComponentRoutineUPP(volume_catcher_component_entry), 0, NULL, NULL, NULL); + + // Capture the original component, so we always get found instead. + CaptureComponent(mOriginalDefaultOutput, mVolumeAdjuster); + +} + +static ComponentResult volume_catcher_component_entry(ComponentParameters *cp, Handle componentStorage) +{ + ComponentResult result = badComponentSelector; + VolumeCatcherStorage *storage = (VolumeCatcherStorage*)componentStorage; + + switch(cp->what) + { + case kComponentOpenSelect: +// std::cerr << "kComponentOpenSelect" << std::endl; + result = CallComponentFunctionWithStorageProcInfo((Handle)storage, cp, (ProcPtr)volume_catcher_component_open, uppCallComponentOpenProcInfo); + break; + + case kComponentCloseSelect: +// std::cerr << "kComponentCloseSelect" << std::endl; + result = CallComponentFunctionWithStorageProcInfo((Handle)storage, cp, (ProcPtr)volume_catcher_component_close, uppCallComponentCloseProcInfo); + // CallComponentFunctionWithStorageProcInfo + break; + + default: +// std::cerr << "Delegating selector: " << cp->what << " to component instance " << storage->delegate << std::endl; + result = DelegateComponentCall(cp, storage->delegate); + break; + } + + return result; +} + +static ComponentResult volume_catcher_component_open(VolumeCatcherStorage *storage, ComponentInstance self) +{ + ComponentResult result = noErr; + VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); + + storage = new VolumeCatcherStorage; + + storage->self = self; + storage->delegate = NULL; + + result = OpenAComponent(impl->mOriginalDefaultOutput, &(storage->delegate)); + + if(result != noErr) + { +// std::cerr << "OpenAComponent result = " << result << ", component ref = " << storage->delegate << std::endl; + + // If we failed to open the delagate component, our open is going to fail. Clean things up. + delete storage; + } + else + { + // Success -- set up this component's storage + SetComponentInstanceStorage(self, (Handle)storage); + + // add this instance to the global list + impl->mComponentInstances.push_back(storage); + + // and set up the initial volume + impl->setInstanceVolume(storage); + } + + return result; +} + +static ComponentResult volume_catcher_component_close(VolumeCatcherStorage *storage, ComponentInstance self) +{ + ComponentResult result = noErr; + + if(storage) + { + if(storage->delegate) + { + CloseComponent(storage->delegate); + storage->delegate = NULL; + } + + VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); + impl->mComponentInstances.remove(storage); + delete[] storage; + } + + return result; +} + +void VolumeCatcherImpl::setVolume(F32 volume) +{ + VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); + impl->mVolume = volume; + + // Iterate through all known instances, setting the volume on each. + for(std::list<VolumeCatcherStorage*>::iterator iter = mComponentInstances.begin(); iter != mComponentInstances.end(); ++iter) + { + impl->setInstanceVolume(*iter); + } +} + +void VolumeCatcherImpl::setPan(F32 pan) +{ + VolumeCatcherImpl *impl = VolumeCatcherImpl::getInstance(); + impl->mPan = pan; + + // TODO: implement this. + // This will probably require adding a "panner" audio unit to the chain somehow. + // There's also a "3d mixer" component that we might be able to use... +} + +void VolumeCatcherImpl::setInstanceVolume(VolumeCatcherStorage *instance) +{ +// std::cerr << "Setting volume on component instance: " << (instance->delegate) << " to " << mVolume << std::endl; + + OSStatus err = noErr; + + if(instance && instance->delegate) + { + err = AudioUnitSetParameter( + instance->delegate, + kHALOutputParam_Volume, + kAudioUnitScope_Global, + 0, + mVolume, + 0); + } + + if(err) + { +// std::cerr << " AudioUnitSetParameter returned " << err << std::endl; + } +} + +///////////////////////////////////////////////////// + +VolumeCatcher::VolumeCatcher() +{ + pimpl = VolumeCatcherImpl::getInstance(); +} + +VolumeCatcher::~VolumeCatcher() +{ + // Let the instance persist until exit. +} + +void VolumeCatcher::setVolume(F32 volume) +{ + pimpl->setVolume(volume); +} + +void VolumeCatcher::setPan(F32 pan) +{ + pimpl->setPan(pan); +} + +void VolumeCatcher::pump() +{ + // No periodic tasks are necessary for this implementation. +} + diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp index 09ba8dc..f9b6451 100755 --- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -49,13 +49,15 @@ #if LL_LINUX # include <iomanip> # define LL_QTWEBKIT_USES_PIXMAPS 0 +extern "C" { +# include <glib.h> +# include <glib-object.h> +} #else # define LL_QTWEBKIT_USES_PIXMAPS 0 #endif // LL_LINUX -#if LL_LINUX -# include "linux_volume_catcher.h" -#endif // LL_LINUX +# include "volume_catcher.h" #if LL_WINDOWS # include <direct.h> @@ -65,7 +67,7 @@ #endif #if LL_WINDOWS - // *NOTE:Mani - This captures the module handle fo rthe dll. This is used below + // *NOTE:Mani - This captures the module handle for the dll. This is used below // to get the path to this dll for webkit initialization. // I don't know how/if this can be done with apr... namespace { HMODULE gModuleHandle;}; @@ -122,9 +124,7 @@ private: F32 mBackgroundG; F32 mBackgroundB; -#if LL_LINUX - LinuxVolumeCatcher mLinuxVolumeCatcher; -#endif // LL_LINUX + VolumeCatcher mVolumeCatcher; void setInitState(int state) { @@ -136,11 +136,19 @@ private: // void update(int milliseconds) { +#if LL_QTLINUX_DOESNT_HAVE_GLIB + // pump glib generously, as Linux browser plugins are on the + // glib main loop, even if the browser itself isn't - ugh + // This is NOT NEEDED if Qt itself was built with glib + // mainloop integration. + GMainContext *mainc = g_main_context_default(); + while(g_main_context_iteration(mainc, FALSE)); +#endif // LL_QTLINUX_DOESNT_HAVE_GLIB + + // pump qt LLQtWebKit::getInstance()->pump( milliseconds ); -#if LL_LINUX - mLinuxVolumeCatcher.pump(); -#endif // LL_LINUX + mVolumeCatcher.pump(); checkEditState(); @@ -209,6 +217,14 @@ private: } std::string application_dir = std::string( cwd ); +#if LL_LINUX + // take care to initialize glib properly, because some + // versions of Qt don't, and we indirectly need it for (some + // versions of) Flash to not crash the browser. + if (!g_thread_supported ()) g_thread_init (NULL); + g_type_init(); +#endif + #if LL_DARWIN // When running under the Xcode debugger, there's a setting called "Break on Debugger()/DebugStr()" which defaults to being turned on. // This causes the environment variable USERBREAK to be set to 1, which causes these legacy calls to break into the debugger. @@ -306,11 +322,14 @@ private: // append details to agent string LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent ); + // Set up window open behavior + LLQtWebKit::getInstance()->setWindowOpenBehavior(mBrowserWindowId, LLQtWebKit::WOB_SIMULATE_BLANK_HREF_CLICK); + #if !LL_QTWEBKIT_USES_PIXMAPS // don't flip bitmap LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true ); #endif // !LL_QTWEBKIT_USES_PIXMAPS - + // set background color // convert background color channels from [0.0, 1.0] to [0, 255]; LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, int(mBackgroundR * 255.0f), int(mBackgroundG * 255.0f), int(mBackgroundB * 255.0f) ); @@ -511,6 +530,19 @@ private: sendMessage(message); } + + //////////////////////////////////////////////////////////////////////////////// + // virtual + void onCookieChanged(const EventType& event) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "cookie_set"); + message.setValue("cookie", event.getStringValue()); + // These could be passed through as well, but aren't really needed. +// message.setValue("uri", event.getEventUri()); +// message.setValueBoolean("dead", (event.getIntValue() != 0)) + sendMessage(message); + } + LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers) { int result = 0; @@ -1056,6 +1088,10 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) mJavascriptEnabled = message_in.getValueBoolean("enable"); //LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled ); } + else if(message_name == "set_cookies") + { + LLQtWebKit::getInstance()->setCookies(message_in.getValue("cookies")); + } else if(message_name == "proxy_setup") { bool val = message_in.getValueBoolean("enable"); @@ -1125,9 +1161,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) void MediaPluginWebKit::setVolume(F32 volume) { -#if LL_LINUX - mLinuxVolumeCatcher.setVolume(volume); -#endif // LL_LINUX + mVolumeCatcher.setVolume(volume); } int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) diff --git a/linden/indra/media_plugins/webkit/volume_catcher.h b/linden/indra/media_plugins/webkit/volume_catcher.h new file mode 100644 index 0000000..855e99f --- /dev/null +++ b/linden/indra/media_plugins/webkit/volume_catcher.h @@ -0,0 +1,61 @@ +/** + * @file volume_catcher.h + * @brief Interface to a class with platform-specific implementations that allows control of the audio volume of all sources in the current process. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#ifndef VOLUME_CATCHER_H +#define VOLUME_CATCHER_H + +#include "linden_common.h" + +class VolumeCatcherImpl; + +class VolumeCatcher +{ + public: + VolumeCatcher(); + ~VolumeCatcher(); + + void setVolume(F32 volume); // 0.0 - 1.0 + + // Set the left-right pan of audio sources + // where -1.0 = left, 0 = center, and 1.0 = right + void setPan(F32 pan); + + void pump(); // call this at least a few times a second if you can - it affects how quickly we can 'catch' a new audio source and adjust its volume + + private: + VolumeCatcherImpl *pimpl; +}; + +#endif // VOLUME_CATCHER_H diff --git a/linden/indra/media_plugins/webkit/windows_volume_catcher.cpp b/linden/indra/media_plugins/webkit/windows_volume_catcher.cpp new file mode 100644 index 0000000..c02e7fc --- /dev/null +++ b/linden/indra/media_plugins/webkit/windows_volume_catcher.cpp @@ -0,0 +1,124 @@ +/** + * @file windows_volume_catcher.cpp + * @brief A Windows implementation of volume level control of all audio channels opened by a process. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#include "volume_catcher.h" +#include <windows.h> +#include "llsingleton.h" +class VolumeCatcherImpl : public LLSingleton<VolumeCatcherImpl> +{ +friend LLSingleton<VolumeCatcherImpl>; +public: + + void setVolume(F32 volume); + void setPan(F32 pan); + +private: + // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. + VolumeCatcherImpl(); + ~VolumeCatcherImpl(); + + typedef void (WINAPI *set_volume_func_t)(F32); + typedef void (WINAPI *set_mute_func_t)(bool); + + set_volume_func_t mSetVolumeFunc; + set_mute_func_t mSetMuteFunc; + + F32 mVolume; + F32 mPan; +}; +VolumeCatcherImpl::VolumeCatcherImpl() +: mVolume(1.0f), // default volume is max + mPan(0.f) // default pan is centered +{ + HMODULE handle = ::LoadLibrary(L"winmm.dll"); + if(handle) + { + mSetVolumeFunc = (set_volume_func_t)::GetProcAddress(handle, "setPluginVolume"); + mSetMuteFunc = (set_mute_func_t)::GetProcAddress(handle, "setPluginMute"); + } +} + +VolumeCatcherImpl::~VolumeCatcherImpl() +{ +} + + +void VolumeCatcherImpl::setVolume(F32 volume) +{ + mVolume = volume; + + if (mSetMuteFunc) + { + mSetMuteFunc(volume == 0.f); + } + if (mSetVolumeFunc) + { + mSetVolumeFunc(mVolume); + } +} + +void VolumeCatcherImpl::setPan(F32 pan) +{ // remember pan for calculating individual channel levels later + mPan = pan; +} + +///////////////////////////////////////////////////// + +VolumeCatcher::VolumeCatcher() +{ + pimpl = VolumeCatcherImpl::getInstance(); +} + +VolumeCatcher::~VolumeCatcher() +{ + // Let the instance persist until exit. +} + +void VolumeCatcher::setVolume(F32 volume) +{ + pimpl->setVolume(volume); +} + +void VolumeCatcher::setPan(F32 pan) +{ + pimpl->setPan(pan); +} + +void VolumeCatcher::pump() +{ + // No periodic tasks are necessary for this implementation. +} + + diff --git a/linden/install.xml b/linden/install.xml index 07e7498..402ce00 100644 --- a/linden/install.xml +++ b/linden/install.xml @@ -1144,30 +1144,23 @@ Portions copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura <key>darwin</key> <map> <key>md5sum</key> - <string>38a31c64cbb021320c6f8c0296933f2b</string> + <string>becffca6bd8dcb239de284ea2a8b485b</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20100402.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6+cookies-darwin-20100617.tar.bz2</uri> </map> <key>linux</key> <map> <key>md5sum</key> - <string>78e22d53c84c8642fbaa027fed20cc48</string> + <string>414d72dd59e3d83c96f0e1531360792e</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-20100407.tar.bz2</uri> - </map> - <key>linux64</key> - <map> - <key>md5sum</key> - <string>d602324a827be7e0a8c90f85d27d6151</string> - <key>url</key> - <uri>http://imprudenceviewer.org/download/libs/llqtwebkit-linux64-20100617.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-20100618.tar.bz2</uri> </map> <key>windows</key> <map> <key>md5sum</key> - <string>b6ec5fe296b8ad9097b182b5c09a9589</string> + <string>df1bdd683128e060d60e435f65d8f7e8</string> <key>url</key> - <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.6-20100402.tar.bz2</uri> + <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.6-20100617.tar.bz2</uri> </map> </map> </map> @@ -1456,6 +1449,25 @@ Copyright (C) 2004-2005 Vladimir Berezniker @ http://public.xdi.org/=vmpn </map> </map> </map> + <key>pulseaudio</key> + <map> + <key>copyright</key> + <string>Copyright 2004-2006 Lennart Poettering, Copyright 2006 Pierre Ossman (ossman@cendio.se) for Cendio AB</string> + <key>description</key> + <string>pulseaudio: headers only</string> + <key>license</key> + <string>lgpl</string> + <key>packages</key> + <map> + <key>linux</key> + <map> + <key>md5sum</key> + <string>30cb00069fe2a545fbf7be1070386236</string> + <key>url</key> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/linux-pulse-headers-0.9.14.tar.bz2</uri> + </map> + </map> + </map> <key>quicktime</key> <map> <key>copyright</key> -- cgit v1.1 From fcf35900271fbcb123b9d0d5652d79db0d1965fb Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Tue, 7 Sep 2010 17:38:53 +0200 Subject: fix platform specific mime_type xml loading note: mime_type<_nonwindowsplatform>.xml directs SLPlugin to the actual implementation. For using gstreamer on mac + win the file has to be changed (try the linux one :) ) --- linden/indra/newview/CMakeLists.txt | 14 +------------- linden/indra/newview/llappviewer.cpp | 11 +++++++++-- 2 files changed, 10 insertions(+), 15 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index 6fd259a..3dabb3b 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt @@ -1547,19 +1547,7 @@ if (WINDOWS) COMMENT "Copying Quicktime Plugin to the runtime folder." ) - # Copying the mime_types.xml file to app_settings - set(mime_types_source "${CMAKE_SOURCE_DIR}/newview/skins/default/xui/en-us") - set(mime_types_dest "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings") - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - -E - copy_if_different - ${mime_types_source}/mime_types_windows.xml - ${mime_types_dest}/mime_types.xml - COMMENT "Copying mime_types_windows.xml to mime_types.xml." - ) + endif (WINDOWS) diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp index a9a6052..f422f33 100644 --- a/linden/indra/newview/llappviewer.cpp +++ b/linden/indra/newview/llappviewer.cpp @@ -707,8 +707,15 @@ bool LLAppViewer::init() LLViewerJointMesh::updateVectorize(); // load MIME type -> media impl mappings - LLMIMETypes::parseMIMETypes( std::string("mime_types.xml") ); - + std::string mime_types_name; +#if LL_DARWIN + mime_types_name = "mime_types_mac.xml"; +#elif LL_LINUX + mime_types_name = "mime_types_linux.xml"; +#else + mime_types_name = "mime_types.xml"; +#endif + LLMIMETypes::parseMIMETypes( mime_types_name ); // Copy settings to globals. *TODO: Remove or move to appropriage class initializers settings_to_globals(); -- cgit v1.1 From f27a85fab0418b3aa6cd70a7111f970f7982e72e Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Thu, 9 Sep 2010 00:38:21 -0700 Subject: Removed more unused 'prepare' dependencies --- linden/indra/llprimitive/CMakeLists.txt | 1 - linden/indra/llrender/CMakeLists.txt | 1 - 2 files changed, 2 deletions(-) (limited to 'linden') diff --git a/linden/indra/llprimitive/CMakeLists.txt b/linden/indra/llprimitive/CMakeLists.txt index 716b247..e7ee811 100755 --- a/linden/indra/llprimitive/CMakeLists.txt +++ b/linden/indra/llprimitive/CMakeLists.txt @@ -52,7 +52,6 @@ set_source_files_properties(${llprimitive_HEADER_FILES} list(APPEND llprimitive_SOURCE_FILES ${llprimitive_HEADER_FILES}) add_library (llprimitive ${llprimitive_SOURCE_FILES}) -add_dependencies(llprimitive prepare) #add unit tests INCLUDE(LLAddBuildTest) diff --git a/linden/indra/llrender/CMakeLists.txt b/linden/indra/llrender/CMakeLists.txt index e42f9ab..3ba841e 100644 --- a/linden/indra/llrender/CMakeLists.txt +++ b/linden/indra/llrender/CMakeLists.txt @@ -90,4 +90,3 @@ else (SERVER AND NOT WINDOWS AND NOT DARWIN) ) endif (SERVER AND NOT WINDOWS AND NOT DARWIN) add_library (llrender ${llrender_SOURCE_FILES}) -add_dependencies(llrender prepare) -- cgit v1.1 From adc28fac384c713638946a37df2628dbffed3244 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Thu, 9 Sep 2010 05:06:41 -0700 Subject: Fixed plugin compile issues on windows --- linden/indra/media_plugins/webkit/media_plugin_webkit.cpp | 1 + linden/indra/media_plugins/webkit/windows_volume_catcher.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'linden') diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp index f9b6451..ebf64f8 100755 --- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -37,6 +37,7 @@ #include "linden_common.h" #include "indra_constants.h" // for indra keyboard codes +#include <iomanip> #include "llgl.h" diff --git a/linden/indra/media_plugins/webkit/windows_volume_catcher.cpp b/linden/indra/media_plugins/webkit/windows_volume_catcher.cpp index c02e7fc..f1afea7 100644 --- a/linden/indra/media_plugins/webkit/windows_volume_catcher.cpp +++ b/linden/indra/media_plugins/webkit/windows_volume_catcher.cpp @@ -35,7 +35,7 @@ #include "volume_catcher.h" #include <windows.h> -#include "llsingleton.h" +#include "llmemory.h" class VolumeCatcherImpl : public LLSingleton<VolumeCatcherImpl> { friend LLSingleton<VolumeCatcherImpl>; -- cgit v1.1 From f41c6363087f95ce5f7d99385e455d7e0105d883 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Sat, 10 Jul 2010 14:35:58 +0200 Subject: Imprudence style gstreamer plugin (remove llgst, syms and such) --- .../media_plugins/gstreamer010/CMakeLists.txt | 2 - .../gstreamer010/llmediaimplgstreamer_syms.cpp | 174 -------- .../gstreamer010/llmediaimplgstreamer_syms.h | 81 ---- .../gstreamer010/llmediaimplgstreamer_syms_raw.inc | 51 --- .../llmediaimplgstreamer_syms_rawv.inc | 5 - .../gstreamer010/llmediaimplgstreamervidplug.cpp | 166 +++++--- .../gstreamer010/llmediaimplgstreamervidplug.h | 5 +- .../gstreamer010/media_plugin_gstreamer010.cpp | 454 ++++++++++++++------- linden/indra/newview/lloverlaybar.cpp | 52 +-- linden/indra/newview/llstartup.cpp | 2 +- .../indra/newview/llviewermedia_streamingaudio.cpp | 22 +- .../indra/newview/llviewermedia_streamingaudio.h | 10 +- 12 files changed, 440 insertions(+), 584 deletions(-) delete mode 100755 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp delete mode 100755 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h delete mode 100755 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc delete mode 100755 linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc (limited to 'linden') diff --git a/linden/indra/media_plugins/gstreamer010/CMakeLists.txt b/linden/indra/media_plugins/gstreamer010/CMakeLists.txt index 6eab49c..a031157 100644 --- a/linden/indra/media_plugins/gstreamer010/CMakeLists.txt +++ b/linden/indra/media_plugins/gstreamer010/CMakeLists.txt @@ -44,13 +44,11 @@ endif (NOT CMAKE_SIZEOF_VOID_P MATCHES 4) set(media_plugin_gstreamer010_SOURCE_FILES media_plugin_gstreamer010.cpp - llmediaimplgstreamer_syms.cpp llmediaimplgstreamervidplug.cpp ) set(media_plugin_gstreamer010_HEADER_FILES llmediaimplgstreamervidplug.h - llmediaimplgstreamer_syms.h llmediaimplgstreamertriviallogging.h ) diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp deleted file mode 100755 index 82978ad..0000000 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/** - * @file llmediaimplgstreamer_syms.cpp - * @brief dynamic GStreamer symbol-grabbing code - * - * @cond - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2010, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlife.com/developers/opensource/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - * - * @endcond - */ - -#if LL_GSTREAMER010_ENABLED - -#include <string> - -extern "C" { -#include <gst/gst.h> - -#include "apr_pools.h" -#include "apr_dso.h" -} - -#include "llmediaimplgstreamertriviallogging.h" - -#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL -#include "llmediaimplgstreamer_syms_raw.inc" -#include "llmediaimplgstreamer_syms_rawv.inc" -#undef LL_GST_SYM - -// a couple of stubs for disgusting reasons -GstDebugCategory* -ll_gst_debug_category_new(gchar *name, guint color, gchar *description) -{ - static GstDebugCategory dummy; - return &dummy; -} -void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname) -{ -} - -static bool sSymsGrabbed = false; -static apr_pool_t *sSymGSTDSOMemoryPool = NULL; -static apr_dso_handle_t *sSymGSTDSOHandleG = NULL; -static apr_dso_handle_t *sSymGSTDSOHandleV = NULL; - - -bool grab_gst_syms(std::string gst_dso_name, - std::string gst_dso_name_vid) -{ - if (sSymsGrabbed) - { - // already have grabbed good syms - return TRUE; - } - - bool sym_error = false; - bool rtn = false; - apr_status_t rv; - apr_dso_handle_t *sSymGSTDSOHandle = NULL; - -#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##GSTSYM, sSymGSTDSOHandle, #GSTSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #GSTSYM); if (REQ) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #GSTSYM, (void*)ll##GSTSYM);}while(0) - - //attempt to load the shared libraries - apr_pool_create(&sSymGSTDSOMemoryPool, NULL); - - if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle, - gst_dso_name.c_str(), - sSymGSTDSOMemoryPool) )) - { - INFOMSG("Found DSO: %s", gst_dso_name.c_str()); -#include "llmediaimplgstreamer_syms_raw.inc" - - if ( sSymGSTDSOHandle ) - { - sSymGSTDSOHandleG = sSymGSTDSOHandle; - sSymGSTDSOHandle = NULL; - } - - if ( APR_SUCCESS == - (rv = apr_dso_load(&sSymGSTDSOHandle, - gst_dso_name_vid.c_str(), - sSymGSTDSOMemoryPool) )) - { - INFOMSG("Found DSO: %s", gst_dso_name_vid.c_str()); -#include "llmediaimplgstreamer_syms_rawv.inc" - rtn = !sym_error; - } - else - { - INFOMSG("Couldn't load DSO: %s", gst_dso_name_vid.c_str()); - rtn = false; // failure - } - } - else - { - INFOMSG("Couldn't load DSO: %s", gst_dso_name.c_str()); - rtn = false; // failure - } - - if (sym_error) - { - WARNMSG("Failed to find necessary symbols in GStreamer libraries."); - } - - if ( sSymGSTDSOHandle ) - { - sSymGSTDSOHandleV = sSymGSTDSOHandle; - sSymGSTDSOHandle = NULL; - } -#undef LL_GST_SYM - - sSymsGrabbed = !!rtn; - return rtn; -} - - -void ungrab_gst_syms() -{ - // should be safe to call regardless of whether we've - // actually grabbed syms. - - if ( sSymGSTDSOHandleG ) - { - apr_dso_unload(sSymGSTDSOHandleG); - sSymGSTDSOHandleG = NULL; - } - - if ( sSymGSTDSOHandleV ) - { - apr_dso_unload(sSymGSTDSOHandleV); - sSymGSTDSOHandleV = NULL; - } - - if ( sSymGSTDSOMemoryPool ) - { - apr_pool_destroy(sSymGSTDSOMemoryPool); - sSymGSTDSOMemoryPool = NULL; - } - - // NULL-out all of the symbols we'd grabbed -#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{ll##GSTSYM = NULL;}while(0) -#include "llmediaimplgstreamer_syms_raw.inc" -#include "llmediaimplgstreamer_syms_rawv.inc" -#undef LL_GST_SYM - - sSymsGrabbed = false; -} - - -#endif // LL_GSTREAMER010_ENABLED diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h deleted file mode 100755 index c309043..0000000 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @file llmediaimplgstreamer_syms.h - * @brief dynamic GStreamer symbol-grabbing code - * - * @cond - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2010, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlife.com/developers/opensource/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - * - * @endcond - */ - -#include "linden_common.h" - -#if LL_GSTREAMER010_ENABLED - -extern "C" { -#include <gst/gst.h> -} - -bool grab_gst_syms(std::string gst_dso_name, - std::string gst_dso_name_vid); -void ungrab_gst_syms(); - -#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__) -#include "llmediaimplgstreamer_syms_raw.inc" -#include "llmediaimplgstreamer_syms_rawv.inc" -#undef LL_GST_SYM - -// regrettable hacks to give us better runtime compatibility with older systems -#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0) -#define llg_return_val_if_fail(COND,V) do{if (!(COND)) return V;}while(0) - -// regrettable hacks because GStreamer was not designed for runtime loading -#undef GST_TYPE_MESSAGE -#define GST_TYPE_MESSAGE (llgst_message_get_type()) -#undef GST_TYPE_OBJECT -#define GST_TYPE_OBJECT (llgst_object_get_type()) -#undef GST_TYPE_PIPELINE -#define GST_TYPE_PIPELINE (llgst_pipeline_get_type()) -#undef GST_TYPE_ELEMENT -#define GST_TYPE_ELEMENT (llgst_element_get_type()) -#undef GST_TYPE_VIDEO_SINK -#define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type()) -// more regrettable hacks to stub-out these .h-exposed GStreamer internals -void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname); -#undef _gst_debug_register_funcptr -#define _gst_debug_register_funcptr ll_gst_debug_register_funcptr -GstDebugCategory* ll_gst_debug_category_new(gchar *name, guint color, gchar *description); -#undef _gst_debug_category_new -#define _gst_debug_category_new ll_gst_debug_category_new -#undef __gst_debug_enabled -#define __gst_debug_enabled (0) - -// more hacks -#define LLGST_MESSAGE_TYPE_NAME(M) (llgst_message_type_get_name(GST_MESSAGE_TYPE(M))) - -#endif // LL_GSTREAMER010_ENABLED diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc deleted file mode 100755 index b33e593..0000000 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc +++ /dev/null @@ -1,51 +0,0 @@ - -// required symbols to grab -LL_GST_SYM(true, gst_pad_peer_accept_caps, gboolean, GstPad *pad, GstCaps *caps); -LL_GST_SYM(true, gst_buffer_new, GstBuffer*, void); -LL_GST_SYM(true, gst_buffer_set_caps, void, GstBuffer*, GstCaps *); -LL_GST_SYM(true, gst_structure_set_value, void, GstStructure *, const gchar *, const GValue*); -LL_GST_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err); -LL_GST_SYM(true, gst_message_get_type, GType, void); -LL_GST_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type); -LL_GST_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug); -LL_GST_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug); -LL_GST_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending); -LL_GST_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state); -LL_GST_SYM(true, gst_object_unref, void, gpointer object); -LL_GST_SYM(true, gst_object_get_type, GType, void); -LL_GST_SYM(true, gst_pipeline_get_type, GType, void); -LL_GST_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline); -LL_GST_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data); -LL_GST_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name); -LL_GST_SYM(true, gst_element_get_type, GType, void); -LL_GST_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template); -LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp); -LL_GST_SYM(true, gst_element_class_set_details, void, GstElementClass *klass, const GstElementDetails *details); -LL_GST_SYM(true, gst_caps_unref, void, GstCaps* caps); -LL_GST_SYM(true, gst_caps_ref, GstCaps *, GstCaps* caps); -//LL_GST_SYM(true, gst_caps_is_empty, gboolean, const GstCaps *caps); -LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string); -LL_GST_SYM(true, gst_caps_replace, void, GstCaps **caps, GstCaps *newcaps); -LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index); -LL_GST_SYM(true, gst_caps_copy, GstCaps *, const GstCaps * caps); -//LL_GST_SYM(true, gst_caps_intersect, GstCaps *, const GstCaps *caps1, const GstCaps *caps2); -LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type); -LL_GST_SYM(true, _gst_plugin_register_static, void, GstPluginDesc *desc); -LL_GST_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value); -LL_GST_SYM(true, gst_structure_get_value, G_CONST_RETURN GValue *, const GstStructure *structure, const gchar *fieldname); -LL_GST_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value); -LL_GST_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value); -LL_GST_SYM(true, gst_structure_get_name, G_CONST_RETURN gchar *, const GstStructure *structure); -LL_GST_SYM(true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64); - -// optional symbols to grab -LL_GST_SYM(false, gst_registry_fork_set_enabled, void, gboolean enabled); -LL_GST_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled); -LL_GST_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent); -LL_GST_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug); -LL_GST_SYM(false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur); -LL_GST_SYM(false, gst_version, void, guint *major, guint *minor, guint *micro, guint *nano); - -// GStreamer 'internal' symbols which may not be visible in some runtimes but are still used in expanded GStreamer header macros - yuck! We'll substitute our own stubs for these. -//LL_GST_SYM(true, _gst_debug_register_funcptr, void, GstDebugFuncPtr func, gchar* ptrname); -//LL_GST_SYM(true, _gst_debug_category_new, GstDebugCategory *, gchar *name, guint color, gchar *description); diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc deleted file mode 100755 index 14fbcb4..0000000 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc +++ /dev/null @@ -1,5 +0,0 @@ - -// required symbols to grab -LL_GST_SYM(true, gst_video_sink_get_type, GType, void); - -// optional symbols to grab diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp index 9242830..1fee545 100755 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp @@ -33,7 +33,7 @@ * @endcond */ -#if LL_GSTREAMER010_ENABLED +///#if LL_GSTREAMER010_ENABLED #include "linden_common.h" @@ -41,15 +41,29 @@ #include <gst/video/video.h> #include <gst/video/gstvideosink.h> -#include "llmediaimplgstreamer_syms.h" #include "llmediaimplgstreamertriviallogging.h" +// #include "llthread.h" #include "llmediaimplgstreamervidplug.h" - GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug); #define GST_CAT_DEFAULT gst_slvideo_debug +/* Filter signals and args *//* +enum +{ + *//* FILL ME *//* + LAST_SIGNAL +}; + +enum +{ + ARG_0 +}; + +#define SLV_SIZECAPS ", width=(int){1,2,4,8,16,32,64,128,256,512,1024}, height=(int){1,2,4,8,16,32,64,128,256,512,1024} " +#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS ";" GST_VIDEO_CAPS_BGRx SLV_SIZECAPS +*/ #define SLV_SIZECAPS ", width=(int)[1,2048], height=(int)[1,2048] " #define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS @@ -81,9 +95,9 @@ gst_slvideo_base_init (gpointer gclass) }; GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - llgst_element_class_add_pad_template (element_class, - llgst_static_pad_template_get (&sink_factory)); - llgst_element_class_set_details (element_class, &element_details); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); + gst_element_class_set_details (element_class, &element_details); } @@ -94,7 +108,7 @@ gst_slvideo_finalize (GObject * object) slvideo = GST_SLVIDEO (object); if (slvideo->caps) { - llgst_caps_unref(slvideo->caps); + gst_caps_unref(slvideo->caps); } G_OBJECT_CLASS(parent_class)->finalize (object); @@ -105,7 +119,7 @@ static GstFlowReturn gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf) { GstSLVideo *slvideo; - llg_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); slvideo = GST_SLVIDEO(bsink); @@ -197,7 +211,7 @@ gst_slvideo_get_caps (GstBaseSink * bsink) GstSLVideo *slvideo; slvideo = GST_SLVIDEO(bsink); - return llgst_caps_ref (slvideo->caps); + return gst_caps_ref (slvideo->caps); } @@ -207,21 +221,32 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps) { GstSLVideo *filter; GstStructure *structure; +// GstCaps *intersection; GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps); filter = GST_SLVIDEO(bsink); - int width, height; +/* + intersection = gst_caps_intersect (filter->caps, caps); + if (gst_caps_is_empty (intersection)) + { + // no overlap between our caps and requested caps + return FALSE; + } + gst_caps_unref(intersection); +*/ + int width = 0; + int height = 0; gboolean ret; const GValue *fps; const GValue *par; - structure = llgst_caps_get_structure (caps, 0); - ret = llgst_structure_get_int (structure, "width", &width); - ret = ret && llgst_structure_get_int (structure, "height", &height); - fps = llgst_structure_get_value (structure, "framerate"); + structure = gst_caps_get_structure (caps, 0); + ret = gst_structure_get_int (structure, "width", &width); + ret = ret && gst_structure_get_int (structure, "height", &height); + fps = gst_structure_get_value (structure, "framerate"); ret = ret && (fps != NULL); - par = llgst_structure_get_value (structure, "pixel-aspect-ratio"); + par = gst_structure_get_value (structure, "pixel-aspect-ratio"); if (!ret) return FALSE; @@ -231,34 +256,35 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps) filter->width = width; filter->height = height; - - filter->fps_n = llgst_value_get_fraction_numerator(fps); - filter->fps_d = llgst_value_get_fraction_denominator(fps); + filter->fps_n = gst_value_get_fraction_numerator(fps); + filter->fps_d = gst_value_get_fraction_denominator(fps); if (par) { - filter->par_n = llgst_value_get_fraction_numerator(par); - filter->par_d = llgst_value_get_fraction_denominator(par); + filter->par_n = gst_value_get_fraction_numerator(par); + filter->par_d = gst_value_get_fraction_denominator(par); } else { filter->par_n = 1; filter->par_d = 1; } + GST_VIDEO_SINK_WIDTH(filter) = width; GST_VIDEO_SINK_HEIGHT(filter) = height; - + // crufty lump - we *always* accept *only* RGBX now. /* + filter->format = SLV_PF_UNKNOWN; - if (0 == strcmp(llgst_structure_get_name(structure), + if (0 == strcmp(gst_structure_get_name(structure), "video/x-raw-rgb")) { int red_mask; int green_mask; int blue_mask; - llgst_structure_get_int(structure, "red_mask", &red_mask); - llgst_structure_get_int(structure, "green_mask", &green_mask); - llgst_structure_get_int(structure, "blue_mask", &blue_mask); + gst_structure_get_int(structure, "red_mask", &red_mask); + gst_structure_get_int(structure, "green_mask", &green_mask); + gst_structure_get_int(structure, "blue_mask", &blue_mask); if ((unsigned int)red_mask == 0xFF000000 && (unsigned int)green_mask == 0x00FF0000 && (unsigned int)blue_mask == 0x0000FF00) @@ -272,12 +298,13 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps) filter->format = SLV_PF_BGRX; //fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n"); } - }*/ - + + }*/ + filter->format = SLV_PF_RGBX; GST_OBJECT_UNLOCK(filter); - + return TRUE; } @@ -324,15 +351,15 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, // we can ignore these and reverse-negotiate our preferred dimensions with // the peer if we like - we need to do this to obey dynamic resize requests // flowing in from the app. - structure = llgst_caps_get_structure (caps, 0); - if (!llgst_structure_get_int(structure, "width", &width) || - !llgst_structure_get_int(structure, "height", &height)) + structure = gst_caps_get_structure (caps, 0); + if (!gst_structure_get_int(structure, "width", &width) || + !gst_structure_get_int(structure, "height", &height)) { GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps); return GST_FLOW_NOT_NEGOTIATED; } - GstBuffer *newbuf = llgst_buffer_new(); + GstBuffer *newbuf = gst_buffer_new(); bool made_bufferdata_ptr = false; #define MAXDEPTHHACK 4 @@ -352,19 +379,19 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, GstCaps *desired_caps; GstStructure *desired_struct; - desired_caps = llgst_caps_copy (caps); - desired_struct = llgst_caps_get_structure (desired_caps, 0); + desired_caps = gst_caps_copy (caps); + desired_struct = gst_caps_get_structure (desired_caps, 0); GValue value = {0}; g_value_init(&value, G_TYPE_INT); g_value_set_int(&value, slwantwidth); - llgst_structure_set_value (desired_struct, "width", &value); + gst_structure_set_value (desired_struct, "width", &value); g_value_unset(&value); g_value_init(&value, G_TYPE_INT); g_value_set_int(&value, slwantheight); - llgst_structure_set_value (desired_struct, "height", &value); + gst_structure_set_value (desired_struct, "height", &value); - if (llgst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo), + if (gst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo), desired_caps)) { // todo: re-use buffers from a pool? @@ -375,13 +402,13 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK; GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf)); GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf); - llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps); + gst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps); made_bufferdata_ptr = true; } else { // peer hates our cap suggestion INFOMSG("peer hates us :("); - llgst_caps_unref(desired_caps); + gst_caps_unref(desired_caps); } } } @@ -393,7 +420,7 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK; GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf)); GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf); - llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps); + gst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps); } *buf = GST_BUFFER_CAST(newbuf); @@ -435,6 +462,20 @@ gst_slvideo_class_init (GstSLVideoClass * klass) #undef LLGST_DEBUG_FUNCPTR } +/* +static void +gst_slvideo_update_caps (GstSLVideo * slvideo) +{ + GstCaps *caps; + + // GStreamer will automatically convert colourspace if necessary. + // GStreamer will automatically resize media to one of these enumerated + // powers-of-two that we ask for (yay GStreamer!) + caps = gst_caps_from_string (SLV_ALLCAPS); + + gst_caps_replace (&slvideo->caps, caps); +} +*/ /* initialize the new element * instantiate pads and add them to element @@ -457,24 +498,24 @@ gst_slvideo_init (GstSLVideo * filter, filter->retained_frame_width = filter->width; filter->retained_frame_height = filter->height; filter->retained_frame_format = SLV_PF_UNKNOWN; - GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS); - llgst_caps_replace (&filter->caps, caps); + GstCaps *caps = gst_caps_from_string (SLV_ALLCAPS); + gst_caps_replace (&filter->caps, caps); filter->resize_forced_always = false; filter->resize_try_width = -1; filter->resize_try_height = -1; GST_OBJECT_UNLOCK(filter); + + //gst_slvideo_update_caps(filter); } static void gst_slvideo_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - llg_return_if_fail (GST_IS_SLVIDEO (object)); + g_return_if_fail (GST_IS_SLVIDEO (object)); - switch (prop_id) { - default: + if (prop_id) { G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; } } @@ -482,12 +523,10 @@ static void gst_slvideo_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - llg_return_if_fail (GST_IS_SLVIDEO (object)); + g_return_if_fail (GST_IS_SLVIDEO (object)); - switch (prop_id) { - default: + if (prop_id) { G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; } } @@ -505,7 +544,7 @@ plugin_init (GstPlugin * plugin) GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin", 0, (gchar*)"Second Life Video Sink"); - return llgst_element_register (plugin, "private-slvideo", + return gst_element_register (plugin, "private-slvideo", GST_RANK_NONE, GST_TYPE_SLVIDEO); } @@ -515,20 +554,19 @@ plugin_init (GstPlugin * plugin) some g++ versions buggily avoid __attribute__((constructor)) functions - so we provide an explicit plugin init function. */ -#define PACKAGE (gchar*)"packagehack" - // this macro quietly refers to PACKAGE internally - GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - (gchar*)"private-slvideoplugin", - (gchar*)"SL Video sink plugin", - plugin_init, (gchar*)"0.1", (gchar*)GST_LICENSE_UNKNOWN, - (gchar*)"Second Life", - (gchar*)"http://www.secondlife.com/"); -#undef PACKAGE + void gst_slvideo_init_class (void) { - ll_gst_plugin_register_static (&gst_plugin_desc); - DEBUGMSG("CLASS INIT"); + gst_plugin_register_static( GST_VERSION_MAJOR, + GST_VERSION_MINOR, + (const gchar *)"private-slvideoplugin", + (gchar *)"SL Video sink plugin", + plugin_init, + (const gchar *)"0.1", + GST_LICENSE_UNKNOWN, + (const gchar *)"Second Life", + (const gchar *)"Second Life", + (const gchar *)"http://www.secondlife.com/" ); } -#endif // LL_GSTREAMER010_ENABLED +///#endif // LL_GSTREAMER010_ENABLED diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h index 56f6db9..0ad8cf1 100755 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h @@ -36,12 +36,13 @@ #ifndef __GST_SLVIDEO_H__ #define __GST_SLVIDEO_H__ -#if LL_GSTREAMER010_ENABLED +///#if LL_GSTREAMER010_ENABLED extern "C" { #include <gst/gst.h> #include <gst/video/video.h> #include <gst/video/gstvideosink.h> +// #include <glib/gthread.h> } G_BEGIN_DECLS @@ -107,6 +108,6 @@ void gst_slvideo_init_class (void); G_END_DECLS -#endif // LL_GSTREAMER010_ENABLED +///#endif // LL_GSTREAMER010_ENABLED #endif /* __GST_SLVIDEO_H__ */ diff --git a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp index 7d34a1e..4dd182e 100755 --- a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp +++ b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp @@ -46,6 +46,7 @@ extern "C" { #include <gst/gst.h> +#include <gst/gstelement.h> } #include "llmediaimplgstreamer.h" @@ -53,8 +54,6 @@ extern "C" { #include "llmediaimplgstreamervidplug.h" -#include "llmediaimplgstreamer_syms.h" - ////////////////////////////////////////////////////////////////////////////// // class MediaPluginGStreamer010 : public MediaPluginBase @@ -68,6 +67,8 @@ public: static bool startup(); static bool closedown(); + static void set_gst_plugin_path(); + gboolean processGSTEvents(GstBus *bus, GstMessage *message); @@ -139,6 +140,8 @@ private: bool mSeekWanted; double mSeekDestination; + + std::string mLastTitle; // Very GStreamer-specific GMainLoop *mPump; // event pump for this media @@ -196,149 +199,179 @@ MediaPluginGStreamer010::processGSTEvents(GstBus *bus, GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING) { DEBUGMSG("Got GST message type: %s", - LLGST_MESSAGE_TYPE_NAME (message)); + GST_MESSAGE_TYPE_NAME (message)); } else { // TODO: grok 'duration' message type DEBUGMSG("Got GST message type: %s", - LLGST_MESSAGE_TYPE_NAME (message)); + GST_MESSAGE_TYPE_NAME (message)); } - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_BUFFERING: { - // NEEDS GST 0.10.11+ - if (llgst_message_parse_buffering) + switch (GST_MESSAGE_TYPE (message)) + { + case GST_MESSAGE_BUFFERING: { + // NEEDS GST 0.10.11+ and America discovered by C.Columbus gint percent = 0; - llgst_message_parse_buffering(message, &percent); + gst_message_parse_buffering(message, &percent); DEBUGMSG("GST buffering: %d%%", percent); - } - break; - } - case GST_MESSAGE_STATE_CHANGED: { - GstState old_state; - GstState new_state; - GstState pending_state; - llgst_message_parse_state_changed(message, - &old_state, - &new_state, - &pending_state); -#ifdef LL_GST_REPORT_STATE_CHANGES - // not generally very useful, and rather spammy. - DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s", - get_gst_state_name(old_state), - get_gst_state_name(new_state), - get_gst_state_name(pending_state)); -#endif // LL_GST_REPORT_STATE_CHANGES - switch (new_state) { - case GST_STATE_VOID_PENDING: - break; - case GST_STATE_NULL: break; - case GST_STATE_READY: - setStatus(STATUS_LOADED); - break; - case GST_STATE_PAUSED: - setStatus(STATUS_PAUSED); + } + case GST_MESSAGE_STATE_CHANGED: { + GstState old_state; + GstState new_state; + GstState pending_state; + gst_message_parse_state_changed(message, + &old_state, + &new_state, + &pending_state); + #ifdef LL_GST_REPORT_STATE_CHANGES + // not generally very useful, and rather spammy. + DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s", + get_gst_state_name(old_state), + get_gst_state_name(new_state), + get_gst_state_name(pending_state)); + #endif // LL_GST_REPORT_STATE_CHANGES + + switch (new_state) + { + case GST_STATE_VOID_PENDING: + break; + case GST_STATE_NULL: + break; + case GST_STATE_READY: + setStatus(STATUS_LOADED); + break; + case GST_STATE_PAUSED: + setStatus(STATUS_PAUSED); + break; + case GST_STATE_PLAYING: + setStatus(STATUS_PLAYING); + break; + } break; - case GST_STATE_PLAYING: - setStatus(STATUS_PLAYING); + } + case GST_MESSAGE_ERROR: + { + GError *err = NULL; + gchar *debug = NULL; + + gst_message_parse_error (message, &err, &debug); + WARNMSG("GST error: %s", err?err->message:"(unknown)"); + if (err) + g_error_free (err); + g_free (debug); + + mCommand = COMMAND_STOP; + + setStatus(STATUS_ERROR); + break; } - break; - } - case GST_MESSAGE_ERROR: { - GError *err = NULL; - gchar *debug = NULL; - - llgst_message_parse_error (message, &err, &debug); - WARNMSG("GST error: %s", err?err->message:"(unknown)"); - if (err) - g_error_free (err); - g_free (debug); - - mCommand = COMMAND_STOP; - - setStatus(STATUS_ERROR); - - break; - } - case GST_MESSAGE_INFO: { - if (llgst_message_parse_info) + case GST_MESSAGE_INFO: { GError *err = NULL; gchar *debug = NULL; - llgst_message_parse_info (message, &err, &debug); + gst_message_parse_info (message, &err, &debug); INFOMSG("GST info: %s", err?err->message:"(unknown)"); if (err) g_error_free (err); g_free (debug); + + break; } - break; - } - case GST_MESSAGE_WARNING: { - GError *err = NULL; - gchar *debug = NULL; + case GST_MESSAGE_WARNING: + { + GError *err = NULL; + gchar *debug = NULL; + + gst_message_parse_warning (message, &err, &debug); + WARNMSG("GST warning: %s", err?err->message:"(unknown)"); + if (err) + g_error_free (err); + g_free (debug); + + break; + } + case GST_MESSAGE_TAG: + { + GstTagList *new_tags; - llgst_message_parse_warning (message, &err, &debug); - WARNMSG("GST warning: %s", err?err->message:"(unknown)"); - if (err) - g_error_free (err); - g_free (debug); + gst_message_parse_tag( message, &new_tags ); - break; - } - case GST_MESSAGE_EOS: - /* end-of-stream */ - DEBUGMSG("GST end-of-stream."); - if (mIsLooping) - { - DEBUGMSG("looping media..."); - double eos_pos_sec = 0.0F; - bool got_eos_position = getTimePos(eos_pos_sec); + gchar *title = NULL; - if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC) + if ( gst_tag_list_get_string(new_tags, GST_TAG_TITLE, &title) ) { - // if we know that the movie is really short, don't - // loop it else it can easily become a time-hog - // because of GStreamer spin-up overhead - DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec); - // inject a COMMAND_PAUSE - mCommand = COMMAND_PAUSE; + //WARMING("Title: %s", title); + std::string newtitle(title); + gst_tag_list_free(new_tags); + + if ( newtitle != mLastTitle && !newtitle.empty() ) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); + message.setValue("name", newtitle ); + sendMessage( message ); + mLastTitle = newtitle; + } + g_free(title); } - else + + break; + } + case GST_MESSAGE_EOS: + { + /* end-of-stream */ + DEBUGMSG("GST end-of-stream."); + if (mIsLooping) { -#undef LLGST_LOOP_BY_SEEKING -// loop with a stop-start instead of a seek, because it actually seems rather -// faster than seeking on remote streams. -#ifdef LLGST_LOOP_BY_SEEKING - // first, try looping by an explicit rewind - bool seeksuccess = seek(0.0); - if (seeksuccess) + DEBUGMSG("looping media..."); + double eos_pos_sec = 0.0F; + bool got_eos_position = getTimePos(eos_pos_sec); + + if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC) { - play(1.0); + // if we know that the movie is really short, don't + // loop it else it can easily become a time-hog + // because of GStreamer spin-up overhead + DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec); + // inject a COMMAND_PAUSE + mCommand = COMMAND_PAUSE; } else -#endif // LLGST_LOOP_BY_SEEKING - { // use clumsy stop-start to loop - DEBUGMSG("didn't loop by rewinding - stopping and starting instead..."); - stop(); - play(1.0); + { + #undef LLGST_LOOP_BY_SEEKING + // loop with a stop-start instead of a seek, because it actually seems rather + // faster than seeking on remote streams. + #ifdef LLGST_LOOP_BY_SEEKING + // first, try looping by an explicit rewind + bool seeksuccess = seek(0.0); + if (seeksuccess) + { + play(1.0); + } + else + #endif // LLGST_LOOP_BY_SEEKING + { // use clumsy stop-start to loop + DEBUGMSG("didn't loop by rewinding - stopping and starting instead..."); + stop(); + play(1.0); + } } } - } - else // not a looping media - { - // inject a COMMAND_STOP - mCommand = COMMAND_STOP; - } - break; - default: - /* unhandled message */ - break; + else // not a looping media + { + // inject a COMMAND_STOP + mCommand = COMMAND_STOP; + } + } break; + + default: + /* unhandled message */ + break; } /* we want to be notified again the next time there is a message @@ -544,7 +577,7 @@ MediaPluginGStreamer010::pause() { DEBUGMSG("pausing media..."); // todo: error-check this? - llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); + gst_element_set_state(mPlaybin, GST_STATE_PAUSED); return true; } @@ -553,7 +586,7 @@ MediaPluginGStreamer010::stop() { DEBUGMSG("stopping media..."); // todo: error-check this? - llgst_element_set_state(mPlaybin, GST_STATE_READY); + gst_element_set_state(mPlaybin, GST_STATE_READY); return true; } @@ -564,7 +597,7 @@ MediaPluginGStreamer010::play(double rate) DEBUGMSG("playing media... rate=%f", rate); // todo: error-check this? - llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); + gst_element_set_state(mPlaybin, GST_STATE_PLAYING); return true; } @@ -593,7 +626,7 @@ MediaPluginGStreamer010::seek(double time_sec) bool success = false; if (mDoneInit && mPlaybin) { - success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME, + success = gst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME, GstSeekFlags(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT), GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND), @@ -612,11 +645,9 @@ MediaPluginGStreamer010::getTimePos(double &sec_out) { gint64 pos; GstFormat timefmt = GST_FORMAT_TIME; - got_position = - llgst_element_query_position && - llgst_element_query_position(mPlaybin, - &timefmt, - &pos); + got_position = gst_element_query_position(mPlaybin, + &timefmt, + &pos); got_position = got_position && (timefmt == GST_FORMAT_TIME); // GStreamer may have other ideas, but we consider the current position @@ -669,7 +700,7 @@ MediaPluginGStreamer010::load() } // instantiate a playbin element to do the hard work - mPlaybin = llgst_element_factory_make ("playbin", "play"); + mPlaybin = gst_element_factory_make ("playbin", "play"); if (!mPlaybin) { setStatus(STATUS_ERROR); @@ -677,21 +708,21 @@ MediaPluginGStreamer010::load() } // get playbin's bus - GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin)); + GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mPlaybin)); if (!bus) { setStatus(STATUS_ERROR); return false; // error } - mBusWatchID = llgst_bus_add_watch (bus, + mBusWatchID = gst_bus_add_watch (bus, llmediaimplgstreamer_bus_callback, this); - llgst_object_unref (bus); + gst_object_unref (bus); if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) { // instantiate a custom video sink mVideoSink = - GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo")); + GST_SLVIDEO(gst_element_factory_make ("private-slvideo", "slvideo")); if (!mVideoSink) { WARNMSG("Could not instantiate private-slvideo element."); @@ -721,8 +752,8 @@ MediaPluginGStreamer010::unload () if (mPlaybin) { - llgst_element_set_state (mPlaybin, GST_STATE_NULL); - llgst_object_unref (GST_OBJECT (mPlaybin)); + gst_element_set_state (mPlaybin, GST_STATE_NULL); + gst_object_unref (GST_OBJECT (mPlaybin)); mPlaybin = NULL; } @@ -755,7 +786,10 @@ MediaPluginGStreamer010::startup() // Init the glib type system - we need it. g_type_init(); + set_gst_plugin_path(); + +/* // Get symbols! #if LL_DARWIN if (! grab_gst_syms("libgstreamer-0.10.dylib", @@ -771,24 +805,24 @@ MediaPluginGStreamer010::startup() WARNMSG("Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled."); return false; } - - if (llgst_segtrap_set_enabled) - { - llgst_segtrap_set_enabled(FALSE); - } - else - { - WARNMSG("gst_segtrap_set_enabled() is not available; plugin crashes won't be caught."); - } - +*/ +// if (gst_segtrap_set_enabled) +// { + gst_segtrap_set_enabled(FALSE); +// } +// else +// { +// WARNMSG("gst_segtrap_set_enabled() is not available; plugin crashes won't be caught."); +// } +/* #if LL_LINUX // Gstreamer tries a fork during init, waitpid-ing on it, // which conflicts with any installed SIGCHLD handler... struct sigaction tmpact, oldact; - if (llgst_registry_fork_set_enabled) { + if (gst_registry_fork_set_enabled) { // if we can disable SIGCHLD-using forking behaviour, // do it. - llgst_registry_fork_set_enabled(false); + gst_registry_fork_set_enabled(false); } else { // else temporarily install default SIGCHLD handler @@ -799,24 +833,24 @@ MediaPluginGStreamer010::startup() sigaction(SIGCHLD, &tmpact, &oldact); } #endif // LL_LINUX - +*/ // Protect against GStreamer resetting the locale, yuck. static std::string saved_locale; saved_locale = setlocale(LC_ALL, NULL); // finally, try to initialize GStreamer! GError *err = NULL; - gboolean init_gst_success = llgst_init_check(NULL, NULL, &err); + gboolean init_gst_success = gst_init_check(NULL, NULL, &err); // restore old locale setlocale(LC_ALL, saved_locale.c_str() ); - +/* #if LL_LINUX // restore old SIGCHLD handler - if (!llgst_registry_fork_set_enabled) + if (!gst_registry_fork_set_enabled) sigaction(SIGCHLD, &oldact, NULL); #endif // LL_LINUX - +*/ if (!init_gst_success) // fail { if (err) @@ -830,16 +864,139 @@ MediaPluginGStreamer010::startup() } return false; } - + + // Set up logging facilities + gst_debug_remove_log_function( gst_debug_log_default ); +// gst_debug_add_log_function( gstreamer_log, NULL ); + // Init our custom plugins - only really need do this once. gst_slvideo_init_class(); - +/* + // List the plugins GStreamer can find + LL_DEBUGS("MediaImpl") << "Found GStreamer plugins:" << LL_ENDL; + GList *list; + GstRegistry *registry = gst_registry_get_default(); + std::string loaded = ""; + for (list = gst_registry_get_plugin_list(registry); + list != NULL; + list = g_list_next(list)) + { + GstPlugin *list_plugin = (GstPlugin *)list->data; + (bool)gst_plugin_is_loaded(list_plugin) ? loaded = "Yes" : loaded = "No"; + LL_DEBUGS("MediaImpl") << gst_plugin_get_name(list_plugin) << ", loaded? " << loaded << LL_ENDL; + } + gst_plugin_list_free(list); +*/ mDoneInit = true; } return true; } +void MediaPluginGStreamer010::set_gst_plugin_path() +{ + // Linux sets GST_PLUGIN_PATH in wrapper.sh, not here. +#if LL_WINDOWS || LL_DARWIN + + std::string imp_dir = ""; + + // Get the current working directory: +#if LL_WINDOWS + char* raw_dir; + raw_dir = _getcwd(NULL,0); + if( raw_dir != NULL ) + { + imp_dir = std::string( raw_dir ); + } +#elif LL_DARWIN + CFBundleRef main_bundle = CFBundleGetMainBundle(); + if( main_bundle != NULL ) + { + CFURLRef bundle_url = CFBundleCopyBundleURL( main_bundle ); + if( bundle_url != NULL ) + { + #ifndef MAXPATHLEN + #define MAXPATHLEN 1024 + #endif + char raw_dir[MAXPATHLEN]; + if( CFURLGetFileSystemRepresentation( bundle_url, true, (UInt8 *)raw_dir, MAXPATHLEN) ) + { + imp_dir = std::string( raw_dir ) + "/Contents/MacOS/"; + } + CFRelease(bundle_url); + } + } +#endif + + if( imp_dir == "" ) + { + WARNMSG("Could not get application directory, not setting GST_PLUGIN_PATH."); + return; + } + + DEBUGMSG("Imprudence is installed at %s", imp_dir); + + // ":" on Mac and 'Nix, ";" on Windows + std::string separator = G_SEARCHPATH_SEPARATOR_S; + + // Grab the current path, if it's set. + std::string old_plugin_path = ""; + char *old_path = getenv("GST_PLUGIN_PATH"); + if(old_path == NULL) + { + DEBUGMSG("Did not find user-set GST_PLUGIN_PATH."); + } + else + { + old_plugin_path = separator + std::string( old_path ); + } + + + // Search both Imprudence and Imprudence\lib\gstreamer-plugins. + // But we also want to search the path the user has set, if any. + std::string plugin_path = + "GST_PLUGIN_PATH=" + +#if LL_WINDOWS + imp_dir + "\\lib\\gstreamer-plugins" + +#elif LL_DARWIN + imp_dir + separator + + imp_dir + "/../Resources/lib/gstreamer-plugins" + +#endif + old_plugin_path; + + int put_result; + + // Place GST_PLUGIN_PATH in the environment settings +#if LL_WINDOWS + put_result = _putenv( (char*)plugin_path.c_str() ); +#elif LL_DARWIN + put_result = putenv( (char*)plugin_path.c_str() ); +#endif + + if( put_result == -1 ) + { + WARNMSG("Setting GST_PLUGIN_PATH failed!"); + } + else + { + DEBUGMSG("GST_PLUGIN_PATH set to %s", getenv("GST_PLUGIN_PATH")); + } + + // Don't load system plugins. We only want to use ours, to avoid conflicts. +#if LL_WINDOWS + put_result = _putenv( "GST_PLUGIN_SYSTEM_PATH=\"\"" ); +#elif LL_DARWIN + put_result = putenv( "GST_PLUGIN_SYSTEM_PATH=\"\"" ); +#endif + + if( put_result == -1 ) + { + WARNMSG("Setting GST_PLUGIN_SYSTEM_PATH=\"\" failed!"); + } + +#endif // LL_WINDOWS || LL_DARWIN +} + void MediaPluginGStreamer010::sizeChanged() @@ -881,7 +1038,7 @@ MediaPluginGStreamer010::closedown() if (!mDoneInit) return false; // error - ungrab_gst_syms(); +// ungrab_gst_syms(); mDoneInit = false; @@ -902,11 +1059,10 @@ std::string MediaPluginGStreamer010::getVersion() { std::string plugin_version = "GStreamer010 media plugin, GStreamer version "; - if (mDoneInit && - llgst_version) + if (mDoneInit) // && gst_version) { guint major, minor, micro, nano; - llgst_version(&major, &minor, µ, &nano); + gst_version(&major, &minor, µ, &nano); plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor, (unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR, (unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO); } else diff --git a/linden/indra/newview/lloverlaybar.cpp b/linden/indra/newview/lloverlaybar.cpp index e903df7..e713e22 100644 --- a/linden/indra/newview/lloverlaybar.cpp +++ b/linden/indra/newview/lloverlaybar.cpp @@ -43,7 +43,7 @@ #include "llagent.h" #include "llbutton.h" #include "llchatbar.h" -#include "llfloaterchat.h" +//#include "llfloaterchat.h" #include "llfocusmgr.h" #include "llimview.h" #include "llmediaremotectrl.h" @@ -75,60 +75,10 @@ LLOverlayBar *gOverlayBar = NULL; extern S32 MENU_BAR_HEIGHT; -//awfixme -/* -class LLTitleObserver - : public LLMediaObserver -{ -public: - void init(std::string url); - *//*virtual*//* void onMediaTitleChange(const EventType& event_in); -private: - LLMediaBase* mMediaSource; -}; - -static LLTitleObserver sTitleObserver; - -static LLRegisterWidget<LLMediaRemoteCtrl> r("media_remote"); - -void LLTitleObserver::init(std::string url) -{ - - if (!gAudiop) - { - return; - } - - mMediaSource = gAudiop->getStreamMedia(); // LLViewerMedia::getSource(); - - if ( mMediaSource ) - { - mMediaSource->addObserver(this); - } -} - -//virtual -void LLTitleObserver::onMediaTitleChange(const EventType& event_in) -{ - if ( !gSavedSettings.getBOOL("ShowStreamTitle") ) - { - return; - } - - LLChat chat; - //TODO: set this in XUI - std::string playing_msg = "Playing: " + event_in.getStringValue(); - chat.mText = playing_msg; - LLFloaterChat::addChat(chat, FALSE, FALSE); -} -*/ - // // Functions // - - void* LLOverlayBar::createMediaRemote(void* userdata) { LLOverlayBar *self = (LLOverlayBar*)userdata; diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index 237a967..64a2308 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp @@ -39,7 +39,7 @@ #else # include <sys/stat.h> // mkdir() #endif - +#include "llpluginclassmediaowner.h" #include "llviewermedia_streamingaudio.h" #include "llaudioengine.h" diff --git a/linden/indra/newview/llviewermedia_streamingaudio.cpp b/linden/indra/newview/llviewermedia_streamingaudio.cpp index 06946da..575dbc8 100644 --- a/linden/indra/newview/llviewermedia_streamingaudio.cpp +++ b/linden/indra/newview/llviewermedia_streamingaudio.cpp @@ -36,6 +36,7 @@ #include "linden_common.h" #include "llpluginclassmedia.h" #include "llviewermedia.h" +#include "llviewercontrol.h" #include "llviewermedia_streamingaudio.h" @@ -43,6 +44,8 @@ #include "llvfs.h" #include "lldir.h" +#include "llchat.h" +#include "llfloaterchat.h" LLStreamingAudio_MediaPlugins::LLStreamingAudio_MediaPlugins() : mMediaPlugin(NULL), @@ -153,9 +156,26 @@ std::string LLStreamingAudio_MediaPlugins::getURL() return mURL; } +void LLStreamingAudio_MediaPlugins::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ + if (event == MEDIA_EVENT_NAME_CHANGED) + { + std::string title = self->getMediaName(); + if (!title.empty() && gSavedSettings.getBOOL("ShowStreamTitle")) + { + //llinfos << "Playing: " << title << llendl; + LLChat chat; + //TODO: set this in XUI + std::string playing_msg = "Playing: " + title; + chat.mText = playing_msg; + LLFloaterChat::addChat(chat, FALSE, FALSE); + } + } +} + LLPluginClassMedia* LLStreamingAudio_MediaPlugins::initializeMedia(const std::string& media_type) { - LLPluginClassMediaOwner* owner = NULL; + LLPluginClassMediaOwner* owner = this; S32 default_size = 1; // audio-only - be minimal, doesn't matter LLPluginClassMedia* media_source = LLViewerMediaImpl::newSourceFromMediaType(media_type, owner, default_size, default_size); diff --git a/linden/indra/newview/llviewermedia_streamingaudio.h b/linden/indra/newview/llviewermedia_streamingaudio.h index 270bab7..816e213 100644 --- a/linden/indra/newview/llviewermedia_streamingaudio.h +++ b/linden/indra/newview/llviewermedia_streamingaudio.h @@ -36,12 +36,13 @@ #include "stdtypes.h" // from llcommon - #include "llstreamingaudio.h" class LLPluginClassMedia; -class LLStreamingAudio_MediaPlugins : public LLStreamingAudioInterface +class LLStreamingAudio_MediaPlugins : + public LLStreamingAudioInterface, + public LLPluginClassMediaOwner { public: LLStreamingAudio_MediaPlugins(); @@ -56,14 +57,17 @@ class LLStreamingAudio_MediaPlugins : public LLStreamingAudioInterface /*virtual*/ F32 getGain(); /*virtual*/ std::string getURL(); + // inherited from LLPluginClassMediaOwner + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + private: LLPluginClassMedia* initializeMedia(const std::string& media_type); LLPluginClassMedia *mMediaPlugin; - std::string mURL; F32 mGain; }; + #endif //LL_VIEWERMEDIA_STREAMINGAUDIO_H -- cgit v1.1 From 197f915816579a14e102075cf25a26127dfc1d32 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Thu, 23 Sep 2010 20:30:12 +0200 Subject: linux* kill imprudence gstreamer, use system gstreamer instead. who ever builds a release with that needs to consider to install some really old gstreamer at /usr/local/lib - lenny has 0.10.19 --- linden/indra/cmake/GStreamer.cmake | 114 -- linden/indra/cmake/GStreamer010Plugin.cmake | 20 +- linden/indra/llmedia/llmediaimplgstreamer.cpp | 928 --------------- .../gstreamer010/media_plugin_gstreamer010.cpp~ | 1219 -------------------- linden/indra/newview/linux_tools/getvoice.sh | 5 +- linden/indra/newview/linux_tools/wrapper.sh | 8 +- linden/indra/newview/viewer_manifest.py | 248 ++-- linden/indra/newview/viewer_manifest.py~ | 1176 ------------------- linden/install.xml | 14 - 9 files changed, 143 insertions(+), 3589 deletions(-) delete mode 100644 linden/indra/cmake/GStreamer.cmake delete mode 100644 linden/indra/llmedia/llmediaimplgstreamer.cpp delete mode 100755 linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp~ delete mode 100755 linden/indra/newview/viewer_manifest.py~ (limited to 'linden') diff --git a/linden/indra/cmake/GStreamer.cmake b/linden/indra/cmake/GStreamer.cmake deleted file mode 100644 index f5f9c03..0000000 --- a/linden/indra/cmake/GStreamer.cmake +++ /dev/null @@ -1,114 +0,0 @@ -# -*- cmake -*- -include(Prebuilt) - - # Maybe libxml and glib should have their own .cmake files - use_prebuilt_binary(libxml) - use_prebuilt_binary(glib) - - set(GSTREAMER_FOUND ON FORCE BOOL) - set(GSTREAMER_PLUGINS_BASE_FOUND ON FORCE BOOL) - - use_prebuilt_binary(gstreamer) - use_prebuilt_binary(gstreamer-plugins) - -if (WINDOWS) - - use_prebuilt_binary(iconv) - set(GSTREAMER_FOUND ON FORCE BOOL) - set(GSTREAMER_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib - ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/gio - ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/gobject - ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/libxml2 - ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/iconv - ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/gst - ) - - set(GSTREAMER_LIBRARIES - glib-2.0 - gio-2.0 - gmodule-2.0 - gobject-2.0 - gthread-2.0 - libgstvideo.lib - libgsttag.lib - libgstsdp.lib - libgstrtsp.lib - libgstrtp.lib - libgstriff.lib - libgstreamer-0.10.lib - libgstpbutils.lib - libgstnetbuffer.lib - libgstnet-0.10.lib - libgstinterfaces.lib - libgstdshow.lib - libgstdataprotocol-0.10.lib - libgstcontroller-0.10.lib - libgstbase-0.10.lib - libgstaudio.lib - libgstapp.lib - libxml2 - libxml2_a - libxml2_a_dll - iconv - iconv_a - ) - -else (WINDOWS) - - set(GSTREAMER_INCLUDE_DIRS - ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/gstreamer-0.10 - ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0 - ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0/glib - ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0/gobject - ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/libxml2 - ) - - if (DARWIN) # Mac - - use_prebuilt_binary(flac) - use_prebuilt_binary(liboil) - use_prebuilt_binary(neon) - use_prebuilt_binary(theora) - - set(GSTREAMER_LIBRARIES - gstvideo-0.10 - gstaudio-0.10 - gstbase-0.10 - gstreamer-0.10 - gobject-2.0 - gmodule-2.0 - gthread-2.0 - glib-2.0 - xml2.2 - ) - - else (DARWIN) # Linux - - use_prebuilt_binary(liboil) - use_prebuilt_binary(theora) - - set(GSTREAMER_LIBRARIES - gstvideo-0.10 - gstaudio-0.10 - gstbase-0.10 - gstreamer-0.10 - gobject-2.0 - gmodule-2.0 - dl - gthread-2.0 - rt - glib-2.0 - ) - - endif (DARWIN) - -endif (WINDOWS) - -if (GSTREAMER_FOUND AND GSTREAMER_PLUGINS_BASE_FOUND) - set(GSTREAMER ON CACHE BOOL "Build with GStreamer streaming media support.") -endif (GSTREAMER_FOUND AND GSTREAMER_PLUGINS_BASE_FOUND) - -if (GSTREAMER) - add_definitions(-DLL_GSTREAMER_ENABLED=1) -endif (GSTREAMER) diff --git a/linden/indra/cmake/GStreamer010Plugin.cmake b/linden/indra/cmake/GStreamer010Plugin.cmake index 0d33483..78ffd94 100644 --- a/linden/indra/cmake/GStreamer010Plugin.cmake +++ b/linden/indra/cmake/GStreamer010Plugin.cmake @@ -19,14 +19,18 @@ elseif (LINUX) ) # We don't need to explicitly link against gstreamer itself, because # LLMediaImplGStreamer probes for the system's copy at runtime. - set(GSTREAMER010_LIBRARIES - gobject-2.0 - gmodule-2.0 - dl - gthread-2.0 - rt - glib-2.0 - ) + set(GSTREAMER010_LIBRARIES + gstvideo-0.10 + gstaudio-0.10 + gstbase-0.10 + gstreamer-0.10 + gobject-2.0 + gmodule-2.0 + dl + gthread-2.0 + rt + glib-2.0 + ) endif (STANDALONE) if (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND) diff --git a/linden/indra/llmedia/llmediaimplgstreamer.cpp b/linden/indra/llmedia/llmediaimplgstreamer.cpp deleted file mode 100644 index 7af9c9a..0000000 --- a/linden/indra/llmedia/llmediaimplgstreamer.cpp +++ /dev/null @@ -1,928 +0,0 @@ -/** - * @file llmediaimplgstreamer.cpp - * @author Tofu Linden - * @brief implementation that supports various media through GStreamer. - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -///#if LL_GSTREAMER_ENABLED - -#if LL_WINDOWS - // GStreamer 0.10.22 - gstutils.h - conversion from 'guint64' to 'guint8'. - // This was an intentional change to make GStreamer more threadsafe, and - // is okay. Delete this bit if GStreamer ever gets more VS-friendly -- McCabe - #pragma warning(disable : 4244) -#endif - -#include "linden_common.h" -#include "llmediaimplgstreamer.h" - -extern "C" { -#include <gst/gst.h> -#include <gst/gstelement.h> -} - -#if LL_WINDOWS - #pragma warning(default : 4244) -#include <direct.h> -#include <stdlib.h> -#endif - -#include "llmediamanager.h" -#include "llmediaimplregister.h" - -#include "llmediaimplgstreamervidplug.h" -#include "llgstplaythread.h" - - -#if LL_DARWIN -#include <CoreFoundation/CoreFoundation.h> // For CF functions used in set_gst_plugin_path -#endif - -// register this impl with media manager factory -static LLMediaImplRegister sLLMediaImplGStreamerReg( "LLMediaImplGStreamer", new LLMediaImplGStreamerMaker() ); - -LLMediaImplGStreamerMaker::LLMediaImplGStreamerMaker() -{ - // Register to handle the scheme - mSchema.push_back( "rtsp" ); - mSchema.push_back( "rtmp" ); - - // Register to handle the category - mMimeTypeCategories.push_back( "video" ); - mMimeTypeCategories.push_back( "audio" ); -} - -/////////////////////////////////////////////////////////////////////////////// -// -LLMediaImplGStreamer:: -LLMediaImplGStreamer () : - mediaData ( NULL ), - mMediaRowbytes ( 1 ), - mTextureFormatPrimary ( LL_MEDIA_BGRA ), - mTextureFormatType ( LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV ), - mPump ( NULL ), - mPlaybin ( NULL ), - mVideoSink ( NULL ), - mLastTitle ( "" ), - mState( GST_STATE_NULL ), - mPlayThread ( NULL ) -{ - startup( NULL ); // Startup gstreamer if it hasn't been already. - - LL_DEBUGS("MediaManager") << "constructing media..." << LL_ENDL; - mVolume = -1.0; // XXX Hack to make the vould change happend first time - - setMediaDepth(4); - - // Create a pumpable main-loop for this media - mPump = g_main_loop_new (NULL, FALSE); - if (!mPump) - { - return; // error - } - - // instantiate a playbin element to do the hard work - mPlaybin = gst_element_factory_make ("playbin", "play"); - if (!mPlaybin) - { - // todo: cleanup pump - return; // error - } - - if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) - { - // instantiate and connect a custom video sink - LL_DEBUGS("MediaManager") << "extrenal video sink..." << LL_ENDL; - - // Plays inworld instead of in external player - mVideoSink = - GST_SLVIDEO(gst_element_factory_make ("private-slvideo", "slvideo")); - if (!mVideoSink) - { - LL_WARNS("MediaImpl") << "Could not instantiate private-slvideo element." << LL_ENDL; - // todo: cleanup. - return; // error - } - - g_object_set(mPlaybin, "video-sink", mVideoSink, (void*)NULL); - } -} - -// virtual -int LLMediaImplGStreamer::getTextureFormatPrimary() const -{ - return mTextureFormatPrimary; -} - -// virtual -int LLMediaImplGStreamer::getTextureFormatType() const -{ - return mTextureFormatType; -} - -// virtual -int LLMediaImplGStreamer::getTextureFormatInternal() const -{ - return LL_MEDIA_RGB8; -} - -/////////////////////////////////////////////////////////////////////////////// -// -LLMediaImplGStreamer:: -~LLMediaImplGStreamer () -{ - LL_DEBUGS("MediaImpl") << ("dtor of media...") << LL_ENDL; - unload(); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual -std::string LLMediaImplGStreamer::getVersion() -{ - guint major, minor, micro, nano; - gst_version(&major, &minor, µ, &nano); - std::string version = llformat("%d.%d.%d.%d",major,minor,micro,nano); - return version; -} - -// -// STARTUP -/////////////////////////////////////////////////////////////////////////////// -// (static) super-initialization - called once at application startup -bool LLMediaImplGStreamer::startup (LLMediaManagerData* init_data) -{ - static bool done_init = false; - if (!done_init) - { - // Init the glib type system - we need it. - g_type_init(); - - set_gst_plugin_path(); - - // Protect against GStreamer resetting the locale, yuck. - static std::string saved_locale; - saved_locale = setlocale(LC_ALL, NULL); - if (0 == gst_init_check(NULL, NULL, NULL)) - { - LL_WARNS("MediaImpl") << "GStreamer library failed to initialize and load standard plugins." << LL_ENDL; - setlocale(LC_ALL, saved_locale.c_str() ); - return false; - } - setlocale(LC_ALL, saved_locale.c_str() ); - - // Set up logging facilities - gst_debug_remove_log_function( gst_debug_log_default ); - gst_debug_add_log_function( gstreamer_log, NULL ); - - // Init our custom plugins - only really need do this once. - gst_slvideo_init_class(); - - - // List the plugins GStreamer can find - LL_DEBUGS("MediaImpl") << "Found GStreamer plugins:" << LL_ENDL; - GList *list; - GstRegistry *registry = gst_registry_get_default(); - std::string loaded = ""; - for (list = gst_registry_get_plugin_list(registry); - list != NULL; - list = g_list_next(list)) - { - GstPlugin *list_plugin = (GstPlugin *)list->data; - (bool)gst_plugin_is_loaded(list_plugin) ? loaded = "Yes" : loaded = "No"; - LL_DEBUGS("MediaImpl") << gst_plugin_get_name(list_plugin) << ", loaded? " << loaded << LL_ENDL; - } - gst_plugin_list_free(list); - - - done_init = true; - } - return true; -} - - -void LLMediaImplGStreamer::set_gst_plugin_path() -{ - // Linux sets GST_PLUGIN_PATH in wrapper.sh, not here. -#if LL_WINDOWS || LL_DARWIN - - std::string imp_dir = ""; - - // Get the current working directory: -#if LL_WINDOWS - char* raw_dir; - raw_dir = _getcwd(NULL,0); - if( raw_dir != NULL ) - { - imp_dir = std::string( raw_dir ); - } -#elif LL_DARWIN - CFBundleRef main_bundle = CFBundleGetMainBundle(); - if( main_bundle != NULL ) - { - CFURLRef bundle_url = CFBundleCopyBundleURL( main_bundle ); - if( bundle_url != NULL ) - { - #ifndef MAXPATHLEN - #define MAXPATHLEN 1024 - #endif - char raw_dir[MAXPATHLEN]; - if( CFURLGetFileSystemRepresentation( bundle_url, true, (UInt8 *)raw_dir, MAXPATHLEN) ) - { - imp_dir = std::string( raw_dir ) + "/Contents/MacOS/"; - } - CFRelease(bundle_url); - } - } -#endif - - if( imp_dir == "" ) - { - LL_WARNS("MediaImpl") << "Could not get application directory, not setting GST_PLUGIN_PATH." - << LL_ENDL; - return; - } - - LL_DEBUGS("MediaImpl") << "Imprudence is installed at " - << imp_dir << LL_ENDL; - - // ":" on Mac and 'Nix, ";" on Windows - std::string separator = G_SEARCHPATH_SEPARATOR_S; - - // Grab the current path, if it's set. - std::string old_plugin_path = ""; - char *old_path = getenv("GST_PLUGIN_PATH"); - if(old_path == NULL) - { - LL_DEBUGS("MediaImpl") << "Did not find user-set GST_PLUGIN_PATH." - << LL_ENDL; - } - else - { - old_plugin_path = separator + std::string( old_path ); - } - - - // Search both Imprudence and Imprudence\lib\gstreamer-plugins. - // But we also want to search the path the user has set, if any. - std::string plugin_path = -#if LL_WINDOWS - imp_dir + "\\lib\\gstreamer-plugins" + -#elif LL_DARWIN - imp_dir + separator + - imp_dir + "/../Resources/lib/gstreamer-plugins" + -#endif - old_plugin_path; - - int put_result; - - // Place GST_PLUGIN_PATH in the environment settings -#if LL_WINDOWS - put_result = _putenv_s( "GST_PLUGIN_PATH", (char*)plugin_path.c_str() ); -#elif LL_DARWIN - put_result = setenv( "GST_PLUGIN_PATH", (char*)plugin_path.c_str(), 1 ); -#endif - - if( put_result == -1 ) - { - LL_WARNS("MediaImpl") << "Setting GST_PLUGIN_PATH failed!" << LL_ENDL; - } - else - { - LL_DEBUGS("MediaImpl") << "GST_PLUGIN_PATH set to " - << getenv("GST_PLUGIN_PATH") << LL_ENDL; - } - - // Don't load system plugins. We only want to use ours, to avoid conflicts. -#if LL_WINDOWS - put_result = _putenv_s( "GST_PLUGIN_SYSTEM_PATH", "" ); -#elif LL_DARWIN - put_result = setenv( "GST_PLUGIN_SYSTEM_PATH", "", 1 ); -#endif - - if( put_result == -1 ) - { - LL_WARNS("MediaImpl") << "Setting GST_PLUGIN_SYSTEM_PATH=\"\" failed!" - << LL_ENDL; - } - -#endif // LL_WINDOWS || LL_DARWIN -} - - -void LLMediaImplGStreamer::gstreamer_log(GstDebugCategory *category, - GstDebugLevel level, - const gchar *file, - const gchar *function, - gint line, - GObject *object, - GstDebugMessage *message, - gpointer data) -{ - std::stringstream log(std::stringstream::out); - - // Log format example: - // - // GST_ELEMENT_PADS: removing pad 'sink' (in gstelement.c:757:gst_element_remove_pad) - // - log << gst_debug_category_get_name( category ) << ": " - << gst_debug_message_get(message) << " " - << "(in " << file << ":" << line << ":" << function << ")"; - - switch( level ) - { - case GST_LEVEL_ERROR: - LL_WARNS("MediaImpl") << "(ERROR) " << log.str() << LL_ENDL; - break; - case GST_LEVEL_WARNING: - LL_WARNS("MediaImpl") << log.str() << LL_ENDL; - break; - case GST_LEVEL_DEBUG: - LL_DEBUGS("MediaImpl") << log.str() << LL_ENDL; - break; - case GST_LEVEL_INFO: - LL_INFOS("MediaImpl") << log.str() << LL_ENDL; - break; - default: - // Do nothing. - break; - } -} - - -bool LLMediaImplGStreamer::closedown() -{ - return true; -} - - -bool LLMediaImplGStreamer::setDebugLevel( LLMediaBase::EDebugLevel level ) -{ - // Do parent class stuff. - LLMediaImplCommon::setDebugLevel(level); - - // Set GStreamer verbosity. - gst_debug_set_default_threshold( (GstDebugLevel)level ); - - return true; -} - - -/////////////////////////////////////////////////////////////////////////////// -// -// Uncomment the line below to enable spammy debug data. -//#define LL_GST_REPORT_STATE_CHANGES -#ifdef LL_GST_REPORT_STATE_CHANGES -static const char* get_gst_state_name(GstState state) -{ - switch (state) - { - case GST_STATE_VOID_PENDING: return "VOID_PENDING"; - case GST_STATE_NULL: return "NULL"; - case GST_STATE_READY: return "READY"; - case GST_STATE_PAUSED: return "PAUSED"; - case GST_STATE_PLAYING: return "PLAYING"; - } - return "(unknown)"; -} -#endif // LL_GST_REPORT_STATE_CHANGES - -//static -gboolean LLMediaImplGStreamer::bus_callback(GstBus *bus, GstMessage *message, gpointer data) -{ -#ifdef LL_GST_REPORT_STATE_CHANGES - LL_DEBUGS("MediaCallback") << "Got GST message type: " << GST_MESSAGE_TYPE_NAME (message) << LL_ENDL; -#endif - - LLMediaImplGStreamer *impl = (LLMediaImplGStreamer*)data; - - switch (GST_MESSAGE_TYPE (message)) - { - case GST_MESSAGE_BUFFERING: - { - gint percent = 0; - gst_message_parse_buffering(message, &percent); -#ifdef LL_GST_REPORT_STATE_CHANGES - LL_DEBUGS("MediaBuffering") << "GST buffering: " << percent << "%%" << LL_ENDL; -#endif - LLMediaEvent event( impl, percent ); - impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event ); - } - break; - case GST_MESSAGE_STATE_CHANGED: - { - GstState old_state; - GstState new_state; - GstState pending_state; - gst_message_parse_state_changed(message, - &old_state, - &new_state, - &pending_state); -#ifdef LL_GST_REPORT_STATE_CHANGES - // not generally very useful, and rather spammy. - LL_DEBUGS("MediaState") << "GST state change (old,<new>,pending): "<< get_gst_state_name(old_state) << ",<" << get_gst_state_name(new_state) << ">," << get_gst_state_name(pending_state) << LL_ENDL; -#endif // LL_GST_REPORT_STATE_CHANGES - - switch (new_state) - { - case GST_STATE_VOID_PENDING: - break; - case GST_STATE_NULL: -#ifdef LL_GST_REPORT_STATE_CHANGES - LL_DEBUGS("MediaImpl") << "State changed to NULL" << LL_ENDL; -#endif - if (impl->getState() == GST_STATE_PLAYING) - { - // Stream was probably dropped, trying to restart - impl->play(); -#ifdef LL_GST_REPORT_STATE_CHANGES - LL_DEBUGS("MediaImpl") << "Trying to restart." << LL_ENDL; -#endif - } - break; - case GST_STATE_READY: - break; - case GST_STATE_PAUSED: - break; - case GST_STATE_PLAYING: - //impl->mLastTitle = ""; - - LLMediaEvent event( impl, 100 ); - impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event ); - // emit an event to say that a media source was loaded - LLMediaEvent event2( impl ); - impl->getEventEmitter().update( &LLMediaObserver::onMediaLoaded, event2 ); - break; - } - break; - } - case GST_MESSAGE_ERROR: - { - GError *err = NULL; - gchar *debug = NULL; - - gst_message_parse_error (message, &err, &debug); - LL_WARNS("MediaImpl") << "GST Error: " << err->message << LL_ENDL; - g_error_free (err); - g_free (debug); - - impl->addCommand(LLMediaBase::COMMAND_STOP); - //impl->addCommand(LLMediaBase::COMMAND_START); - - break; - } - case GST_MESSAGE_INFO: - { - GError *err = NULL; - gchar *debug = NULL; - - gst_message_parse_info (message, &err, &debug); - LL_INFOS("MediaImpl") << "GST info: " << err->message - << LL_ENDL; - g_error_free (err); - g_free (debug); - break; - } - case GST_MESSAGE_WARNING: - { - GError *err = NULL; - gchar *debug = NULL; - - gst_message_parse_warning (message, &err, &debug); - LL_WARNS("MediaImpl") << "GST warning: " << err->message - << LL_ENDL; - g_error_free (err); - g_free (debug); - - break; - } - case GST_MESSAGE_TAG: - { - GstTagList *new_tags; - - gst_message_parse_tag( message, &new_tags ); - - gchar *title; - - if ( gst_tag_list_get_string(new_tags, GST_TAG_TITLE, &title) ) - { - LL_INFOS("MediaInfo") << "Title: " << title << LL_ENDL; - std::string newtitle(title); - gst_tag_list_free(new_tags); - - if ( newtitle != impl->mLastTitle && newtitle != "" ) - { - impl->mLastTitle = newtitle; - LLMediaEvent event( impl, impl->mLastTitle ); - impl->getEventEmitter().update( &LLMediaObserver::onMediaTitleChange, event ); - } - - g_free(title); - } - - break; - } - case GST_MESSAGE_EOS: - { - /* end-of-stream */ - LL_DEBUGS("MediaImpl") << "GST end-of-stream." << LL_ENDL; - if (impl->isLooping()) - { - LL_DEBUGS("MediaImpl") << "looping media..." << LL_ENDL; - impl->stop(); - impl->play(); - } - else - { - // inject a COMMAND_STOP - impl->addCommand(LLMediaBase::COMMAND_STOP); - } - break; - } - default: - /* unhandled message */ - break; - } - /* we want to be notified again the next time there is a message - * on the bus, so return true (false means we want to stop watching - * for messages on the bus and our callback should not be called again) - */ - return TRUE; -} - -/////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplGStreamer::navigateTo (const std::string urlIn) -{ - LL_DEBUGS("MediaImpl") << "Setting media URI: " << urlIn.c_str() - << LL_ENDL; - - if (mPump == NULL || mPlaybin == NULL) - { - return false; - } - - setStatus( LLMediaBase::STATUS_NAVIGATING ); - - // set URI - g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), (void*)NULL); - - // get playbin's bus - perhaps this can/should be done in ctor - GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mPlaybin)); - if (!bus) - { - return false; - } - gst_bus_add_watch (bus, bus_callback, this); - gst_object_unref (bus); - - mState = GST_STATE_READY; - - return true; -} - -/////////////////////////////////////////////////////////////////////////////// -// -bool LLMediaImplGStreamer::unload() -{ - LL_DEBUGS("MediaImpl") << "unloading media..." << LL_ENDL; - if (mPlaybin) - { - gst_element_set_state (mPlaybin, GST_STATE_NULL); - mState = GST_STATE_NULL; - gst_object_unref (GST_OBJECT (mPlaybin)); - mPlaybin = NULL; - } - - if (mPump) - { - g_main_loop_quit(mPump); - mPump = NULL; - } - - if (mediaData) - { - delete [] mediaData; - mediaData = NULL; - } - - mVideoSink = NULL; - mState = GST_STATE_NULL; - setStatus(LLMediaBase::STATUS_UNKNOWN); - - return true; -} - -/////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplGStreamer::updateMedia() -{ - //LL_DEBUGS("MediaImpl") << "updating media..." << LL_ENDL; - - // sanity check - if (mPump == NULL || mPlaybin == NULL) - { -#ifdef LL_GST_REPORT_STATE_CHANGES - LL_DEBUGS("MediaImpl") << "dead media..." << LL_ENDL; -#endif - mState = GST_STATE_NULL; - setStatus(LLMediaBase::STATUS_DEAD); - return false; - } - - if (mState == GST_STATE_VOID_PENDING || mState == GST_STATE_NULL) - return false; - - // process next outstanding command - switch (nextCommand()) - { - case LLMediaBase::COMMAND_START: - LL_DEBUGS("MediaImpl") << "COMMAND_START" << LL_ENDL; - if (getStatus() == LLMediaBase::STATUS_PAUSED || - getStatus() == LLMediaBase::STATUS_NAVIGATING || - getStatus() == LLMediaBase::STATUS_STOPPED) - { - play(); - setStatus(LLMediaBase::STATUS_STARTED); - clearCommand(); - } - break; - case LLMediaBase::COMMAND_STOP: - LL_DEBUGS("MediaImpl") << "COMMAND_STOP" << LL_ENDL; - stop(); - setStatus(LLMediaBase::STATUS_STOPPED); - clearCommand(); - break; - case LLMediaBase::COMMAND_PAUSE: - LL_DEBUGS("MediaImpl") << "COMMAND_PAUSE" << LL_ENDL; - if (getStatus() == LLMediaBase::STATUS_STARTED) - { - pause(); - setStatus(LLMediaBase::STATUS_PAUSED); - clearCommand(); - } - break; - default: - LL_INFOS("MediaImpl") << "Unknown command" << LL_ENDL; - clearCommand(); - break; - case LLMediaBase::COMMAND_NONE: - break; - } - - // deal with results - if (g_main_context_pending(g_main_loop_get_context(mPump))) - { - g_main_context_iteration(g_main_loop_get_context(mPump), FALSE); - } - - if (mVideoSink) - { - GST_OBJECT_LOCK(mVideoSink); - if (mVideoSink->retained_frame_ready) - { -#ifdef LL_GST_REPORT_STATE_CHANGES - LL_DEBUGS("MediaImpl") <<"NEW FRAME " << LL_ENDL; -#endif - if (mVideoSink->retained_frame_width != getMediaWidth() || - mVideoSink->retained_frame_height != getMediaHeight()) - // *TODO: also check for change in format - { - // just resize containe - int neww = mVideoSink->retained_frame_width; - int newh = mVideoSink->retained_frame_height; - int newd = SLVPixelFormatBytes[mVideoSink->retained_frame_format]; - if (SLV_PF_RGBX == mVideoSink->retained_frame_format) - { - mTextureFormatPrimary = LL_MEDIA_RGBA; - mTextureFormatType = LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV; - } - else - { - mTextureFormatPrimary = LL_MEDIA_BGRA; - mTextureFormatType = LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV; - } - mMediaRowbytes = neww * newd; - LL_DEBUGS("MediaImpl") - << "video container resized to " << - neww <<"x"<< newh << LL_ENDL; - - delete[] mediaData; - mediaData = new unsigned char[mMediaRowbytes * - newh]; - - GST_OBJECT_UNLOCK(mVideoSink); - - setMediaDepth(newd); - setMediaSize(neww, newh); - return true; - } - - // we're gonna totally consume this frame - reset 'ready' flag - mVideoSink->retained_frame_ready = FALSE; - memcpy(mediaData, mVideoSink->retained_frame_data, - mMediaRowbytes * getMediaHeight()); - - GST_OBJECT_UNLOCK(mVideoSink); - LLMediaEvent event( this ); - mEventEmitter.update( &LLMediaObserver::onMediaContentsChange, event ); - return true; - } - else - { - // nothing to do yet. - GST_OBJECT_UNLOCK(mVideoSink); - return true; - } - } - - return true; -} - -/////////////////////////////////////////////////////////////////////////////// -// -bool LLMediaImplGStreamer::stop() -{ - LL_DEBUGS("MediaImpl") << "attempting to stop..." << LL_ENDL; - - if (!mPlaybin || mState == GST_STATE_NULL) - return true; - - GstStateChangeReturn state_change; - - state_change = gst_element_set_state(mPlaybin, GST_STATE_READY); - - LL_DEBUGS("MediaImpl") << gst_element_state_change_return_get_name(state_change) << LL_ENDL; - - if (state_change == GST_STATE_CHANGE_FAILURE) - { - LL_WARNS("MediaImpl") << "could not stop stream!" << LL_ENDL; - return false; - } - else - { - // Going into pending after play keeps dead streams from looping - (mState == GST_STATE_PLAYING) ? (mState = GST_STATE_VOID_PENDING) : (mState = GST_STATE_READY); - return true; - } -} - -/////////////////////////////////////////////////////////////////////////////// -// -bool LLMediaImplGStreamer::play() -{ - LL_DEBUGS("MediaImpl") << "attempting to play..." << LL_ENDL; - - if (!mPlaybin || mState == GST_STATE_NULL) - return true; - - - if( getState() == GST_STATE_PLAYING ) - { - LL_DEBUGS("MediaImpl") << "... but already playing." << LL_ENDL; - return true; - } - - // Clean up the existing thread, if any. - if( mPlayThread != NULL && mPlayThread->isStopped()) - { - delete mPlayThread; - mPlayThread = NULL; - } - - if( mPlayThread == NULL ) - { - // Make a new thread to start playing. This keeps the viewer - // responsive while the stream is resolved and buffered. - mPlayThread = new LLGstPlayThread( (LLMediaImplCommon *)this, "GstPlayThread", NULL); - mPlayThread->start(); - } - - return true; -} - - -void LLMediaImplGStreamer::startPlay() -{ - GstStateChangeReturn state_change; - - state_change = gst_element_set_state(mPlaybin, GST_STATE_PLAYING); - mState = GST_STATE_PLAYING; - - LL_DEBUGS("MediaImpl") << gst_element_state_change_return_get_name(state_change) << LL_ENDL; - - // Check to make sure playing was successful. If not, stop. - // NOTE: state_change is almost always GST_STATE_CHANGE_ASYNC - if (state_change == GST_STATE_CHANGE_FAILURE) - { - // If failing from a bad stream, go into an unknown - // state to stop bus_callback from looping back. - // We also force a stop in case the operations don't sync - setStatus(LLMediaBase::STATUS_UNKNOWN); - stop(); - } -} - -/////////////////////////////////////////////////////////////////////////////// -// -bool LLMediaImplGStreamer::pause() -{ - LL_DEBUGS("MediaImpl") << "attempting to pause..." << LL_ENDL; - - if (!mPlaybin || mState == GST_STATE_NULL) - return true; - - GstStateChangeReturn state_change; - - state_change = gst_element_set_state(mPlaybin, GST_STATE_PAUSED); - - LL_DEBUGS("MediaImpl") << gst_element_state_change_return_get_name(state_change) << LL_ENDL; - - if (state_change == GST_STATE_CHANGE_FAILURE) - { - LL_WARNS("MediaImpl") << "could not pause stream!" << LL_ENDL; - return false; - } - else - { - mState = GST_STATE_PAUSED; - return true; - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -// virtual -unsigned char* LLMediaImplGStreamer::getMediaData() -{ - return mediaData; -} - - -/////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplGStreamer::seek(double time) -{ - bool success = false; - if (mPlaybin) - { - success = gst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME, - GstSeekFlags(GST_SEEK_FLAG_FLUSH | - GST_SEEK_FLAG_KEY_UNIT), - GST_SEEK_TYPE_SET, gint64(time*1000000000.0F), - GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); - } - LL_DEBUGS("MediaImpl") << "MEDIA SEEK REQUEST to " << float(time) - << "sec result was " << int(success) << LL_ENDL; - return success; -} - - -/////////////////////////////////////////////////////////////////////////////// -// virtual -bool LLMediaImplGStreamer::setVolume(float volume) -{ - // we try to only update volume as conservatively as - // possible, as many gst-plugins-base versions up to at least - // November 2008 have critical race-conditions in setting volume - sigh - if (mVolume == volume) - return true; // nothing to do, everything's fine - - mVolume = volume; - if (mPlaybin) - { - g_object_set(mPlaybin, "volume", mVolume, (void*)NULL); - return true; - } - - return false; -} - - - -///#endif // LL_GSTREAMER_ENABLED diff --git a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp~ b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp~ deleted file mode 100755 index 7d34a1e..0000000 --- a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp~ +++ /dev/null @@ -1,1219 +0,0 @@ -/** - * @file media_plugin_gstreamer010.cpp - * @brief GStreamer-0.10 plugin for LLMedia API plugin system - * - * @cond - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2010, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlife.com/developers/opensource/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - * - * @endcond - */ - -#include "linden_common.h" - -#include "llgl.h" - -#include "llplugininstance.h" -#include "llpluginmessage.h" -#include "llpluginmessageclasses.h" -#include "media_plugin_base.h" - -#if LL_GSTREAMER010_ENABLED - -extern "C" { -#include <gst/gst.h> -} - -#include "llmediaimplgstreamer.h" -#include "llmediaimplgstreamertriviallogging.h" - -#include "llmediaimplgstreamervidplug.h" - -#include "llmediaimplgstreamer_syms.h" - -////////////////////////////////////////////////////////////////////////////// -// -class MediaPluginGStreamer010 : public MediaPluginBase -{ -public: - MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - ~MediaPluginGStreamer010(); - - /* virtual */ void receiveMessage(const char *message_string); - - static bool startup(); - static bool closedown(); - - gboolean processGSTEvents(GstBus *bus, - GstMessage *message); - -private: - std::string getVersion(); - bool navigateTo( const std::string urlIn ); - bool seek( double time_sec ); - bool setVolume( float volume ); - - // misc - bool pause(); - bool stop(); - bool play(double rate); - bool getTimePos(double &sec_out); - - static const double MIN_LOOP_SEC = 1.0F; - - bool mIsLooping; - - enum ECommand { - COMMAND_NONE, - COMMAND_STOP, - COMMAND_PLAY, - COMMAND_FAST_FORWARD, - COMMAND_FAST_REWIND, - COMMAND_PAUSE, - COMMAND_SEEK, - }; - ECommand mCommand; - -private: - bool unload(); - bool load(); - - bool update(int milliseconds); - void mouseDown( int x, int y ); - void mouseUp( int x, int y ); - void mouseMove( int x, int y ); - - void sizeChanged(); - - static bool mDoneInit; - - guint mBusWatchID; - - float mVolume; - - int mDepth; - - // media NATURAL size - int mNaturalWidth; - int mNaturalHeight; - // media current size - int mCurrentWidth; - int mCurrentHeight; - int mCurrentRowbytes; - // previous media size so we can detect changes - int mPreviousWidth; - int mPreviousHeight; - // desired render size from host - int mWidth; - int mHeight; - // padded texture size we need to write into - int mTextureWidth; - int mTextureHeight; - - int mTextureFormatPrimary; - int mTextureFormatType; - - bool mSeekWanted; - double mSeekDestination; - - // Very GStreamer-specific - GMainLoop *mPump; // event pump for this media - GstElement *mPlaybin; - GstSLVideo *mVideoSink; -}; - -//static -bool MediaPluginGStreamer010::mDoneInit = false; - -MediaPluginGStreamer010::MediaPluginGStreamer010( - LLPluginInstance::sendMessageFunction host_send_func, - void *host_user_data ) : - MediaPluginBase(host_send_func, host_user_data), - mBusWatchID ( 0 ), - mCurrentRowbytes ( 4 ), - mTextureFormatPrimary ( GL_RGBA ), - mTextureFormatType ( GL_UNSIGNED_INT_8_8_8_8_REV ), - mSeekWanted(false), - mSeekDestination(0.0), - mPump ( NULL ), - mPlaybin ( NULL ), - mVideoSink ( NULL ), - mCommand ( COMMAND_NONE ) -{ - std::ostringstream str; - INFOMSG("MediaPluginGStreamer010 constructor - my PID=%u", U32(getpid())); -} - -/////////////////////////////////////////////////////////////////////////////// -// -//#define LL_GST_REPORT_STATE_CHANGES -#ifdef LL_GST_REPORT_STATE_CHANGES -static char* get_gst_state_name(GstState state) -{ - switch (state) { - case GST_STATE_VOID_PENDING: return "VOID_PENDING"; - case GST_STATE_NULL: return "NULL"; - case GST_STATE_READY: return "READY"; - case GST_STATE_PAUSED: return "PAUSED"; - case GST_STATE_PLAYING: return "PLAYING"; - } - return "(unknown)"; -} -#endif // LL_GST_REPORT_STATE_CHANGES - -gboolean -MediaPluginGStreamer010::processGSTEvents(GstBus *bus, - GstMessage *message) -{ - if (!message) - return TRUE; // shield against GStreamer bug - - if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED && - GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING) - { - DEBUGMSG("Got GST message type: %s", - LLGST_MESSAGE_TYPE_NAME (message)); - } - else - { - // TODO: grok 'duration' message type - DEBUGMSG("Got GST message type: %s", - LLGST_MESSAGE_TYPE_NAME (message)); - } - - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_BUFFERING: { - // NEEDS GST 0.10.11+ - if (llgst_message_parse_buffering) - { - gint percent = 0; - llgst_message_parse_buffering(message, &percent); - DEBUGMSG("GST buffering: %d%%", percent); - } - break; - } - case GST_MESSAGE_STATE_CHANGED: { - GstState old_state; - GstState new_state; - GstState pending_state; - llgst_message_parse_state_changed(message, - &old_state, - &new_state, - &pending_state); -#ifdef LL_GST_REPORT_STATE_CHANGES - // not generally very useful, and rather spammy. - DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s", - get_gst_state_name(old_state), - get_gst_state_name(new_state), - get_gst_state_name(pending_state)); -#endif // LL_GST_REPORT_STATE_CHANGES - - switch (new_state) { - case GST_STATE_VOID_PENDING: - break; - case GST_STATE_NULL: - break; - case GST_STATE_READY: - setStatus(STATUS_LOADED); - break; - case GST_STATE_PAUSED: - setStatus(STATUS_PAUSED); - break; - case GST_STATE_PLAYING: - setStatus(STATUS_PLAYING); - break; - } - break; - } - case GST_MESSAGE_ERROR: { - GError *err = NULL; - gchar *debug = NULL; - - llgst_message_parse_error (message, &err, &debug); - WARNMSG("GST error: %s", err?err->message:"(unknown)"); - if (err) - g_error_free (err); - g_free (debug); - - mCommand = COMMAND_STOP; - - setStatus(STATUS_ERROR); - - break; - } - case GST_MESSAGE_INFO: { - if (llgst_message_parse_info) - { - GError *err = NULL; - gchar *debug = NULL; - - llgst_message_parse_info (message, &err, &debug); - INFOMSG("GST info: %s", err?err->message:"(unknown)"); - if (err) - g_error_free (err); - g_free (debug); - } - break; - } - case GST_MESSAGE_WARNING: { - GError *err = NULL; - gchar *debug = NULL; - - llgst_message_parse_warning (message, &err, &debug); - WARNMSG("GST warning: %s", err?err->message:"(unknown)"); - if (err) - g_error_free (err); - g_free (debug); - - break; - } - case GST_MESSAGE_EOS: - /* end-of-stream */ - DEBUGMSG("GST end-of-stream."); - if (mIsLooping) - { - DEBUGMSG("looping media..."); - double eos_pos_sec = 0.0F; - bool got_eos_position = getTimePos(eos_pos_sec); - - if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC) - { - // if we know that the movie is really short, don't - // loop it else it can easily become a time-hog - // because of GStreamer spin-up overhead - DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec); - // inject a COMMAND_PAUSE - mCommand = COMMAND_PAUSE; - } - else - { -#undef LLGST_LOOP_BY_SEEKING -// loop with a stop-start instead of a seek, because it actually seems rather -// faster than seeking on remote streams. -#ifdef LLGST_LOOP_BY_SEEKING - // first, try looping by an explicit rewind - bool seeksuccess = seek(0.0); - if (seeksuccess) - { - play(1.0); - } - else -#endif // LLGST_LOOP_BY_SEEKING - { // use clumsy stop-start to loop - DEBUGMSG("didn't loop by rewinding - stopping and starting instead..."); - stop(); - play(1.0); - } - } - } - else // not a looping media - { - // inject a COMMAND_STOP - mCommand = COMMAND_STOP; - } - break; - default: - /* unhandled message */ - break; - } - - /* we want to be notified again the next time there is a message - * on the bus, so return true (false means we want to stop watching - * for messages on the bus and our callback should not be called again) - */ - return TRUE; -} - -extern "C" { -gboolean -llmediaimplgstreamer_bus_callback (GstBus *bus, - GstMessage *message, - gpointer data) -{ - MediaPluginGStreamer010 *impl = (MediaPluginGStreamer010*)data; - return impl->processGSTEvents(bus, message); -} -} // extern "C" - - - -bool -MediaPluginGStreamer010::navigateTo ( const std::string urlIn ) -{ - if (!mDoneInit) - return false; // error - - setStatus(STATUS_LOADING); - - DEBUGMSG("Setting media URI: %s", urlIn.c_str()); - - mSeekWanted = false; - - if (NULL == mPump || - NULL == mPlaybin) - { - setStatus(STATUS_ERROR); - return false; // error - } - - // set URI - g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL); - //g_object_set (G_OBJECT (mPlaybin), "uri", "file:///tmp/movie", NULL); - - // navigateTo implicitly plays, too. - play(1.0); - - return true; -} - - -bool -MediaPluginGStreamer010::update(int milliseconds) -{ - if (!mDoneInit) - return false; // error - - DEBUGMSG("updating media..."); - - // sanity check - if (NULL == mPump || - NULL == mPlaybin) - { - DEBUGMSG("dead media..."); - return false; - } - - // see if there's an outstanding seek wanted - if (mSeekWanted && - // bleh, GST has to be happy that the movie is really truly playing - // or it may quietly ignore the seek (with rtsp:// at least). - (GST_STATE(mPlaybin) == GST_STATE_PLAYING)) - { - seek(mSeekDestination); - mSeekWanted = false; - } - - // *TODO: time-limit - but there isn't a lot we can do here, most - // time is spent in gstreamer's own opaque worker-threads. maybe - // we can do something sneaky like only unlock the video object - // for 'milliseconds' and otherwise hold the lock. - while (g_main_context_pending(g_main_loop_get_context(mPump))) - { - g_main_context_iteration(g_main_loop_get_context(mPump), FALSE); - } - - // check for availability of a new frame - - if (mVideoSink) - { - GST_OBJECT_LOCK(mVideoSink); - if (mVideoSink->retained_frame_ready) - { - DEBUGMSG("NEW FRAME READY"); - - if (mVideoSink->retained_frame_width != mCurrentWidth || - mVideoSink->retained_frame_height != mCurrentHeight) - // *TODO: also check for change in format - { - // just resize container, don't consume frame - int neww = mVideoSink->retained_frame_width; - int newh = mVideoSink->retained_frame_height; - - int newd = 4; - mTextureFormatPrimary = GL_RGBA; - mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; - - /* - int newd = SLVPixelFormatBytes[mVideoSink->retained_frame_format]; - if (SLV_PF_BGRX == mVideoSink->retained_frame_format) - { - mTextureFormatPrimary = GL_BGRA; - mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; - } - else - { - mTextureFormatPrimary = GL_RGBA; - mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; - } - */ - - GST_OBJECT_UNLOCK(mVideoSink); - - mCurrentRowbytes = neww * newd; - DEBUGMSG("video container resized to %dx%d", - neww, newh); - - mDepth = newd; - mCurrentWidth = neww; - mCurrentHeight = newh; - sizeChanged(); - return true; - } - - if (mPixels && - mCurrentHeight <= mHeight && - mCurrentWidth <= mWidth && - !mTextureSegmentName.empty()) - { - // we're gonna totally consume this frame - reset 'ready' flag - mVideoSink->retained_frame_ready = FALSE; - int destination_rowbytes = mWidth * mDepth; - for (int row=0; row<mCurrentHeight; ++row) - { - memcpy(&mPixels - [destination_rowbytes * row], - &mVideoSink->retained_frame_data - [mCurrentRowbytes * row], - mCurrentRowbytes); - } - - GST_OBJECT_UNLOCK(mVideoSink); - DEBUGMSG("NEW FRAME REALLY TRULY CONSUMED, TELLING HOST"); - - setDirty(0,0,mCurrentWidth,mCurrentHeight); - } - else - { - // new frame ready, but we're not ready to - // consume it. - - GST_OBJECT_UNLOCK(mVideoSink); - - DEBUGMSG("NEW FRAME not consumed, still waiting for a shm segment and/or shm resize"); - } - - return true; - } - else - { - // nothing to do yet. - GST_OBJECT_UNLOCK(mVideoSink); - return true; - } - } - - return true; -} - - -void -MediaPluginGStreamer010::mouseDown( int x, int y ) -{ - // do nothing -} - -void -MediaPluginGStreamer010::mouseUp( int x, int y ) -{ - // do nothing -} - -void -MediaPluginGStreamer010::mouseMove( int x, int y ) -{ - // do nothing -} - - -bool -MediaPluginGStreamer010::pause() -{ - DEBUGMSG("pausing media..."); - // todo: error-check this? - llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); - return true; -} - -bool -MediaPluginGStreamer010::stop() -{ - DEBUGMSG("stopping media..."); - // todo: error-check this? - llgst_element_set_state(mPlaybin, GST_STATE_READY); - return true; -} - -bool -MediaPluginGStreamer010::play(double rate) -{ - // NOTE: we don't actually support non-natural rate. - - DEBUGMSG("playing media... rate=%f", rate); - // todo: error-check this? - llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); - return true; -} - -bool -MediaPluginGStreamer010::setVolume( float volume ) -{ - // we try to only update volume as conservatively as - // possible, as many gst-plugins-base versions up to at least - // November 2008 have critical race-conditions in setting volume - sigh - if (mVolume == volume) - return true; // nothing to do, everything's fine - - mVolume = volume; - if (mDoneInit && mPlaybin) - { - g_object_set(mPlaybin, "volume", mVolume, NULL); - return true; - } - - return false; -} - -bool -MediaPluginGStreamer010::seek(double time_sec) -{ - bool success = false; - if (mDoneInit && mPlaybin) - { - success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME, - GstSeekFlags(GST_SEEK_FLAG_FLUSH | - GST_SEEK_FLAG_KEY_UNIT), - GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND), - GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); - } - DEBUGMSG("MEDIA SEEK REQUEST to %fsec result was %d", - float(time_sec), int(success)); - return success; -} - -bool -MediaPluginGStreamer010::getTimePos(double &sec_out) -{ - bool got_position = false; - if (mPlaybin) - { - gint64 pos; - GstFormat timefmt = GST_FORMAT_TIME; - got_position = - llgst_element_query_position && - llgst_element_query_position(mPlaybin, - &timefmt, - &pos); - got_position = got_position - && (timefmt == GST_FORMAT_TIME); - // GStreamer may have other ideas, but we consider the current position - // undefined if not PLAYING or PAUSED - got_position = got_position && - (GST_STATE(mPlaybin) == GST_STATE_PLAYING || - GST_STATE(mPlaybin) == GST_STATE_PAUSED); - if (got_position && !GST_CLOCK_TIME_IS_VALID(pos)) - { - if (GST_STATE(mPlaybin) == GST_STATE_PLAYING) - { - // if we're playing then we treat an invalid clock time - // as 0, for complicated reasons (insert reason here) - pos = 0; - } - else - { - got_position = false; - } - - } - // If all the preconditions succeeded... we can trust the result. - if (got_position) - { - sec_out = double(pos) / double(GST_SECOND); // gst to sec - } - } - return got_position; -} - -bool -MediaPluginGStreamer010::load() -{ - if (!mDoneInit) - return false; // error - - setStatus(STATUS_LOADING); - - DEBUGMSG("setting up media..."); - - mIsLooping = false; - mVolume = 0.1234567; // minor hack to force an initial volume update - - // Create a pumpable main-loop for this media - mPump = g_main_loop_new (NULL, FALSE); - if (!mPump) - { - setStatus(STATUS_ERROR); - return false; // error - } - - // instantiate a playbin element to do the hard work - mPlaybin = llgst_element_factory_make ("playbin", "play"); - if (!mPlaybin) - { - setStatus(STATUS_ERROR); - return false; // error - } - - // get playbin's bus - GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin)); - if (!bus) - { - setStatus(STATUS_ERROR); - return false; // error - } - mBusWatchID = llgst_bus_add_watch (bus, - llmediaimplgstreamer_bus_callback, - this); - llgst_object_unref (bus); - - if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) { - // instantiate a custom video sink - mVideoSink = - GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo")); - if (!mVideoSink) - { - WARNMSG("Could not instantiate private-slvideo element."); - // todo: cleanup. - setStatus(STATUS_ERROR); - return false; // error - } - - // connect the pieces - g_object_set(mPlaybin, "video-sink", mVideoSink, NULL); - } - - return true; -} - -bool -MediaPluginGStreamer010::unload () -{ - if (!mDoneInit) - return false; // error - - DEBUGMSG("unloading media..."); - - // stop getting callbacks for this bus - g_source_remove(mBusWatchID); - mBusWatchID = 0; - - if (mPlaybin) - { - llgst_element_set_state (mPlaybin, GST_STATE_NULL); - llgst_object_unref (GST_OBJECT (mPlaybin)); - mPlaybin = NULL; - } - - if (mPump) - { - g_main_loop_quit(mPump); - mPump = NULL; - } - - mVideoSink = NULL; - - setStatus(STATUS_NONE); - - return true; -} - - -//static -bool -MediaPluginGStreamer010::startup() -{ - // first - check if GStreamer is explicitly disabled - if (NULL != getenv("LL_DISABLE_GSTREAMER")) - return false; - - // only do global GStreamer initialization once. - if (!mDoneInit) - { - g_thread_init(NULL); - - // Init the glib type system - we need it. - g_type_init(); - - // Get symbols! -#if LL_DARWIN - if (! grab_gst_syms("libgstreamer-0.10.dylib", - "libgstvideo-0.10.dylib") ) -#elseif LL_WINDOWS - if (! grab_gst_syms("libgstreamer-0.10.dll", - "libgstvideo-0.10.dll") ) -#else // linux or other ELFy unixoid - if (! grab_gst_syms("libgstreamer-0.10.so.0", - "libgstvideo-0.10.so.0") ) -#endif - { - WARNMSG("Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled."); - return false; - } - - if (llgst_segtrap_set_enabled) - { - llgst_segtrap_set_enabled(FALSE); - } - else - { - WARNMSG("gst_segtrap_set_enabled() is not available; plugin crashes won't be caught."); - } - -#if LL_LINUX - // Gstreamer tries a fork during init, waitpid-ing on it, - // which conflicts with any installed SIGCHLD handler... - struct sigaction tmpact, oldact; - if (llgst_registry_fork_set_enabled) { - // if we can disable SIGCHLD-using forking behaviour, - // do it. - llgst_registry_fork_set_enabled(false); - } - else { - // else temporarily install default SIGCHLD handler - // while GStreamer initialises - tmpact.sa_handler = SIG_DFL; - sigemptyset( &tmpact.sa_mask ); - tmpact.sa_flags = SA_SIGINFO; - sigaction(SIGCHLD, &tmpact, &oldact); - } -#endif // LL_LINUX - - // Protect against GStreamer resetting the locale, yuck. - static std::string saved_locale; - saved_locale = setlocale(LC_ALL, NULL); - - // finally, try to initialize GStreamer! - GError *err = NULL; - gboolean init_gst_success = llgst_init_check(NULL, NULL, &err); - - // restore old locale - setlocale(LC_ALL, saved_locale.c_str() ); - -#if LL_LINUX - // restore old SIGCHLD handler - if (!llgst_registry_fork_set_enabled) - sigaction(SIGCHLD, &oldact, NULL); -#endif // LL_LINUX - - if (!init_gst_success) // fail - { - if (err) - { - WARNMSG("GST init failed: %s", err->message); - g_error_free(err); - } - else - { - WARNMSG("GST init failed for unspecified reason."); - } - return false; - } - - // Init our custom plugins - only really need do this once. - gst_slvideo_init_class(); - - mDoneInit = true; - } - - return true; -} - - -void -MediaPluginGStreamer010::sizeChanged() -{ - // the shared writing space has possibly changed size/location/whatever - - // Check to see whether the movie's NATURAL size has been set yet - if (1 == mNaturalWidth && - 1 == mNaturalHeight) - { - mNaturalWidth = mCurrentWidth; - mNaturalHeight = mCurrentHeight; - DEBUGMSG("Media NATURAL size better detected as %dx%d", - mNaturalWidth, mNaturalHeight); - } - - // if the size has changed then the shm has changed and the app needs telling - if (mCurrentWidth != mPreviousWidth || - mCurrentHeight != mPreviousHeight) - { - mPreviousWidth = mCurrentWidth; - mPreviousHeight = mCurrentHeight; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); - message.setValue("name", mTextureSegmentName); - message.setValueS32("width", mNaturalWidth); - message.setValueS32("height", mNaturalHeight); - DEBUGMSG("<--- Sending size change request to application with name: '%s' - natural size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight); - sendMessage(message); - } -} - - - -//static -bool -MediaPluginGStreamer010::closedown() -{ - if (!mDoneInit) - return false; // error - - ungrab_gst_syms(); - - mDoneInit = false; - - return true; -} - -MediaPluginGStreamer010::~MediaPluginGStreamer010() -{ - DEBUGMSG("MediaPluginGStreamer010 destructor"); - - closedown(); - - DEBUGMSG("GStreamer010 closing down"); -} - - -std::string -MediaPluginGStreamer010::getVersion() -{ - std::string plugin_version = "GStreamer010 media plugin, GStreamer version "; - if (mDoneInit && - llgst_version) - { - guint major, minor, micro, nano; - llgst_version(&major, &minor, µ, &nano); - plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor, (unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR, (unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO); - } - else - { - plugin_version += "(unknown)"; - } - return plugin_version; -} - -void MediaPluginGStreamer010::receiveMessage(const char *message_string) -{ - //std::cerr << "MediaPluginGStreamer010::receiveMessage: received message: \"" << message_string << "\"" << std::endl; - - LLPluginMessage message_in; - - if(message_in.parse(message_string) >= 0) - { - std::string message_class = message_in.getClass(); - std::string message_name = message_in.getName(); - if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) - { - if(message_name == "init") - { - LLPluginMessage message("base", "init_response"); - LLSD versions = LLSD::emptyMap(); - versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; - message.setValueLLSD("versions", versions); - - if ( load() ) - { - DEBUGMSG("GStreamer010 media instance set up"); - } - else - { - WARNMSG("GStreamer010 media instance failed to set up"); - } - - message.setValue("plugin_version", getVersion()); - sendMessage(message); - } - else if(message_name == "idle") - { - // no response is necessary here. - double time = message_in.getValueReal("time"); - - // Convert time to milliseconds for update() - update((int)(time * 1000.0f)); - } - else if(message_name == "cleanup") - { - unload(); - closedown(); - } - else if(message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); - - std::ostringstream str; - INFOMSG("MediaPluginGStreamer010::receiveMessage: shared memory added, name: %s, size: %d, address: %p", name.c_str(), int(info.mSize), info.mAddress); - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - } - else if(message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - - DEBUGMSG("MediaPluginGStreamer010::receiveMessage: shared memory remove, name = %s", name.c_str()); - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - if(mPixels == iter->second.mAddress) - { - // This is the currently active pixel buffer. Make sure we stop drawing to it. - mPixels = NULL; - mTextureSegmentName.clear(); - - // Make sure the movie decoder is no longer pointed at the shared segment. - sizeChanged(); - } - mSharedSegments.erase(iter); - } - else - { - WARNMSG("MediaPluginGStreamer010::receiveMessage: unknown shared memory region!"); - } - - // Send the response so it can be cleaned up. - LLPluginMessage message("base", "shm_remove_response"); - message.setValue("name", name); - sendMessage(message); - } - else - { - std::ostringstream str; - INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown base message: %s", message_name.c_str()); - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) - { - if(message_name == "init") - { - // Plugin gets to decide the texture parameters to use. - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - // lame to have to decide this now, it depends on the movie. Oh well. - mDepth = 4; - - mCurrentWidth = 1; - mCurrentHeight = 1; - mPreviousWidth = 1; - mPreviousHeight = 1; - mNaturalWidth = 1; - mNaturalHeight = 1; - mWidth = 1; - mHeight = 1; - mTextureWidth = 1; - mTextureHeight = 1; - - message.setValueU32("format", GL_RGBA); - message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV); - - message.setValueS32("depth", mDepth); - message.setValueS32("default_width", mWidth); - message.setValueS32("default_height", mHeight); - message.setValueU32("internalformat", GL_RGBA8); - message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. - message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale - sendMessage(message); - } - else if(message_name == "size_change") - { - std::string name = message_in.getValue("name"); - S32 width = message_in.getValueS32("width"); - S32 height = message_in.getValueS32("height"); - S32 texture_width = message_in.getValueS32("texture_width"); - S32 texture_height = message_in.getValueS32("texture_height"); - - std::ostringstream str; - INFOMSG("---->Got size change instruction from application with shm name: %s - size is %d x %d", name.c_str(), width, height); - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); - message.setValue("name", name); - message.setValueS32("width", width); - message.setValueS32("height", height); - message.setValueS32("texture_width", texture_width); - message.setValueS32("texture_height", texture_height); - sendMessage(message); - - if(!name.empty()) - { - // Find the shared memory region with this name - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - INFOMSG("*** Got size change with matching shm, new size is %d x %d", width, height); - INFOMSG("*** Got size change with matching shm, texture size size is %d x %d", texture_width, texture_height); - - mPixels = (unsigned char*)iter->second.mAddress; - mTextureSegmentName = name; - mWidth = width; - mHeight = height; - - if (texture_width > 1 || - texture_height > 1) // not a dummy size from the app, a real explicit forced size - { - INFOMSG("**** = REAL RESIZE REQUEST FROM APP"); - - GST_OBJECT_LOCK(mVideoSink); - mVideoSink->resize_forced_always = true; - mVideoSink->resize_try_width = texture_width; - mVideoSink->resize_try_height = texture_height; - GST_OBJECT_UNLOCK(mVideoSink); - } - - mTextureWidth = texture_width; - mTextureHeight = texture_height; - } - } - } - else if(message_name == "load_uri") - { - std::string uri = message_in.getValue("uri"); - navigateTo( uri ); - sendStatus(); - } - else if(message_name == "mouse_event") - { - std::string event = message_in.getValue("event"); - S32 x = message_in.getValueS32("x"); - S32 y = message_in.getValueS32("y"); - - if(event == "down") - { - mouseDown(x, y); - } - else if(event == "up") - { - mouseUp(x, y); - } - else if(event == "move") - { - mouseMove(x, y); - }; - }; - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) - { - if(message_name == "stop") - { - stop(); - } - else if(message_name == "start") - { - double rate = 0.0; - if(message_in.hasValue("rate")) - { - rate = message_in.getValueReal("rate"); - } - // NOTE: we don't actually support rate. - play(rate); - } - else if(message_name == "pause") - { - pause(); - } - else if(message_name == "seek") - { - double time = message_in.getValueReal("time"); - // defer the actual seek in case we haven't - // really truly started yet in which case there - // is nothing to seek upon - mSeekWanted = true; - mSeekDestination = time; - } - else if(message_name == "set_loop") - { - bool loop = message_in.getValueBoolean("loop"); - mIsLooping = loop; - } - else if(message_name == "set_volume") - { - double volume = message_in.getValueReal("volume"); - setVolume(volume); - } - } - else - { - INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown message class: %s", message_class.c_str()); - } - } -} - -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) -{ - if (MediaPluginGStreamer010::startup()) - { - MediaPluginGStreamer010 *self = new MediaPluginGStreamer010(host_send_func, host_user_data); - *plugin_send_func = MediaPluginGStreamer010::staticReceiveMessage; - *plugin_user_data = (void*)self; - - return 0; // okay - } - else - { - return -1; // failed to init - } -} - -#else // LL_GSTREAMER010_ENABLED - -// Stubbed-out class with constructor/destructor (necessary or windows linker -// will just think its dead code and optimize it all out) -class MediaPluginGStreamer010 : public MediaPluginBase -{ -public: - MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - ~MediaPluginGStreamer010(); - /* virtual */ void receiveMessage(const char *message_string); -}; - -MediaPluginGStreamer010::MediaPluginGStreamer010( - LLPluginInstance::sendMessageFunction host_send_func, - void *host_user_data ) : - MediaPluginBase(host_send_func, host_user_data) -{ - // no-op -} - -MediaPluginGStreamer010::~MediaPluginGStreamer010() -{ - // no-op -} - -void MediaPluginGStreamer010::receiveMessage(const char *message_string) -{ - // no-op -} - -// We're building without GStreamer enabled. Just refuse to initialize. -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) -{ - return -1; -} - -#endif // LL_GSTREAMER010_ENABLED diff --git a/linden/indra/newview/linux_tools/getvoice.sh b/linden/indra/newview/linux_tools/getvoice.sh index 13b632f..afebda9 100755 --- a/linden/indra/newview/linux_tools/getvoice.sh +++ b/linden/indra/newview/linux_tools/getvoice.sh @@ -3,8 +3,9 @@ SCRIPTSRC=`readlink -f "$0" || echo "$0"` RUN_PATH=`dirname "${SCRIPTSRC}" || echo .` -#if mozilla-runtime-linux-x86_64 is present we are using 64bit Imprudence on 64bit Linux -if [ -d "${RUN_PATH}/app_settings/mozilla-runtime-linux-x86_64/" ]; then +BINARY_SYSTEM=$(expr match "$(file -b /bin/uname)" '\(.*executable\)') +BINARY_VIEWER=$(expr match "$(file -b ${RUN_PATH}/bin/do-not-directly-run-imprudence-bin)" '\(.*executable\)') +if ( [ "$BINARY_SYSTEM" == "ELF 64-bit LSB executable" ] && [ "$BINARY_VIEWER" == "ELF 64-bit LSB executable" ] ); then LIB_INSTALLDIR="lib32/" # It's 32bit voice on 64bit Linux and 64bit viewer. Not using lib/ for avoiding ambiguity. else LIB_INSTALLDIR="lib/" # It's 32bit voice on 32 or 64bit Linux and 32bit viewer. diff --git a/linden/indra/newview/linux_tools/wrapper.sh b/linden/indra/newview/linux_tools/wrapper.sh index bc2c127..8c47434 100755 --- a/linden/indra/newview/linux_tools/wrapper.sh +++ b/linden/indra/newview/linux_tools/wrapper.sh @@ -106,13 +106,13 @@ if [ -n "$LL_TCMALLOC" ]; then fi fi fi - -if([ "`uname -m`" = "x86_64" ] && [ -d "${RUN_PATH}/app_settings/mozilla-runtime-linux-x86_64/" ]); then - export GST_PLUGIN_PATH="${GST_PLUGIN_PATH}:${RUN_PATH}/lib64/gstreamer-plugins/" +BINARY_SYSTEM=$(expr match "$(file -b /bin/uname)" '\(.*executable\)') +BINARY_VIEWER=$(expr match "$(file -b ${RUN_PATH}/bin/do-not-directly-run-imprudence-bin)" '\(.*executable\)') +echo "viewer: $BINARY_VIEWER system: $BINARY_SYSTEM" +if ( [ "$BINARY_SYSTEM" == "ELF 64-bit LSB executable" ] && [ "$BINARY_VIEWER" == "ELF 64-bit LSB executable" ] ); then export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib64:"`pwd`"/lib32:"`pwd`"/app_settings/mozilla-runtime-linux-x86_64:"${LD_LIBRARY_PATH}"' else - export GST_PLUGIN_PATH="${GST_PLUGIN_PATH}:${RUN_PATH}/lib/gstreamer-plugins/" export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"`pwd`"/app_settings/mozilla-runtime-linux-i686:"${LD_LIBRARY_PATH}"' fi diff --git a/linden/indra/newview/viewer_manifest.py b/linden/indra/newview/viewer_manifest.py index 0c00995..4c95f00 100755 --- a/linden/indra/newview/viewer_manifest.py +++ b/linden/indra/newview/viewer_manifest.py @@ -973,68 +973,69 @@ class Linux_i686Manifest(LinuxManifest): # self.path("libpangoxft-1.0.so.0") self.path("libpixman-1.so.0") +#KILL IT WITH FIRE # Gstreamer libs - self.path("libgstbase-0.10.so.0") - self.path("libgstreamer-0.10.so.0") - self.path("libgstaudio-0.10.so.0") - self.path("libgstbase-0.10.so.0") - self.path("libgstcontroller-0.10.so.0") - self.path("libgstdataprotocol-0.10.so.0") - self.path("libgstinterfaces-0.10.so.0") - self.path("libgstnetbuffer-0.10.so.0") - self.path("libgstpbutils-0.10.so.0") - self.path("libgstriff-0.10.so.0") - self.path("libgstrtp-0.10.so.0") - self.path("libgstrtsp-0.10.so.0") - self.path("libgstsdp-0.10.so.0") - self.path("libgsttag-0.10.so.0") - self.path("libgstvideo-0.10.so.0") - - # Gstreamer plugin dependencies - self.path("libfaad.so.0") - self.path("libogg.so.0") - self.path("libtheora.so.0") - self.path("libvorbis.so.0") - self.path("libvorbisenc.so.2") - self.path("liboil-0.3.so.0") - - # Gstreamer plugins - if self.prefix("gstreamer-plugins"): - self.path("libgstalsa.so") - self.path("libgstasf.so") - self.path("libgstaudioconvert.so") - self.path("libgstaudioresample.so") - self.path("libgstautodetect.so") - self.path("libgstavi.so") - self.path("libgstcoreelements.so") - self.path("libgstcoreindexers.so") - self.path("libgstdecodebin2.so") - self.path("libgstdecodebin.so") - self.path("libgstesd.so") - self.path("libgstfaad.so") - self.path("libgstffmpeg.so") - self.path("libgstgnomevfs.so") - self.path("libgsticydemux.so") - self.path("libgstid3demux.so") - self.path("libgstmpegdemux.so") - self.path("libgstmultifile.so") - self.path("libgstmultipart.so") - self.path("libgstogg.so") - self.path("libgstossaudio.so") - self.path("libgstplaybin.so") - self.path("libgstpulse.so") - self.path("libgstqtdemux.so") - self.path("libgstqueue2.so") - self.path("libgsttcp.so") - self.path("libgsttheora.so") - self.path("libgsttypefindfunctions.so") - self.path("libgstudp.so") - self.path("libgstvideoscale.so") - self.path("libgstvolume.so") - self.path("libgstvorbis.so") - self.path("libgstwavparse.so") + #self.path("libgstbase-0.10.so.0") + #self.path("libgstreamer-0.10.so.0") + #self.path("libgstaudio-0.10.so.0") + #self.path("libgstbase-0.10.so.0") + #self.path("libgstcontroller-0.10.so.0") + #self.path("libgstdataprotocol-0.10.so.0") + #self.path("libgstinterfaces-0.10.so.0") + #self.path("libgstnetbuffer-0.10.so.0") + #self.path("libgstpbutils-0.10.so.0") + #self.path("libgstriff-0.10.so.0") + #self.path("libgstrtp-0.10.so.0") + #self.path("libgstrtsp-0.10.so.0") + #self.path("libgstsdp-0.10.so.0") + #self.path("libgsttag-0.10.so.0") + #self.path("libgstvideo-0.10.so.0") + + ## Gstreamer plugin dependencies + #self.path("libfaad.so.0") + #self.path("libogg.so.0") + #self.path("libtheora.so.0") + #self.path("libvorbis.so.0") + #self.path("libvorbisenc.so.2") + #self.path("liboil-0.3.so.0") + + ## Gstreamer plugins + #if self.prefix("gstreamer-plugins"): + #self.path("libgstalsa.so") + #self.path("libgstasf.so") + #self.path("libgstaudioconvert.so") + #self.path("libgstaudioresample.so") + #self.path("libgstautodetect.so") + #self.path("libgstavi.so") + #self.path("libgstcoreelements.so") + #self.path("libgstcoreindexers.so") + #self.path("libgstdecodebin2.so") + #self.path("libgstdecodebin.so") + #self.path("libgstesd.so") + #self.path("libgstfaad.so") + #self.path("libgstffmpeg.so") + #self.path("libgstgnomevfs.so") + #self.path("libgsticydemux.so") + #self.path("libgstid3demux.so") + #self.path("libgstmpegdemux.so") + #self.path("libgstmultifile.so") + #self.path("libgstmultipart.so") + #self.path("libgstogg.so") + #self.path("libgstossaudio.so") + #self.path("libgstplaybin.so") + #self.path("libgstpulse.so") + #self.path("libgstqtdemux.so") + #self.path("libgstqueue2.so") + #self.path("libgsttcp.so") + #self.path("libgsttheora.so") + #self.path("libgsttypefindfunctions.so") + #self.path("libgstudp.so") + #self.path("libgstvideoscale.so") + #self.path("libgstvolume.so") + #self.path("libgstvorbis.so") + #self.path("libgstwavparse.so") - self.end_prefix("gstreamer-plugins") + #self.end_prefix("gstreamer-plugins") self.end_prefix("lib") @@ -1064,8 +1065,6 @@ class Linux_x86_64Manifest(LinuxManifest): self.path("featuretable_linux.txt") #self.path("secondlife-x86_64.supp") - self.path("app_settings/mozilla-runtime-linux-x86_64") - if self.prefix("../../libraries/x86_64-linux/lib_release_client", dst="lib64"): self.path("libapr-1.so.0") self.path("libaprutil-1.so.0") @@ -1102,69 +1101,70 @@ class Linux_x86_64Manifest(LinuxManifest): # self.path("libpangoxft-1.0.so.0") # So we depend system gdk pixbufs and pango anyway. self.path("libpixman-1.so.0") - # Gstreamer libs - self.path("libgstbase-0.10.so.0") - self.path("libgstreamer-0.10.so.0") - self.path("libgstaudio-0.10.so.0") - self.path("libgstbase-0.10.so.0") - self.path("libgstcontroller-0.10.so.0") - self.path("libgstdataprotocol-0.10.so.0") - self.path("libgstinterfaces-0.10.so.0") - self.path("libgstnetbuffer-0.10.so.0") - self.path("libgstpbutils-0.10.so.0") - self.path("libgstriff-0.10.so.0") - self.path("libgstrtp-0.10.so.0") - self.path("libgstrtsp-0.10.so.0") - self.path("libgstsdp-0.10.so.0") - self.path("libgsttag-0.10.so.0") - self.path("libgstvideo-0.10.so.0") - - # Gstreamer plugin dependencies - self.path("libfaad.so.0") - self.path("libogg.so.0") - self.path("libtheora.so.0") - self.path("libvorbis.so.0") - self.path("libvorbisenc.so.2") - self.path("liboil-0.3.so.0") - - # Gstreamer plugins - if self.prefix("gstreamer-plugins"): - self.path("libgstalsa.so") - self.path("libgstasf.so") - self.path("libgstaudioconvert.so") - self.path("libgstaudioresample.so") - self.path("libgstautodetect.so") - self.path("libgstavi.so") - self.path("libgstcoreelements.so") - self.path("libgstcoreindexers.so") - self.path("libgstdecodebin2.so") - self.path("libgstdecodebin.so") - self.path("libgstesd.so") - self.path("libgstfaad.so") - self.path("libgstffmpeg.so") - self.path("libgstffmpegcolorspace.so") - self.path("libgstgnomevfs.so") - self.path("libgsticydemux.so") - self.path("libgstid3demux.so") - self.path("libgstmpegdemux.so") - self.path("libgstmultifile.so") - self.path("libgstmultipart.so") - self.path("libgstogg.so") - self.path("libgstossaudio.so") - self.path("libgstplaybin.so") - self.path("libgstpulse.so") - self.path("libgstqtdemux.so") - self.path("libgstqueue2.so") - self.path("libgsttcp.so") - self.path("libgsttheora.so") - self.path("libgsttypefindfunctions.so") - self.path("libgstudp.so") - self.path("libgstvideoscale.so") - self.path("libgstvolume.so") - self.path("libgstvorbis.so") - self.path("libgstwavparse.so") +#KILL IT WITH FIRE + ## Gstreamer libs + #self.path("libgstbase-0.10.so.0") + #self.path("libgstreamer-0.10.so.0") + #self.path("libgstaudio-0.10.so.0") + #self.path("libgstbase-0.10.so.0") + #self.path("libgstcontroller-0.10.so.0") + #self.path("libgstdataprotocol-0.10.so.0") + #self.path("libgstinterfaces-0.10.so.0") + #self.path("libgstnetbuffer-0.10.so.0") + #self.path("libgstpbutils-0.10.so.0") + #self.path("libgstriff-0.10.so.0") + #self.path("libgstrtp-0.10.so.0") + #self.path("libgstrtsp-0.10.so.0") + #self.path("libgstsdp-0.10.so.0") + #self.path("libgsttag-0.10.so.0") + #self.path("libgstvideo-0.10.so.0") + + ## Gstreamer plugin dependencies + #self.path("libfaad.so.0") + #self.path("libogg.so.0") + #self.path("libtheora.so.0") + #self.path("libvorbis.so.0") + #self.path("libvorbisenc.so.2") + #self.path("liboil-0.3.so.0") + + ## Gstreamer plugins + #if self.prefix("gstreamer-plugins"): + #self.path("libgstalsa.so") + #self.path("libgstasf.so") + #self.path("libgstaudioconvert.so") + #self.path("libgstaudioresample.so") + #self.path("libgstautodetect.so") + #self.path("libgstavi.so") + #self.path("libgstcoreelements.so") + #self.path("libgstcoreindexers.so") + #self.path("libgstdecodebin2.so") + #self.path("libgstdecodebin.so") + #self.path("libgstesd.so") + #self.path("libgstfaad.so") + #self.path("libgstffmpeg.so") + #self.path("libgstffmpegcolorspace.so") + #self.path("libgstgnomevfs.so") + #self.path("libgsticydemux.so") + #self.path("libgstid3demux.so") + #self.path("libgstmpegdemux.so") + #self.path("libgstmultifile.so") + #self.path("libgstmultipart.so") + #self.path("libgstogg.so") + #self.path("libgstossaudio.so") + #self.path("libgstplaybin.so") + #self.path("libgstpulse.so") + #self.path("libgstqtdemux.so") + #self.path("libgstqueue2.so") + #self.path("libgsttcp.so") + #self.path("libgsttheora.so") + #self.path("libgsttypefindfunctions.so") + #self.path("libgstudp.so") + #self.path("libgstvideoscale.so") + #self.path("libgstvolume.so") + #self.path("libgstvorbis.so") + #self.path("libgstwavparse.so") - self.end_prefix("gstreamer-plugins") + #self.end_prefix("gstreamer-plugins") self.end_prefix("lib64") diff --git a/linden/indra/newview/viewer_manifest.py~ b/linden/indra/newview/viewer_manifest.py~ deleted file mode 100755 index 452b165..0000000 --- a/linden/indra/newview/viewer_manifest.py~ +++ /dev/null @@ -1,1176 +0,0 @@ -#!/usr/bin/python -# @file viewer_manifest.py -# @author Ryan Williams -# @brief Description of all installer viewer files, and methods for packaging -# them into installers for all supported platforms. -# -# $LicenseInfo:firstyear=2006&license=viewergpl$ -# -# Copyright (c) 2006-2009, Linden Research, Inc. -# -# Second Life Viewer Source Code -# The source code in this file ("Source Code") is provided by Linden Lab -# to you under the terms of the GNU General Public License, version 2.0 -# ("GPL"), unless you have obtained a separate licensing agreement -# ("Other License"), formally executed by you and Linden Lab. Terms of -# the GPL can be found in doc/GPL-license.txt in this distribution, or -# online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 -# -# There are special exceptions to the terms and conditions of the GPL as -# it is applied to this Source Code. View the full text of the exception -# in the file doc/FLOSS-exception.txt in this software distribution, or -# online at -# http://secondlifegrid.net/programs/open_source/licensing/flossexception -# -# By copying, modifying or distributing this software, you acknowledge -# that you have read and understood your obligations described above, -# and agree to abide by those obligations. -# -# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO -# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, -# COMPLETENESS OR PERFORMANCE. -# $/LicenseInfo$ - -# DO NOT RUN THIS FILE DIRECTLY -# Instead, run develop.py with "configure -DPACKAGE:BOOL=ON" e.g.: -# develop.py -G vc80 configure -DPACKAGE:BOOL=ON -# to generate the "package" project in Visual Studio 2005 -# Note: as of Imprudence 1.3, this defaults to on for Windows - -import sys -import os.path -import re -import tarfile -viewer_dir = os.path.dirname(__file__) -# add llmanifest library to our path so we don't have to muck with PYTHONPATH -sys.path.append(os.path.join(viewer_dir, '../lib/python/indra/util')) -from llmanifest import LLManifest, main, proper_windows_path, path_ancestors - -class ViewerManifest(LLManifest): - def construct(self): - super(ViewerManifest, self).construct() - self.exclude("*.svn*") - self.path(src="../../scripts/messages/message_template.msg", dst="app_settings/message_template.msg") - self.path(src="../../etc/message.xml", dst="app_settings/message.xml") - - if self.prefix(src="app_settings"): - self.exclude("logcontrol.xml") - self.exclude("logcontrol-dev.xml") - self.path("*.pem") - self.path("*.ini") - self.path("*.xml") - self.path("*.db2") - - # include the entire shaders directory recursively - self.path("shaders") - # ... and the entire windlight directory - self.path("windlight") - self.end_prefix("app_settings") - - if self.prefix(src="character"): - self.path("*.llm") - self.path("*.xml") - self.path("*.tga") - self.end_prefix("character") - - # Include our fonts - if self.prefix(src="fonts"): - self.path("LiberationSans-Bold.ttf") - self.path("LiberationSans-Regular.ttf") - self.path("VeraMono.ttf") - self.path("DejaVuSansCondensed-BoldOblique.ttf") - self.path("DejaVuSansCondensed-Bold.ttf") - self.path("DejaVuSansCondensed-Oblique.ttf") - self.path("DejaVuSansCondensed.ttf") - self.path("GPL.txt") - self.path("Liberation-License.txt") - self.path("Vera-License.txt") - self.end_prefix("fonts") - - # skins - if self.prefix(src="skins"): - self.path("paths.xml") - # include the entire textures directory recursively - if self.prefix(src="*/textures"): - self.path("*.tga") - self.path("*.j2c") - self.path("*.jpg") - self.path("*.png") - self.path("textures.xml") - self.end_prefix("*/textures") - self.path("*/xui/*/*.xml") - self.path("*/*.xml") - - # Local HTML files (e.g. loading screen) - if self.prefix(src="*/html"): - self.path("*.png") - self.path("*/*/*.html") - self.path("*/*/*.gif") - self.path("*/*/*.png") - self.end_prefix("*/html") - self.end_prefix("skins") - - # Files in the newview/ directory - self.path("gpu_table.txt") - - - # Gather up the README file, etc. - def gather_documents(self): - # From the top level directory (imprudence) - if self.prefix("../../..", dst=""): - self.path("README.txt") - self.path("MANIFESTO.txt") - self.path("CONTRIBUTE.txt") - self.path("RELEASE_NOTES.txt") - self.path("ChangeLog.txt", required=False) - self.end_prefix("../../..") - - # From the linden directory - if self.prefix("../..", dst="doc"): - self.path("LICENSE-source.txt") - self.path("LICENSE-logos.txt", "LICENSE-artwork.txt") - self.end_prefix("../..") - - # From the linden/doc directory - if self.prefix("../../doc", dst="doc"): - self.path("contributions.txt") - self.path("GPL-license.txt", "GPL.txt") - self.path("FLOSS-exception.txt") - self.end_prefix("../../doc") - - - def login_channel(self): - """Channel reported for login and upgrade purposes ONLY; - used for A/B testing""" - # NOTE: Do not return the normal channel if login_channel - # is not specified, as some code may branch depending on - # whether or not this is present - return self.args.get('login_channel') - - def grid(self): - return self.args['grid'] - def channel(self): - return self.args['channel'] - def channel_unique(self): - return self.channel().replace("Imprudence", "").strip() - def channel_oneword(self): - return "".join(self.channel_unique().split()) - def channel_lowerword(self): - return self.channel_oneword().lower() - - def flags_list(self): - """ Convenience function that returns the command-line flags - for the grid""" - - # Set command line flags relating to the target grid - grid_flags = '' - if not self.default_grid(): - grid_flags = "--grid %(grid)s "\ - "--helperuri http://preview-%(grid)s.secondlife.com/helpers/" %\ - {'grid':self.grid()} - - # set command line flags for channel - channel_flags = '' - if self.login_channel() and self.login_channel() != self.channel(): - # Report a special channel during login, but use default - channel_flags = '--channel "%s"' % (self.login_channel()) - elif not self.default_channel(): - channel_flags = '--channel "%s"' % self.channel() - - # Deal with settings - setting_flags = '' - if not self.default_channel() or not self.default_grid(): - if self.default_grid(): - setting_flags = '--settings settings_%s.xml'\ - % self.channel_lowerword() - else: - setting_flags = '--settings settings_%s_%s.xml'\ - % (self.grid(), self.channel_lowerword()) - - return " ".join((channel_flags, grid_flags, setting_flags)).strip() - - -class WindowsManifest(ViewerManifest): - def final_exe(self): - if self.default_channel(): - if self.default_grid(): - return "imprudence.exe" - else: - return "imprudencepreview.exe" - else: - return ''.join(self.channel().split()) + '.exe' - - - def construct(self): - super(WindowsManifest, self).construct() - # the final exe is complicated because we're not sure where it's coming from, - # nor do we have a fixed name for the executable - self.path(self.find_existing_file('debug/imprudence-bin.exe', 'release/imprudence-bin.exe', 'relwithdebinfo/imprudence-bin.exe'), dst=self.final_exe()) - - self.gather_documents() - - if self.prefix("../..", dst="doc"): - self.path("LICENSE-libraries.txt") - self.end_prefix("../..") - - - self.path("imprudence.url") - - # Plugin host application - self.path(os.path.join(os.pardir, - 'llplugin', 'slplugin', self.args['configuration'], "SLPlugin.exe"), - "SLPlugin.exe") - - - self.path("featuretable.txt") - - # For use in crash reporting (generates minidumps) - self.path("dbghelp.dll") - - # For using FMOD for sound... DJS - #self.path("fmod.dll") - - # For spellchecking - self.path("libhunspell.dll") - - # For textures - if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): - self.path("openjpeg.dll") - self.end_prefix() - - # For sound - if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): - self.path("openal32.dll") - self.path("alut.dll") - self.end_prefix() - - - # Media plugins - QuickTime - if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"): - self.path("media_plugin_quicktime.dll") - self.end_prefix() - - # Media plugins - WebKit/Qt - if self.prefix(src='../media_plugins/webkit/%s' % self.args['configuration'], dst="llplugin"): - self.path("media_plugin_webkit.dll") - self.end_prefix() - - # For WebKit/Qt plugin runtimes - if self.prefix(src="../../libraries/i686-win32/lib/release", dst="llplugin"): - self.path("libeay32.dll") - self.path("qtcore4.dll") - self.path("qtgui4.dll") - self.path("qtnetwork4.dll") - self.path("qtopengl4.dll") - self.path("qtwebkit4.dll") - self.path("ssleay32.dll") - self.end_prefix() - - # For WebKit/Qt plugin runtimes (image format plugins) - if self.prefix(src="../../libraries/i686-win32/lib/release/imageformats", dst="llplugin/imageformats"): - self.path("qgif4.dll") - self.path("qico4.dll") - self.path("qjpeg4.dll") - self.path("qmng4.dll") - self.path("qsvg4.dll") - self.path("qtiff4.dll") - self.end_prefix() - - # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388 - self.path("skins/default/xui/en-us/mime_types_windows.xml", "skins/default/xui/en-us/mime_types.xml") - - # These need to be installed as a SxS assembly, currently a 'private' assembly. - # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx - if self.prefix(src=self.args['configuration'], dst=""): - if self.args['configuration'] == 'Debug': - self.path("msvcr80d.dll") - self.path("msvcp80d.dll") - self.path("Microsoft.VC80.DebugCRT.manifest") - else: - self.path("msvcr80.dll") - self.path("msvcp80.dll") - self.path("Microsoft.VC80.CRT.manifest") - self.end_prefix() - - # The config file name needs to match the exe's name. - self.path(src="%s/imprudence-bin.exe.config" % self.args['configuration'], dst=self.final_exe() + ".config") - - # We need this one too, so that llkdu loads at runtime - DEV-41194 - #self.path(src="%s/imprudence-bin.exe.config" % self.args['configuration'], dst="llkdu.dll.2.config") - self.path("llkdu.dll.2.config") - - # We need this one too, so that win_crash_logger.exe loads at runtime - DEV-19004 - #self.path(src="%s/imprudence-bin.exe.config" % self.args['configuration'], dst="win_crash_logger.exe.config") - - # same thing for auto-updater. - #self.path(src="%s/imprudence-bin.exe.config" % self.args['configuration'], dst="updater.exe.config") - - # Vivox runtimes - if self.prefix(src="vivox-runtime/i686-win32", dst=""): - # self.path("alut.dll") - self.path("wrap_oal.dll") - self.path("SLVoice.exe") - # self.path("SLVoiceAgent.exe") - # self.path("libeay32.dll") - # self.path("srtp.dll") - # self.path("ssleay32.dll") - # self.path("tntk.dll") - self.path("vivoxsdk.dll") - self.path("ortp.dll") - - self.end_prefix() - - # Gstreamer plugins - if self.prefix(src="lib/gstreamer-plugins", dst=""): - self.path("*.dll", dst="lib/gstreamer-plugins/*.dll") - self.end_prefix() - - # Gstreamer libs - if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): - self.path("iconv.dll") - self.path("libxml2.dll") - self.path("libcairo-2.dll") - self.path("libgio-2.0-0.dll") - self.path("libglib-2.0-0.dll") - self.path("libgmodule-2.0-0.dll") - self.path("libgobject-2.0-0.dll") - self.path("libgthread-2.0-0.dll") - self.path("charset.dll") - self.path("intl.dll") - self.path("libgcrypt-11.dll") - self.path("libgnutls-26.dll") - self.path("libgpg-error-0.dll") - self.path("libgstapp.dll") - self.path("libgstaudio.dll") - self.path("libgstbase-0.10.dll") - self.path("libgstcdda.dll") - self.path("libgstcontroller-0.10.dll") - self.path("libgstdataprotocol-0.10.dll") - self.path("libgstdshow.dll") - self.path("libgstfft.dll") - self.path("libgstinterfaces.dll") - self.path("libgstnet-0.10.dll") - self.path("libgstnetbuffer.dll") - self.path("libgstpbutils.dll") - self.path("libgstreamer-0.10.dll") - self.path("libgstriff.dll") - self.path("libgstrtp.dll") - self.path("libgstrtsp.dll") - self.path("libgstsdp.dll") - self.path("libgsttag.dll") - self.path("libgstvideo.dll") - self.path("libjpeg.dll") - self.path("libmp3lame-0.dll") - self.path("libneon-27.dll") - self.path("libogg-0.dll") - self.path("liboil-0.3-0.dll") - self.path("libopenjpeg-2.dll") - self.path("libpng12-0.dll") - self.path("libschroedinger-1.0-0.dll") - self.path("libspeex-1.dll") - self.path("libtheora-0.dll") - self.path("libvorbis-0.dll") - self.path("libvorbisenc-2.dll") - self.path("libxml2-2.dll") - self.path("glew32.dll") - self.path("xvidcore.dll") - self.path("zlib1.dll") - self.end_prefix() - -# # pull in the crash logger and updater from other projects -# self.path(src=self.find_existing_file( # tag:"crash-logger" here as a cue to the exporter -# "../win_crash_logger/debug/windows-crash-logger.exe", -# "../win_crash_logger/release/windows-crash-logger.exe", -# "../win_crash_logger/relwithdebinfo/windows-crash-logger.exe"), -# dst="win_crash_logger.exe") - self.path(src=self.find_existing_file( - "../win_updater/debug/windows-updater.exe", - "../win_updater/release/windows-updater.exe", - "../win_updater/relwithdebinfo/windows-updater.exe"), - dst="updater.exe") - - # For google-perftools tcmalloc allocator. - #if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): - # self.path("libtcmalloc_minimal.dll") - # self.end_prefix() - - - def nsi_file_commands(self, install=True): - def wpath(path): - if path.endswith('/') or path.endswith(os.path.sep): - path = path[:-1] - path = path.replace('/', '\\') - return path - - result = "" - dest_files = [pair[1] for pair in self.file_list if pair[0] and os.path.isfile(pair[1])] - # sort deepest hierarchy first - dest_files.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b)) - dest_files.reverse() - out_path = None - for pkg_file in dest_files: - rel_file = os.path.normpath(pkg_file.replace(self.get_dst_prefix()+os.path.sep,'')) - installed_dir = wpath(os.path.join('$INSTDIR', os.path.dirname(rel_file))) - pkg_file = wpath(os.path.normpath(pkg_file)) - if installed_dir != out_path: - if install: - out_path = installed_dir - result += 'SetOutPath ' + out_path + '\n' - if install: - result += 'File ' + pkg_file + '\n' - else: - result += 'Delete ' + wpath(os.path.join('$INSTDIR', rel_file)) + '\n' - # at the end of a delete, just rmdir all the directories - if not install: - deleted_file_dirs = [os.path.dirname(pair[1].replace(self.get_dst_prefix()+os.path.sep,'')) for pair in self.file_list] - # find all ancestors so that we don't skip any dirs that happened to have no non-dir children - deleted_dirs = [] - for d in deleted_file_dirs: - deleted_dirs.extend(path_ancestors(d)) - # sort deepest hierarchy first - deleted_dirs.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b)) - deleted_dirs.reverse() - prev = None - for d in deleted_dirs: - if d != prev: # skip duplicates - result += 'RMDir ' + wpath(os.path.join('$INSTDIR', os.path.normpath(d))) + '\n' - prev = d - - return result - - def package_finish(self): - # a standard map of strings for replacing in the templates - substitution_strings = { - 'version' : '.'.join(self.args['version']).replace(' ', '_'), - 'version_short' : '.'.join(self.args['version'][:-1]).replace(' ', '_'), - 'version_dashes' : '-'.join(self.args['version']).replace(' ', '_'), - 'final_exe' : self.final_exe(), - 'grid':self.args['grid'], - 'grid_caps':self.args['grid'].upper(), - # escape quotes becase NSIS doesn't handle them well - 'flags':self.flags_list().replace('"', '$\\"'), - 'channel':self.channel(), - 'channel_oneword':self.channel_oneword(), - 'channel_unique':self.channel_unique(), - } - - version_vars = """ - !define INSTEXE "%(final_exe)s" - !define VERSION "%(version_short)s" - !define VERSION_LONG "%(version)s" - !define VERSION_DASHES "%(version_dashes)s" - """ % substitution_strings - if self.default_channel(): - if self.default_grid(): - # release viewer - installer_file = "Imprudence_%(version_dashes)s_Setup.exe" - grid_vars_template = """ - OutFile "%(installer_file)s" - !define INSTFLAGS "%(flags)s" - !define INSTNAME "Imprudence" - !define SHORTCUT "Imprudence" - !define URLNAME "imprudence" - Caption "Imprudence ${VERSION}" - """ - else: - # beta grid viewer - installer_file = "Imprudence_%(version_dashes)s_(%(grid_caps)s)_Setup.exe" - grid_vars_template = """ - OutFile "%(installer_file)s" - !define INSTFLAGS "%(flags)s" - !define INSTNAME "Imprudence%(grid_caps)s" - !define SHORTCUT "Imprudence (%(grid_caps)s)" - !define URLNAME "imprudence%(grid)s" - !define UNINSTALL_SETTINGS 1 - Caption "Imprudence %(grid)s ${VERSION}" - """ - else: - # some other channel on some grid - installer_file = "Imprudence_%(version_dashes)s_%(channel_oneword)s_Setup.exe" - grid_vars_template = """ - OutFile "%(installer_file)s" - !define INSTFLAGS "%(flags)s" - !define INSTNAME "Imprudence%(channel_oneword)s" - !define SHORTCUT "%(channel)s" - !define URLNAME "imprudence" - !define UNINSTALL_SETTINGS 1 - Caption "%(channel)s ${VERSION}" - """ - if 'installer_name' in self.args: - installer_file = self.args['installer_name'] - else: - installer_file = installer_file % substitution_strings - substitution_strings['installer_file'] = installer_file - - tempfile = "imprudence_setup_tmp.nsi" - # the following replaces strings in the nsi template - # it also does python-style % substitution - self.replace_in("installers/windows/installer_template.nsi", tempfile, { - "%%VERSION%%":version_vars, - "%%SOURCE%%":self.get_src_prefix(), - "%%GRID_VARS%%":grid_vars_template % substitution_strings, - "%%INSTALL_FILES%%":self.nsi_file_commands(True), - "%%DELETE_FILES%%":self.nsi_file_commands(False)}) - - # We use the Unicode version of NSIS, available from - # http://www.scratchpaper.com/ - NSIS_path = 'C:\\Program Files\\NSIS\\Unicode\\makensis.exe' - self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile)) - # self.remove(self.dst_path_of(tempfile)) - # If we're on a build machine, sign the code using our Authenticode certificate. JC - sign_py = 'C:\\buildscripts\\code-signing\\sign.py' - if os.path.exists(sign_py): - self.run_command(sign_py + ' ' + self.dst_path_of(installer_file)) - else: - print "Skipping code signing,", sign_py, "does not exist" - self.created_path(self.dst_path_of(installer_file)) - self.package_file = installer_file - - -class DarwinManifest(ViewerManifest): - def construct(self): - # copy over the build result (this is a no-op if run within the xcode script) - self.path(self.args['configuration'] + "/Imprudence.app", dst="") - - if self.prefix(src="", dst="Contents"): # everything goes in Contents - - self.path("Info-Imprudence.plist", dst="Info.plist") - - # copy additional libs in <bundle>/Contents/MacOS/ - if self.prefix(src="../../libraries/universal-darwin/lib_release", dst="MacOS/"): - - self.path("libndofdev.dylib") - - self.path("libopenal.1.dylib") - self.path("libalut.0.dylib") - - self.path("libglib-2.0.dylib") - self.path("libgmodule-2.0.dylib") - self.path("libgobject-2.0.dylib") - self.path("libgthread-2.0.dylib") - - self.path("libgstreamer-0.10.dylib") - self.path("libgstapp-0.10.dylib") - self.path("libgstaudio-0.10.dylib") - self.path("libgstbase-0.10.dylib") - self.path("libgstcdda-0.10.dylib") - self.path("libgstcontroller-0.10.dylib") - self.path("libgstdataprotocol-0.10.dylib") - self.path("libgstfft-0.10.dylib") - self.path("libgstinterfaces-0.10.dylib") - self.path("libgstnet-0.10.dylib") - self.path("libgstnetbuffer-0.10.dylib") - self.path("libgstpbutils-0.10.dylib") - self.path("libgstriff-0.10.dylib") - self.path("libgstrtp-0.10.dylib") - self.path("libgstrtsp-0.10.dylib") - self.path("libgstsdp-0.10.dylib") - self.path("libgsttag-0.10.dylib") - self.path("libgstvideo-0.10.dylib") - - self.path("libxml2.2.dylib") - self.path("libfaad.2.dylib") - self.path("libFLAC.8.dylib") - self.path("libintl.3.dylib") - self.path("libjpeg.62.dylib") - self.path("libpng12.0.dylib") - self.path("libneon.27.dylib") - self.path("libogg.0.dylib") - self.path("liboil-0.3.0.dylib") - self.path("libopenjpeg.1.4.dylib") - self.path("libtheora.0.dylib") - self.path("libvorbis.0.dylib") - self.path("libvorbisenc.2.dylib") - self.path("libvorbisfile.3.dylib") - - self.end_prefix("../../libraries/universal-darwin/lib_release") - - # most everything goes in the Resources directory - if self.prefix(src="", dst="Resources"): - super(DarwinManifest, self).construct() - - if self.prefix("cursors_mac"): - self.path("*.tif") - self.end_prefix("cursors_mac") - - # From the linden directory - if self.prefix("../..", dst="doc"): - self.path("LICENSE-libraries.txt") - self.end_prefix("../..") - - self.gather_documents() - - self.path("featuretable_mac.txt") - self.path("SecondLife.nib") - - self.path("viewer.icns") - - # Translations - self.path("English.lproj") - self.path("German.lproj") - self.path("Japanese.lproj") - self.path("Korean.lproj") - self.path("da.lproj") - self.path("es.lproj") - self.path("fr.lproj") - self.path("hu.lproj") - self.path("it.lproj") - self.path("nl.lproj") - self.path("pl.lproj") - self.path("pt.lproj") - self.path("ru.lproj") - self.path("tr.lproj") - self.path("uk.lproj") - self.path("zh-Hans.lproj") - - - if self.prefix(src="../../libraries/universal-darwin/lib_release/gstreamer-plugins", dst="lib/gstreamer-plugins"): - self.path("libgstaacparse.so") - self.path("libgstadder.so") - self.path("libgstaiffparse.so") - self.path("libgstamrparse.so") - self.path("libgstapp.so") - self.path("libgstaudioconvert.so") - self.path("libgstaudiorate.so") - self.path("libgstaudioresample.so") - self.path("libgstautodetect.so") - self.path("libgstavi.so") - self.path("libgstcoreelements.so") - self.path("libgstcoreindexers.so") - self.path("libgstdebug.so") - self.path("libgstdecodebin.so") - self.path("libgstdecodebin2.so") - self.path("libgstdeinterlace2.so") - self.path("libgstequalizer.so") - self.path("libgstfaad.so") - self.path("libgstffmpeg.so") - self.path("libgstffmpegcolorspace.so") - self.path("libgstffmpegscale.so") - self.path("libgstfilter.so") - self.path("libgstflac.so") - self.path("libgstflv.so") - self.path("libgstgdp.so") - self.path("libgsth264parse.so") - self.path("libgsticydemux.so") - self.path("libgstid3demux.so") - self.path("libgstinterleave.so") - self.path("libgstjpeg.so") - self.path("libgstlevel.so") - self.path("libgstmetadata.so") - self.path("libgstmpeg4videoparse.so") - self.path("libgstmpegdemux.so") - self.path("libgstmpegvideoparse.so") - self.path("libgstmultifile.so") - self.path("libgstmultipart.so") - self.path("libgstneonhttpsrc.so") - self.path("libgstogg.so") - self.path("libgstosxaudio.so") - self.path("libgstosxvideosink.so") - self.path("libgstplaybin.so") - self.path("libgstpng.so") - self.path("libgstpostproc.so") - self.path("libgstqtdemux.so") - #self.path("libgstqtwrapper.so") - self.path("libgstqueue2.so") - self.path("libgstreal.so") - self.path("libgstrtp.so") - self.path("libgstrtpmanager.so") - self.path("libgstrtsp.so") - self.path("libgstsdpelem.so") - self.path("libgstselector.so") - self.path("libgststereo.so") - self.path("libgsttcp.so") - self.path("libgsttheora.so") - self.path("libgsttypefindfunctions.so") - self.path("libgstudp.so") - self.path("libgstvideobalance.so") - self.path("libgstvideobox.so") - self.path("libgstvideocrop.so") - self.path("libgstvideoflip.so") - self.path("libgstvideomixer.so") - self.path("libgstvideorate.so") - self.path("libgstvideoscale.so") - self.path("libgstvideosignal.so") - self.path("libgstvolume.so") - self.path("libgstvorbis.so") - self.path("libgstwavparse.so") - - self.end_prefix("../../libraries/universal-darwin/lib_release/gstreamer-plugins") - - - # SLVoice and vivox lols - self.path("vivox-runtime/universal-darwin/libalut.dylib", "libalut.dylib") - self.path("vivox-runtime/universal-darwin/libopenal.dylib", "libopenal.dylib") - self.path("vivox-runtime/universal-darwin/libortp.dylib", "libortp.dylib") - self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib") - self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice") - #self.path("vivox-runtime/universal-darwin/SLVoiceAgent.app", "SLVoiceAgent.app") - - #libfmodwrapper.dylib - #self.path(self.args['configuration'] + "/libfmodwrapper.dylib", "libfmodwrapper.dylib") - - # our apps -# self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app") - self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app") - - # plugin launcher - self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin", "SLPlugin") - - # plugins - if self.prefix(src="", dst="llplugin"): - self.path("../media_plugins/quicktime/" + self.args['configuration'] + "/media_plugin_quicktime.dylib", "media_plugin_quicktime.dylib") - self.path("../media_plugins/webkit/" + self.args['configuration'] + "/media_plugin_webkit.dylib", "media_plugin_webkit.dylib") - self.path("../../libraries/universal-darwin/lib_release/libllqtwebkit.dylib", "libllqtwebkit.dylib") - - self.end_prefix("llplugin") - - # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388 - self.path("skins/default/xui/en-us/mime_types_mac.xml", "skins/default/xui/en-us/mime_types.xml") - - # command line arguments for connecting to the proper grid - self.put_in_file(self.flags_list(), 'arguments.txt') - - self.end_prefix("Resources") - - self.end_prefix("Contents") - - # NOTE: the -S argument to strip causes it to keep enough info for - # annotated backtraces (i.e. function names in the crash log). 'strip' with no - # arguments yields a slightly smaller binary but makes crash logs mostly useless. - # This may be desirable for the final release. Or not. - if ("package" in self.args['actions'] or - "unpacked" in self.args['actions']): - self.run_command('strip -S "%(viewer_binary)s"' % - { 'viewer_binary' : self.dst_path_of('Contents/MacOS/Second Life')}) - - - def package_finish(self): - channel_standin = 'Imprudence' # hah, our default channel is not usable on its own - if not self.default_channel(): - channel_standin = self.channel() - - imagename="Imprudence_" + '_'.join(self.args['version']) - - # MBW -- If the mounted volume name changes, it breaks the .DS_Store's background image and icon positioning. - # If we really need differently named volumes, we'll need to create multiple DS_Store file images, or use some other trick. - - volname="Imprudence Installer" # DO NOT CHANGE without understanding comment above - - if self.default_channel(): - if not self.default_grid(): - # beta case - imagename = imagename + '_' + self.args['grid'].upper() - else: - # first look, etc - imagename = imagename + '_' + self.channel_oneword().upper() - - sparsename = imagename + ".sparseimage" - finalname = imagename + ".dmg" - # make sure we don't have stale files laying about - self.remove(sparsename, finalname) - - self.run_command('hdiutil create "%(sparse)s" -volname "%(vol)s" -fs HFS+ -type SPARSE -megabytes 400 -layout SPUD' % { - 'sparse':sparsename, - 'vol':volname}) - - # mount the image and get the name of the mount point and device node - hdi_output = self.run_command('hdiutil attach -private "' + sparsename + '"') - devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip() - volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip() - - # Copy everything in to the mounted .dmg - - if self.default_channel() and not self.default_grid(): - app_name = "Imprudence " + self.args['grid'] - else: - app_name = channel_standin.strip() - - # Hack: - # Because there is no easy way to coerce the Finder into positioning - # the app bundle in the same place with different app names, we are - # adding multiple .DS_Store files to svn. There is one for release, - # one for release candidate and one for first look. Any other channels - # will use the release .DS_Store, and will look broken. - # - Ambroff 2008-08-20 - dmg_template = os.path.join( - 'installers', - 'darwin', - '%s-dmg' % "".join(self.channel_unique().split()).lower()) - - if not os.path.exists (self.src_path_of(dmg_template)): - dmg_template = os.path.join ('installers', 'darwin', 'release-dmg') - - for s,d in {self.get_dst_prefix():app_name + ".app", - os.path.join(dmg_template, "_VolumeIcon.icns"): ".VolumeIcon.icns", - os.path.join(dmg_template, "background.jpg"): "background.jpg", - os.path.join(dmg_template, "_DS_Store"): ".DS_Store"}.items(): - print "Copying to dmg", s, d - self.copy_action(self.src_path_of(s), os.path.join(volpath, d)) - - # Hide the background image, DS_Store file, and volume icon file (set their "visible" bit) - self.run_command('SetFile -a V "' + os.path.join(volpath, ".VolumeIcon.icns") + '"') - self.run_command('SetFile -a V "' + os.path.join(volpath, "background.jpg") + '"') - self.run_command('SetFile -a V "' + os.path.join(volpath, ".DS_Store") + '"') - - # Create the alias file (which is a resource file) from the .r - self.run_command('rez "' + self.src_path_of("installers/darwin/release-dmg/Applications-alias.r") + '" -o "' + os.path.join(volpath, "Applications") + '"') - - # Set the alias file's alias and custom icon bits - self.run_command('SetFile -a AC "' + os.path.join(volpath, "Applications") + '"') - - # Set the disk image root's custom icon bit - self.run_command('SetFile -a C "' + volpath + '"') - - # Unmount the image - self.run_command('hdiutil detach -force "' + devfile + '"') - - print "Converting temp disk image to final disk image" - self.run_command('hdiutil convert "%(sparse)s" -format UDZO -imagekey zlib-level=9 -o "%(final)s"' % {'sparse':sparsename, 'final':finalname}) - # get rid of the temp file - self.package_file = finalname - self.remove(sparsename) - -class LinuxManifest(ViewerManifest): - def construct(self): - super(LinuxManifest, self).construct() - - self.path("res/imprudence_icon.png","imprudence_icon.png") - if self.prefix("linux_tools", dst=""): - #self.path("client-readme.txt","README-linux.txt") - self.path("client-readme-voice.txt","README-linux-voice.txt") - #self.path("client-readme-joystick.txt","README-linux-joystick.txt") - self.path("wrapper.sh","imprudence") - self.path("handle_secondlifeprotocol.sh") - self.path("register_secondlifeprotocol.sh") - self.path("getvoice.sh") - self.end_prefix("linux_tools") - - self.gather_documents() - - # From the linden directory - if self.prefix("../..", dst="doc"): - self.path("LICENSE-libraries.txt") - self.end_prefix("../..") - - # Create an appropriate gridargs.dat for this package, denoting required grid. - self.put_in_file(self.flags_list(), 'gridargs.dat') - self.path("linux_tools/launch_url.sh","launch_url.sh") - self.path("../llplugin/slplugin/SLPlugin", "bin/SLPlugin") - if self.prefix("res-sdl"): - self.path("*") - # recurse - self.end_prefix("res-sdl") - - # plugins - if self.prefix(src="", dst="bin/llplugin"): - self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so") - self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") - self.end_prefix("bin/llplugin") - - # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388 - self.path("skins/default/xui/en-us/mime_types_linux.xml", "skins/default/xui/en-us/mime_types.xml") - - self.path("featuretable_linux.txt") - - - def package_finish(self): - if 'installer_name' in self.args: - installer_name = self.args['installer_name'] - else: - installer_name_components = ['Imprudence_', self.args.get('arch')] - installer_name_components.extend(self.args['version']) - installer_name = "_".join(installer_name_components) - if self.default_channel(): - if not self.default_grid(): - installer_name += '_' + self.args['grid'].upper() - else: - installer_name += '_' + self.channel_oneword().upper() - - # Fix access permissions - self.run_command(""" - find %(dst)s -type d | xargs --no-run-if-empty chmod 755; - find %(dst)s -type f -perm 0700 | xargs --no-run-if-empty chmod 0755; - find %(dst)s -type f -perm 0500 | xargs --no-run-if-empty chmod 0555; - find %(dst)s -type f -perm 0600 | xargs --no-run-if-empty chmod 0644; - find %(dst)s -type f -perm 0400 | xargs --no-run-if-empty chmod 0444; - true""" % {'dst':self.get_dst_prefix() }) - - self.package_file = installer_name + '.tar.bz2' - - # Disabled for now. It's a waste of time to package every compile. - - # if("package" in self.args['actions'] or - # "unpacked" in self.args['actions']): - # - # # temporarily move directory tree so that it has the right - # # name in the tarfile - # self.run_command("mv %(dst)s %(inst)s" % { - # 'dst': self.get_dst_prefix(), - # 'inst': self.build_path_of(installer_name)}) - # try: - # # --numeric-owner hides the username of the builder for - # # security etc. - # self.run_command('tar -C %(dir)s --numeric-owner -cjf ' - # '%(inst_path)s.tar.bz2 %(inst_name)s' % { - # 'dir': self.get_build_prefix(), - # 'inst_name': installer_name, - # 'inst_path':self.build_path_of(installer_name)}) - # finally: - # self.run_command("mv %(inst)s %(dst)s" % { - # 'dst': self.get_dst_prefix(), - # 'inst': self.build_path_of(installer_name)}) - -class Linux_i686Manifest(LinuxManifest): - def construct(self): - super(Linux_i686Manifest, self).construct() - self.path("imprudence-stripped","bin/do-not-directly-run-imprudence-bin") - - - if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"): - self.path("libapr-1.so.0") - self.path("libaprutil-1.so.0") - self.path("libdb-4.2.so") - self.path("libcrypto.so.0.9.7") - self.path("libexpat.so.1") - self.path("libssl.so.0.9.7") - self.path("libuuid.so", "libuuid.so.1") - self.path("libSDL-1.2.so.0") - self.path("libELFIO.so") - self.path("libopenjpeg.so.2") - self.path("libxml2.so.2") - self.path("libz.so.1") - - # OpenAL - self.path("libopenal.so.1") - self.path("libalut.so.0") - - # GTK+ and dependencies - self.path("libatk-1.0.so.0") - self.path("libcairo.so.2") - self.path("libfontconfig.so.1") - self.path("libfreetype.so.6") - # self.path("libgdk_pixbuf-2.0.so.0") # see linux64 why - self.path("libgdk-x11-2.0.so.0") - self.path("libgtk-x11-2.0.so.0") - # self.path("libpango-1.0.so.0") # dto. - # self.path("libpangoft2-1.0.so.0") - # self.path("libpangox-1.0.so.0") - # self.path("libpangoxft-1.0.so.0") - self.path("libpixman-1.so.0") - - # Gstreamer libs - self.path("libgstbase-0.10.so.0") - self.path("libgstreamer-0.10.so.0") - self.path("libgstaudio-0.10.so.0") - self.path("libgstbase-0.10.so.0") - self.path("libgstcontroller-0.10.so.0") - self.path("libgstdataprotocol-0.10.so.0") - self.path("libgstinterfaces-0.10.so.0") - self.path("libgstnetbuffer-0.10.so.0") - self.path("libgstpbutils-0.10.so.0") - self.path("libgstriff-0.10.so.0") - self.path("libgstrtp-0.10.so.0") - self.path("libgstrtsp-0.10.so.0") - self.path("libgstsdp-0.10.so.0") - self.path("libgsttag-0.10.so.0") - self.path("libgstvideo-0.10.so.0") - - # Gstreamer plugin dependencies - self.path("libfaad.so.0") - self.path("libogg.so.0") - self.path("libtheora.so.0") - self.path("libvorbis.so.0") - self.path("libvorbisenc.so.2") - self.path("liboil-0.3.so.0") - - # Gstreamer plugins - if self.prefix("gstreamer-plugins"): - self.path("libgstalsa.so") - self.path("libgstasf.so") - self.path("libgstaudioconvert.so") - self.path("libgstaudioresample.so") - self.path("libgstautodetect.so") - self.path("libgstavi.so") - self.path("libgstcoreelements.so") - self.path("libgstcoreindexers.so") - self.path("libgstdecodebin2.so") - self.path("libgstdecodebin.so") - self.path("libgstesd.so") - self.path("libgstfaad.so") - self.path("libgstffmpeg.so") - self.path("libgstgnomevfs.so") - self.path("libgsticydemux.so") - self.path("libgstid3demux.so") - self.path("libgstmpegdemux.so") - self.path("libgstmultifile.so") - self.path("libgstmultipart.so") - self.path("libgstogg.so") - self.path("libgstossaudio.so") - self.path("libgstplaybin.so") - self.path("libgstpulse.so") - self.path("libgstqtdemux.so") - self.path("libgstqueue2.so") - self.path("libgsttcp.so") - self.path("libgsttheora.so") - self.path("libgsttypefindfunctions.so") - self.path("libgstudp.so") - self.path("libgstvideoscale.so") - self.path("libgstvolume.so") - self.path("libgstvorbis.so") - self.path("libgstwavparse.so") - - self.end_prefix("gstreamer-plugins") - - self.end_prefix("lib") - - # Vivox runtimes and libs - if self.prefix(src="vivox-runtime/i686-linux", dst="bin"): - self.path("SLVoice") - self.end_prefix("bin") - - if self.prefix(src="vivox-runtime/i686-linux", dst="lib"): - self.path("libalut.so") - self.path("libortp.so") - self.path("libvivoxsdk.so") - self.end_prefix("lib") - -class Linux_x86_64Manifest(LinuxManifest): - def construct(self): - super(Linux_x86_64Manifest, self).construct() - self.path("imprudence-stripped","bin/do-not-directly-run-imprudence-bin") -# self.path("../linux_crash_logger/linux-crash-logger-stripped","linux-crash-logger.bin") - - self.path("linux_tools/launch_url.sh","launch_url.sh") - if self.prefix("res-sdl"): - self.path("*") - # recurse - self.end_prefix("res-sdl") - - self.path("featuretable_linux.txt") - #self.path("secondlife-x86_64.supp") - - self.path("app_settings/mozilla-runtime-linux-x86_64") - - if self.prefix("../../libraries/x86_64-linux/lib_release_client", dst="lib64"): - self.path("libapr-1.so.0") - self.path("libaprutil-1.so.0") - self.path("libdb-4.2.so") - self.path("libcrypto.so.0.9.8") - self.path("libexpat.so.1") - self.path("libssl.so.0.9.8") - self.path("libuuid.so", "libuuid.so.1") - self.path("libSDL-1.2.so.0") - self.path("libELFIO.so") - self.path("libjpeg.so.7") - self.path("libpng12.so.0") - self.path("libopenjpeg.so.2") - self.path("libxml2.so.2") - #self.path("libz.so.1") #not needed - - # OpenAL - self.path("libopenal.so.1") - self.path("libalut.so.0") - - # GTK+ and dependencies - self.path("libatk-1.0.so.0") - self.path("libcairo.so.2") - self.path("libfontconfig.so.1") - self.path("libfreetype.so.6") - self.path("libgdk_pixbuf-2.0.so.0") # was commented to use systems gdk pixbufs instead - - # but seems webkit needs it o_O . Packaging for testing now. - self.path("libgdk-x11-2.0.so.0") - self.path("libgtk-x11-2.0.so.0") -# self.path("libpango-1.0.so.0") # use systems pango instead -# self.path("libpangoft2-1.0.so.0") # Both gdk pixbufs and pango would load systems modules -# self.path("libpangox-1.0.so.0") # and crash if not compatible or present. -# self.path("libpangoxft-1.0.so.0") # So we depend system gdk pixbufs and pango anyway. - self.path("libpixman-1.so.0") - - # Gstreamer libs - self.path("libgstbase-0.10.so.0") - self.path("libgstreamer-0.10.so.0") - self.path("libgstaudio-0.10.so.0") - self.path("libgstbase-0.10.so.0") - self.path("libgstcontroller-0.10.so.0") - self.path("libgstdataprotocol-0.10.so.0") - self.path("libgstinterfaces-0.10.so.0") - self.path("libgstnetbuffer-0.10.so.0") - self.path("libgstpbutils-0.10.so.0") - self.path("libgstriff-0.10.so.0") - self.path("libgstrtp-0.10.so.0") - self.path("libgstrtsp-0.10.so.0") - self.path("libgstsdp-0.10.so.0") - self.path("libgsttag-0.10.so.0") - self.path("libgstvideo-0.10.so.0") - - # Gstreamer plugin dependencies - self.path("libfaad.so.0") - self.path("libogg.so.0") - self.path("libtheora.so.0") - self.path("libvorbis.so.0") - self.path("libvorbisenc.so.2") - self.path("liboil-0.3.so.0") - - # Gstreamer plugins - if self.prefix("gstreamer-plugins"): - self.path("libgstalsa.so") - self.path("libgstasf.so") - self.path("libgstaudioconvert.so") - self.path("libgstaudioresample.so") - self.path("libgstautodetect.so") - self.path("libgstavi.so") - self.path("libgstcoreelements.so") - self.path("libgstcoreindexers.so") - self.path("libgstdecodebin2.so") - self.path("libgstdecodebin.so") - self.path("libgstesd.so") - self.path("libgstfaad.so") - self.path("libgstffmpeg.so") - self.path("libgstffmpegcolorspace.so") - self.path("libgstgnomevfs.so") - self.path("libgsticydemux.so") - self.path("libgstid3demux.so") - self.path("libgstmpegdemux.so") - self.path("libgstmultifile.so") - self.path("libgstmultipart.so") - self.path("libgstogg.so") - self.path("libgstossaudio.so") - self.path("libgstplaybin.so") - self.path("libgstpulse.so") - self.path("libgstqtdemux.so") - self.path("libgstqueue2.so") - self.path("libgsttcp.so") - self.path("libgsttheora.so") - self.path("libgsttypefindfunctions.so") - self.path("libgstudp.so") - self.path("libgstvideoscale.so") - self.path("libgstvolume.so") - self.path("libgstvorbis.so") - self.path("libgstwavparse.so") - - self.end_prefix("gstreamer-plugins") - self.end_prefix("lib64") - - - # Vivox runtimes and libs - if self.prefix(src="vivox-runtime/i686-linux", dst="bin"): - self.path("SLVoice") - self.end_prefix("bin") - - if self.prefix(src="vivox-runtime/i686-linux", dst="lib32"): - #self.path("libalut.so") - self.path("libortp.so") - self.path("libvivoxsdk.so") - self.end_prefix("lib32") - - # 32bit libs needed for voice - if self.prefix("../../libraries/x86_64-linux/lib_release_client/32bit-compat", dst="lib32"): - self.path("libalut.so") - self.path("libidn.so.11") - self.path("libopenal.so.1") - # self.path("libortp.so") - self.path("libuuid.so.1") - self.end_prefix("lib32") - -if __name__ == "__main__": - main() diff --git a/linden/install.xml b/linden/install.xml index 402ce00..5154fe0 100644 --- a/linden/install.xml +++ b/linden/install.xml @@ -735,20 +735,6 @@ <key>url</key> <uri>http://imprudenceviewer.org/download/libs/gstreamer-plugins-darwin-20100826.tar.bz2</uri> </map> - <key>linux</key> - <map> - <key>md5sum</key> - <string>973aabcba37f6ee0ceab2e3d063eea84</string> - <key>url</key> - <uri>http://imprudenceviewer.org/download/libs/gstreamer-plugins-linux-20100827.tar.bz2</uri> - </map> - <key>linux64</key> - <map> - <key>md5sum</key> - <string>663c29f3885ab8429ad6841d80181c31</string> - <key>url</key> - <uri>http://imprudenceviewer.org/download/libs/gstreamer-plugins-linux64-20100827.tar.bz2</uri> - </map> </map> </map> <key>gtk-etc</key> -- cgit v1.1 From e596df5f4e84229f0c7edf02490197e3cef33f70 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Fri, 10 Sep 2010 11:11:16 +0200 Subject: fix conversion that is ambiguous for linux64 gcc; introduced in 11e4c300 maybe squash with 11e4c300 --- linden/indra/newview/llfloaterassetbrowser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linden') diff --git a/linden/indra/newview/llfloaterassetbrowser.cpp b/linden/indra/newview/llfloaterassetbrowser.cpp index 9b41390..ca0e8d1 100644 --- a/linden/indra/newview/llfloaterassetbrowser.cpp +++ b/linden/indra/newview/llfloaterassetbrowser.cpp @@ -122,7 +122,7 @@ void LLFloaterAssetBrowser::createThumbnails() temp.mUUID = itemp->getUUID(); temp.mName = itemp->getName(); temp.mTexturep = NULL; - temp.mAssetRect = NULL; + temp.mAssetRect = LLRect::null; mTextureAssets.push_back(temp); } -- cgit v1.1 From 2e63340ddd69bfd41930e52dcb97912f282c8a32 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Fri, 10 Sep 2010 21:01:31 +0200 Subject: fix minimap surface not rendered --- linden/indra/newview/llsurface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linden') diff --git a/linden/indra/newview/llsurface.cpp b/linden/indra/newview/llsurface.cpp index 2e20ace..700ff8e 100644 --- a/linden/indra/newview/llsurface.cpp +++ b/linden/indra/newview/llsurface.cpp @@ -278,7 +278,7 @@ void LLSurface::createWaterTexture() } } - mWaterTexturep = new LLViewerImage(sTextureSize/2, sTextureSize/2, 4, FALSE); + mWaterTexturep = new LLViewerImage(raw, FALSE); mWaterTexturep->dontDiscard(); gGL.getTexUnit(0)->bind(mWaterTexturep); mWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); -- cgit v1.1 From 341f3416d4108f625f1591ed7afe78324e560480 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Sun, 19 Sep 2010 21:51:40 +0200 Subject: fix: cached trees + grass white on opensim issues remaining: windlight water is "flat" --- linden/indra/newview/llvograss.cpp | 5 +++-- linden/indra/newview/llvograss.h | 2 +- linden/indra/newview/llvotree.cpp | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/llvograss.cpp b/linden/indra/newview/llvograss.cpp index c56d676..e516aeb 100644 --- a/linden/indra/newview/llvograss.cpp +++ b/linden/indra/newview/llvograss.cpp @@ -108,7 +108,9 @@ void LLVOGrass::updateSpecies() SpeciesMap::const_iterator it = sSpeciesTable.begin(); mSpecies = (*it).first; } - setTEImage(0, gImageList.getImageFromFile(sSpeciesTable[mSpecies]->mTextureName)); + + mGrassImage = gImageList.getImageFromFile(sSpeciesTable[mSpecies]->mTextureName, TRUE, TRUE); + setTEImage(0, mGrassImage); } @@ -162,7 +164,6 @@ void LLVOGrass::initClass() GrassSpeciesData* newGrass = new GrassSpeciesData(); - std::string textureName; static LLStdStringHandle texture_name_string = LLXmlTree::addAttributeString("texture_name"); diff --git a/linden/indra/newview/llvograss.h b/linden/indra/newview/llvograss.h index c55c59b..c05908b 100644 --- a/linden/indra/newview/llvograss.h +++ b/linden/indra/newview/llvograss.h @@ -128,7 +128,7 @@ private: void updateSpecies(); F32 mLastHeight; // For cheap update hack S32 mNumBlades; - + LLPointer<LLViewerImage> mGrassImage; static SpeciesMap sSpeciesTable; }; #endif // LL_VO_GRASS_ diff --git a/linden/indra/newview/llvotree.cpp b/linden/indra/newview/llvotree.cpp index 89d6491..53cfbdb 100644 --- a/linden/indra/newview/llvotree.cpp +++ b/linden/indra/newview/llvotree.cpp @@ -324,7 +324,7 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys, // // Load Species-Specific data // - mTreeImagep = gImageList.getImageFromFile(sSpeciesTable[mSpecies]->mTextureName); + mTreeImagep = gImageList.getImageFromFile(sSpeciesTable[mSpecies]->mTextureName, TRUE, TRUE); if (mTreeImagep) { gGL.getTexUnit(0)->bind(mTreeImagep.get()); -- cgit v1.1 From 994de98c7bf0461a5e1c1ea6aea517d9437ea4fd Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Mon, 20 Sep 2010 11:48:27 +0200 Subject: one more poke on trees+grass + fix the windlight water --- linden/indra/newview/llviewerimagelist.cpp | 2 +- linden/indra/newview/llvograss.cpp | 9 +++++++-- linden/indra/newview/llvograss.h | 2 +- linden/indra/newview/llvotree.cpp | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/llviewerimagelist.cpp b/linden/indra/newview/llviewerimagelist.cpp index f795de6..7642e80 100644 --- a/linden/indra/newview/llviewerimagelist.cpp +++ b/linden/indra/newview/llviewerimagelist.cpp @@ -156,7 +156,7 @@ void LLViewerImageList::doPreloadImages() image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = getImage(DEFAULT_WATER_NORMAL, MIPMAP_YES, IMMEDIATE_YES); + image = getImageFromFile(DEFAULT_WATER_NORMAL.asString()+".j2c", MIPMAP_YES, IMMEDIATE_YES,0,0,DEFAULT_WATER_NORMAL); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); diff --git a/linden/indra/newview/llvograss.cpp b/linden/indra/newview/llvograss.cpp index e516aeb..8f4c0de 100644 --- a/linden/indra/newview/llvograss.cpp +++ b/linden/indra/newview/llvograss.cpp @@ -109,8 +109,8 @@ void LLVOGrass::updateSpecies() mSpecies = (*it).first; } - mGrassImage = gImageList.getImageFromFile(sSpeciesTable[mSpecies]->mTextureName, TRUE, TRUE); - setTEImage(0, mGrassImage); + LLViewerImage* grass_image = gImageList.getImageFromFile(sSpeciesTable[mSpecies]->mTextureName, TRUE, TRUE, 0, 0, sSpeciesTable[mSpecies]->mTextureID); + setTEImage(0, grass_image); } @@ -170,6 +170,11 @@ void LLVOGrass::initClass() success &= grass_def->getFastAttributeString(texture_name_string, textureName); newGrass->mTextureName = textureName; + std::string textureID; + static LLStdStringHandle texture_id = LLXmlTree::addAttributeString("texture_id"); + success &= grass_def->getFastAttributeString(texture_id, textureID); + newGrass->mTextureID = LLUUID(textureID); + static LLStdStringHandle blade_sizex_string = LLXmlTree::addAttributeString("blade_size_x"); success &= grass_def->getFastAttributeF32(blade_sizex_string, F32_val); newGrass->mBladeSizeX = F32_val; diff --git a/linden/indra/newview/llvograss.h b/linden/indra/newview/llvograss.h index c05908b..86e4b95 100644 --- a/linden/indra/newview/llvograss.h +++ b/linden/indra/newview/llvograss.h @@ -128,7 +128,7 @@ private: void updateSpecies(); F32 mLastHeight; // For cheap update hack S32 mNumBlades; - LLPointer<LLViewerImage> mGrassImage; +// LLPointer<LLViewerImage> mGrassImage; static SpeciesMap sSpeciesTable; }; #endif // LL_VO_GRASS_ diff --git a/linden/indra/newview/llvotree.cpp b/linden/indra/newview/llvotree.cpp index 53cfbdb..fc38a5f 100644 --- a/linden/indra/newview/llvotree.cpp +++ b/linden/indra/newview/llvotree.cpp @@ -324,7 +324,7 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys, // // Load Species-Specific data // - mTreeImagep = gImageList.getImageFromFile(sSpeciesTable[mSpecies]->mTextureName, TRUE, TRUE); + mTreeImagep = gImageList.getImageFromFile(sSpeciesTable[mSpecies]->mTextureName, TRUE, TRUE, 0, 0, sSpeciesTable[mSpecies]->mTextureID); if (mTreeImagep) { gGL.getTexUnit(0)->bind(mTreeImagep.get()); -- cgit v1.1 From b6ca1620c712288268913dfb616fbd3d96c1fcf5 Mon Sep 17 00:00:00 2001 From: Robin Cornelius Date: Sat, 9 Oct 2010 10:20:10 +0100 Subject: Fix some STL errors highlighted by MSVC debug --- linden/indra/llrender/llfontregistry.cpp | 2 +- linden/indra/llui/lllineeditor.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'linden') diff --git a/linden/indra/llrender/llfontregistry.cpp b/linden/indra/llrender/llfontregistry.cpp index 2140dbd..9792a91 100644 --- a/linden/indra/llrender/llfontregistry.cpp +++ b/linden/indra/llrender/llfontregistry.cpp @@ -107,7 +107,7 @@ bool removeSubString(std::string& str, const std::string& substr) size_t pos = str.find(substr); if (pos != string::npos) { - str.replace(pos,substr.length(),(const char *)NULL, 0); + str.erase(pos,substr.length()); return true; } return false; diff --git a/linden/indra/llui/lllineeditor.cpp b/linden/indra/llui/lllineeditor.cpp index e73b287..a3785e4 100644 --- a/linden/indra/llui/lllineeditor.cpp +++ b/linden/indra/llui/lllineeditor.cpp @@ -416,7 +416,16 @@ void LLLineEditor::setText(const LLStringExplicit &new_text) setCursor(llmin((S32)mText.length(), getCursor())); // Set current history line to end of history. - mCurrentHistoryLine = mLineHistory.end() - 1; + // RC Fix, its really not safe to just take 1 of the end itterator, if end==begin + // that leaves an invalid state upseting the secure STL checks + if(mLineHistory.empty()) + { + mCurrentHistoryLine = mLineHistory.begin(); + } + else + { + mCurrentHistoryLine = mLineHistory.end() - 1; + } mPrevText = mText; } -- cgit v1.1 From 1924ac57d991dc00ef7eb7c121ac7e7064b29717 Mon Sep 17 00:00:00 2001 From: Robin Cornelius Date: Sat, 9 Oct 2010 10:22:23 +0100 Subject: Add a fall back to find NSIS on win64 --- linden/indra/newview/viewer_manifest.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/viewer_manifest.py b/linden/indra/newview/viewer_manifest.py index 7563268..f01cd7a 100755 --- a/linden/indra/newview/viewer_manifest.py +++ b/linden/indra/newview/viewer_manifest.py @@ -517,8 +517,12 @@ class WindowsManifest(ViewerManifest): # We use the Unicode version of NSIS, available from # http://www.scratchpaper.com/ - NSIS_path = 'C:\\Program Files\\NSIS\\Unicode\\makensis.exe' - self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile)) + try: + NSIS_path = 'C:\\Program Files\\NSIS\\Unicode\\makensis.exe' + self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile)) + except: + NSIS_path = 'C:\\Program Files (x86)\\NSIS\\Unicode\\makensis.exe' + self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile)) # self.remove(self.dst_path_of(tempfile)) # If we're on a build machine, sign the code using our Authenticode certificate. JC sign_py = 'C:\\buildscripts\\code-signing\\sign.py' -- cgit v1.1 From db79d815c873d3c2c408e4f0e10ace4a345ddf99 Mon Sep 17 00:00:00 2001 From: Robin Cornelius Date: Sat, 9 Oct 2010 10:23:52 +0100 Subject: Fix tab/space issues in viewer_manifest.py --- linden/indra/newview/viewer_manifest.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/viewer_manifest.py b/linden/indra/newview/viewer_manifest.py index f01cd7a..ff59aec 100755 --- a/linden/indra/newview/viewer_manifest.py +++ b/linden/indra/newview/viewer_manifest.py @@ -845,7 +845,7 @@ class LinuxManifest(ViewerManifest): self.path("wrapper.sh","imprudence") self.path("handle_secondlifeprotocol.sh") self.path("register_secondlifeprotocol.sh") - self.path("getvoice.sh") + self.path("getvoice.sh") self.end_prefix("linux_tools") self.gather_documents() @@ -974,7 +974,7 @@ class Linux_i686Manifest(LinuxManifest): self.path("libgstvideo-0.10.so.0") # Gstreamer plugin dependencies - self.path("libfaad.so.0") + self.path("libfaad.so.0") self.path("libogg.so.0") self.path("libtheora.so.0") self.path("libvorbis.so.0") @@ -1124,7 +1124,7 @@ class Linux_x86_64Manifest(LinuxManifest): self.path("libgstdecodebin2.so") self.path("libgstdecodebin.so") self.path("libgstesd.so") - self.path("libgstfaad.so") + self.path("libgstfaad.so") self.path("libgstffmpeg.so") self.path("libgstffmpegcolorspace.so") self.path("libgstgnomevfs.so") @@ -1162,14 +1162,14 @@ class Linux_x86_64Manifest(LinuxManifest): self.path("libortp.so") self.path("libvivoxsdk.so") self.end_prefix("lib32") - - # 32bit libs needed for voice - if self.prefix("../../libraries/x86_64-linux/lib_release_client/32bit-compat", dst="lib32"): - self.path("libalut.so") - self.path("libidn.so.11") - self.path("libopenal.so.1") - # self.path("libortp.so") - self.path("libuuid.so.1") + + # 32bit libs needed for voice + if self.prefix("../../libraries/x86_64-linux/lib_release_client/32bit-compat", dst="lib32"): + self.path("libalut.so") + self.path("libidn.so.11") + self.path("libopenal.so.1") + # self.path("libortp.so") + self.path("libuuid.so.1") self.end_prefix("lib32") if __name__ == "__main__": -- cgit v1.1 From 13e0e20e1be8a3437c8672369e25dec8e38ea983 Mon Sep 17 00:00:00 2001 From: Robin Cornelius Date: Sat, 9 Oct 2010 10:30:11 +0100 Subject: Use all those cores for compile --- linden/indra/cmake/00-Common.cmake | 1 + 1 file changed, 1 insertion(+) (limited to 'linden') diff --git a/linden/indra/cmake/00-Common.cmake b/linden/indra/cmake/00-Common.cmake index 3497ec9..032a3cf 100644 --- a/linden/indra/cmake/00-Common.cmake +++ b/linden/indra/cmake/00-Common.cmake @@ -55,6 +55,7 @@ if (WINDOWS) /Zc:forScope /nologo /Oy- + /MP ) if(MSVC80 OR MSVC90) -- cgit v1.1 From f001c10b78553fe3a59a2a71c223d094118bf8a8 Mon Sep 17 00:00:00 2001 From: Robin Cornelius Date: Sun, 10 Oct 2010 15:48:32 +0100 Subject: Let the gstreamer plugin build on windows --- linden/indra/cmake/GStreamer010Plugin.cmake | 29 ++++++++++++++++++---- .../llmediaimplgstreamertriviallogging.h | 15 +++++++++-- .../gstreamer010/media_plugin_gstreamer010.cpp | 11 ++++++-- linden/indra/newview/CMakeLists.txt | 20 ++++++++++++--- linden/indra/newview/viewer_manifest.py | 6 ++++- 5 files changed, 67 insertions(+), 14 deletions(-) (limited to 'linden') diff --git a/linden/indra/cmake/GStreamer010Plugin.cmake b/linden/indra/cmake/GStreamer010Plugin.cmake index 78ffd94..cafcd4c 100644 --- a/linden/indra/cmake/GStreamer010Plugin.cmake +++ b/linden/indra/cmake/GStreamer010Plugin.cmake @@ -6,7 +6,8 @@ if (STANDALONE) pkg_check_modules(GSTREAMER010 REQUIRED gstreamer-0.10) pkg_check_modules(GSTREAMER010_PLUGINS_BASE REQUIRED gstreamer-plugins-base-0.10) -elseif (LINUX) +endif (STANDALONE) + use_prebuilt_binary(gstreamer) # possible libxml should have its own .cmake file instead use_prebuilt_binary(libxml) @@ -17,6 +18,21 @@ elseif (LINUX) ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/libxml2 ) + +if (WINDOWS) + # We don't need to explicitly link against gstreamer itself, because + # LLMediaImplGStreamer probes for the system's copy at runtime. + set(GSTREAMER010_LIBRARIES + libgstvideo + libgstaudio + libgstbase-0.10 + libgstreamer-0.10 + gobject-2.0 + gmodule-2.0 + gthread-2.0 + glib-2.0 + ) +else (WINDOWS) # We don't need to explicitly link against gstreamer itself, because # LLMediaImplGStreamer probes for the system's copy at runtime. set(GSTREAMER010_LIBRARIES @@ -31,13 +47,16 @@ elseif (LINUX) rt glib-2.0 ) -endif (STANDALONE) + + +endif (WINDOWS) + if (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND) set(GSTREAMER010 ON CACHE BOOL "Build with GStreamer-0.10 streaming media support.") + add_definitions(-DLL_GSTREAMER010_ENABLED=1) endif (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND) -if (GSTREAMER010) - add_definitions(-DLL_GSTREAMER010_ENABLED=1) -endif (GSTREAMER010) + + diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h index f5da637..0ea096a 100755 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h @@ -40,18 +40,29 @@ extern "C" { #include <sys/types.h> -#include <unistd.h> +//#include <unistd.h> //fiuxme } +#define MSGMODULEFOO "(media plugin)" + +#ifdef LL_LINUX ///////////////////////////////////////////////////////////////////////// // Debug/Info/Warning macros. -#define MSGMODULEFOO "(media plugin)" + #define STDERRMSG(...) do{\ fprintf(stderr, " pid:%d: ", (int)getpid());\ fprintf(stderr, MSGMODULEFOO " %s:%d: ", __FUNCTION__, __LINE__);\ fprintf(stderr, __VA_ARGS__);\ fputc('\n',stderr);\ }while(0) +#else +#define STDERRMSG(...) do{\ + fprintf(stderr, MSGMODULEFOO " %s:%d: ", __FUNCTION__, __LINE__);\ + fprintf(stderr, __VA_ARGS__);\ + fputc('\n',stderr);\ + }while(0) +#endif + #define NULLMSG(...) do{}while(0) #define DEBUGMSG NULLMSG diff --git a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp index 4dd182e..44bc32e 100755 --- a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp +++ b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp @@ -35,6 +35,13 @@ #include "linden_common.h" +// Needed for _getcwd() RC +#ifdef LL_WINDOWS +#include <direct.h> +#include <stdlib.h> +#include <stdio.h> +#endif + #include "llgl.h" #include "llplugininstance.h" @@ -84,7 +91,7 @@ private: bool play(double rate); bool getTimePos(double &sec_out); - static const double MIN_LOOP_SEC = 1.0F; + #define MIN_LOOP_SEC 1.0F bool mIsLooping; @@ -689,7 +696,7 @@ MediaPluginGStreamer010::load() DEBUGMSG("setting up media..."); mIsLooping = false; - mVolume = 0.1234567; // minor hack to force an initial volume update + mVolume = (float) 0.1234567; // minor hack to force an initial volume update // Create a pumpable main-loop for this media mPump = g_main_loop_new (NULL, FALSE); diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index 3dabb3b..8b1d59a 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt @@ -1336,7 +1336,7 @@ if (WINDOWS) DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit media_plugin_gstreamer) if (PACKAGE) add_custom_target(package ALL DEPENDS ${CMAKE_CFG_INTDIR}/touched.bat) @@ -1456,7 +1456,7 @@ if (DARWIN) DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit media_plugin_gstreamer010) if (PACKAGE) add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME}) @@ -1481,7 +1481,7 @@ if (DARWIN) ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit media_plugin_gstreamer010) add_custom_command( TARGET package POST_BUILD COMMAND ${PYTHON_EXECUTABLE} @@ -1534,7 +1534,19 @@ if (WINDOWS) ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin COMMENT "Copying WebKit Plugin to the runtime folder." ) - + + get_target_property(BUILT_GSTREAMER_PLUGIN media_plugin_gstreamer010 LOCATION) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_if_different + ${BUILT_GSTREAMER_PLUGIN} + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin + COMMENT "Copying Gstreamer Plugin to the runtime folder." + ) + get_target_property(BUILT_QUICKTIME_PLUGIN media_plugin_quicktime LOCATION) add_custom_command( TARGET ${VIEWER_BINARY_NAME} POST_BUILD diff --git a/linden/indra/newview/viewer_manifest.py b/linden/indra/newview/viewer_manifest.py index 4c95f00..9c2dbed 100755 --- a/linden/indra/newview/viewer_manifest.py +++ b/linden/indra/newview/viewer_manifest.py @@ -257,7 +257,6 @@ class WindowsManifest(ViewerManifest): self.path("alut.dll") self.end_prefix() - # Media plugins - QuickTime if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"): self.path("media_plugin_quicktime.dll") @@ -268,6 +267,11 @@ class WindowsManifest(ViewerManifest): self.path("media_plugin_webkit.dll") self.end_prefix() + # Media plugins - Gstreamer + if self.prefix(src='../media_plugins/gstreamer/%s' % self.args['configuration'], dst="llplugin"): + self.path("media_plugin_gstreamer010.dll") + self.end_prefix() + # For WebKit/Qt plugin runtimes if self.prefix(src="../../libraries/i686-win32/lib/release", dst="llplugin"): self.path("libeay32.dll") -- cgit v1.1 From 1d3e052f723df0c3670e271a792a3bd84d6d1ca5 Mon Sep 17 00:00:00 2001 From: Robin Cornelius Date: Sun, 10 Oct 2010 15:52:28 +0100 Subject: Force mime_types.xml to use gstreamer as default --- .../newview/skins/default/xui/en-us/mime_types.xml | 38 +++++++++++----------- .../skins/default/xui/en-us/mime_types_windows.xml | 36 ++++++++++---------- 2 files changed, 37 insertions(+), 37 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types.xml index a585069..360438a 100644 --- a/linden/indra/newview/skins/default/xui/en-us/mime_types.xml +++ b/linden/indra/newview/skins/default/xui/en-us/mime_types.xml @@ -109,7 +109,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </scheme> <mimetype name="blank"> @@ -142,7 +142,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> <mimetype name="video/*"> @@ -153,7 +153,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> <mimetype name="image/*"> @@ -169,13 +169,13 @@ </mimetype> <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> <label name="vnd.secondlife.qt.legacy_label"> - Movie (QuickTime) + Movie (gstreamer) </label> <widgettype> movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> <mimetype name="application/javascript"> @@ -197,7 +197,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> <mimetype name="application/pdf"> @@ -274,7 +274,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> <mimetype name="audio/mpeg"> @@ -285,7 +285,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> <mimetype name="audio/x-aiff"> @@ -296,7 +296,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> <mimetype name="audio/x-wav"> @@ -307,7 +307,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> <mimetype menu="1" name="image/bmp"> @@ -417,7 +417,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> <mimetype name="video/mp4"> @@ -428,18 +428,18 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> - <mimetype menu="1" name="video/quicktime"> - <label name="video/quicktime_label"> - Movie (QuickTime) + <mimetype menu="1" name="video/gstreamer"> + <label name="video/gstreamer_label"> + Movie (gstreamer) </label> <widgettype> movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> <mimetype name="video/x-ms-asf"> @@ -450,7 +450,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> <mimetype name="video/x-ms-wmv"> @@ -461,7 +461,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> <mimetype menu="1" name="video/x-msvideo"> @@ -472,7 +472,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> </mimetypes> diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml index 4a7a6e1..d4d47cb 100644 --- a/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml +++ b/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml @@ -109,7 +109,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer </impl> </scheme> <mimetype name="blank"> @@ -120,7 +120,7 @@ none </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer </impl> </mimetype> <mimetype name="none/none"> @@ -157,13 +157,13 @@ </mimetype> <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> <label name="vnd.secondlife.qt.legacy_label"> - Movie (QuickTime) + Movie (gstreamer) </label> <widgettype> movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer </impl> </mimetype> <mimetype name="application/javascript"> @@ -214,7 +214,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer </impl> </mimetype> <mimetype name="application/xhtml+xml"> @@ -241,7 +241,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer </impl> </mimetype> <mimetype name="audio/mpeg"> @@ -252,7 +252,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer </impl> </mimetype> <mimetype name="audio/x-aiff"> @@ -263,7 +263,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer </impl> </mimetype> <mimetype name="audio/x-wav"> @@ -274,7 +274,7 @@ audio </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010 </impl> </mimetype> <mimetype menu="1" name="image/bmp"> @@ -384,7 +384,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010010 </impl> </mimetype> <mimetype name="video/mp4"> @@ -395,18 +395,18 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010010 </impl> </mimetype> - <mimetype menu="1" name="video/quicktime"> - <label name="video/quicktime_label"> - Movie (QuickTime) + <mimetype menu="1" name="video/gstreamer"> + <label name="video/gstreamer_label"> + Movie (gstreamer) </label> <widgettype> movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010010 </impl> </mimetype> <mimetype name="video/x-ms-asf"> @@ -417,7 +417,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010010 </impl> </mimetype> <mimetype name="video/x-ms-wmv"> @@ -428,7 +428,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010010 </impl> </mimetype> <mimetype menu="1" name="video/x-msvideo"> @@ -439,7 +439,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_gstreamer010010 </impl> </mimetype> </mimetypes> -- cgit v1.1 From b5f6f8919b99e897ea4616e8df4a10b281f51826 Mon Sep 17 00:00:00 2001 From: Armin Weatherwax Date: Sat, 25 Sep 2010 00:49:50 +0200 Subject: Thickbrick Sleaford, Soft Linden: STORM-164 make gcc-4.4 happy about llvosky.h --- linden/indra/newview/llvosky.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linden') diff --git a/linden/indra/newview/llvosky.h b/linden/indra/newview/llvosky.h index 5e23065..08038a5 100644 --- a/linden/indra/newview/llvosky.h +++ b/linden/indra/newview/llvosky.h @@ -147,7 +147,7 @@ protected: static S32 getResolution() { return sResolution; } static S32 getCurrent() { return sCurrent; } - static S32 stepCurrent() { return (sCurrent = ++sCurrent % 2); } + static S32 stepCurrent() { sCurrent++; sCurrent&=1; return sCurrent; } static S32 getNext() { return ((sCurrent+1) % 2); } static S32 getWhich(const BOOL curr) { return curr ? sCurrent : getNext(); } -- cgit v1.1 From b3b30285126289f54b57bd42569bb0721e40e088 Mon Sep 17 00:00:00 2001 From: Robin Cornelius Date: Sun, 10 Oct 2010 22:10:33 +0100 Subject: Revert "port of LL renderpipeline/Kirstens S19 pipeline for bridging to Viewer 2 texture system" This reverts commit 087e15e89930d51c3964329befb273ae3b2d330d. Conflicts: linden/indra/newview/llsurface.cpp linden/indra/newview/llviewerwindow.cpp linden/indra/newview/llvoavatar.cpp linden/indra/newview/pipeline.cpp linden/indra/newview/pipeline.h --- linden/indra/llmath/llbbox.cpp | 162 -- linden/indra/llmath/llbbox.h | 103 - linden/indra/llmath/llcamera.cpp | 24 - linden/indra/llmath/llcamera.h | 16 +- linden/indra/llmath/llmath.h | 2 +- linden/indra/llmath/llmodularmath.cpp | 36 - linden/indra/llmath/llvolume.cpp | 14 +- linden/indra/llrender/CMakeLists.txt | 5 +- linden/indra/llrender/llcubemap.cpp | 17 +- linden/indra/llrender/llfont.cpp | 2 +- linden/indra/llrender/llfontgl.cpp | 6 +- linden/indra/llrender/llgl.cpp | 8 +- linden/indra/llrender/llgl.h | 31 - linden/indra/llrender/llglslshader.cpp | 2 +- linden/indra/llrender/llimagegl.cpp | 451 ++-- linden/indra/llrender/llimagegl.h | 117 +- linden/indra/llrender/llrender.cpp | 64 +- linden/indra/llrender/llrendertarget.cpp | 57 +- linden/indra/llrender/llrendertarget.h | 1 - linden/indra/llrender/lltextureatlas.cpp | 411 --- linden/indra/llrender/lltextureatlas.h | 92 - linden/indra/llrender/llvertexbuffer.cpp | 72 +- linden/indra/newview/CMakeLists.txt | 4 - linden/indra/newview/app_settings/settings.xml | 701 +---- .../shaders/class1/deferred/alphaF.glsl | 24 +- .../shaders/class1/deferred/alphaV.glsl | 10 +- .../shaders/class1/deferred/avatarAlphaF.glsl | 2 +- .../shaders/class1/deferred/avatarF.glsl | 13 +- .../shaders/class1/deferred/avatarShadowF.glsl | 3 +- .../shaders/class1/deferred/avatarShadowV.glsl | 3 +- .../shaders/class1/deferred/avatarV.glsl | 2 + .../shaders/class1/deferred/blurLightF.glsl | 41 +- .../shaders/class1/deferred/bumpF.glsl | 8 +- .../shaders/class1/deferred/bumpV.glsl | 3 + .../shaders/class1/deferred/diffuseF.glsl | 6 +- .../shaders/class1/deferred/diffuseV.glsl | 5 +- .../shaders/class1/deferred/fullbrightF.glsl | 28 +- .../shaders/class1/deferred/fullbrightV.glsl | 2 +- .../app_settings/shaders/class1/deferred/giF.glsl | 165 -- .../app_settings/shaders/class1/deferred/giV.glsl | 22 - .../shaders/class1/deferred/luminanceF.glsl | 15 - .../shaders/class1/deferred/luminanceV.glsl | 20 - .../shaders/class1/deferred/multiPointLightF.glsl | 62 +- .../shaders/class1/deferred/multiSpotLightF.glsl | 184 -- .../shaders/class1/deferred/pointLightF.glsl | 61 +- .../shaders/class1/deferred/pointLightV.glsl | 6 +- .../shaders/class1/deferred/postDeferredF.glsl | 57 - .../shaders/class1/deferred/postDeferredV.glsl | 17 - .../shaders/class1/deferred/postgiF.glsl | 107 - .../shaders/class1/deferred/postgiV.glsl | 16 - .../shaders/class1/deferred/shadowF.glsl | 3 - .../shaders/class1/deferred/shadowV.glsl | 10 +- .../shaders/class1/deferred/softenLightF.glsl | 4 + .../shaders/class1/deferred/spotLightF.glsl | 199 -- .../shaders/class1/deferred/sunLightF.glsl | 111 +- .../shaders/class1/deferred/terrainF.glsl | 6 +- .../shaders/class1/deferred/terrainV.glsl | 2 + .../shaders/class1/deferred/treeF.glsl | 4 +- .../shaders/class1/deferred/treeV.glsl | 3 + .../shaders/class1/deferred/waterF.glsl | 2 +- .../shaders/class1/effects/colorFilterF.glsl | 31 - .../shaders/class1/effects/drawQuadV.glsl | 14 - .../shaders/class1/effects/nightVisionF.glsl | 42 - .../shaders/class2/deferred/alphaF.glsl | 112 - .../shaders/class2/deferred/alphaV.glsl | 75 - .../shaders/class2/deferred/avatarAlphaF.glsl | 77 - .../shaders/class2/deferred/avatarAlphaV.glsl | 78 - .../shaders/class2/deferred/blurLightF.glsl | 71 - .../shaders/class2/deferred/blurLightV.glsl | 17 - .../shaders/class2/deferred/multiSpotLightF.glsl | 188 -- .../shaders/class2/deferred/postDeferredF.glsl | 59 - .../shaders/class2/deferred/postDeferredV.glsl | 17 - .../shaders/class2/deferred/softenLightF.glsl | 294 --- .../shaders/class2/deferred/softenLightV.glsl | 24 - .../shaders/class2/deferred/spotLightF.glsl | 199 -- .../shaders/class2/deferred/sunLightF.glsl | 203 -- .../shaders/class2/deferred/sunLightV.glsl | 25 - .../shaders/class2/deferred/waterF.glsl | 139 - .../shaders/class2/deferred/waterV.glsl | 76 - .../shaders/class3/deferred/avatarF.glsl | 18 - .../shaders/class3/deferred/bumpF.glsl | 27 - .../shaders/class3/deferred/diffuseF.glsl | 18 - .../shaders/class3/deferred/giDownsampleF.glsl | 84 - .../shaders/class3/deferred/giDownsampleV.glsl | 17 - .../app_settings/shaders/class3/deferred/giF.glsl | 219 -- .../app_settings/shaders/class3/deferred/giV.glsl | 22 - .../shaders/class3/deferred/luminanceF.glsl | 16 - .../shaders/class3/deferred/luminanceV.glsl | 20 - .../shaders/class3/deferred/postDeferredF.glsl | 76 - .../shaders/class3/deferred/postDeferredV.glsl | 17 - .../shaders/class3/deferred/postgiF.glsl | 87 - .../shaders/class3/deferred/postgiV.glsl | 17 - .../shaders/class3/deferred/softenLightF.glsl | 312 --- .../shaders/class3/deferred/softenLightV.glsl | 24 - .../shaders/class3/deferred/treeF.glsl | 18 - .../shaders/class3/deferred/waterF.glsl | 139 - .../app_settings/shaders/class3/effects/blurF.glsl | 31 - .../app_settings/shaders/class3/effects/blurV.glsl | 35 - .../shaders/class3/effects/colorFilterF.glsl | 31 - .../shaders/class3/effects/drawQuadV.glsl | 14 - .../shaders/class3/effects/extractF.glsl | 22 - .../shaders/class3/effects/nightVisionF.glsl | 42 - .../shaders/class3/effects/simpleF.glsl | 14 - linden/indra/newview/llagent.cpp | 3 +- linden/indra/newview/llagent.h | 1 - linden/indra/newview/llappviewer.cpp | 2 +- linden/indra/newview/llcolorswatch.cpp | 3 +- linden/indra/newview/llcompilequeue.cpp | 1 + linden/indra/newview/llconsole.cpp | 166 +- linden/indra/newview/llconsole.h | 47 +- linden/indra/newview/lldebugview.cpp | 24 +- linden/indra/newview/lldrawable.cpp | 76 +- linden/indra/newview/lldrawable.h | 3 +- linden/indra/newview/lldrawpool.h | 5 - linden/indra/newview/lldrawpoolalpha.cpp | 59 +- linden/indra/newview/lldrawpoolavatar.cpp | 69 +- linden/indra/newview/lldrawpoolbump.cpp | 25 +- linden/indra/newview/lldrawpoolsky.cpp | 68 +- linden/indra/newview/lldrawpoolsky.h | 4 - linden/indra/newview/lldrawpoolterrain.cpp | 6 +- linden/indra/newview/lldrawpooltree.cpp | 15 +- linden/indra/newview/lldrawpoolwater.cpp | 20 +- linden/indra/newview/lldynamictexture.cpp | 21 +- linden/indra/newview/lldynamictexture.h | 4 +- linden/indra/newview/llface.cpp | 445 ++-- linden/indra/newview/llface.h | 38 +- linden/indra/newview/llfloaterassetbrowser.cpp | 16 +- linden/indra/newview/llfloaterchat.cpp | 3 +- linden/indra/newview/llfloaterhardwaresettings.cpp | 27 +- linden/indra/newview/llfloaterhardwaresettings.h | 4 - linden/indra/newview/llfloaterlagmeter.cpp | 2 +- linden/indra/newview/llfloaterpostprocess.cpp | 66 +- linden/indra/newview/llfloaterreporter.cpp | 3 +- linden/indra/newview/llhudeffect.cpp | 2 +- linden/indra/newview/llhudtext.cpp | 2 - linden/indra/newview/llmanip.cpp | 2 +- linden/indra/newview/llmaniptranslate.h | 2 +- linden/indra/newview/llmediactrl.cpp | 3 +- linden/indra/newview/lloverlaybar.cpp | 1 + linden/indra/newview/llpanelvolume.cpp | 117 - linden/indra/newview/llpanelvolume.h | 5 - linden/indra/newview/llpostprocess.cpp | 594 ----- linden/indra/newview/llpostprocess.h | 274 -- linden/indra/newview/llpreview.cpp | 1 - linden/indra/newview/llselectmgr.cpp | 22 +- linden/indra/newview/llselectmgr.h | 2 +- linden/indra/newview/llsky.cpp | 14 - linden/indra/newview/llspatialpartition.cpp | 390 +-- linden/indra/newview/llspatialpartition.h | 62 +- linden/indra/newview/llstartup.cpp | 2 +- linden/indra/newview/llsurface.cpp | 17 +- linden/indra/newview/llsurfacepatch.cpp | 34 +- linden/indra/newview/llsurfacepatch.h | 1 - linden/indra/newview/lltexlayer.cpp | 26 +- linden/indra/newview/lltexlayer.h | 4 +- linden/indra/newview/lltextureatlasmanager.cpp | 274 -- linden/indra/newview/lltextureatlasmanager.h | 112 - linden/indra/newview/lltextureview.cpp | 238 +- linden/indra/newview/lltoolpie.h | 1 + linden/indra/newview/llviewercamera.cpp | 4 +- linden/indra/newview/llviewercontrol.cpp | 16 +- linden/indra/newview/llviewerdisplay.cpp | 27 +- linden/indra/newview/llviewerimage.cpp | 367 +-- linden/indra/newview/llviewerimage.h | 31 +- linden/indra/newview/llviewerimagelist.cpp | 50 +- linden/indra/newview/llviewerimagelist.h | 4 +- linden/indra/newview/llviewerjointmesh.cpp | 10 +- linden/indra/newview/llviewermedia.cpp | 4 +- linden/indra/newview/llviewermenu.cpp | 20 +- linden/indra/newview/llviewerobject.cpp | 35 +- linden/indra/newview/llviewerobject.h | 11 +- linden/indra/newview/llviewerobjectlist.cpp | 2 +- linden/indra/newview/llviewerobjectlist.h | 1 + linden/indra/newview/llviewerparceloverlay.cpp | 4 +- linden/indra/newview/llviewershadermgr.cpp | 106 +- linden/indra/newview/llviewershadermgr.h | 25 - linden/indra/newview/llviewerstats.h | 2 +- linden/indra/newview/llviewerwindow.cpp | 60 +- linden/indra/newview/llvlcomposition.cpp | 4 - linden/indra/newview/llvoavatar.cpp | 98 +- linden/indra/newview/llvoavatar.h | 10 +- linden/indra/newview/llvoclouds.cpp | 7 +- linden/indra/newview/llvoclouds.h | 2 +- linden/indra/newview/llvograss.cpp | 2 +- linden/indra/newview/llvograss.h | 2 +- linden/indra/newview/llvoground.cpp | 2 +- linden/indra/newview/llvoground.h | 2 +- linden/indra/newview/llvopartgroup.cpp | 20 +- linden/indra/newview/llvopartgroup.h | 2 +- linden/indra/newview/llvosky.cpp | 8 +- linden/indra/newview/llvosky.h | 2 +- linden/indra/newview/llvosurfacepatch.cpp | 18 +- linden/indra/newview/llvosurfacepatch.h | 3 +- linden/indra/newview/llvotextbubble.cpp | 2 +- linden/indra/newview/llvotextbubble.h | 2 +- linden/indra/newview/llvotree.cpp | 6 +- linden/indra/newview/llvotree.h | 2 +- linden/indra/newview/llvotreenew.h | 2 +- linden/indra/newview/llvovolume.cpp | 422 +-- linden/indra/newview/llvovolume.h | 23 +- linden/indra/newview/llvowater.cpp | 6 +- linden/indra/newview/llvowater.h | 2 +- linden/indra/newview/llwaterparammanager.cpp | 3 +- linden/indra/newview/llwlparammanager.cpp | 3 +- linden/indra/newview/llworld.h | 6 +- linden/indra/newview/pipeline.cpp | 2779 +++----------------- linden/indra/newview/pipeline.h | 100 +- .../xui/en-us/floater_hardware_settings.xml | 30 +- .../skins/default/xui/en-us/floater_tools.xml | 44 +- 209 files changed, 2040 insertions(+), 12466 deletions(-) delete mode 100644 linden/indra/llmath/llbbox.cpp delete mode 100644 linden/indra/llmath/llbbox.h delete mode 100644 linden/indra/llmath/llmodularmath.cpp delete mode 100644 linden/indra/llrender/lltextureatlas.cpp delete mode 100644 linden/indra/llrender/lltextureatlas.h delete mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/giF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/giV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class1/effects/drawQuadV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class1/effects/nightVisionF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class2/deferred/waterV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/avatarF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/bumpF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/diffuseF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/giF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/giV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/blurF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/blurV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/colorFilterF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/drawQuadV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/extractF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/nightVisionF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/effects/simpleF.glsl delete mode 100644 linden/indra/newview/llpostprocess.cpp delete mode 100644 linden/indra/newview/llpostprocess.h delete mode 100644 linden/indra/newview/lltextureatlasmanager.cpp delete mode 100644 linden/indra/newview/lltextureatlasmanager.h (limited to 'linden') diff --git a/linden/indra/llmath/llbbox.cpp b/linden/indra/llmath/llbbox.cpp deleted file mode 100644 index f0ec010..0000000 --- a/linden/indra/llmath/llbbox.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/** - * @file llbbox.cpp - * @brief General purpose bounding box class (Not axis aligned) - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2010, /linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by /linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and /linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL /linden LAB SOURCE CODE IS PROVIDED "AS IS." /linden LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -// self include -#include "llbbox.h" - -// library includes -#include "m4math.h" - -void LLBBox::addPointLocal(const LLVector3& p) -{ - if (mEmpty) - { - mMinLocal = p; - mMaxLocal = p; - mEmpty = FALSE; - } - else - { - mMinLocal.mV[VX] = llmin( p.mV[VX], mMinLocal.mV[VX] ); - mMinLocal.mV[VY] = llmin( p.mV[VY], mMinLocal.mV[VY] ); - mMinLocal.mV[VZ] = llmin( p.mV[VZ], mMinLocal.mV[VZ] ); - mMaxLocal.mV[VX] = llmax( p.mV[VX], mMaxLocal.mV[VX] ); - mMaxLocal.mV[VY] = llmax( p.mV[VY], mMaxLocal.mV[VY] ); - mMaxLocal.mV[VZ] = llmax( p.mV[VZ], mMaxLocal.mV[VZ] ); - } -} - -void LLBBox::addPointAgent( LLVector3 p) -{ - p -= mPosAgent; - p.rotVec( ~mRotation ); - addPointLocal( p ); -} - - -void LLBBox::addBBoxAgent(const LLBBox& b) -{ - if (mEmpty) - { - mPosAgent = b.mPosAgent; - mRotation = b.mRotation; - mMinLocal.clearVec(); - mMaxLocal.clearVec(); - } - LLVector3 vertex[8]; - vertex[0].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] ); - vertex[1].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] ); - vertex[2].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] ); - vertex[3].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] ); - vertex[4].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] ); - vertex[5].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] ); - vertex[6].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] ); - vertex[7].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] ); - - LLMatrix4 m( b.mRotation ); - m.translate( b.mPosAgent ); - m.translate( -mPosAgent ); - m.rotate( ~mRotation ); - - for( S32 i=0; i<8; i++ ) - { - addPointLocal( vertex[i] * m ); - } -} - - -void LLBBox::expand( F32 delta ) -{ - mMinLocal.mV[VX] -= delta; - mMinLocal.mV[VY] -= delta; - mMinLocal.mV[VZ] -= delta; - mMaxLocal.mV[VX] += delta; - mMaxLocal.mV[VY] += delta; - mMaxLocal.mV[VZ] += delta; -} - -LLVector3 LLBBox::localToAgent(const LLVector3& v) const -{ - LLMatrix4 m( mRotation ); - m.translate( mPosAgent ); - return v * m; -} - -LLVector3 LLBBox::agentToLocal(const LLVector3& v) const -{ - LLMatrix4 m; - m.translate( -mPosAgent ); - m.rotate( ~mRotation ); // inverse rotation - return v * m; -} - -LLVector3 LLBBox::localToAgentBasis(const LLVector3& v) const -{ - LLMatrix4 m( mRotation ); - return v * m; -} - -LLVector3 LLBBox::agentToLocalBasis(const LLVector3& v) const -{ - LLMatrix4 m( ~mRotation ); // inverse rotation - return v * m; -} - -BOOL LLBBox::containsPointLocal(const LLVector3& p) const -{ - if ( (p.mV[VX] < mMinLocal.mV[VX]) - ||(p.mV[VX] > mMaxLocal.mV[VX]) - ||(p.mV[VY] < mMinLocal.mV[VY]) - ||(p.mV[VY] > mMaxLocal.mV[VY]) - ||(p.mV[VZ] < mMinLocal.mV[VZ]) - ||(p.mV[VZ] > mMaxLocal.mV[VZ])) - { - return FALSE; - } - return TRUE; -} - -BOOL LLBBox::containsPointAgent(const LLVector3& p) const -{ - LLVector3 point_local = agentToLocal(p); - return containsPointLocal(point_local); -} - - -/* -LLBBox operator*(const LLBBox &a, const LLMatrix4 &b) -{ - return LLBBox( a.mMin * b, a.mMax * b ); -} -*/ diff --git a/linden/indra/llmath/llbbox.h b/linden/indra/llmath/llbbox.h deleted file mode 100644 index 3559284..0000000 --- a/linden/indra/llmath/llbbox.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @file llbbox.h - * @brief General purpose bounding box class - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2010, /linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by /linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and /linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL /linden LAB SOURCE CODE IS PROVIDED "AS IS." /linden LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_BBOX_H -#define LL_BBOX_H - -#include "v3math.h" -#include "llquaternion.h" - -// Note: "local space" for an LLBBox is defined relative to agent space in terms of -// a translation followed by a rotation. There is no scale term since the LLBBox's min and -// max are not necessarily symetrical and define their own extents. - -class LLBBox -{ -public: - LLBBox() {mEmpty = TRUE;} - LLBBox( const LLVector3& pos_agent, - const LLQuaternion& rot, - const LLVector3& min_local, - const LLVector3& max_local ) - : - mMinLocal( min_local ), mMaxLocal( max_local ), mPosAgent(pos_agent), mRotation( rot), mEmpty( TRUE ) - {} - - // Default copy constructor is OK. - - const LLVector3& getPositionAgent() const { return mPosAgent; } - const LLQuaternion& getRotation() const { return mRotation; } - - const LLVector3& getMinLocal() const { return mMinLocal; } - void setMinLocal( const LLVector3& min ) { mMinLocal = min; } - - const LLVector3& getMaxLocal() const { return mMaxLocal; } - void setMaxLocal( const LLVector3& max ) { mMaxLocal = max; } - - LLVector3 getCenterLocal() const { return (mMaxLocal - mMinLocal) * 0.5f + mMinLocal; } - LLVector3 getCenterAgent() const { return localToAgent( getCenterLocal() ); } - - LLVector3 getExtentLocal() const { return mMaxLocal - mMinLocal; } - - BOOL containsPointLocal(const LLVector3& p) const; - BOOL containsPointAgent(const LLVector3& p) const; - - void addPointAgent(LLVector3 p); - void addBBoxAgent(const LLBBox& b); - - void addPointLocal(const LLVector3& p); - void addBBoxLocal(const LLBBox& b) { addPointLocal( b.mMinLocal ); addPointLocal( b.mMaxLocal ); } - - void expand( F32 delta ); - - LLVector3 localToAgent( const LLVector3& v ) const; - LLVector3 agentToLocal( const LLVector3& v ) const; - - // Changes rotation but not position - LLVector3 localToAgentBasis(const LLVector3& v) const; - LLVector3 agentToLocalBasis(const LLVector3& v) const; - - -// friend LLBBox operator*(const LLBBox& a, const LLMatrix4& b); - -private: - LLVector3 mMinLocal; - LLVector3 mMaxLocal; - LLVector3 mPosAgent; // Position relative to Agent's Region - LLQuaternion mRotation; - BOOL mEmpty; // Nothing has been added to this bbox yet -}; - -//LLBBox operator*(const LLBBox &a, const LLMatrix4 &b); - - -#endif // LL_BBOX_H diff --git a/linden/indra/llmath/llcamera.cpp b/linden/indra/llmath/llcamera.cpp index 9c37fcf..e6b6797 100644 --- a/linden/indra/llmath/llcamera.cpp +++ b/linden/indra/llmath/llcamera.cpp @@ -246,10 +246,6 @@ S32 LLCamera::AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius) for (U32 i = 0; i < mPlaneCount; i++) { mask = mAgentPlanes[i].mask; - if (mask == 0xff) - { - continue; - } LLPlane p = mAgentPlanes[i].p; LLVector3 n = LLVector3(p); float d = p.mV[3]; @@ -298,10 +294,6 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector3 ¢er, const LLVector3& r } mask = mAgentPlanes[i].mask; - if (mask == 0xff) - { - continue; - } LLPlane p = mAgentPlanes[i].p; LLVector3 n = LLVector3(p); float d = p.mV[3]; @@ -445,11 +437,6 @@ int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius) int res = 2; for (int i = 0; i < 6; i++) { - if (mAgentPlanes[i].mask == 0xff) - { - continue; - } - float d = mAgentPlanes[i].p.dist(sphere_center); if (d > radius) @@ -635,17 +622,6 @@ U8 LLCamera::calcPlaneMask(const LLPlane& plane) return mask; } -void LLCamera::ignoreAgentFrustumPlane(S32 idx) -{ - if (idx < 0 || idx > (S32) mPlaneCount) - { - return; - } - - mAgentPlanes[idx].mask = 0xff; - mAgentPlanes[idx].p.clearVec(); -} - void LLCamera::calcAgentFrustumPlanes(LLVector3* frust) { diff --git a/linden/indra/llmath/llcamera.h b/linden/indra/llmath/llcamera.h index 8d3ad08..85b93df 100644 --- a/linden/indra/llmath/llcamera.h +++ b/linden/indra/llmath/llcamera.h @@ -84,17 +84,6 @@ public: PLANE_TOP_MASK = (1<<PLANE_TOP), PLANE_ALL_MASK = 0xf }; - - enum - { - AGENT_PLANE_LEFT = 0, - AGENT_PLANE_RIGHT, - AGENT_PLANE_NEAR, - AGENT_PLANE_BOTTOM, - AGENT_PLANE_TOP, - AGENT_PLANE_FAR, - }; - enum { HORIZ_PLANE_LEFT = 0, HORIZ_PLANE_RIGHT = 1, @@ -134,8 +123,7 @@ private: public: LLVector3 mAgentFrustum[8]; //8 corners of 6-plane frustum F32 mFrustumCornerDist; //distance to corner of frustum against far clip plane - LLPlane getAgentPlane(U32 idx) { return mAgentPlanes[idx].p; } - + public: LLCamera(); LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane); @@ -182,8 +170,6 @@ public: // Return number of bytes copied. size_t readFrustumFromBuffer(const char *buffer); void calcAgentFrustumPlanes(LLVector3* frust); - void ignoreAgentFrustumPlane(S32 idx); - // Returns 1 if partly in, 2 if fully in. // NOTE: 'center' is in absolute frame. S32 sphereInFrustumOld(const LLVector3 ¢er, const F32 radius) const; diff --git a/linden/indra/llmath/llmath.h b/linden/indra/llmath/llmath.h index ec1076d..0de568c 100644 --- a/linden/indra/llmath/llmath.h +++ b/linden/indra/llmath/llmath.h @@ -203,7 +203,7 @@ inline S32 llfloor( F32 f ) } return result; #else - return (S32)floorf(f); + return (S32)floor(f); #endif } diff --git a/linden/indra/llmath/llmodularmath.cpp b/linden/indra/llmath/llmodularmath.cpp deleted file mode 100644 index f0afeb7..0000000 --- a/linden/indra/llmath/llmodularmath.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @file llmodularmath.cpp - * @brief LLModularMath class implementation - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2010, /linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by /linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and /linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL /linden LAB SOURCE CODE IS PROVIDED "AS IS." /linden LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes. -#include "llmodularmath.h" diff --git a/linden/indra/llmath/llvolume.cpp b/linden/indra/llmath/llvolume.cpp index a1d891a..b0b8a94 100644 --- a/linden/indra/llmath/llvolume.cpp +++ b/linden/indra/llmath/llvolume.cpp @@ -2208,10 +2208,16 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, S32 requested_sizeS = 0; S32 requested_sizeT = 0; - sculpt_calc_mesh_resolution(sculpt_width, sculpt_height, sculpt_type, mDetail, requested_sizeS, requested_sizeT); + // create oblong sculpties with high LOD always + F32 sculpt_detail = mDetail; + if (sculpt_width != sculpt_height && sculpt_detail < 4.0) + { + sculpt_detail = 4.0; + } + sculpt_calc_mesh_resolution(sculpt_width, sculpt_height, sculpt_type, sculpt_detail, requested_sizeS, requested_sizeT); - mPathp->generate(mParams.getPathParams(), mDetail, 0, TRUE, requested_sizeS); - mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), mDetail, 0, TRUE, requested_sizeT); + mPathp->generate(mParams.getPathParams(), sculpt_detail, 0, TRUE, requested_sizeS); + mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), sculpt_detail, 0, TRUE, requested_sizeT); S32 sizeS = mPathp->mPath.size(); // we requested a specific size, now see what we really got S32 sizeT = mProfilep->mProfile.size(); // we requested a specific size, now see what we really got @@ -4268,7 +4274,7 @@ LLFaceID LLVolume::generateFaceMask() } break; default: - llerrs << "Unknown profile!" << llendl; + llerrs << "Unknown profile!" << llendl break; } diff --git a/linden/indra/llrender/CMakeLists.txt b/linden/indra/llrender/CMakeLists.txt index 3ba841e..0bdb55f 100644 --- a/linden/indra/llrender/CMakeLists.txt +++ b/linden/indra/llrender/CMakeLists.txt @@ -32,9 +32,9 @@ set(llrender_SOURCE_FILES llgldbg.cpp llglslshader.cpp llimagegl.cpp + llpostprocess.cpp llrendersphere.cpp llshadermgr.cpp - lltextureatlas.cpp llvertexbuffer.cpp ) @@ -53,10 +53,10 @@ set(llrender_HEADER_FILES llglstates.h llgltypes.h llimagegl.h + llpostprocess.h llrender.h llrendersphere.h llshadermgr.h - lltextureatlas.h llvertexbuffer.h ) @@ -81,7 +81,6 @@ if (SERVER AND NOT WINDOWS AND NOT DARWIN) ${llrender_SOURCE_FILES} ${server_SOURCE_FILES} ) - add_dependencies(llrenderheadless prepare) else (SERVER AND NOT WINDOWS AND NOT DARWIN) list(APPEND llrender_SOURCE_FILES llgl.cpp diff --git a/linden/indra/llrender/llcubemap.cpp b/linden/indra/llrender/llcubemap.cpp index e0923e4..a5c677d 100644 --- a/linden/indra/llrender/llcubemap.cpp +++ b/linden/indra/llrender/llcubemap.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2002&license=viewergpl$ * - * Copyright (c) 2002-2010, Linden Research, Inc. + * Copyright (c) 2002-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -63,12 +63,6 @@ LLCubeMap::LLCubeMap() mTextureCoordStage(0), mMatrixStage(0) { - mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB; - mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; - mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB; - mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB; - mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB; - mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB; } LLCubeMap::~LLCubeMap() @@ -81,6 +75,13 @@ void LLCubeMap::initGL() if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) { + mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB; + mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; + mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB; + mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB; + mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB; + mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB; + // Not initialized, do stuff. if (mImages[0].isNull()) { @@ -93,7 +94,7 @@ void LLCubeMap::initGL() mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE)); mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP); mRawImages[i] = new LLImageRaw(64, 64, 4); - mImages[i]->createGLTexture(0, mRawImages[i], texname); + mImages[i]->createGLTexture(0, mRawImages[i], texname, TRUE); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/linden/indra/llrender/llfont.cpp b/linden/indra/llrender/llfont.cpp index 946f52f..5ee3929 100644 --- a/linden/indra/llrender/llfont.cpp +++ b/linden/indra/llrender/llfont.cpp @@ -81,7 +81,7 @@ LLFontManager::LLFontManager() if (error) { // Clean up freetype libs. - llwarns << "Freetype initialization failure!" << llendl; + llerrs << "Freetype initialization failure!" << llendl; FT_Done_FreeType(gFTLibrary); } } diff --git a/linden/indra/llrender/llfontgl.cpp b/linden/indra/llrender/llfontgl.cpp index 9d1f1d4..5d3d6a7 100644 --- a/linden/indra/llrender/llfontgl.cpp +++ b/linden/indra/llrender/llfontgl.cpp @@ -121,7 +121,7 @@ LLFontGL::LLFontGL() LLFontGL::LLFontGL(const LLFontGL &source) { - llwarns << "Not implemented!" << llendl; + llerrs << "Not implemented!" << llendl; } LLFontGL::~LLFontGL() @@ -278,7 +278,7 @@ void LLFontGL::destroyGL() LLFontGL &LLFontGL::operator=(const LLFontGL &source) { - llwarns << "Not implemented" << llendl; + llerrs << "Not implemented" << llendl; return *this; } @@ -584,7 +584,7 @@ S32 LLFontGL::render(const LLWString &wstr, const LLFontGlyphInfo* fgi= getGlyphInfo(wch); if (!fgi) { - llwarns << "Missing Glyph Info" << llendl; + llerrs << "Missing Glyph Info" << llendl; break; } // Per-glyph bitmap texture. diff --git a/linden/indra/llrender/llgl.cpp b/linden/indra/llrender/llgl.cpp index d73f7b6..2e9b2bd 100644 --- a/linden/indra/llrender/llgl.cpp +++ b/linden/indra/llrender/llgl.cpp @@ -59,13 +59,11 @@ BOOL gDebugGL = FALSE; BOOL gClothRipple = FALSE; BOOL gNoRender = FALSE; -BOOL gGLActive = FALSE; LLMatrix4 gGLObliqueProjectionInverse; #define LL_GL_NAME_POOLING 0 LLGLNamePool::pool_list_t LLGLNamePool::sInstances; -std::list<LLGLUpdate*> LLGLUpdate::sGLQ; #if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS // ATI prototypes @@ -1011,7 +1009,7 @@ void assert_glerror() if (quit) { - llwarns << "One or more unhandled GL errors." << llendl; + llerrs << "One or more unhandled GL errors." << llendl; } } @@ -1705,11 +1703,11 @@ void LLGLNamePool::release(GLuint name) } else { - llwarns << "Attempted to release a pooled name that is not in use!" << llendl; + llerrs << "Attempted to release a pooled name that is not in use!" << llendl; } } } - llwarns << "Attempted to release a non pooled name!" << llendl; + llerrs << "Attempted to release a non pooled name!" << llendl; #else releaseName(name); #endif diff --git a/linden/indra/llrender/llgl.h b/linden/indra/llrender/llgl.h index 90642b3..cc7ebff 100644 --- a/linden/indra/llrender/llgl.h +++ b/linden/indra/llrender/llgl.h @@ -359,35 +359,6 @@ protected: virtual void releaseName(GLuint name) = 0; }; -/* - Interface for objects that need periodic GL updates applied to them. - Used to synchronize GL updates with GL thread. -*/ -class LLGLUpdate -{ -public: - - static std::list<LLGLUpdate*> sGLQ; - - BOOL mInQ; - LLGLUpdate() - : mInQ(FALSE) - { - } - virtual ~LLGLUpdate() - { - if (mInQ) - { - std::list<LLGLUpdate*>::iterator iter = std::find(sGLQ.begin(), sGLQ.end(), this); - if (iter != sGLQ.end()) - { - sGLQ.erase(iter); - } - } - } - virtual void updateGL() = 0; -}; - extern LLMatrix4 gGLObliqueProjectionInverse; #include "llglstates.h" @@ -406,6 +377,4 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor extern BOOL gClothRipple; extern BOOL gNoRender; -extern BOOL gGLActive; - #endif // LL_LLGL_H diff --git a/linden/indra/llrender/llglslshader.cpp b/linden/indra/llrender/llglslshader.cpp index 18974a7..08d6548 100644 --- a/linden/indra/llrender/llglslshader.cpp +++ b/linden/indra/llrender/llglslshader.cpp @@ -408,7 +408,7 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode) { if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode) { - llwarns << "Texture channel " << index << " texture type corrupted." << llendl; + llerrs << "Texture channel " << index << " texture type corrupted." << llendl; } gGL.getTexUnit(index)->disable(); } diff --git a/linden/indra/llrender/llimagegl.cpp b/linden/indra/llrender/llimagegl.cpp index 1bddd49..7cd4dd7 100644 --- a/linden/indra/llrender/llimagegl.cpp +++ b/linden/indra/llrender/llimagegl.cpp @@ -43,8 +43,6 @@ #include "llmath.h" #include "llgl.h" #include "llrender.h" -#include "lltextureatlas.h" - //---------------------------------------------------------------------------- const F32 MIN_TEXTURE_LIFETIME = 10.f; @@ -58,17 +56,19 @@ S32 LLImageGL::sGlobalTextureMemoryInBytes = 0; S32 LLImageGL::sBoundTextureMemoryInBytes = 0; S32 LLImageGL::sCurBoundTextureMemory = 0; S32 LLImageGL::sCount = 0; -std::list<U32> LLImageGL::sDeadTextureList; BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; F32 LLImageGL::sLastFrameTime = 0.f; -BOOL LLImageGL::sUseTextureAtlas = FALSE ; // render-pipeline KL +BOOL LLImageGL::sAllowReadBackRaw = FALSE ; std::set<LLImageGL*> LLImageGL::sImageList; -#if !LL_RELEASE_FOR_DOWNLOAD +//**************************************************************************************************** +//The below for texture auditing use only +//**************************************************************************************************** //----------------------- //debug use +BOOL gAuditTexture = FALSE ; #define MAX_TEXTURE_LOG_SIZE 22 //2048 * 2048 std::vector<S32> LLImageGL::sTextureLoadedCounter(MAX_TEXTURE_LOG_SIZE + 1) ; std::vector<S32> LLImageGL::sTextureBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ; @@ -76,8 +76,15 @@ std::vector<S32> LLImageGL::sTextureCurBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ; S32 LLImageGL::sCurTexSizeBar = -1 ; S32 LLImageGL::sCurTexPickSize = -1 ; LLPointer<LLImageGL> LLImageGL::sDefaultTexturep = NULL; +S32 LLImageGL::sMaxCatagories = 1 ; + +std::vector<S32> LLImageGL::sTextureMemByCategory; +std::vector<S32> LLImageGL::sTextureMemByCategoryBound ; +std::vector<S32> LLImageGL::sTextureCurMemByCategoryBound ; //------------------------ -#endif +//**************************************************************************************************** +//End for texture auditing use only +//**************************************************************************************************** //************************************************************************************** //below are functions for debug use @@ -103,12 +110,9 @@ void LLImageGL::checkTexSize() const { GLint texname; glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname); - BOOL error = FALSE; if (texname != mTexName) { - - llwarns << "Invalid texture bound!" << llendl; - + llerrs << "Invalid texture bound!" << llendl; } stop_glerror() ; LLGLint x = 0, y = 0 ; @@ -121,15 +125,7 @@ void LLImageGL::checkTexSize() const } if(x != (mWidth >> mCurrentDiscardLevel) || y != (mHeight >> mCurrentDiscardLevel)) { - error = TRUE; - - llwarns << "wrong texture size and discard level!" << llendl; - - } - - if (error) - { - llwarns << "LLImageGL::checkTexSize failed." << llendl; + llerrs << "wrong texture size and discard level!" << llendl ; } } } @@ -137,6 +133,20 @@ void LLImageGL::checkTexSize() const //************************************************************************************** //---------------------------------------------------------------------------- +//static +void LLImageGL::initClass(S32 num_catagories) +{ + sMaxCatagories = num_catagories ; + + sTextureMemByCategory.resize(sMaxCatagories); + sTextureMemByCategoryBound.resize(sMaxCatagories) ; + sTextureCurMemByCategoryBound.resize(sMaxCatagories) ; +} + +//static +void LLImageGL::cleanupClass() +{ +} //static S32 LLImageGL::dataFormatBits(S32 dataformat) @@ -155,7 +165,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) case GL_RGBA: return 32; case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac default: - llwarns << "LLImageGL::Unknown format: " << dataformat << llendl; + llerrs << "LLImageGL::Unknown format: " << dataformat << llendl; return 0; } } @@ -190,7 +200,7 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat) case GL_RGBA: return 4; case GL_BGRA: return 4; // Used for QuickTime media textures on the Mac default: - llwarns << "LLImageGL::Unknown format: " << dataformat << llendl; + llerrs << "LLImageGL::Unknown format: " << dataformat << llendl; return 0; } } @@ -204,25 +214,43 @@ void LLImageGL::updateStats(F32 current_time) sBoundTextureMemoryInBytes = sCurBoundTextureMemory; sCurBoundTextureMemory = 0; -#if !LL_RELEASE_FOR_DOWNLOAD - for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++) + if(gAuditTexture) { - sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ; - sTextureCurBoundCounter[i] = 0 ; + for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++) + { + sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ; + sTextureCurBoundCounter[i] = 0 ; + } + for(U32 i = 0 ; i < sTextureCurMemByCategoryBound.size() ; i++) + { + sTextureMemByCategoryBound[i] = sTextureCurMemByCategoryBound[i] ; + sTextureCurMemByCategoryBound[i] = 0 ; + } } -#endif } //static -//#if !LL_RELEASE_FOR_DOWNLOAD -//S32 LLImageGL::updateBoundTexMem(const S32 delta, const S32 size) -//{ -// sTextureCurBoundCounter[getTextureCounterIndex(size)]++ ; -//#else -S32 LLImageGL::updateBoundTexMem(const S32 delta) -{ -//#endif - LLImageGL::sCurBoundTextureMemory += delta; +S32 LLImageGL::updateBoundTexMemStatic(const S32 delta, const S32 size, S32 category) +{ + if(gAuditTexture) + { + sTextureCurBoundCounter[getTextureCounterIndex(size)]++ ; + sTextureCurMemByCategoryBound[category] += delta ; + } + + LLImageGL::sCurBoundTextureMemory += delta ; + return LLImageGL::sCurBoundTextureMemory; +} + +S32 LLImageGL::updateBoundTexMem()const +{ + if(gAuditTexture) + { + sTextureCurBoundCounter[getTextureCounterIndex(mTextureMemory / mComponents)]++ ; + sTextureCurMemByCategoryBound[mCategory] += mTextureMemory ; + } + + LLImageGL::sCurBoundTextureMemory += mTextureMemory ; return LLImageGL::sCurBoundTextureMemory; } @@ -236,6 +264,7 @@ void LLImageGL::destroyGL(BOOL save_state) gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE); } + sAllowReadBackRaw = true ; for (std::set<LLImageGL*>::iterator iter = sImageList.begin(); iter != sImageList.end(); iter++) { @@ -255,7 +284,7 @@ void LLImageGL::destroyGL(BOOL save_state) stop_glerror(); } } -// sAllowReadBackRaw = false ; + sAllowReadBackRaw = false ; } //static @@ -267,13 +296,13 @@ void LLImageGL::restoreGL() LLImageGL* glimage = *iter; if(glimage->getTexName()) { - llwarns << "tex name is not 0." << llendl ; + llerrs << "tex name is not 0." << llendl ; } if (glimage->mSaveData.notNull()) { if (glimage->getComponents() && glimage->mSaveData->getComponents()) { - glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData); + glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData, 0, TRUE, glimage->getCategory()); stop_glerror(); } glimage->mSaveData = NULL; // deletes data @@ -355,7 +384,7 @@ void LLImageGL::init(BOOL usemipmaps) mTextureState = NO_DELETE ; mTextureMemory = 0; mLastBindTime = 0.f; - + mTarget = GL_TEXTURE_2D; mBindTarget = LLTexUnit::TT_TEXTURE; mUseMipMaps = usemipmaps; @@ -382,12 +411,9 @@ void LLImageGL::init(BOOL usemipmaps) mHasExplicitFormat = FALSE; mGLTextureCreated = FALSE ; + mIsMask = FALSE; -// mCategory = -1 ; - mCanAddToAtlas = TRUE ; - mDiscardLevelInAtlas = -1 ; - mTexelsInAtlas = 0 ; - mTexelsInGLTexture = 0 ; + mCategory = -1 ; } void LLImageGL::cleanup() @@ -429,7 +455,7 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents) // Check if dimensions are a power of two! if (!checkSize(width,height)) { - llwarns << llformat("Texture has non power of two dimention: %dx%d",width,height) << llendl; + llerrs << llformat("Texture has non power of two dimention: %dx%d",width,height) << llendl; } if (mTexName) @@ -487,6 +513,10 @@ void LLImageGL::dump() } //---------------------------------------------------------------------------- +void LLImageGL::forceUpdateBindStats(void) const +{ + mLastBindTime = sLastFrameTime; +} void LLImageGL::updateBindStats(void) const { @@ -500,12 +530,8 @@ void LLImageGL::updateBindStats(void) const { // we haven't accounted for this texture yet this frame sUniqueCount++; - -//#if !LL_RELEASE_FOR_DOWNLOAD -// updateBoundTexMem(mTextureMemory, getWidth(mCurrentDiscardLevel) * getHeight(mCurrentDiscardLevel)) ; -//#else - updateBoundTexMem(mTextureMemory); -//#endif + + updateBoundTexMem(); mLastBindTime = sLastFrameTime; } } @@ -518,7 +544,7 @@ bool LLImageGL::bindError(const S32 stage) const } //virtual -bool LLImageGL::bindDefaultImage(const S32 stage) const +bool LLImageGL::bindDefaultImage(const S32 stage) { return false; } @@ -557,7 +583,6 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { // LLFastTimer t1(LLFastTimer::FTM_TEMP1); - llpushcallstacks ; bool is_compressed = false; if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) { @@ -565,7 +590,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } // LLFastTimer t2(LLFastTimer::FTM_TEMP2); - llverify(gGL.getTexUnit(0)->bind(this, false, true)); + gGL.getTexUnit(0)->bind(this); if (mUseMipMaps) { @@ -728,7 +753,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } else { - llwarns << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << llendl; + llerrs << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << llendl; } mHasMipMaps = true; } @@ -770,63 +795,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } stop_glerror(); mGLTextureCreated = true; - llpushcallstacks ; -} - -BOOL LLImageGL::canAddToAtlas() -{ - return sUseTextureAtlas && mCanAddToAtlas ; -} - -BOOL LLImageGL::addToAtlas(const LLImageRaw* raw_image, LLTextureAtlas* atlasp, S16 slot_col, S16 slot_row) -{ - if(!atlasp) - { - return FALSE ; - } - - preAddToAtlas(raw_image->getWidth()) ; - LLGLuint tex_name = atlasp->insertSubTexture(raw_image, slot_col, slot_row); - postAddToAtlas() ; - - if(tex_name > 0) //successfully added to atlas - { - //gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); - //gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); - gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); - return TRUE ; - } - - return FALSE ; -} - -void LLImageGL::preAddToAtlas(S32 data_width) -{ - glPixelStorei(GL_UNPACK_ROW_LENGTH, data_width); - stop_glerror(); - - if(mFormatSwapBytes) - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); - stop_glerror(); - } } -void LLImageGL::postAddToAtlas() +BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) { - if(mFormatSwapBytes) - { - glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); - stop_glerror(); - } - - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - stop_glerror(); -} - -BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) -{ - llpushcallstacks ; if (!width || !height) { return TRUE; @@ -842,7 +814,8 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 return FALSE; } - if (x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height) + // HACK: allow the caller to explicitly force the fast path (i.e. using glTexSubImage2D here instead of calling setImage) even when updating the full texture. + if (!force_fast_update && x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height) { setImage(datap, FALSE); } @@ -851,7 +824,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 if (mUseMipMaps) { dump(); - llwarns << "setSubImage called with mipmapped image (not supported)" << llendl; + llerrs << "setSubImage called with mipmapped image (not supported)" << llendl; } llassert_always(mCurrentDiscardLevel == 0); llassert_always(x_pos >= 0 && y_pos >= 0); @@ -860,7 +833,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 (y_pos + height) > getHeight()) { dump(); - llwarns << "Subimage not wholly in target image!" + llerrs << "Subimage not wholly in target image!" << " x_pos " << x_pos << " y_pos " << y_pos << " width " << width @@ -874,7 +847,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 (y_pos + height) > data_height) { dump(); - llwarns << "Subimage not wholly in source image!" + llerrs << "Subimage not wholly in source image!" << " x_pos " << x_pos << " y_pos " << y_pos << " width " << width @@ -897,7 +870,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 datap += (y_pos * data_width + x_pos) * getComponents(); // Update the GL texture BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName); - if (!res) llwarns << "LLImageGL::setSubImage(): bindTexture failed" << llendl; + if (!res) llerrs << "LLImageGL::setSubImage(): bindTexture failed" << llendl; stop_glerror(); glTexSubImage2D(mTarget, 0, x_pos, y_pos, @@ -915,13 +888,12 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 stop_glerror(); mGLTextureCreated = true; } - llpushcallstacks ; return TRUE; } -BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height) +BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) { - return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height); + return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update); } // Copy sub image from frame buffer @@ -929,6 +901,7 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ { if (gGL.getTexUnit(0)->bind(this, false, true)) { + //checkTexSize() ; glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height); mGLTextureCreated = true; stop_glerror(); @@ -949,17 +922,13 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures) // static void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) { - for (S32 i = 0; i < numTextures; i++) - { - sDeadTextureList.push_back(textures[i]); - } + glDeleteTextures(numTextures, (GLuint*)textures); } // static void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels) { glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels); - stop_glerror(); } //create an empty GL texture: just create a texture name @@ -986,26 +955,21 @@ BOOL LLImageGL::createGLTexture() stop_glerror(); if (!mTexName) { - llwarns << "LLImageGL::createGLTexture failed to make an empty texture" << llendl; + llerrs << "LLImageGL::createGLTexture failed to make an empty texture" << llendl; } return TRUE ; } -BOOL LLImageGL::createGLTextureInAtlas(S32 discard_level, const LLImageRaw* imageraw, LLTextureAtlas* atlasp, S16 slot_col, S16 slot_row) +BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category) { - if(!sUseTextureAtlas) - { - return FALSE ; - } - if (gGLManager.mIsDisabled) { llwarns << "Trying to create a texture while GL is disabled!" << llendl; return FALSE; } - // mGLTextureCreated = false ; // KL not in SD + mGLTextureCreated = false ; llassert(gGLManager.mInited); stop_glerror(); @@ -1017,8 +981,10 @@ BOOL LLImageGL::createGLTextureInAtlas(S32 discard_level, const LLImageRaw* imag discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); // Actual image width/height = raw image width/height * 2^discard_level - S32 w = imageraw->getWidth() << discard_level; - S32 h = imageraw->getHeight() << discard_level; + S32 raw_w = imageraw->getWidth() ; + S32 raw_h = imageraw->getHeight() ; + S32 w = raw_w << discard_level; + S32 h = raw_h << discard_level; // setSize may call destroyGLTexture if the size does not match setSize(w, h, imageraw->getComponents()); @@ -1050,87 +1016,27 @@ BOOL LLImageGL::createGLTextureInAtlas(S32 discard_level, const LLImageRaw* imag mFormatType = GL_UNSIGNED_BYTE; break; default: - llwarns << "Bad number of components for texture: " << (U32)getComponents() << llendl; + LL_DEBUGS("Openjpeg") << "Bad number of components for texture: " << (U32)getComponents() << LL_ENDL; + to_create = false; + break; } } - if(addToAtlas(imageraw, atlasp, slot_col, slot_row)) + if(!to_create) //not create a gl texture { - // destroyGLTexture(); + destroyGLTexture(); mCurrentDiscardLevel = discard_level; - mDiscardLevelInAtlas = discard_level; - mTexelsInAtlas = imageraw->getWidth() * imageraw->getHeight() ; mLastBindTime = sLastFrameTime; - mGLTextureCreated = false ; return TRUE ; } - return FALSE ; -} - -BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) -{ - if (gGLManager.mIsDisabled) - { - llwarns << "Trying to create a texture while GL is disabled!" << llendl; - return FALSE; - } - - mGLTextureCreated = false ; - llassert(gGLManager.mInited); - stop_glerror(); - - if (discard_level < 0) - { - llassert(mCurrentDiscardLevel >= 0); - discard_level = mCurrentDiscardLevel; - } - discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - - // Actual image width/height = raw image width/height * 2^discard_level - S32 w = imageraw->getWidth() << discard_level; - S32 h = imageraw->getHeight() << discard_level; - - // setSize may call destroyGLTexture if the size does not match - setSize(w, h, imageraw->getComponents()); - - if( !mHasExplicitFormat ) - { - switch (mComponents) - { - case 1: - // Use luminance alpha (for fonts) - mFormatInternal = GL_LUMINANCE8; - mFormatPrimary = GL_LUMINANCE; - mFormatType = GL_UNSIGNED_BYTE; - break; - case 2: - // Use luminance alpha (for fonts) - mFormatInternal = GL_LUMINANCE8_ALPHA8; - mFormatPrimary = GL_LUMINANCE_ALPHA; - mFormatType = GL_UNSIGNED_BYTE; - break; - case 3: - mFormatInternal = GL_RGB8; - mFormatPrimary = GL_RGB; - mFormatType = GL_UNSIGNED_BYTE; - break; - case 4: - mFormatInternal = GL_RGBA8; - mFormatPrimary = GL_RGBA; - mFormatType = GL_UNSIGNED_BYTE; - break; - default: - llwarns << "Bad number of components for texture: " << (U32)getComponents() << llendl; - } - } + mCategory = category ; const U8* rawdata = imageraw->getData(); return createGLTexture(discard_level, rawdata, FALSE, usename); } BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) { - llpushcallstacks ; llassert(data_in); if (discard_level < 0) @@ -1167,7 +1073,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } if (!mTexName) { - llwarns << "LLImageGL::createGLTexture failed to make texture" << llendl; + llerrs << "LLImageGL::createGLTexture failed to make texture" << llendl; } if (mUseMipMaps) @@ -1198,30 +1104,30 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ if (old_name != 0) { sGlobalTextureMemoryInBytes -= mTextureMemory; -#if !LL_RELEASE_FOR_DOWNLOAD - decTextureCounter(mTextureMemory / mComponents) ; -#endif + + if(gAuditTexture) + { + decTextureCounter() ; + } LLImageGL::deleteTextures(1, &old_name); + stop_glerror(); } mTextureMemory = getMipBytes(discard_level); sGlobalTextureMemoryInBytes += mTextureMemory; - mTexelsInGLTexture = getWidth() * getHeight() ; - -#if !LL_RELEASE_FOR_DOWNLOAD - incTextureCounter(mTextureMemory / mComponents) ; -#endif setActive() ; + if(gAuditTexture) + { + incTextureCounter() ; + } // mark this as bound at this point, so we don't throw it out immediately mLastBindTime = sLastFrameTime; - - llpushcallstacks ; return TRUE; } - +#if 0 BOOL LLImageGL::setDiscardLevel(S32 discard_level) { llassert(discard_level >= 0); @@ -1243,7 +1149,7 @@ BOOL LLImageGL::setDiscardLevel(S32 discard_level) { // larger image dump(); - llwarns << "LLImageGL::setDiscardLevel() called with larger discard level; use createGLTexture()" << llendl; + llerrs << "LLImageGL::setDiscardLevel() called with larger discard level; use createGLTexture()" << llendl; return FALSE; } else if (mUseMipMaps) @@ -1268,30 +1174,19 @@ BOOL LLImageGL::setDiscardLevel(S32 discard_level) { #if !LL_LINUX && !LL_SOLARIS // *FIX: This should not be skipped for the linux client. - llwarns << "LLImageGL::setDiscardLevel() called on image without mipmaps" << llendl; + llerrs << "LLImageGL::setDiscardLevel() called on image without mipmaps" << llendl; #endif return FALSE; } } - -BOOL LLImageGL::isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) -{ - assert_glerror(); - S32 gl_discard = discard_level - mCurrentDiscardLevel; - LLGLint glwidth = 0; - glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth); - LLGLint glheight = 0; - glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_HEIGHT, (GLint*)&glheight); - LLGLint glcomponents = 0 ; - glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&glcomponents); - assert_glerror(); - - return glwidth >= image_width && glheight >= image_height && (GL_RGB8 == glcomponents || GL_RGBA8 == glcomponents) ; -} +#endif BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) { - llpushcallstacks ; + // VWR-13505 : Merov : Allow gl texture read back so save texture works again (temporary) + //llassert_always(sAllowReadBackRaw) ; + //llerrs << "should not call this function!" << llendl ; + if (discard_level < 0) { discard_level = mCurrentDiscardLevel; @@ -1396,48 +1291,41 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre return FALSE ; } //----------------------------------------------------------------------------------------------- - llpushcallstacks ; + return TRUE ; } -void LLImageGL::deleteDeadTextures() +void LLImageGL::destroyGLTexture() { - while (!sDeadTextureList.empty()) + if (mTexName != 0) { - GLuint tex = sDeadTextureList.front(); - sDeadTextureList.pop_front(); + stop_glerror(); + for (int i = 0; i < gGLManager.mNumTextureUnits; i++) { - if (sCurrentBoundTextures[i] == tex) + if (sCurrentBoundTextures[i] == mTexName) { gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE); stop_glerror(); } } - - glDeleteTextures(1, &tex); - stop_glerror(); - } -} - -void LLImageGL::destroyGLTexture() -{ - if (mTexName != 0) - { + if(mTextureMemory) { -#if !LL_RELEASE_FOR_DOWNLOAD - decTextureCounter(mTextureMemory / mComponents) ; -#endif + if(gAuditTexture) + { + decTextureCounter() ; + } sGlobalTextureMemoryInBytes -= mTextureMemory; mTextureMemory = 0; } - + LLImageGL::deleteTextures(1, &mTexName); - mTextureState = DELETED ; + mTextureState = DELETED ; mTexName = 0; mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. mGLTextureCreated = FALSE ; + stop_glerror(); } } @@ -1466,12 +1354,12 @@ void LLImageGL::setFilteringOption(LLTexUnit::eTextureFilterOptions option) mFilterOption = option; } - if (mTexName != 0 && gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName) + if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName) { gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureFilteringOption(option); mTexOptionsDirty = false; - stop_glerror(); } + stop_glerror(); } BOOL LLImageGL::getIsResident(BOOL test_now) @@ -1547,6 +1435,11 @@ S32 LLImageGL::getMipBytes(S32 discard_level) const return res; } +BOOL LLImageGL::isJustBound() const +{ + return (BOOL)(sLastFrameTime - mLastBindTime < 0.5f); +} + BOOL LLImageGL::getBoundRecently() const { return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME); @@ -1708,7 +1601,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) U32 pick_offset = pick_bit%8; if (pick_idx >= mPickMaskSize) { - llwarns << "WTF?" << llendl; + llerrs << "WTF?" << llendl; } mPickMask[pick_idx] |= 1 << pick_offset; @@ -1734,7 +1627,7 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) if (u < 0.f || u > 1.f || v < 0.f || v > 1.f) { - llwarns << "WTF?" << llendl; // WTF really useful info NOT + llerrs << "WTF?" << llendl; } S32 x = (S32)(u * width); @@ -1757,8 +1650,24 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) return res; } -//---------------------------------------------------------------------------- -#if !LL_RELEASE_FOR_DOWNLOAD +void LLImageGL::setCategory(S32 category) +{ + if(!gAuditTexture) + { + return ; + } + if(mCategory != category) + { + if(mCategory > -1) + { + sTextureMemByCategory[mCategory] -= mTextureMemory ; + } + sTextureMemByCategory[category] += mTextureMemory ; + + mCategory = category; + } +} + //for debug use //val is a "power of two" number S32 LLImageGL::getTextureCounterIndex(U32 val) @@ -1782,18 +1691,38 @@ S32 LLImageGL::getTextureCounterIndex(U32 val) return ret ; } } -void LLImageGL::incTextureCounter(U32 val) +void LLImageGL::incTextureCounterStatic(U32 val, S32 ncomponents, S32 category) { sTextureLoadedCounter[getTextureCounterIndex(val)]++ ; + sTextureMemByCategory[category] += (S32)val * ncomponents ; } -void LLImageGL::decTextureCounter(U32 val) +void LLImageGL::decTextureCounterStatic(U32 val, S32 ncomponents, S32 category) { sTextureLoadedCounter[getTextureCounterIndex(val)]-- ; + sTextureMemByCategory[category] += (S32)val * ncomponents ; +} +void LLImageGL::incTextureCounter() +{ + sTextureLoadedCounter[getTextureCounterIndex(mTextureMemory / mComponents)]++ ; + sTextureMemByCategory[mCategory] += mTextureMemory ; +} +void LLImageGL::decTextureCounter() +{ + sTextureLoadedCounter[getTextureCounterIndex(mTextureMemory / mComponents)]-- ; + sTextureMemByCategory[mCategory] -= mTextureMemory ; } -void LLImageGL::setCurTexSizebar(S32 index) +void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size) { sCurTexSizeBar = index ; - sCurTexPickSize = (1 << index) ; + + if(set_pick_size) + { + sCurTexPickSize = (1 << index) ; + } + else + { + sCurTexPickSize = -1 ; + } } void LLImageGL::resetCurTexSizebar() { @@ -1801,7 +1730,9 @@ void LLImageGL::resetCurTexSizebar() sCurTexPickSize = -1 ; } //---------------------------------------------------------------------------- -#endif + +//---------------------------------------------------------------------------- + // Manual Mip Generation /* diff --git a/linden/indra/llrender/llimagegl.h b/linden/indra/llrender/llimagegl.h index 56f79ff..c7114c3 100644 --- a/linden/indra/llrender/llimagegl.h +++ b/linden/indra/llrender/llimagegl.h @@ -45,23 +45,18 @@ #define BYTES_TO_MEGA_BYTES(x) ((x) >> 20) #define MEGA_BYTES_TO_BYTES(x) ((x) << 20) -class LLTextureAtlas ; //============================================================================ - class LLImageGL : public LLRefCount { friend class LLTexUnit; public: - static std::list<U32> sDeadTextureList; - - static void deleteDeadTextures(); - // Size calculation static S32 dataFormatBits(S32 dataformat); static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height); static S32 dataFormatComponents(S32 dataformat); void updateBindStats(void) const; + void forceUpdateBindStats(void) const; // needs to be called every frame static void updateStats(F32 current_time); @@ -70,12 +65,10 @@ public: static void destroyGL(BOOL save_state = TRUE); static void restoreGL(); - // Sometimes called externally for textures not using LLImageGL (should go away...) -//#if !LL_RELEASE_FOR_DOWNLOAD -// static S32 updateBoundTexMem(const S32 delta, const S32 size) ; -//#else - static S32 updateBoundTexMem(const S32 delta); -//#endif + // Sometimes called externally for textures not using LLImageGL (should go away...) + static S32 updateBoundTexMemStatic(const S32 delta, const S32 size, S32 category) ; + S32 updateBoundTexMem()const; + static bool checkSize(S32 width, S32 height); // Not currently necessary for LLImageGL, but required in some derived classes, @@ -97,7 +90,7 @@ protected: public: virtual void dump(); // debugging info to llinfos virtual bool bindError(const S32 stage = 0) const; - virtual bool bindDefaultImage(const S32 stage = 0) const; + virtual bool bindDefaultImage(const S32 stage = 0) ; virtual void forceImmediateUpdate() ; void setSize(S32 width, S32 height, S32 ncomponents); @@ -109,14 +102,15 @@ public: static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels); BOOL createGLTexture() ; - BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0); + BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, + S32 category = sMaxCatagories - 1); BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); void setImage(const LLImageRaw* imageraw); void setImage(const U8* data_in, BOOL data_hasmips = FALSE); - BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height); - BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height); + BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); + BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE); BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); - BOOL setDiscardLevel(S32 discard_level); + // Read back a raw image for this discard level, if it exists BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok); void destroyGLTexture(); @@ -136,7 +130,7 @@ public: S32 getBytes(S32 discard_level = -1) const; S32 getMipBytes(S32 discard_level = -1) const; BOOL getBoundRecently() const; - //BOOL isJustBound() const; + BOOL isJustBound() const; LLGLenum getPrimaryFormat() const { return mFormatPrimary; } BOOL getHasGLTexture() const { return mTexName != 0; } @@ -157,8 +151,6 @@ public: BOOL getUseDiscard() const { return mUseMipMaps && !mDontDiscard; } BOOL getDontDiscard() const { return mDontDiscard; } - BOOL isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) ; - void updatePickMask(S32 width, S32 height, const U8* data_in); BOOL getMask(const LLVector2 &tc); @@ -184,20 +176,8 @@ public: void setActive() ; void forceActive() ; void setNoDelete() ; - - BOOL canAddToAtlas() ; - BOOL createGLTextureInAtlas(S32 discard_level, const LLImageRaw* imageraw, LLTextureAtlas* atlasp, S16 slot_col, S16 slot_row); - BOOL addToAtlas(const LLImageRaw* raw_image, LLTextureAtlas* atlasp, S16 slot_col, S16 slot_row) ; - - LLGLenum getTexTarget()const { return mTarget ;} - S8 getDiscardLevelInAtlas()const {return mDiscardLevelInAtlas;} - U32 getTexelsInAtlas()const { return mTexelsInAtlas ;} - U32 getTexelsInGLTexture()const {return mTexelsInGLTexture;} -private: - void preAddToAtlas(S32 data_width) ; - void postAddToAtlas() ; - + void setTextureSize(S32 size) {mTextureMemory = size;} protected: void init(BOOL usemipmaps); virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors @@ -206,7 +186,7 @@ public: // Various GL/Rendering options S32 mTextureMemory; mutable F32 mLastBindTime; // last time this was bound, by discard level - + private: LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel @@ -222,15 +202,8 @@ private: U16 mWidth; U16 mHeight; S8 mCurrentDiscardLevel; - - S8 mDiscardLevelInAtlas; - U32 mTexelsInAtlas ; - U32 mTexelsInGLTexture; - + protected: - - BOOL mCanAddToAtlas ; - LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps) bool mHasMipMaps; @@ -268,18 +241,42 @@ public: static S32 sCount; static F32 sLastFrameTime; - + static LLGLuint sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS]; // Currently bound texture ID // Global memory statistics static S32 sGlobalTextureMemoryInBytes; // Tracks main memory texmem - static S32 sBoundTextureMemoryInBytes; // Tracks bound texmem for last completed frame + static S32 sBoundTextureMemoryInBytes; // Tracks bound texmem for last completed frame static S32 sCurBoundTextureMemory; // Tracks bound texmem for current frame static U32 sBindCount; // Tracks number of texture binds for current frame static U32 sUniqueCount; // Tracks number of unique texture binds for current frame static BOOL sGlobalUseAnisotropic; - static BOOL sUseTextureAtlas ; -#if !LL_RELEASE_FOR_DOWNLOAD +#if DEBUG_MISS + BOOL mMissed; // Missed on last bind? + BOOL getMissed() const { return mMissed; }; +#else + BOOL getMissed() const { return FALSE; }; +#endif + +public: + static void initClass(S32 num_catagories) ; + static void cleanupClass() ; +private: + static S32 sMaxCatagories ; + + //the flag to allow to call readBackRaw(...). + //can be removed if we do not use that function at all. + static BOOL sAllowReadBackRaw ; +// +//**************************************************************************************************** +//The below for texture auditing use only +//**************************************************************************************************** +private: + S32 mCategory ; +public: + void setCategory(S32 category) ; + S32 getCategory()const {return mCategory ;} + //for debug use: show texture size distribution //---------------------------------------- static LLPointer<LLImageGL> sDefaultTexturep; //default texture to replace normal textures @@ -290,19 +287,27 @@ public: static S32 sCurTexPickSize ; static S32 getTextureCounterIndex(U32 val) ; - static void incTextureCounter(U32 val) ; - static void decTextureCounter(U32 val) ; - static void setCurTexSizebar(S32 index) ; + static void incTextureCounterStatic(U32 val, S32 ncomponents, S32 category) ; + static void decTextureCounterStatic(U32 val, S32 ncomponents, S32 category) ; + static void setCurTexSizebar(S32 index, BOOL set_pick_size = TRUE) ; static void resetCurTexSizebar(); + + void incTextureCounter() ; + void decTextureCounter() ; //---------------------------------------- -#endif -#if DEBUG_MISS - BOOL mMissed; // Missed on last bind? - BOOL getMissed() const { return mMissed; }; -#else - BOOL getMissed() const { return FALSE; }; -#endif + //for debug use: show texture category distribution + //---------------------------------------- + + static std::vector<S32> sTextureMemByCategory; + static std::vector<S32> sTextureMemByCategoryBound ; + static std::vector<S32> sTextureCurMemByCategoryBound ; + //---------------------------------------- +//**************************************************************************************************** +//End of definitions for texture auditing use only +//**************************************************************************************************** + }; +extern BOOL gAuditTexture; #endif // LL_LLIMAGEGL_H diff --git a/linden/indra/llrender/llrender.cpp b/linden/indra/llrender/llrender.cpp index 07ba9f1..b1fe153 100644 --- a/linden/indra/llrender/llrender.cpp +++ b/linden/indra/llrender/llrender.cpp @@ -47,7 +47,7 @@ F64 gGLLastModelView[16]; F64 gGLProjection[16]; S32 gGLViewport[4]; -static const U32 LL_NUM_TEXTURE_LAYERS = 16; // KL was 8 ( keep a track on this ) 16 in render-pipeline +static const U32 LL_NUM_TEXTURE_LAYERS = 8; static GLenum sGLTextureType[] = { @@ -192,25 +192,24 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) if (!texture->getTexName()) //if texture does not exist { - //if deleted, will re-generate it immediately - texture->forceImmediateUpdate() ; + if (texture->isDeleted()) + { + // This will re-generate the texture immediately. + texture->forceImmediateUpdate() ; + } + texture->forceUpdateBindStats() ; return texture->bindDefaultImage(mIndex); } -#if !LL_RELEASE_FOR_DOWNLOAD - if(for_rendering) + if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0) { - int w = texture->getWidth(texture->getDiscardLevel()) ; - int h = texture->getHeight(texture->getDiscardLevel()) ; - - if(w * h == LLImageGL::sCurTexPickSize) + if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize) { texture->updateBindStats(); return bind(LLImageGL::sDefaultTexturep.get()); } } -#endif if ((mCurrTexture != texture->getTexName()) || forceBind) { @@ -228,6 +227,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) setTextureFilteringOption(texture->mFilterOption); } } + return true; } @@ -280,11 +280,6 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) if (bindDepth) { - if (renderTarget->hasStencil()) - { - llwarns << "Cannot bind a render buffer for sampling. Allocate render target without a stencil buffer if sampling of depth buffer is required." << llendl; - } - bindManual(renderTarget->getUsage(), renderTarget->getDepth()); } else @@ -298,18 +293,15 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips) { - if (mIndex < 0) return false; - - if(mCurrTexture != texture) - { - gGL.flush(); + if (mIndex < 0 || mCurrTexture == texture) return false; + + gGL.flush(); - activate(); - enable(type); - mCurrTexture = texture; - glBindTexture(sGLTextureType[type], texture); - mHasMipMaps = hasMips; - } + activate(); + enable(type); + mCurrTexture = texture; + glBindTexture(sGLTextureType[type], texture); + mHasMipMaps = hasMips; return true; } @@ -422,7 +414,7 @@ void LLTexUnit::setTextureBlendType(eTextureBlendType type) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); break; default: - llwarns << "Unknown Texture Blend Type: " << type << llendl; + llerrs << "Unknown Texture Blend Type: " << type << llendl; break; } setColorScale(scale_amount); @@ -817,7 +809,7 @@ void LLRender::setSceneBlendType(eBlendType type) glBlendFunc(GL_ONE, GL_ZERO); break; default: - llwarns << "Unknown Scene Blend Type: " << type << llendl; + llerrs << "Unknown Scene Blend Type: " << type << llendl; break; } } @@ -891,7 +883,7 @@ void LLRender::begin(const GLuint& mode) } else if (mCount != 0) { - llwarns << "gGL.begin() called redundantly." << llendl; + llerrs << "gGL.begin() called redundantly." << llendl; } mMode = mode; @@ -922,22 +914,22 @@ void LLRender::flush() #if 0 if (!glIsEnabled(GL_VERTEX_ARRAY)) { - llwarns << "foo 1" << llendl; + llerrs << "foo 1" << llendl; } if (!glIsEnabled(GL_COLOR_ARRAY)) { - llwarns << "foo 2" << llendl; + llerrs << "foo 2" << llendl; } if (!glIsEnabled(GL_TEXTURE_COORD_ARRAY)) { - llwarns << "foo 3" << llendl; + llerrs << "foo 3" << llendl; } if (glIsEnabled(GL_NORMAL_ARRAY)) { - llwarns << "foo 7" << llendl; + llerrs << "foo 7" << llendl; } GLvoid* pointer; @@ -945,19 +937,19 @@ void LLRender::flush() glGetPointerv(GL_VERTEX_ARRAY_POINTER, &pointer); if (pointer != &(mBuffer[0].v)) { - llwarns << "foo 4" << llendl; + llerrs << "foo 4" << llendl; } glGetPointerv(GL_COLOR_ARRAY_POINTER, &pointer); if (pointer != &(mBuffer[0].c)) { - llwarns << "foo 5" << llendl; + llerrs << "foo 5" << llendl; } glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &pointer); if (pointer != &(mBuffer[0].uv)) { - llwarns << "foo 6" << llendl; + llerrs << "foo 6" << llendl; } #endif diff --git a/linden/indra/llrender/llrendertarget.cpp b/linden/indra/llrender/llrendertarget.cpp index 151b761..4cf8451 100644 --- a/linden/indra/llrender/llrendertarget.cpp +++ b/linden/indra/llrender/llrendertarget.cpp @@ -47,10 +47,10 @@ void check_framebuffer_status() case GL_FRAMEBUFFER_COMPLETE_EXT: break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - llwarns << "WTF?" << llendl; + llerrs << "WTF?" << llendl; break; default: - llwarns << "WTF?" << llendl; + llerrs << "WTF?" << llendl; } } } @@ -139,9 +139,9 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt) U32 offset = mTex.size(); if (offset >= 4 || - offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)) + (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) { - llwarns << "Too many color attachments!" << llendl; // KL + llerrs << "Too many color attachments!" << llendl; } U32 tex; @@ -203,7 +203,7 @@ void LLRenderTarget::allocateDepth() gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH24_STENCIL8_EXT, mResX, mResY, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); } } @@ -211,7 +211,7 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) { if (!mFBO || !target.mFBO) { - llwarns << "Cannot share depth buffer between non FBO render targets." << llendl; + llerrs << "Cannot share depth buffer between non FBO render targets." << llendl; } if (mDepth) @@ -349,16 +349,16 @@ U32 LLRenderTarget::getTexture(U32 attachment) const { if (attachment > mTex.size()-1) { - llwarns << "Invalid attachment index [getTexture]." << llendl; // lets not crash KL its a pain in the ass! + llerrs << "Invalid attachment index." << llendl; } return mTex[attachment]; } void LLRenderTarget::bindTexture(U32 index, S32 channel) { - if (index > 6)//mTex.size()-1) // KL yeah i know its a bit arbitary but make the number big enough as some unused render defer elements cause this to go wild + if (index > mTex.size()-1) { - llwarns << "Invalid attachment index [bindtexture]." << llendl; + llerrs << "Invalid attachment index." << llendl; } gGL.getTexUnit(channel)->bindManual(mUsage, mTex[index]); } @@ -440,7 +440,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, #if !LL_DARWIN if (!source.mFBO || !mFBO) { - llwarns << "Cannot copy framebuffer contents for non FBO render targets." << llendl; + llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; } if (mSampleBuffer) @@ -449,27 +449,12 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, } else { - if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil) - { - source.bindTarget(); - gGL.getTexUnit(0)->bind(this, true); + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO); - glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1); - source.flush(); - } - else - { - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO); - stop_glerror(); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO); - stop_glerror(); - check_framebuffer_status(); - stop_glerror(); - glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); - stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - stop_glerror(); - } + glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } #endif } @@ -568,14 +553,14 @@ void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth if (!gGLManager.mHasFramebufferMultisample) { - llwarns << "Attempting to allocate unsupported render target type!" << llendl; + llerrs << "Attempting to allocate unsupported render target type!" << llendl; } mSamples = samples; if (mSamples <= 1) { - llwarns << "Cannot create a multisample buffer with less than 2 samples." << llendl; + llerrs << "Cannot create a multisample buffer with less than 2 samples." << llendl; } stop_glerror(); @@ -623,9 +608,9 @@ void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) U32 offset = mTex.size(); if (offset >= 4 || - offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)) + (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) { - llwarns << "Too many color attachments!" << llendl; + llerrs << "Too many color attachments!" << llendl; } U32 tex; @@ -646,10 +631,10 @@ void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) case GL_FRAMEBUFFER_COMPLETE_EXT: break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - llwarns << "WTF?" << llendl; + llerrs << "WTF?" << llendl; break; default: - llwarns << "WTF?" << llendl; + llerrs << "WTF?" << llendl; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); diff --git a/linden/indra/llrender/llrendertarget.h b/linden/indra/llrender/llrendertarget.h index 69af1ea..d5d809b 100644 --- a/linden/indra/llrender/llrendertarget.h +++ b/linden/indra/llrender/llrendertarget.h @@ -121,7 +121,6 @@ public: U32 getTexture(U32 attachment = 0) const; U32 getDepth(void) const { return mDepth; } - BOOL hasStencil() const { return mStencil; } void bindTexture(U32 index, S32 channel); diff --git a/linden/indra/llrender/lltextureatlas.cpp b/linden/indra/llrender/lltextureatlas.cpp deleted file mode 100644 index c0f5419..0000000 --- a/linden/indra/llrender/lltextureatlas.cpp +++ /dev/null @@ -1,411 +0,0 @@ -/** - * @file lltextureatlas.cpp - * @brief LLTextureAtlas class implementation. - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ -#include "linden_common.h" -#include "llerror.h" -#include "llimage.h" -#include "llmath.h" -#include "llgl.h" -#include "llrender.h" -#include "lltextureatlas.h" - -//------------------- -S16 LLTextureAtlas::sMaxSubTextureSize = 64 ; -S16 LLTextureAtlas::sSlotSize = 32 ; - -#ifndef DEBUG_ATLAS -#define DEBUG_ATLAS 0 -#endif - -#ifndef DEBUG_USAGE_BITS -#define DEBUG_USAGE_BITS 0 -#endif -//************************************************************************************************************** -LLTextureAtlas::LLTextureAtlas(U8 ncomponents, S16 atlas_dim) : LLImageGL(), - mAtlasDim(atlas_dim) -{ - setComponents(ncomponents) ; - - mCanAddToAtlas = FALSE ;//do not add one atlas to another. - mNumSlotsReserved = 0 ; - mMaxSlotsInAtlas = mAtlasDim * mAtlasDim ; - - generateEmptyUsageBits() ; - - //generate an empty texture - S32 dim = mAtlasDim * sSlotSize ; //number of pixels per dimension - LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim, dim, getComponents()); - createGLTexture(0, image_raw, 0); - image_raw = NULL; - dontDiscard(); -} - -LLTextureAtlas::~LLTextureAtlas() -{ - if(mSpatialGroupList.size() > 0) - { - llwarns << "Not clean up the spatial groups!" << llendl ; - } - releaseUsageBits() ; -} - -void LLTextureAtlas::getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yoffset) -{ -#if !DEBUG_ATLAS - xoffset = (F32)col / mAtlasDim ; - yoffset = (F32)row / mAtlasDim ; -#endif -} - -void LLTextureAtlas::getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale) -{ -#if !DEBUG_ATLAS - xscale = (F32)w / (mAtlasDim * sSlotSize) ; - yscale = (F32)h / (mAtlasDim * sSlotSize) ; -#endif -} - -//insert a texture piece into the atlas -LLGLuint LLTextureAtlas::insertSubTexture(const LLImageRaw* raw_image, S16 slot_col, S16 slot_row) -{ - S32 w = raw_image->getWidth() ; - S32 h = raw_image->getHeight() ; - if(w < 8 || w > sMaxSubTextureSize || h < 8 || h > sMaxSubTextureSize) - { - //size overflow - return 0 ; - } - - BOOL res = gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getTexName()); - if (!res) llwarns << "bindTexture failed" << llendl; - stop_glerror(); - - GLint xoffset = sSlotSize * slot_col ; - GLint yoffset = sSlotSize * slot_row ; - - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, TRUE); - glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, - w, h, mFormatPrimary, mFormatType, raw_image->getData()); - - return getTexName(); -} - -//release a sub-texture slot from the atlas -void LLTextureAtlas::releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width) -{ - unmarkUsageBits(slot_width, slot_col, slot_row) ; - mNumSlotsReserved -= slot_width * slot_width ; -} - -BOOL LLTextureAtlas::isEmpty() const -{ - return !mNumSlotsReserved ; -} - -BOOL LLTextureAtlas::isFull(S8 to_be_reserved) const -{ - return mNumSlotsReserved + to_be_reserved > mMaxSlotsInAtlas ; -} -F32 LLTextureAtlas::getFullness() const -{ - return (F32)mNumSlotsReserved / mMaxSlotsInAtlas ; -} - -void LLTextureAtlas::addSpatialGroup(LLSpatialGroup* groupp) -{ - if(groupp && !hasSpatialGroup(groupp)) - { - mSpatialGroupList.push_back(groupp); - } -} - -void LLTextureAtlas::removeSpatialGroup(LLSpatialGroup* groupp) -{ - if(groupp) - { - mSpatialGroupList.remove(groupp); - } -} - -void LLTextureAtlas::clearSpatialGroup() -{ - mSpatialGroupList.clear(); -} -void LLTextureAtlas::removeLastSpatialGroup() -{ - mSpatialGroupList.pop_back() ; -} - -LLSpatialGroup* LLTextureAtlas::getLastSpatialGroup() -{ - if(mSpatialGroupList.size() > 0) - { - return mSpatialGroupList.back() ; - } - return NULL ; -} - -BOOL LLTextureAtlas::hasSpatialGroup(LLSpatialGroup* groupp) -{ - for(std::list<LLSpatialGroup*>::iterator iter = mSpatialGroupList.begin(); iter != mSpatialGroupList.end() ; ++iter) - { - if(*iter == groupp) - { - return TRUE ; - } - } - return FALSE ; -} - -//-------------------------------------------------------------------------------------- -//private -void LLTextureAtlas::generateEmptyUsageBits() -{ - S32 col_len = (mAtlasDim + 7) >> 3 ; - mUsageBits = new U8*[mAtlasDim] ; - *mUsageBits = new U8[mAtlasDim * col_len] ; - - mUsageBits[0] = *mUsageBits ; - for(S32 i = 1 ; i < mAtlasDim ; i++) - { - mUsageBits[i] = mUsageBits[i-1] + col_len ; - - for(S32 j = 0 ; j < col_len ; j++) - { - //init by 0 for all bits. - mUsageBits[i][j] = 0 ; - } - } - - //do not forget mUsageBits[0]! - for(S32 j = 0 ; j < col_len ; j++) - { - //init by 0 for all bits. - mUsageBits[0][j] = 0 ; - } - - mTestBits = NULL ; -#if DEBUG_USAGE_BITS - //------------ - //test - mTestBits = new U8*[mAtlasDim] ; - *mTestBits = new U8[mAtlasDim * mAtlasDim] ; - mTestBits[0] = *mTestBits ; - for(S32 i = 1 ; i < mAtlasDim ; i++) - { - mTestBits[i] = mTestBits[i-1] + mAtlasDim ; - - for(S32 j = 0 ; j < mAtlasDim ; j++) - { - //init by 0 for all bits. - mTestBits[i][j] = 0 ; - } - } - - for(S32 j = 0 ; j < mAtlasDim ; j++) - { - //init by 0 for all bits. - mTestBits[0][j] = 0 ; - } -#endif -} - -void LLTextureAtlas::releaseUsageBits() -{ - if(mUsageBits) - { - delete[] *mUsageBits ; - delete[] mUsageBits ; - } - mUsageBits = NULL ; - - //test - if( mTestBits) - { - delete[] *mTestBits; - delete[] mTestBits; - } - mTestBits = NULL ; -} - -void LLTextureAtlas::markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row) -{ - S16 x = col >> 3 ; - - for(S8 i = 0 ; i < bits_len ; i++) - { - mUsageBits[row + i][x] |= mask ; - } - -#if DEBUG_USAGE_BITS - //test - for(S8 i = row ; i < row + bits_len ; i++) - { - for(S8 j = col ; j < col + bits_len ; j++) - { - mTestBits[i][j] = 1 ; - } - } -#endif -} - -void LLTextureAtlas::unmarkUsageBits(S8 bits_len, S16 col, S16 row) -{ - S16 x = col >> 3 ; - U8 mask = 1 ; - for(S8 i = 1 ; i < bits_len ; i++) - { - mask |= (1 << i) ; - } - mask <<= (col & 7) ; - mask = ~mask ; - - for(S8 i = 0 ; i < bits_len ; i++) - { - mUsageBits[row + i][x] &= mask ; - } - -#if DEBUG_USAGE_BITS - //test - for(S8 i = row ; i < row + bits_len ; i++) - { - for(S8 j = col ; j < col + bits_len ; j++) - { - mTestBits[i][j] = 0 ; - } - } -#endif -} - -//return true if any of bits in the range marked. -BOOL LLTextureAtlas::areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row) -{ - BOOL ret = FALSE ; - S16 x = col >> 3 ; - - for(S8 i = 0 ; i < bits_len ; i++) - { - if(mUsageBits[row + i][x] & mask) - { - ret = TRUE ; - break ; - //return TRUE ; - } - } - -#if DEBUG_USAGE_BITS - //test - BOOL ret2 = FALSE ; - for(S8 i = row ; i < row + bits_len ; i++) - { - for(S8 j = col ; j < col + bits_len ; j++) - { - if(mTestBits[i][j]) - { - ret2 = TRUE ; - } - } - } - - if(ret != ret2) - { - llwarns << "bits map corrupted." << llendl ; - } -#endif - return ret ;//FALSE ; -} - -//---------------------------------------------------------------------- -// -//index order: Z order, i.e.: -// |-----|-----|-----|-----| -// | 10 | 11 | 14 | 15 | -// |-----|-----|-----|-----| -// | 8 | 9 | 12 | 13 | -// |-----|-----|-----|-----| -// | 2 | 3 | 6 | 7 | -// |-----|-----|-----|-----| -// | 0 | 1 | 4 | 5 | -// |-----|-----|-----|-----| -void LLTextureAtlas::getPositionFromIndex(S16 index, S16& col, S16& row) -{ - col = 0 ; - row = 0 ; - - S16 index_copy = index ; - for(S16 i = 0 ; index_copy && i < 16 ; i += 2) - { - col |= ((index & (1 << i)) >> i) << (i >> 1) ; - row |= ((index & (1 << (i + 1))) >> (i + 1)) << (i >> 1) ; - index_copy >>= 2 ; - } -} -void LLTextureAtlas::getIndexFromPosition(S16 col, S16 row, S16& index) -{ - index = 0 ; - S16 col_copy = col ; - S16 row_copy = row ; - for(S16 i = 0 ; (col_copy || row_copy) && i < 16 ; i++) - { - index |= ((col & 1 << i) << i) | ((row & 1 << i) << ( i + 1)) ; - col_copy >>= 1 ; - row_copy >>= 1 ; - } -} -//---------------------------------------------------------------------- -//return TRUE if succeeds. -BOOL LLTextureAtlas::getNextAvailableSlot(S8 bits_len, S16& col, S16& row) -{ - S16 index_step = bits_len * bits_len ; - - U8 mask = 1 ; - for(S8 i = 1 ; i < bits_len ; i++) - { - mask |= (1 << i) ; - } - - U8 cur_mask ; - for(S16 index = 0 ; index < mMaxSlotsInAtlas ; index += index_step) - { - getPositionFromIndex(index, col, row) ; - - cur_mask = mask << (col & 7) ; - if(!areUsageBitsMarked(bits_len, cur_mask, col, row)) - { - markUsageBits(bits_len, cur_mask, col, row) ; - mNumSlotsReserved += bits_len * bits_len ; - - return TRUE ; - } - } - - return FALSE ; -} diff --git a/linden/indra/llrender/lltextureatlas.h b/linden/indra/llrender/lltextureatlas.h deleted file mode 100644 index 4922175..0000000 --- a/linden/indra/llrender/lltextureatlas.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @file lltextureatlas.h - * @brief LLTextureAtlas base class. - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - - -#ifndef LL_TEXTUREATLAS_H -#define LL_TEXTUREATLAS_H - -#include "llimagegl.h" -class LLSpatialGroup ; - -class LLTextureAtlas : public LLImageGL -{ -public: - LLTextureAtlas(U8 ncomponents, S16 atlas_dim = 16) ; - ~LLTextureAtlas() ; - - LLGLuint insertSubTexture(const LLImageRaw* raw_image, S16 slot_col, S16 slot_row) ; - void releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width); - - BOOL getNextAvailableSlot(S8 bits_len, S16& col, S16& row) ; - void getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yOffset) ; - void getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale) ; - - BOOL isEmpty() const ; - BOOL isFull(S8 to_be_reserved = 1) const ; - F32 getFullness() const ; - - void addSpatialGroup(LLSpatialGroup* groupp) ; - void removeSpatialGroup(LLSpatialGroup* groupp) ; - LLSpatialGroup* getLastSpatialGroup() ; - void removeLastSpatialGroup() ; - BOOL hasSpatialGroup(LLSpatialGroup* groupp) ; - void clearSpatialGroup() ; - std::list<LLSpatialGroup*>* getSpatialGroupList() {return &mSpatialGroupList;} -private: - void generateEmptyUsageBits() ; - void releaseUsageBits() ; - - void markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row) ; - void unmarkUsageBits(S8 bits_len, S16 col, S16 row) ; - - void getPositionFromIndex(S16 index, S16& col, S16& row) ; - void getIndexFromPosition(S16 col, S16 row, S16& index) ; - BOOL areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row) ; - -private: - S16 mAtlasDim ; //number of slots per edge, i.e, there are "mAtlasDim * mAtlasDim" total slots in the atlas. - S16 mNumSlotsReserved ; - S16 mMaxSlotsInAtlas ; - U8 **mUsageBits ; - std::list<LLSpatialGroup*> mSpatialGroupList ; - -public: - //debug use only - U8 **mTestBits ; - -public: - static S16 sMaxSubTextureSize ; - static S16 sSlotSize ; -}; - -#endif - diff --git a/linden/indra/llrender/llvertexbuffer.cpp b/linden/indra/llrender/llvertexbuffer.cpp index 31c2d75..461edbe 100644 --- a/linden/indra/llrender/llvertexbuffer.cpp +++ b/linden/indra/llrender/llvertexbuffer.cpp @@ -96,7 +96,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { /*if (LLGLImmediate::sStarted) { - llwarns << "Cannot use LLGLImmediate and LLVertexBuffer simultaneously!" << llendl; + llerrs << "Cannot use LLGLImmediate and LLVertexBuffer simultaneously!" << llendl; }*/ if (sLastMask != data_mask) @@ -129,7 +129,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { //needs to be enabled, make sure it was (DEBUG TEMPORARY) if (i > 0 && !glIsEnabled(array[i])) { - llwarns << "Bad client state! " << array[i] << " disabled." << llendl; + llerrs << "Bad client state! " << array[i] << " disabled." << llendl; } } } @@ -141,7 +141,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) } else if (gDebugGL && glIsEnabled(array[i])) { //needs to be disabled, make sure it was (DEBUG TEMPORARY) - llwarns << "Bad client state! " << array[i] << " enabled." << llendl; + llerrs << "Bad client state! " << array[i] << " enabled." << llendl; } } } @@ -197,28 +197,28 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi if (start >= (U32) mRequestedNumVerts || end >= (U32) mRequestedNumVerts) { - llwarns << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl; + llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl; } if (indices_offset >= (U32) mRequestedNumIndices || indices_offset + count > (U32) mRequestedNumIndices) { - llwarns << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; + llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; } if (mGLIndices != sGLRenderIndices) { - llwarns << "Wrong index buffer bound." << llendl; + llerrs << "Wrong index buffer bound." << llendl; } if (mGLBuffer != sGLRenderBuffer) { - llwarns << "Wrong vertex buffer bound." << llendl; + llerrs << "Wrong vertex buffer bound." << llendl; } if (mode > LLRender::NUM_MODES) { - llwarns << "Invalid draw mode: " << mode << llendl; + llerrs << "Invalid draw mode: " << mode << llendl; return; } @@ -233,22 +233,22 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const if (indices_offset >= (U32) mRequestedNumIndices || indices_offset + count > (U32) mRequestedNumIndices) { - llwarns << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; + llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; } if (mGLIndices != sGLRenderIndices) { - llwarns << "Wrong index buffer bound." << llendl; + llerrs << "Wrong index buffer bound." << llendl; } if (mGLBuffer != sGLRenderBuffer) { - llwarns << "Wrong vertex buffer bound." << llendl; + llerrs << "Wrong vertex buffer bound." << llendl; } if (mode > LLRender::NUM_MODES) { - llwarns << "Invalid draw mode: " << mode << llendl; + llerrs << "Invalid draw mode: " << mode << llendl; return; } @@ -263,17 +263,17 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const if (first >= (U32) mRequestedNumVerts || first + count > (U32) mRequestedNumVerts) { - llwarns << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl; + llerrs << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl; } if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive) { - llwarns << "Wrong vertex buffer bound." << llendl; + llerrs << "Wrong vertex buffer bound." << llendl; } if (mode > LLRender::NUM_MODES) { - llwarns << "Invalid draw mode: " << mode << llendl; + llerrs << "Invalid draw mode: " << mode << llendl; return; } @@ -530,7 +530,7 @@ void LLVertexBuffer::destroyGLBuffer() { if (mMappedData || mMappedIndexData) { - llwarns << "Vertex buffer destroyed while mapped!" << llendl; + llerrs << "Vertex buffer destroyed while mapped!" << llendl; } releaseBuffer(); } @@ -557,7 +557,7 @@ void LLVertexBuffer::destroyGLIndices() { if (mMappedData || mMappedIndexData) { - llwarns << "Vertex buffer destroyed while mapped." << llendl; + llerrs << "Vertex buffer destroyed while mapped." << llendl; } releaseIndices(); } @@ -634,7 +634,7 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) if (mMappedData) { - llwarns << "LLVertexBuffer::allocateBuffer() called redundantly." << llendl; + llerrs << "LLVertexBuffer::allocateBuffer() called redundantly." << llendl; } if (create && (nverts || nindices)) { @@ -782,11 +782,11 @@ U8* LLVertexBuffer::mapBuffer(S32 access) LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mFinal) { - llwarns << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl; + llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl; } if (!useVBOs() && !mMappedData && !mMappedIndexData) { - llwarns << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl; + llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl; } if (!mLocked && useVBOs()) @@ -813,11 +813,11 @@ U8* LLVertexBuffer::mapBuffer(S32 access) glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); if (buff != mGLBuffer) { - llwarns << "Invalid GL vertex buffer bound: " << buff << llendl; + llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; } - llwarns << "glMapBuffer returned NULL (no vertex data)" << llendl; + llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl; } if (!mMappedIndexData) @@ -826,10 +826,10 @@ U8* LLVertexBuffer::mapBuffer(S32 access) glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if (buff != mGLIndices) { - llwarns << "Invalid GL index buffer bound: " << buff << llendl; + llerrs << "Invalid GL index buffer bound: " << buff << llendl; } - llwarns << "glMapBuffer returned NULL (no index data)" << llendl; + llerrs << "glMapBuffer returned NULL (no index data)" << llendl; } sMappedCount++; @@ -908,7 +908,7 @@ template <class T,S32 type> struct VertexBufferStrider } else { - llwarns << "VertexBufferStrider could not find valid vertex data." << llendl; + llerrs << "VertexBufferStrider could not find valid vertex data." << llendl; } return FALSE; } @@ -965,7 +965,7 @@ void LLVertexBuffer::setStride(S32 type, S32 new_stride) LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mNumVerts) { - llwarns << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl; + llerrs << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl; } // This code assumes that setStride() will only be called once per VBO per type. S32 delta = new_stride - sTypeOffsets[type]; @@ -1020,15 +1020,15 @@ void LLVertexBuffer::setBuffer(U32 data_mask) { GLint buff; glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); - if ((GLuint)buff != mGLBuffer) + if (buff != mGLBuffer) { - llwarns << "Invalid GL vertex buffer bound: " << buff << llendl; + llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; } glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); - if ((GLuint)buff != mGLIndices) + if (buff != mGLIndices) { - llwarns << "Invalid GL index buffer bound: " << buff << llendl; + llerrs << "Invalid GL index buffer bound: " << buff << llendl; } } @@ -1038,15 +1038,15 @@ void LLVertexBuffer::setBuffer(U32 data_mask) { GLint buff; glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); - if ((GLuint)buff != mGLBuffer) + if (buff != mGLBuffer) { - llwarns << "Invalid GL vertex buffer bound: " << buff << llendl; + llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; } glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); - if ((GLuint)buff != mGLIndices) + if (buff != mGLIndices) { - llwarns << "Invalid GL index buffer bound: " << buff << llendl; + llerrs << "Invalid GL index buffer bound: " << buff << llendl; } } @@ -1068,7 +1068,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask) if (data_mask != 0) { - llwarns << "Buffer set for rendering before being filled after resize." << llendl; + llerrs << "Buffer set for rendering before being filled after resize." << llendl; } } @@ -1129,7 +1129,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const if ((data_mask & mTypeMask) != data_mask) { - llwarns << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; + llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; } if (data_mask & MAP_NORMAL) diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index fafcfa8..04ed486 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt @@ -330,7 +330,6 @@ set(viewer_SOURCE_FILES llpolymesh.cpp llpolymorph.cpp llprefsadvanced.cpp - llpostprocess.cpp llprefschat.cpp llprefsim.cpp llprefsvoice.cpp @@ -361,7 +360,6 @@ set(viewer_SOURCE_FILES llsurface.cpp llsurfacepatch.cpp lltexlayer.cpp - lltextureatlasmanager.cpp lltexturecache.cpp lltexturectrl.cpp lltexturefetch.cpp @@ -780,7 +778,6 @@ set(viewer_HEADER_FILES llpolymesh.h llpolymorph.h llprefsadvanced.h - llpostprocess.h llprefschat.h llprefsim.h llprefsvoice.h @@ -813,7 +810,6 @@ set(viewer_HEADER_FILES llsurfacepatch.h lltable.h lltexlayer.h - lltextureatlasmanager.h lltexturecache.h lltexturectrl.h lltexturefetch.h diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml index d306f0d..57ed4c0 100644 --- a/linden/indra/newview/app_settings/settings.xml +++ b/linden/indra/newview/app_settings/settings.xml @@ -5122,21 +5122,6 @@ <key>Value</key> <integer>1</integer> </map> - -<!--KL port --> - <key>EnableTextureAtlas</key> - <map> - <key>Comment</key> - <string>Whether to use texture atlas or not</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> -<!--/KL port --> - <key>EnableVoiceChat</key> <map> <key>Comment</key> @@ -8968,74 +8953,11 @@ <string>Vector3</string> <key>Value</key> <array> - <real>1.0</real> - <real>12.0</real> - <real>32.0</real> - </array> - </map> - <key>RenderShadowSplitExponent</key> - <map> - <key>Comment</key> - <string>Near clip plane split distances for shadow map frusta (x=perspective, y=ortho, z=transition rate).</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Vector3</string> - <key>Value</key> - <array> - <real>3.0</real> - <real>3.0</real> - <real>2.0</real> - </array> - </map> - <key>RenderShadowOrthoClipPlanes</key> - <map> - <key>Comment</key> - <string>Near clip plane split distances for orthographic shadow map frusta.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Vector3</string> - <key>Value</key> - <array> <real>4.0</real> <real>8.0</real> <real>24.0</real> </array> </map> - <key>RenderShadowProjOffset</key> - <map> - <key>Comment</key> - <string>Amount to scale distance to virtual origin of shadow perspective projection.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>2.0</real> - </map> - <key>RenderShadowSlopeThreshold</key> - <map> - <key>Comment</key> - <string>Cutoff slope value for points to affect perspective shadow generation</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.0</real> - </map> - <key>RenderShadowProjExponent</key> - <map> - <key>Comment</key> - <string>Exponent applied to transition between ortho and perspective shadow projections based on viewing angle and light vector.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.5</real> - </map> <key>RenderSSAOScale</key> <map> <key>Comment</key> @@ -9195,184 +9117,6 @@ <key>Value</key> <integer>0</integer> </map> - - <key>RenderGILightRadius</key> - <map> - <key>Comment</key> - <string>Distance of ambiant bounce lighting from sun.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>8</real> - </map> - - <key>RenderGISamples</key> - <map> - <key>Comment</key> - <string>Number of samples to take for GI.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <real>64</real> - </map> - - <key>RenderGIRange</key> - <map> - <key>Comment</key> - <string>Distance to cut off GI effect.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>128</real> - </map> - - - <key>RenderGIDirectionWeight</key> - <map> - <key>Comment</key> - <string>Weight of reflected light vector in GI angular attenuation.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.5</real> - </map> - - <key>RenderGILightOffset</key> - <map> - <key>Comment</key> - <string>Amount to offset light from point of impact in gi map (scaled by light radius).</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.0</real> - </map> - - <key>RenderGIColorCurve</key> - <map> - <key>Comment</key> - <string>Global illumination color correction curve parameters.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Vector3</string> - <key>Value</key> - <array> - <real>0.0</real> - <real>0.2</real> - <real>0.02</real> - </array> - </map> - - <key>RenderLuminanceColorCurve</key> - <map> - <key>Comment</key> - <string>Luminance color correction curve parameters.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Vector3</string> - <key>Value</key> - <array> - <real>0.30</real> - <real>0.0</real> - <real>0.04</real> - </array> - </map> - - <key>RenderGILuminanceColorCurve</key> - <map> - <key>Comment</key> - <string>Luminance color correction curve parameters.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Vector3</string> - <key>Value</key> - <array> - <real>0.4</real> - <real>0.0</real> - <real>0.05</real> - </array> - </map> - - <key>RenderSunLuminanceColorCurve</key> - <map> - <key>Comment</key> - <string>Luminance color correction curve parameters.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Vector3</string> - <key>Value</key> - <array> - <real>0.6</real> - <real>0.0</real> - <real>-0.3</real> - </array> - </map> - - <key>RenderLuminanceDetail</key> - <map> - <key>Comment</key> - <string>Mipmap level to use for luminance</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>8.0</real> - </map> - - <key>RenderLuminanceFade</key> - <map> - <key>Comment</key> - <string>Scaler for speed of luminance adjustment</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.05</real> - </map> - - <key>RenderGISpecularCurve</key> - <map> - <key>Comment</key> - <string>Global illumination specular color correction curve parameters.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Vector3</string> - <key>Value</key> - <array> - <real>0.1</real> - <real>0.0</real> - <real>0.9</real> - </array> - </map> - - <key>RenderGIIntensity</key> - <map> - <key>Comment</key> - <string>Distance of ambiant bounce lighting from sun.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.2f</real> - </map> - <key>RenderDeferredAlphaSoften</key> <map> <key>Comment</key> @@ -9395,455 +9139,72 @@ <key>Value</key> <real>4</real> </map> - <key>RenderDeferredSpotShadowBias</key> - <map> - <key>Comment</key> - <string>Bias value for spot shadows (prevent shadow acne).</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>-64.0</real> - </map> - <key>RenderDeferredSpotShadowOffset</key> + <key>RenderDeferred</key> <map> <key>Comment</key> - <string>Offset value for spot shadows (prevent shadow acne).</string> + <string>Use deferred rendering pipeline.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>F32</string> + <string>Boolean</string> <key>Value</key> - <real>0.8</real> + <integer>0</integer> </map> - - <key>RenderShadowBias</key> + <key>RenderDeferredSunShadow</key> <map> <key>Comment</key> - <string>Bias value for shadows (prevent shadow acne).</string> + <string>Generate shadows from the sun.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>F32</string> + <string>Boolean</string> <key>Value</key> - <real>0.001</real> - </map> - <key>RenderShadowOffset</key> - <map> - <key>Comment</key> - <string>Offset value for shadows (prevent shadow acne).</string> - <key>Persist</key> <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.6</real> </map> - - <key>RenderShadowResolutionScale</key> + <key>RenderDeferredSunWash</key> <map> <key>Comment</key> - <string>Scale of shadow map resolution vs. screen resolution</string> + <string>Amount local lights are washed out by sun.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>F32</string> <key>Value</key> - <real>1.0</real> + <real>0.5</real> </map> - - - - <key>RenderDeferredTreeShadowBias</key> + <key>RenderShadowNoise</key> <map> <key>Comment</key> - <string>Bias value for tree shadows (prevent shadow acne).</string> + <string>Magnitude of noise on shadow samples.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>F32</string> <key>Value</key> - <real>1.0</real> + <real>-0.0001</real> </map> - <key>RenderDeferredTreeShadowOffset</key> + <key>RenderShadowBlurSize</key> <map> <key>Comment</key> - <string>Offset value for tree shadows (prevent shadow acne).</string> + <string>Scale of shadow softening kernel.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>F32</string> <key>Value</key> - <real>1.0</real> + <real>0.7</real> </map> - - <key>RenderHighlightFadeTime</key> + <key>RenderShadowBlurSamples</key> <map> <key>Comment</key> - <string>Transition time for mouseover highlights.</string> + <string>Number of samples to take for each pass of shadow blur (value range 1-16). Actual number of samples is value * 2 - 1.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>F32</string> + <string>U32</string> <key>Value</key> - <real>0.2</real> + <real>5</real> </map> - - <key>RenderHighlightBrightness</key> - <map> - <key>Comment</key> - <string>Brightness of mouseover highlights.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>4.0</real> - </map> - - <key>RenderHighlightThickness</key> - <map> - <key>Comment</key> - <string>Thickness of mouseover highlights.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.6</real> - </map> - - <key>RenderHighlightColor</key> - <map> - <key>Comment</key> - <string>Brightness of mouseover highlights.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Color4</string> - <key>Value</key> - <array> - <real>0.4</real> - <real>0.98</real> - <real>0.93</real> - <real>1.0</real> - </array> - </map> - - <key>RenderSpecularResX</key> - <map> - <key>Comment</key> - <string>Spec map resolution.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <real>128</real> - </map> - - <key>RenderSpecularResY</key> - <map> - <key>Comment</key> - <string>Spec map resolution.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <real>128</real> - </map> - - <key>RenderSpecularExponent</key> - <map> - <key>Comment</key> - <string>Specular exponent for generating spec map</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>1</real> - </map> - - <key>RenderDeferred</key> - <map> - <key>Comment</key> - <string>Use deferred rendering pipeline.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - - <key>RenderDeferredShadow</key> - <map> - <key>Comment</key> - <string>Enable shadows in deferred renderer.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - - <key>RenderDeferredGI</key> - <map> - <key>Comment</key> - <string>Enable GI in deferred renderer.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - - <key>RenderDeferredSunShadow</key> - <map> - <key>Comment</key> - <string>Generate shadows from the sun.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - - <key>RenderDeferredSun</key> - <map> - <key>Comment</key> - <string>Execute sunlight shader in deferred renderer.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - - <key>RenderDeferredAtmospheric</key> - <map> - <key>Comment</key> - <string>Execute atmospheric shader in deferred renderer.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - - <key>RenderDeferredBlurLight</key> - <map> - <key>Comment</key> - <string>Execute shadow softening shader in deferred renderer.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - - <key>RenderDeferredLocalLights</key> - <map> - <key>Comment</key> - <string>Execute local lighting shader in deferred renderer.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - - <key>RenderDeferredFullscreenLights</key> - <map> - <key>Comment</key> - <string>Execute local lighting shader in deferred renderer.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> - - <key>RenderDeferredSunWash</key> - <map> - <key>Comment</key> - <string>Amount local lights are washed out by sun.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.5</real> - </map> - <key>RenderShadowNoise</key> - <map> - <key>Comment</key> - <string>Magnitude of noise on shadow samples.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>-0.0001</real> - </map> - <key>RenderShadowErrorCutoff</key> - <map> - <key>Comment</key> - <string>Cutoff error value to use ortho instead of perspective projection.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>5.0</real> - </map> - <key>RenderShadowFOVCutoff</key> - <map> - <key>Comment</key> - <string>Cutoff FOV to use ortho instead of perspective projection.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>1.1</real> - </map> - - <key>RenderShadowGaussian</key> - <map> - <key>Comment</key> - <string>Gaussian coefficients for the two shadow/SSAO blurring passes (z component unused).</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Vector3</string> - <key>Value</key> - <array> - <real>3.0</real> - <real>2.0</real> - <real>0.0</real> - </array> - </map> - - <key>RenderShadowBlurSize</key> - <map> - <key>Comment</key> - <string>Scale of shadow softening kernel.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.8</real> - </map> - <key>RenderShadowBlurSamples</key> - <map> - <key>Comment</key> - <string>Number of samples to take for each pass of shadow blur (value range 1-16). Actual number of samples is value * 2 - 1.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <real>4</real> - </map> - <key>RenderShadowBlurDistFactor</key> - <map> - <key>Comment</key> - <string>Distance scaler for shadow blur.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.1</real> - </map> - - <key>RenderGIBlurColorCurve</key> - <map> - <key>Comment</key> - <string>Color curve for GI softening kernel</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Vector3</string> - <key>Value</key> - <array> - <real>1.0</real> - <real>0.6</real> - <real>0.1</real> - </array> - </map> - - <key>RenderGIGaussian</key> - <map> - <key>Comment</key> - <string>Gaussian coefficient for the two GI blurring passes.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>64</real> - </map> - - <key>RenderGIBlurPasses</key> - <map> - <key>Comment</key> - <string>Scale of GI softening kernel.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <real>2</real> - </map> - - <key>RenderGIBlurSize</key> - <map> - <key>Comment</key> - <string>Scale of GI softening kernel.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>3.0</real> - </map> - <key>RenderGIBlurSamples</key> - <map> - <key>Comment</key> - <string>Number of samples to take for each pass of GI blur (value range 1-16). Actual number of samples is value * 2 - 1.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <real>6</real> - </map> - <key>RenderGIBlurDistFactor</key> - <map> - <key>Comment</key> - <string>Distance scaler for GI blur.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <real>0.0</real> - </map> - <key>RenderDynamicLOD</key> <map> <key>Comment</key> @@ -10094,17 +9455,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderHighlightSelections</key> - <map> - <key>Comment</key> - <string>Show selection outlines on objects</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>RenderHiddenSelections</key> <map> <key>Comment</key> @@ -10413,17 +9763,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderUIBuffer</key> - <map> - <key>Comment</key> - <string>Cache ui render in a screen aligned buffer.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>RenderUnloadedAvatar</key> <map> <key>Comment</key> diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index f90d91f..a91e9fa 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -13,9 +13,9 @@ uniform sampler2DShadow shadowMap1; uniform sampler2DShadow shadowMap2; uniform sampler2DShadow shadowMap3; uniform sampler2D noiseMap; -uniform sampler2DRect depthMap; +uniform sampler2DRect positionMap; -uniform mat4 shadow_matrix[6]; +uniform mat4 shadow_matrix[4]; uniform vec4 shadow_clip; uniform vec2 screen_res; @@ -26,31 +26,15 @@ varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_fragcoord; varying vec3 vary_position; -varying vec3 vary_light; uniform float alpha_soften; -uniform mat4 inv_proj; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - void main() { vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; frag *= screen_res; - vec3 samp_pos = getPosition(frag).xyz; + vec3 samp_pos = texture2DRect(positionMap, frag).xyz; float shadow = 1.0; vec4 pos = vec4(vary_position, 1.0); @@ -98,7 +82,7 @@ void main() //gl_FragColor = gl_Color; gl_FragColor = color; - //gl_FragColor = vec4(1,0,1,1)*shadow; + //gl_FragColor = vec4(1,0,1,1); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 48baf77..b496bd6 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -20,11 +20,8 @@ varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_fragcoord; varying vec3 vary_position; -varying vec3 vary_light; uniform float near_clip; -uniform float shadow_offset; -uniform float shadow_bias; void main() { @@ -35,9 +32,8 @@ void main() vec4 pos = (gl_ModelViewMatrix * gl_Vertex); vec3 norm = normalize(gl_NormalMatrix * gl_Normal); - // KL this works around ATI not compiling the shader but maintains shadow offset and bias vec3 not vec4 - vary_position = pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias); - + vary_position = pos.xyz; + calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); @@ -58,8 +54,6 @@ void main() col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); - vary_light = gl_LightSource[0].position.xyz; - vary_ambient = col.rgb*gl_Color.rgb; vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl index ff64a6b..6c94f5c 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl @@ -12,7 +12,7 @@ uniform sampler2DShadow shadowMap2; uniform sampler2DShadow shadowMap3; uniform sampler2D noiseMap; -uniform mat4 shadow_matrix[6]; +uniform mat4 shadow_matrix[4]; uniform vec4 shadow_clip; vec3 atmosLighting(vec3 light); diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index 4b9cca2..58aa5a9 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -8,18 +8,13 @@ uniform sampler2D diffuseMap; varying vec3 vary_normal; +varying vec4 vary_position; void main() { - vec4 diff = gl_Color*texture2D(diffuseMap, gl_TexCoord[0].xy); - // Viewer 2.0 uses 0.2 but for KL's viewer if i want a complete avatar need this to be 0.0 for now. - if (diff.a < 0.0) - { - discard; - } - - gl_FragData[0] = vec4(diff.rgb, 1.0); + gl_FragData[0] = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy); gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + gl_FragData[2] = vec4(normalize(vary_normal), 0.0); + gl_FragData[3] = vary_position; } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl index 00083eb..27c09db 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl @@ -10,7 +10,6 @@ uniform sampler2D diffuseMap; void main() { - gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a); - //gl_FragColor = vec4(1,1,1,1); + gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy)); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl index 8c8489d..14da6b1 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl @@ -28,7 +28,8 @@ void main() norm = normalize(norm); pos = gl_ProjectionMatrix * pos; - pos.z = max(pos.z, -pos.w+0.01); + //smash geometry against near clip plane + pos.z = max(pos.z, -1.0); gl_Position = pos; gl_FrontColor = gl_Color; diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl index 471a1f0..12a7ff7 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl @@ -10,6 +10,7 @@ mat4 getSkinnedTransform(); attribute vec4 weight; varying vec3 vary_normal; +varying vec4 vary_position; void main() { @@ -29,6 +30,7 @@ void main() norm.z = dot(trans[2].xyz, gl_Normal); norm = normalize(norm); + vary_position = pos; vary_normal = norm; gl_Position = gl_ProjectionMatrix * pos; diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index 1713fe9..3c6700a 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -7,11 +7,10 @@ #extension GL_ARB_texture_rectangle : enable -uniform sampler2DRect depthMap; +uniform sampler2DRect positionMap; uniform sampler2DRect normalMap; uniform sampler2DRect lightMap; -uniform float dist_factor; uniform float blur_size; uniform vec2 delta; uniform vec3 kern[32]; @@ -20,52 +19,30 @@ uniform float kern_scale; varying vec2 vary_fragcoord; -uniform mat4 inv_proj; -uniform vec2 screen_res; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; - vec3 pos = getPosition(vary_fragcoord.xy).xyz; - vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba; + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + vec3 pos = texture2DRect(positionMap, vary_fragcoord.xy).xyz; + vec2 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rg; vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); - dlt /= max(-pos.z*dist_factor, 1.0); - vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' - vec4 col = defined_weight.xyxx * ccol; + vec2 col = defined_weight * ccol; for (int i = 1; i < kern_length; i++) { vec2 tc = vary_fragcoord.xy + kern[i].z*dlt; - vec3 samppos = getPosition(tc).xyz; + vec3 samppos = texture2DRect(positionMap, tc).xyz; float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane if (d*d <= 0.003) { - col += texture2DRect(lightMap, tc)*kern[i].xyxx; + col += texture2DRect(lightMap, tc).rg*kern[i].xy; defined_weight += kern[i].xy; } } + col /= defined_weight; - - col /= defined_weight.xyxx; - - gl_FragColor = col; - - //gl_FragColor = ccol; + gl_FragColor = vec4(col.r, col.g, 0.0, 1.0); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 1c29dae..a8712bc 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -11,6 +11,7 @@ uniform sampler2D bumpMap; varying vec3 vary_mat0; varying vec3 vary_mat1; varying vec3 vary_mat2; +varying vec4 vary_position; void main() { @@ -21,7 +22,8 @@ void main() dot(norm,vary_mat1), dot(norm,vary_mat2)); - gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0); - gl_FragData[1] = vec4(col*gl_Color.a, gl_Color.a); - gl_FragData[2] = vec4(normalize(tnorm)*0.5+0.5, 0.0); + gl_FragData[0].rgb = gl_Color.rgb*col; + gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a); + gl_FragData[2] = vec4(normalize(tnorm), 0.0); + gl_FragData[3] = vary_position; } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl index 9589912..ba18092 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl @@ -8,6 +8,7 @@ varying vec3 vary_mat0; varying vec3 vary_mat1; varying vec3 vary_mat2; +varying vec4 vary_position; void main() { @@ -15,6 +16,8 @@ void main() gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + vary_position = gl_ModelViewMatrix * gl_Vertex; + vec3 n = normalize(gl_NormalMatrix * gl_Normal); vec3 b = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz); vec3 t = cross(b, n); diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 919dd5d..f2ba2df 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -8,11 +8,13 @@ uniform sampler2D diffuseMap; varying vec3 vary_normal; +varying vec4 vary_position; void main() { vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; - gl_FragData[0] = vec4(gl_Color.rgb*col, 1.0); // KL viewer 2.0 has 0.0 but this is not working right yet besides i like to see my eyes :) + gl_FragData[0] = vec4(gl_Color.rgb*col, 1.0); gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + gl_FragData[2] = vec4(normalize(vary_normal), 0.0); + gl_FragData[3] = vary_position; } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index 44468cd..3413a7f 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -6,13 +6,16 @@ */ varying vec3 vary_normal; +varying vec4 vary_position; void main() { //transform vertex - gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + vary_position = gl_ModelViewMatrix * gl_Vertex; + vary_normal = normalize(gl_NormalMatrix * gl_Normal); gl_FrontColor = gl_Color; diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl index e518bdd..2a811c5 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -8,9 +8,14 @@ #extension GL_ARB_texture_rectangle : enable uniform sampler2D diffuseMap; -uniform sampler2DRect depthMap; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; uniform sampler2D noiseMap; +uniform sampler2DRect positionMap; +uniform mat4 shadow_matrix[4]; uniform vec4 shadow_clip; uniform vec2 screen_res; @@ -25,27 +30,12 @@ varying vec3 vary_fragcoord; uniform float alpha_soften; -uniform mat4 inv_proj; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - void main() { vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; frag *= screen_res; - vec3 samp_pos = getPosition(frag).xyz; + vec3 samp_pos = texture2DRect(positionMap, frag).xyz; float shadow = 1.0; vec4 pos = vary_position; @@ -56,10 +46,10 @@ void main() color.rgb = fullbrightScaleSoftClip(color.rgb); - if (samp_pos.z != 0.0 && color.a < 1.0) + if (samp_pos.z != 0.0) { float dist_factor = alpha_soften; - float a = color.a; + float a = gl_Color.a; a *= a; dist_factor *= 1.0/(1.0-a); color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl index aff5117..6381a1c 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl @@ -12,12 +12,12 @@ vec3 atmosAffectDirectionalLight(float lightIntensity); vec3 scaleDownLight(vec3 light); vec3 scaleUpLight(vec3 light); +varying vec4 vary_position; varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_normal; varying vec3 vary_fragcoord; uniform float near_clip; -varying vec4 vary_position; void main() { diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/giF.glsl deleted file mode 100644 index b351eec..0000000 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/giF.glsl +++ /dev/null @@ -1,165 +0,0 @@ -/** - * @file giF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform sampler2D noiseMap; - -uniform sampler2D diffuseGIMap; -uniform sampler2D normalGIMap; -uniform sampler2D depthGIMap; - -uniform sampler2D lightFunc; - -// Inputs -varying vec2 vary_fragcoord; - -uniform vec2 screen_res; - -uniform mat4 inv_proj; -uniform mat4 gi_mat; //gPipeline.mGIMatrix - eye space to sun space -uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space -uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix -uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space -uniform float gi_radius; -uniform float gi_intensity; -uniform int gi_samples; -uniform vec2 gi_kern[25]; -uniform vec2 gi_scale; -uniform vec3 gi_quad; -uniform vec3 gi_spec; -uniform float gi_direction_weight; -uniform float gi_light_offset; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -vec4 getGIPosition(vec2 gi_tc) -{ - float depth = texture2D(depthGIMap, gi_tc).a; - vec2 sc = gi_tc*2.0; - sc -= vec2(1.0, 1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = gi_inv_proj*ndc; - pos.xyz /= pos.w; - pos.w = 1.0; - return pos; -} - -vec3 giAmbient(vec3 pos, vec3 norm) -{ - vec4 gi_c = gi_mat_proj * vec4(pos, 1.0); - gi_c.xyz /= gi_c.w; - - vec4 gi_pos = gi_mat*vec4(pos,1.0); - vec3 gi_norm = (gi_norm_mat*vec4(norm,1.0)).xyz; - gi_norm = normalize(gi_norm); - - vec2 tcx = gi_norm.xy; - vec2 tcy = gi_norm.yx; - - vec4 eye_pos = gi_mat*vec4(0,0,0,1.0); - - vec3 eye_dir = normalize(gi_pos.xyz-eye_pos.xyz/eye_pos.w); - - //vec3 eye_dir = vec3(0,0,-1); - //eye_dir = (gi_norm_mat*vec4(eye_dir, 1.0)).xyz; - //eye_dir = normalize(eye_dir); - - //float round_x = gi_scale.x; - //float round_y = gi_scale.y; - - vec3 debug = texture2D(normalGIMap, gi_c.xy).rgb*0.5+0.5; - debug.xz = vec2(0.0,0.0); - //debug = fract(debug); - - float round_x = 1.0/64.0; - float round_y = 1.0/64.0; - - //gi_c.x = floor(gi_c.x/round_x+0.5)*round_x; - //gi_c.y = floor(gi_c.y/round_y+0.5)*round_y; - - float fda = 0.0; - vec3 fdiff = vec3(0,0,0); - - vec3 rcol = vec3(0,0,0); - - float fsa = 0.0; - - for (int i = -1; i < 2; i+=2 ) - { - for (int j = -1; j < 2; j+=2) - { - vec2 tc = vec2(i, j)*0.75; - vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0+tc*0.5).xyz; - //tc += gi_norm.xy*nz.z; - tc += nz.xy*2.0; - tc /= gi_samples; - tc += gi_c.xy; - - vec3 lnorm = -normalize(texture2D(normalGIMap, tc.xy).xyz*2.0-1.0); - vec3 lpos = getGIPosition(tc.xy).xyz; - - vec3 at = lpos-gi_pos.xyz; - float dist = dot(at,at); - float da = clamp(1.0/(gi_spec.x*dist), 0.0, 1.0); - - if (da > 0.0) - { - //add angular attenuation - vec3 ldir = at; - float ang_atten = clamp(dot(ldir, gi_norm), 0.0, 1.0); - - float ld = -dot(ldir, lnorm); - - if (ang_atten > 0.0 && ld < 0.0) - { - vec3 diff = texture2D(diffuseGIMap, tc.xy).xyz; - da = da*ang_atten; - fda += da; - fdiff += diff*da; - } - } - } - } - - fdiff /= max(gi_spec.y*fda, gi_quad.z); - fdiff = clamp(fdiff, vec3(0), vec3(1)); - - vec3 ret = fda*fdiff; - //ret = ret*ret*gi_quad.x+ret*gi_quad.y+gi_quad.z; - - //fda *= nz.z; - - //rcol.rgb *= gi_intensity; - //return rcol.rgb+vary_AmblitColor.rgb*0.25; - //return vec4(debug, 0.0); - //return vec4(fda*fdiff, 0.0); - return clamp(ret,vec3(0.0), vec3(1.0)); - //return debug.xyz; -} - -void main() -{ - vec2 pos_screen = vary_fragcoord.xy; - vec4 pos = getPosition(pos_screen); - vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; - - gl_FragData[0].xyz = giAmbient(pos, norm); -} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/giV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/giV.glsl deleted file mode 100644 index 71dcea9..0000000 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/giV.glsl +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @file giV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -varying vec2 vary_fragcoord; - -uniform vec2 screen_res; - -void main() -{ - //transform vertex - gl_Position = ftransform(); - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; - vec4 tex = gl_MultiTexCoord0; - tex.w = 1.0; - - gl_FrontColor = gl_Color; -} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl deleted file mode 100644 index e8b53b0..0000000 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @file luminanceF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2DRect diffuseMap; - -varying vec2 vary_fragcoord; - -void main() -{ - gl_FragColor = texture2DRect(diffuseMap, vary_fragcoord.xy); -} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl deleted file mode 100644 index db8775f..0000000 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @file giV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -varying vec2 vary_fragcoord; - -uniform vec2 screen_res; - -void main() -{ - //transform vertex - gl_Position = ftransform(); - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; - - gl_FrontColor = gl_Color; -} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index ce0494c..3689d12 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -7,15 +7,13 @@ #extension GL_ARB_texture_rectangle : enable -uniform sampler2DRect depthMap; uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; +uniform sampler2DRect positionMap; uniform sampler2DRect normalMap; uniform samplerCube environmentMap; uniform sampler2DRect lightMap; uniform sampler2D noiseMap; -uniform sampler2D lightFunc; - uniform vec3 env_mat[3]; uniform float sun_wash; @@ -25,48 +23,24 @@ uniform int light_count; uniform vec4 light[16]; uniform vec4 light_col[16]; -varying vec4 vary_fragcoord; +varying vec3 vary_fragcoord; uniform vec2 screen_res; -uniform float far_z; - -uniform mat4 inv_proj; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - void main() { vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res; - vec3 pos = getPosition(frag.xy).xyz; - if (pos.z < far_z) - { - discard; - } - - vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz*2.0-1.0); + vec3 pos = texture2DRect(positionMap, frag.xy).xyz; + vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz); vec4 spec = texture2DRect(specularRect, frag.xy); vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb; float noise = texture2D(noiseMap, frag.xy/128.0).b; vec3 out_col = vec3(0,0,0); - vec3 npos = normalize(-pos); for (int i = 0; i < light_count; ++i) { vec3 lv = light[i].xyz-pos; float dist2 = dot(lv,lv); - dist2 /= light[i].w; - if (dist2 > 1.0) + if (dist2 > light[i].w) { continue; } @@ -81,41 +55,29 @@ void main() da = dot(norm, lv); float fa = light_col[i].a+1.0; - float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + float dist_atten = clamp(1.0-(dist2-light[i].w*(1.0-fa))/(light[i].w*fa), 0.0, 1.0); dist_atten *= noise; float lit = da * dist_atten; vec3 col = light_col[i].rgb*lit*diff; - //vec3 col = vec3(dist2, light_col[i].a, lit); if (spec.a > 0.0) { - //vec3 ref = dot(pos+lv, norm); - - float sa = dot(normalize(lv+npos),norm); - - if (sa > 0) - { - sa = texture2D(lightFunc,vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*light_col[i].rgb*spec.rgb; - } + vec3 ref = reflect(normalize(pos), norm); + float sa = dot(ref,lv); + sa = max(sa, 0.0); + sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); + sa *= noise; + col += da*sa*light_col[i].rgb*spec.rgb; } out_col += col; } - if (dot(out_col, out_col) <= 0.0) - { - discard; - } - //attenuate point light contribution by SSAO component out_col *= texture2DRect(lightMap, frag.xy).g; gl_FragColor.rgb = out_col; gl_FragColor.a = 0.0; - - //gl_FragColor = vec4(0.1, 0.025, 0.025/4.0, 0.0); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl deleted file mode 100644 index 021e8a2..0000000 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ /dev/null @@ -1,184 +0,0 @@ -/** - * @file multiSpotLightF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -#version 120 - -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform samplerCube environmentMap; -uniform sampler2DRect lightMap; -uniform sampler2D noiseMap; -uniform sampler2D lightFunc; -uniform sampler2D projectionMap; - -uniform mat4 proj_mat; //screen space to light space -uniform float proj_near; //near clip for projection -uniform vec3 proj_p; //plane projection is emitting from (in screen space) -uniform vec3 proj_n; -uniform float proj_focus; //distance from plane to begin blurring -uniform float proj_lod; //(number of mips in proj map) -uniform float proj_range; //range between near clip and far clip plane of projection -uniform float proj_ambient_lod; -uniform float proj_ambiance; -uniform float near_clip; -uniform float far_clip; - -uniform vec3 proj_origin; //origin of projection to be used for angular attenuation -uniform float sun_wash; -uniform int proj_shadow_idx; -uniform float shadow_fade; - -varying vec4 vary_light; - -varying vec4 vary_fragcoord; -uniform vec2 screen_res; - -uniform mat4 inv_proj; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -void main() -{ - vec4 frag = vary_fragcoord; - frag.xyz /= frag.w; - frag.xyz = frag.xyz*0.5+0.5; - frag.xy *= screen_res; - - vec3 pos = getPosition(frag.xy).xyz; - vec3 lv = vary_light.xyz-pos.xyz; - float dist2 = dot(lv,lv); - dist2 /= vary_light.w; - if (dist2 > 1.0) - { - discard; - } - - float shadow = 1.0; - - if (proj_shadow_idx >= 0) - { - vec4 shd = texture2DRect(lightMap, frag.xy); - float sh[2]; - sh[0] = shd.b; - sh[1] = shd.a; - shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); - } - - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; - - norm = normalize(norm); - float l_dist = -dot(lv, proj_n); - - vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); - if (proj_tc.z < 0.0) - { - discard; - } - - proj_tc.xyz /= proj_tc.w; - - float fa = gl_Color.a+1.0; - float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - - lv = proj_origin-pos.xyz; - lv = normalize(lv); - float da = dot(norm, lv); - - vec3 col = vec3(0,0,0); - - vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; - - float noise = texture2D(noiseMap, frag.xy/128.0).b; - if (proj_tc.z > 0.0 && - proj_tc.x < 1.0 && - proj_tc.y < 1.0 && - proj_tc.x > 0.0 && - proj_tc.y > 0.0) - { - float lit = 0.0; - float amb_da = proj_ambiance; - - if (da > 0.0) - { - float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); - float lod = diff * proj_lod; - - vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); - - vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; - - lit = da * dist_atten * noise; - - col = lcol*lit*diff_tex*shadow; - amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; - } - - //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_ambient_lod); - - amb_da += (da*da*0.5+0.5)*proj_ambiance; - - amb_da *= dist_atten * noise; - - amb_da = min(amb_da, 1.0-lit); - - col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; - } - - - vec4 spec = texture2DRect(specularRect, frag.xy); - if (spec.a > 0.0) - { - vec3 ref = reflect(normalize(pos), norm); - - //project from point pos in direction ref to plane proj_p, proj_n - vec3 pdelta = proj_p-pos; - float ds = dot(ref, proj_n); - - if (ds < 0.0) - { - vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - - vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); - - if (stc.z > 0.0) - { - stc.xy /= stc.w; - - if (stc.x < 1.0 && - stc.y < 1.0 && - stc.x > 0.0 && - stc.y > 0.0) - { - vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); - col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow; - } - } - } - } - - //attenuate point light contribution by SSAO component - col *= texture2DRect(lightMap, frag.xy).g; - - gl_FragColor.rgb = col; - gl_FragColor.a = 0.0; -} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index d8ccfd4..52bad1f 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -9,54 +9,33 @@ uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; +uniform sampler2DRect positionMap; uniform sampler2DRect normalMap; uniform samplerCube environmentMap; uniform sampler2DRect lightMap; uniform sampler2D noiseMap; -uniform sampler2D lightFunc; -uniform sampler2DRect depthMap; uniform vec3 env_mat[3]; uniform float sun_wash; varying vec4 vary_light; -varying vec4 vary_fragcoord; +varying vec3 vary_fragcoord; uniform vec2 screen_res; -uniform mat4 inv_proj; -uniform vec4 viewport; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = (pos_screen.xy-viewport.xy)*2.0; - sc /= viewport.zw; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - void main() { - vec4 frag = vary_fragcoord; - frag.xyz /= frag.w; - frag.xyz = frag.xyz*0.5+0.5; - frag.xy *= screen_res; - - vec3 pos = getPosition(frag.xy).xyz; + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; + frag *= screen_res; + vec3 pos = texture2DRect(positionMap, frag).xyz; vec3 lv = vary_light.xyz-pos; float dist2 = dot(lv,lv); - dist2 /= vary_light.w; - if (dist2 > 1.0) + if (dist2 > vary_light.w) { discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, frag).xyz; float da = dot(norm, lv); if (da < 0.0) { @@ -67,30 +46,24 @@ void main() lv = normalize(lv); da = dot(norm, lv); - float noise = texture2D(noiseMap, frag.xy/128.0).b; + float noise = texture2D(noiseMap, frag/128.0).b; - vec3 col = texture2DRect(diffuseRect, frag.xy).rgb; + vec3 col = texture2DRect(diffuseRect, frag).rgb; float fa = gl_Color.a+1.0; - float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + float dist_atten = clamp(1.0-(dist2-vary_light.w*(1.0-fa))/(vary_light.w*fa), 0.0, 1.0); float lit = da * dist_atten * noise; col = gl_Color.rgb*lit*col; - vec4 spec = texture2DRect(specularRect, frag.xy); + vec4 spec = texture2DRect(specularRect, frag); if (spec.a > 0.0) { - float sa = dot(normalize(lv-normalize(pos)),norm); - if (sa > 0.0) - { - sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*gl_Color.rgb*spec.rgb; - } - } - - if (dot(col, col) <= 0.0) - { - discard; + vec3 ref = reflect(normalize(pos), norm); + float sa = dot(ref,lv); + sa = max(sa, 0.0); + sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); + sa *= noise; + col += da*sa*gl_Color.rgb*spec.rgb; } //attenuate point light contribution by SSAO component diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl index e815ca2..a4edb88 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl @@ -6,7 +6,7 @@ */ varying vec4 vary_light; -varying vec4 vary_fragcoord; +varying vec3 vary_fragcoord; uniform vec2 screen_res; uniform float near_clip; @@ -14,10 +14,10 @@ uniform float near_clip; void main() { //transform vertex - gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_Position = ftransform(); vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = pos; + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); vec4 tex = gl_MultiTexCoord0; tex.w = 1.0; diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl deleted file mode 100644 index 71de036..0000000 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @file postDeferredF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect diffuseRect; -uniform sampler2DRect localLightMap; -uniform sampler2DRect sunLightMap; -uniform sampler2DRect giLightMap; -uniform sampler2D luminanceMap; -uniform sampler2DRect lightMap; - -uniform vec3 lum_quad; -uniform float lum_lod; -uniform vec4 ambient; - -uniform vec3 gi_quad; - -uniform vec2 screen_res; -varying vec2 vary_fragcoord; - -void main() -{ - vec2 tc = vary_fragcoord.xy; - vec3 lum = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb; - float luminance = lum.r; - luminance = luminance*lum_quad.y+lum_quad.z; - - vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); - - float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g; - - vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; - gi_col = gi_col*gi_col*gi_quad.x + gi_col*gi_quad.y+gi_quad.z*ambocc*ambient.rgb; - gi_col *= diff; - - vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy); - - vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb; - - - sun_col *= 1.0/min(luminance, 1.0); - gi_col *= 1.0/luminance; - - vec3 col = sun_col.rgb+gi_col+local_col; - - gl_FragColor.rgb = col.rgb; - col.rgb = max(col.rgb-vec3(1.0,1.0,1.0), vec3(0.0, 0.0, 0.0)); - - gl_FragColor.a = 0.0; // max(dot(col.rgb,col.rgb)*lum_quad.x, sun_col.a); - - //gl_FragColor.rgb = vec3(lum_lod); -} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl deleted file mode 100644 index 9819232..0000000 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @file postDeferredV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -varying vec2 vary_fragcoord; -uniform vec2 screen_res; - -void main() -{ - //transform vertex - gl_Position = ftransform(); - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; -} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl deleted file mode 100644 index 3556c7b..0000000 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl +++ /dev/null @@ -1,107 +0,0 @@ -/** - * @file postgiF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2D diffuseGIMap; -uniform sampler2D normalGIMap; -uniform sampler2D depthGIMap; -uniform sampler2D diffuseMap; - -uniform sampler2D lastDiffuseGIMap; -uniform sampler2D lastNormalGIMap; -uniform sampler2D lastMinpGIMap; -uniform sampler2D lastMaxpGIMap; - -uniform float gi_blend; - -uniform mat4 gi_mat; //gPipeline.mGIMatrix - eye space to sun space -uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space -uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix -uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space -uniform float gi_radius; -uniform float gi_intensity; -uniform vec2 gi_kern[16]; -uniform vec2 gi_scale; - - -vec4 getGIPosition(vec2 gi_tc) -{ - float depth = texture2D(depthGIMap, gi_tc).a; - vec2 sc = gi_tc*2.0; - sc -= vec2(1.0, 1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = gi_inv_proj*ndc; - pos.xyz /= pos.w; - pos.w = 1.0; - return pos; -} - - -void main() -{ - vec2 c_tc = gl_TexCoord[0].xy; - - vec3 diff = vec3(0,0,0); - vec3 minp = vec3(1024,1024,1024); - vec3 maxp = vec3(-1024,-1024,-1024); - vec3 norm = vec3(0,0,0); - - float dweight = 0.0; - - vec3 cnorm = normalize(texture2D(normalGIMap, c_tc).rgb*2.0-1.0); - - vec3 cpos = vec3(0,0,0); - float tweight = 0.0; - - for (int i = 0; i < 8; ++i) - { - for (int j = 0; j < 8; ++j) - { - vec2 tc = vec2(i-4+0.5, j-4+0.5); - float weight = 1.0-length(tc)/6.0; - tc *= 1.0/(256.0); - tc += c_tc; - - vec3 n = texture2D(normalGIMap, tc).rgb*2.0-1.0; - tweight += weight; - - diff += weight*texture2D(diffuseGIMap, tc).rgb; - - norm += n*weight; - - dweight += dot(n, cnorm); - - vec3 pos = getGIPosition(tc).xyz; - cpos += pos*weight; - - minp = min(pos, minp); - maxp = max(pos, maxp); - } - } - - dweight = abs(1.0-dweight/64.0); - float mind = min(sqrt(dweight+0.5), 1.0); - - dweight *= dweight; - - cpos /= tweight; - - diff = clamp(diff/tweight, vec3(1.0/2.2), vec3(1,1,1)); - norm = normalize(norm); - maxp = cpos; - minp = vec3(dweight, mind, cpos.z-minp.z); - - //float blend = 1.0; - //diff = mix(texture2D(lastDiffuseGIMap, c_tc).rgb, diff, blend); - //norm = mix(texture2D(lastNormalGIMap, c_tc).rgb, norm, blend); - //maxp = mix(texture2D(lastMaxpGIMap, c_tc).rgb, maxp, blend); - //minp = mix(texture2D(lastMinpGIMap, c_tc).rgb, minp, blend); - - gl_FragData[0].rgb = diff; - gl_FragData[2].xyz = normalize(norm); - gl_FragData[1].xyz = maxp; - gl_FragData[3].xyz = minp; -} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl deleted file mode 100644 index 5a8eb65..0000000 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @file postgiV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -varying vec3 vary_normal; - -void main() -{ - //transform vertex - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - gl_Position = pos; - gl_TexCoord[0].xy = pos.xy*0.5+0.5; -} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl index b0b31fd..b3758c3 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl @@ -7,11 +7,8 @@ uniform sampler2D diffuseMap; -varying vec4 post_pos; void main() { gl_FragColor = vec4(1,1,1,texture2D(diffuseMap, gl_TexCoord[0].xy).a * gl_Color.a); - - gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl index 7214d24..aae1bee 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl @@ -5,17 +5,13 @@ * $License$ */ -varying vec4 post_pos; - void main() { //transform vertex vec4 pos = gl_ModelViewProjectionMatrix*gl_Vertex; - - post_pos = pos; - - gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); - + //smash geometry against the near clip plane (great for ortho projections) + pos.z = max(pos.z, -1.0); + gl_Position = pos; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; gl_FrontColor = gl_Color; } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 64e263a..d5671a6 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -272,4 +272,8 @@ void main() gl_FragColor.rgb = col; gl_FragColor.a = 0.0; + //gl_FragColor.rg = scol_ambocc.rg; + //gl_FragColor.rgb = norm.rgb*0.5+0.5; + //gl_FragColor.rgb = vec3(ambocc); + //gl_FragColor.rgb = vec3(scol); } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl deleted file mode 100644 index d653408..0000000 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ /dev/null @@ -1,199 +0,0 @@ -/** - * @file spotLightF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -#version 120 - -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform samplerCube environmentMap; -uniform sampler2DRect lightMap; -uniform sampler2D noiseMap; -uniform sampler2D lightFunc; -uniform sampler2D projectionMap; - -uniform mat4 proj_mat; //screen space to light space -uniform float proj_near; //near clip for projection -uniform vec3 proj_p; //plane projection is emitting from (in screen space) -uniform vec3 proj_n; -uniform float proj_focus; //distance from plane to begin blurring -uniform float proj_lod; //(number of mips in proj map) -uniform float proj_range; //range between near clip and far clip plane of projection -uniform float proj_ambiance; -uniform float near_clip; -uniform float far_clip; - -uniform vec3 proj_origin; //origin of projection to be used for angular attenuation -uniform float sun_wash; -uniform int proj_shadow_idx; -uniform float shadow_fade; - -varying vec4 vary_light; - -varying vec4 vary_fragcoord; -uniform vec2 screen_res; - -uniform mat4 inv_proj; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -void main() -{ - vec4 frag = vary_fragcoord; - frag.xyz /= frag.w; - frag.xyz = frag.xyz*0.5+0.5; - frag.xy *= screen_res; - - float shadow = 1.0; - - if (proj_shadow_idx >= 0) - { - vec4 shd = texture2DRect(lightMap, frag.xy); - float sh[2]; - sh[0] = shd.b; - sh[1] = shd.a; - shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); - } - - vec3 pos = getPosition(frag.xy).xyz; - vec3 lv = vary_light.xyz-pos.xyz; - float dist2 = dot(lv,lv); - dist2 /= vary_light.w; - if (dist2 > 1.0) - { - discard; - } - - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; - - norm = normalize(norm); - float l_dist = -dot(lv, proj_n); - - vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); - if (proj_tc.z < 0.0) - { - discard; - } - - proj_tc.xyz /= proj_tc.w; - - float fa = gl_Color.a+1.0; - float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - - lv = proj_origin-pos.xyz; - lv = normalize(lv); - float da = dot(norm, lv); - - vec3 col = vec3(0,0,0); - - vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; - - float noise = texture2D(noiseMap, frag.xy/128.0).b; - if (proj_tc.z > 0.0 && - proj_tc.x < 1.0 && - proj_tc.y < 1.0 && - proj_tc.x > 0.0 && - proj_tc.y > 0.0) - { - float lit = 0.0; - if (da > 0.0) - { - float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); - float lod = diff * proj_lod; - - vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); - - vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; - - lit = da * dist_atten * noise; - - col = lcol*lit*diff_tex*shadow; - } - - float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - float lod = diff * proj_lod; - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); - //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); - float amb_da = proj_ambiance; - if (da > 0.0) - { - amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; - } - - amb_da += (da*da*0.5+0.5)*proj_ambiance; - - amb_da *= dist_atten * noise; - - amb_da = min(amb_da, 1.0-lit); - - col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; - } - - - vec4 spec = texture2DRect(specularRect, frag.xy); - if (spec.a > 0.0) - { - vec3 ref = reflect(normalize(pos), norm); - - //project from point pos in direction ref to plane proj_p, proj_n - vec3 pdelta = proj_p-pos; - float ds = dot(ref, proj_n); - - if (ds < 0.0) - { - vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - - vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; - - if (stc.z > 0.0) - { - stc.xy /= stc.z+proj_near; - - if (stc.x < 1.0 && - stc.y < 1.0 && - stc.x > 0.0 && - stc.y > 0.0) - { - vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); - col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow; - } - } - } - } - - /*if (spec.a > 0.0) - { - //vec3 ref = reflect(normalize(pos), norm); - float sa = dot(normalize(lv-normalize(pos)),norm);; - //sa = max(sa, 0.0); - //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); - sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*lcol*spec.rgb; - }*/ - - //attenuate point light contribution by SSAO component - col *= texture2DRect(lightMap, frag.xy).g; - - - gl_FragColor.rgb = col; - gl_FragColor.a = 0.0; -} diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl index 22bdd2c..d43fe6c 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl @@ -7,21 +7,17 @@ #extension GL_ARB_texture_rectangle : enable -uniform sampler2DRect depthMap; +uniform sampler2DRect positionMap; uniform sampler2DRect normalMap; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; -uniform sampler2DRectShadow shadowMap4; -uniform sampler2DRectShadow shadowMap5; +uniform sampler2DRect depthMap; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; uniform sampler2D noiseMap; -uniform sampler2D lightFunc; - - // Inputs -uniform mat4 shadow_matrix[6]; +uniform mat4 shadow_matrix[4]; uniform vec4 shadow_clip; uniform float ssao_radius; uniform float ssao_max_radius; @@ -31,25 +27,6 @@ uniform float ssao_factor_inv; varying vec2 vary_fragcoord; varying vec4 vary_light; -uniform mat4 inv_proj; -uniform vec2 screen_res; - -uniform float shadow_bias; -uniform float shadow_offset; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - //calculate decreases in ambient lighting when crowded out (SSAO) float calcAmbientOcclusion(vec4 pos, vec3 norm) { @@ -77,7 +54,7 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) for (int i = 0; i < 8; i++) { vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); - vec3 samppos_world = getPosition(samppos_screen).xyz; + vec3 samppos_world = texture2DRect(positionMap, samppos_screen).xyz; vec3 diff = pos_world - samppos_world; float dist2 = dot(diff, diff); @@ -97,18 +74,14 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); - return (1.0 - (float(points != 0) * angle_hidden)); + return 1.0 - (float(points != 0) * angle_hidden); } void main() { vec2 pos_screen = vary_fragcoord.xy; - - //try doing an unproject here - - vec4 pos = getPosition(pos_screen); - - vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; + vec4 pos = vec4(texture2DRect(positionMap, pos_screen).xyz, 1.0); + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL { @@ -117,45 +90,35 @@ void main() }*/ float shadow = 1.0; - float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); + float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); - vec4 spos = vec4(pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias), 1.0); - - //vec3 debug = vec3(0,0,0); - if (dp_directional_light == 0.0) { // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup shadow = 0.0; } - else if (spos.z > -shadow_clip.w) + else if (pos.z > -shadow_clip.w) { - vec4 lpos; - - if (spos.z < -shadow_clip.z) + if (pos.z < -shadow_clip.z) { - lpos = shadow_matrix[3]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap3, lpos).x; + vec4 lpos = shadow_matrix[3]*pos; + shadow = shadow2DProj(shadowMap3, lpos).x; shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); } - else if (spos.z < -shadow_clip.y) + else if (pos.z < -shadow_clip.y) { - lpos = shadow_matrix[2]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap2, lpos).x; + vec4 lpos = shadow_matrix[2]*pos; + shadow = shadow2DProj(shadowMap2, lpos).x; } - else if (spos.z < -shadow_clip.x) + else if (pos.z < -shadow_clip.x) { - lpos = shadow_matrix[1]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap1, lpos).x; + vec4 lpos = shadow_matrix[1]*pos; + shadow = shadow2DProj(shadowMap1, lpos).x; } else { - lpos = shadow_matrix[0]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap0, lpos).x; + vec4 lpos = shadow_matrix[0]*pos; + shadow = shadow2DProj(shadowMap0, lpos).x; } // take the most-shadowed value out of these two: @@ -163,17 +126,6 @@ void main() // * an unblurred dot product between the sun and this norm // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting shadow = min(shadow, dp_directional_light); - - /*debug.r = lpos.y / (lpos.w*screen_res.y); - - lpos.xy /= lpos.w*32.0; - if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1) - { - debug.gb = vec2(0.5, 0.5); - } - - debug += (1.0-shadow)*0.5;*/ - } else { @@ -183,18 +135,5 @@ void main() gl_FragColor[0] = shadow; gl_FragColor[1] = calcAmbientOcclusion(pos, norm); - - //spotlight shadow 1 - vec4 lpos = shadow_matrix[4]*spos; - lpos.xy *= screen_res; - gl_FragColor[2] = shadow2DRectProj(shadowMap4, lpos).x; - - //spotlight shadow 2 - lpos = shadow_matrix[5]*spos; - lpos.xy *= screen_res; - gl_FragColor[3] = shadow2DRectProj(shadowMap5, lpos).x; - - //gl_FragColor.rgb = pos.xyz; - //gl_FragColor.b = shadow; - //gl_FragColor.rgb = debug; + //gl_FragColor[2] is unused as of August 2008, may be used for debugging } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index 308b9b1..211b2e0 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -12,6 +12,7 @@ uniform sampler2D detail_3; uniform sampler2D alpha_ramp; varying vec3 vary_normal; +varying vec4 vary_position; void main() { @@ -27,8 +28,9 @@ void main() float alphaFinal = texture2D(alpha_ramp, gl_TexCoord[1].zw).a; vec4 outColor = mix( mix(color3, color2, alpha2), mix(color1, color0, alpha1), alphaFinal ); - gl_FragData[0] = vec4(outColor.rgb, 0.0); // Kl 0.0 looks fine atm however check grass above waterline when GI enabled in future releases! + gl_FragData[0] = vec4(outColor.rgb, 1.0); gl_FragData[1] = vec4(outColor.rgb*0.2, 0.2); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + gl_FragData[2] = vec4(normalize(vary_normal), 0.0); + gl_FragData[3] = vary_position; } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl index 3038b14..e9d6dca 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl @@ -6,6 +6,7 @@ */ varying vec3 vary_normal; +varying vec4 vary_position; vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1) { @@ -26,6 +27,7 @@ void main() //transform vertex gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_position = gl_ModelViewMatrix * gl_Vertex; vary_normal = normalize(gl_NormalMatrix * gl_Normal); // Transform and pass tex coords diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index 49c65f1..bc2c981 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -8,11 +8,13 @@ uniform sampler2D diffuseMap; varying vec3 vary_normal; +varying vec4 vary_position; void main() { vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); gl_FragData[0] = gl_Color*col; gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + gl_FragData[2] = vec4(normalize(vary_normal), 0.0); + gl_FragData[3] = vary_position; } diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl index 6b9dc2d..9131d7c 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl @@ -6,6 +6,7 @@ */ varying vec3 vary_normal; +varying vec4 vary_position; void main() { @@ -13,6 +14,8 @@ void main() gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + vary_position = gl_ModelViewMatrix * gl_Vertex; + vary_normal = normalize(gl_NormalMatrix * gl_Normal); gl_FrontColor = gl_Color; diff --git a/linden/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/linden/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index 6eea656..0a1f019 100644 --- a/linden/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -17,7 +17,7 @@ uniform sampler2DShadow shadowMap2; uniform sampler2DShadow shadowMap3; uniform sampler2D noiseMap; -uniform mat4 shadow_matrix[6]; +uniform mat4 shadow_matrix[4]; uniform vec4 shadow_clip; uniform float sunAngle; diff --git a/linden/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl b/linden/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl deleted file mode 100644 index 623ef7a..0000000 --- a/linden/indra/newview/app_settings/shaders/class1/effects/colorFilterF.glsl +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @file colorFilterF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2DRect RenderTexture; -uniform float brightness; -uniform float contrast; -uniform vec3 contrastBase; -uniform float saturation; -uniform vec3 lumWeights; - -const float gamma = 2.0; - -void main(void) -{ - vec3 color = vec3(texture2DRect(RenderTexture, gl_TexCoord[0].st)); - - /// Modulate brightness - color *= brightness; - - /// Modulate contrast - color = mix(contrastBase, color, contrast); - - /// Modulate saturation - color = mix(vec3(dot(color, lumWeights)), color, saturation); - - gl_FragColor = vec4(color, 1.0); -} diff --git a/linden/indra/newview/app_settings/shaders/class1/effects/drawQuadV.glsl b/linden/indra/newview/app_settings/shaders/class1/effects/drawQuadV.glsl deleted file mode 100644 index 29c2a09..0000000 --- a/linden/indra/newview/app_settings/shaders/class1/effects/drawQuadV.glsl +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @file drawQuadV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -void main(void) -{ - //transform vertex - gl_Position = ftransform(); - gl_TexCoord[0] = gl_MultiTexCoord0; - gl_TexCoord[1] = gl_MultiTexCoord1; -} diff --git a/linden/indra/newview/app_settings/shaders/class1/effects/nightVisionF.glsl b/linden/indra/newview/app_settings/shaders/class1/effects/nightVisionF.glsl deleted file mode 100644 index 271d5cf..0000000 --- a/linden/indra/newview/app_settings/shaders/class1/effects/nightVisionF.glsl +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file nightVisionF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2DRect RenderTexture; -uniform sampler2D NoiseTexture; -uniform float brightMult; -uniform float noiseStrength; - -float luminance(vec3 color) -{ - /// CALCULATING LUMINANCE (Using NTSC lum weights) - /// http://en.wikipedia.org/wiki/Luma_%28video%29 - return dot(color, vec3(0.299, 0.587, 0.114)); -} - -void main(void) -{ - /// Get scene color - vec3 color = vec3(texture2DRect(RenderTexture, gl_TexCoord[0].st)); - - /// Extract luminance and scale up by night vision brightness - float lum = luminance(color) * brightMult; - - /// Convert into night vision color space - /// Newer NVG colors (crisper and more saturated) - vec3 outColor = (lum * vec3(0.91, 1.21, 0.9)) + vec3(-0.07, 0.1, -0.12); - - /// Add noise - float noiseValue = texture2D(NoiseTexture, gl_TexCoord[1].st).r; - noiseValue = (noiseValue - 0.5) * noiseStrength; - - /// Older NVG colors (more muted) - // vec3 outColor = (lum * vec3(0.82, 0.75, 0.83)) + vec3(0.05, 0.32, -0.11); - - outColor += noiseValue; - - gl_FragColor = vec4(outColor, 1.0); -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl deleted file mode 100644 index 0055a73..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ /dev/null @@ -1,112 +0,0 @@ -/** - * @file alphaF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2D diffuseMap; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; -uniform sampler2D noiseMap; -uniform sampler2DRect depthMap; - -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; -uniform vec2 screen_res; - -vec3 atmosLighting(vec3 light); -vec3 scaleSoftClip(vec3 light); - -varying vec3 vary_ambient; -varying vec3 vary_directional; -varying vec3 vary_fragcoord; -varying vec3 vary_position; -varying vec3 vary_light; - -uniform float alpha_soften; - -uniform mat4 inv_proj; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -void main() -{ - vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - frag *= screen_res; - - vec3 samp_pos = getPosition(frag).xyz; - - float shadow = 1.0; - vec4 pos = vec4(vary_position, 1.0); - - vec4 spos = pos; - - if (spos.z > -shadow_clip.w) - { - vec4 lpos; - - if (spos.z < -shadow_clip.z) - { - lpos = shadow_matrix[3]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap3, lpos).x; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - else if (spos.z < -shadow_clip.y) - { - lpos = shadow_matrix[2]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap2, lpos).x; - } - else if (spos.z < -shadow_clip.x) - { - lpos = shadow_matrix[1]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap1, lpos).x; - } - else - { - lpos = shadow_matrix[0]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap0, lpos).x; - } - } - - vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a); - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col; - - color.rgb = atmosLighting(color.rgb); - - color.rgb = scaleSoftClip(color.rgb); - - if (samp_pos.z != 0.0) - { - float dist_factor = alpha_soften; - float a = gl_Color.a; - a *= a; - dist_factor *= 1.0/(1.0-a); - color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); - } - - //gl_FragColor = gl_Color; - gl_FragColor = color; - //gl_FragColor = vec4(1,0,1,1)*shadow; - -} - diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl deleted file mode 100644 index ab60b65..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file alphaV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); -void calcAtmospherics(vec3 inPositionEye); - -float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); - -vec3 atmosAmbient(vec3 light); -vec3 atmosAffectDirectionalLight(float lightIntensity); -vec3 scaleDownLight(vec3 light); -vec3 scaleUpLight(vec3 light); - -varying vec3 vary_ambient; -varying vec3 vary_directional; -varying vec3 vary_fragcoord; -varying vec3 vary_position; -varying vec3 vary_light; - -uniform float near_clip; -uniform float shadow_offset; -uniform float shadow_bias; - -void main() -{ - //transform vertex - gl_Position = ftransform(); - - gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - - vec4 pos = (gl_ModelViewMatrix * gl_Vertex); - vec3 norm = normalize(gl_NormalMatrix * gl_Normal); - - vary_position = vec4(pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias), 1.0); - - calcAtmospherics(pos.xyz); - - //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col; - col.a = gl_Color.a; - - // Add windlight lights - col.rgb = atmosAmbient(vec3(0.)); - col.rgb = scaleUpLight(col.rgb); - - // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); - col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); - col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); - col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); - col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); - col.rgb = scaleDownLight(col.rgb); - - vary_light = gl_LightSource[0].position.xyz; - - vary_ambient = col.rgb*gl_Color.rgb; - vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); - - col.rgb = min(col.rgb*gl_Color.rgb, 1.0); - - gl_FrontColor = col; - - gl_FogFragCoord = pos.z; - - pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); - -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl deleted file mode 100644 index fe83c3c..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @file avatarAlphaF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2D diffuseMap; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; -uniform sampler2D noiseMap; - -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; -uniform vec2 screen_res; - -vec3 atmosLighting(vec3 light); -vec3 scaleSoftClip(vec3 light); - -varying vec3 vary_ambient; -varying vec3 vary_directional; -varying vec4 vary_position; -varying vec3 vary_normal; - -void main() -{ - float shadow = 1.0; - vec4 pos = vary_position; - vec3 norm = normalize(vary_normal); - - vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; - - vec4 spos = pos; - - if (spos.z > -shadow_clip.w) - { - vec4 lpos; - - if (spos.z < -shadow_clip.z) - { - lpos = shadow_matrix[3]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap3, lpos).x; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - else if (spos.z < -shadow_clip.y) - { - lpos = shadow_matrix[2]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap2, lpos).x; - } - else if (spos.z < -shadow_clip.x) - { - lpos = shadow_matrix[1]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap1, lpos).x; - } - else - { - lpos = shadow_matrix[0]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap0, lpos).x; - } - } - - - vec4 col = vec4(vary_ambient + vary_directional*shadow, gl_Color.a); - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col; - - color.rgb = atmosLighting(color.rgb); - - color.rgb = scaleSoftClip(color.rgb); - - gl_FragColor = color; -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl deleted file mode 100644 index c1988d3..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file avatarAlphaV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); -mat4 getSkinnedTransform(); -void calcAtmospherics(vec3 inPositionEye); - -float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); - -vec3 atmosAmbient(vec3 light); -vec3 atmosAffectDirectionalLight(float lightIntensity); -vec3 scaleDownLight(vec3 light); -vec3 scaleUpLight(vec3 light); - -varying vec4 vary_position; -varying vec3 vary_ambient; -varying vec3 vary_directional; -varying vec3 vary_normal; - -void main() -{ - gl_TexCoord[0] = gl_MultiTexCoord0; - - vec4 pos; - vec3 norm; - - mat4 trans = getSkinnedTransform(); - pos.x = dot(trans[0], gl_Vertex); - pos.y = dot(trans[1], gl_Vertex); - pos.z = dot(trans[2], gl_Vertex); - pos.w = 1.0; - - norm.x = dot(trans[0].xyz, gl_Normal); - norm.y = dot(trans[1].xyz, gl_Normal); - norm.z = dot(trans[2].xyz, gl_Normal); - norm = normalize(norm); - - gl_Position = gl_ProjectionMatrix * pos; - vary_position = pos; - vary_normal = norm; - - calcAtmospherics(pos.xyz); - - //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col; - col.a = gl_Color.a; - - // Add windlight lights - col.rgb = atmosAmbient(vec3(0.)); - col.rgb = scaleUpLight(col.rgb); - - // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); - col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); - col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); - col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); - col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); - col.rgb = scaleDownLight(col.rgb); - - vary_ambient = col.rgb*gl_Color.rgb; - vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); - - col.rgb = min(col.rgb*gl_Color.rgb, 1.0); - - gl_FrontColor = col; - - gl_FogFragCoord = pos.z; - -} - - diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl deleted file mode 100644 index 1713fe9..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @file blurLightF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform sampler2DRect lightMap; - -uniform float dist_factor; -uniform float blur_size; -uniform vec2 delta; -uniform vec3 kern[32]; -uniform int kern_length; -uniform float kern_scale; - -varying vec2 vary_fragcoord; - -uniform mat4 inv_proj; -uniform vec2 screen_res; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -void main() -{ - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; - vec3 pos = getPosition(vary_fragcoord.xy).xyz; - vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba; - - vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); - - dlt /= max(-pos.z*dist_factor, 1.0); - - vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' - vec4 col = defined_weight.xyxx * ccol; - - for (int i = 1; i < kern_length; i++) - { - vec2 tc = vary_fragcoord.xy + kern[i].z*dlt; - vec3 samppos = getPosition(tc).xyz; - float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane - if (d*d <= 0.003) - { - col += texture2DRect(lightMap, tc)*kern[i].xyxx; - defined_weight += kern[i].xy; - } - } - - - - col /= defined_weight.xyxx; - - gl_FragColor = col; - - //gl_FragColor = ccol; -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl deleted file mode 100644 index b7f07e5..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @file blurLightF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -varying vec2 vary_fragcoord; -uniform vec2 screen_res; - -void main() -{ - //transform vertex - gl_Position = ftransform(); - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl deleted file mode 100644 index 6519594..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ /dev/null @@ -1,188 +0,0 @@ -/** - * @file multiSpotLightF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -#version 120 - -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform samplerCube environmentMap; -uniform sampler2DRect lightMap; -uniform sampler2D noiseMap; -uniform sampler2D lightFunc; -uniform sampler2D projectionMap; - -uniform mat4 proj_mat; //screen space to light space -uniform float proj_near; //near clip for projection -uniform vec3 proj_p; //plane projection is emitting from (in screen space) -uniform vec3 proj_n; -uniform float proj_focus; //distance from plane to begin blurring -uniform float proj_lod; //(number of mips in proj map) -uniform float proj_range; //range between near clip and far clip plane of projection -uniform float proj_ambient_lod; -uniform float proj_ambiance; -uniform float near_clip; -uniform float far_clip; - -uniform vec3 proj_origin; //origin of projection to be used for angular attenuation -uniform float sun_wash; -uniform int proj_shadow_idx; -uniform float shadow_fade; - -varying vec4 vary_light; - -varying vec4 vary_fragcoord; -uniform vec2 screen_res; - -uniform mat4 inv_proj; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -void main() -{ - vec4 frag = vary_fragcoord; - frag.xyz /= frag.w; - frag.xyz = frag.xyz*0.5+0.5; - frag.xy *= screen_res; - - vec3 pos = getPosition(frag.xy).xyz; - vec3 lv = vary_light.xyz-pos.xyz; - float dist2 = dot(lv,lv); - dist2 /= vary_light.w; - if (dist2 > 1.0) - { - discard; - } - - float shadow = 1.0; - - if (proj_shadow_idx >= 0) - { - vec4 shd = texture2DRect(lightMap, frag.xy); - float sh[2]; - sh[0] = shd.b; - sh[1] = shd.a; - shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); - } - - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; - - norm = normalize(norm); - float l_dist = -dot(lv, proj_n); - - vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); - if (proj_tc.z < 0.0) - { - discard; - } - - proj_tc.xyz /= proj_tc.w; - - float fa = gl_Color.a+1.0; - float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); - if (dist_atten <= 0.0) - { - discard; - } - - lv = proj_origin-pos.xyz; - lv = normalize(lv); - float da = dot(norm, lv); - - vec3 col = vec3(0,0,0); - - vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; - - float noise = texture2D(noiseMap, frag.xy/128.0).b; - if (proj_tc.z > 0.0 && - proj_tc.x < 1.0 && - proj_tc.y < 1.0 && - proj_tc.x > 0.0 && - proj_tc.y > 0.0) - { - float lit = 0.0; - float amb_da = proj_ambiance; - - if (da > 0.0) - { - float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); - float lod = diff * proj_lod; - - vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); - - vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; - - lit = da * dist_atten * noise; - - col = lcol*lit*diff_tex*shadow; - amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; - } - - //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_ambient_lod); - - amb_da += (da*da*0.5+0.5)*proj_ambiance; - - amb_da *= dist_atten * noise; - - amb_da = min(amb_da, 1.0-lit); - - col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; - } - - - vec4 spec = texture2DRect(specularRect, frag.xy); - if (spec.a > 0.0) - { - vec3 ref = reflect(normalize(pos), norm); - - //project from point pos in direction ref to plane proj_p, proj_n - vec3 pdelta = proj_p-pos; - float ds = dot(ref, proj_n); - - if (ds < 0.0) - { - vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - - vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); - - if (stc.z > 0.0) - { - stc.xy /= stc.w; - - if (stc.x < 1.0 && - stc.y < 1.0 && - stc.x > 0.0 && - stc.y > 0.0) - { - vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); - col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow; - } - } - } - } - - //attenuate point light contribution by SSAO component - col *= texture2DRect(lightMap, frag.xy).g; - - gl_FragColor.rgb = col; - gl_FragColor.a = 0.0; -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl deleted file mode 100644 index ee0e9d6..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @file postDeferredF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2DRect diffuseRect; -uniform sampler2DRect localLightMap; -uniform sampler2DRect sunLightMap; -uniform sampler2DRect giLightMap; -uniform sampler2D luminanceMap; -uniform sampler2DRect lightMap; - -uniform vec3 gi_lum_quad; -uniform vec3 sun_lum_quad; -uniform vec3 lum_quad; -uniform float lum_lod; -uniform vec4 ambient; - -uniform vec3 gi_quad; - -uniform vec2 screen_res; -varying vec2 vary_fragcoord; - -void main() -{ - vec2 tc = vary_fragcoord.xy; - vec3 lcol = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb; - - float lum = sqrt(lcol.r)*lum_quad.x+lcol.r*lcol.r*lum_quad.y+lcol.r*lum_quad.z; - - vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); - - float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g; - - vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; - gi_col = gi_col*gi_col*gi_quad.x + gi_col*gi_quad.y+gi_quad.z*ambocc*ambient.rgb; - gi_col *= diff; - - vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy); - - vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb; - - - float sun_lum = 1.0-lum; - sun_lum = sun_lum*sun_lum*sun_lum_quad.x + sun_lum*sun_lum_quad.y+sun_lum_quad.z; - - float gi_lum = lum; - gi_lum = gi_lum*gi_lum*gi_lum_quad.x+gi_lum*gi_lum_quad.y+gi_lum_quad.z; - gi_col *= 1.0/gi_lum; - - vec3 col = sun_col.rgb*(1.0+max(sun_lum,0.0))+gi_col+local_col; - - gl_FragColor.rgb = col.rgb; - gl_FragColor.a = max(sun_lum*min(sun_col.r+sun_col.g+sun_col.b, 1.0), sun_col.a); - - //gl_FragColor.rgb = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl deleted file mode 100644 index 9819232..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @file postDeferredV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -varying vec2 vary_fragcoord; -uniform vec2 screen_res; - -void main() -{ - //transform vertex - gl_Position = ftransform(); - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl deleted file mode 100644 index 52b79e3..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ /dev/null @@ -1,294 +0,0 @@ -/** - * @file softenLightF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect normalMap; -uniform sampler2DRect lightMap; -uniform sampler2D noiseMap; -uniform samplerCube environmentMap; -uniform sampler2D lightFunc; -uniform vec3 gi_quad; - -uniform float blur_size; -uniform float blur_fidelity; - -// Inputs -uniform vec4 morphFactor; -uniform vec3 camPosLocal; -//uniform vec4 camPosWorld; -uniform vec4 gamma; -uniform vec4 lightnorm; -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 vec4 glow; -uniform float scene_light_strength; -uniform vec3 env_mat[3]; -uniform vec4 shadow_clip; -uniform mat3 ssao_effect_mat; - -uniform sampler2DRect depthMap; -uniform mat4 inv_proj; -uniform vec2 screen_res; - -varying vec4 vary_light; -varying vec2 vary_fragcoord; - -vec3 vary_PositionEye; - -vec3 vary_SunlitColor; -vec3 vary_AmblitColor; -vec3 vary_AdditiveColor; -vec3 vary_AtmosAttenuation; - -vec4 getPosition(vec2 pos_screen) -{ //get position in screen space (world units) given window coordinate and depth map - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -vec3 getPositionEye() -{ - return vary_PositionEye; -} -vec3 getSunlitColor() -{ - return vary_SunlitColor; -} -vec3 getAmblitColor() -{ - return vary_AmblitColor; -} -vec3 getAdditiveColor() -{ - return vary_AdditiveColor; -} -vec3 getAtmosAttenuation() -{ - return vary_AtmosAttenuation; -} - - -void setPositionEye(vec3 v) -{ - vary_PositionEye = v; -} - -void setSunlitColor(vec3 v) -{ - vary_SunlitColor = v; -} - -void setAmblitColor(vec3 v) -{ - vary_AmblitColor = v; -} - -void setAdditiveColor(vec3 v) -{ - vary_AdditiveColor = v; -} - -void setAtmosAttenuation(vec3 v) -{ - vary_AtmosAttenuation = v; -} - -void calcAtmospherics(vec3 inPositionEye, float ambFactor) { - - vec3 P = 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); - - vec3 tmpLightnorm = lightnorm.xyz; - - vec3 Pn = normalize(P); - float Plen = length(P); - - vec4 temp1 = vec4(0); - vec3 temp2 = vec3(0); - vec4 blue_weight; - vec4 haze_weight; - 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 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); - //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); - blue_weight = blue_density / temp1; - haze_weight = vec4(haze_density.r) / temp1; - - //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain) - temp2.y = max(0.0, tmpLightnorm.y); - temp2.y = 1. / temp2.y; - sunlight *= exp( - light_atten * temp2.y); - - // main atmospheric scattering line integral - temp2.z = Plen * density_multiplier.x; - - // Transparency (-> temp1) - // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati - // compiler gets confused. - temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); - - //final atmosphere attenuation factor - setAtmosAttenuation(temp1.rgb); - - //compute haze glow - //(can use temp2.x as temp because we haven't used it yet) - temp2.x = dot(Pn, tmpLightnorm.xyz); - temp2.x = 1. - temp2.x; - //temp2.x is 0 at the sun and increases away from sun - temp2.x = max(temp2.x, .03); //was glow.y - //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) - temp2.x *= glow.x; - //higher glow.x gives dimmer glow (because next step is 1 / "angle") - temp2.x = pow(temp2.x, glow.z); - //glow.z should be negative, so we're doing a sort of (1 / "angle") function - - //add "minimum anti-solar illumination" - temp2.x += .25; - - //increase ambient when there are more clouds - vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 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 - * // The following line of code performs the equivalent of: - * float ambAlpha = tmpAmbient.a; - * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis - * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); - * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); - */ - tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); - - //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 - + tmpAmbient))); - - //brightness of surface both sunlight and ambient - setSunlitColor(vec3(sunlight * .5)); - setAmblitColor(vec3(tmpAmbient * .25)); - setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1)); -} - -vec3 atmosLighting(vec3 light) -{ - light *= getAtmosAttenuation().r; - light += getAdditiveColor(); - return (2.0 * light); -} - -vec3 atmosTransport(vec3 light) { - light *= getAtmosAttenuation().r; - light += getAdditiveColor() * 2.0; - return light; -} -vec3 atmosGetDiffuseSunlightColor() -{ - return getSunlitColor(); -} - -vec3 scaleDownLight(vec3 light) -{ - return (light / scene_light_strength ); -} - -vec3 scaleUpLight(vec3 light) -{ - return (light * scene_light_strength); -} - -vec3 atmosAmbient(vec3 light) -{ - return getAmblitColor() + light / 2.0; -} - -vec3 atmosAffectDirectionalLight(float lightIntensity) -{ - return getSunlitColor() * lightIntensity; -} - -vec3 scaleSoftClip(vec3 light) -{ - //soft clip effect: - light = 1. - clamp(light, vec3(0.), vec3(1.)); - light = 1. - pow(light, gamma.xxx); - - return light; -} - -void main() -{ - vec2 tc = vary_fragcoord.xy; - vec3 pos = getPosition(tc).xyz; - vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0; - vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; - - float da = max(dot(norm.xyz, vary_light.xyz), 0.0); - - vec4 diffuse = texture2DRect(diffuseRect, tc); - vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); - - vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; - float scol = max(scol_ambocc.r, diffuse.a); - float ambocc = scol_ambocc.g; - - calcAtmospherics(pos.xyz, ambocc); - - vec3 col = atmosAmbient(vec3(0)); - col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a)); - - col *= diffuse.rgb; - - if (spec.a > 0.0) - { - vec3 ref = normalize(reflect(pos.xyz, norm.xyz)); - float sa = dot(ref, vary_light.xyz); - col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; - } - - col = atmosLighting(col); - col = scaleSoftClip(col); - - gl_FragColor.rgb = col; - - //gl_FragColor.rgb = gi_col.rgb; - gl_FragColor.a = 0.0; - - //gl_FragColor.rg = scol_ambocc.rg; - //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb; - //gl_FragColor.rgb = norm.rgb*0.5+0.5; - //gl_FragColor.rgb = vec3(ambocc); - //gl_FragColor.rgb = vec3(scol); -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl deleted file mode 100644 index ad8af47..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @file softenLightF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform vec2 screen_res; - -varying vec4 vary_light; -varying vec2 vary_fragcoord; -void main() -{ - //transform vertex - gl_Position = ftransform(); - - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; - - vec4 tex = gl_MultiTexCoord0; - tex.w = 1.0; - - vary_light = gl_MultiTexCoord0; -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl deleted file mode 100644 index d653408..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ /dev/null @@ -1,199 +0,0 @@ -/** - * @file spotLightF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -#version 120 - -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform samplerCube environmentMap; -uniform sampler2DRect lightMap; -uniform sampler2D noiseMap; -uniform sampler2D lightFunc; -uniform sampler2D projectionMap; - -uniform mat4 proj_mat; //screen space to light space -uniform float proj_near; //near clip for projection -uniform vec3 proj_p; //plane projection is emitting from (in screen space) -uniform vec3 proj_n; -uniform float proj_focus; //distance from plane to begin blurring -uniform float proj_lod; //(number of mips in proj map) -uniform float proj_range; //range between near clip and far clip plane of projection -uniform float proj_ambiance; -uniform float near_clip; -uniform float far_clip; - -uniform vec3 proj_origin; //origin of projection to be used for angular attenuation -uniform float sun_wash; -uniform int proj_shadow_idx; -uniform float shadow_fade; - -varying vec4 vary_light; - -varying vec4 vary_fragcoord; -uniform vec2 screen_res; - -uniform mat4 inv_proj; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -void main() -{ - vec4 frag = vary_fragcoord; - frag.xyz /= frag.w; - frag.xyz = frag.xyz*0.5+0.5; - frag.xy *= screen_res; - - float shadow = 1.0; - - if (proj_shadow_idx >= 0) - { - vec4 shd = texture2DRect(lightMap, frag.xy); - float sh[2]; - sh[0] = shd.b; - sh[1] = shd.a; - shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); - } - - vec3 pos = getPosition(frag.xy).xyz; - vec3 lv = vary_light.xyz-pos.xyz; - float dist2 = dot(lv,lv); - dist2 /= vary_light.w; - if (dist2 > 1.0) - { - discard; - } - - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; - - norm = normalize(norm); - float l_dist = -dot(lv, proj_n); - - vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); - if (proj_tc.z < 0.0) - { - discard; - } - - proj_tc.xyz /= proj_tc.w; - - float fa = gl_Color.a+1.0; - float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - - lv = proj_origin-pos.xyz; - lv = normalize(lv); - float da = dot(norm, lv); - - vec3 col = vec3(0,0,0); - - vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; - - float noise = texture2D(noiseMap, frag.xy/128.0).b; - if (proj_tc.z > 0.0 && - proj_tc.x < 1.0 && - proj_tc.y < 1.0 && - proj_tc.x > 0.0 && - proj_tc.y > 0.0) - { - float lit = 0.0; - if (da > 0.0) - { - float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); - float lod = diff * proj_lod; - - vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); - - vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; - - lit = da * dist_atten * noise; - - col = lcol*lit*diff_tex*shadow; - } - - float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - float lod = diff * proj_lod; - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); - //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); - float amb_da = proj_ambiance; - if (da > 0.0) - { - amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; - } - - amb_da += (da*da*0.5+0.5)*proj_ambiance; - - amb_da *= dist_atten * noise; - - amb_da = min(amb_da, 1.0-lit); - - col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; - } - - - vec4 spec = texture2DRect(specularRect, frag.xy); - if (spec.a > 0.0) - { - vec3 ref = reflect(normalize(pos), norm); - - //project from point pos in direction ref to plane proj_p, proj_n - vec3 pdelta = proj_p-pos; - float ds = dot(ref, proj_n); - - if (ds < 0.0) - { - vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - - vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; - - if (stc.z > 0.0) - { - stc.xy /= stc.z+proj_near; - - if (stc.x < 1.0 && - stc.y < 1.0 && - stc.x > 0.0 && - stc.y > 0.0) - { - vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); - col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow; - } - } - } - } - - /*if (spec.a > 0.0) - { - //vec3 ref = reflect(normalize(pos), norm); - float sa = dot(normalize(lv-normalize(pos)),norm);; - //sa = max(sa, 0.0); - //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); - sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*lcol*spec.rgb; - }*/ - - //attenuate point light contribution by SSAO component - col *= texture2DRect(lightMap, frag.xy).g; - - - gl_FragColor.rgb = col; - gl_FragColor.a = 0.0; -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl deleted file mode 100644 index 8ced94e..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ /dev/null @@ -1,203 +0,0 @@ -/** - * @file sunLightF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; -uniform sampler2DRectShadow shadowMap4; -uniform sampler2DRectShadow shadowMap5; -uniform sampler2D noiseMap; - -uniform sampler2D lightFunc; - - -// Inputs -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; -uniform float ssao_radius; -uniform float ssao_max_radius; -uniform float ssao_factor; -uniform float ssao_factor_inv; - -varying vec2 vary_fragcoord; -varying vec4 vary_light; - -uniform mat4 inv_proj; -uniform vec2 screen_res; - -uniform float shadow_bias; -uniform float shadow_offset; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -//calculate decreases in ambient lighting when crowded out (SSAO) -float calcAmbientOcclusion(vec4 pos, vec3 norm) -{ - vec2 kern[8]; - // exponentially (^2) distant occlusion samples spread around origin - kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; - kern[1] = vec2(1.0, 0.0) * 0.250*0.250; - kern[2] = vec2(0.0, 1.0) * 0.375*0.375; - kern[3] = vec2(0.0, -1.0) * 0.500*0.500; - kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; - kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; - kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; - kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; - - vec2 pos_screen = vary_fragcoord.xy; - vec3 pos_world = pos.xyz; - vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; - - float angle_hidden = 0.0; - int points = 0; - - float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); - - // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) - for (int i = 0; i < 8; i++) - { - vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); - vec3 samppos_world = getPosition(samppos_screen).xyz; - - vec3 diff = pos_world - samppos_world; - float dist2 = dot(diff, diff); - - // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area - // --> solid angle shrinking by the square of distance - //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 - //(k should vary inversely with # of samples, but this is taken care of later) - - //if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces - // angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor) - angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv); - - // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" - points = points + int(diff.z > -1.0); - } - - angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); - - return (1.0 - (float(points != 0) * angle_hidden)); -} - -void main() -{ - vec2 pos_screen = vary_fragcoord.xy; - - //try doing an unproject here - - vec4 pos = getPosition(pos_screen); - - vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; - - /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL - { - gl_FragColor = vec4(0.0); // doesn't matter - return; - }*/ - - float shadow = 1.0; - float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); - - vec4 spos = vec4(pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias), 1.0); - - //vec3 debug = vec3(0,0,0); - - if (spos.z > -shadow_clip.w) - { - if (dp_directional_light == 0.0) - { - // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup - shadow = 0.0; - } - else - { - vec4 lpos; - - if (spos.z < -shadow_clip.z) - { - lpos = shadow_matrix[3]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap3, lpos).x; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - else if (spos.z < -shadow_clip.y) - { - lpos = shadow_matrix[2]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap2, lpos).x; - } - else if (spos.z < -shadow_clip.x) - { - lpos = shadow_matrix[1]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap1, lpos).x; - } - else - { - lpos = shadow_matrix[0]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap0, lpos).x; - } - - // take the most-shadowed value out of these two: - // * the blurred sun shadow in the light (shadow) map - // * an unblurred dot product between the sun and this norm - // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting - shadow = min(shadow, dp_directional_light); - } - - /*debug.r = lpos.y / (lpos.w*screen_res.y); - - lpos.xy /= lpos.w*32.0; - if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1) - { - debug.gb = vec2(0.5, 0.5); - } - - debug += (1.0-shadow)*0.5;*/ - - } - else - { - // more distant than the shadow map covers - shadow = 1.0; - } - - gl_FragColor[0] = shadow; - gl_FragColor[1] = calcAmbientOcclusion(pos, norm); - - //spotlight shadow 1 - vec4 lpos = shadow_matrix[4]*spos; - lpos.xy *= screen_res; - gl_FragColor[2] = shadow2DRectProj(shadowMap4, lpos).x; - - //spotlight shadow 2 - lpos = shadow_matrix[5]*spos; - lpos.xy *= screen_res; - gl_FragColor[3] = shadow2DRectProj(shadowMap5, lpos).x; - - //gl_FragColor.rgb = pos.xyz; - //gl_FragColor.b = shadow; - //gl_FragColor.rgb = debug; -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl deleted file mode 100644 index 5081485..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @file sunLightF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -varying vec4 vary_light; -varying vec2 vary_fragcoord; - -uniform vec2 screen_res; - -void main() -{ - //transform vertex - gl_Position = ftransform(); - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; - vec4 tex = gl_MultiTexCoord0; - tex.w = 1.0; - - vary_light = gl_MultiTexCoord0; - - gl_FrontColor = gl_Color; -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl deleted file mode 100644 index 7342186..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @file waterF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -vec3 scaleSoftClip(vec3 inColor); -vec3 atmosTransport(vec3 inColor); - -uniform sampler2D bumpMap; -uniform sampler2D screenTex; -uniform sampler2D refTex; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; -uniform sampler2D noiseMap; - -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; - -uniform float sunAngle; -uniform float sunAngle2; -uniform vec3 lightDir; -uniform vec3 specular; -uniform float lightExp; -uniform float refScale; -uniform float kd; -uniform vec2 screenRes; -uniform vec3 normScale; -uniform float fresnelScale; -uniform float fresnelOffset; -uniform float blurMultiplier; -uniform vec2 screen_res; -uniform mat4 norm_mat; //region space to screen space - -//bigWave is (refCoord.w, view.w); -varying vec4 refCoord; -varying vec4 littleWave; -varying vec4 view; -varying vec4 vary_position; - -void main() -{ - vec4 color; - float dist = length(view.xy); - - //normalize view vector - vec3 viewVec = normalize(view.xyz); - - //get wave normals - vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0; - vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0; - vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0; - //get base fresnel components - - vec3 df = vec3( - dot(viewVec, wave1), - dot(viewVec, (wave2 + wave3) * 0.5), - dot(viewVec, wave3) - ) * fresnelScale + fresnelOffset; - df *= df; - - vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; - - float dist2 = dist; - dist = max(dist, 5.0); - - float dmod = sqrt(dist); - - vec2 dmod_scale = vec2(dmod*dmod, dmod); - - //get reflected color - vec2 refdistort1 = wave1.xy*normScale.x; - vec2 refvec1 = distort+refdistort1/dmod_scale; - vec4 refcol1 = texture2D(refTex, refvec1); - - vec2 refdistort2 = wave2.xy*normScale.y; - vec2 refvec2 = distort+refdistort2/dmod_scale; - vec4 refcol2 = texture2D(refTex, refvec2); - - vec2 refdistort3 = wave3.xy*normScale.z; - vec2 refvec3 = distort+refdistort3/dmod_scale; - vec4 refcol3 = texture2D(refTex, refvec3); - - vec4 refcol = refcol1 + refcol2 + refcol3; - float df1 = df.x + df.y + df.z; - refcol *= df1 * 0.333; - - vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5; - //wavef.z *= max(-viewVec.z, 0.1); - wavef = normalize(wavef); - - float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset; - - vec2 refdistort4 = wavef.xy*0.125; - refdistort4.y -= abs(refdistort4.y); - vec2 refvec4 = distort+refdistort4/dmod; - float dweight = min(dist2*blurMultiplier, 1.0); - vec4 baseCol = texture2D(refTex, refvec4); - refcol = mix(baseCol*df2, refcol, dweight); - - //get specular component - //float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0); - - //harden specular - //spec = pow(spec, 128.0); - - //figure out distortion vector (ripply) - vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0); - - vec4 fb = texture2D(screenTex, distort2); - - //mix with reflection - // Note we actually want to use just df1, but multiplying by 0.999999 gets around and nvidia compiler bug - color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999); - - float shadow = 1.0; - vec4 pos = vary_position; - - vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; - vec4 spos = pos; - - //spec *= shadow; - //color.rgb += spec * specular; - - //color.rgb = atmosTransport(color.rgb); - //color.rgb = scaleSoftClip(color.rgb); - //color.a = spec * sunAngle2; - - //wavef.z *= 0.1f; - wavef = normalize(wavef); - wavef = (norm_mat*vec4(wavef, 1.0)).xyz; - - gl_FragData[0] = vec4(color.rgb, 0.75); - gl_FragData[1] = vec4(1,1,1, 0.8); - gl_FragData[2] = vec4(wavef*0.5+0.5, 0.f); -} diff --git a/linden/indra/newview/app_settings/shaders/class2/deferred/waterV.glsl b/linden/indra/newview/app_settings/shaders/class2/deferred/waterV.glsl deleted file mode 100644 index b45e5c5..0000000 --- a/linden/indra/newview/app_settings/shaders/class2/deferred/waterV.glsl +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file waterV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -void calcAtmospherics(vec3 inPositionEye); - -uniform vec2 d1; -uniform vec2 d2; -uniform float time; -uniform vec3 eyeVec; -uniform float waterHeight; - -varying vec4 refCoord; -varying vec4 littleWave; -varying vec4 view; - -varying vec4 vary_position; - -float wave(vec2 v, float t, float f, vec2 d, float s) -{ - return (dot(d, v)*f + t*s)*f; -} - -void main() -{ - //transform vertex - vec4 position = gl_Vertex; - mat4 modelViewProj = gl_ModelViewProjectionMatrix; - - vec4 oPosition; - - //get view vector - vec3 oEyeVec; - oEyeVec.xyz = position.xyz-eyeVec; - - float d = length(oEyeVec.xy); - float ld = min(d, 2560.0); - - position.xy = eyeVec.xy + oEyeVec.xy/d*ld; - view.xyz = oEyeVec; - - d = clamp(ld/1536.0-0.5, 0.0, 1.0); - d *= d; - - oPosition = position; - oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d); - vary_position = gl_ModelViewMatrix * oPosition; - oPosition = modelViewProj * oPosition; - - refCoord.xyz = oPosition.xyz + vec3(0,0,0.2); - - //get wave position parameter (create sweeping horizontal waves) - vec3 v = position.xyz; - v.x += (cos(v.x*0.08/*+time*0.01*/)+sin(v.y*0.02))*6.0; - - //push position for further horizon effect. - position.xyz = oEyeVec.xyz*(waterHeight/oEyeVec.z); - position.w = 1.0; - position = position*gl_ModelViewMatrix; - - calcAtmospherics((gl_ModelViewMatrix * gl_Vertex).xyz); - - - //pass wave parameters to pixel shader - vec2 bigWave = (v.xy) * vec2(0.04,0.04) + d1 * time * 0.055; - //get two normal map (detail map) texture coordinates - littleWave.xy = (v.xy) * vec2(0.45, 0.9) + d2 * time * 0.13; - littleWave.zw = (v.xy) * vec2(0.1, 0.2) + d1 * time * 0.1; - view.w = bigWave.y; - refCoord.w = bigWave.x; - - gl_Position = oPosition; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/avatarF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/avatarF.glsl deleted file mode 100644 index 9cc71a7..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/avatarF.glsl +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file avatarF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2D diffuseMap; - -varying vec3 vary_normal; - -void main() -{ - gl_FragData[0] = vec4(gl_Color.rgb * texture2D(diffuseMap, gl_TexCoord[0].xy).rgb, 0.0); - gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); -} - diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/bumpF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/bumpF.glsl deleted file mode 100644 index 6eb4a51..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/bumpF.glsl +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @file bumpF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2D diffuseMap; -uniform sampler2D bumpMap; - -varying vec3 vary_mat0; -varying vec3 vary_mat1; -varying vec3 vary_mat2; - -void main() -{ - vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; - vec3 norm = texture2D(bumpMap, gl_TexCoord[0].xy).rgb * 2.0 - 1.0; - - vec3 tnorm = vec3(dot(norm,vary_mat0), - dot(norm,vary_mat1), - dot(norm,vary_mat2)); - - gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0); - gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); - gl_FragData[2] = vec4(normalize(tnorm)*0.5+0.5, 0.0); -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/diffuseF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/diffuseF.glsl deleted file mode 100644 index c9f75f7..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/diffuseF.glsl +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file diffuseF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2D diffuseMap; - -varying vec3 vary_normal; - -void main() -{ - vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; - gl_FragData[0] = vec4(gl_Color.rgb*col, 0.0); - gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl deleted file mode 100644 index 7325825..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @file giDownsampleF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2DRect giLightMap; - -uniform vec2 kern[32]; -uniform float dist_factor; -uniform float blur_size; -uniform vec2 delta; -uniform int kern_length; -uniform float kern_scale; -uniform vec3 blur_quad; - -varying vec2 vary_fragcoord; - -uniform mat4 inv_proj; -uniform vec2 screen_res; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -float getDepth(vec2 pos_screen) -{ - float z = texture2DRect(depthMap, pos_screen.xy).a; - z = z*2.0-1.0; - vec4 ndc = vec4(0.0, 0.0, z, 1.0); - vec4 p = inv_proj*ndc; - return p.z/p.w; -} - -void main() -{ - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; - float depth = getDepth(vary_fragcoord.xy); - - vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; - vec2 dlt = kern_scale * delta/(vec2(1.0,1.0)+norm.xy*norm.xy); - dlt /= clamp(-depth*blur_quad.x, 1.0, 3.0); - float defined_weight = kern[0].x; - vec3 col = ccol*kern[0].x; - - for (int i = 0; i < kern_length; i++) - { - vec2 tc = vary_fragcoord.xy + kern[i].y*dlt; - vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0; - - float d = dot(norm.xyz, sampNorm); - - if (d > 0.5) - { - float sampdepth = getDepth(tc.xy); - sampdepth -= depth; - if (sampdepth*sampdepth < blur_quad.z) - { - col += texture2DRect(giLightMap, tc).rgb*kern[i].x; - defined_weight += kern[i].x; - } - } - } - - col /= defined_weight; - - //col = ccol; - - col = col*blur_quad.y; - - gl_FragData[0].xyz = col; - - //gl_FragColor = ccol; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl deleted file mode 100644 index 6adcda8..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @file postgiV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -varying vec2 vary_fragcoord; -uniform vec2 screen_res; - -void main() -{ - //transform vertex - gl_Position = ftransform(); - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/giF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/giF.glsl deleted file mode 100644 index 43da836..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/giF.glsl +++ /dev/null @@ -1,219 +0,0 @@ -/** - * @file giF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform sampler2DRect lightMap; -uniform sampler2DRect specularRect; - -uniform sampler2D noiseMap; - -uniform sampler2D diffuseGIMap; -uniform sampler2D specularGIMap; -uniform sampler2D normalGIMap; -uniform sampler2D depthGIMap; - -uniform sampler2D lightFunc; - -// Inputs -varying vec2 vary_fragcoord; - -uniform vec2 screen_res; - -uniform vec4 sunlight_color; - -uniform mat4 inv_proj; -uniform mat4 gi_mat; //gPipeline.mGIMatrix - eye space to sun space -uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space -uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix -uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space -uniform float gi_radius; -uniform float gi_intensity; -uniform int gi_samples; -uniform vec2 gi_kern[25]; -uniform vec2 gi_scale; -uniform vec3 gi_quad; -uniform vec3 gi_spec; -uniform float gi_direction_weight; -uniform float gi_light_offset; -uniform float gi_range; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -vec4 getGIPosition(vec2 gi_tc) -{ - float depth = texture2D(depthGIMap, gi_tc).a; - vec2 sc = gi_tc*2.0; - sc -= vec2(1.0, 1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = gi_inv_proj*ndc; - pos.xyz /= pos.w; - pos.w = 1.0; - return pos; -} - -vec3 giAmbient(vec3 pos, vec3 norm) -{ - vec4 gi_c = gi_mat_proj * vec4(pos, 1.0); - gi_c.xyz /= gi_c.w; - - vec4 gi_pos = gi_mat*vec4(pos,1.0); - vec3 gi_norm = (gi_norm_mat*vec4(norm,1.0)).xyz; - gi_norm = normalize(gi_norm); - - vec4 c_spec = texture2DRect(specularRect, vary_fragcoord.xy); - gi_pos.xyz += (texture2D(noiseMap, vary_fragcoord.xy/128.0).x)*gi_spec.z*gi_norm.xyz; - vec2 tcx = gi_norm.xy; - vec2 tcy = gi_norm.yx; - - vec4 eye_pos = gi_mat*vec4(0,0,0,1.0); - - vec3 eye_dir = normalize(gi_pos.xyz-eye_pos.xyz); - vec3 eye_ref = reflect(eye_dir, gi_norm); - - //vec3 eye_dir = vec3(0,0,-1); - //eye_dir = (gi_norm_mat*vec4(eye_dir, 1.0)).xyz; - //eye_dir = normalize(eye_dir); - - //float round_x = gi_scale.x; - //float round_y = gi_scale.y; - - vec3 debug = texture2D(normalGIMap, gi_c.xy).rgb; - //debug.xz = vec2(0.0,0.0); - //debug = fract(debug); - - float round_x = 1.0/64.0; - float round_y = 1.0/64.0; - - //gi_c.x = floor(gi_c.x/round_x+0.5)*round_x; - //gi_c.y = floor(gi_c.y/round_y+0.5)*round_y; - - float da = texture2DRect(lightMap, vary_fragcoord.xy).r; - - vec3 fdiff = vec3(da); - - if (da > 0.0) - { - vec3 ha = -eye_dir; - ha.z += 1.0; - ha = normalize(ha); - - float sa = dot(ha,gi_norm); - da = min(da, texture2D(lightFunc, vec2(sa, c_spec.a)).a); - fdiff += da*(c_spec.rgb*c_spec.a*2.0); - } - - float fda = da; - - vec3 rcol = vec3(0,0,0); - - float fsa = 0.0; - - - for (int i = -1; i <= 1; i += 1 ) - { - for (int j = -1; j <= 1; j+= 1) - { - vec2 tc = vec2(i, j)*0.75+gi_norm.xy; - vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0+tc*0.5).xyz; - tc += gi_norm.xy*nz.z; - tc += nz.xy*2.0; - tc /= gi_samples; - tc += gi_c.xy; - - vec3 lnorm = -normalize(texture2D(normalGIMap, tc.xy).xyz*2.0-1.0); - vec3 lpos = getGIPosition(tc.xy).xyz; - - vec3 at = lpos-gi_pos.xyz; - float dist = dot(at,at); - float da = clamp(1.0/(gi_spec.x*dist), 0.0, 1.0); - - - if (da > 0.01) - { //possible contribution of indirect light to this surface - vec3 ldir = at; - - float ld = -dot(ldir, lnorm); - - if (ld < 0.0) - { - float ang_atten = dot(ldir, gi_norm); - - if (ang_atten > 0.0) - { - vec4 spec = texture2D(specularGIMap, tc.xy); - at = normalize(at); - vec3 diff; - - { //contribution from indirect source to visible pixel - vec3 ha = at; - ha.z -= 1.0; - ha = normalize(ha); - float sa = dot(ha,lnorm); - da = min(da, texture2D(lightFunc, vec2(sa, spec.a)).a); - - diff = texture2D(diffuseGIMap, tc.xy).rgb+spec.rgb*spec.a*2.0; - } - - if (da > 0.0) - { //contribution from visible pixel to eye - vec3 ha = normalize(at-eye_dir); - float sa = dot(ha, gi_norm); - da = min(da, texture2D(lightFunc, vec2(sa, c_spec.a)).a); - fda += da; - fdiff += da*(c_spec.rgb*c_spec.a*2.0+vec3(1,1,1))*diff.rgb; - } - } - } - } - } - } - - //fdiff /= max(gi_spec.y*fda, gi_quad.z); - //fdiff = clamp(fdiff, vec3(0), vec3(1)); - fdiff *= 64.0; - fdiff *= sunlight_color.rgb; - - vec3 ret = fda*fdiff; - //ret = ret*ret*gi_quad.x+ret*gi_quad.y+gi_quad.z; - - //fda *= nz.z; - - //rcol.rgb *= gi_intensity; - //return rcol.rgb+vary_AmblitColor.rgb*0.25; - //return vec4(debug, 0.0); - //return vec4(fda*fdiff, 0.0); - return clamp(ret,vec3(0.0), vec3(1.0)); - //return debug.xyz; -} - -void main() -{ - vec2 pos_screen = vary_fragcoord.xy; - vec4 pos = getPosition(pos_screen); - - float rad = gi_range*0.5; - - vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; - float dist = max(length(pos.xyz)-rad, 0.0); - - float da = clamp(1.0-dist/rad, 0.0, 1.0); - gl_FragData[0].xyz = da > 0.0 ? giAmbient(pos, norm)*da : vec3(0,0,0); -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/giV.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/giV.glsl deleted file mode 100644 index 71dcea9..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/giV.glsl +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @file giV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -varying vec2 vary_fragcoord; - -uniform vec2 screen_res; - -void main() -{ - //transform vertex - gl_Position = ftransform(); - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; - vec4 tex = gl_MultiTexCoord0; - tex.w = 1.0; - - gl_FrontColor = gl_Color; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl deleted file mode 100644 index 0de0d11..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @file luminanceF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2DRect diffuseMap; - -varying vec2 vary_fragcoord; -uniform float fade; -void main() -{ - gl_FragColor.rgb = texture2DRect(diffuseMap, vary_fragcoord.xy).rgb; - gl_FragColor.a = fade; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl deleted file mode 100644 index db8775f..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @file giV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -varying vec2 vary_fragcoord; - -uniform vec2 screen_res; - -void main() -{ - //transform vertex - gl_Position = ftransform(); - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; - - gl_FrontColor = gl_Color; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl deleted file mode 100644 index 609fb1d..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file postDeferredF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect localLightMap; -uniform sampler2DRect sunLightMap; -uniform sampler2DRect giLightMap; -uniform sampler2D luminanceMap; -uniform sampler2DRect lightMap; -uniform sampler2D lightFunc; - - -uniform vec3 gi_lum_quad; -uniform vec3 sun_lum_quad; -uniform vec3 lum_quad; -uniform float lum_lod; -uniform vec4 ambient; - -uniform vec3 gi_quad; - -uniform vec2 screen_res; -varying vec2 vary_fragcoord; - -void main() -{ - vec2 tc = vary_fragcoord.xy; - vec3 lcol = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb; - - float lum = sqrt(lcol.r)*lum_quad.x+lcol.r*lcol.r*lum_quad.y+lcol.r*lum_quad.z; - - vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); - vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); - - float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g; - - vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; - vec3 gi_col = ccol; - /*for (int i = -1; i <= 1; i+=1) - { - for (int j = -1; j <= 1; j+=1) - { - vec2 tc = vec2(i,j); - float wght = 1.0/(length(tc)+1.0); - gi_col += texture2DRect(giLightMap, vary_fragcoord.xy+vec2(i,j)).rgb * wght; - } - }*/ - - //gi_col *= 1.0+spec.a*4.0; - gi_col = (sqrt(gi_col)*gi_quad.x + gi_col*gi_quad.y)*(diff.rgb+spec.rgb*spec.a)+gi_quad.z*ambocc*ambient.rgb*diff.rgb; - - vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy); - - vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb; - - - float sun_lum = 1.0-lum; - sun_lum = sun_lum*sun_lum*sun_lum_quad.x + sun_lum*sun_lum_quad.y+sun_lum_quad.z; - - float gi_lum = lum; - gi_lum = gi_lum*gi_lum*gi_lum_quad.x+gi_lum*gi_lum_quad.y+gi_lum_quad.z; - gi_col *= 1.0/gi_lum; - - - vec3 col = sun_col.rgb*(1.0+max(sun_lum,0.0))+gi_col+local_col; - - gl_FragColor.rgb = col.rgb; - gl_FragColor.a = max(sun_lum*min(sun_col.r+sun_col.g+sun_col.b, 1.0), sun_col.a); - - //gl_FragColor.rgb = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; - //gl_FragColor.rgb = vec3(texture2D(lightFunc, vary_fragcoord.xy/512.0-vec2(0.5, 0.5)).a); -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl deleted file mode 100644 index 9819232..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @file postDeferredV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -varying vec2 vary_fragcoord; -uniform vec2 screen_res; - -void main() -{ - //transform vertex - gl_Position = ftransform(); - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl deleted file mode 100644 index 12a5f39..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file postgiF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform sampler2DRect giLightMap; -uniform sampler2D noiseMap; - -uniform vec2 kern[32]; -uniform float dist_factor; -uniform float blur_size; -uniform vec2 delta; -uniform int kern_length; -uniform float kern_scale; -uniform vec3 blur_quad; - -varying vec2 vary_fragcoord; - -uniform mat4 inv_proj; -uniform vec2 screen_res; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -float getDepth(vec2 pos_screen) -{ - float z = texture2DRect(depthMap, pos_screen.xy).a; - z = z*2.0-1.0; - vec4 ndc = vec4(0.0, 0.0, z, 1.0); - vec4 p = inv_proj*ndc; - return p.z/p.w; -} - -void main() -{ - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; - float depth = getDepth(vary_fragcoord.xy); - - vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; - vec2 dlt = kern_scale * delta/(vec2(1.0,1.0)+norm.xy*norm.xy); - dlt /= clamp(-depth*blur_quad.x, 1.0, 3.0); - float defined_weight = kern[0].x; - vec3 col = ccol*kern[0].x; - - for (int i = 0; i < kern_length; i++) - { - vec2 tc = vary_fragcoord.xy + kern[i].y*dlt; - vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0; - - float d = dot(norm.xyz, sampNorm); - - if (d > 0.5) - { - float sampdepth = getDepth(tc.xy); - sampdepth -= depth; - if (sampdepth*sampdepth < blur_quad.z) - { - col += texture2DRect(giLightMap, tc).rgb*kern[i].x; - defined_weight += kern[i].x; - } - } - } - - col /= defined_weight; - - //col = ccol; - - col = col*blur_quad.y; - - gl_FragData[0].xyz = col; - - //gl_FragColor = ccol; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl deleted file mode 100644 index 6adcda8..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @file postgiV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -varying vec2 vary_fragcoord; -uniform vec2 screen_res; - -void main() -{ - //transform vertex - gl_Position = ftransform(); - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl deleted file mode 100644 index 654b182..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ /dev/null @@ -1,312 +0,0 @@ -/** - * @file softenLightF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect diffuseRect; -uniform sampler2DRect specularRect; -uniform sampler2DRect normalMap; -uniform sampler2DRect lightMap; -uniform sampler2DRect giLightMap; -uniform sampler2D noiseMap; -uniform samplerCube environmentMap; -uniform sampler2D lightFunc; -uniform sampler2D luminanceMap; - -uniform vec3 gi_quad; -uniform vec3 lum_quad; -uniform float lum_lod; - -uniform float blur_size; -uniform float blur_fidelity; - -// Inputs -uniform vec4 morphFactor; -uniform vec3 camPosLocal; -//uniform vec4 camPosWorld; -uniform vec4 gamma; -uniform vec4 lightnorm; -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 vec4 glow; -uniform float scene_light_strength; -uniform vec3 env_mat[3]; -uniform vec4 shadow_clip; -uniform mat3 ssao_effect_mat; - -uniform sampler2DRect depthMap; -uniform mat4 inv_proj; -uniform vec2 screen_res; - -varying vec4 vary_light; -varying vec2 vary_fragcoord; - -vec3 vary_PositionEye; - -vec3 vary_SunlitColor; -vec3 vary_AmblitColor; -vec3 vary_AdditiveColor; -vec3 vary_AtmosAttenuation; - -vec4 getPosition(vec2 pos_screen) -{ //get position in screen space (world units) given window coordinate and depth map - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -vec3 getPositionEye() -{ - return vary_PositionEye; -} -vec3 getSunlitColor() -{ - return vary_SunlitColor; -} -vec3 getAmblitColor() -{ - return vary_AmblitColor; -} -vec3 getAdditiveColor() -{ - return vary_AdditiveColor; -} -vec3 getAtmosAttenuation() -{ - return vary_AtmosAttenuation; -} - - -void setPositionEye(vec3 v) -{ - vary_PositionEye = v; -} - -void setSunlitColor(vec3 v) -{ - vary_SunlitColor = v; -} - -void setAmblitColor(vec3 v) -{ - vary_AmblitColor = v; -} - -void setAdditiveColor(vec3 v) -{ - vary_AdditiveColor = v; -} - -void setAtmosAttenuation(vec3 v) -{ - vary_AtmosAttenuation = v; -} - -void calcAtmospherics(vec3 inPositionEye, float ambFactor) { - - vec3 P = 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); - - vec3 tmpLightnorm = lightnorm.xyz; - - vec3 Pn = normalize(P); - float Plen = length(P); - - vec4 temp1 = vec4(0); - vec3 temp2 = vec3(0); - vec4 blue_weight; - vec4 haze_weight; - 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 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); - //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); - blue_weight = blue_density / temp1; - haze_weight = vec4(haze_density.r) / temp1; - - //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain) - temp2.y = max(0.0, tmpLightnorm.y); - temp2.y = 1. / temp2.y; - sunlight *= exp( - light_atten * temp2.y); - - // main atmospheric scattering line integral - temp2.z = Plen * density_multiplier.x; - - // Transparency (-> temp1) - // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati - // compiler gets confused. - temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); - - //final atmosphere attenuation factor - setAtmosAttenuation(temp1.rgb); - - //compute haze glow - //(can use temp2.x as temp because we haven't used it yet) - temp2.x = dot(Pn, tmpLightnorm.xyz); - temp2.x = 1. - temp2.x; - //temp2.x is 0 at the sun and increases away from sun - temp2.x = max(temp2.x, .03); //was glow.y - //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) - temp2.x *= glow.x; - //higher glow.x gives dimmer glow (because next step is 1 / "angle") - temp2.x = pow(temp2.x, glow.z); - //glow.z should be negative, so we're doing a sort of (1 / "angle") function - - //add "minimum anti-solar illumination" - temp2.x += .25; - - //increase ambient when there are more clouds - vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 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 - * // The following line of code performs the equivalent of: - * float ambAlpha = tmpAmbient.a; - * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis - * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); - * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); - */ - tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); - - //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 - + tmpAmbient))); - - //brightness of surface both sunlight and ambient - setSunlitColor(vec3(sunlight * .5)); - setAmblitColor(vec3(tmpAmbient * .25)); - setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1)); -} - -vec3 atmosLighting(vec3 light) -{ - light *= getAtmosAttenuation().r; - light += getAdditiveColor(); - return (2.0 * light); -} - -vec3 atmosTransport(vec3 light) { - light *= getAtmosAttenuation().r; - light += getAdditiveColor() * 2.0; - return light; -} -vec3 atmosGetDiffuseSunlightColor() -{ - return getSunlitColor(); -} - -vec3 scaleDownLight(vec3 light) -{ - return (light / scene_light_strength ); -} - -vec3 scaleUpLight(vec3 light) -{ - return (light * scene_light_strength); -} - -vec3 atmosAmbient(vec3 light) -{ - return getAmblitColor() + light / 2.0; -} - -vec3 atmosAffectDirectionalLight(float lightIntensity) -{ - return getSunlitColor() * lightIntensity; -} - -vec3 scaleSoftClip(vec3 light) -{ - //soft clip effect: - light = 1. - clamp(light, vec3(0.), vec3(1.)); - light = 1. - pow(light, gamma.xxx); - - return light; -} - -void main() -{ - vec2 tc = vary_fragcoord.xy; - vec3 pos = getPosition(tc).xyz; - vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0; - vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; - - vec3 at = normalize(pos); - - vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); - - vec3 lum = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb; - - vec3 ha = normalize(vary_light.xyz-at); - - float da = dot(ha, norm.xyz); - da = texture2D(lightFunc, vec2(da, spec.a)).a; - - vec4 diffuse = texture2DRect(diffuseRect, tc); - - vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; - float scol = max(scol_ambocc.r, diffuse.a); - float ambocc = scol_ambocc.g; - - calcAtmospherics(pos.xyz, ambocc); - - vec3 col = vec3(0,0,0); - - col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a)*(1.0+spec.a)); - - col *= diffuse.rgb; - - col += da*spec.rgb*spec.a*vary_SunlitColor*scol_ambocc.r; - - /*if (spec.a > 0.0) - { - vec3 ref = normalize(reflect(pos.xyz, norm.xyz)); - float sa = dot(ref, vary_light.xyz); - col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; - }*/ - - col = atmosLighting(col); - col = scaleSoftClip(col); - - col = col*vec3(1.0+1.0/2.2); - - gl_FragColor.rgb = col; - //gl_FragColor.rgb = lum; - - gl_FragColor.a = 0.0; - - //gl_FragColor.rg = scol_ambocc.rg; - //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb; - //gl_FragColor.rgb = norm.rgb*0.5+0.5; - //gl_FragColor.rgb = vec3(ambocc); - //gl_FragColor.rgb = vec3(scol); -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl deleted file mode 100644 index ad8af47..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @file softenLightF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform vec2 screen_res; - -varying vec4 vary_light; -varying vec2 vary_fragcoord; -void main() -{ - //transform vertex - gl_Position = ftransform(); - - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; - - vec4 tex = gl_MultiTexCoord0; - tex.w = 1.0; - - vary_light = gl_MultiTexCoord0; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl deleted file mode 100644 index 258acee..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file treeF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2D diffuseMap; - -varying vec3 vary_normal; - -void main() -{ - vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); - gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005); - gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); -} diff --git a/linden/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl b/linden/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl deleted file mode 100644 index bea1515..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @file waterF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -vec3 scaleSoftClip(vec3 inColor); -vec3 atmosTransport(vec3 inColor); - -uniform sampler2D bumpMap; -uniform sampler2D screenTex; -uniform sampler2D refTex; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; -uniform sampler2D noiseMap; - -uniform mat4 shadow_matrix[6]; -uniform vec4 shadow_clip; - -uniform float sunAngle; -uniform float sunAngle2; -uniform vec3 lightDir; -uniform vec3 specular; -uniform float lightExp; -uniform float refScale; -uniform float kd; -uniform vec2 screenRes; -uniform vec3 normScale; -uniform float fresnelScale; -uniform float fresnelOffset; -uniform float blurMultiplier; -uniform vec2 screen_res; -uniform mat4 norm_mat; //region space to screen space - -//bigWave is (refCoord.w, view.w); -varying vec4 refCoord; -varying vec4 littleWave; -varying vec4 view; -varying vec4 vary_position; - -void main() -{ - vec4 color; - float dist = length(view.xy); - - //normalize view vector - vec3 viewVec = normalize(view.xyz); - - //get wave normals - vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0; - vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0; - vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0; - //get base fresnel components - - vec3 df = vec3( - dot(viewVec, wave1), - dot(viewVec, (wave2 + wave3) * 0.5), - dot(viewVec, wave3) - ) * fresnelScale + fresnelOffset; - df *= df; - - vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; - - float dist2 = dist; - dist = max(dist, 5.0); - - float dmod = sqrt(dist); - - vec2 dmod_scale = vec2(dmod*dmod, dmod); - - //get reflected color - vec2 refdistort1 = wave1.xy*normScale.x; - vec2 refvec1 = distort+refdistort1/dmod_scale; - vec4 refcol1 = texture2D(refTex, refvec1); - - vec2 refdistort2 = wave2.xy*normScale.y; - vec2 refvec2 = distort+refdistort2/dmod_scale; - vec4 refcol2 = texture2D(refTex, refvec2); - - vec2 refdistort3 = wave3.xy*normScale.z; - vec2 refvec3 = distort+refdistort3/dmod_scale; - vec4 refcol3 = texture2D(refTex, refvec3); - - vec4 refcol = refcol1 + refcol2 + refcol3; - float df1 = df.x + df.y + df.z; - refcol *= df1 * 0.333; - - vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5; - //wavef.z *= max(-viewVec.z, 0.1); - wavef = normalize(wavef); - - float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset; - - vec2 refdistort4 = wavef.xy*0.125; - refdistort4.y -= abs(refdistort4.y); - vec2 refvec4 = distort+refdistort4/dmod; - float dweight = min(dist2*blurMultiplier, 1.0); - vec4 baseCol = texture2D(refTex, refvec4); - refcol = mix(baseCol*df2, refcol, dweight); - - //get specular component - //float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0); - - //harden specular - //spec = pow(spec, 128.0); - - //figure out distortion vector (ripply) - vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0); - - vec4 fb = texture2D(screenTex, distort2); - - //mix with reflection - // Note we actually want to use just df1, but multiplying by 0.999999 gets around and nvidia compiler bug - color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999); - - float shadow = 1.0; - vec4 pos = vary_position; - - vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; - vec4 spos = pos; - - //spec *= shadow; - //color.rgb += spec * specular; - - //color.rgb = atmosTransport(color.rgb); - //color.rgb = scaleSoftClip(color.rgb); - //color.a = spec * sunAngle2; - - //wavef.z *= 0.1f; - wavef = normalize(wavef); - wavef = (norm_mat*vec4(wavef, 1.0)).xyz; - - gl_FragData[0] = vec4(color.rgb, 0.5); - gl_FragData[1] = vec4(0.5,0.5,0.5, 0.95); - gl_FragData[2] = vec4(wavef*0.5+0.5, 0.f); -} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/blurF.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/blurF.glsl deleted file mode 100644 index 9443320..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/effects/blurF.glsl +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @file blurf.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2DRect RenderTexture; -uniform float bloomStrength; - -varying vec4 gl_TexCoord[gl_MaxTextureCoords]; -void main(void) -{ - float blurWeights[7]; - blurWeights[0] = 0.05; - blurWeights[1] = 0.1; - blurWeights[2] = 0.2; - blurWeights[3] = 0.3; - blurWeights[4] = 0.2; - blurWeights[5] = 0.1; - blurWeights[6] = 0.05; - - vec3 color = vec3(0,0,0); - for (int i = 0; i < 7; i++){ - color += vec3(texture2DRect(RenderTexture, gl_TexCoord[i].st)) * blurWeights[i]; - } - - color *= bloomStrength; - - gl_FragColor = vec4(color, 1.0); -} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/blurV.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/blurV.glsl deleted file mode 100644 index ba65b16..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/effects/blurV.glsl +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @file blurV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform vec2 texelSize; -uniform vec2 blurDirection; -uniform float blurWidth; - -void main(void) -{ - // Transform vertex - gl_Position = ftransform(); - - vec2 blurDelta = texelSize * blurDirection * vec2(blurWidth, blurWidth); - vec2 s = gl_MultiTexCoord0.st - (blurDelta * 3.0); - - // for (int i = 0; i < 7; i++) { - // gl_TexCoord[i].st = s + (i * blurDelta); - // } - - // MANUALLY UNROLL - gl_TexCoord[0].st = s; - gl_TexCoord[1].st = s + blurDelta; - gl_TexCoord[2].st = s + (2. * blurDelta); - gl_TexCoord[3].st = s + (3. * blurDelta); - gl_TexCoord[4].st = s + (4. * blurDelta); - gl_TexCoord[5].st = s + (5. * blurDelta); - gl_TexCoord[6].st = s + (6. * blurDelta); - - // gl_TexCoord[0].st = s; - // gl_TexCoord[1].st = blurDelta; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/colorFilterF.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/colorFilterF.glsl deleted file mode 100644 index 623ef7a..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/effects/colorFilterF.glsl +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @file colorFilterF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2DRect RenderTexture; -uniform float brightness; -uniform float contrast; -uniform vec3 contrastBase; -uniform float saturation; -uniform vec3 lumWeights; - -const float gamma = 2.0; - -void main(void) -{ - vec3 color = vec3(texture2DRect(RenderTexture, gl_TexCoord[0].st)); - - /// Modulate brightness - color *= brightness; - - /// Modulate contrast - color = mix(contrastBase, color, contrast); - - /// Modulate saturation - color = mix(vec3(dot(color, lumWeights)), color, saturation); - - gl_FragColor = vec4(color, 1.0); -} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/drawQuadV.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/drawQuadV.glsl deleted file mode 100644 index 29c2a09..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/effects/drawQuadV.glsl +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @file drawQuadV.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -void main(void) -{ - //transform vertex - gl_Position = ftransform(); - gl_TexCoord[0] = gl_MultiTexCoord0; - gl_TexCoord[1] = gl_MultiTexCoord1; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/extractF.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/extractF.glsl deleted file mode 100644 index a1583b1..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/effects/extractF.glsl +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @file extractF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2DRect RenderTexture; -uniform float extractLow; -uniform float extractHigh; -uniform vec3 lumWeights; - -void main(void) -{ - /// Get scene color - vec3 color = vec3(texture2DRect(RenderTexture, gl_TexCoord[0].st)); - - /// Extract luminance and scale up by night vision brightness - float lum = smoothstep(extractLow, extractHigh, dot(color, lumWeights)); - - gl_FragColor = vec4(vec3(lum), 1.0); -} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/nightVisionF.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/nightVisionF.glsl deleted file mode 100644 index 271d5cf..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/effects/nightVisionF.glsl +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file nightVisionF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2DRect RenderTexture; -uniform sampler2D NoiseTexture; -uniform float brightMult; -uniform float noiseStrength; - -float luminance(vec3 color) -{ - /// CALCULATING LUMINANCE (Using NTSC lum weights) - /// http://en.wikipedia.org/wiki/Luma_%28video%29 - return dot(color, vec3(0.299, 0.587, 0.114)); -} - -void main(void) -{ - /// Get scene color - vec3 color = vec3(texture2DRect(RenderTexture, gl_TexCoord[0].st)); - - /// Extract luminance and scale up by night vision brightness - float lum = luminance(color) * brightMult; - - /// Convert into night vision color space - /// Newer NVG colors (crisper and more saturated) - vec3 outColor = (lum * vec3(0.91, 1.21, 0.9)) + vec3(-0.07, 0.1, -0.12); - - /// Add noise - float noiseValue = texture2D(NoiseTexture, gl_TexCoord[1].st).r; - noiseValue = (noiseValue - 0.5) * noiseStrength; - - /// Older NVG colors (more muted) - // vec3 outColor = (lum * vec3(0.82, 0.75, 0.83)) + vec3(0.05, 0.32, -0.11); - - outColor += noiseValue; - - gl_FragColor = vec4(outColor, 1.0); -} diff --git a/linden/indra/newview/app_settings/shaders/class3/effects/simpleF.glsl b/linden/indra/newview/app_settings/shaders/class3/effects/simpleF.glsl deleted file mode 100644 index e55d278..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/effects/simpleF.glsl +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @file simpleF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2DRect RenderTexture; - -void main(void) -{ - vec3 color = vec3(texture2DRect(RenderTexture, gl_TexCoord[0].st)); - gl_FragColor = vec4(1.0 - color, 1.0); -} diff --git a/linden/indra/newview/llagent.cpp b/linden/indra/newview/llagent.cpp index bfaa4ad..1b2c8e1 100644 --- a/linden/indra/newview/llagent.cpp +++ b/linden/indra/newview/llagent.cpp @@ -223,7 +223,6 @@ LLAgent gAgent; // Statics // BOOL LLAgent::sPhantom = FALSE; -BOOL LLAgent::sDebugDisplayTarget = FALSE; const F32 LLAgent::TYPING_TIMEOUT_SECS = 5.f; @@ -6624,7 +6623,7 @@ void LLAgent::saveWearable( EWearableType type, BOOL send_update ) return; } - // getAvatarObject()->wearableUpdated( type ); + getAvatarObject()->wearableUpdated( type ); if( send_update ) { diff --git a/linden/indra/newview/llagent.h b/linden/indra/newview/llagent.h index 22851c1..f1cad9c 100644 --- a/linden/indra/newview/llagent.h +++ b/linden/indra/newview/llagent.h @@ -771,7 +771,6 @@ public: BOOL mInitialized; - static BOOL sDebugDisplayTarget; S32 mNumPendingQueries; S32* mActiveCacheQueries; diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp index 3a3f51b..9fad9f1 100644 --- a/linden/indra/newview/llappviewer.cpp +++ b/linden/indra/newview/llappviewer.cpp @@ -448,7 +448,7 @@ static void settings_modify() LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4] gDebugGL = gSavedSettings.getBOOL("RenderDebugGL"); gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline"); -// gAuditTexture = gSavedSettings.getBOOL("AuditTexture"); + gAuditTexture = gSavedSettings.getBOOL("AuditTexture"); #if LL_VECTORIZE if (gSysCPU.hasAltivec()) { diff --git a/linden/indra/newview/llcolorswatch.cpp b/linden/indra/newview/llcolorswatch.cpp index 3222c0d..5905bb0 100644 --- a/linden/indra/newview/llcolorswatch.cpp +++ b/linden/indra/newview/llcolorswatch.cpp @@ -219,12 +219,11 @@ void LLColorSwatchCtrl::draw() gl_rect_2d(interior, mColor, TRUE); LLColor4 opaque_color = mColor; opaque_color.mV[VALPHA] = 1.f; - gGL.color4fv(opaque_color.mV); if (mAlphaGradientImage.notNull()) { gGL.pushMatrix(); { - mAlphaGradientImage->draw(interior, mColor); + mAlphaGradientImage->draw(interior, opaque_color); } gGL.popMatrix(); } diff --git a/linden/indra/newview/llcompilequeue.cpp b/linden/indra/newview/llcompilequeue.cpp index a81972d..ed18a10 100644 --- a/linden/indra/newview/llcompilequeue.cpp +++ b/linden/indra/newview/llcompilequeue.cpp @@ -58,6 +58,7 @@ #include "llfloaterchat.h" #include "llviewerstats.h" #include "lluictrlfactory.h" +#include "llselectmgr.h" ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs diff --git a/linden/indra/newview/llconsole.cpp b/linden/indra/newview/llconsole.cpp index a8554a0..2379da3 100644 --- a/linden/indra/newview/llconsole.cpp +++ b/linden/indra/newview/llconsole.cpp @@ -63,25 +63,17 @@ const S32 CONSOLE_GUTTER_LEFT = 14; const S32 CONSOLE_GUTTER_RIGHT = 15; -LLConsole::LLConsole(const std::string& name, const LLRect &rect, +LLConsole::LLConsole(const std::string& name, const U32 max_lines, const LLRect &rect, S32 font_size_index, F32 persist_time ) - : LLFixedBuffer(), - LLView(name, rect, FALSE), - mLinePersistTime(persist_time), - mFadeTime(persist_time - FADE_DURATION), - mFont(LLFontGL::getFontSansSerif()), - mConsoleWidth(0), - mConsoleHeight(0), - mQueueMutex(NULL) + : + LLFixedBuffer(max_lines), + LLView(name, rect, FALSE) { - mTimer.reset(); + mLinePersistTime = persist_time; // seconds + mFadeTime = persist_time - FADE_DURATION; - setFontSize( font_size_index ); -} - -LLConsole::~LLConsole() -{ - clear(); + setFontSize( font_size_index ); + setMaxLines(gSavedSettings.getS32("ConsoleMaxLines")); } void LLConsole::setLinePersistTime(F32 seconds) @@ -106,10 +98,10 @@ void LLConsole::reshape(S32 width, S32 height, BOOL called_from_parent) mConsoleHeight= new_height; LLView::reshape(new_width, new_height, called_from_parent); - + for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++) { - (*paragraph_it)->updateLines((F32)getRect().getWidth(), mFont, true); + (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true); } } @@ -134,7 +126,7 @@ void LLConsole::setFontSize(S32 size_index) for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++) { - (*paragraph_it)->updateLines((F32)getRect().getWidth(), mFont, true); + (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true); } } @@ -142,49 +134,35 @@ void LLConsole::draw() { LLGLSUIDefault gls_ui; - { - LLMutexLock lock(&mQueueMutex); - for(paragraph_t::iterator paragraph_it = mNewParagraphs.begin(); paragraph_it != mNewParagraphs.end(); paragraph_it++) - { - Paragraph* paragraph = *paragraph_it; - mParagraphs.push_back(paragraph); - paragraph->updateLines((F32)getRect().getWidth(), mFont); - } - mNewParagraphs.clear(); - } - - if (mParagraphs.empty()) //No text to draw. - { - return; - } - // skip lines added more than mLinePersistTime ago F32 cur_time = mTimer.getElapsedTimeF32(); F32 skip_time = cur_time - mLinePersistTime; F32 fade_time = cur_time - mFadeTime; - U32 max_lines = gSavedSettings.getS32("ConsoleMaxLines"); + updateBuffer() ; + + if (mParagraphs.empty()) //No text to draw. + { + return; + } + U32 num_lines=0; paragraph_t::reverse_iterator paragraph_it; paragraph_it = mParagraphs.rbegin(); U32 paragraph_num=mParagraphs.size(); - + while (!mParagraphs.empty() && paragraph_it != mParagraphs.rend()) { - num_lines += (*paragraph_it)->mLines.size(); - if(num_lines > max_lines - || ( (mLinePersistTime > (F32)0.f) && ((*paragraph_it)->mAddTime - skip_time)/(mLinePersistTime - mFadeTime) <= (F32)0.f)) + num_lines += (*paragraph_it).mLines.size(); + if(num_lines > mMaxLines + || ( (mLinePersistTime > (F32)0.f) && ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime) <= (F32)0.f)) { //All lines above here are done. Lose them. for (U32 i=0;i<paragraph_num;i++) { if (!mParagraphs.empty()) - { - Paragraph* paragraph = mParagraphs.front(); mParagraphs.pop_front(); - delete paragraph; - } } break; } @@ -215,8 +193,8 @@ void LLConsole::draw() S32 bkg_width=0; for(paragraph_it = mParagraphs.rbegin(); paragraph_it != mParagraphs.rend(); paragraph_it++) { - S32 target_height = llfloor( (*paragraph_it)->mLines.size() * line_height + message_spacing); - S32 target_width = llfloor( (*paragraph_it)->mMaxWidth + CONSOLE_GUTTER_RIGHT); + S32 target_height = llfloor( (*paragraph_it).mLines.size() * line_height + message_spacing); + S32 target_width = llfloor( (*paragraph_it).mMaxWidth + CONSOLE_GUTTER_RIGHT); bkg_height+= target_height; if (target_width > bkg_width) @@ -225,7 +203,7 @@ void LLConsole::draw() } // Why is this not using llfloor as above? - y_pos += ((*paragraph_it)->mLines.size()) * line_height; + y_pos += ((*paragraph_it).mLines.size()) * line_height; y_pos += message_spacing; //Extra spacing between messages. } imagep->drawSolid(-CONSOLE_GUTTER_LEFT, (S32)(y_pos + line_height - bkg_height - message_spacing), bkg_width, bkg_height, color); @@ -235,10 +213,10 @@ void LLConsole::draw() for(paragraph_it = mParagraphs.rbegin(); paragraph_it != mParagraphs.rend(); paragraph_it++) { //080813 Spatters: Dainty per-message block boxes -// S32 target_height = llfloor( (*paragraph_it)->mLines.size() * line_height + 8); - S32 target_width = llfloor( (*paragraph_it)->mMaxWidth + CONSOLE_GUTTER_RIGHT); +// S32 target_height = llfloor( (*paragraph_it).mLines.size() * line_height + 8); + S32 target_width = llfloor( (*paragraph_it).mMaxWidth + CONSOLE_GUTTER_RIGHT); - y_pos += ((*paragraph_it)->mLines.size()) * line_height; + y_pos += ((*paragraph_it).mLines.size()) * line_height; //080813 Spatters: Dainty per-message block boxes // imagep->drawSolid(-14, (S32)(y_pos + line_height - target_height), target_width, target_height, color); @@ -246,9 +224,9 @@ void LLConsole::draw() F32 alpha; - if ((mLinePersistTime > 0.f) && ((*paragraph_it)->mAddTime < fade_time)) + if ((mLinePersistTime > 0.f) && ((*paragraph_it).mAddTime < fade_time)) { - alpha = ((*paragraph_it)->mAddTime - skip_time)/(mLinePersistTime - mFadeTime); + alpha = ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime); } else { @@ -257,12 +235,12 @@ void LLConsole::draw() if( alpha > 0.f ) { - for (lines_t::iterator line_it=(*paragraph_it)->mLines.begin(); - line_it != (*paragraph_it)->mLines.end(); + for (lines_t::iterator line_it=(*paragraph_it).mLines.begin(); + line_it != (*paragraph_it).mLines.end(); line_it ++) { - for (line_color_segments_t::iterator seg_it = (*line_it).begin(); - seg_it != (*line_it).end(); + for (line_color_segments_t::iterator seg_it = (*line_it).mLineColorSegments.begin(); + seg_it != (*line_it).mLineColorSegments.end(); seg_it++) { mFont->render((*seg_it).mText, 0, (*seg_it).mXPosition - 8, y_pos - y_off, @@ -285,34 +263,21 @@ void LLConsole::draw() } } -//virtual -void LLConsole::clear() +void LLConsole::addLine(const std::string& utf8line) { - mTimer.reset(); - LLMutexLock lock(&mQueueMutex); - std::for_each(mParagraphs.begin(), mParagraphs.end(), DeletePointer()); - mParagraphs.clear(); - std::for_each(mNewParagraphs.begin(), mNewParagraphs.end(), DeletePointer()); - mNewParagraphs.clear(); + LLWString wline = utf8str_to_wstring(utf8line); + addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f)); } -//virtual -void LLConsole::addLine(const std::string& utf8line) +void LLConsole::addLine(const LLWString& wline) { - addConsoleLine(utf8line, LLColor4(1.f, 1.f, 1.f, 1.f)); + addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f)); } -void LLConsole::addConsoleLine(const std::string& utf8line, const LLColor4 &color) +void LLConsole::addLine(const std::string& utf8line, F32 size, const LLColor4 &color) { LLWString wline = utf8str_to_wstring(utf8line); - addConsoleLine(wline, color); -} - -void LLConsole::addConsoleLine(const LLWString& wline, const LLColor4 &color) -{ - Paragraph* paragraph = new Paragraph(wline, color, mTimer.getElapsedTimeF32()); - LLMutexLock lock(&mQueueMutex); - mNewParagraphs.push_back ( paragraph ); + addLine(wline, size, color); } //Generate highlight color segments for this paragraph. Pass in default color of paragraph. @@ -394,7 +359,7 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, LLFontGL* font, bool fo F32 x_position = 0; //Screen X position of text. mMaxWidth = llmax( mMaxWidth, (F32)font->getWidth( mParagraphText.substr( paragraph_offset, drawable ).c_str() ) ); - line_color_segments_t line; + Line line; U32 left_to_draw = drawable; U32 drawn = 0; @@ -403,7 +368,7 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, LLFontGL* font, bool fo && current_color != mParagraphColorSegments.end() ) { LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, current_color_length ); - line.push_back( LineColorSegment( color_text, //Append segment to line. + line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line. (*current_color).mColor, x_position ) ); @@ -424,7 +389,7 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, LLFontGL* font, bool fo { LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, left_to_draw ); - line.push_back( LineColorSegment( color_text, //Append segment to line. + line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line. (*current_color).mColor, x_position ) ); @@ -442,9 +407,50 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, LLFontGL* font, bool fo } //Pass in the string and the default color for this block of text. -LLConsole::Paragraph::Paragraph (LLWString str, const LLColor4 &color, F32 add_time) +LLConsole::Paragraph::Paragraph (LLWString str, const LLColor4 &color, F32 add_time, LLFontGL* font, F32 screen_width) : mParagraphText(str), mAddTime(add_time), mMaxWidth(-1) { makeParagraphColorSegments(color); + updateLines( screen_width, font ); } +void LLConsole::addLine(const LLWString& wline, F32 size, const LLColor4 &color) +{ + Paragraph paragraph(wline, color, mTimer.getElapsedTimeF32(), mFont, (F32)getRect().getWidth() ); + + mParagraphs.push_back ( paragraph ); + +#if LL_WINDOWS && LL_LCD_COMPILE + // add to LCD screen + AddNewDebugConsoleToLCD(wline); +#endif +} + +// +//check if there are some messages stored in the buffer +//if yes, output them. +// +void LLConsole::updateBuffer() +{ + BOOL need_clear = FALSE ; + + mMutex.lock() ; + if(!mLines.empty()) + { + S32 end = mLines.size() ; + LLColor4 color(1.f, 1.f, 1.f, 1.f) ; + for(S32 i = 0 ; i < end ; i++) + { + Paragraph paragraph(mLines[i], color, mAddTimes[i], mFont, (F32)getRect().getWidth() ); + mParagraphs.push_back ( paragraph ); + } + + need_clear = TRUE ; + } + mMutex.unlock() ; + + if(need_clear) + { + clear() ; + } +} diff --git a/linden/indra/newview/llconsole.h b/linden/indra/newview/llconsole.h index 578670e..2915c48 100644 --- a/linden/indra/newview/llconsole.h +++ b/linden/indra/newview/llconsole.h @@ -33,8 +33,7 @@ #ifndef LL_LLCONSOLE_H #define LL_LLCONSOLE_H -#include "llerrorcontrol.h" // For LLLineBuffer -#include "llthread.h" +#include "llfixedbuffer.h" #include "llview.h" #include "v4color.h" #include <deque> @@ -48,10 +47,10 @@ private: F32 mLinePersistTime; // Age at which to stop drawing. F32 mFadeTime; // Age at which to start fading LLFontGL* mFont; + S32 mLastBoxHeight; + S32 mLastBoxWidth; S32 mConsoleWidth; S32 mConsoleHeight; - LLMutex mQueueMutex; - LLTimer mTimer; public: //A paragraph color segment defines the color of text in a line @@ -81,7 +80,14 @@ public: typedef std::list<LineColorSegment> line_color_segments_t; - typedef std::list<line_color_segments_t> lines_t; + //A line is composed of one or more color segments. + class Line + { + public: + line_color_segments_t mLineColorSegments; + }; + + typedef std::list<Line> lines_t; typedef std::list<ParagraphColorSegment> paragraph_color_segments_t; //A paragraph is a processed element containing the entire text of the @@ -92,7 +98,7 @@ public: class Paragraph { public: - Paragraph (LLWString str, const LLColor4 &color, F32 add_time); + Paragraph (LLWString str, const LLColor4 &color, F32 add_time, LLFontGL* font, F32 screen_width); void makeParagraphColorSegments ( const LLColor4 &color); void updateLines ( F32 screen_width, LLFontGL* font, bool force_resize=false ); public: @@ -105,32 +111,35 @@ public: }; //The console contains a deque of paragraphs which represent the individual messages. - typedef std::deque<Paragraph*> paragraph_t; + typedef std::deque<Paragraph> paragraph_t; paragraph_t mParagraphs; - paragraph_t mNewParagraphs; // Font size: // -1 = monospace, 0 means small, font size = 1 means big - LLConsole(const std::string& name, const LLRect &rect, - S32 font_size_index, F32 persist_time ); - ~LLConsole(); + LLConsole(const std::string& name, const U32 max_lines, const LLRect &rect, + S32 font_size_index, F32 persist_time ); + ~LLConsole(){}; // each line lasts this long after being added - void setLinePersistTime(F32 seconds); + void setLinePersistTime(F32 seconds); - void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); // -1 = monospace, 0 means small, font size = 1 means big - void setFontSize(S32 size_index); + void setFontSize(S32 size_index); - // From LLLineBuffer - /*virtual*/ void clear(); - /*virtual*/ void addLine(const std::string& utf8line); - void addConsoleLine(const std::string& utf8line, const LLColor4 &color); - void addConsoleLine(const LLWString& wline, const LLColor4 &color); + void addLine(const std::string& utf8line, F32 size, const LLColor4 &color); + void addLine(const LLWString& wline, F32 size, const LLColor4 &color); // Overrides /*virtual*/ void draw(); + + //do not make these two "virtual" + void addLine(const std::string& utf8line); + void addLine(const LLWString& line); + +private: + void updateBuffer() ; }; extern LLConsole* gConsole; diff --git a/linden/indra/newview/lldebugview.cpp b/linden/indra/newview/lldebugview.cpp index a6d6f2d..40f5202 100644 --- a/linden/indra/newview/lldebugview.cpp +++ b/linden/indra/newview/lldebugview.cpp @@ -62,7 +62,7 @@ LLDebugView::LLDebugView(const std::string& name, const LLRect &rect) LLRect r; r.set(10, rect.getHeight() - 100, rect.getWidth()/2, 100); - mDebugConsolep = new LLConsole("debug console", r, -1, 0.f ); + mDebugConsolep = new LLConsole("debug console", 20, r, -1, 0.f ); mDebugConsolep->setFollowsBottom(); mDebugConsolep->setFollowsLeft(); mDebugConsolep->setVisible( FALSE ); @@ -98,27 +98,6 @@ LLDebugView::LLDebugView(const std::string& name, const LLRect &rect) addChild(gTextureView); //gTextureView->reshape(r.getWidth(), r.getHeight(), TRUE); -/* -//there seems to be some debug code, we don't have -#if !LL_RELEASE_FOR_DOWNLOAD - r.set(150, rect.getHeight() - 50, 900 + LLImageGL::sTextureLoadedCounter.size() * 30, 100); - gTextureSizeView = new LLTextureSizeView("gTextureSizeView"); - gTextureSizeView->setRect(r); - gTextureSizeView->setFollowsBottom(); - gTextureSizeView->setFollowsLeft(); - addChild(gTextureSizeView); - - - r.set(150, rect.getHeight() - 50, 900 + LLImageGL::sTextureMemByCategory.size() * 30, 100); - gTextureCategoryView = new LLTextureSizeView("gTextureCategoryView"); - gTextureCategoryView->setRect(r); - gTextureCategoryView->setFollowsBottom(); - gTextureCategoryView->setFollowsLeft(); - gTextureCategoryView->setType(LLTextureSizeView::TEXTURE_MEM_OVER_CATEGORY); - addChild(gTextureCategoryView); -#endif -*/ - const S32 VELOCITY_LEFT = 10; // 370; const S32 VELOCITY_WIDTH = 500; const S32 VELOCITY_TOP = 140; @@ -136,6 +115,5 @@ LLDebugView::~LLDebugView() // These have already been deleted. Fix the globals appropriately. gDebugView = NULL; gTextureView = NULL; - gTextureSizeView = NULL; } diff --git a/linden/indra/newview/lldrawable.cpp b/linden/indra/newview/lldrawable.cpp index 2b43374..5a383bc 100644 --- a/linden/indra/newview/lldrawable.cpp +++ b/linden/indra/newview/lldrawable.cpp @@ -102,7 +102,7 @@ void LLDrawable::init() mVObjp = NULL; // mFaces mSpatialGroupp = NULL; - mVisible = 0; + mVisible = sCurVisible - 2;//invisible for the current frame and the last frame. mRadius = 0.f; mGeneration = -1; @@ -125,7 +125,7 @@ void LLDrawable::destroy() if (LLSpatialGroup::sNoDelete) { - llwarns << "Illegal deletion of LLDrawable!" << llendl; + llerrs << "Illegal deletion of LLDrawable!" << llendl; } std::for_each(mFaces.begin(), mFaces.end(), DeletePointer()); @@ -234,7 +234,7 @@ LLFace* LLDrawable::addFace(LLFacePool *poolp, LLViewerImage *texturep) LLMemType mt(LLMemType::MTYPE_DRAWABLE); LLFace *face = new LLFace(this, mVObjp); - if (!face) llwarns << "Allocating new Face: " << mFaces.size() << llendl; + if (!face) llerrs << "Allocating new Face: " << mFaces.size() << llendl; if (face) { @@ -346,7 +346,7 @@ void LLDrawable::deleteFaces(S32 offset, S32 count) void LLDrawable::update() { - llwarns << "Shouldn't be called!" << llendl; + llerrs << "Shouldn't be called!" << llendl; } @@ -369,7 +369,7 @@ void LLDrawable::makeActive() pcode == LLViewerObject::LL_VO_GROUND || pcode == LLViewerObject::LL_VO_SKY) { - llwarns << "Static viewer object has active drawable!" << llendl; + llerrs << "Static viewer object has active drawable!" << llendl; } } #endif @@ -693,22 +693,19 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) pos += volume->getRegion()->getOriginAgent(); } - if (isState(LLDrawable::HAS_ALPHA)) + for (S32 i = 0; i < getNumFaces(); i++) { - for (S32 i = 0; i < getNumFaces(); i++) + LLFace* facep = getFace(i); + if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA) { - LLFace* facep = getFace(i); - if (facep->getPoolType() == LLDrawPool::POOL_ALPHA) + LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f; + LLVector3 v = (facep->mCenterLocal-camera.getOrigin()); + LLVector3 at = camera.getAtAxis(); + for (U32 j = 0; j < 3; j++) { - LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f; - LLVector3 v = (facep->mCenterLocal-camera.getOrigin()); - const LLVector3& at = camera.getAtAxis(); - for (U32 j = 0; j < 3; j++) - { - v.mV[j] -= box.mV[j] * at.mV[j]; - } - facep->mDistance = v * camera.getAtAxis(); + v.mV[j] -= box.mV[j] * at.mV[j]; } + facep->mDistance = v * camera.getAtAxis(); } } } @@ -740,11 +737,7 @@ void LLDrawable::updateTexture() if (getVOVolume()) { - if (!isActive()) - { - //gPipeline.markMoved(this); - } - else + if (isActive()) { if (isRoot()) { @@ -1011,8 +1004,8 @@ BOOL LLDrawable::isVisible() const // Spatial Partition Bridging Drawable //======================================= -LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask) // KL Sd version -: LLSpatialPartition(data_mask, render_by_group, FALSE) +LLSpatialBridge::LLSpatialBridge(LLDrawable* root, U32 data_mask) +: LLSpatialPartition(data_mask, FALSE) { mDrawable = root; root->setSpatialBridge(this); @@ -1142,26 +1135,26 @@ void LLDrawable::setVisible(LLCamera& camera, std::vector<LLDrawable*>* results, { if (isActive() && !mParent->isActive()) { - llwarns << "Active drawable has static parent!" << llendl; + llerrs << "Active drawable has static parent!" << llendl; } if (isStatic() && !mParent->isStatic()) { - llwarns << "Static drawable has active parent!" << llendl; + llerrs << "Static drawable has active parent!" << llendl; } if (mSpatialBridge) { - llwarns << "Child drawable has spatial bridge!" << llendl; + llerrs << "Child drawable has spatial bridge!" << llendl; } } else if (isActive() && !mSpatialBridge) { - llwarns << "Active root drawable has no spatial bridge!" << llendl; + llerrs << "Active root drawable has no spatial bridge!" << llendl; } else if (isStatic() && mSpatialBridge.notNull()) { - llwarns << "Static drawable has spatial bridge!" << llendl; + llerrs << "Static drawable has spatial bridge!" << llendl; } } #endif @@ -1285,25 +1278,12 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update) return; } - if (mDrawable->getVObj()) - { - if (mDrawable->getVObj()->isAttachment()) - { - LLDrawable* parent = mDrawable->getParent(); - if (parent && parent->getVObj()) - { - LLVOAvatar* av = parent->getVObj()->asAvatar(); - if (av && av->isImpostor()) - { - return; - } - } - } - - LLCamera camera = transformCamera(camera_in); + LLCamera camera = transformCamera(camera_in); mDrawable->updateDistance(camera, force_update); + if (mDrawable->getVObj()) + { LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); iter++) @@ -1325,7 +1305,7 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update) void LLSpatialBridge::makeActive() { //it is an error to make a spatial bridge active (it's already active) - llwarns << "makeActive called on spatial bridge" << llendl; + llerrs << "makeActive called on spatial bridge" << llendl; } void LLSpatialBridge::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate) @@ -1441,9 +1421,9 @@ void LLDrawable::updateFaceSize(S32 idx) } LLBridgePartition::LLBridgePartition() -: LLSpatialPartition(0, FALSE, 0) +: LLSpatialPartition(0, TRUE) { - //mRenderByGroup = FALSE; // KL + mRenderByGroup = FALSE; mDrawableType = LLPipeline::RENDER_TYPE_AVATAR; mPartitionType = LLViewerRegion::PARTITION_BRIDGE; mLODPeriod = 16; diff --git a/linden/indra/newview/lldrawable.h b/linden/indra/newview/lldrawable.h index e6753b5..71b75dc 100644 --- a/linden/indra/newview/lldrawable.h +++ b/linden/indra/newview/lldrawable.h @@ -267,8 +267,7 @@ public: BUILT = 0x08000000, FORCE_INVISIBLE = 0x10000000, // stay invis until CLEAR_INVISIBLE is set (set of orphaned) CLEAR_INVISIBLE = 0x20000000, // clear FORCE_INVISIBLE next draw frame - REBUILD_SHADOW = 0x40000000, - HAS_ALPHA = 0x80000000, + REBUILD_SHADOW = 0x40000000 } EDrawableFlags; LLXformMatrix mXform; diff --git a/linden/indra/newview/lldrawpool.h b/linden/indra/newview/lldrawpool.h index 6920a99..f8c2ead 100644 --- a/linden/indra/newview/lldrawpool.h +++ b/linden/indra/newview/lldrawpool.h @@ -68,11 +68,6 @@ public: POOL_GLOW, POOL_ALPHA, NUM_POOL_TYPES, - // * invisiprims work by rendering to the depth buffer but not the color buffer, occluding anything rendered after them - // - and the LLDrawPool types enum controls what order things are rendered in - // - so, it has absolute control over what invisprims block - // ...invisiprims being rendered in pool_invisible - // ...shiny/bump mapped objects in rendered in POOL_BUMP }; LLDrawPool(const U32 type); diff --git a/linden/indra/newview/lldrawpoolalpha.cpp b/linden/indra/newview/lldrawpoolalpha.cpp index c9c06f4..4b552ac 100644 --- a/linden/indra/newview/lldrawpoolalpha.cpp +++ b/linden/indra/newview/lldrawpoolalpha.cpp @@ -88,12 +88,7 @@ void LLDrawPoolAlpha::beginDeferredPass(S32 pass) void LLDrawPoolAlpha::endDeferredPass(S32 pass) { - -} - -void LLDrawPoolAlpha::renderDeferred(S32 pass) -{ - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.4f); { LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); gDeferredTreeProgram.bind(); @@ -104,6 +99,11 @@ void LLDrawPoolAlpha::renderDeferred(S32 pass) gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } +void LLDrawPoolAlpha::renderDeferred(S32 pass) +{ + +} + S32 LLDrawPoolAlpha::getNumPostDeferredPasses() { @@ -261,8 +261,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) { BOOL initialized_lighting = FALSE; BOOL light_enabled = TRUE; - S32 diffuse_channel = 0; - //BOOL is_particle = FALSE; BOOL use_shaders = (LLPipeline::sUnderWaterRender && gPipeline.canUseVertexShaders()) || gPipeline.canUseWindLightShadersOnObjects(); @@ -293,6 +291,19 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) LLRenderPass::applyModelMatrix(params); + if (params.mTexture.notNull()) + { + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->bind(params.mTexture.get()); + + if (params.mTextureMatrix) + { + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + } + } + if (params.mFullbright) { // Turn off lighting if it hasn't already been so. @@ -333,13 +344,11 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) if (deferred_render && current_shader != NULL) { gPipeline.unbindDeferredShader(*current_shader); - diffuse_channel = 0; } current_shader = target_shader; if (deferred_render) { gPipeline.bindDeferredShader(*current_shader); - diffuse_channel = current_shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } else { @@ -348,12 +357,11 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) } else if (!use_shaders && current_shader != NULL) { + LLGLSLShader::bindNoShader(); if (deferred_render) { gPipeline.unbindDeferredShader(*current_shader); - diffuse_channel = 0; } - LLGLSLShader::bindNoShader(); current_shader = NULL; } @@ -361,24 +369,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) { params.mGroup->rebuildMesh(); } - - - if (params.mTexture.notNull()) - { - gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get(), TRUE, TRUE); - if(params.mViewerTexture.notNull()) - { - params.mViewerTexture->addTextureStats(params.mVSize); - } - if (params.mTextureMatrix) - { - gGL.getTexUnit(0)->activate(); - glMatrixMode(GL_TEXTURE); - glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; - } - } - params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount/3); @@ -393,15 +383,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) } } - if (deferred_render && current_shader != NULL) - { - gPipeline.unbindDeferredShader(*current_shader); - LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - } - if (!light_enabled) { gPipeline.enableLightsDynamic(); diff --git a/linden/indra/newview/lldrawpoolavatar.cpp b/linden/indra/newview/lldrawpoolavatar.cpp index af7b5e3..80c7d73 100644 --- a/linden/indra/newview/lldrawpoolavatar.cpp +++ b/linden/indra/newview/lldrawpoolavatar.cpp @@ -94,7 +94,6 @@ BOOL gAvatarEmbossBumpMap = FALSE; static BOOL sRenderingSkinned = FALSE; S32 normal_channel = -1; S32 specular_channel = -1; -S32 diffuse_channel = -1; LLDrawPoolAvatar::LLDrawPoolAvatar() : LLFacePool(POOL_AVATAR) @@ -448,8 +447,7 @@ void LLDrawPoolAvatar::beginDeferredImpostor() normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); - diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); // KL SD - + sVertexProgram->bind(); } @@ -458,7 +456,6 @@ void LLDrawPoolAvatar::endDeferredImpostor() sShaderLevel = mVertexShaderLevel; sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); - sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); // KL SD sVertexProgram->unbind(); gGL.getTexUnit(0)->activate(); } @@ -702,8 +699,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) avatarp->mImpostor.bindTexture(1, specular_channel); } } - // avatarp->renderImpostor(LLColor4U(255,255,255,255), diffuse_channel); // KL SD - avatarp->renderImpostor(); + avatarp->renderImpostor(); } else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred) { @@ -756,67 +752,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if( !single_avatar || (avatarp == single_avatar) ) { - if (LLVOAvatar::sShowCollisionVolumes) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - avatarp->renderCollisionVolumes(); - } - - if (avatarp->isSelf() && LLAgent::sDebugDisplayTarget) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLVector3 pos = avatarp->getPositionAgent(); - - gGL.color4f(1.0f, 0.0f, 0.0f, 0.8f); - gGL.begin(LLRender::LINES); - { - gGL.vertex3fv((pos - LLVector3(0.2f, 0.f, 0.f)).mV); - gGL.vertex3fv((pos + LLVector3(0.2f, 0.f, 0.f)).mV); - gGL.vertex3fv((pos - LLVector3(0.f, 0.2f, 0.f)).mV); - gGL.vertex3fv((pos + LLVector3(0.f, 0.2f, 0.f)).mV); - gGL.vertex3fv((pos - LLVector3(0.f, 0.f, 0.2f)).mV); - gGL.vertex3fv((pos + LLVector3(0.f, 0.f, 0.2f)).mV); - }gGL.end(); - - pos = avatarp->mDrawable->getPositionAgent(); - gGL.color4f(1.0f, 0.0f, 0.0f, 0.8f); - gGL.begin(LLRender::LINES); - { - gGL.vertex3fv((pos - LLVector3(0.2f, 0.f, 0.f)).mV); - gGL.vertex3fv((pos + LLVector3(0.2f, 0.f, 0.f)).mV); - gGL.vertex3fv((pos - LLVector3(0.f, 0.2f, 0.f)).mV); - gGL.vertex3fv((pos + LLVector3(0.f, 0.2f, 0.f)).mV); - gGL.vertex3fv((pos - LLVector3(0.f, 0.f, 0.2f)).mV); - gGL.vertex3fv((pos + LLVector3(0.f, 0.f, 0.2f)).mV); - }gGL.end(); - - pos = avatarp->mRoot.getWorldPosition(); - gGL.color4f(1.0f, 1.0f, 1.0f, 0.8f); - gGL.begin(LLRender::LINES); - { - gGL.vertex3fv((pos - LLVector3(0.2f, 0.f, 0.f)).mV); - gGL.vertex3fv((pos + LLVector3(0.2f, 0.f, 0.f)).mV); - gGL.vertex3fv((pos - LLVector3(0.f, 0.2f, 0.f)).mV); - gGL.vertex3fv((pos + LLVector3(0.f, 0.2f, 0.f)).mV); - gGL.vertex3fv((pos - LLVector3(0.f, 0.f, 0.2f)).mV); - gGL.vertex3fv((pos + LLVector3(0.f, 0.f, 0.2f)).mV); - }gGL.end(); - - pos = avatarp->mPelvisp->getWorldPosition(); - gGL.color4f(0.0f, 0.0f, 1.0f, 0.8f); - gGL.begin(LLRender::LINES); - { - gGL.vertex3fv((pos - LLVector3(0.2f, 0.f, 0.f)).mV); - gGL.vertex3fv((pos + LLVector3(0.2f, 0.f, 0.f)).mV); - gGL.vertex3fv((pos - LLVector3(0.f, 0.2f, 0.f)).mV); - gGL.vertex3fv((pos + LLVector3(0.f, 0.2f, 0.f)).mV); - gGL.vertex3fv((pos - LLVector3(0.f, 0.f, 0.2f)).mV); - gGL.vertex3fv((pos + LLVector3(0.f, 0.f, 0.2f)).mV); - }gGL.end(); - - color.setColor(1.0f, 1.0f, 1.0f, 1.0f); - } - avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); } } diff --git a/linden/indra/newview/lldrawpoolbump.cpp b/linden/indra/newview/lldrawpoolbump.cpp index e14b34d..93fadca 100644 --- a/linden/indra/newview/lldrawpoolbump.cpp +++ b/linden/indra/newview/lldrawpoolbump.cpp @@ -140,7 +140,7 @@ void LLStandardBumpmap::restoreGL() return; } -// llinfos << "Loading bumpmap: " << bump_file << " from viewerart" << llendl; + llinfos << "Loading bumpmap: " << bump_file << " from viewerart" << llendl; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage = gImageList.getImageFromFile(bump_file, @@ -310,8 +310,8 @@ void LLDrawPoolBump::endRenderPass(S32 pass) void LLDrawPoolBump::beginShiny(bool invisible) { LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); - if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| - invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) + if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| + (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) { return; } @@ -385,8 +385,8 @@ void LLDrawPoolBump::beginShiny(bool invisible) void LLDrawPoolBump::renderShiny(bool invisible) { LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); - if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| - invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) + if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| + (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) { return; } @@ -412,8 +412,8 @@ void LLDrawPoolBump::renderShiny(bool invisible) void LLDrawPoolBump::endShiny(bool invisible) { LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); - if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| - invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) + if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| + (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) { return; } @@ -573,11 +573,7 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) LLImageGL* bump = NULL; U8 bump_code = params.mBump; - LLViewerImage* tex = params.mViewerTexture; - if(!tex) - { - return FALSE ; - } + LLViewerImage* tex = params.mTexture; switch( bump_code ) { @@ -1231,10 +1227,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) if (params.mTexture.notNull()) { gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get()); - if(params.mViewerTexture.notNull()) - { - params.mViewerTexture->addTextureStats(params.mVSize); - } + //params.mTexture->addTextureStats(params.mVSize); } else { diff --git a/linden/indra/newview/lldrawpoolsky.cpp b/linden/indra/newview/lldrawpoolsky.cpp index 0ca9130..bed1030 100644 --- a/linden/indra/newview/lldrawpoolsky.cpp +++ b/linden/indra/newview/lldrawpoolsky.cpp @@ -61,8 +61,8 @@ LLDrawPool *LLDrawPoolSky::instancePool() void LLDrawPoolSky::prerender() { - mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); -// gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable); + mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); + gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable); } void LLDrawPoolSky::render(S32 pass) @@ -97,7 +97,6 @@ void LLDrawPoolSky::render(S32 pass) } - LLVOSky *voskyp = gSky.mVOSkyp; LLGLSPipelineSkyBox gls_skybox; LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); @@ -120,43 +119,9 @@ void LLDrawPoolSky::render(S32 pass) { renderSkyCubeFace(i); } - - LLFace *hbfaces[3]; - hbfaces[0] = NULL; - hbfaces[1] = NULL; - hbfaces[2] = NULL; - for (S32 curr_face = 0; curr_face < face_count; curr_face++) - { - LLFace* facep = mDrawFace[curr_face]; - if (voskyp->isSameFace(LLVOSky::FACE_SUN, facep)) - { - hbfaces[0] = facep; - } - if (voskyp->isSameFace(LLVOSky::FACE_MOON, facep)) - { - hbfaces[1] = facep; - } - if (voskyp->isSameFace(LLVOSky::FACE_BLOOM, facep)) - { - hbfaces[2] = facep; - } - } LLGLEnable blend(GL_BLEND); - if (hbfaces[2]) - { - // renderSunHalo(hbfaces[2]); - } - if (hbfaces[0]) - { - // renderHeavenlyBody(0, hbfaces[0]); - } - if (hbfaces[1]) - { - // renderHeavenlyBody(1, hbfaces[1]); - } - glPopMatrix(); } @@ -181,35 +146,6 @@ void LLDrawPoolSky::renderSkyCubeFace(U8 side) } } -void LLDrawPoolSky::renderHeavenlyBody(U8 hb, LLFace* face) -{ - if ( !mHB[hb]->getDraw() ) return; - if (! face->getGeomCount()) return; - - LLImageGL* tex = face->getTexture(); - gGL.getTexUnit(0)->bind(tex); - LLColor4 color(mHB[hb]->getInterpColor()); - LLOverrideFaceColor override(this, color); - face->renderIndexed(); -} - - - -void LLDrawPoolSky::renderSunHalo(LLFace* face) -{ - if (! mHB[0]->getDraw()) return; - if (! face->getGeomCount()) return; - - LLImageGL* tex = face->getTexture(); - gGL.getTexUnit(0)->bind(tex); - LLColor4 color(mHB[0]->getInterpColor()); - color.mV[3] = llclamp(mHB[0]->getHaloBrighness(), 0.f, 1.f); - - LLOverrideFaceColor override(this, color); - face->renderIndexed(); -} - - void LLDrawPoolSky::renderForSelect() { } diff --git a/linden/indra/newview/lldrawpoolsky.h b/linden/indra/newview/lldrawpoolsky.h index f35b114..8595d73 100644 --- a/linden/indra/newview/lldrawpoolsky.h +++ b/linden/indra/newview/lldrawpoolsky.h @@ -36,14 +36,12 @@ #include "lldrawpool.h" class LLSkyTex; -class LLHeavenBody; class LLGLSLShader; class LLDrawPoolSky : public LLFacePool { private: LLSkyTex *mSkyTex; - LLHeavenBody *mHB[2]; // Sun and Moon LLGLSLShader *mShader; public: @@ -69,8 +67,6 @@ public: /*virtual*/ void renderForSelect(); /*virtual*/ void endRenderPass(S32 pass); void setSkyTex(LLSkyTex* const st) { mSkyTex = st; } - void setSun(LLHeavenBody* sun_flag) { mHB[0] = sun_flag; } - void setMoon(LLHeavenBody* moon) { mHB[1] = moon; } void renderSkyCubeFace(U8 side); void renderHeavenlyBody(U8 hb, LLFace* face); diff --git a/linden/indra/newview/lldrawpoolterrain.cpp b/linden/indra/newview/lldrawpoolterrain.cpp index 249f5a9..d0bf2c1 100644 --- a/linden/indra/newview/lldrawpoolterrain.cpp +++ b/linden/indra/newview/lldrawpoolterrain.cpp @@ -73,19 +73,19 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerImage *texturep) : TRUE, TRUE, GL_ALPHA8, GL_ALPHA, LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb")); - //gGL.getTexUnit(0)->bind(mAlphaRampImagep.get()); + gGL.getTexUnit(0)->bind(mAlphaRampImagep.get()); mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); m2DAlphaRampImagep = gImageList.getImageFromFile("alpha_gradient_2d.j2c", TRUE, TRUE, GL_ALPHA8, GL_ALPHA, LLUUID("38b86f85-2575-52a9-a531-23108d8da837")); - //gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); + gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_TERRAIN); - //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } LLDrawPoolTerrain::~LLDrawPoolTerrain() diff --git a/linden/indra/newview/lldrawpooltree.cpp b/linden/indra/newview/lldrawpooltree.cpp index 52f669a..e4560f2 100644 --- a/linden/indra/newview/lldrawpooltree.cpp +++ b/linden/indra/newview/lldrawpooltree.cpp @@ -52,7 +52,7 @@ LLDrawPoolTree::LLDrawPoolTree(LLViewerImage *texturep) : LLFacePool(POOL_TREE), mTexturep(texturep) { -// gGL.getTexUnit(0)->bind(mTexturep.get()); + gGL.getTexUnit(0)->bind(mTexturep.get()); mTexturep->setAddressMode(LLTexUnit::TAM_WRAP); } @@ -110,7 +110,7 @@ void LLDrawPoolTree::render(S32 pass) } else { - gGL.getTexUnit(sDiffTex)->bind(mTexturep, TRUE); + gGL.getTexUnit(sDiffTex)->bind(mTexturep); for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) @@ -140,7 +140,7 @@ void LLDrawPoolTree::endRenderPass(S32 pass) void LLDrawPoolTree::beginDeferredPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); // KL Render-pipeline has this set at 0.f ... NOOOOOO! make shitty trees :) + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); shader = &gDeferredTreeProgram; shader->bind(); @@ -166,9 +166,6 @@ void LLDrawPoolTree::beginShadowPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - glPolygonOffset(gSavedSettings.getF32("RenderDeferredTreeShadowOffset"), - gSavedSettings.getF32("RenderDeferredTreeShadowBias")); - gDeferredShadowProgram.bind(); } @@ -181,11 +178,7 @@ void LLDrawPoolTree::endShadowPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - - glPolygonOffset(gSavedSettings.getF32("RenderDeferredSpotShadowOffset"), - gSavedSettings.getF32("RenderDeferredSpotShadowBias")); - - //gDeferredShadowProgram.unbind(); + gDeferredShadowProgram.unbind(); } diff --git a/linden/indra/newview/lldrawpoolwater.cpp b/linden/indra/newview/lldrawpoolwater.cpp index d08d004..624b8a8 100644 --- a/linden/indra/newview/lldrawpoolwater.cpp +++ b/linden/indra/newview/lldrawpoolwater.cpp @@ -98,7 +98,7 @@ void LLDrawPoolWater::restoreGL() LLDrawPool *LLDrawPoolWater::instancePool() { - llwarns << "Should never be calling instancePool on a water pool!" << llendl; + llerrs << "Should never be calling instancePool on a water pool!" << llendl; return NULL; } @@ -401,15 +401,6 @@ void LLDrawPoolWater::shade() shader = &gWaterProgram; } - if (deferred_render) - { - gPipeline.bindDeferredShader(*shader); - } - else - { - shader->bind(); - } - sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f; S32 reftex = shader->enableTexture(LLViewerShaderMgr::WATER_REFTEX); @@ -445,6 +436,15 @@ void LLDrawPoolWater::shade() S32 screentex = shader->enableTexture(LLViewerShaderMgr::WATER_SCREENTEX); + if (deferred_render) + { + gPipeline.bindDeferredShader(*shader); + } + else + { + shader->bind(); + } + if (screentex > -1) { shader->uniform4fv(LLViewerShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV); diff --git a/linden/indra/newview/lldynamictexture.cpp b/linden/indra/newview/lldynamictexture.cpp index e219d4b..61f5a89 100644 --- a/linden/indra/newview/lldynamictexture.cpp +++ b/linden/indra/newview/lldynamictexture.cpp @@ -41,7 +41,6 @@ #include "llvertexbuffer.h" #include "llviewerdisplay.h" #include "llrender.h" -#include "pipeline.h" // static LLDynamicTexture::instance_list_t LLDynamicTexture::sInstances[ LLDynamicTexture::ORDER_COUNT ]; @@ -59,14 +58,9 @@ LLDynamicTexture::LLDynamicTexture(S32 width, S32 height, S32 components, EOrder mClamp(clamp) { llassert((1 <= components) && (components <= 4)); - if(!LLPipeline::sRenderDeferred) - { - generateGLTexture(); - } - else - { - gPipeline.markGLRebuild(this); // KL SD well for this to work its either gotta be one or the other so lets slap in the if/else can't do any harm. - } + + generateGLTexture(); + llassert( 0 <= order && order < ORDER_COUNT ); LLDynamicTexture::sInstances[ order ].insert(this); } @@ -83,11 +77,6 @@ LLDynamicTexture::~LLDynamicTexture() } } -void LLDynamicTexture::updateGL() -{ - generateGLTexture(); -} - //----------------------------------------------------------------------------- // releaseGLTexture() //----------------------------------------------------------------------------- @@ -112,7 +101,7 @@ void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum prima { if (mComponents < 1 || mComponents > 4) { - llwarns << "Bad number of components in dynamic texture: " << mComponents << llendl; + llerrs << "Bad number of components in dynamic texture: " << mComponents << llendl; } releaseGLTexture(); LLPointer<LLImageRaw> raw_image = new LLImageRaw(mWidth, mHeight, mComponents); @@ -122,7 +111,7 @@ void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum prima mTexture->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes); } // llinfos << "ALLOCATING " << (mWidth*mHeight*mComponents)/1024 << "K" << llendl; - mTexture->createGLTexture(0, raw_image); + mTexture->createGLTexture(0, raw_image, 0, TRUE, LLViewerImageBoostLevel::DYNAMIC_TEX); mTexture->setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP); mTexture->setGLTextureCreated(false); } diff --git a/linden/indra/newview/lldynamictexture.h b/linden/indra/newview/lldynamictexture.h index 1480799..5a20eae 100644 --- a/linden/indra/newview/lldynamictexture.h +++ b/linden/indra/newview/lldynamictexture.h @@ -37,7 +37,7 @@ #include "llcoord.h" #include "llimagegl.h" -class LLDynamicTexture : public LLGLUpdate +class LLDynamicTexture { public: enum EOrder { ORDER_FIRST = 0, ORDER_MIDDLE = 1, ORDER_LAST = 2, ORDER_RESET = 3, ORDER_COUNT = 4 }; @@ -49,8 +49,6 @@ public: BOOL clamp); virtual ~LLDynamicTexture(); - void updateGL(); - S32 getOriginX() { return mOrigin.mX; } S32 getOriginY() { return mOrigin.mY; } S32 getWidth() { return mWidth; } diff --git a/linden/indra/newview/llface.cpp b/linden/indra/newview/llface.cpp index ae57a3c..aa8cd15 100644 --- a/linden/indra/newview/llface.cpp +++ b/linden/indra/newview/llface.cpp @@ -176,8 +176,8 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mLastIndicesCount = mIndicesCount; mLastIndicesIndex = mIndicesIndex; - mAtlasInfop = NULL ; - mUsingAtlas = FALSE ; + mImportanceToCamera = 0.f ; + mBoundingSphereRadius = 0.0f ; } @@ -205,14 +205,12 @@ void LLFace::destroy() if (group) { group->dirtyGeom(); - gPipeline.markRebuild(group, TRUE); } } } setDrawInfo(NULL); - removeAtlas(); mDrawablep = NULL; mVObjp = NULL; } @@ -225,7 +223,7 @@ void LLFace::initClass() void LLFace::setWorldMatrix(const LLMatrix4 &mat) { - llwarns << "Faces on this drawable are not independently modifiable\n" << llendl; + llerrs << "Faces on this drawable are not independently modifiable\n" << llendl; } void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep) @@ -234,7 +232,7 @@ void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep) if (!new_pool) { - llwarns << "Setting pool to null!" << llendl; + llerrs << "Setting pool to null!" << llendl; } if (new_pool != mDrawPoolp) @@ -272,7 +270,6 @@ void LLFace::setTexture(LLViewerImage* tex) if(mTexture.notNull()) { mTexture->removeFace(this) ; - removeAtlas() ; } mTexture = tex ; @@ -456,15 +453,8 @@ void LLFace::renderForSelect(U32 data_mask) void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) { - if (mDrawablep->getSpatialGroup() == NULL) - { - return; - } - - mDrawablep->getSpatialGroup()->rebuildGeom(); - mDrawablep->getSpatialGroup()->rebuildMesh(); - - if(mDrawablep.isNull() || mVertexBuffer.isNull()) + if(mDrawablep.isNull() || mVertexBuffer.isNull() || mDrawablep->getSpatialGroup() == NULL || + mDrawablep->getSpatialGroup()->isState(LLSpatialGroup::GEOM_DIRTY)) { return; } @@ -483,10 +473,17 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) glMultMatrixf((GLfloat*)mDrawablep->getRegion()->mRenderMatrix.mMatrix); } - glColor4fv(color.mV); + setFaceColor(color); + renderSetColor(); + mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); +#if !LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); +#endif mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); + unsetFaceColor(); + unsetFaceColor(); gGL.popMatrix(); } } @@ -730,8 +727,8 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, } mCenterLocal = (newMin+newMax)*0.5f; - // LLVector3 tmp = (newMin - newMax) ; - // mBoundingSphereRadius = tmp.length() * 0.5f ; + LLVector3 tmp = (newMin - newMax) ; + mBoundingSphereRadius = tmp.length() * 0.5f ; updateCenterAgent(); } @@ -966,12 +963,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, mVertexBuffer->getBinormalStrider(binormals, mGeomIndex); } - F32 tcoord_xoffset = 0.f ; - F32 tcoord_yoffset = 0.f ; - F32 tcoord_xscale = 1.f ; - F32 tcoord_yscale = 1.f ; - BOOL in_atlas = FALSE ; - if (rebuild_tcoord) { mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); @@ -979,18 +970,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex); } - - in_atlas = isAtlasInUse() ; - if(in_atlas) - { - const LLVector2* tmp = getTexCoordOffset() ; - tcoord_xoffset = tmp->mV[0] ; - tcoord_yoffset = tmp->mV[1] ; - - tmp = getTexCoordScale() ; - tcoord_xscale = tmp->mV[0] ; - tcoord_yscale = tmp->mV[1] ; - } } if (rebuild_color) { @@ -1078,7 +1057,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, 0.75f }; - if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || LLPipeline::sRenderBump && tep->getShiny())) + if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || (LLPipeline::sRenderBump && tep->getShiny()))) { color.mV[3] = U8 (alpha[tep->getShiny()] * 255); } @@ -1200,93 +1179,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, xform(tc, cos_ang, sin_ang, os, ot, ms, mt); } - if(in_atlas) - { - // - //manually calculate tex-coord per vertex for varying address modes. - //should be removed if shader can handle this. - // - - S32 int_part = 0 ; - switch(mTexture->getAddressMode()) - { - case LLTexUnit::TAM_CLAMP: - if(tc.mV[0] < 0.f) - { - tc.mV[0] = 0.f ; - } - else if(tc.mV[0] > 1.f) - { - tc.mV[0] = 1.f; - } - - if(tc.mV[1] < 0.f) - { - tc.mV[1] = 0.f ; - } - else if(tc.mV[1] > 1.f) - { - tc.mV[1] = 1.f; - } - break; - case LLTexUnit::TAM_MIRROR: - if(tc.mV[0] < 0.f) - { - tc.mV[0] = -tc.mV[0] ; - } - int_part = (S32)tc.mV[0] ; - if(int_part & 1) //odd number - { - tc.mV[0] = int_part + 1 - tc.mV[0] ; - } - else //even number - { - tc.mV[0] -= int_part ; - } - - if(tc.mV[1] < 0.f) - { - tc.mV[1] = -tc.mV[1] ; - } - int_part = (S32)tc.mV[1] ; - if(int_part & 1) //odd number - { - tc.mV[1] = int_part + 1 - tc.mV[1] ; - } - else //even number - { - tc.mV[1] -= int_part ; - } - break; - case LLTexUnit::TAM_WRAP: - if(tc.mV[0] > 1.f) - tc.mV[0] -= (S32)(tc.mV[0] - 0.00001f) ; - else if(tc.mV[0] < -1.f) - tc.mV[0] -= (S32)(tc.mV[0] + 0.00001f) ; - - if(tc.mV[1] > 1.f) - tc.mV[1] -= (S32)(tc.mV[1] - 0.00001f) ; - else if(tc.mV[1] < -1.f) - tc.mV[1] -= (S32)(tc.mV[1] + 0.00001f) ; - - if(tc.mV[0] < 0.f) - { - tc.mV[0] = 1.0f + tc.mV[0] ; - } - if(tc.mV[1] < 0.f) - { - tc.mV[1] = 1.0f + tc.mV[1] ; - } - break; - default: - break; - } - - tc.mV[0] = tcoord_xoffset + tcoord_xscale * tc.mV[0] ; - tc.mV[1] = tcoord_yoffset + tcoord_yscale * tc.mV[1] ; - } - - *tex_coords++ = tc; if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) @@ -1353,6 +1245,159 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, return TRUE; } +const F32 LEAST_IMPORTANCE = 0.05f ; +const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ; + +F32 LLFace::getTextureVirtualSize() +{ + F32 radius; + F32 cos_angle_to_view_dir; + mPixelArea = calcPixelArea(cos_angle_to_view_dir, radius); + + if (mPixelArea <= 0) + { + return 0.f; + } + + //get area of circle in texture space + LLVector2 tdim = mTexExtents[1] - mTexExtents[0]; + F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f; + if (texel_area <= 0) + { + // Probably animated, use default + texel_area = 1.f; + } + + F32 face_area; + if (mVObjp->isSculpted() && texel_area > 1.f) + { + //sculpts can break assumptions about texel area + face_area = mPixelArea; + } + else + { + //apply texel area to face area to get accurate ratio + //face_area /= llclamp(texel_area, 1.f/64.f, 16.f); + face_area = mPixelArea / llclamp(texel_area, 0.015625f, 1024.f); + } + + if(face_area > LLViewerImage::sMaxSmallImageSize) + { + if(mImportanceToCamera < LEAST_IMPORTANCE) //if the face is not important, do not load hi-res. + { + face_area = LLViewerImage::sMaxSmallImageSize ; + } + else if(face_area > LLViewerImage::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping. + { + if(mImportanceToCamera < LEAST_IMPORTANCE_FOR_LARGE_IMAGE)//if the face is not important, do not load hi-res. + { + face_area = LLViewerImage::sMinLargeImageSize ; + } + else if(mTexture.notNull() && mTexture->isLargeImage()) + { + face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius ); + } + } + } + + return face_area; +} + +F32 LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) +{ + //get area of circle around face + LLVector3 center = getPositionAgent(); + LLVector3 size = (mExtents[1] - mExtents[0]) * 0.5f; + + LLVector3 lookAt = center - LLViewerCamera::getInstance()->getOrigin(); + F32 dist = lookAt.normVec() ; + + //get area of circle around node + F32 app_angle = atanf(size.length()/dist); + radius = app_angle*LLDrawable::sCurPixelAngle; + F32 face_area = radius*radius * 3.14159f; + + if(dist < mBoundingSphereRadius) //camera is very close + { + cos_angle_to_view_dir = 1.0f ; + mImportanceToCamera = 1.0f ; + } + else + { + cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ; + mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ; + } + + return face_area ; +} + +//the projection of the face partially overlaps with the screen +F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ) +{ + F32 screen_radius = (F32)llmax(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()) ; + F32 center_angle = acosf(cos_angle_to_view_dir) ; + F32 d = center_angle * LLDrawable::sCurPixelAngle ; + + if(d + radius > screen_radius + 5.f) + { + //---------------------------------------------- + //calculate the intersection area of two circles + //F32 radius_square = radius * radius ; + //F32 d_square = d * d ; + //F32 screen_radius_square = screen_radius * screen_radius ; + //face_area = + // radius_square * acosf((d_square + radius_square - screen_radius_square)/(2 * d * radius)) + + // screen_radius_square * acosf((d_square + screen_radius_square - radius_square)/(2 * d * screen_radius)) - + // 0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ; + //---------------------------------------------- + + //the above calculation is too expensive + //the below is a good estimation: bounding box of the bounding sphere: + F32 alpha = 0.5f * (radius + screen_radius - d) / radius ; + alpha = llclamp(alpha, 0.f, 1.f) ; + return alpha * alpha ; + } + return 1.0f ; +} + +const S8 FACE_IMPORTANCE_LEVEL = 4 ; +const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL][2] = //{distance, importance_weight} + {{16.1f, 1.0f}, {32.1f, 0.5f}, {48.1f, 0.2f}, {96.1f, 0.05f} } ; +const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[FACE_IMPORTANCE_LEVEL][2] = //{cos(angle), importance_weight} + {{0.985f /*cos(10 degrees)*/, 1.0f}, {0.94f /*cos(20 degrees)*/, 0.8f}, {0.866f /*cos(30 degrees)*/, 0.64f}, {0.0f, 0.36f}} ; + +//static +F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist) +{ + F32 importance = 0.f ; + + if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() && + dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0]) + { + F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; + F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); + + if(camera_moving_speed > 10.0f || camera_angular_speed > 1.0f) + { + //if camera moves or rotates too fast, ignore the importance factor + return 0.f ; + } + + //F32 camera_relative_speed = camera_moving_speed * (lookAt * LLViewerCamera::getInstance()->getVelocityDir()) ; + + S32 i = 0 ; + for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i); + i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; + F32 dist_factor = FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][1] ; + + for(i = 0; i < FACE_IMPORTANCE_LEVEL && cos_angle_to_view_dir < FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][0] ; ++i) ; + i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; + importance = dist_factor * FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][1] ; + } + + return importance ; +} + BOOL LLFace::verify(const U32* indices_array) const { BOOL ok = TRUE; @@ -1541,153 +1586,3 @@ LLVector3 LLFace::getPositionAgent() const return mCenterLocal * getRenderMatrix(); } } - -// -//atlas -// -void LLFace::removeAtlas() -{ - setAtlasInUse(FALSE) ; - mAtlasInfop = NULL ; -} - -const LLTextureAtlas* LLFace::getAtlas()const -{ - if(mAtlasInfop) - { - return mAtlasInfop->getAtlas() ; - } - return NULL ; -} - -const LLVector2* LLFace::getTexCoordOffset()const -{ - if(isAtlasInUse()) - { - return mAtlasInfop->getTexCoordOffset() ; - } - return NULL ; -} -const LLVector2* LLFace::getTexCoordScale() const -{ - if(isAtlasInUse()) - { - return mAtlasInfop->getTexCoordScale() ; - } - return NULL ; -} - -BOOL LLFace::isAtlasInUse()const -{ - return mUsingAtlas ; -} - -BOOL LLFace::canUseAtlas()const -{ - //no drawable or no spatial group, do not use atlas - if(!mDrawablep || !mDrawablep->getSpatialGroup()) - { - return FALSE ; - } - - //if bump face, do not use atlas - if(getTextureEntry() && getTextureEntry()->getBumpmap()) - { - return FALSE ; - } - - //if animated texture, do not use atlas - if(isState(TEXTURE_ANIM)) - { - return FALSE ; - } - - return TRUE ; -} - -void LLFace::setAtlasInUse(BOOL flag) -{ - //no valid atlas to use. - if(flag && (!mAtlasInfop || !mAtlasInfop->isValid())) - { - flag = FALSE ; - } - - if(!flag && !mUsingAtlas) - { - return ; - } - - // - //at this stage (flag || mUsingAtlas) is always true. - // - - //rebuild the tex coords - if(mDrawablep) - { - gPipeline.markRebuild(mDrawablep, LLDrawable::REBUILD_TCOORD); - mUsingAtlas = flag ; - } - else - { - mUsingAtlas = FALSE ; - } -} - -LLTextureAtlasSlot* LLFace::getAtlasInfo() -{ - return mAtlasInfop ; -} - -void LLFace::setAtlasInfo(LLTextureAtlasSlot* atlasp) -{ - if(mAtlasInfop != atlasp) - { - if(mAtlasInfop) - { - //llwarns << "Atlas slot changed!" << llendl ; - } - mAtlasInfop = atlasp ; - } -} - -LLImageGL* LLFace::getGLTexture() const -{ - if(isAtlasInUse()) - { - return (LLImageGL*)mAtlasInfop->getAtlas() ; - } - - return (LLImageGL*)mTexture ; -} - -//switch to atlas or switch back to gl texture -//return TRUE if using atlas. -BOOL LLFace::switchTexture() -{ - //no valid atlas or texture - if(!mAtlasInfop || !mAtlasInfop->isValid() || !mTexture) - { - return FALSE ; - } - - if(mTexture->getTexelsInAtlas() >= (U32)mVSize || mTexture->getTexelsInAtlas() >= mTexture->getTexelsInGLTexture()) - { - //switch to use atlas - //atlas resolution is qualified, use it. - if(!mUsingAtlas) - { - setAtlasInUse(TRUE) ; - } - } - else //if atlas not qualified. - { - //switch back to GL texture - if(mUsingAtlas && mTexture->isGLTextureCreated() && mTexture->getDiscardLevel() < mTexture->getDiscardLevelInAtlas()) - { - setAtlasInUse(FALSE) ; - } - } - - return mUsingAtlas ; -} diff --git a/linden/indra/newview/llface.h b/linden/indra/newview/llface.h index 9f76d6b..4893e82 100644 --- a/linden/indra/newview/llface.h +++ b/linden/indra/newview/llface.h @@ -48,7 +48,6 @@ #include "llviewerimage.h" #include "llstat.h" #include "lldrawable.h" -#include "lltextureatlasmanager.h" class LLFacePool; class LLVolume; @@ -57,7 +56,6 @@ class LLTextureEntry; class LLVertexProgram; class LLViewerImage; class LLGeometryManager; -class LLTextureAtlasSlot; const F32 MIN_ALPHA_SIZE = 1024.f; const F32 MIN_TEX_ANIM_SIZE = 512.f; @@ -191,18 +189,14 @@ public: void setIndicesIndex(S32 idx) { mIndicesIndex = idx; } void setDrawInfo(LLDrawInfo* draw_info); - // KL was atlas S19 - LLImageGL* getGLTexture() const; - LLTextureAtlasSlot* getAtlasInfo() ; - void setAtlasInUse(BOOL flag); - void setAtlasInfo(LLTextureAtlasSlot* atlasp); - BOOL isAtlasInUse()const; - BOOL canUseAtlas() const; - const LLVector2* getTexCoordScale() const ; - const LLVector2* getTexCoordOffset()const; - const LLTextureAtlas* getAtlas()const ; - void removeAtlas() ; - BOOL switchTexture() ; + F32 getTextureVirtualSize() ; + F32 getImportanceToCamera()const {return mImportanceToCamera ;} + +private: + F32 adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ); + F32 calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) ; +public: + static F32 calcImportanceToCamera(F32 to_view_dir, F32 dist); public: @@ -218,7 +212,7 @@ public: LLMatrix4* mTextureMatrix; LLDrawInfo* mDrawInfo; -protected: +private: friend class LLGeometryManager; friend class LLVolumeGeometryManager; @@ -248,10 +242,12 @@ protected: F32 mVSize; F32 mPixelArea; - //atlas - LLPointer<LLTextureAtlasSlot> mAtlasInfop ; - BOOL mUsingAtlas ; - + //importance factor, in the range [0, 1.0]. + //1.0: the most important. + //based on the distance from the face to the view point and the angle from the face center to the view direction. + F32 mImportanceToCamera ; + F32 mBoundingSphereRadius ; + protected: static BOOL sSafeRenderSelect; @@ -279,9 +275,9 @@ public: const LLTextureEntry* lte = lhs->getTextureEntry(); const LLTextureEntry* rte = rhs->getTextureEntry(); - if(lhs->getGLTexture() != rhs->getGLTexture()) // KL SD get GL + if (lhs->getTexture() != rhs->getTexture()) { - return lhs->getGLTexture() < rhs->getGLTexture(); // not getTexture? + return lhs->getTexture() < rhs->getTexture(); } else if (lte->getBumpShinyFullbright() != rte->getBumpShinyFullbright()) { diff --git a/linden/indra/newview/llfloaterassetbrowser.cpp b/linden/indra/newview/llfloaterassetbrowser.cpp index ca0e8d1..af81c4a 100644 --- a/linden/indra/newview/llfloaterassetbrowser.cpp +++ b/linden/indra/newview/llfloaterassetbrowser.cpp @@ -63,7 +63,7 @@ LLFloaterAssetBrowser::~LLFloaterAssetBrowser() mTextureAssets.clear(); mMaxIndex = 0; mFirstIndex = 0; - mMouseOverIndex = NULL; + mMouseOverIndex = 0; mMouseOverUUID = LLUUID::null; mMouseOverAssetUUID = LLUUID::null; mFloaterTitle = ""; @@ -79,7 +79,7 @@ void LLFloaterAssetBrowser::initialize() mAssetInfoIndex = 0; mFloaterHeight = getRect().getHeight(); mFloaterWidth = getRect().getWidth(); - mMouseOverIndex = NULL; + mMouseOverIndex = 0; mMouseOverUUID = LLUUID::null; mMouseOverAssetUUID = LLUUID::null; mFloaterTitle = ""; @@ -131,14 +131,14 @@ void LLFloaterAssetBrowser::createThumbnails() { mTextureAssets[i].mTexturep = gImageList.getImage(mTextureAssets[i].mAssetUUID, MIPMAP_YES, IMMEDIATE_NO); mTextureAssets[i].mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_PREVIEW); - mTextureAssets[i].mTexturep->processTextureStats(); + //mTextureAssets[i].mTexturep->processTextureStats(); } //Generate the asset info text - for(S32 i = 0; i < items.count(); i++) + /*for(S32 i = 0; i < items.count(); i++) { - std::string asset_info; - std::string dimensions; + LLString asset_info; + LLString dimensions; asset_info.append(mTextureAssets[i].mName); @@ -151,7 +151,7 @@ void LLFloaterAssetBrowser::createThumbnails() asset_info.append(dimensions); mTextureAssets[i].mAssetInfo = asset_info; - } + }*/ mFloaterTitle = llformat("Asset Browser (%d assets fetched)", mTextureAssets.size()); setTitle(mFloaterTitle); @@ -288,7 +288,7 @@ void LLFloaterAssetBrowser::draw() if(mImageAssetID.notNull()) { mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO); - mTexturep->setBoostLevel(LLViewerImageBoostLevel::BOOST_PREVIEW); + //mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); mTexturep->processTextureStats(); mTextureAssets[i].mWidth = mTexturep->mFullWidth; mTextureAssets[i].mHeight = mTexturep->mFullHeight; diff --git a/linden/indra/newview/llfloaterchat.cpp b/linden/indra/newview/llfloaterchat.cpp index 5f43406..2daa5aa 100644 --- a/linden/indra/newview/llfloaterchat.cpp +++ b/linden/indra/newview/llfloaterchat.cpp @@ -582,8 +582,7 @@ void LLFloaterChat::addChat(const LLChat& chat, // We display anything if it's not an IM. If it's an IM, check pref... if ( !from_instant_message || gSavedSettings.getBOOL("IMInChatConsole") ) { - gConsole->addConsoleLine(chat.mText, text_color); - + gConsole->addLine(chat.mText, size, text_color); } } diff --git a/linden/indra/newview/llfloaterhardwaresettings.cpp b/linden/indra/newview/llfloaterhardwaresettings.cpp index 8c91f5a..7886e39 100644 --- a/linden/indra/newview/llfloaterhardwaresettings.cpp +++ b/linden/indra/newview/llfloaterhardwaresettings.cpp @@ -68,7 +68,6 @@ void LLFloaterHardwareSettings::onClickHelp(void* data) void LLFloaterHardwareSettings::initCallbacks(void) { - childSetCommitCallback("fbo", refreshState); } // menu maintenance functions @@ -84,8 +83,7 @@ void LLFloaterHardwareSettings::refresh() mVideoCardMem = gSavedSettings.getS32("TextureMemory"); mFogRatio = gSavedSettings.getF32("RenderFogRatio"); mProbeHardwareOnStartup = gSavedSettings.getBOOL("ProbeHardwareOnStartup"); - mRenderDeferred = gSavedSettings.getBOOL("RenderDeferred"); - mRenderUseFBO = gSavedSettings.getBOOL("RenderUseFBO"); + childSetValue("fsaa", (LLSD::Integer) mFSAASamples); refreshEnabledState(); } @@ -103,20 +101,6 @@ void LLFloaterHardwareSettings::refreshEnabledState() childSetEnabled("vbo", FALSE); } - if (!gGLManager.mHasFramebufferObject) - { - childSetEnabled("fbo", FALSE); - } - - if (!gGLManager.mHasDrawBuffers || !gSavedSettings.getBOOL("RenderUseFBO")) - { - childSetEnabled("deferred", FALSE); - } - else - { - childSetEnabled("deferred", TRUE); - } - // if no windlight shaders, turn off nighttime brightness, gamma, and fog distance childSetEnabled("gamma", !gPipeline.canUseWindLightShaders()); childSetEnabled("(brightness, lower is brighter)", !gPipeline.canUseWindLightShaders()); @@ -124,12 +108,6 @@ void LLFloaterHardwareSettings::refreshEnabledState() } -//static -void LLFloaterHardwareSettings::refreshState(LLUICtrl*, void*) -{ - LLFloaterHardwareSettings::instance()->refreshEnabledState(); -} - // static instance of it LLFloaterHardwareSettings* LLFloaterHardwareSettings::instance() { @@ -224,8 +202,7 @@ void LLFloaterHardwareSettings::cancel() gSavedSettings.setS32("TextureMemory", mVideoCardMem); gSavedSettings.setF32("RenderFogRatio", mFogRatio); gSavedSettings.setBOOL("ProbeHardwareOnStartup", mProbeHardwareOnStartup ); - gSavedSettings.setBOOL("RenderUseFBO", mRenderUseFBO); - gSavedSettings.setBOOL("RenderDeferred", mRenderDeferred); + close(); } diff --git a/linden/indra/newview/llfloaterhardwaresettings.h b/linden/indra/newview/llfloaterhardwaresettings.h index e564e1c..04a33f6 100644 --- a/linden/indra/newview/llfloaterhardwaresettings.h +++ b/linden/indra/newview/llfloaterhardwaresettings.h @@ -61,8 +61,6 @@ public: /// OK button static void onBtnOK( void* userdata ); - static void refreshState(LLUICtrl*, void*); - //// menu management /// show off our menu @@ -90,8 +88,6 @@ protected: LLSliderCtrl* mCtrlVideoCardMem; BOOL mUseVBO; - BOOL mRenderUseFBO; - BOOL mRenderDeferred; BOOL mUseAniso; U32 mFSAASamples; F32 mGamma; diff --git a/linden/indra/newview/llfloaterlagmeter.cpp b/linden/indra/newview/llfloaterlagmeter.cpp index 2ae2e32..8fe455f 100644 --- a/linden/indra/newview/llfloaterlagmeter.cpp +++ b/linden/indra/newview/llfloaterlagmeter.cpp @@ -180,7 +180,7 @@ void LLFloaterLagMeter::determineClient() { mClientCause->setText( getString("client_texture_loading_cause_msg", mStringArgs) ); } - else if((LLViewerImage::sBoundTextureMemoryInBytes >> 20) > LLViewerImage::sMaxBoundTextureMemInMegaBytes) + else if((BYTES_TO_MEGA_BYTES(LLViewerImage::sBoundTextureMemoryInBytes)) > LLViewerImage::sMaxBoundTextureMemInMegaBytes) { mClientCause->setText( getString("client_texture_memory_cause_msg", mStringArgs) ); } diff --git a/linden/indra/newview/llfloaterpostprocess.cpp b/linden/indra/newview/llfloaterpostprocess.cpp index c5b2018..de9b598 100644 --- a/linden/indra/newview/llfloaterpostprocess.cpp +++ b/linden/indra/newview/llfloaterpostprocess.cpp @@ -52,29 +52,28 @@ LLFloaterPostProcess::LLFloaterPostProcess() : LLFloater(std::string("Post-Proce LLUICtrlFactory::getInstance()->buildFloater(this, "floater_post_process.xml"); /// Color Filter Callbacks - //childSetCommitCallback("ColorFilterToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_color_filter"); - childSetCommitCallback("wmiColorFilterToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_color_filter"); + childSetCommitCallback("ColorFilterToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_color_filter"); //childSetCommitCallback("ColorFilterGamma", &LLFloaterPostProcess::onFloatControlMoved, &(gPostProcess->tweaks.gamma())); - childSetCommitCallback("wmiColorFilterBrightness", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness"); - childSetCommitCallback("wmiColorFilterSaturation", &LLFloaterPostProcess::onFloatControlMoved, (char*)"saturation"); - childSetCommitCallback("wmiColorFilterContrast", &LLFloaterPostProcess::onFloatControlMoved, (char*)"contrast"); + childSetCommitCallback("ColorFilterBrightness", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness"); + childSetCommitCallback("ColorFilterSaturation", &LLFloaterPostProcess::onFloatControlMoved, (char*)"saturation"); + childSetCommitCallback("ColorFilterContrast", &LLFloaterPostProcess::onFloatControlMoved, (char*)"contrast"); - childSetCommitCallback("wmiColorFilterBaseR", &LLFloaterPostProcess::onColorControlRMoved, (char*)"contrast_base"); - childSetCommitCallback("wmiColorFilterBaseG", &LLFloaterPostProcess::onColorControlGMoved, (char*)"contrast_base"); - childSetCommitCallback("wmiColorFilterBaseB", &LLFloaterPostProcess::onColorControlBMoved, (char*)"contrast_base"); - childSetCommitCallback("wmiColorFilterBaseI", &LLFloaterPostProcess::onColorControlIMoved, (char*)"contrast_base"); + childSetCommitCallback("ColorFilterBaseR", &LLFloaterPostProcess::onColorControlRMoved, (char*)"contrast_base"); + childSetCommitCallback("ColorFilterBaseG", &LLFloaterPostProcess::onColorControlGMoved, (char*)"contrast_base"); + childSetCommitCallback("ColorFilterBaseB", &LLFloaterPostProcess::onColorControlBMoved, (char*)"contrast_base"); + childSetCommitCallback("ColorFilterBaseI", &LLFloaterPostProcess::onColorControlIMoved, (char*)"contrast_base"); /// Night Vision Callbacks - childSetCommitCallback("wmiNightVisionToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_night_vision"); - childSetCommitCallback("wmiNightVisionBrightMult", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness_multiplier"); - childSetCommitCallback("wmiNightVisionNoiseSize", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_size"); - childSetCommitCallback("wmiNightVisionNoiseStrength", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_strength"); + childSetCommitCallback("NightVisionToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_night_vision"); + childSetCommitCallback("NightVisionBrightMult", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness_multiplier"); + childSetCommitCallback("NightVisionNoiseSize", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_size"); + childSetCommitCallback("NightVisionNoiseStrength", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_strength"); /// Bloom Callbacks - childSetCommitCallback("wmiBloomToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_bloom"); - childSetCommitCallback("wmiBloomExtract", &LLFloaterPostProcess::onFloatControlMoved, (char*)"extract_low"); - childSetCommitCallback("wmiBloomSize", &LLFloaterPostProcess::onFloatControlMoved, (char*)"bloom_width"); - childSetCommitCallback("wmiBloomStrength", &LLFloaterPostProcess::onFloatControlMoved, (char*)"bloom_strength"); + childSetCommitCallback("BloomToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_bloom"); + childSetCommitCallback("BloomExtract", &LLFloaterPostProcess::onFloatControlMoved, (char*)"extract_low"); + childSetCommitCallback("BloomSize", &LLFloaterPostProcess::onFloatControlMoved, (char*)"bloom_width"); + childSetCommitCallback("BloomStrength", &LLFloaterPostProcess::onFloatControlMoved, (char*)"bloom_strength"); // Effect loading and saving. LLComboBox* comboBox = getChild<LLComboBox>("PPEffectsCombo"); @@ -114,7 +113,6 @@ void LLFloaterPostProcess::onBoolToggle(LLUICtrl* ctrl, void* userData) // check the bool LLCheckBoxCtrl* cbCtrl = static_cast<LLCheckBoxCtrl*>(ctrl); gPostProcess->tweaks[boolVariableName] = cbCtrl->getValue(); - } // Float Moved @@ -249,25 +247,25 @@ void LLFloaterPostProcess::syncMenu() comboBox->selectByValue(gPostProcess->getSelectedEffect()); /// Sync Color Filter Menu - childSetValue("wmiColorFilterToggle", gPostProcess->tweaks.useColorFilter()); + childSetValue("ColorFilterToggle", gPostProcess->tweaks.useColorFilter()); //childSetValue("ColorFilterGamma", gPostProcess->tweaks.gamma()); - childSetValue("wmiColorFilterBrightness", gPostProcess->tweaks.brightness()); - childSetValue("wmiColorFilterSaturation", gPostProcess->tweaks.saturation()); - childSetValue("wmiColorFilterContrast", gPostProcess->tweaks.contrast()); - childSetValue("wmiColorFilterBaseR", gPostProcess->tweaks.contrastBaseR()); - childSetValue("wmiColorFilterBaseG", gPostProcess->tweaks.contrastBaseG()); - childSetValue("wmiColorFilterBaseB", gPostProcess->tweaks.contrastBaseB()); - childSetValue("wmiColorFilterBaseI", gPostProcess->tweaks.contrastBaseIntensity()); + childSetValue("ColorFilterBrightness", gPostProcess->tweaks.brightness()); + childSetValue("ColorFilterSaturation", gPostProcess->tweaks.saturation()); + childSetValue("ColorFilterContrast", gPostProcess->tweaks.contrast()); + childSetValue("ColorFilterBaseR", gPostProcess->tweaks.contrastBaseR()); + childSetValue("ColorFilterBaseG", gPostProcess->tweaks.contrastBaseG()); + childSetValue("ColorFilterBaseB", gPostProcess->tweaks.contrastBaseB()); + childSetValue("ColorFilterBaseI", gPostProcess->tweaks.contrastBaseIntensity()); /// Sync Night Vision Menu - childSetValue("wmiNightVisionToggle", gPostProcess->tweaks.useNightVisionShader()); - childSetValue("wmiNightVisionBrightMult", gPostProcess->tweaks.brightMult()); - childSetValue("wmiNightVisionNoiseSize", gPostProcess->tweaks.noiseSize()); - childSetValue("wmiNightVisionNoiseStrength", gPostProcess->tweaks.noiseStrength()); + childSetValue("NightVisionToggle", gPostProcess->tweaks.useNightVisionShader()); + childSetValue("NightVisionBrightMult", gPostProcess->tweaks.brightMult()); + childSetValue("NightVisionNoiseSize", gPostProcess->tweaks.noiseSize()); + childSetValue("NightVisionNoiseStrength", gPostProcess->tweaks.noiseStrength()); /// Sync Bloom Menu - childSetValue("wmiBloomToggle", LLSD(gPostProcess->tweaks.useBloomShader())); - childSetValue("wmiBloomExtract", gPostProcess->tweaks.extractLow()); - childSetValue("wmiBloomSize", gPostProcess->tweaks.bloomWidth()); - childSetValue("wmiBloomStrength", gPostProcess->tweaks.bloomStrength()); + childSetValue("BloomToggle", LLSD(gPostProcess->tweaks.useBloomShader())); + childSetValue("BloomExtract", gPostProcess->tweaks.extractLow()); + childSetValue("BloomSize", gPostProcess->tweaks.bloomWidth()); + childSetValue("BloomStrength", gPostProcess->tweaks.bloomStrength()); } diff --git a/linden/indra/newview/llfloaterreporter.cpp b/linden/indra/newview/llfloaterreporter.cpp index 9209f41..a7f41ea 100644 --- a/linden/indra/newview/llfloaterreporter.cpp +++ b/linden/indra/newview/llfloaterreporter.cpp @@ -952,8 +952,7 @@ void LLFloaterReporter::takeScreenshot() // store in the image list so it doesn't try to fetch from the server LLPointer<LLViewerImage> image_in_list = new LLViewerImage(mResourceDatap->mAssetInfo.mUuid); - image_in_list->createGLTexture(0, raw); - + image_in_list->createGLTexture(0, raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); gImageList.addImage(image_in_list); // the texture picker then uses that texture diff --git a/linden/indra/newview/llhudeffect.cpp b/linden/indra/newview/llhudeffect.cpp index 20bbb32..c1d46f9 100644 --- a/linden/indra/newview/llhudeffect.cpp +++ b/linden/indra/newview/llhudeffect.cpp @@ -78,7 +78,7 @@ void LLHUDEffect::unpackData(LLMessageSystem *mesgsys, S32 blocknum) void LLHUDEffect::render() { - llwarns << "Never call this!" << llendl; // Then why the &*^&*^ is it here? + llerrs << "Never call this!" << llendl; } void LLHUDEffect::setID(const LLUUID &id) diff --git a/linden/indra/newview/llhudtext.cpp b/linden/indra/newview/llhudtext.cpp index b17f8d7..7d9f7f9 100644 --- a/linden/indra/newview/llhudtext.cpp +++ b/linden/indra/newview/llhudtext.cpp @@ -1116,8 +1116,6 @@ void LLHUDText::renderAllHUD() LLVertexBuffer::unbind(); - LLVertexBuffer::unbind(); // KL not entirely sure why but render pipeline has this twice? - LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); diff --git a/linden/indra/newview/llmanip.cpp b/linden/indra/newview/llmanip.cpp index 0c88c47..45550fc 100644 --- a/linden/indra/newview/llmanip.cpp +++ b/linden/indra/newview/llmanip.cpp @@ -60,7 +60,7 @@ #include "llglheaders.h" // Local constants... -const S32 VERTICAL_OFFSET = 100; // KL adjusted to compensate for toolbars move to the top of the screen! +const S32 VERTICAL_OFFSET = 50; F32 LLManip::sHelpTextVisibleTime = 2.f; F32 LLManip::sHelpTextFadeTime = 2.f; diff --git a/linden/indra/newview/llmaniptranslate.h b/linden/indra/newview/llmaniptranslate.h index 25ff35c..77f12ff 100644 --- a/linden/indra/newview/llmaniptranslate.h +++ b/linden/indra/newview/llmaniptranslate.h @@ -116,7 +116,7 @@ private: LLVector3d mDragCursorStartGlobal; LLVector3d mDragSelectionStartGlobal; LLTimer mUpdateTimer; - typedef std::set<ManipulatorHandle*, compare_manipulators> minpulator_list_t; + typedef std::multiset<ManipulatorHandle*, compare_manipulators> minpulator_list_t; minpulator_list_t mProjectedManipulators; LLVector4 mManipulatorVertices[18]; F32 mSnapOffsetMeters; diff --git a/linden/indra/newview/llmediactrl.cpp b/linden/indra/newview/llmediactrl.cpp index a517332..1530598 100644 --- a/linden/indra/newview/llmediactrl.cpp +++ b/linden/indra/newview/llmediactrl.cpp @@ -1012,7 +1012,8 @@ BOOL LLWebBrowserTexture::render() x_pos, y_pos, width, - height); + height, + TRUE); // force a fast update (i.e. don't call analyzeAlpha, etc.) } media_plugin->resetDirty(); diff --git a/linden/indra/newview/lloverlaybar.cpp b/linden/indra/newview/lloverlaybar.cpp index 1b60eee..3af3d0e 100644 --- a/linden/indra/newview/lloverlaybar.cpp +++ b/linden/indra/newview/lloverlaybar.cpp @@ -444,6 +444,7 @@ void LLOverlayBar::toggleMusicPlay(void*) // if ( gAudiop->isInternetStreamPlaying() == 0 ) { gAudiop->startInternetStream(parcel->getMusicURL()); +//awfixme sTitleObserver.init(parcel->getMusicURL()); } } } diff --git a/linden/indra/newview/llpanelvolume.cpp b/linden/indra/newview/llpanelvolume.cpp index 4270f0b..6d014a2 100644 --- a/linden/indra/newview/llpanelvolume.cpp +++ b/linden/indra/newview/llpanelvolume.cpp @@ -53,7 +53,6 @@ #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcolorswatch.h" -#include "lltexturectrl.h" #include "llcombobox.h" #include "llfirstuse.h" #include "llfocusmgr.h" @@ -112,28 +111,12 @@ BOOL LLPanelVolume::postBuild() LightColorSwatch->setOnSelectCallback(onLightSelectColor); childSetCommitCallback("colorswatch",onCommitLight,this); } - - LLTextureCtrl* LightTexPicker = getChild<LLTextureCtrl>("light texture control"); - if (LightTexPicker) - { - LightTexPicker->setOnCancelCallback(onLightCancelTexture); - LightTexPicker->setOnSelectCallback(onLightSelectTexture); - childSetCommitCallback("light texture control", onCommitLight, this); - } - childSetCommitCallback("Light Intensity",onCommitLight,this); childSetValidate("Light Intensity",precommitValidate); childSetCommitCallback("Light Radius",onCommitLight,this); childSetValidate("Light Radius",precommitValidate); childSetCommitCallback("Light Falloff",onCommitLight,this); childSetValidate("Light Falloff",precommitValidate); - - childSetCommitCallback("Light FOV", onCommitLight, this); - childSetValidate("Light FOV", precommitValidate); - childSetCommitCallback("Light Focus", onCommitLight, this); - childSetValidate("Light Focus", precommitValidate); - childSetCommitCallback("Light Ambiance", onCommitLight, this); - childSetValidate("Light Ambiance", precommitValidate); } // Start with everyone disabled @@ -238,32 +221,14 @@ void LLPanelVolume::getState( ) LightColorSwatch->setValid( TRUE ); LightColorSwatch->set(volobjp->getLightBaseColor()); } - - LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control"); - if (LightTextureCtrl) - { - LightTextureCtrl->setEnabled(TRUE); - LightTextureCtrl->setValid(TRUE); - LightTextureCtrl->setImageAssetID(volobjp->getLightTextureID()); - } - childSetEnabled("Light Intensity",true); childSetEnabled("Light Radius",true); childSetEnabled("Light Falloff",true); - childSetEnabled("Light FOV", true); - childSetEnabled("Light Focus", true); - childSetEnabled("Light Ambiance", true); - childSetValue("Light Intensity",volobjp->getLightIntensity()); childSetValue("Light Radius",volobjp->getLightRadius()); childSetValue("Light Falloff",volobjp->getLightFalloff()); - LLVector3 params = volobjp->getSpotLightParams(); - childSetValue("Light FOV", params.mV[0]); - childSetValue("Light Focus", params.mV[1]); - childSetValue("Light Ambiance", params.mV[2]); - mLightSavedColor = volobjp->getLightColor(); } else @@ -279,20 +244,9 @@ void LLPanelVolume::getState( ) LightColorSwatch->setEnabled( FALSE ); LightColorSwatch->setValid( FALSE ); } - LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control"); - if (LightTextureCtrl) - { - LightTextureCtrl->setEnabled(FALSE); - LightTextureCtrl->setValid(FALSE); - } - childSetEnabled("Light Intensity",false); childSetEnabled("Light Radius",false); childSetEnabled("Light Falloff",false); - - childSetEnabled("Light FOV",false); - childSetEnabled("Light Focus",false); - childSetEnabled("Light Ambiance",false); } // Flexible properties @@ -408,13 +362,6 @@ void LLPanelVolume::clearCtrls() LightColorSwatch->setEnabled( FALSE ); LightColorSwatch->setValid( FALSE ); } - LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control"); - if(LightTextureCtrl) - { - LightTextureCtrl->setEnabled( FALSE ); - LightTextureCtrl->setValid( FALSE ); - } - childSetEnabled("Light Intensity",false); childSetEnabled("Light Radius",false); childSetEnabled("Light Falloff",false); @@ -491,16 +438,6 @@ void LLPanelVolume::onLightCancelColor(LLUICtrl* ctrl, void* userdata) onLightSelectColor(NULL, userdata); } -void LLPanelVolume::onLightCancelTexture(LLUICtrl* ctrl, void* userdata) -{ - LLPanelVolume* self = (LLPanelVolume*) userdata; - LLTextureCtrl* LightTextureCtrl = self->getChild<LLTextureCtrl>("light texture control"); - if (LightTextureCtrl) - { - LightTextureCtrl->setImageAssetID(self->mLightSavedTexture); - } -} - void LLPanelVolume::onLightSelectColor(LLUICtrl* ctrl, void* userdata) { LLPanelVolume* self = (LLPanelVolume*) userdata; @@ -522,25 +459,6 @@ void LLPanelVolume::onLightSelectColor(LLUICtrl* ctrl, void* userdata) } } -void LLPanelVolume::onLightSelectTexture(LLUICtrl* ctrl, void* userdata) -{ - LLPanelVolume* self = (LLPanelVolume*) userdata; - LLViewerObject* objectp = self->mObject; - if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) - { - return; - } - LLVOVolume *volobjp = (LLVOVolume *)objectp; - - - LLTextureCtrl* LightTextureCtrl = self->getChild<LLTextureCtrl>("light texture control"); - if(LightTextureCtrl) - { - LLUUID id = LightTextureCtrl->getImageAssetID(); - volobjp->setLightTextureID(id); - self->mLightSavedTexture = id; - } -} // static void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata ) { @@ -556,47 +474,12 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata ) volobjp->setLightIntensity((F32)self->childGetValue("Light Intensity").asReal()); volobjp->setLightRadius((F32)self->childGetValue("Light Radius").asReal()); volobjp->setLightFalloff((F32)self->childGetValue("Light Falloff").asReal()); - LLColorSwatchCtrl* LightColorSwatch = self->getChild<LLColorSwatchCtrl>("colorswatch"); if(LightColorSwatch) { LLColor4 clr = LightColorSwatch->get(); volobjp->setLightColor(LLColor3(clr)); } - - LLTextureCtrl* LightTextureCtrl = self->getChild<LLTextureCtrl>("light texture control"); - if(LightTextureCtrl) - { - LLUUID id = LightTextureCtrl->getImageAssetID(); - if (id.notNull()) - { - if (volobjp->getLightTextureID().isNull()) - { //this commit is making this a spot light, set UI to default params - volobjp->setLightTextureID(id); - LLVector3 spot_params = volobjp->getSpotLightParams(); - self->childSetValue("Light FOV", spot_params.mV[0]); - self->childSetValue("Light Focus", spot_params.mV[1]); - self->childSetValue("Light Ambiance", spot_params.mV[2]); - } - else - { //modifying existing params - LLVector3 spot_params; - spot_params.mV[0] = (F32) self->childGetValue("Light FOV").asReal(); - spot_params.mV[1] = (F32) self->childGetValue("Light Focus").asReal(); - spot_params.mV[2] = (F32) self->childGetValue("Light Ambiance").asReal(); - volobjp->setSpotLightParams(spot_params); - } - } - else if (volobjp->getLightTextureID().notNull()) - { //no longer a spot light - volobjp->setLightTextureID(id); - //self->childDisable("Light FOV"); - //self->childDisable("Light Focus"); - //self->childDisable("Light Ambiance"); - } - } - - } // static diff --git a/linden/indra/newview/llpanelvolume.h b/linden/indra/newview/llpanelvolume.h index 5d206fc..841880b 100644 --- a/linden/indra/newview/llpanelvolume.h +++ b/linden/indra/newview/llpanelvolume.h @@ -74,10 +74,6 @@ public: static void onLightCancelColor(LLUICtrl* ctrl, void* userdata); static void onLightSelectColor(LLUICtrl* ctrl, void* userdata); - static void onLightCancelTexture(LLUICtrl* ctrl, void* userdata); - static void onLightSelectTexture(LLUICtrl* ctrl, void* userdata); - - protected: void getState(); @@ -103,7 +99,6 @@ protected: */ LLColor4 mLightSavedColor; - LLUUID mLightSavedTexture; LLPointer<LLViewerObject> mObject; LLPointer<LLViewerObject> mRootObject; }; diff --git a/linden/indra/newview/llpostprocess.cpp b/linden/indra/newview/llpostprocess.cpp deleted file mode 100644 index c7d5dad..0000000 --- a/linden/indra/newview/llpostprocess.cpp +++ /dev/null @@ -1,594 +0,0 @@ -/** - * @file llpostprocess.cpp - * @brief LLPostProcess class implementation - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "linden_common.h" - -#include "llpostprocess.h" -#include "llglslshader.h" -#include "llsdserialize.h" -#include "llrender.h" - -#include "llviewershadermgr.h" // KL throwing some includes at postprocess see if we can get the bastard working! -#include "pipeline.h" -#include "llimagegl.h" - - - -LLPostProcess * gPostProcess = NULL; - - -static const unsigned int NOISE_SIZE = 512; - -/// CALCULATING LUMINANCE (Using NTSC lum weights) -/// http://en.wikipedia.org/wiki/Luma_%28video%29 -static const float LUMINANCE_R = 0.299f; -static const float LUMINANCE_G = 0.587f; -static const float LUMINANCE_B = 0.114f; - -static const char * const XML_FILENAME = "postprocesseffects.xml"; - -LLPostProcess::LLPostProcess(void) : - initialized(false), - mAllEffects(LLSD::emptyMap()), - screenW(1), screenH(1) -{ - mSceneRenderTexture = NULL ; - mNoiseTexture = NULL ; - mTempBloomTexture = NULL ; - - // Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender. - std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME)); - LL_DEBUGS2("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL; - - llifstream effectsXML(pathName); - - if (effectsXML) - { - LLPointer<LLSDParser> parser = new LLSDXMLParser(); - - parser->parse(effectsXML, mAllEffects, LLSDSerialize::SIZE_UNLIMITED); - } - - if (!mAllEffects.has("default")) - { - LLSD & defaultEffect = (mAllEffects["default"] = LLSD::emptyMap()); - - defaultEffect["enable_night_vision"] = LLSD::Boolean(false); - defaultEffect["enable_bloom"] = LLSD::Boolean(false); - defaultEffect["enable_color_filter"] = LLSD::Boolean(false); - - /// NVG Defaults - defaultEffect["brightness_multiplier"] = 3.0; - defaultEffect["noise_size"] = 25.0; - defaultEffect["noise_strength"] = 0.4; - - // TODO BTest potentially add this to tweaks? - noiseTextureScale = 1.0f; - - /// Bloom Defaults - defaultEffect["extract_low"] = 0.95; - defaultEffect["extract_high"] = 1.0; - defaultEffect["bloom_width"] = 2.25; - defaultEffect["bloom_strength"] = 1.5; - - /// Color Filter Defaults - defaultEffect["brightness"] = 1.0; - defaultEffect["contrast"] = 1.0; - defaultEffect["saturation"] = 1.0; - - LLSD& contrastBase = (defaultEffect["contrast_base"] = LLSD::emptyArray()); - contrastBase.append(1.0); - contrastBase.append(1.0); - contrastBase.append(1.0); - contrastBase.append(0.5); - } - - setSelectedEffect("default"); - -} - -LLPostProcess::~LLPostProcess(void) -{ - invalidate() ; -} - -// static -void LLPostProcess::initClass(void) -{ - //this will cause system to crash at second time login - //if first time login fails due to network connection --- bao - //***llassert_always(gPostProcess == NULL); - //replaced by the following line: - if(gPostProcess) - return ; - - - gPostProcess = new LLPostProcess(); -} - -// static -void LLPostProcess::cleanupClass() -{ - delete gPostProcess; - gPostProcess = NULL; -} - -void LLPostProcess::setSelectedEffect(std::string const & effectName) -{ - mSelectedEffectName = effectName; - static_cast<LLSD &>(tweaks) = mAllEffects[effectName]; -} - -void LLPostProcess::saveEffect(std::string const & effectName) -{ - // Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender. - mAllEffects[effectName] = tweaks; - - std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME)); - //llinfos << "Saving PostProcess Effects settings to " << pathName << llendl; - - llofstream effectsXML(pathName); - - LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter(); - - formatter->format(mAllEffects, effectsXML); - -} -void LLPostProcess::invalidate() -{ - mSceneRenderTexture = NULL ; - mNoiseTexture = NULL ; - mTempBloomTexture = NULL ; - initialized = FALSE ; -} - -void LLPostProcess::apply(unsigned int width, unsigned int height) -{ - if (!initialized || width != screenW || height != screenH){ - initialize(width, height); - } - if (shadersEnabled()){ - doEffects(); - } -} - -void LLPostProcess::initialize(unsigned int width, unsigned int height) -{ - screenW = width; - screenH = height; - createTexture(mSceneRenderTexture, screenW, screenH); - initialized = true; - - checkError(); - createNightVisionShader(); - createBloomShader(); - createColorFilterShader(); - checkError(); -} - -inline bool LLPostProcess::shadersEnabled(void) -{ - return (tweaks.useColorFilter().asBoolean() || - tweaks.useNightVisionShader().asBoolean() || - tweaks.useBloomShader().asBoolean() ); - -} - -void LLPostProcess::applyShaders(void) -{ - if (tweaks.useColorFilter()){ - applyColorFilterShader(); - checkError(); - } - if (tweaks.useNightVisionShader()){ - /// If any of the above shaders have been called update the frame buffer; - if (tweaks.useColorFilter()) - { - U32 tex = mSceneRenderTexture->getTexName() ; - copyFrameBuffer(tex, screenW, screenH); - } - applyNightVisionShader(); - checkError(); - } - if (tweaks.useBloomShader()){ - /// If any of the above shaders have been called update the frame buffer; - if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean()) - { - U32 tex = mSceneRenderTexture->getTexName() ; - copyFrameBuffer(tex, screenW, screenH); - } - applyBloomShader(); - checkError(); - } -} - -void LLPostProcess::applyColorFilterShader(void) -{ - // Do nothing. moved back to newview work in progress KL - gPostColorFilterProgram.bind(); - - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE); - - U32 tex = mSceneRenderTexture->getTexName() ; // KL - - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, tex); - - getShaderUniforms(colorFilterUniforms, gPostColorFilterProgram.mProgramObject); - glUniform1iARB(colorFilterUniforms["RenderTexture"], 0); - glUniform1fARB(colorFilterUniforms["brightness"], tweaks.getBrightness()); - glUniform1fARB(colorFilterUniforms["contrast"], tweaks.getContrast()); - float baseI = (tweaks.getContrastBaseR() + tweaks.getContrastBaseG() + tweaks.getContrastBaseB()) / 3.0f; - baseI = tweaks.getContrastBaseIntensity() / ((baseI < 0.001f) ? 0.001f : baseI); - float baseR = tweaks.getContrastBaseR() * baseI; - float baseG = tweaks.getContrastBaseG() * baseI; - float baseB = tweaks.getContrastBaseB() * baseI; - glUniform3fARB(colorFilterUniforms["contrastBase"], baseR, baseG, baseB); - glUniform1fARB(colorFilterUniforms["saturation"], tweaks.getSaturation()); - glUniform3fARB(colorFilterUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B); - - LLGLEnable blend(GL_BLEND); - gGL.setSceneBlendType(LLRender::BT_REPLACE); - LLGLDepthTest depth(GL_FALSE); - - /// Draw a screen space quad - drawOrthoQuad(screenW, screenH, QUAD_NORMAL); - gPostColorFilterProgram.unbind(); - -} - -void LLPostProcess::createColorFilterShader(void) -{ - /// Define uniform names - colorFilterUniforms["RenderTexture"] = 0; - colorFilterUniforms["brightness"] = 0; - colorFilterUniforms["contrast"] = 0; - colorFilterUniforms["contrastBase"] = 0; - colorFilterUniforms["saturation"] = 0; - colorFilterUniforms["lumWeights"] = 0; -} - -void LLPostProcess::applyNightVisionShader(void) -{ - // KL re-enabled and moved back to newview - gPostNightVisionProgram.bind(); - - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE); - - getShaderUniforms(nightVisionUniforms, gPostNightVisionProgram.mProgramObject); - U32 sceneRenderTexture = mSceneRenderTexture->getTexName() ; // KL - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, sceneRenderTexture); - glUniform1iARB(nightVisionUniforms["RenderTexture"], 0); - - gGL.getTexUnit(1)->activate(); - gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); - U32 noiseTexture = mNoiseTexture->getTexName(); //KL - gGL.getTexUnit(1)->bindManual(LLTexUnit::TT_TEXTURE, noiseTexture); - glUniform1iARB(nightVisionUniforms["NoiseTexture"], 1); - - - glUniform1fARB(nightVisionUniforms["brightMult"], tweaks.getBrightMult()); - glUniform1fARB(nightVisionUniforms["noiseStrength"], tweaks.getNoiseStrength()); - noiseTextureScale = 0.01f + ((101.f - tweaks.getNoiseSize()) / 100.f); - noiseTextureScale *= (screenH / NOISE_SIZE); - - - glUniform3fARB(nightVisionUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B); - - LLGLEnable blend(GL_BLEND); - gGL.setSceneBlendType(LLRender::BT_REPLACE); - LLGLDepthTest depth(GL_FALSE); - - /// Draw a screen space quad - drawOrthoQuad(screenW, screenH, QUAD_NOISE); - gPostNightVisionProgram.unbind(); - gGL.getTexUnit(0)->activate(); - -} - -void LLPostProcess::createNightVisionShader(void) -{ - /// Define uniform names - nightVisionUniforms["RenderTexture"] = 0; - nightVisionUniforms["NoiseTexture"] = 0; - nightVisionUniforms["brightMult"] = 0; - nightVisionUniforms["noiseStrength"] = 0; - nightVisionUniforms["lumWeights"] = 0; - - createNoiseTexture(mNoiseTexture); -} - -void LLPostProcess::applyBloomShader(void) -{ - -} - -void LLPostProcess::createBloomShader(void) -{ - createTexture(mTempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5)); - - /// Create Bloom Extract Shader - bloomExtractUniforms["RenderTexture"] = 0; - bloomExtractUniforms["extractLow"] = 0; - bloomExtractUniforms["extractHigh"] = 0; - bloomExtractUniforms["lumWeights"] = 0; - - /// Create Bloom Blur Shader - bloomBlurUniforms["RenderTexture"] = 0; - bloomBlurUniforms["bloomStrength"] = 0; - bloomBlurUniforms["texelSize"] = 0; - bloomBlurUniforms["blurDirection"] = 0; - bloomBlurUniforms["blurWidth"] = 0; -} - -void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog) -{ - /// Find uniform locations and insert into map - std::map<const char *, GLuint>::iterator i; - for (i = uniforms.begin(); i != uniforms.end(); ++i){ - i->second = glGetUniformLocationARB(prog, i->first); - } -} - -void LLPostProcess::doEffects(void) -{ - /// Save GL State - glPushAttrib(GL_ALL_ATTRIB_BITS); - glPushClientAttrib(GL_ALL_ATTRIB_BITS); - - /// Copy the screen buffer to the render texture - { - U32 tex = mSceneRenderTexture->getTexName() ; - copyFrameBuffer(tex, screenW, screenH); - } - - /// Clear the frame buffer. - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - /// Change to an orthogonal view - viewOrthogonal(screenW, screenH); - - checkError(); - applyShaders(); - - LLGLSLShader::bindNoShader(); - checkError(); - - /// Change to a perspective view - viewPerspective(); - - /// Reset GL State - glPopClientAttrib(); - glPopAttrib(); - checkError(); -} - -void LLPostProcess::copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height) -{ - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture); - glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0); -} - -void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadType type) -{ - - float noiseX = 0.f; - float noiseY = 0.f; - float screenRatio = 1.0f; - - if (type == QUAD_NOISE){ - noiseX = ((float) rand() / (float) RAND_MAX); - noiseY = ((float) rand() / (float) RAND_MAX); - screenRatio = (float) width / (float) height; - } - - - glBegin(GL_QUADS); - if (type != QUAD_BLOOM_EXTRACT){ - glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height); - } else { - glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height * 2.0f); - } - if (type == QUAD_NOISE){ - glMultiTexCoord2fARB(GL_TEXTURE1_ARB, - noiseX, - noiseTextureScale + noiseY); - } else if (type == QUAD_BLOOM_COMBINE){ - glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, (GLfloat) height * 0.5f); - } - glVertex2f(0.f, (GLfloat) screenH - height); - - if (type != QUAD_BLOOM_EXTRACT){ - glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f); - } else { - glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f); - } - if (type == QUAD_NOISE){ - glMultiTexCoord2fARB(GL_TEXTURE1_ARB, - noiseX, - noiseY); - } else if (type == QUAD_BLOOM_COMBINE){ - glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, 0.f); - } - glVertex2f(0.f, (GLfloat) height + (screenH - height)); - - - if (type != QUAD_BLOOM_EXTRACT){ - glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, 0.f); - } else { - glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, 0.f); - } - if (type == QUAD_NOISE){ - glMultiTexCoord2fARB(GL_TEXTURE1_ARB, - screenRatio * noiseTextureScale + noiseX, - noiseY); - } else if (type == QUAD_BLOOM_COMBINE){ - glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, 0.f); - } - glVertex2f((GLfloat) width, (GLfloat) height + (screenH - height)); - - - if (type != QUAD_BLOOM_EXTRACT){ - glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, (GLfloat) height); - } else { - glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, (GLfloat) height * 2.0f); - } - if (type == QUAD_NOISE){ - glMultiTexCoord2fARB(GL_TEXTURE1_ARB, - screenRatio * noiseTextureScale + noiseX, - noiseTextureScale + noiseY); - } else if (type == QUAD_BLOOM_COMBINE){ - glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, (GLfloat) height * 0.5f); - } - glVertex2f((GLfloat) width, (GLfloat) screenH - height); - glEnd(); - -} - -void LLPostProcess::viewOrthogonal(unsigned int width, unsigned int height) -{ - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho( 0.f, (GLdouble) width , (GLdouble) height , 0.f, -1.f, 1.f ); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); -} - -void LLPostProcess::viewPerspective(void) -{ - glMatrixMode( GL_PROJECTION ); - glPopMatrix(); - glMatrixMode( GL_MODELVIEW ); - glPopMatrix(); -} - -void LLPostProcess::changeOrthogonal(unsigned int width, unsigned int height) -{ - viewPerspective(); - viewOrthogonal(width, height); -} - -void LLPostProcess::createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height) -{ - std::vector<GLubyte> data(width * height * 4, 0) ; - - texture = new LLImageGL(FALSE) ; - if(texture->createGLTexture()) - { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture->getTexName()); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - } -} - -void LLPostProcess::createNoiseTexture(LLPointer<LLImageGL>& texture) -{ - std::vector<GLubyte> buffer(NOISE_SIZE * NOISE_SIZE); - for (unsigned int i = 0; i < NOISE_SIZE; i++){ - for (unsigned int k = 0; k < NOISE_SIZE; k++){ - buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f); - } - } - - texture = new LLImageGL(FALSE) ; - if(texture->createGLTexture()) - { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName()); - LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - } -} - -bool LLPostProcess::checkError(void) -{ - GLenum glErr; - bool retCode = false; - - glErr = glGetError(); - while (glErr != GL_NO_ERROR) - { - // shaderErrorLog << (const char *) gluErrorString(glErr) << std::endl; - char const * err_str_raw = (const char *) gluErrorString(glErr); - - if(err_str_raw == NULL) - { - std::ostringstream err_builder; - err_builder << "unknown error number " << glErr; - mShaderErrorString = err_builder.str(); - } - else - { - mShaderErrorString = err_str_raw; - } - - retCode = true; - glErr = glGetError(); - } - return retCode; -} - -void LLPostProcess::checkShaderError(GLhandleARB shader) -{ - GLint infologLength = 0; - GLint charsWritten = 0; - GLchar *infoLog; - - checkError(); // Check for OpenGL errors - - glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength); - - checkError(); // Check for OpenGL errors - - if (infologLength > 0) - { - infoLog = (GLchar *)malloc(infologLength); - if (infoLog == NULL) - { - /// Could not allocate infolog buffer - return; - } - glGetInfoLogARB(shader, infologLength, &charsWritten, infoLog); - // shaderErrorLog << (char *) infoLog << std::endl; - mShaderErrorString = (char *) infoLog; - free(infoLog); - } - checkError(); // Check for OpenGL errors -} \ No newline at end of file diff --git a/linden/indra/newview/llpostprocess.h b/linden/indra/newview/llpostprocess.h deleted file mode 100644 index d6926e4..0000000 --- a/linden/indra/newview/llpostprocess.h +++ /dev/null @@ -1,274 +0,0 @@ -/** - * @file llpostprocess.h - * @brief LLPostProcess class definition - * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_POSTPROCESS_H -#define LL_POSTPROCESS_H - -#include <map> -#include <fstream> -#include "llgl.h" -#include "llglheaders.h" - -class LLPostProcess -{ -public: - - typedef enum _QuadType { - QUAD_NORMAL, - QUAD_NOISE, - QUAD_BLOOM_EXTRACT, - QUAD_BLOOM_COMBINE - } QuadType; - - /// GLSL Shader Encapsulation Struct - typedef std::map<const char *, GLuint> glslUniforms; - - struct PostProcessTweaks : public LLSD { - inline PostProcessTweaks() : LLSD(LLSD::emptyMap()) - { - } - - inline LLSD & brightMult() { - return (*this)["brightness_multiplier"]; - } - - inline LLSD & noiseStrength() { - return (*this)["noise_strength"]; - } - - inline LLSD & noiseSize() { - return (*this)["noise_size"]; - } - - inline LLSD & extractLow() { - return (*this)["extract_low"]; - } - - inline LLSD & extractHigh() { - return (*this)["extract_high"]; - } - - inline LLSD & bloomWidth() { - return (*this)["bloom_width"]; - } - - inline LLSD & bloomStrength() { - return (*this)["bloom_strength"]; - } - - inline LLSD & brightness() { - return (*this)["brightness"]; - } - - inline LLSD & contrast() { - return (*this)["contrast"]; - } - - inline LLSD & contrastBaseR() { - return (*this)["contrast_base"][0]; - } - - inline LLSD & contrastBaseG() { - return (*this)["contrast_base"][1]; - } - - inline LLSD & contrastBaseB() { - return (*this)["contrast_base"][2]; - } - - inline LLSD & contrastBaseIntensity() { - return (*this)["contrast_base"][3]; - } - - inline LLSD & saturation() { - return (*this)["saturation"]; - } - - inline LLSD & useNightVisionShader() { - return (*this)["enable_night_vision"]; - } - - inline LLSD & useBloomShader() { - return (*this)["enable_bloom"]; - } - - inline LLSD & useColorFilter() { - return (*this)["enable_color_filter"]; - } - - - inline F32 getBrightMult() const { - return F32((*this)["brightness_multiplier"].asReal()); - } - - inline F32 getNoiseStrength() const { - return F32((*this)["noise_strength"].asReal()); - } - - inline F32 getNoiseSize() const { - return F32((*this)["noise_size"].asReal()); - } - - inline F32 getExtractLow() const { - return F32((*this)["extract_low"].asReal()); - } - - inline F32 getExtractHigh() const { - return F32((*this)["extract_high"].asReal()); - } - - inline F32 getBloomWidth() const { - return F32((*this)["bloom_width"].asReal()); - } - - inline F32 getBloomStrength() const { - return F32((*this)["bloom_strength"].asReal()); - } - - inline F32 getBrightness() const { - return F32((*this)["brightness"].asReal()); - } - - inline F32 getContrast() const { - return F32((*this)["contrast"].asReal()); - } - - inline F32 getContrastBaseR() const { - return F32((*this)["contrast_base"][0].asReal()); - } - - inline F32 getContrastBaseG() const { - return F32((*this)["contrast_base"][1].asReal()); - } - - inline F32 getContrastBaseB() const { - return F32((*this)["contrast_base"][2].asReal()); - } - - inline F32 getContrastBaseIntensity() const { - return F32((*this)["contrast_base"][3].asReal()); - } - - inline F32 getSaturation() const { - return F32((*this)["saturation"].asReal()); - } - - }; - - bool initialized; - PostProcessTweaks tweaks; - - // the map of all availible effects - LLSD mAllEffects; - -private: - LLPointer<LLImageGL> mSceneRenderTexture ; - LLPointer<LLImageGL> mNoiseTexture ; - LLPointer<LLImageGL> mTempBloomTexture ; - - - -public: - LLPostProcess(void); - - ~LLPostProcess(void); - - void apply(unsigned int width, unsigned int height); - void invalidate() ; - - /// Perform global initialization for this class. - static void initClass(void); - - // Cleanup of global data that's only inited once per class. - static void cleanupClass(); - - void setSelectedEffect(std::string const & effectName); - - inline std::string const & getSelectedEffect(void) const { - return mSelectedEffectName; - } - - void saveEffect(std::string const & effectName); - -private: - /// read in from file - std::string mShaderErrorString; - unsigned int screenW; - unsigned int screenH; - - float noiseTextureScale; - - /// Shader Uniforms - glslUniforms nightVisionUniforms; - glslUniforms bloomExtractUniforms; - glslUniforms bloomBlurUniforms; - glslUniforms colorFilterUniforms; - - // the name of currently selected effect in mAllEffects - //invariant: tweaks == mAllEffects[mSelectedEffectName] - std::string mSelectedEffectName; - - /// General functions - void initialize(unsigned int width, unsigned int height); - void doEffects(void); - void applyShaders(void); - bool shadersEnabled(void); - - /// Night Vision Functions - void createNightVisionShader(void); - void applyNightVisionShader(void); - - /// Bloom Functions - void createBloomShader(void); - void applyBloomShader(void); - - /// Color Filter Functions - void createColorFilterShader(void); - void applyColorFilterShader(void); - - /// OpenGL Helper Functions - void getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog); - void createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height); - void copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height); - void createNoiseTexture(LLPointer<LLImageGL>& texture); - bool checkError(void); - void checkShaderError(GLhandleARB shader); - void drawOrthoQuad(unsigned int width, unsigned int height, QuadType type); - void viewOrthogonal(unsigned int width, unsigned int height); - void changeOrthogonal(unsigned int width, unsigned int height); - void viewPerspective(void); -}; - -extern LLPostProcess * gPostProcess; - - -#endif // LL_POSTPROCESS_H diff --git a/linden/indra/newview/llpreview.cpp b/linden/indra/newview/llpreview.cpp index 019bd5f..f679a75 100644 --- a/linden/indra/newview/llpreview.cpp +++ b/linden/indra/newview/llpreview.cpp @@ -641,7 +641,6 @@ void LLPreview::setAssetId(const LLUUID& asset_id) LLViewerObject* object = gObjectList.findObject(mObjectUUID); if(NULL == object) { - llwarns << "LLPreview::setAssetId() called on unrecognized object, UUID : " << mObjectUUID << llendl; return; } object->updateViewerInventoryAsset(item, asset_id); diff --git a/linden/indra/newview/llselectmgr.cpp b/linden/indra/newview/llselectmgr.cpp index 44ac8fd..16f79ec 100644 --- a/linden/indra/newview/llselectmgr.cpp +++ b/linden/indra/newview/llselectmgr.cpp @@ -766,7 +766,7 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab } else { - llwarns << "LLSelectMgr::add face " << face << " out-of-range" << llendl; + llerrs << "LLSelectMgr::add face " << face << " out-of-range" << llendl; return; } @@ -1189,7 +1189,7 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable) } else { - llwarns << "LLSelectMgr::remove - tried to remove TE " << te << " that wasn't selected" << llendl; + llerrs << "LLSelectMgr::remove - tried to remove TE " << te << " that wasn't selected" << llendl; return; } @@ -1212,7 +1212,7 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable) else { // ...out of range face - llwarns << "LLSelectMgr::remove - TE " << te << " out of range" << llendl; + llerrs << "LLSelectMgr::remove - TE " << te << " out of range" << llendl; } updateSelectionCenter(); @@ -1711,7 +1711,7 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright) } sendfunc(fullbright); getSelection()->applyToObjects(&sendfunc); } -/* + void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url) { U8 media_flags = LLTextureEntry::MF_NONE; @@ -1754,7 +1754,7 @@ void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& } sendfunc(media_type, media_url); getSelection()->applyToObjects(&sendfunc); } -*/ + void LLSelectMgr::selectionSetGlow(F32 glow) { struct f1 : public LLSelectedTEFunctor @@ -3359,7 +3359,7 @@ void LLSelectMgr::packPermissionsHead(void* user_data) /* void LLSelectMgr::sendSelect() { - llwarns << "Not implemented" << llendl; + llerrs << "Not implemented" << llendl; } */ @@ -4183,7 +4183,7 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name, break; default: - llwarns << "Bad send type " << send_type << " passed to SendListToRegions()" << llendl; + llerrs << "Bad send type " << send_type << " passed to SendListToRegions()" << llendl; } // bail if nothing selected @@ -4590,6 +4590,11 @@ extern LLGLdouble gGLModelView[16]; void LLSelectMgr::updateSilhouettes() { + if (!mRenderSilhouettes || !LLSelectMgr::sRenderSelectionHighlights) + { + return; + } + S32 num_sils_genned = 0; LLVector3d cameraPos = gAgent.getCameraPositionGlobal(); @@ -5803,7 +5808,8 @@ BOOL LLSelectMgr::canSelectObject(LLViewerObject* object) } if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !object->permYouOwner()) || - (gSavedSettings.getBOOL("SelectMovableOnly") && !object->permMove())) + (gSavedSettings.getBOOL("SelectMovableOnly") && !object->permMove()) || + (gSavedSettings.getBOOL("SelectCopyableOnly") && !object->permCopy())) { // only select my own objects return FALSE; diff --git a/linden/indra/newview/llselectmgr.h b/linden/indra/newview/llselectmgr.h index 0c57f7b..c19d33d 100644 --- a/linden/indra/newview/llselectmgr.h +++ b/linden/indra/newview/llselectmgr.h @@ -503,7 +503,7 @@ public: void selectionSetTexGen( U8 texgen ); void selectionSetShiny( U8 shiny ); void selectionSetFullbright( U8 fullbright ); -// void selectionSetMediaTypeAndURL( U8 media_type, const std::string& media_url ); + void selectionSetMediaTypeAndURL( U8 media_type, const std::string& media_url ); void selectionSetClickAction(U8 action); void selectionSetIncludeInSearch(bool include_in_search); void selectionSetGlow(const F32 glow); diff --git a/linden/indra/newview/llsky.cpp b/linden/indra/newview/llsky.cpp index b779aa0..ac7e865 100644 --- a/linden/indra/newview/llsky.cpp +++ b/linden/indra/newview/llsky.cpp @@ -422,20 +422,6 @@ void LLSky::updateFog(const F32 distance) void LLSky::updateCull() { - /*if (mVOSkyp.notNull() && mVOSkyp->mDrawable.notNull()) - { - gPipeline.markVisible(mVOSkyp->mDrawable); - } - else - { - llinfos << "No sky drawable!" << llendl; - }*/ - - /*if (mVOGroundp.notNull() && mVOGroundp->mDrawable.notNull()) - { - gPipeline.markVisible(mVOGroundp->mDrawable); - }*/ - // *TODO: do culling for wl sky properly -Brad } diff --git a/linden/indra/newview/llspatialpartition.cpp b/linden/indra/newview/llspatialpartition.cpp index 34ed292..c1d5ff3 100644 --- a/linden/indra/newview/llspatialpartition.cpp +++ b/linden/indra/newview/llspatialpartition.cpp @@ -48,7 +48,6 @@ #include "llrender.h" #include "lloctree.h" #include "llvoavatar.h" -#include "lltextureatlas.h" const F32 SG_OCCLUSION_FUDGE = 0.25f; #define SG_DISCARD_TOLERANCE 0.01f @@ -96,7 +95,7 @@ void sg_assert(BOOL expr) #if LL_OCTREE_PARANOIA_CHECK if (!expr) { - llwarns << "Octree invalid!" << llendl; + llerrs << "Octree invalid!" << llendl; } #endif } @@ -282,10 +281,10 @@ S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3 LLSpatialGroup::~LLSpatialGroup() { - /*if (sNoDelete) + if (sNoDelete) { - llwarns << "Illegal deletion of LLSpatialGroup!" << llendl; - }*/ + llerrs << "Illegal deletion of LLSpatialGroup!" << llendl; + } if (isState(DEAD)) { @@ -303,129 +302,6 @@ LLSpatialGroup::~LLSpatialGroup() LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); clearDrawMap(); - clearAtlasList() ; -} - -BOOL LLSpatialGroup::hasAtlas(LLTextureAtlas* atlasp) -{ - S8 type = atlasp->getComponents() - 1 ; - for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter) - { - if(atlasp == *iter) - { - return TRUE ; - } - } - return FALSE ; -} - -void LLSpatialGroup::addAtlas(LLTextureAtlas* atlasp, S8 recursive_level) -{ - if(!hasAtlas(atlasp)) - { - mAtlasList[atlasp->getComponents() - 1].push_back(atlasp) ; - atlasp->addSpatialGroup(this) ; - } - - --recursive_level; - if(recursive_level)//levels propagating up. - { - LLSpatialGroup* parent = getParent() ; - if(parent) - { - parent->addAtlas(atlasp, recursive_level) ; - } - } -} - -void LLSpatialGroup::removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group, S8 recursive_level) -{ - mAtlasList[atlasp->getComponents() - 1].remove(atlasp) ; - if(remove_group) - { - atlasp->removeSpatialGroup(this) ; - } - - --recursive_level; - if(recursive_level)//levels propagating up. - { - LLSpatialGroup* parent = getParent() ; - if(parent) - { - parent->removeAtlas(atlasp, recursive_level) ; - } - } -} - -void LLSpatialGroup::clearAtlasList() -{ - std::list<LLTextureAtlas*>::iterator iter ; - for(S8 i = 0 ; i < 4 ; i++) - { - if(mAtlasList[i].size() > 0) - { - for(iter = mAtlasList[i].begin(); iter != mAtlasList[i].end() ; ++iter) - { - ((LLTextureAtlas*)*iter)->removeSpatialGroup(this) ; - } - mAtlasList[i].clear() ; - } - } -} - -LLTextureAtlas* LLSpatialGroup::getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level) -{ - S8 type = ncomponents - 1 ; - if(mAtlasList[type].size() > 0) - { - for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter) - { - if(!((LLTextureAtlas*)*iter)->isFull(to_be_reserved)) - { - return *iter ; - } - } - } - - --recursive_level; - if(recursive_level) - { - LLSpatialGroup* parent = getParent() ; - if(parent) - { - return parent->getAtlas(ncomponents, to_be_reserved, recursive_level) ; - } - } - return NULL ; -} - -void LLSpatialGroup::setCurUpdatingSlot(LLTextureAtlasSlot* slotp) -{ - mCurUpdatingSlotp = slotp; - - //if(!hasAtlas(mCurUpdatingSlotp->getAtlas())) - //{ - // addAtlas(mCurUpdatingSlotp->getAtlas()) ; - //} -} - -LLTextureAtlasSlot* LLSpatialGroup::getCurUpdatingSlot(LLViewerImage* imagep, S8 recursive_level) -{ - if(gFrameCount && mCurUpdatingTime == gFrameCount && mCurUpdatingTexture == imagep) - { - return mCurUpdatingSlotp ; - } - - //--recursive_level ; - //if(recursive_level) - //{ - // LLSpatialGroup* parent = getParent() ; - // if(parent) - // { - // return parent->getCurUpdatingSlot(imagep, recursive_level) ; - // } - //} - return NULL ; } void LLSpatialGroup::clearDrawMap() @@ -472,7 +348,7 @@ void LLSpatialGroup::validate() LLSpatialPartition* part = drawable->asPartition(); if (!part) { - llwarns << "Drawable reports it is a spatial bridge but not a partition." << llendl; + llerrs << "Drawable reports it is a spatial bridge but not a partition." << llendl; } LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); group->validate(); @@ -535,7 +411,7 @@ public: if (mInheritedMask && !group->isState(mInheritedMask)) { - llwarns << "Spatial group failed inherited mask test." << llendl; + llerrs << "Spatial group failed inherited mask test." << llendl; } if (group->isState(LLSpatialGroup::DIRTY)) @@ -551,7 +427,7 @@ public: { if (!parent->isState(state)) { - llwarns << "Spatial group failed parent state check." << llendl; + llerrs << "Spatial group failed parent state check." << llendl; } parent = parent->getParent(); } @@ -572,39 +448,39 @@ void validate_draw_info(LLDrawInfo& params) #if LL_OCTREE_PARANOIA_CHECK if (params.mVertexBuffer.isNull()) { - llwarns << "Draw batch has no vertex buffer." << llendl; + llerrs << "Draw batch has no vertex buffer." << llendl; } //bad range if (params.mStart >= params.mEnd) { - llwarns << "Draw batch has invalid range." << llendl; + llerrs << "Draw batch has invalid range." << llendl; } if (params.mEnd >= (U32) params.mVertexBuffer->getNumVerts()) { - llwarns << "Draw batch has buffer overrun error." << llendl; + llerrs << "Draw batch has buffer overrun error." << llendl; } if (params.mOffset + params.mCount > (U32) params.mVertexBuffer->getNumIndices()) { - llwarns << "Draw batch has index buffer ovverrun error." << llendl; + llerrs << "Draw batch has index buffer ovverrun error." << llendl; } //bad indices - U16* indicesp = (U16*) params.mVertexBuffer->getIndicesPointer(); // KL 16 indices for SD not 32 + U32* indicesp = (U32*) params.mVertexBuffer->getIndicesPointer(); if (indicesp) { for (U32 i = params.mOffset; i < params.mOffset+params.mCount; i++) { - if (indicesp[i] < (U16)params.mStart) //KL + if (indicesp[i] < params.mStart) { - llwarns << "Draw batch has vertex buffer index out of range error (index too low)." << llendl; + llerrs << "Draw batch has vertex buffer index out of range error (index too low)." << llendl; } - if (indicesp[i] > (U16)params.mEnd) // KL + if (indicesp[i] > params.mEnd) { - llwarns << "Draw batch has vertex buffer index out of range error (index too high)." << llendl; + llerrs << "Draw batch has vertex buffer index out of range error (index too high)." << llendl; } } } @@ -664,7 +540,6 @@ BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_oc drawablep->setSpatialGroup(this); validate_drawable(drawablep); setState(OBJECT_DIRTY | GEOM_DIRTY | DISCARD_QUERY); - gPipeline.markRebuild(this, TRUE); if (drawablep->isSpatialBridge()) { mBridgeList.push_back((LLSpatialBridge*) drawablep); @@ -697,23 +572,22 @@ void LLSpatialGroup::rebuildMesh() void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) { - /*if (!gPipeline.hasRenderType(mDrawableType)) + if (!gPipeline.hasRenderType(mDrawableType)) { return; - }*/ + } + + if (!LLPipeline::sSkipUpdate && group->changeLOD()) + { + group->mLastUpdateDistance = group->mDistance; + group->mLastUpdateViewAngle = group->mViewAngle; + } if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) { - /*if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && mRenderByGroup) - { - llwarns << "WTF?" << llendl; - }*/ return; } - group->mLastUpdateDistance = group->mDistance; - group->mLastUpdateViewAngle = group->mViewAngle; - LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO); group->clearDrawMap(); @@ -751,7 +625,6 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) group->clearState(LLSpatialGroup::GEOM_DIRTY); } - void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group) { @@ -790,11 +663,8 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO drawablep = *i; minMax = drawablep->getSpatialExtents(); - update_min_max(newMin, newMax, minMax[0]); - update_min_max(newMin, newMax, minMax[1]); - //bin up the object - /*for (U32 i = 0; i < 3; i++) + for (U32 i = 0; i < 3; i++) { if (minMax[0].mV[i] < newMin.mV[i]) { @@ -804,7 +674,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO { newMax.mV[i] = minMax[1].mV[i]; } - }*/ + } } mObjectBounds[0] = (newMin + newMax) * 0.5f; @@ -868,10 +738,6 @@ LLSpatialGroup* LLSpatialGroup::getParent() return NULL; } - if(!mOctreeNode) - { - return NULL; - } OctreeNode* parent = mOctreeNode->getOctParent(); if (parent) @@ -897,8 +763,6 @@ BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) { drawablep->setSpatialGroup(NULL); setState(GEOM_DIRTY); - gPipeline.markRebuild(this, TRUE); - if (drawablep->isSpatialBridge()) { for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i) @@ -935,7 +799,6 @@ void LLSpatialGroup::shift(const LLVector3 &offset) //if (!mSpatialPartition->mRenderByGroup) { setState(GEOM_DIRTY); - gPipeline.markRebuild(this, TRUE); } if (mOcclusionVerts) @@ -1085,11 +948,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mLastUpdateDistance(-1.f), mLastUpdateTime(gFrameTimeSeconds), mViewAngle(0.f), - mLastUpdateViewAngle(-1.f), - mAtlasList(4), - mCurUpdatingTime(0), - mCurUpdatingSlotp(NULL), - mCurUpdatingTexture (NULL) + mLastUpdateViewAngle(-1.f) { sNodeCount++; LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -1097,7 +956,6 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : sg_assert(mOctreeNode->getListenerCount() == 0); mOctreeNode->addListener(this); setState(SG_INITIAL_STATE_MASK); - gPipeline.markRebuild(this, TRUE); mBounds[0] = LLVector3(node->getCenter()); mBounds[1] = LLVector3(node->getSize()); @@ -1117,7 +975,7 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) #if !LL_RELEASE_FOR_DOWNLOAD if (isState(LLSpatialGroup::OBJECT_DIRTY)) { - llwarns << "Spatial group dirty on distance update." << llendl; + llerrs << "Spatial group dirty on distance update." << llendl; } #endif if (!getData().empty() && !LLSpatialPartition::sFreezeState) @@ -1156,7 +1014,6 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order, //not setting this node to dirty would be a very good thing group->setState(LLSpatialGroup::ALPHA_DIRTY); - gPipeline.markRebuild(group, FALSE); } } } @@ -1193,18 +1050,6 @@ F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera) return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera); } -F32 LLSpatialGroup::getUpdateUrgency() const -{ - if (!isVisible()) - { - return 0.f; - } - else - { - return (gFrameTimeSeconds - mLastUpdateTime+4.f)/mDistance; - } -} - BOOL LLSpatialGroup::needsUpdate() { return (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE; @@ -1312,8 +1157,6 @@ void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNo void LLSpatialGroup::destroyGL() { setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); - gPipeline.markRebuild(this, TRUE); - mLastUpdateTime = gFrameTimeSeconds; mVertexBuffer = NULL; mBufferMap.clear(); @@ -1517,8 +1360,7 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) //============================================== -LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage) -: mRenderByGroup(render_by_group) +LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); mOcclusionEnabled = TRUE; @@ -1530,7 +1372,7 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage = buffer_usage; mDepthMask = FALSE; mSlopRatio = 0.25f; - //mRenderByGroup = TRUE; + mRenderByGroup = TRUE; mInfiniteFarClip = FALSE; LLGLNamePool::registerPool(&sQueryPool); @@ -1826,76 +1668,13 @@ public: return false; } - virtual void traverse(const LLSpatialGroup::TreeNode* n) - { - LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - - if (earlyFail(group)) - { - return; - } - - if (mRes == 2) - { - //fully in, don't traverse further (won't effect extents - } - else if (mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) - { //don't need to do frustum check - LLSpatialGroup::OctreeTraveler::traverse(n); - } - else - { - mRes = frustumCheck(group); - - if (mRes) - { //at least partially in, run on down - LLSpatialGroup::OctreeTraveler::traverse(n); - } - - mRes = 0; - } - } - virtual void processGroup(LLSpatialGroup* group) { - if (group->isState(LLSpatialGroup::DIRTY) || group->getData().empty()) - { - llwarns << "WTF?" << llendl; - } - - if (mRes < 2) - { - - if (mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]) == 2) - { - mEmpty = FALSE; - update_min_max(mMin, mMax, group->mObjectExtents[0]); - update_min_max(mMin, mMax, group->mObjectExtents[1]); - } - else - { - if (group->mObjectBounds[1].magVecSquared() < 256.f * 256.f) - { //megaprims and water edge patches be damned! - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) - { - LLDrawable* drawable = i->get(); - const LLVector3* ext = drawable->getSpatialExtents(); - - if (mCamera->AABBInFrustum((ext[1]+ext[0])*0.5f, (ext[1]-ext[0])*0.5f)) - { - mEmpty = FALSE; - update_min_max(mMin, mMax, ext[0]); - update_min_max(mMin, mMax, ext[1]); - } - } - } - } - } - else - { + if (group->mObjectBounds[1].magVecSquared() < 256.f * 256.f) + { //megaprims and water edge patches be damned! mEmpty = FALSE; - update_min_max(mMin, mMax, group->mExtents[0]); - update_min_max(mMin, mMax, group->mExtents[1]); + update_min_max(mMin, mMax, group->mObjectExtents[0]); + update_min_max(mMin, mMax, group->mObjectExtents[1]); } } @@ -2674,39 +2453,6 @@ void renderBatchSize(LLDrawInfo* params) pushVerts(params, LLVertexBuffer::MAP_VERTEX); } -void renderShadowFrusta(LLDrawInfo* params) -{ - LLGLEnable blend(GL_BLEND); - gGL.setSceneBlendType(LLRender::BT_ADD); - - LLVector3 center = (params->mExtents[1]+params->mExtents[0])*0.5f; - LLVector3 size = (params->mExtents[1]-params->mExtents[0])*0.5f; - - if (gPipeline.mShadowCamera[4].AABBInFrustum(center, size)) - { - glColor3f(1,0,0); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); - } - if (gPipeline.mShadowCamera[5].AABBInFrustum(center, size)) - { - glColor3f(0,1,0); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); - } - if (gPipeline.mShadowCamera[6].AABBInFrustum(center, size)) - { - glColor3f(0,0,1); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); - } - if (gPipeline.mShadowCamera[7].AABBInFrustum(center, size)) - { - glColor3f(1,0,1); - pushVerts(params, LLVertexBuffer::MAP_VERTEX); - } - - gGL.setSceneBlendType(LLRender::BT_ALPHA); -} - - void renderLights(LLDrawable* drawablep) { if (!drawablep->isLight()) @@ -2842,9 +2588,6 @@ public: //draw tight fit bounding boxes for spatial group if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE)) { - group->rebuildGeom(); - group->rebuildMesh(); - renderOctree(group); stop_glerror(); } @@ -2852,9 +2595,6 @@ public: //render visibility wireframe if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) { - group->rebuildGeom(); - group->rebuildMesh(); - gGL.flush(); glPushMatrix(); gGLLastMatrix = NULL; @@ -2880,19 +2620,6 @@ public: LLVector3 nodeCenter = group->mBounds[0]; LLVector3 octCenter = LLVector3(group->mOctreeNode->getCenter()); - group->rebuildGeom(); - group->rebuildMesh(); - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) - { - if (!group->getData().empty()) - { - gGL.color3f(0,0,1); - drawBoxOutline(group->mObjectBounds[0], - group->mObjectBounds[1]); - } - } - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) { LLDrawable* drawable = *i; @@ -2902,16 +2629,6 @@ public: renderBoundingBox(drawable); } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BUILD_QUEUE)) - { - if (drawable->isState(LLDrawable::IN_REBUILD_Q2)) - { - gGL.color4f(0.6f, 0.6f, 0.1f, 1.f); - const LLVector3* ext = drawable->getSpatialExtents(); - drawBoxOutline((ext[0]+ext[1])*0.5f, (ext[1]-ext[0])*0.5f); - } - } - if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) { renderTexturePriority(drawable); @@ -2932,9 +2649,9 @@ public: renderRaycast(drawable); } - // LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get()); + LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get()); - /* if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_VOLUME)) + if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_VOLUME)) { renderAvatarCollisionVolumes(avatar); } @@ -2942,7 +2659,7 @@ public: if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AGENT_TARGET)) { renderAgentTarget(avatar); - } */ + } } @@ -2960,10 +2677,6 @@ public: { renderBatchSize(draw_info); } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) - { - renderShadowFrusta(draw_info); - } } } } @@ -3014,7 +2727,7 @@ void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera) pusher.traverse(mOctree); } -void LLSpatialPartition::renderDebug() // KL SD version +void LLSpatialPartition::renderDebug() { if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | LLPipeline::RENDER_DEBUG_OCCLUSION | @@ -3025,8 +2738,8 @@ void LLSpatialPartition::renderDebug() // KL SD version LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY | LLPipeline::RENDER_DEBUG_TEXTURE_ANIM | LLPipeline::RENDER_DEBUG_RAYCAST | - LLPipeline::RENDER_DEBUG_BUILD_QUEUE | - LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + LLPipeline::RENDER_DEBUG_AVATAR_VOLUME | + LLPipeline::RENDER_DEBUG_AGENT_TARGET)) { return; } @@ -3061,12 +2774,6 @@ void LLSpatialPartition::renderDebug() // KL SD version render_debug.traverse(mOctree); } -void LLSpatialGroup::drawObjectBox(LLColor4 col) -{ - gGL.color4fv(col.mV); - drawBox(mObjectBounds[0], mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); -} - BOOL LLSpatialPartition::isVisible(const LLVector3& v) { @@ -3211,12 +2918,11 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector3& start, con } LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, - LLImageGL* gl_texture, LLViewerImage* texture, LLVertexBuffer* buffer, + LLViewerImage* texture, LLVertexBuffer* buffer, BOOL fullbright, U8 bump, BOOL particle, F32 part_size) : mVertexBuffer(buffer), - mTexture(gl_texture), - mViewerTexture(texture), + mTexture(texture), mTextureMatrix(NULL), mModelMatrix(NULL), mStart(start), @@ -3236,22 +2942,22 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, if (mStart >= mVertexBuffer->getRequestedVerts() || mEnd >= mVertexBuffer->getRequestedVerts()) { - llwarns << "Invalid draw info vertex range." << llendl; + llerrs << "Invalid draw info vertex range." << llendl; } if (mOffset >= (U32) mVertexBuffer->getRequestedIndices() || mOffset + mCount > (U32) mVertexBuffer->getRequestedIndices()) { - llwarns << "Invalid draw info index range." << llendl; + llerrs << "Invalid draw info index range." << llendl; } } LLDrawInfo::~LLDrawInfo() { - /*if (LLSpatialGroup::sNoDelete) + if (LLSpatialGroup::sNoDelete) { - llwarns << "LLDrawInfo deleted illegally!" << llendl; - }*/ + llerrs << "LLDrawInfo deleted illegally!" << llendl; + } if (mFace) { @@ -3456,7 +3162,7 @@ void LLCullResult::assertDrawMapsEmpty() { if (mRenderMapSize[i] != 0) { - llwarns << "Stale LLDrawInfo's in LLCullResult!" << llendl; + llerrs << "Stale LLDrawInfo's in LLCullResult!" << llendl; } } } diff --git a/linden/indra/newview/llspatialpartition.h b/linden/indra/newview/llspatialpartition.h index deb8b0e..be0163b 100644 --- a/linden/indra/newview/llspatialpartition.h +++ b/linden/indra/newview/llspatialpartition.h @@ -52,8 +52,6 @@ class LLSpatialPartition; class LLSpatialBridge; class LLSpatialGroup; -class LLTextureAtlas; -class LLTextureAtlasSlot; S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad); S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &radius_squared); @@ -68,13 +66,12 @@ protected: public: LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, - LLImageGL* gl_image, LLViewerImage* image, LLVertexBuffer* buffer, + LLViewerImage* image, LLVertexBuffer* buffer, BOOL fullbright = FALSE, U8 bump = 0, BOOL particle = FALSE, F32 part_size = 0); LLPointer<LLVertexBuffer> mVertexBuffer; - LLPointer<LLImageGL> mTexture; - LLPointer<LLViewerImage> mViewerTexture; + LLPointer<LLViewerImage> mTexture; LLColor4U mGlowColor; S32 mDebugColor; const LLMatrix4* mTextureMatrix; @@ -162,13 +159,11 @@ public: typedef std::vector<LLPointer<LLSpatialGroup> > sg_vector_t; typedef std::set<LLPointer<LLSpatialGroup> > sg_set_t; - typedef std::list<LLPointer<LLSpatialGroup> > sg_list_t; typedef std::vector<LLPointer<LLSpatialBridge> > bridge_list_t; typedef std::vector<LLPointer<LLDrawInfo> > drawmap_elem_t; typedef std::map<U32, drawmap_elem_t > draw_map_t; typedef std::vector<LLPointer<LLVertexBuffer> > buffer_list_t; - typedef std::map<LLPointer<LLImageGL>, buffer_list_t> buffer_texture_map_t; // KL render-pipeline -// typedef std::map<LLPointer<LLViewerImage>, buffer_list_t> buffer_texture_map_t; // KL standard + typedef std::map<LLPointer<LLViewerImage>, buffer_list_t> buffer_texture_map_t; typedef std::map<U32, buffer_texture_map_t> buffer_map_t; typedef LLOctreeListener<LLDrawable> BaseType; @@ -188,14 +183,6 @@ public: } }; - struct CompareUpdateUrgency - { - bool operator()(const LLPointer<LLSpatialGroup> lhs, const LLPointer<LLSpatialGroup> rhs) - { - return lhs->getUpdateUrgency() > rhs->getUpdateUrgency(); - } - }; - struct CompareDepthGreater { bool operator()(const LLSpatialGroup* const& lhs, const LLSpatialGroup* const& rhs) @@ -222,10 +209,6 @@ public: IMAGE_DIRTY = 0x00004000, OCCLUSION_DIRTY = 0x00008000, MESH_DIRTY = 0x00010000, - NEW_DRAWINFO = 0x00020000, - IN_BUILD_Q1 = 0x00040000, - IN_BUILD_Q2 = 0x00080000, - } eSpatialState; typedef enum @@ -269,7 +252,6 @@ public: void updateDistance(LLCamera& camera); BOOL needsUpdate(); - F32 getUpdateUrgency() const; BOOL changeLOD(); void rebuildGeom(); void rebuildMesh(); @@ -279,8 +261,6 @@ public: element_list& getData() { return mOctreeNode->getData(); } U32 getElementCount() const { return mOctreeNode->getElementCount(); } - void drawObjectBox(LLColor4 col); - //LISTENER FUNCTIONS virtual void handleInsertion(const TreeNode* node, LLDrawable* face); virtual void handleRemoval(const TreeNode* node, LLDrawable* face); @@ -289,36 +269,6 @@ public: virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child); virtual void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child); -//------------------- -//for atlas use -//------------------- - //atlas - void setCurUpdatingTime(U32 t) {mCurUpdatingTime = t ;} - U32 getCurUpdatingTime() const { return mCurUpdatingTime ;} - - void setCurUpdatingSlot(LLTextureAtlasSlot* slotp) ; - LLTextureAtlasSlot* getCurUpdatingSlot(LLViewerImage* imagep, S8 recursive_level = 3) ; - - void setCurUpdatingTexture(LLViewerImage* tex){ mCurUpdatingTexture = tex ;} - LLViewerImage* getCurUpdatingTexture() const { return mCurUpdatingTexture ;} - - BOOL hasAtlas(LLTextureAtlas* atlasp) ; - LLTextureAtlas* getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level = 3) ; - void addAtlas(LLTextureAtlas* atlasp, S8 recursive_level = 3) ; - void removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group = TRUE, S8 recursive_level = 3) ; - void clearAtlasList() ; -private: - U32 mCurUpdatingTime ; - //do not make the below two to use LLPointer - //because mCurUpdatingTime invalidates them automatically. - LLTextureAtlasSlot* mCurUpdatingSlotp ; - LLViewerImage* mCurUpdatingTexture ; - - std::vector< std::list<LLTextureAtlas*> > mAtlasList ; -//------------------- -//end for atlas use -//------------------- - protected: virtual ~LLSpatialGroup(); @@ -377,7 +327,7 @@ class LLSpatialPartition: public LLGeometryManager public: static BOOL sFreezeState; //if true, no spatialgroup state updates will be made - LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage); + LLSpatialPartition(U32 data_mask, U32 mBufferUsage = GL_STATIC_DRAW_ARB); virtual ~LLSpatialPartition(); LLSpatialGroup *put(LLDrawable *drawablep, BOOL was_visible = FALSE); @@ -423,7 +373,7 @@ public: BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed BOOL mInfiniteFarClip; // if TRUE, frustum culling ignores far clip plane U32 mBufferUsage; - const BOOL mRenderByGroup; + BOOL mRenderByGroup; U32 mLODSeed; U32 mLODPeriod; //number of frames between LOD updates for a given spatial group (staggered by mLODSeed) U32 mVertexDataMask; @@ -442,7 +392,7 @@ protected: public: typedef std::vector<LLPointer<LLSpatialBridge> > bridge_vector_t; - LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask); + LLSpatialBridge(LLDrawable* root, U32 data_mask); virtual BOOL isSpatialBridge() const { return TRUE; } diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index a03ce1d..bd22772 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp @@ -3735,7 +3735,7 @@ void init_start_screen(S32 location_id) } raw->expandToPowerOfTwo(); - gStartImageGL->createGLTexture(0, raw); + gStartImageGL->createGLTexture(0, raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); } diff --git a/linden/indra/newview/llsurface.cpp b/linden/indra/newview/llsurface.cpp index f6ef9c7..578b565 100644 --- a/linden/indra/newview/llsurface.cpp +++ b/linden/indra/newview/llsurface.cpp @@ -149,7 +149,7 @@ LLSurface::~LLSurface() } else { - llwarns << "Terrain pool not empty!" << llendl; + llerrs << "Terrain pool not empty!" << llendl; } } @@ -238,7 +238,6 @@ void LLSurface::createSTexture() if (!mSTexturep) { // Fill with dummy gray data. - // GL NOT ACTIVE HERE LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize, sTextureSize, 3); U8 *default_texture = raw->getData(); for (S32 i = 0; i < sTextureSize; i++) @@ -256,7 +255,6 @@ void LLSurface::createSTexture() gGL.getTexUnit(0)->bind(mSTexturep.get()); mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); gImageList.addImage(mSTexturep); - } } @@ -280,7 +278,7 @@ void LLSurface::createWaterTexture() mWaterTexturep = new LLViewerImage(raw, FALSE); mWaterTexturep->dontDiscard(); - gGL.getTexUnit(0)->bind(mWaterTexturep); + gGL.getTexUnit(0)->bind(mWaterTexturep.get()); mWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); gImageList.addImage(mWaterTexturep); } @@ -632,8 +630,6 @@ void LLSurface::updatePatchVisibilities(LLAgent &agent) BOOL LLSurface::idleUpdate(F32 max_update_time) { -//SG2: LLMemType mt_ius(LLMemType::MTYPE_IDLE_UPDATE_SURFACE); - if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TERRAIN)) { return FALSE; @@ -1138,12 +1134,12 @@ LLSurfacePatch *LLSurface::getPatch(const S32 x, const S32 y) const { if ((x < 0) || (x >= mPatchesPerEdge)) { - llwarns << "Asking for patch out of bounds" << llendl; + llerrs << "Asking for patch out of bounds" << llendl; return NULL; } if ((y < 0) || (y >= mPatchesPerEdge)) { - llwarns << "Asking for patch out of bounds" << llendl; + llerrs << "Asking for patch out of bounds" << llendl; return NULL; } @@ -1287,11 +1283,6 @@ BOOL LLSurface::generateWaterTexture(const F32 x, const F32 y, } } - if (!mWaterTexturep->getHasGLTexture()) - { - mWaterTexturep->createGLTexture(0, raw); - } - mWaterTexturep->setSubImage(raw, x_begin, y_begin, x_end - x_begin, y_end - y_begin); return TRUE; } diff --git a/linden/indra/newview/llsurfacepatch.cpp b/linden/indra/newview/llsurfacepatch.cpp index 04b732a..5fac5fd 100644 --- a/linden/indra/newview/llsurfacepatch.cpp +++ b/linden/indra/newview/llsurfacepatch.cpp @@ -712,7 +712,17 @@ BOOL LLSurfacePatch::updateTexture() if (mVObjp) { mVObjp->dirtyGeom(); - gPipeline.markGLRebuild(mVObjp); + } + updateCompositionStats(); + F32 tex_patch_size = meters_per_grid*grids_per_patch_edge; + if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY], + tex_patch_size, tex_patch_size)) + { + mSTexUpdate = FALSE; + + // Also generate the water texture + mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY], + tex_patch_size, tex_patch_size); return TRUE; } } @@ -725,28 +735,6 @@ BOOL LLSurfacePatch::updateTexture() } } -void LLSurfacePatch::updateGL() // KL SD -{ - F32 meters_per_grid = getSurface()->getMetersPerGrid(); - F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge(); - - LLViewerRegion *regionp = getSurface()->getRegion(); - LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal(); - - LLVLComposition* comp = regionp->getComposition(); - - updateCompositionStats(); - F32 tex_patch_size = meters_per_grid*grids_per_patch_edge; - if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY], - tex_patch_size, tex_patch_size)) - { - mSTexUpdate = FALSE; - - // Also generate the water texture - mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY], - tex_patch_size, tex_patch_size); - } -} // KL void LLSurfacePatch::dirtyZ() { diff --git a/linden/indra/newview/llsurfacepatch.h b/linden/indra/newview/llsurfacepatch.h index 1f9658d..7e84f7f 100644 --- a/linden/indra/newview/llsurfacepatch.h +++ b/linden/indra/newview/llsurfacepatch.h @@ -90,7 +90,6 @@ public: void updateCameraDistanceRegion( const LLVector3 &pos_region); void updateVisibility(); - void updateGL(); void dirtyZ(); // Dirty the z values of this patch void setHasReceivedData(); diff --git a/linden/indra/newview/lltexlayer.cpp b/linden/indra/newview/lltexlayer.cpp index fb5be84..5175cbb 100644 --- a/linden/indra/newview/lltexlayer.cpp +++ b/linden/indra/newview/lltexlayer.cpp @@ -813,19 +813,14 @@ void LLTexLayerSet::requestUpdate() if( mUpdatesEnabled ) { createComposite(); - if (mComposite) - { - mComposite->requestUpdate(); - } + mComposite->requestUpdate(); } } void LLTexLayerSet::requestUpload() { - if (mComposite) - { - mComposite->requestUpload(); - } + createComposite(); + mComposite->requestUpload(); } void LLTexLayerSet::cancelUpload() @@ -840,15 +835,6 @@ void LLTexLayerSet::createComposite() { if( !mComposite ) { - gPipeline.markGLRebuild(this); - } - //updateGL(); // KL -} - -void LLTexLayerSet::updateGL() -{ - if (!mComposite) - { S32 width = mInfo->mWidth; S32 height = mInfo->mHeight; // Composite other avatars at reduced resolution @@ -879,7 +865,7 @@ void LLTexLayerSet::setUpdatesEnabled( BOOL b ) void LLTexLayerSet::updateComposite() { createComposite(); - //mComposite->updateImmediate(); //KL exception here this needs fixing for S19 + mComposite->updateImmediate(); } LLTexLayerSetBuffer* LLTexLayerSet::getComposite() @@ -2118,7 +2104,7 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) // Create the GL texture, and then hang onto it for future use. if( mNeedsCreateTexture ) { - mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw, 0); + mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw, 0, TRUE, LLViewerImageBoostLevel::TEXLAYER_CACHE); mNeedsCreateTexture = FALSE; gGL.getTexUnit(0)->bind(mCachedProcessedImageGL); mCachedProcessedImageGL->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -2574,7 +2560,7 @@ LLImageGL* LLTexStaticImageList::getImageGL(const std::string& file_name, BOOL i image_gl->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); } - image_gl->createGLTexture(0, image_raw, 0); + image_gl->createGLTexture(0, image_raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); gGL.getTexUnit(0)->bind(image_gl); image_gl->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/linden/indra/newview/lltexlayer.h b/linden/indra/newview/lltexlayer.h index b841fa3..020ba86 100644 --- a/linden/indra/newview/lltexlayer.h +++ b/linden/indra/newview/lltexlayer.h @@ -249,7 +249,7 @@ private: // LLTexLayerSet // An ordered set of texture layers that get composited into a single texture. //----------------------------------------------------------------------------- -class LLTexLayerSet : public LLGLUpdate +class LLTexLayerSet { friend class LLTexLayerSetBuffer; public: @@ -284,7 +284,7 @@ public: LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; } void setBakedTexIndex(LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } BOOL isVisible() const { return mIsVisible; } - /*virtual*/ void updateGL(); + public: static BOOL sHasCaches; diff --git a/linden/indra/newview/lltextureatlasmanager.cpp b/linden/indra/newview/lltextureatlasmanager.cpp deleted file mode 100644 index df6a39d..0000000 --- a/linden/indra/newview/lltextureatlasmanager.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/** - * @file lltextureatlasmanager.cpp - * @brief LLTextureAtlasManager class implementation. - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ -#include "llviewerprecompiledheaders.h" -#include "linden_common.h" -#include "llerror.h" -#include "llmath.h" -#include "lltextureatlas.h" -#include "lltextureatlasmanager.h" -#include "llspatialpartition.h" - -const S8 MAX_NUM_EMPTY_ATLAS = 2 ; -const F32 MIN_ATLAS_FULLNESS = 0.6f ; - -//********************************************************************************************* -//implementation of class LLTextureAtlasInfo -//********************************************************************************************* -LLTextureAtlasSlot::LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) : - mAtlasp(atlasp), - mGroupp(groupp), - mCol(col), - mRow(row), - mReservedSlotWidth(slot_width), - mValid(FALSE), - mUpdatedTime(0), - mTexCoordOffset(xoffset, yoffset), - mTexCoordScale(1.f, 1.f) -{ - llassert_always(mAtlasp || mGroupp || mReservedSlotWidth) ; -} - -LLTextureAtlasSlot::~LLTextureAtlasSlot() -{ - if(mAtlasp) - { - mAtlasp->releaseSlot(mCol, mRow, mReservedSlotWidth) ; - if(mAtlasp->isEmpty()) - { - LLTextureAtlasManager::getInstance()->releaseAtlas(mAtlasp) ; - } - mAtlasp = NULL ; - } -} - -//void LLTextureAtlasSlot::setAtlas(LLTextureAtlas* atlasp) -//{ -// mAtlasp = atlasp ; -//} -//void LLTextureAtlasSlot::setSlotPos(S16 col, S16 row) -//{ -// mCol = col ; -// mRow = row ; -//} -//void LLTextureAtlasSlot::setSlotWidth(S8 width) -//{ -// //slot is a square with each edge length a power-of-two number -// mReservedSlotWidth = width ; -//} -//void LLTextureAtlasSlot::setTexCoordOffset(F32 xoffset, F32 yoffset) -//{ -// mTexCoordOffset.mV[0] = xoffset ; -// mTexCoordOffset.mV[1] = yoffset ; -//} - -void LLTextureAtlasSlot::setSpatialGroup(LLSpatialGroup* groupp) -{ - mGroupp = groupp ; -} -void LLTextureAtlasSlot::setTexCoordScale(F32 xscale, F32 yscale) -{ - mTexCoordScale.mV[0] = xscale ; - mTexCoordScale.mV[1] = yscale ; -} -//********************************************************************************************* -//END of implementation of class LLTextureAtlasInfo -//********************************************************************************************* - -//********************************************************************************************* -//implementation of class LLTextureAtlasManager -//********************************************************************************************* -LLTextureAtlasManager::LLTextureAtlasManager() : - mAtlasMap(4), - mEmptyAtlasMap(4) -{ -} - -LLTextureAtlasManager::~LLTextureAtlasManager() -{ - for(S32 i = 0 ; i < 4 ; i++) - { - for(ll_texture_atlas_list_t::iterator j = mAtlasMap[i].begin() ; j != mAtlasMap[i].end() ; ++j) - { - *j = NULL ; - } - for(ll_texture_atlas_list_t::iterator j = mEmptyAtlasMap[i].begin() ; j != mEmptyAtlasMap[i].end() ; ++j) - { - *j = NULL ; - } - - mAtlasMap[i].clear() ; - mEmptyAtlasMap[i].clear() ; - } - mAtlasMap.clear() ; - mEmptyAtlasMap.clear() ; -} - -//return TRUE if qualified -BOOL LLTextureAtlasManager::canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target) -{ - if(ncomponents < 1 || ncomponents > 4) - { - return FALSE ; - } - //only support GL_TEXTURE_2D - if(GL_TEXTURE_2D != target) - { - return FALSE ; - } - //real image size overflows - if(w < 8 || w > LLTextureAtlas::sMaxSubTextureSize || h < 8 || h > LLTextureAtlas::sMaxSubTextureSize) - { - return FALSE ; - } - - //if non-power-of-two number - if((w & (w - 1)) || (h & (h - 1))) - { - return FALSE ; - } - - return TRUE ; -} - -void LLTextureAtlasManager::releaseAtlas(LLTextureAtlas* atlasp) -{ - LLSpatialGroup* groupp = atlasp->getLastSpatialGroup() ; - while(groupp) - { - groupp->removeAtlas(atlasp, FALSE) ; - atlasp->removeLastSpatialGroup() ; - - groupp = atlasp->getLastSpatialGroup() ; - } - - S8 type = atlasp->getComponents() - 1 ; - //insert to the empty list - if(mEmptyAtlasMap[type].size() < MAX_NUM_EMPTY_ATLAS) - { - mEmptyAtlasMap[type].push_back(atlasp) ; - } - - //delete the atlasp - mAtlasMap[type].remove(atlasp) ; -} - -// -//this function reserves an appropriate slot from atlas pool for an image. -//return non-NULL if succeeds. -//Note: -//1, this function does not check if the image this slot assigned for qualifies for atlas or not, -// call LLTextureAtlasManager::canAddToAtlas(...) to do the check before calling this function. -//2, this function also dose not check if the image is already in atlas. It always assigns a new slot anyway. -//3, this function tries to group sub-textures from same spatial group into ONE atlas to improve render batching. -// -LLPointer<LLTextureAtlasSlot> LLTextureAtlasManager::reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents, - LLSpatialGroup* groupp, LLViewerImage* imagep) -{ - if(!groupp) - { - //do not insert to atlas if does not have a group. - return NULL ; - } - - //bits_len must <= 8 and is a power of two number, i.e.: must be one of these numbers: 1, 2, 4, 8. - if(sub_texture_size > LLTextureAtlas::sMaxSubTextureSize) - { - sub_texture_size = LLTextureAtlas::sMaxSubTextureSize ; - } - S8 bits_len = sub_texture_size / LLTextureAtlas::sSlotSize ; - if(bits_len < 1) - { - bits_len = 1 ; - } - - S16 col = -1, row = -1; - S8 total_bits = bits_len * bits_len ; - - //insert to the atlas reserved by the same spatial group - LLPointer<LLTextureAtlas> atlasp = groupp->getAtlas(ncomponents, total_bits) ; - if(atlasp.notNull()) - { - if(!atlasp->getNextAvailableSlot(bits_len, col, row)) - { - //failed - atlasp = NULL ; - } - } - - //search an atlas to fit for 'size' - if(!atlasp) - { - S8 atlas_index = ncomponents - 1 ; - ll_texture_atlas_list_t::iterator iter = mAtlasMap[atlas_index].begin() ; - for(; iter != mAtlasMap[atlas_index].end(); ++iter) - { - LLTextureAtlas* cur = (LLTextureAtlas*)*iter ; - if(cur->getFullness() < MIN_ATLAS_FULLNESS)//this atlas is empty enough for this group to insert more sub-textures later if necessary. - { - if(cur->getNextAvailableSlot(bits_len, col, row)) - { - atlasp = cur ; - groupp->addAtlas(atlasp) ; - break ; - } - } - } - } - - //create a new atlas if necessary - if(!atlasp) - { - if(mEmptyAtlasMap[ncomponents - 1].size() > 0) - { - //there is an empty one - atlasp = mEmptyAtlasMap[ncomponents - 1].back() ; - mEmptyAtlasMap[ncomponents - 1].pop_back() ; - } - else - { - atlasp = new LLTextureAtlas(ncomponents, 16) ; - } - mAtlasMap[ncomponents - 1].push_back(atlasp) ; - atlasp->getNextAvailableSlot(bits_len, col, row) ; - groupp->addAtlas(atlasp) ; - } - - F32 xoffset, yoffset ; - atlasp->getTexCoordOffset(col, row, xoffset, yoffset) ; - LLPointer<LLTextureAtlasSlot> slot_infop = new LLTextureAtlasSlot(atlasp, groupp, col, row, xoffset, yoffset, bits_len) ; - - return slot_infop ; -} - -//********************************************************************************************* -//END of implementation of class LLTextureAtlasManager -//********************************************************************************************* diff --git a/linden/indra/newview/lltextureatlasmanager.h b/linden/indra/newview/lltextureatlasmanager.h deleted file mode 100644 index 70689bf..0000000 --- a/linden/indra/newview/lltextureatlasmanager.h +++ /dev/null @@ -1,112 +0,0 @@ -/** - * @file lltextureatlasmanager.h - * @brief LLTextureAtlasManager base class. - * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - - -#ifndef LL_TEXTUREATLASMANAGER_H -#define LL_TEXTUREATLASMANAGER_H - -#include "llmemory.h" - -class LLSpatialGroup ; -class LLViewerImage ; - -//just use it as a structure. -class LLTextureAtlasSlot : public LLRefCount -{ -public: - LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) ; - -protected: - virtual ~LLTextureAtlasSlot(); - -public: - - // - //do not allow to change those values - // - //void setAtlas(LLTextureAtlas* atlasp) ; - //void setSlotPos(S16 col, S16 row) ; - //void setSlotWidth(S8 width) ; - //void setTexCoordOffset(F32 xoffser, F32 yoffset) ; - // - - void setSpatialGroup(LLSpatialGroup* groupp) ; - void setTexCoordScale(F32 xscale, F32 yscale) ; - void setValid() {mValid = TRUE ;} - - LLTextureAtlas* getAtlas()const {return mAtlasp;} - LLSpatialGroup* getSpatialGroup() const {return mGroupp ;} - S16 getSlotCol()const {return mCol;} - S16 getSlotRow()const {return mRow;} - S8 getSlotWidth()const{return mReservedSlotWidth;} - BOOL isValid()const { return mValid;} - const LLVector2* getTexCoordOffset()const {return &mTexCoordOffset;} - const LLVector2* getTexCoordScale() const {return &mTexCoordScale;} - - void setUpdatedTime(U32 t) {mUpdatedTime = t;} - U32 getUpdatedTime()const {return mUpdatedTime;} - -private: - LLTextureAtlas* mAtlasp; - S16 mCol ;//col of the slot - S16 mRow ;//row of the slot - S8 mReservedSlotWidth ; //slot is a square with each edge length a power-of-two number - LLSpatialGroup* mGroupp ; - BOOL mValid ; - - LLVector2 mTexCoordOffset ; - LLVector2 mTexCoordScale ; - - U32 mUpdatedTime ; -} ; - -class LLTextureAtlasManager : public LLSingleton<LLTextureAtlasManager> -{ -private: - typedef std::list<LLPointer<LLTextureAtlas> > ll_texture_atlas_list_t ; - -public: - LLTextureAtlasManager(); - ~LLTextureAtlasManager(); - - LLPointer<LLTextureAtlasSlot> reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents, - LLSpatialGroup* groupp, LLViewerImage* imagep) ; - void releaseAtlas(LLTextureAtlas* atlasp); - - BOOL canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target) ; - -private: - std::vector<ll_texture_atlas_list_t> mAtlasMap ; - std::vector<ll_texture_atlas_list_t> mEmptyAtlasMap ; //delay some empty atlases deletion to avoid possible creation of new atlas immediately. -}; - -#endif diff --git a/linden/indra/newview/lltextureview.cpp b/linden/indra/newview/lltextureview.cpp index 903a6e5..04cebf5 100644 --- a/linden/indra/newview/lltextureview.cpp +++ b/linden/indra/newview/lltextureview.cpp @@ -57,16 +57,14 @@ extern F32 texmem_lower_bound_scale; LLTextureView *gTextureView = NULL; -LLTextureSizeView *gTextureSizeView = NULL; -LLTextureSizeView *gTextureCategoryView = NULL; //static std::set<LLViewerImage*> LLTextureView::sDebugImages; //////////////////////////////////////////////////////////////////////////// -static std::string title_string1a("Tex UUID Area DDis(Req) DecodePri(Fetch) [download]"); -static std::string title_string1b("Tex UUID Area DDis(Req) Fetch(DecodePri) [download]"); +static std::string title_string1a("Tex UUID Area DDis(Req) DecodePri(Fetch) [download] pk/max"); +static std::string title_string1b("Tex UUID Area DDis(Req) Fetch(DecodePri) [download] pk/max"); static std::string title_string2("State"); static std::string title_string3("Pkt Bnd"); static std::string title_string4(" W x H (Dis) Mem"); @@ -203,14 +201,13 @@ void LLTextureBar::draw() } else { - tex_str = llformat("%s %7.0f %d(%d) %8.0f(0x%08x) %1.2f", + tex_str = llformat("%s %7.0f %d(%d) %8.0f(0x%08x)", uuid_str.c_str(), mImagep->mMaxVirtualSize, mImagep->mDesiredDiscardLevel, mImagep->mRequestedDiscardLevel, mImagep->getDecodePriority(), - mImagep->mFetchPriority, - mImagep->mDownloadProgress); + mImagep->mFetchPriority); } LLFontGL::getFontMonospace()->renderUTF8(tex_str, 0, title_x1, getRect().getHeight(), @@ -256,7 +253,7 @@ void LLTextureBar::draw() // Draw the progress bar. S32 bar_width = 100; - S32 bar_left = 330; + S32 bar_left = 260; left = bar_left; right = left + bar_width; @@ -265,7 +262,7 @@ void LLTextureBar::draw() F32 data_progress = mImagep->mDownloadProgress; - if (data_progress > 0.0f && data_progress <= 1.0f) + if (data_progress > 0.0f) { // Downloaded bytes right = left + llfloor(data_progress * (F32)bar_width); @@ -275,16 +272,6 @@ void LLTextureBar::draw() gl_rect_2d(left, top, right, bottom); } } - else if (data_progress > 1.0f) - { - // Small cached textures generate this oddity. SNOW-168 - right = left + bar_width; - if (right > left) - { - gGL.color4f(0.f, 0.33f, 0.f, 0.75f); - gl_rect_2d(left, top, right, bottom); - } - } S32 pip_width = 6; S32 pip_space = 14; @@ -399,9 +386,9 @@ private: void LLGLTexMemBar::draw() { - S32 bound_mem = (LLViewerImage::sBoundTextureMemoryInBytes >> 20); + S32 bound_mem = BYTES_TO_MEGA_BYTES(LLViewerImage::sBoundTextureMemoryInBytes); S32 max_bound_mem = LLViewerImage::sMaxBoundTextureMemInMegaBytes; - S32 total_mem = (LLViewerImage::sTotalTextureMemoryInBytes >> 20); + S32 total_mem = BYTES_TO_MEGA_BYTES(LLViewerImage::sTotalTextureMemoryInBytes); S32 max_total_mem = LLViewerImage::sMaxTotalTextureMemInMegaBytes; F32 discard_bias = LLViewerImage::sDesiredDiscardBias; S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); @@ -491,25 +478,28 @@ void LLGLTexMemBar::draw() #endif //---------------------------------------------------------------------------- - text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d RAW:%d HTP:%d BW: %.0f/%.0f", + text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d RAW:%d HTP:%d", gImageList.getNumImages(), - LLAppViewer::getTextureFetch()->getNumRequests(), - LLAppViewer::getTextureFetch()->getNumDeletes(), - LLAppViewer::getTextureFetch()->mPacketCount, - LLAppViewer::getTextureFetch()->mBadPacketCount, - LLAppViewer::getTextureCache()->getNumReads(), - LLAppViewer::getTextureCache()->getNumWrites(), + LLAppViewer::getTextureFetch()->getNumRequests(), LLAppViewer::getTextureFetch()->getNumDeletes(), + LLAppViewer::getTextureFetch()->mPacketCount, LLAppViewer::getTextureFetch()->mBadPacketCount, + LLAppViewer::getTextureCache()->getNumReads(), LLAppViewer::getTextureCache()->getNumWrites(), LLLFSThread::sLocal->getPending(), LLAppViewer::getImageDecodeThread()->getPending(), LLImageRaw::sRawImageCount, - LLAppViewer::getTextureFetch()->getNumHTTPRequests(), - LLAppViewer::getTextureFetch()->getTextureBandwidth(), - gSavedSettings.getF32("ThrottleBandwidthKBPS")); + LLAppViewer::getTextureFetch()->getNumHTTPRequests()); LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, line_height*2, text_color, LLFontGL::LEFT, LLFontGL::TOP); - left = 600; + + left = 550; + F32 bandwidth = LLAppViewer::getTextureFetch()->getTextureBandwidth(); + F32 max_bandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); + color = bandwidth > max_bandwidth ? LLColor4::red : bandwidth > max_bandwidth*.75f ? LLColor4::yellow : text_color; + color[VALPHA] = text_color[VALPHA]; + text = llformat("BW:%.0f/%.0f",bandwidth, max_bandwidth); + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*2, + color, LLFontGL::LEFT, LLFontGL::TOP); S32 dx1 = 0; if (LLAppViewer::getTextureFetch()->mDebugPause) @@ -576,7 +566,7 @@ public: void setTop(S32 loaded, S32 bound, F32 scale) {mTopLoaded = loaded ; mTopBound = bound; mScale = scale ;} void draw(); - BOOL handleHover(S32 x, S32 y, MASK mask) ; + BOOL handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size) ; private: S32 mIndex ; @@ -589,19 +579,16 @@ private: F32 mScale ; }; -BOOL LLGLTexSizeBar::handleHover(S32 x, S32 y, MASK mask) +BOOL LLGLTexSizeBar::handleHover(S32 x, S32 y, MASK mask, BOOL set_pick_size) { -#if !LL_RELEASE_FOR_DOWNLOAD if(y > mBottom && (y < mBottom + (S32)(mTopLoaded * mScale) || y < mBottom + (S32)(mTopBound * mScale))) { - LLImageGL::setCurTexSizebar(mIndex); + LLImageGL::setCurTexSizebar(mIndex, set_pick_size); } -#endif return TRUE ; } void LLGLTexSizeBar::draw() { -#if !LL_RELEASE_FOR_DOWNLOAD LLGLSUIDefault gls_ui; if(LLImageGL::sCurTexSizeBar == mIndex) @@ -622,7 +609,6 @@ void LLGLTexSizeBar::draw() F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f}; gl_rect_2d(mLeft, mBottom + (S32)(mTopLoaded * mScale), (mLeft + mRight) / 2, mBottom, loaded_color) ; gl_rect_2d((mLeft + mRight) / 2, mBottom + (S32)(mTopBound * mScale), mRight, mBottom, bound_color) ; -#endif } //////////////////////////////////////////////////////////////////////////// @@ -927,7 +913,31 @@ LLTextureSizeView::~LLTextureSizeView() } void LLTextureSizeView::draw() { -#if !LL_RELEASE_FOR_DOWNLOAD + if(mType == TEXTURE_MEM_OVER_SIZE) + { + drawTextureSizeGraph(); + } + else + { + drawTextureCategoryGraph() ; + } + + LLView::draw(); +} + +BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask) +{ + if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight) + { + mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask, (mType == TEXTURE_MEM_OVER_SIZE)) ; + } + + return TRUE ; +} + +//draw real-time texture mem bar over size +void LLTextureSizeView::drawTextureSizeGraph() +{ if(mTextureSizeBar.size() == 0) { S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); @@ -948,29 +958,16 @@ void LLTextureSizeView::draw() mTextureSizeBar[i]->draw() ; } LLImageGL::resetCurTexSizebar(); - - LLView::draw(); -#endif -} - -BOOL LLTextureSizeView::handleHover(S32 x, S32 y, MASK mask) -{ - if(x > mTextureSizeBarRect.mLeft && x < mTextureSizeBarRect.mRight) - { - mTextureSizeBar[(x - mTextureSizeBarRect.mLeft) / mTextureSizeBarWidth]->handleHover(x, y, mask) ; - } - - return TRUE ; } //draw background of texture size bar graph F32 LLTextureSizeView::drawTextureSizeDistributionGraph() { + //scale F32 scale = 1.0f ; -#if !LL_RELEASE_FOR_DOWNLOAD + LLGLSUIDefault gls_ui; - //scale { S32 count = 0 ; for(U32 i = 0 ; i < LLImageGL::sTextureLoadedCounter.size() ; i++) @@ -1060,7 +1057,136 @@ F32 LLTextureSizeView::drawTextureSizeDistributionGraph() text = llformat("Texture Size Distribution") ; LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3, text_color, LLFontGL::LEFT, LLFontGL::TOP); + return scale ; +} + +//draw real-time texture mem bar over category +void LLTextureSizeView::drawTextureCategoryGraph() +{ + if(mTextureSizeBar.size() == 0) + { + S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); + mTextureSizeBar.resize(LLImageGL::sTextureMemByCategory.size()) ; + mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ; + + for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) + { + mTextureSizeBar[i] = new LLGLTexSizeBar(i, mTextureSizeBarRect.mLeft + i * mTextureSizeBarWidth , + line_height * 2, mTextureSizeBarRect.mLeft + (i + 1) * mTextureSizeBarWidth, line_height) ; + } + } + + F32 size_bar_scale = drawTextureCategoryDistributionGraph() ; + for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) + { + mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[i] >> 20, LLImageGL::sTextureMemByCategoryBound[i] >> 20, size_bar_scale) ; + mTextureSizeBar[i]->draw() ; + } + LLImageGL::resetCurTexSizebar(); +} + +//draw background for TEXTURE_MEM_OVER_CATEGORY +F32 LLTextureSizeView::drawTextureCategoryDistributionGraph() +{ + //scale + F32 scale = 4.0f ; + + LLGLSUIDefault gls_ui; + + { + S32 count = 0 ; + for(U32 i = 0 ; i < LLImageGL::sTextureMemByCategory.size() ; i++) + { + S32 tmp = LLImageGL::sTextureMemByCategory[i] >> 20 ; + if(tmp > count) + { + count = tmp ; + } + } + if(count > mTextureSizeBarRect.getHeight() * 0.25f) + { + scale = (F32)mTextureSizeBarRect.getHeight() * 0.25f / count ; + } + } + + S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); + S32 left = mTextureSizeBarRect.mLeft ; + S32 bottom = mTextureSizeBarRect.mBottom ; + S32 right = mTextureSizeBarRect.mRight ; + S32 top = mTextureSizeBarRect.mTop ; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + //background rect + gl_rect_2d(left - 25, top + 30, right + 100, bottom - 25, LLColor4(0.0f, 0.0f, 0.0f, 0.25f)) ; + + //-------------------------------------------------- + gGL.color4f(1.0f, 0.5f, 0.5f, 0.75f); + gl_line_2d(left, bottom, right, bottom) ; //x axis + gl_line_2d(left, bottom, left, top) ; //y axis + + //ruler + //-------------------------------------------------- + gGL.color4f(1.0f, 0.5f, 0.5f, 0.5f); + for(S32 i = bottom + 50 ; i <= top ; i += 50) + { + gl_line_2d(left, i, right, i) ; + } + + //texts + //-------------------------------------------------- + F32 text_color[] = {1.f, 1.f, 1.f, 0.75f}; + std::string text; + + //------- + //x axis: size label + static char category[LLViewerImageBoostLevel::MAX_GL_IMAGE_CATEGORY][4] = + {"Non", "Bak", "Av", "Cld", "Scp", "Hi", "Trn", "Slt", "Hud", "Bsf", "UI", "Pvw", "Map", "Mvs", "Slf", "Tbp", "Scr", "Fnt", "Bmp", "Dyn", "Tlc", "Mdi", "ALT", "Oth" } ; + + text = llformat("%s", category[0]) ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 12, bottom - line_height / 2, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + for(U32 i = 1 ; i < mTextureSizeBar.size() ; i++) + { + text = llformat("%s", category[i]) ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + i * mTextureSizeBarWidth + 12, bottom - line_height / 2, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + } + //------- + + //y axis: number label + for(S32 i = bottom + 50 ; i <= top ; i += 50) + { + text = llformat("%d", (S32)((i - bottom) / scale)) ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, i + line_height / 2 , + text_color, LLFontGL::LEFT, LLFontGL::TOP); + LLFontGL::getFontMonospace()->renderUTF8(text, 0, right + 5, i + line_height / 2 , + text_color, LLFontGL::LEFT, LLFontGL::TOP); + } + + text = llformat("MB") ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left - 20, top + line_height * 2 , + text_color, LLFontGL::LEFT, LLFontGL::TOP); + //-------------------------------------------------- + F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f}; + gl_rect_2d(left + 70, top + line_height * 2, left + 90, top + line_height, loaded_color) ; + text = llformat("Loaded") ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 100, top + line_height * 2, + loaded_color, + LLFontGL::LEFT, LLFontGL::TOP); + + F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f}; + gl_rect_2d(left + 170, top + line_height * 2, left + 190, top + line_height, bound_color) ; + text = llformat("Bound") ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 200, top + line_height * 2, + bound_color, LLFontGL::LEFT, LLFontGL::TOP); + + //-------------------------------------------------- + + //title + text = llformat("Texture Category Distribution") ; + LLFontGL::getFontMonospace()->renderUTF8(text, 0, left + 250, top + line_height * 3, + text_color, LLFontGL::LEFT, LLFontGL::TOP); -#endif return scale ; } diff --git a/linden/indra/newview/lltoolpie.h b/linden/indra/newview/lltoolpie.h index 54bf409..001886f 100644 --- a/linden/indra/newview/lltoolpie.h +++ b/linden/indra/newview/lltoolpie.h @@ -86,6 +86,7 @@ private: LLPickInfo mPick; U8 mClickAction; LLSafeHandle<LLObjectSelection> mLeftClickSelection; +protected: LLPointer<LLViewerObject> mClickActionObject; }; diff --git a/linden/indra/newview/llviewercamera.cpp b/linden/indra/newview/llviewercamera.cpp index 6cef2af..dade65f 100644 --- a/linden/indra/newview/llviewercamera.cpp +++ b/linden/indra/newview/llviewercamera.cpp @@ -769,8 +769,8 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts) BOOL in_frustum = pointInFrustum(LLVector3(vec)) > 0; - if ( !in_frustum && all_verts || - in_frustum && !all_verts) + if (( !in_frustum && all_verts) || + (in_frustum && !all_verts)) { return !all_verts; } diff --git a/linden/indra/newview/llviewercontrol.cpp b/linden/indra/newview/llviewercontrol.cpp index 4c9c098..1531e6c 100644 --- a/linden/indra/newview/llviewercontrol.cpp +++ b/linden/indra/newview/llviewercontrol.cpp @@ -90,7 +90,7 @@ std::string gCurrentVersion; extern BOOL gResizeScreenTexture; extern BOOL gDebugGL; -//extern BOOL gAuditTexture; +extern BOOL gAuditTexture; //////////////////////////////////////////////////////////////////////////// // Listeners @@ -418,12 +418,12 @@ static bool handleRenderUseImpostorsChanged(const LLSD& newvalue) LLVOAvatar::sUseImpostors = newvalue.asBoolean(); return true; } -/* + static bool handleAuditTextureChanged(const LLSD& newvalue) { gAuditTexture = newvalue.asBoolean(); return true; -}*/ +} static bool handleRenderDebugGLChanged(const LLSD& newvalue) { @@ -528,11 +528,6 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1)); gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); - - gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); - gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); - gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); - gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); gSavedSettings.getControl("EnableRippleWater")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); @@ -544,9 +539,6 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderAvatarInvisible")->getSignal()->connect(boost::bind(&handleSetSelfInvisible, _1)); gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _1)); gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _1)); - gSavedSettings.getControl("RenderDeferredShadow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); - gSavedSettings.getControl("RenderDeferredGI")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); - gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _1)); gSavedSettings.getControl("RenderTreeLODFactor")->getSignal()->connect(boost::bind(&handleTreeLODChanged, _1)); gSavedSettings.getControl("RenderFlexTimeFactor")->getSignal()->connect(boost::bind(&handleFlexLODChanged, _1)); @@ -592,7 +584,7 @@ void settings_setup_listeners() gSavedSettings.getControl("AudioLevelDoppler")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("AudioLevelRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("AudioStreamingMusic")->getSignal()->connect(boost::bind(&handleAudioStreamMusicChanged, _1)); -// gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _1)); + gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _1)); gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("MuteMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("MuteMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); diff --git a/linden/indra/newview/llviewerdisplay.cpp b/linden/indra/newview/llviewerdisplay.cpp index 5e1cf80..5316337 100644 --- a/linden/indra/newview/llviewerdisplay.cpp +++ b/linden/indra/newview/llviewerdisplay.cpp @@ -128,11 +128,6 @@ void display_startup() return; } - gPipeline.updateGL(); - - // Update images? - gImageList.updateImages(0.01f); - LLGLSDefault gls_default; // Required for HTML update in login screen @@ -604,9 +599,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gPipeline.updateGeom(max_geom_update_time); stop_glerror(); - gPipeline.updateGL(); - stop_glerror(); - gFrameStats.start(LLFrameStats::UPDATE_CULL); S32 water_clip = 0; if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) && @@ -697,8 +689,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gPipeline.generateSunShadow(*LLViewerCamera::getInstance()); } - LLVertexBuffer::unbind(); // KL - LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); @@ -729,7 +719,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery"); gPipeline.generateWaterReflection(*LLViewerCamera::getInstance()); - gPipeline.generateHighlight(*LLViewerCamera::getInstance()); } ////////////////////////////////////// @@ -754,9 +743,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) const F32 max_image_decode_time = llmin(0.005f, 0.005f*10.f*gFrameIntervalSeconds); // 50 ms/second decode time (no more than 5ms/frame) gImageList.updateImages(max_image_decode_time); - - //remove dead textures from GL KL is it req? - LLImageGL::deleteDeadTextures(); stop_glerror(); } llpushcallstacks ; @@ -911,7 +897,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) /// and then display it again with compositor effects. /// Using render to texture would be faster/better, but I don't have a /// grasp of their full display stack just yet. - gPostProcess->apply(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()); // KL + // gPostProcess->apply(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()); if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { @@ -927,8 +913,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) render_ui(); } - gPipeline.rebuildGroups(); - LLSpatialGroup::sNoDelete = FALSE; } @@ -1015,15 +999,6 @@ void render_hud_attachments() 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); diff --git a/linden/indra/newview/llviewerimage.cpp b/linden/indra/newview/llviewerimage.cpp index 93c17a2..400fb2f 100644 --- a/linden/indra/newview/llviewerimage.cpp +++ b/linden/indra/newview/llviewerimage.cpp @@ -60,8 +60,6 @@ #include "pipeline.h" #include "llappviewer.h" #include "llface.h" -#include "lltextureatlas.h" -#include "lltextureatlasmanager.h" #include "llviewercamera.h" /////////////////////////////////////////////////////////////////////////////// @@ -104,7 +102,7 @@ void LLViewerImage::initClass() sNullImagep = new LLImageGL(1,1,3,TRUE); LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3); raw->clear(0x77, 0x77, 0x77, 0xFF); - sNullImagep->createGLTexture(0, raw); + sNullImagep->createGLTexture(0, raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); #if 1 LLPointer<LLViewerImage> imagep = new LLViewerImage(IMG_DEFAULT); @@ -133,7 +131,7 @@ void LLViewerImage::initClass() } } } - imagep->createGLTexture(0, image_raw); + imagep->createGLTexture(0, image_raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); image_raw = NULL; gImageList.addImage(imagep); imagep->dontDiscard(); @@ -143,48 +141,48 @@ void LLViewerImage::initClass() sSmokeImagep = gImageList.getImage(IMG_SMOKE, TRUE, TRUE); sSmokeImagep->setNoDelete() ; -#if !LL_RELEASE_FOR_DOWNLOAD - sDefaultTexturep = new LLImageGL() ; - image_raw = new LLImageRaw(dim,dim,3); - data = image_raw->getData(); - for (S32 i = 0; i<dim; i++) + if(gAuditTexture) { - for (S32 j = 0; j<dim; j++) + sDefaultTexturep = new LLImageGL() ; + image_raw = new LLImageRaw(dim,dim,3); + data = image_raw->getData(); + for (S32 i = 0; i<dim; i++) { - const S32 border = 2; - if (i<border || j<border || i>=(dim-border) || j>=(dim-border)) - { - *data++ = 0xff; - *data++ = 0xff; - *data++ = 0xff; - } - else + for (S32 j = 0; j<dim; j++) { - *data++ = 0xff; - *data++ = 0xff; - *data++ = 0x00; + const S32 border = 2; + if (i<border || j<border || i>=(dim-border) || j>=(dim-border)) + { + *data++ = 0xff; + *data++ = 0xff; + *data++ = 0xff; + } + else + { + *data++ = 0xff; + *data++ = 0xff; + *data++ = 0x00; + } } } + sDefaultTexturep->createGLTexture(0, image_raw, 0, TRUE, LLViewerImageBoostLevel::OTHER); + image_raw = NULL; + sDefaultTexturep->dontDiscard(); } - sDefaultTexturep->createGLTexture(0, image_raw); - image_raw = NULL; - sDefaultTexturep->dontDiscard(); -#endif } // static void LLViewerImage::cleanupClass() { stop_glerror(); + LLImageGL::cleanupClass() ; + sNullImagep = NULL; sDefaultImagep = NULL; sSmokeImagep = NULL; sMissingAssetImagep = NULL; - sWhiteImagep = NULL; - -#if !LL_RELEASE_FOR_DOWNLOAD - LLImageGL::sDefaultTexturep = NULL ; -#endif + sWhiteImagep = NULL; + sDefaultTexturep = NULL ; } // tuning params @@ -233,7 +231,12 @@ void LLViewerImage::updateClass(const F32 velocity, const F32 angular_velocity) } sDesiredDiscardBias = llclamp(sDesiredDiscardBias, sDesiredDiscardBiasMin, sDesiredDiscardBiasMax); - LLImageGL::sUseTextureAtlas = gSavedSettings.getBOOL("EnableTextureAtlas") ; + F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; + F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); + sCameraMovingDiscardBias = (S8)llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1) ; + + LLViewerImage::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) && + (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ; } // static @@ -379,7 +382,6 @@ LLViewerImage::~LLViewerImage() void LLViewerImage::cleanup() { mFaceList.clear() ; - for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) { @@ -409,192 +411,6 @@ void LLViewerImage::reinit(BOOL usemipmaps /* = TRUE */) setSize(0,0,0); } -void LLViewerImage::resetFaceAtlas() -{ - //Nothing should be done here. -} - -//invalidate all atlas slots for this image. -void LLViewerImage::invalidateAtlas(BOOL rebuild_geom) -{ - for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) - { - if(*iter) - { - LLFace* facep = (LLFace*)*iter ; - facep->removeAtlas() ; - if(rebuild_geom && facep->getDrawable() && facep->getDrawable()->getSpatialGroup()) - { - facep->getDrawable()->getSpatialGroup()->setState(LLSpatialGroup::GEOM_DIRTY); - } - } - } -} - -BOOL LLViewerImage::insertToAtlas() -{ - if(mFaceList.size() < 1) - { - return FALSE ; - } - if(!canAddToAtlas()) - { - return FALSE ; - } - if(getDiscardLevelInAtlas() > 0 && mRawDiscardLevel >= getDiscardLevelInAtlas()) - { - return FALSE ; - } - if(!LLTextureAtlasManager::getInstance()->canAddToAtlas(mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents(), getTexTarget())) - { - return FALSE ; - } - - BOOL ret = TRUE ;//if ret is set to false, will generate a gl texture for this image. - S32 raw_w = mRawImage->getWidth() ; - S32 raw_h = mRawImage->getHeight() ; - F32 xscale = 1.0f, yscale = 1.0f ; - LLPointer<LLTextureAtlasSlot> slot_infop; - LLTextureAtlasSlot* cur_slotp ;//no need to be smart pointer. - LLSpatialGroup* groupp ; - LLFace* facep; - - //if the atlas slot pointers for some faces are null, process them later. - ll_face_list_t waiting_list ; - - for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) - { - if(*iter) - { - facep = (LLFace*)*iter ; - - //face can not use atlas. - if(!facep->canUseAtlas()) - { - if(facep->getAtlasInfo()) - { - facep->removeAtlas() ; - } - ret = FALSE ; - continue ; - } - - //the atlas slot is updated - slot_infop = facep->getAtlasInfo() ; - groupp = facep->getDrawable()->getSpatialGroup() ; - - if(slot_infop) - { - if(slot_infop->getSpatialGroup() != groupp) - { - if((cur_slotp = groupp->getCurUpdatingSlot(this))) //switch slot - { - facep->setAtlasInfo(cur_slotp) ; - facep->setAtlasInUse(TRUE) ; - continue ; - } - else //do not forget to update slot_infop->getSpatialGroup(). - { - LLSpatialGroup* gp = slot_infop->getSpatialGroup() ; - gp->setCurUpdatingTime(gFrameCount) ; - gp->setCurUpdatingTexture(this) ; - gp->setCurUpdatingSlot(slot_infop) ; - } - } - else //same group - { - if(gFrameCount && slot_infop->getUpdatedTime() == gFrameCount)//slot is just updated - { - facep->setAtlasInUse(TRUE) ; - continue ; - } - } - } - else - { - //if the slot is null, wait to process them later. - waiting_list.push_back(facep) ; - continue ; - } - - //---------- - //insert to atlas - if(!LLImageGL::createGLTextureInAtlas(mRawDiscardLevel, mRawImage, slot_infop->getAtlas(), slot_infop->getSlotCol(), slot_infop->getSlotRow())) - { - //the texture does not qualify to add to atlas, do not bother to try for other faces. - //invalidateAtlas(); - return FALSE ; - } - - //update texture scale - slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ; - slot_infop->setTexCoordScale(xscale, yscale) ; - slot_infop->setValid() ; - slot_infop->setUpdatedTime(gFrameCount) ; - - //update spatial group atlas info - groupp->setCurUpdatingTime(gFrameCount) ; - groupp->setCurUpdatingTexture(this) ; - groupp->setCurUpdatingSlot(slot_infop) ; - - //make the face to switch to the atlas. - facep->setAtlasInUse(TRUE) ; - } - } - - //process the waiting_list - for(ll_face_list_t::iterator iter = waiting_list.begin(); iter != waiting_list.end(); ++iter) - { - facep = (LLFace*)*iter ; - groupp = facep->getDrawable()->getSpatialGroup() ; - - //check if this texture already inserted to atlas for this group - if((cur_slotp = groupp->getCurUpdatingSlot(this))) - { - facep->setAtlasInfo(cur_slotp) ; - facep->setAtlasInUse(TRUE) ; - continue ; - } - - //need to reserve a slot from atlas - slot_infop = LLTextureAtlasManager::getInstance()->reserveAtlasSlot(llmax(mFullWidth, mFullHeight), getComponents(), groupp, this) ; - - facep->setAtlasInfo(slot_infop) ; - - groupp->setCurUpdatingTime(gFrameCount) ; - groupp->setCurUpdatingTexture(this) ; - groupp->setCurUpdatingSlot(slot_infop) ; - - //slot allocation failed. - if(!slot_infop || !slot_infop->getAtlas()) - { - ret = FALSE ; - facep->setAtlasInUse(FALSE) ; - continue ; - } - - //insert to atlas - if(!LLImageGL::createGLTextureInAtlas(mRawDiscardLevel, mRawImage, slot_infop->getAtlas(), slot_infop->getSlotCol(), slot_infop->getSlotRow())) - { - //the texture does not qualify to add to atlas, do not bother to try for other faces. - ret = FALSE ; - //invalidateAtlas(); - break ; - } - - //update texture scale - slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ; - slot_infop->setTexCoordScale(xscale, yscale) ; - slot_infop->setValid() ; - slot_infop->setUpdatedTime(gFrameCount) ; - - //make the face to switch to the atlas. - facep->setAtlasInUse(TRUE) ; - } - - return ret ; -} - /////////////////////////////////////////////////////////////////////////////// // ONLY called from LLViewerImageList void LLViewerImage::destroyTexture() @@ -616,7 +432,7 @@ void LLViewerImage::addToCreateTexture() if(isForSculptOnly()) { //just update some variables, not to create a real GL texture. - createGLTexture(mRawDiscardLevel, mRawImage, 0) ; + createGLTexture(mRawDiscardLevel, mRawImage, 0, FALSE) ; mNeedsCreateTexture = FALSE ; destroyRawImage(); } @@ -679,7 +495,7 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) mNeedsCreateTexture = FALSE; if (mRawImage.isNull()) { - llwarns << "LLViewerImage trying to create texture with no Raw Image" << llendl; + llerrs << "LLViewerImage trying to create texture with no Raw Image" << llendl; } // llinfos << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ", // mRawDiscardLevel, @@ -703,25 +519,32 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) mOrigHeight = mFullHeight; } - if (LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight())) + bool size_okay = true; + + U32 raw_width = mRawImage->getWidth() << mRawDiscardLevel; + U32 raw_height = mRawImage->getHeight() << mRawDiscardLevel; + if( raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE ) { - if(!(res = insertToAtlas())) - { - res = LLImageGL::createGLTexture(mRawDiscardLevel, mRawImage, usename); - resetFaceAtlas() ; - } + llinfos << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << llendl; + size_okay = false; } - else + if (!LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight())) { // A non power-of-two image was uploaded (through a non standard client) + llinfos << "Non power of two width or height: (" << mRawImage->getWidth() << "," << mRawImage->getHeight() << ")" << llendl; + size_okay = false; + } + + if( !size_okay ) + { + // An inappropriately-sized image was uploaded (through a non standard client) // We treat these images as missing assets which causes them to // be renderd as 'missing image' and to stop requesting data setIsMissingAsset(); destroyRawImage(); return FALSE; } - if (mRawImage->getComponents()>4) { LL_DEBUGS("Openjpeg")<<"broken raw image" << LL_ENDL; @@ -730,6 +553,7 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) return FALSE; } + res = LLImageGL::createGLTexture(mRawDiscardLevel, mRawImage, usename); } // @@ -831,7 +655,6 @@ void LLViewerImage::processTextureStats() S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT); S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT); mTexelsPerImage = (F32)fullwidth * fullheight; - F32 discard_level = 0.f; // If we know the output width and height, we can force the discard @@ -839,8 +662,7 @@ void LLViewerImage::processTextureStats() // data than we need to. if (mBoostLevel == LLViewerImageBoostLevel::BOOST_UI || mBoostLevel == LLViewerImageBoostLevel::BOOST_PREVIEW || - mBoostLevel == LLViewerImageBoostLevel::BOOST_AVATAR_SELF || - mBoostLevel == LLViewerImageBoostLevel::BOOST_AVATAR_BAKED_SELF) + mBoostLevel == LLViewerImageBoostLevel::BOOST_AVATAR_SELF) // JAMESDEBUG what about AVATAR_BAKED_SELF? { discard_level = 0; // full res } @@ -855,6 +677,12 @@ void LLViewerImage::processTextureStats() } else { + if(isLargeImage() && !isJustBound() && mAdditionalDecodePriority < 1.0f) + { + //if is a big image and not being used recently, nor close to the view point, do not load hi-res data. + mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)LLViewerImage::sMinLargeImageSize) ; + } + if ((mCalculatedDiscardLevel >= 0.f) && (llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f)) { @@ -877,7 +705,6 @@ void LLViewerImage::processTextureStats() discard_level += sCameraMovingDiscardBias ; } discard_level = floorf(discard_level); -// discard_level -= (gImageList.mVideoMemorySetting>>1); // more video ram = higher detail F32 min_discard = 0.f; if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) @@ -899,12 +726,15 @@ void LLViewerImage::processTextureStats() if ((sDesiredDiscardBias > 0.0f) && (current_discard >= 0 && mDesiredDiscardLevel >= current_discard)) { - if ( (sBoundTextureMemoryInBytes >> 20) > sMaxBoundTextureMemInMegaBytes*texmem_middle_bound_scale) + // Limit the amount of GL memory bound each frame + if ( (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) && + (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) { scaleDown() ; } // Only allow GL to have 2x the video card memory - else if (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel) + else if ( (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale) && + (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) { scaleDown() ; } @@ -926,7 +756,7 @@ void LLViewerImage::updateVirtualSize() if(facep->getDrawable()->isRecentlyVisible()) { addTextureStats(facep->getVirtualSize()) ; - //setAdditionalDecodePriority(facep->getImportanceToCamera()) ; + setAdditionalDecodePriority(facep->getImportanceToCamera()) ; } } } @@ -966,7 +796,6 @@ void LLViewerImage::switchToCachedImage() mNeedsCreateTexture = TRUE; } } - //============================================================================ F32 LLViewerImage::calcDecodePriority() @@ -988,6 +817,13 @@ F32 LLViewerImage::calcDecodePriority() } S32 cur_discard = getDiscardLevel(); + + //no need to update if the texture reaches its highest res and the memory is sufficient. + //if(LLViewerImage::sFreezeImageScalingDown && !cur_discard) + //{ + // return -5.0f ; + //} + bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); F32 pixel_priority = fsqrtf(mMaxVirtualSize); const S32 MIN_NOT_VISIBLE_FRAMES = 30; // NOTE: this function is not called every frame @@ -1006,6 +842,14 @@ F32 LLViewerImage::calcDecodePriority() { priority = -1.0f ; } + else if (!isJustBound() && mCachedRawImageReady) + { + priority = -1.0f; + } + else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel) + { + priority = -1.0f; + } else if (mDesiredDiscardLevel > mMaxDiscardLevel) { // Don't decode anything we don't need @@ -1066,6 +910,7 @@ F32 LLViewerImage::calcDecodePriority() ddiscard-=2; } ddiscard = llclamp(ddiscard, 0, 4); + priority = ddiscard*100000.f; } if (priority > 0.0f) @@ -1097,7 +942,7 @@ F32 LLViewerImage::calcDecodePriority() //static F32 LLViewerImage::maxDecodePriority() { - return 6000000.f; // KL 2000000 in render pipeline + return 6000000.f; } void LLViewerImage::setDecodePriority(F32 priority) @@ -1124,7 +969,10 @@ void LLViewerImage::setBoostLevel(S32 level) { mBoostLevel = level; - + if(gAuditTexture) + { + setCategory(mBoostLevel); + } if(mBoostLevel != LLViewerImageBoostLevel::BOOST_NONE) { @@ -1174,15 +1022,11 @@ bool LLViewerImage::updateFetch() return false; // process any raw image data in callbacks before replacing } - mFetchState = 0; - mFetchPriority = 0; - mFetchDeltaTime = 999999.f; - mRequestDeltaTime = 999999.f; S32 current_discard = getDiscardLevel(); S32 desired_discard = getDesiredDiscardLevel(); F32 decode_priority = getDecodePriority(); decode_priority = llmax(decode_priority, 0.0f); - //decode_priority = llmin(decode_priority, maxDecodePriority()); + decode_priority = llmin(decode_priority, maxDecodePriority()); if (mIsFetching) { @@ -1215,6 +1059,7 @@ bool LLViewerImage::updateFetch() if (mRawImage.notNull()) { mRawDiscardLevel = fetch_discard; + if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && (current_discard < 0 || mRawDiscardLevel < current_discard)) { @@ -1333,6 +1178,10 @@ bool LLViewerImage::updateFetch() { make_request = false; } + else if (!isJustBound() && mCachedRawImageReady) + { + make_request = false; + } else { if (mIsFetching) @@ -1367,13 +1216,14 @@ bool LLViewerImage::updateFetch() w, h, c, desired_discard, needsAux()); if (fetch_request_created) - { + { mHasFetcher = TRUE; mIsFetching = TRUE; mRequestedDiscardLevel = desired_discard; + mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, - mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); - } + mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); + } // if createRequest() failed, we're finishing up a request for this UUID, // wait for it to complete @@ -1445,12 +1295,12 @@ BOOL LLViewerImage::forceFetch() w, h, c, desired_discard, needsAux()); if (fetch_request_created) - { + { mHasFetcher = TRUE; mIsFetching = TRUE; // Set the image's decode priority to maxDecodePriority() too, or updateFetch() will set // the request priority to 0 and terminate the fetch before we even started (SNOW-203). - // gImageList.bumpToMaxDecodePriority(this); // Kl force immediate update?? + gImageList.bumpToMaxDecodePriority(this); mRequestedDiscardLevel = desired_discard ; mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, @@ -1623,8 +1473,8 @@ bool LLViewerImage::doLoadedCallbacks() destroyRawImage(); readBackRawImage(gl_discard); - //llassert_always(mRawImage.notNull()); - //llassert_always(!mNeedsAux || mAuxRawImage.notNull()); + llassert_always(mRawImage.notNull()); + llassert_always(!mNeedsAux || mAuxRawImage.notNull()); } // @@ -1786,18 +1636,7 @@ bool LLViewerImage::bindDefaultImage(S32 stage) //virtual void LLViewerImage::forceImmediateUpdate() { - //only immediately update a deleted texture which is now being re-used. - if(!isDeleted()) - { - return ; - } - //if already called forceImmediateUpdate() - if(mInImageList && mDecodePriority == LLViewerImage::maxDecodePriority()) - { - return ; - } - - gImageList.forceImmediateUpdate(this) ; + gImageList.bumpToMaxDecodePriority(this) ; return ; } @@ -1808,7 +1647,7 @@ LLImageRaw* LLViewerImage::readBackRawImage(S8 discard_level) llassert_always(mComponents > 0); if (mRawImage.notNull()) { - llwarns << "called with existing mRawImage" << llendl; + llerrs << "called with existing mRawImage" << llendl; mRawImage = NULL; } @@ -1826,7 +1665,7 @@ LLImageRaw* LLViewerImage::readBackRawImage(S8 discard_level) sRawCount++; mIsRawImageValid = TRUE; - + return mRawImage; } diff --git a/linden/indra/newview/llviewerimage.h b/linden/indra/newview/llviewerimage.h index 7d646be..c82b68b 100644 --- a/linden/indra/newview/llviewerimage.h +++ b/linden/indra/newview/llviewerimage.h @@ -41,13 +41,11 @@ #include <map> #include <list> - +class LLFace; #define MIN_VIDEO_RAM_IN_MEGA_BYTES 32 #define MAX_VIDEO_RAM_IN_MEGA_BYTES 512 // 512MB max for performance reasons. class LLViewerImage; -class LLTextureAtlas ; -class LLFace ; typedef void (*loaded_callback_func)( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); @@ -263,29 +261,8 @@ public: void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); } // Host we think might have this image, used for baked av textures. - void setTargetHost(LLHost host) { mTargetHost = host; } LLHost getTargetHost() const { return mTargetHost; } - enum - { - BOOST_NONE = 0, - BOOST_AVATAR_BAKED = 1, - BOOST_AVATAR = 2, - BOOST_CLOUDS = 3, - BOOST_SCULPTED = 4, - - BOOST_HIGH = 10, - BOOST_TERRAIN = 11, // has to be high priority for minimap / low detail - BOOST_SELECTED = 12, - BOOST_HUD = 13, - BOOST_AVATAR_BAKED_SELF = 14, - BOOST_UI = 15, - BOOST_PREVIEW = 16, - BOOST_MAP = 17, - BOOST_MAP_LAYER = 18, - BOOST_AVATAR_SELF = 19, // needed for baking avatar - BOOST_MAX_LEVEL - }; void setBoostLevel(S32 level); S32 getBoostLevel() { return mBoostLevel; } @@ -318,10 +295,6 @@ public: S32 getOriginalWidth() { return mOrigWidth; } S32 getOriginalHeight() { return mOrigHeight; } - BOOL insertToAtlas() ; - void resetFaceAtlas() ; - void invalidateAtlas(BOOL rebuild_geom = FALSE); - BOOL isForSculptOnly() const ; void setForSculpt(); @@ -340,7 +313,6 @@ public: void addFace(LLFace* facep) ; void removeFace(LLFace* facep) ; - BOOL isReferenced()const {return mFaceList.size() > 0 ; } friend class LocalBitmap; // tag: vaa emerald local_asset_browser @@ -446,7 +418,6 @@ private: typedef std::list<LLFace*> ll_face_list_t ; ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture - BOOL mInCreationList ; public: static const U32 sCurrentFileVersion; // Default textures diff --git a/linden/indra/newview/llviewerimagelist.cpp b/linden/indra/newview/llviewerimagelist.cpp index 7642e80..e0f37c9 100644 --- a/linden/indra/newview/llviewerimagelist.cpp +++ b/linden/indra/newview/llviewerimagelist.cpp @@ -199,6 +199,7 @@ static std::string get_texture_list_name() void LLViewerImageList::doPrefetchImages() { +#if 1 if (LLAppViewer::instance()->getPurgeCache()) { // cache was purged, no point @@ -226,7 +227,7 @@ void LLViewerImageList::doPrefetchImages() image->addTextureStats((F32)pixel_area); } } - +#endif } @@ -485,7 +486,7 @@ void LLViewerImageList::removeImageFromList(LLViewerImage *image) { llinfos << "Image is not in mUUIDMap!" << llendl ; } - llwarns << "LLViewerImageList::removeImageFromList - Image not in list" << llendl; + llerrs << "LLViewerImageList::removeImageFromList - Image not in list" << llendl; } llverify(mImageList.erase(image) == 1); image->mInImageList = FALSE; @@ -534,8 +535,7 @@ void LLViewerImageList::deleteImage(LLViewerImage *image) void LLViewerImageList::dirtyImage(LLViewerImage *image) { - //mDirtyTextureList.insert(image); - image->invalidateAtlas(TRUE) ; // KL + mDirtyTextureList.insert(image); } //////////////////////////////////////////////////////////////////////////// @@ -547,21 +547,25 @@ void LLViewerImageList::updateImages(F32 max_time) sNumImagesStat.addValue(sNumImages); sNumRawImagesStat.addValue(LLImageRaw::sRawImageCount); - sGLTexMemStat.addValue((F32)(LLImageGL::sGlobalTextureMemoryInBytes >> 20)); - sGLBoundMemStat.addValue((F32)(LLImageGL::sBoundTextureMemoryInBytes >> 20)); - sRawMemStat.addValue((F32)(LLImageRaw::sGlobalRawMemory >> 20)); - sFormattedMemStat.addValue((F32)(LLImageFormatted::sGlobalFormattedMemory >> 20)); - + sGLTexMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sGlobalTextureMemoryInBytes)); + sGLBoundMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sBoundTextureMemoryInBytes)); + sRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageRaw::sGlobalRawMemory)); + sFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory)); + llpushcallstacks ; + updateImagesDecodePriorities(); + llpushcallstacks ; + F32 total_max_time = max_time; max_time -= updateImagesFetchTextures(max_time); + llpushcallstacks ; - max_time = llmin(llmax(max_time, 0.001f*10.f*gFrameIntervalSeconds), 0.001f); + max_time = llmax(max_time, total_max_time*.25f); // at least 25% of max_time max_time -= updateImagesCreateTextures(max_time); + llpushcallstacks ; - max_time = llmin(llmax(max_time, 0.001f*10.f*gFrameIntervalSeconds), 0.001f); - llpushcallstacks ; + if (!mDirtyTextureList.empty()) { LLFastTimer t(LLFastTimer::FTM_IMAGE_MARK_DIRTY); @@ -735,7 +739,7 @@ F32 LLViewerImageList::updateImagesCreateTextures(F32 max_time) return create_timer.getElapsedTimeF32(); } -void LLViewerImageList::forceImmediateUpdate(LLViewerImage* imagep) +void LLViewerImageList::bumpToMaxDecodePriority(LLViewerImage* imagep) { if(!imagep) { @@ -743,6 +747,11 @@ void LLViewerImageList::forceImmediateUpdate(LLViewerImage* imagep) } if(imagep->mInImageList) { + if (imagep->getDecodePriority() == LLViewerImage::maxDecodePriority()) + { + // Already at maximum. + return; + } removeImageFromList(imagep); } @@ -1019,16 +1028,13 @@ LLPointer<LLImageJ2C> LLViewerImageList::convertToUploadFile(LLPointer<LLImageRa return compressedImage; } - -const S32 MIN_VIDEO_RAM = 32; -const S32 MAX_VIDEO_RAM = 512; // 512MB max for performance reasons. // Returns min setting for TextureMemory (in MB) S32 LLViewerImageList::getMinVideoRamSetting() { - S32 system_ram = (S32)(gSysMemory.getPhysicalMemoryClamped() >> 20); + S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); //min texture mem sets to 64M if total physical mem is more than 1.5GB - return (system_ram > 1500) ? 64 : MIN_VIDEO_RAM; + return (system_ram > 1500) ? 64 : MIN_VIDEO_RAM_IN_MEGA_BYTES ; } //static @@ -1055,14 +1061,14 @@ S32 LLViewerImageList::getMaxVideoRamSetting(bool get_recommended) llwarns << "VRAM amount not detected, defaulting to " << max_texmem << " MB" << llendl; } - S32 system_ram = (S32)(gSysMemory.getPhysicalMemoryClamped() >> 20); // In MB + S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); // In MB //llinfos << "*** DETECTED " << system_ram << " MB of system memory." << llendl; if (get_recommended) max_texmem = llmin(max_texmem, (S32)(system_ram/2)); else max_texmem = llmin(max_texmem, (S32)(system_ram)); - max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), MAX_VIDEO_RAM); + max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), MAX_VIDEO_RAM_IN_MEGA_BYTES); return max_texmem; } @@ -1107,9 +1113,9 @@ void LLViewerImageList::updateMaxResidentTexMem(S32 mem) mMaxTotalTextureMemInMegaBytes -= (mMaxResidentTexMemInMegaBytes >> 2); } - if (mMaxTotalTextureMemInMegaBytes > (S32)(gSysMemory.getPhysicalMemoryClamped() >> 20) - 128) + if (mMaxTotalTextureMemInMegaBytes > (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()) - 128) { - mMaxTotalTextureMemInMegaBytes = (gSysMemory.getPhysicalMemoryClamped() >> 20) - 128 ; + mMaxTotalTextureMemInMegaBytes = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()) - 128 ; } llinfos << "Total Video Memory set to: " << vb_mem << " MB" << llendl; diff --git a/linden/indra/newview/llviewerimagelist.h b/linden/indra/newview/llviewerimagelist.h index f82d9f3..561e8e5 100644 --- a/linden/indra/newview/llviewerimagelist.h +++ b/linden/indra/newview/llviewerimagelist.h @@ -112,7 +112,7 @@ public: LLGLenum primary_format = 0, const LLUUID& force_id = LLUUID::null ); - + // Request image from a specific host, used for baked avatar textures. // Implemented in header in case someone changes default params above. JC LLViewerImage* getImageFromHost(const LLUUID& image_id, LLHost host) @@ -129,7 +129,7 @@ public: // Using image stats, determine what images are necessary, and perform image updates. void updateImages(F32 max_time); - void forceImmediateUpdate(LLViewerImage* imagep) ; + void bumpToMaxDecodePriority(LLViewerImage* imagep) ; // Decode and create textures for all images currently in list. void decodeAllImages(F32 max_decode_time); diff --git a/linden/indra/newview/llviewerjointmesh.cpp b/linden/indra/newview/llviewerjointmesh.cpp index dc08bcd..b6f0daf 100644 --- a/linden/indra/newview/llviewerjointmesh.cpp +++ b/linden/indra/newview/llviewerjointmesh.cpp @@ -523,9 +523,9 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) //---------------------------------------------------------------- if (!gRenderForSelect) { - /* if (is_dummy) + if (is_dummy) glColor4fv(LLVOAvatar::getDummyColor().mV); - else */ + else glColor4fv(mColor.mV); } @@ -557,7 +557,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) { if( mLayerSet->hasComposite() ) { - gGL.getTexUnit(0)->bind(mLayerSet->getComposite()->getTexture(), TRUE); // KL SD + gGL.getTexUnit(0)->bind(mLayerSet->getComposite()->getTexture()); } else { @@ -565,7 +565,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) // Ignore the warning if that's the case. if (!gSavedSettings.getBOOL("RenderUnloadedAvatar")) { - //llwarns << "Layerset without composite" << llendl; + llwarns << "Layerset without composite" << llendl; } gGL.getTexUnit(0)->bind(gImageList.getImage(IMG_DEFAULT)); } @@ -574,7 +574,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) if ( !is_dummy && mTexture.notNull() ) { old_mode = mTexture->getAddressMode(); - gGL.getTexUnit(0)->bind(mTexture.get(), TRUE); // KL SD + gGL.getTexUnit(0)->bind(mTexture.get()); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } else diff --git a/linden/indra/newview/llviewermedia.cpp b/linden/indra/newview/llviewermedia.cpp index 8857170..8c5cf6a 100644 --- a/linden/indra/newview/llviewermedia.cpp +++ b/linden/indra/newview/llviewermedia.cpp @@ -938,7 +938,9 @@ void LLViewerMediaImpl::update() x_pos, y_pos, width, - height); + height, + TRUE); // force a fast update (i.e. don't call analyzeAlpha, etc.) + } mMediaSource->resetDirty(); diff --git a/linden/indra/newview/llviewermenu.cpp b/linden/indra/newview/llviewermenu.cpp index 3d3399a..a405764 100644 --- a/linden/indra/newview/llviewermenu.cpp +++ b/linden/indra/newview/llviewermenu.cpp @@ -1412,14 +1412,14 @@ void init_debug_avatar_menu(LLMenuGL* menu) //menu->append(new LLMenuItemToggleGL("Show Attachment Points", &LLVOAvatar::sShowAttachmentPoints)); //diabling collision plane due to DEV-14477 -brad //menu->append(new LLMenuItemToggleGL("Show Collision Plane", &LLVOAvatar::sShowFootPlane)); - /*menu->append(new LLMenuItemCheckGL("Show Collision Skeleton", + menu->append(new LLMenuItemCheckGL("Show Collision Skeleton", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_AVATAR_VOLUME)); menu->append(new LLMenuItemCheckGL("Display Agent Target", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, - (void*)LLPipeline::RENDER_DEBUG_AGENT_TARGET));*/ + (void*)LLPipeline::RENDER_DEBUG_AGENT_TARGET)); menu->append(new LLMenuItemToggleGL( "Debug Rotation", &LLVOAvatar::sDebugAvatarRotation)); menu->append(new LLMenuItemCallGL("Dump Attachments", handle_dump_attachments)); menu->append(new LLMenuItemCallGL("Refresh Appearance", handle_rebake_textures, NULL, NULL, 'R', MASK_ALT | MASK_CONTROL )); @@ -10463,7 +10463,7 @@ class LLAdvancedCheckShowCollisionPlane : public view_listener_t // SHOW COLLISION SKELETON // ///////////////////////////// -/* + class LLAdvancedToggleShowCollisionSkeleton : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) @@ -10484,13 +10484,13 @@ class LLAdvancedCheckShowCollisionSkeleton : public view_listener_t } }; -*/ + ////////////////////////// // DISPLAY AGENT TARGET // ////////////////////////// -/* + class LLAdvancedToggleDisplayAgentTarget : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) @@ -10511,7 +10511,7 @@ class LLAdvancedCheckDisplayAgentTarget : public view_listener_t } }; -*/ + /////////////////////////// // DEBUG AVATAR ROTATION // @@ -11378,10 +11378,10 @@ void initialize_menus() addMenu(new LLAdvancedCheckDebugCharacterVis(), "Advanced.CheckDebugCharacterVis"); // addMenu(new LLAdvancedToggleShowCollisionPlane(), "Advanced.ToggleShowCollisionPlane"); // addMenu(new LLAdvancedCheckShowCollisionPlane(), "Advanced.CheckShowCollisionPlane"); -// addMenu(new LLAdvancedToggleShowCollisionSkeleton(), "Advanced.ToggleShowCollisionSkeleton"); -// addMenu(new LLAdvancedCheckShowCollisionSkeleton(), "Advanced.CheckShowCollisionSkeleton"); -// addMenu(new LLAdvancedToggleDisplayAgentTarget(), "Advanced.ToggleDisplayAgentTarget"); -// addMenu(new LLAdvancedCheckDisplayAgentTarget(), "Advanced.CheckDisplayAgentTarget"); + addMenu(new LLAdvancedToggleShowCollisionSkeleton(), "Advanced.ToggleShowCollisionSkeleton"); + addMenu(new LLAdvancedCheckShowCollisionSkeleton(), "Advanced.CheckShowCollisionSkeleton"); + addMenu(new LLAdvancedToggleDisplayAgentTarget(), "Advanced.ToggleDisplayAgentTarget"); + addMenu(new LLAdvancedCheckDisplayAgentTarget(), "Advanced.CheckDisplayAgentTarget"); addMenu(new LLAdvancedToggleDebugAvatarRotation(), "Advanced.ToggleDebugAvatarRotation"); addMenu(new LLAdvancedCheckDebugAvatarRotation(), "Advanced.CheckDebugAvatarRotation"); addMenu(new LLAdvancedDumpAttachments(), "Advanced.DumpAttachments"); diff --git a/linden/indra/newview/llviewerobject.cpp b/linden/indra/newview/llviewerobject.cpp index bd5abe2..4ab0957 100644 --- a/linden/indra/newview/llviewerobject.cpp +++ b/linden/indra/newview/llviewerobject.cpp @@ -2787,11 +2787,6 @@ BOOL LLViewerObject::updateGeometry(LLDrawable *drawable) return TRUE; } -void LLViewerObject::updateGL() -{ - -} - void LLViewerObject::updateFaceSize(S32 idx) { @@ -2896,7 +2891,7 @@ F32 LLViewerObject::getMidScale() const } -void LLViewerObject::updateTextures(LLAgent &agent) +void LLViewerObject::updateTextures() { } @@ -3741,7 +3736,6 @@ S32 LLViewerObject::setTEColor(const U8 te, const LLColor4& color) else if (color != tep->getColor()) { retval = LLPrimitive::setTEColor(te, color); - //setChanged(TEXTURE); if (mDrawable.notNull() && retval) { // These should only happen on updates which are not the initial update. @@ -3980,7 +3974,7 @@ LLViewerImage *LLViewerObject::getTEImage(const U8 face) const } } - llwarns << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << llendl; + llerrs << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << llendl; return NULL; } @@ -4166,11 +4160,6 @@ void LLViewerObject::updateText() } } -LLVOAvatar* LLViewerObject::asAvatar() -{ - return NULL; -} - BOOL LLViewerObject::isParticleSource() const { return !mPartSourcep.isNull() && !mPartSourcep->isDead(); @@ -4385,14 +4374,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow gAudiop->cleanupAudioSource(mAudioSourcep); mAudioSourcep = NULL; } -/* - if (mAudioSourcep && mAudioSourcep->isMuted() && - mAudioSourcep->getCurrentData() && mAudioSourcep->getCurrentData()->getID() == audio_uuid) - { - //llinfos << "Already having this sound as muted sound, ignoring" << llendl; - return; - } -*/ + getAudioSource(owner_id); if (mAudioSourcep) @@ -4486,11 +4468,7 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para new_block = new LLSculptParams(); break; } - case LLNetworkData::PARAMS_LIGHT_IMAGE: - { - new_block = new LLLightImageParams(); - break; - } + default: { llinfos << "Unknown param type." << llendl; @@ -4581,7 +4559,7 @@ bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_ bool LLViewerObject::setParameterEntryInUse(U16 param_type, BOOL in_use, bool local_origin) { ExtraParameter* param = getExtraParameterEntryCreate(param_type); - if (param && param->in_use != in_use) + if (param->in_use != in_use) { param->in_use = in_use; parameterChanged(param_type, param->data, in_use, local_origin); @@ -4997,7 +4975,7 @@ U32 LLViewerObject::getPartitionType() const return LLViewerRegion::PARTITION_NONE; } -void LLViewerObject::dirtySpatialGroup(BOOL priority) const +void LLViewerObject::dirtySpatialGroup() const { if (mDrawable) { @@ -5005,7 +4983,6 @@ void LLViewerObject::dirtySpatialGroup(BOOL priority) const if (group) { group->dirtyGeom(); - gPipeline.markRebuild(group, priority); } } } diff --git a/linden/indra/newview/llviewerobject.h b/linden/indra/newview/llviewerobject.h index a227f2d..33e8da2 100644 --- a/linden/indra/newview/llviewerobject.h +++ b/linden/indra/newview/llviewerobject.h @@ -74,7 +74,6 @@ class LLViewerPartSourceScript; class LLViewerRegion; class LLViewerObjectMedia; class LLVOInventoryListener; -class LLVOAvatar; typedef enum e_object_update_type { @@ -117,7 +116,7 @@ public: //============================================================================ -class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate +class LLViewerObject : public LLPrimitive, public LLRefCount { protected: ~LLViewerObject(); // use unref() @@ -144,8 +143,6 @@ public: BOOL isOrphaned() const { return mOrphaned; } BOOL isParticleSource() const; - virtual LLVOAvatar* asAvatar(); - static void initVOClasses(); static void cleanupVOClasses(); @@ -192,12 +189,11 @@ public: S32 getNumFaces() const { return mNumFaces; } // Graphical stuff for objects - maybe broken out into render class later? - virtual void updateTextures(LLAgent &agent); + virtual void updateTextures(); virtual void boostTexturePriority(BOOL boost_children = TRUE); // When you just want to boost priority of this object virtual LLDrawable* createDrawable(LLPipeline *pipeline); virtual BOOL updateGeometry(LLDrawable *drawable); - virtual void updateGL(); virtual void updateFaceSize(S32 idx); virtual BOOL updateLOD(); virtual BOOL setDrawableParent(LLDrawable* parentp); @@ -222,7 +218,6 @@ public: virtual BOOL isFlexible() const { return FALSE; } virtual BOOL isSculpted() const { return FALSE; } - virtual BOOL hasLightTexture() const { return FALSE; } // This method returns true if the object is over land owned by // the agent. @@ -473,7 +468,7 @@ public: virtual S32 getLOD() const { return 3; } virtual U32 getPartitionType() const; - virtual void dirtySpatialGroup(BOOL priority = FALSE) const; + virtual void dirtySpatialGroup() const; virtual void dirtyMesh(); virtual LLNetworkData* getParameterEntry(U16 param_type) const; diff --git a/linden/indra/newview/llviewerobjectlist.cpp b/linden/indra/newview/llviewerobjectlist.cpp index 517bb86..78ce247 100644 --- a/linden/indra/newview/llviewerobjectlist.cpp +++ b/linden/indra/newview/llviewerobjectlist.cpp @@ -629,7 +629,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) // Update distance & gpw objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area - objectp->updateTextures(agent); // Update the image levels of textures for this object. + objectp->updateTextures(); // Update the image levels of textures for this object. } } diff --git a/linden/indra/newview/llviewerobjectlist.h b/linden/indra/newview/llviewerobjectlist.h index a77c33d..07920cb 100644 --- a/linden/indra/newview/llviewerobjectlist.h +++ b/linden/indra/newview/llviewerobjectlist.h @@ -44,6 +44,7 @@ // project includes #include "llviewerobject.h" +class LLCamera; class LLNetMap; class LLDebugBeacon; diff --git a/linden/indra/newview/llviewerparceloverlay.cpp b/linden/indra/newview/llviewerparceloverlay.cpp index 935e3e6..0bcd8f3 100644 --- a/linden/indra/newview/llviewerparceloverlay.cpp +++ b/linden/indra/newview/llviewerparceloverlay.cpp @@ -71,7 +71,7 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_ // Use mipmaps = FALSE, clamped, NEAREST filter, for sharp edges mTexture = new LLImageGL(FALSE); mImageRaw = new LLImageRaw(mParcelGridsPerEdge, mParcelGridsPerEdge, OVERLAY_IMG_COMPONENTS); - mTexture->createGLTexture(0, mImageRaw, 0); + mTexture->createGLTexture(0, mImageRaw, 0, TRUE, LLViewerImageBoostLevel::OTHER); gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->bind(mTexture); mTexture->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -593,7 +593,7 @@ void LLViewerParcelOverlay::addPropertyLine( break; default: - llwarns << "Invalid edge in addPropertyLine" << llendl; + llerrs << "Invalid edge in addPropertyLine" << llendl; return; } diff --git a/linden/indra/newview/llviewershadermgr.cpp b/linden/indra/newview/llviewershadermgr.cpp index 8648271..69f7bd8 100644 --- a/linden/indra/newview/llviewershadermgr.cpp +++ b/linden/indra/newview/llviewershadermgr.cpp @@ -113,8 +113,6 @@ LLGLSLShader gDeferredAvatarProgram; LLGLSLShader gDeferredAvatarAlphaProgram; LLGLSLShader gDeferredLightProgram; LLGLSLShader gDeferredMultiLightProgram; -LLGLSLShader gDeferredSpotLightProgram; -LLGLSLShader gDeferredMultiSpotLightProgram; LLGLSLShader gDeferredSunProgram; LLGLSLShader gDeferredBlurLightProgram; LLGLSLShader gDeferredSoftenProgram; @@ -122,12 +120,6 @@ LLGLSLShader gDeferredShadowProgram; LLGLSLShader gDeferredAvatarShadowProgram; LLGLSLShader gDeferredAlphaProgram; LLGLSLShader gDeferredFullbrightProgram; -LLGLSLShader gDeferredGIProgram; -LLGLSLShader gDeferredPostGIProgram; -LLGLSLShader gDeferredPostProgram; - -LLGLSLShader gLuminanceGatherProgram; - //current avatar shader parameter pointer GLint gAvatarMatrixParam; @@ -159,9 +151,6 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gDeferredMultiLightProgram); mShaderList.push_back(&gDeferredAlphaProgram); mShaderList.push_back(&gDeferredFullbrightProgram); - mShaderList.push_back(&gDeferredPostGIProgram); - mShaderList.push_back(&gDeferredPostProgram); - mShaderList.push_back(&gDeferredGIProgram); mShaderList.push_back(&gDeferredWaterProgram); mShaderList.push_back(&gDeferredAvatarAlphaProgram); } @@ -231,32 +220,13 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void) mReservedUniforms.push_back("shadowMap1"); mReservedUniforms.push_back("shadowMap2"); mReservedUniforms.push_back("shadowMap3"); - mReservedUniforms.push_back("shadowMap4"); - mReservedUniforms.push_back("shadowMap5"); - mReservedUniforms.push_back("normalMap"); mReservedUniforms.push_back("positionMap"); mReservedUniforms.push_back("diffuseRect"); mReservedUniforms.push_back("specularRect"); mReservedUniforms.push_back("noiseMap"); - mReservedUniforms.push_back("lightFunc"); mReservedUniforms.push_back("lightMap"); - mReservedUniforms.push_back("luminanceMap"); - mReservedUniforms.push_back("giLightMap"); - mReservedUniforms.push_back("sunLightMap"); - mReservedUniforms.push_back("localLightMap"); - mReservedUniforms.push_back("projectionMap"); - mReservedUniforms.push_back("diffuseGIMap"); - mReservedUniforms.push_back("specularGIMap"); - mReservedUniforms.push_back("normalGIMap"); - mReservedUniforms.push_back("minpGIMap"); - mReservedUniforms.push_back("maxpGIMap"); - mReservedUniforms.push_back("depthGIMap"); - mReservedUniforms.push_back("lastDiffuseGIMap"); - mReservedUniforms.push_back("lastNormalGIMap"); - mReservedUniforms.push_back("lastMinpGIMap"); - mReservedUniforms.push_back("lastMaxpGIMap"); - + mWLUniforms.push_back("camPosLocal"); mTerrainUniforms.reserve(5); @@ -784,9 +754,9 @@ BOOL LLViewerShaderMgr::loadShadersEffects() } } - - // KL enabling loading of postprocess shaders until we fix - // ATI may still have issues +#if 0 + // disabling loading of postprocess shaders until we fix + // ATI sampler2DRect compatibility. //load Color Filter Shader if (success) @@ -827,7 +797,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects() gPostNightVisionProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT]; success = gPostNightVisionProgram.createShader(NULL, &shaderUniforms); } - + #endif return success; @@ -844,8 +814,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredTerrainProgram.unload(); gDeferredLightProgram.unload(); gDeferredMultiLightProgram.unload(); - gDeferredSpotLightProgram.unload(); - gDeferredMultiSpotLightProgram.unload(); gDeferredSunProgram.unload(); gDeferredBlurLightProgram.unload(); gDeferredSoftenProgram.unload(); @@ -855,10 +823,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAvatarAlphaProgram.unload(); gDeferredAlphaProgram.unload(); gDeferredFullbrightProgram.unload(); - gDeferredPostGIProgram.unload(); - gDeferredPostProgram.unload(); - gLuminanceGatherProgram.unload(); - gDeferredGIProgram.unload(); gDeferredWaterProgram.unload(); return FALSE; } @@ -929,26 +893,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { - gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader"; - gDeferredSpotLightProgram.mShaderFiles.clear(); - gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; - success = gDeferredSpotLightProgram.createShader(NULL, NULL); - } - - if (success) - { - gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader"; - gDeferredMultiSpotLightProgram.mShaderFiles.clear(); - gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredMultiSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; - success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL); - } - - if (success) - { gDeferredSunProgram.mName = "Deferred Sun Shader"; gDeferredSunProgram.mShaderFiles.clear(); gDeferredSunProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB)); @@ -998,36 +942,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { - gDeferredPostGIProgram.mName = "Deferred Post GI Shader"; - gDeferredPostGIProgram.mShaderFiles.clear(); - gDeferredPostGIProgram.mShaderFiles.push_back(make_pair("deferred/postgiV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredPostGIProgram.mShaderFiles.push_back(make_pair("deferred/postgiF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredPostGIProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; - success = gDeferredPostGIProgram.createShader(NULL, NULL); - } - - if (success) - { - gDeferredPostProgram.mName = "Deferred Post Shader"; - gDeferredPostProgram.mShaderFiles.clear(); - gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; - success = gDeferredPostProgram.createShader(NULL, NULL); - } - - if (success) - { - gDeferredGIProgram.mName = "Deferred GI Shader"; - gDeferredGIProgram.mShaderFiles.clear(); - gDeferredGIProgram.mShaderFiles.push_back(make_pair("deferred/giV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredGIProgram.mShaderFiles.push_back(make_pair("deferred/giF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredGIProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; - success = gDeferredGIProgram.createShader(NULL, NULL); - } - - if (success) - { // load water shader gDeferredWaterProgram.mName = "Deferred Water Shader"; gDeferredWaterProgram.mFeatures.calculatesAtmospherics = true; @@ -1108,16 +1022,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); } - if (success) - { - gLuminanceGatherProgram.mName = "Luminance Gather Shader"; - gLuminanceGatherProgram.mShaderFiles.clear(); - gLuminanceGatherProgram.mShaderFiles.push_back(make_pair("deferred/luminanceV.glsl", GL_VERTEX_SHADER_ARB)); - gLuminanceGatherProgram.mShaderFiles.push_back(make_pair("deferred/luminanceF.glsl", GL_FRAGMENT_SHADER_ARB)); - gLuminanceGatherProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; - success = gLuminanceGatherProgram.createShader(NULL, NULL); - } - return success; } diff --git a/linden/indra/newview/llviewershadermgr.h b/linden/indra/newview/llviewershadermgr.h index bb50779..a743966 100644 --- a/linden/indra/newview/llviewershadermgr.h +++ b/linden/indra/newview/llviewershadermgr.h @@ -116,30 +116,12 @@ public: DEFERRED_SHADOW1, DEFERRED_SHADOW2, DEFERRED_SHADOW3, - DEFERRED_SHADOW4, - DEFERRED_SHADOW5, DEFERRED_NORMAL, DEFERRED_POSITION, DEFERRED_DIFFUSE, DEFERRED_SPECULAR, DEFERRED_NOISE, - DEFERRED_LIGHTFUNC, DEFERRED_LIGHT, - DEFERRED_LUMINANCE, - DEFERRED_GI_LIGHT, - DEFERRED_SUN_LIGHT, - DEFERRED_LOCAL_LIGHT, - DEFERRED_PROJECTION, - DEFERRED_GI_DIFFUSE, - DEFERRED_GI_SPECULAR, - DEFERRED_GI_NORMAL, - DEFERRED_GI_MIN_POS, - DEFERRED_GI_MAX_POS, - DEFERRED_GI_DEPTH, - DEFERRED_GI_LAST_DIFFUSE, - DEFERRED_GI_LAST_NORMAL, - DEFERRED_GI_LAST_MIN_POS, - DEFERRED_GI_LAST_MAX_POS, END_RESERVED_UNIFORMS } eGLSLReservedUniforms; @@ -344,23 +326,16 @@ extern LLGLSLShader gDeferredTerrainProgram; extern LLGLSLShader gDeferredTreeProgram; extern LLGLSLShader gDeferredLightProgram; extern LLGLSLShader gDeferredMultiLightProgram; -extern LLGLSLShader gDeferredSpotLightProgram; -extern LLGLSLShader gDeferredMultiSpotLightProgram; extern LLGLSLShader gDeferredSunProgram; -extern LLGLSLShader gDeferredGIProgram; extern LLGLSLShader gDeferredBlurLightProgram; extern LLGLSLShader gDeferredAvatarProgram; extern LLGLSLShader gDeferredSoftenProgram; extern LLGLSLShader gDeferredShadowProgram; -extern LLGLSLShader gDeferredPostGIProgram; -extern LLGLSLShader gDeferredPostProgram; extern LLGLSLShader gDeferredAvatarShadowProgram; extern LLGLSLShader gDeferredAlphaProgram; extern LLGLSLShader gDeferredFullbrightProgram; extern LLGLSLShader gDeferredAvatarAlphaProgram; -extern LLGLSLShader gLuminanceGatherProgram; - //current avatar shader parameter pointer extern GLint gAvatarMatrixParam; diff --git a/linden/indra/newview/llviewerstats.h b/linden/indra/newview/llviewerstats.h index 9107ad6..b176632 100644 --- a/linden/indra/newview/llviewerstats.h +++ b/linden/indra/newview/llviewerstats.h @@ -196,7 +196,7 @@ private: F64 mLastTimeDiff; // used for time stat updates }; -static const F32 SEND_STATS_PERIOD = 3000.0f; +static const F32 SEND_STATS_PERIOD = 300.0f; // The following are from (older?) statistics code found in appviewer. void init_statistics(); diff --git a/linden/indra/newview/llviewerwindow.cpp b/linden/indra/newview/llviewerwindow.cpp index 2ed2f37..f4b738f 100644 --- a/linden/indra/newview/llviewerwindow.cpp +++ b/linden/indra/newview/llviewerwindow.cpp @@ -473,27 +473,6 @@ public: ypos += y_inc; - { - std::ostringstream ostr; - ostr << "Shadow error: " << gPipeline.mShadowError; - addText(xpos, ypos, ostr.str()); - ypos += y_inc; - } - - { - std::ostringstream ostr; - ostr << "Shadow FOV: " << gPipeline.mShadowFOV; - addText(xpos, ypos, ostr.str()); - ypos += y_inc; - } - - { - std::ostringstream ostr; - ostr << "Shadow Splits: " << gPipeline.mSunClipPlanes; - addText(xpos, ypos, ostr.str()); - ypos += y_inc; - } - LLVertexBuffer::sBindCount = LLImageGL::sBindCount = LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0; @@ -1351,6 +1330,7 @@ LLViewerWindow::LLViewerWindow( // Init the image list. Must happen after GL is initialized and before the images that // LLViewerWindow needs are requested. + LLImageGL::initClass(LLViewerImageBoostLevel::MAX_GL_IMAGE_CATEGORY) ; gImageList.init(); LLViewerImage::initClass(); gBumpImageList.init(); @@ -1463,7 +1443,7 @@ void LLViewerWindow::initBase() llassert( !gConsole ); gConsole = new LLConsole( "console", - //gSavedSettings.getS32("ConsoleBufferSize"), + gSavedSettings.getS32("ConsoleBufferSize"), getChatConsoleRect(), gSavedSettings.getS32("ChatFontSize"), gSavedSettings.getF32("ChatPersistTime") ); @@ -2546,6 +2526,7 @@ BOOL LLViewerWindow::handlePerFrameHover() mMouseInWindow = TRUE; } + S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]); S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]); @@ -2570,7 +2551,7 @@ BOOL LLViewerWindow::handlePerFrameHover() mCurrentMouseDelta.set(dx, dy); mouse_vel.setVec((F32) dx, (F32) dy); } - + mMouseVelocityStat.addValue(mouse_vel.magVec()); if (gNoRender) @@ -2833,21 +2814,16 @@ BOOL LLViewerWindow::handlePerFrameHover() gFloaterView->setRect(floater_rect); } - { // snap floaters to top of chat bar/button strip LLView* chatbar_and_buttons = gOverlayBar->getChild<LLView>("chatbar_and_buttons", TRUE); - S32 top, left; - S32 chatbar_and_buttons_x = chatbar_and_buttons->getLocalBoundingRect().mLeft; - S32 chatbar_and_buttons_y = chatbar_and_buttons->getLocalBoundingRect().mTop; - // find top of chatbar and state buttons, if either are visible if (chatbar_and_buttons && !chatbar_and_buttons->getLocalBoundingRect().isNull()) { - // convert top/left corner of chatbar/buttons container to - // gFloaterView-relative coordinates + // convert top/left corner of chatbar/buttons container to gFloaterView-relative coordinates + S32 top, left; chatbar_and_buttons->localPointToOtherView( - chatbar_and_buttons_x, - chatbar_and_buttons_y, + chatbar_and_buttons->getLocalBoundingRect().mLeft, + chatbar_and_buttons->getLocalBoundingRect().mTop, &left, &top, gFloaterView); @@ -2855,9 +2831,10 @@ BOOL LLViewerWindow::handlePerFrameHover() } else if (gToolBar->getVisible()) { + S32 top, left; gToolBar->localPointToOtherView( - chatbar_and_buttons_x, - chatbar_and_buttons_y, + gToolBar->getLocalBoundingRect().mLeft, + gToolBar->getLocalBoundingRect().mTop, &left, &top, gFloaterView); @@ -2867,7 +2844,7 @@ BOOL LLViewerWindow::handlePerFrameHover() { gFloaterView->setSnapOffsetBottom(0); } - } + // Always update console LLRect console_rect = getChatConsoleRect(); console_rect.mBottom = gHUDView->getRect().mBottom + getChatConsoleBottomPad(); @@ -2875,8 +2852,8 @@ BOOL LLViewerWindow::handlePerFrameHover() gConsole->setRect(console_rect); } - mLastMousePoint = mCurrentMousePoint; + // last ditch force of edit menu to selection manager if (LLEditMenuHandler::gEditMenuHandler == NULL && LLSelectMgr::getInstance()->getSelection()->getObjectCount()) { @@ -2939,6 +2916,7 @@ BOOL LLViewerWindow::handlePerFrameHover() &gDebugRaycastBinormal); } + // per frame picking - for tooltips and changing cursor over interactive objects static S32 previous_x = -1; static S32 previous_y = -1; @@ -2981,6 +2959,7 @@ BOOL LLViewerWindow::handlePerFrameHover() previous_x = x; previous_y = y; + return handled; } @@ -4078,7 +4057,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei { if(image_width > window_width || image_height > window_height) //need to enlarge the scene { - if (!LLPipeline::sRenderDeferred && gGLManager.mHasFramebufferObject && !show_ui) + if (gGLManager.mHasFramebufferObject && !show_ui) { GLint max_size = 0; glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &max_size); @@ -4167,17 +4146,10 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei else { const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor)); - if (LLPipeline::sRenderDeferred) - { - display(do_rebuild, scale_factor, subfield, FALSE); - } - else - { display(do_rebuild, scale_factor, subfield, TRUE); // Required for showing the GUI in snapshots? See DEV-16350 for details. JC render_ui(scale_factor, subfield); } - } S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width); // handle fractional rows diff --git a/linden/indra/newview/llvlcomposition.cpp b/linden/indra/newview/llvlcomposition.cpp index f96665b..535c504 100644 --- a/linden/indra/newview/llvlcomposition.cpp +++ b/linden/indra/newview/llvlcomposition.cpp @@ -460,10 +460,6 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, } } - if (!texturep->getHasGLTexture()) - { - texturep->createGLTexture(0, raw); - } texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin); LLSurface::sTextureUpdateTime += gen_timer.getElapsedTimeF32(); LLSurface::sTexelsUpdated += (tex_x_end - tex_x_begin) * (tex_y_end - tex_y_begin); diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp index cd90c59..6522a8b 100644 --- a/linden/indra/newview/llvoavatar.cpp +++ b/linden/indra/newview/llvoavatar.cpp @@ -704,7 +704,6 @@ BOOL LLVOAvatar::sDebugInvisible = FALSE; BOOL LLVOAvatar::sShowAttachmentPoints = FALSE; BOOL LLVOAvatar::sShowAnimationDebug = FALSE; BOOL LLVOAvatar::sShowFootPlane = FALSE; -BOOL LLVOAvatar::sShowCollisionVolumes = FALSE; BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE; F32 LLVOAvatar::sLODFactor = 1.f; BOOL LLVOAvatar::sUseImpostors = FALSE; @@ -741,7 +740,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mTyping(FALSE), mMeshValid(FALSE), mVisible(FALSE), - mMeshTexturesDirty(FALSE), mWindFreq(0.f), mRipplePhase( 0.f ), mBelowWater(FALSE), @@ -802,7 +800,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mBakedTextureData[i].mLastTextureIndex = IMG_DEFAULT_AVATAR; mBakedTextureData[i].mTexLayerSet = NULL; mBakedTextureData[i].mIsLoaded = false; - //mBakedTextureData[i].mIsUsed = false; // KL SG + mBakedTextureData[i].mIsUsed = false; mBakedTextureData[i].mMaskTexName = 0; mBakedTextureData[i].mTextureIndex = getTextureIndex((EBakedTextureIndex)i); } @@ -858,11 +856,9 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mRippleTimeLast = 0.f; mShadowImagep = gImageList.getImageFromFile("foot_shadow.j2c"); - - // GL NOT ACTIVE HERE - //gGL.getTexUnit(0)->bind(mShadowImagep.get()); - //mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP); - + gGL.getTexUnit(0)->bind(mShadowImagep.get()); + mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP); + mInAir = FALSE; mStepOnLand = TRUE; @@ -1299,7 +1295,7 @@ void LLVOAvatar::resetImpostors() // static void LLVOAvatar::deleteCachedImages(bool clearAll) { -/* if(gAuditTexture) +if(gAuditTexture) { S32 total_tex_size = sScratchTexBytes ; S32 tex_size = SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT ; @@ -1341,7 +1337,7 @@ void LLVOAvatar::deleteCachedImages(bool clearAll) total_tex_size -= 4 * tex_size ; } } -*/ + if (LLTexLayerSet::sHasCaches) { lldebugs << "Deleting layer set caches" << llendl; @@ -1866,11 +1862,6 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) return TRUE; } -LLVOAvatar* LLVOAvatar::asAvatar() // KL SD -{ - return this; -} - //----------------------------------------------------------------------------- // LLVOAvatar::startDefaultMotions() //----------------------------------------------------------------------------- @@ -1933,7 +1924,7 @@ void LLVOAvatar::buildCharacter() LLTimer timer; BOOL status = loadAvatar(); - // stop_glerror(); + stop_glerror(); if (gNoRender) { @@ -2043,7 +2034,7 @@ void LLVOAvatar::buildCharacter() processAnimationStateChanges(); mIsBuilt = TRUE; -// stop_glerror(); + stop_glerror(); //------------------------------------------------------------------------- // build the attach and detach menus @@ -5050,7 +5041,7 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color) //------------------------------------------------------------------------ // LLVOAvatar::updateTextures() //------------------------------------------------------------------------ -void LLVOAvatar::updateTextures(LLAgent &agent) // KL SD version +void LLVOAvatar::updateTextures() { BOOL render_avatar = TRUE; @@ -5069,7 +5060,6 @@ void LLVOAvatar::updateTextures(LLAgent &agent) // KL SD version } std::vector<bool> layer_baked; - // GL NOT ACTIVE HERE - *TODO for (U32 i = 0; i < mBakedTextureData.size(); i++) { layer_baked.push_back(isTextureDefined(mBakedTextureData[i].mTextureIndex)); @@ -5152,7 +5142,13 @@ void LLVOAvatar::updateTextures(LLAgent &agent) // KL SD version if (texture_dict->mIsLocalTexture) { addLocalTextureStats((ETextureIndex)index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]); + // SNOW-8 : temporary snowglobe1.0 fix for baked textures + if (render_avatar && !gGLManager.mIsDisabled ) + { + // bind the texture so that its boost level won't be slammed + gGL.getTexUnit(0)->bind(imagep); } + } else if (texture_dict->mIsBakedTexture) { if (layer_baked[baked_index]) @@ -5398,7 +5394,7 @@ void LLVOAvatar::processAnimationStateChanges() } } - //stop_glerror(); + stop_glerror(); } @@ -6383,15 +6379,6 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline) } -void LLVOAvatar::updateGL() -{ - if (mMeshTexturesDirty) - { - updateMeshTextures(); - mMeshTexturesDirty = FALSE; - } -} - //----------------------------------------------------------------------------- // updateGeometry() //----------------------------------------------------------------------------- @@ -7429,20 +7416,12 @@ BOOL LLVOAvatar::bindScratchTexture( LLGLenum format ) if( *last_bind_time != LLImageGL::sLastFrameTime ) { *last_bind_time = LLImageGL::sLastFrameTime; -// #if !LL_RELEASE_FOR_DOWNLOAD -// LLImageGL::updateBoundTexMem(texture_bytes, SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT) ; -// #else - LLImageGL::updateBoundTexMem(texture_bytes); -// #endif + LLImageGL::updateBoundTexMemStatic(texture_bytes, SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; } } else { -// #if !LL_RELEASE_FOR_DOWNLOAD -// LLImageGL::updateBoundTexMem(texture_bytes, SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT) ; -// #else - LLImageGL::updateBoundTexMem(texture_bytes); -// #endif + LLImageGL::updateBoundTexMemStatic(texture_bytes, SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; LLVOAvatar::sScratchTexLastBindTime.addData( format, new F32(LLImageGL::sLastFrameTime) ); } @@ -7464,8 +7443,7 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes ) { case GL_LUMINANCE: components = 1; internal_format = GL_LUMINANCE8; break; case GL_ALPHA: components = 1; internal_format = GL_ALPHA8; break; -// Support for GL_EXT_paletted_texture is deprecated -// case GL_COLOR_INDEX: components = 1; internal_format = GL_COLOR_INDEX8_EXT; break; + case GL_COLOR_INDEX: components = 1; internal_format = GL_COLOR_INDEX8_EXT; break; case GL_LUMINANCE_ALPHA: components = 2; internal_format = GL_LUMINANCE8_ALPHA8; break; case GL_RGB: components = 3; internal_format = GL_RGB8; break; case GL_RGBA: components = 4; internal_format = GL_RGBA8; break; @@ -7507,11 +7485,11 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes ) LLVOAvatar::sScratchTexBytes += *texture_bytes; LLImageGL::sGlobalTextureMemoryInBytes += *texture_bytes; -/* + if(gAuditTexture) { LLImageGL::incTextureCounterStatic(SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT, components, LLViewerImageBoostLevel::AVATAR_SCRATCH_TEX) ; - }*/ + } return name; } @@ -7614,7 +7592,6 @@ void LLVOAvatar::updateMeshTextures() use_lkg_baked_layer[i] = (!is_layer_baked[i] && (mBakedTextureData[i].mLastTextureIndex != IMG_DEFAULT_AVATAR) && mBakedTextureData[i].mTexLayerSet - && mBakedTextureData[i].mTexLayerSet->getComposite() // KL SD && !mBakedTextureData[i].mTexLayerSet->getComposite()->isInitialized()); if (use_lkg_baked_layer[i]) { @@ -7648,7 +7625,7 @@ void LLVOAvatar::updateMeshTextures() if (use_lkg_baked_layer[i] && !self_customizing ) { LLViewerImage* baked_img = gImageList.getImageFromHost( mBakedTextureData[i].mLastTextureIndex, target_host ); - //mBakedTextureData[i].mIsUsed = TRUE; + mBakedTextureData[i].mIsUsed = TRUE; for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++) { mBakedTextureData[i].mMeshes[k]->setTexture( baked_img ); @@ -7678,7 +7655,7 @@ void LLVOAvatar::updateMeshTextures() { mBakedTextureData[i].mTexLayerSet->createComposite(); mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( TRUE ); - // mBakedTextureData[i].mIsUsed = FALSE; + mBakedTextureData[i].mIsUsed = FALSE; for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++) { mBakedTextureData[i].mMeshes[k]->setLayerSet( mBakedTextureData[i].mTexLayerSet ); @@ -7699,13 +7676,9 @@ void LLVOAvatar::updateMeshTextures() mBakedTextureData[BAKED_HAIR].mMeshes[i]->setTexture( hair_img ); } mHasBakedHair = FALSE; - } - else - { - for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++) - { - mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( 1.f, 1.f, 1.f, 1.f ); } + else + { mHasBakedHair = TRUE; } @@ -7837,7 +7810,7 @@ void LLVOAvatar::clearChat() S32 LLVOAvatar::getLocalDiscardLevel( ETextureIndex index ) { // If the texture is not local, we don't care and treat it as fully loaded - if (!isIndexLocalTexture(index)) return FALSE; // KL SD version + if (!isIndexLocalTexture(index)) return 0; LocalTextureData &local_tex_data = mLocalTextureData[index]; if (index >= 0 @@ -7979,7 +7952,7 @@ bool LLVOAvatar::hasPendingBakedUploads() { for (U32 i = 0; i < mBakedTextureData.size(); i++) { - bool upload_pending = (mBakedTextureData[i].mTexLayerSet && mBakedTextureData[i].mTexLayerSet->getComposite() && mBakedTextureData[i].mTexLayerSet->getComposite()->uploadPending()); + bool upload_pending = (mBakedTextureData[i].mTexLayerSet && mBakedTextureData[i].mTexLayerSet->getComposite()->uploadPending()); if (upload_pending) { return true; @@ -8514,8 +8487,7 @@ void LLVOAvatar::onFirstTEMessageReceived() } } - mMeshTexturesDirty = TRUE; // updateMeshTextures(); - gPipeline.markGLRebuild(this); + updateMeshTextures(); } } @@ -8578,22 +8550,20 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // (isTextureDefined(TEX_SKIRT_BAKED) ? "SKIRT " : "skirt " ) << (getTEImage(TEX_SKIRT_BAKED)->getID()) << std::endl << // (isTextureDefined(TEX_HAIR_BAKED) ? "HAIR" : "hair " ) << (getTEImage(TEX_HAIR_BAKED)->getID()) << std::endl << // (isTextureDefined(TEX_EYES_BAKED) ? "EYES" : "eyes" ) << (getTEImage(TEX_EYES_BAKED)->getID()) << llendl ; - + if( !mFirstTEMessageReceived ) { onFirstTEMessageReceived(); } setCompositeUpdatesEnabled( FALSE ); - mMeshTexturesDirty = TRUE; - gPipeline.markGLRebuild(this); // KL SD needing work in S19? if (!mIsSelf) { releaseUnnecessaryTextures(); } - - //updateMeshTextures(); // enables updates for laysets without baked textures. + + updateMeshTextures(); // enables updates for laysets without baked textures. // parse visual params S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam); @@ -8879,7 +8849,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) if (id == image_baked->getID()) { mBakedTextureData[i].mIsLoaded = true; - //mBakedTextureData[i].mIsUsed = true; + mBakedTextureData[i].mIsUsed = true; mBakedTextureData[i].mLastTextureIndex = id; for (U32 k = 0; k < mBakedTextureData[i].mMeshes.size(); k++) { @@ -9788,9 +9758,9 @@ BOOL LLVOAvatar::updateLOD() LLFace* facep = mDrawable->getFace(0); if (facep->mVertexBuffer.isNull() || - (LLVertexBuffer::sEnableVBOs && + LLVertexBuffer::sEnableVBOs && ((facep->mVertexBuffer->getUsage() == GL_STATIC_DRAW ? TRUE : FALSE) != - (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE)))) + (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE))) { mDirtyMesh = TRUE; } diff --git a/linden/indra/newview/llvoavatar.h b/linden/indra/newview/llvoavatar.h index ff07d81..0c32244 100644 --- a/linden/indra/newview/llvoavatar.h +++ b/linden/indra/newview/llvoavatar.h @@ -88,8 +88,6 @@ public: /*virtual*/ void markDead(); void startDefaultMotions(); - /*virtual*/ LLVOAvatar* asAvatar(); // KL SD - static void updateImpostors(); //-------------------------------------------------------------------- @@ -139,7 +137,7 @@ public: LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point ); - /*virtual*/ void updateTextures(LLAgent &agent); // KL SD + /*virtual*/ void updateTextures(); // If setting a baked texture, need to request it from a non-local sim. /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid); /*virtual*/ void onShift(const LLVector3& shift_vector); @@ -157,8 +155,6 @@ public: /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); - /*virtual*/ void updateGL(); - /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); BOOL updateJointLODs(); @@ -478,7 +474,6 @@ private: LLFrameTimer mTypingTimer; //-------------------------------------------------------------------- - BOOL mMeshTexturesDirty; // wind rippling in clothes //-------------------------------------------------------------------- public: @@ -575,7 +570,6 @@ public: static BOOL sShowAnimationDebug; // show animation debug info static BOOL sUseImpostors; //use impostors for far away avatars static BOOL sShowFootPlane; // show foot collision plane reported by server - static BOOL sShowCollisionVolumes; // show skeletal collision volumes // KL SD static BOOL sVisibleInFirstPerson; static S32 sNumLODChangesThisFrame; static S32 sNumVisibleChatBubbles; @@ -777,7 +771,7 @@ private: LLUUID mLastTextureIndex; LLTexLayerSet* mTexLayerSet; bool mIsLoaded; - //bool mIsUsed; // KL SG + bool mIsUsed; LLVOAvatarDefines::ETextureIndex mTextureIndex; U32 mMaskTexName; // Stores pointers to the joint meshes that this baked texture deals with diff --git a/linden/indra/newview/llvoclouds.cpp b/linden/indra/newview/llvoclouds.cpp index 019b6b4..a489f91 100644 --- a/linden/indra/newview/llvoclouds.cpp +++ b/linden/indra/newview/llvoclouds.cpp @@ -101,7 +101,7 @@ void LLVOClouds::setPixelAreaAndAngle(LLAgent &agent) mPixelArea = 1500*100; } -void LLVOClouds::updateTextures(LLAgent &agent) +void LLVOClouds::updateTextures() { getTEImage(0)->addTextureStats(mPixelArea); } @@ -123,10 +123,7 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) return TRUE; } - if (drawable->isVisible()) - { - dirtySpatialGroup(TRUE); - } + dirtySpatialGroup(); LLFace *facep; diff --git a/linden/indra/newview/llvoclouds.h b/linden/indra/newview/llvoclouds.h index f70ea5b..52e5a68 100644 --- a/linden/indra/newview/llvoclouds.h +++ b/linden/indra/newview/llvoclouds.h @@ -65,7 +65,7 @@ public: /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. F32 getPartSize(S32 idx); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area void updateFaceSize(S32 idx) { } diff --git a/linden/indra/newview/llvograss.cpp b/linden/indra/newview/llvograss.cpp index 8f4c0de..f738872 100644 --- a/linden/indra/newview/llvograss.cpp +++ b/linden/indra/newview/llvograss.cpp @@ -337,7 +337,7 @@ void LLVOGrass::setPixelAreaAndAngle(LLAgent &agent) // BUG could speed this up by caching the relative_position and range calculations -void LLVOGrass::updateTextures(LLAgent &agent) +void LLVOGrass::updateTextures() { if (getTEImage(0)) { diff --git a/linden/indra/newview/llvograss.h b/linden/indra/newview/llvograss.h index 86e4b95..25fa04c 100644 --- a/linden/indra/newview/llvograss.h +++ b/linden/indra/newview/llvograss.h @@ -72,7 +72,7 @@ public: LLStrider<U16>& indicesp); void updateFaceSize(S32 idx) { } - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ BOOL updateLOD(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area diff --git a/linden/indra/newview/llvoground.cpp b/linden/indra/newview/llvoground.cpp index fe19e18..0ef0196 100644 --- a/linden/indra/newview/llvoground.cpp +++ b/linden/indra/newview/llvoground.cpp @@ -71,7 +71,7 @@ BOOL LLVOGround::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) } -void LLVOGround::updateTextures(LLAgent &agent) +void LLVOGround::updateTextures() { } diff --git a/linden/indra/newview/llvoground.h b/linden/indra/newview/llvoground.h index f485bd0..b58ebae 100644 --- a/linden/indra/newview/llvoground.h +++ b/linden/indra/newview/llvoground.h @@ -51,7 +51,7 @@ public: // Graphical stuff for objects - maybe broken out into render class // later? - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/linden/indra/newview/llvopartgroup.cpp b/linden/indra/newview/llvopartgroup.cpp index b040366..a0f8068 100644 --- a/linden/indra/newview/llvopartgroup.cpp +++ b/linden/indra/newview/llvopartgroup.cpp @@ -108,7 +108,7 @@ void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent) } } -void LLVOPartGroup::updateTextures(LLAgent &agent) +void LLVOPartGroup::updateTextures() { // Texture stats for particles need to be updated in a different way... } @@ -154,11 +154,6 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) group = drawable->getSpatialGroup(); } - if (group && group->isVisible()) - { - dirtySpatialGroup(TRUE); - } - if (!num_parts) { if (group && drawable->getNumFaces()) @@ -191,12 +186,13 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) S32 count=0; mDepth = 0.f; S32 i = 0 ; + LLVector3 camera_agent = getCameraPosition(); for (i = 0 ; i < (S32)mViewerPartGroupp->mParticles.size(); i++) { const LLViewerPart *part = mViewerPartGroupp->mParticles[i]; LLVector3 part_pos_agent(part->mPosAgent); - LLVector3 at(part_pos_agent - LLViewerCamera::getInstance()->getOrigin()); + LLVector3 at(part_pos_agent - camera_agent); F32 camera_dist_squared = at.lengthSquared(); F32 inv_camera_dist_squared; @@ -319,7 +315,7 @@ void LLVOPartGroup::getGeometry(S32 idx, up *= 0.5f*part.mScale.mV[1]; - const LLVector3& normal = -LLViewerCamera::getInstance()->getXAxis(); + LLVector3 normal = -LLViewerCamera::getInstance()->getXAxis(); *verticesp++ = part_pos_agent + up - right; *verticesp++ = part_pos_agent - up - right; @@ -356,12 +352,12 @@ U32 LLVOPartGroup::getPartitionType() const } LLParticlePartition::LLParticlePartition() -: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB) +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK) { mRenderPass = LLRenderPass::PASS_ALPHA; mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES; mPartitionType = LLViewerRegion::PARTITION_PARTICLE; - // mBufferUsage = GL_DYNAMIC_DRAW_ARB; // KL SD hybrid code + mBufferUsage = GL_DYNAMIC_DRAW_ARB; mSlopRatio = 0.f; mLODPeriod = 1; } @@ -485,9 +481,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) U32 end = start + facep->getGeomCount()-1; U32 offset = facep->getIndicesStart(); U32 count = facep->getIndicesCount(); - LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), - facep->getTexture(), - buffer, fullbright); + LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), buffer, fullbright); info->mExtents[0] = group->mObjectExtents[0]; info->mExtents[1] = group->mObjectExtents[1]; info->mVSize = vsize; diff --git a/linden/indra/newview/llvopartgroup.h b/linden/indra/newview/llvopartgroup.h index 3dc3292..18583b4 100644 --- a/linden/indra/newview/llvopartgroup.h +++ b/linden/indra/newview/llvopartgroup.h @@ -61,7 +61,7 @@ public: virtual U32 getPartitionType() const; /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/linden/indra/newview/llvosky.cpp b/linden/indra/newview/llvosky.cpp index 817a510..8639b60 100644 --- a/linden/indra/newview/llvosky.cpp +++ b/linden/indra/newview/llvosky.cpp @@ -293,7 +293,7 @@ void LLSkyTex::create(const F32 brightness) void LLSkyTex::createGLImage(S32 which) { - mImageGL[which]->createGLTexture(0, mImageRaw[which]); + mImageGL[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLViewerImageBoostLevel::OTHER); mImageGL[which]->setAddressMode(LLTexUnit::TAM_CLAMP); } @@ -1102,10 +1102,10 @@ BOOL LLVOSky::updateSky() mLastTotalAmbient.mV[2] - mTotalAmbient.mV[2]); if ( mForceUpdate - || (((dot_lighting < LIGHT_DIRECTION_THRESHOLD) + || ((dot_lighting < LIGHT_DIRECTION_THRESHOLD) || (delta_color.length() > COLOR_CHANGE_THRESHOLD) || !mInitialized) - && !direction.isExactlyZero())) + && !direction.isExactlyZero()) { mLastLightingDirection = direction; mLastTotalAmbient = mTotalAmbient; @@ -1187,7 +1187,7 @@ BOOL LLVOSky::updateSky() return TRUE; } -void LLVOSky::updateTextures(LLAgent &agent) +void LLVOSky::updateTextures() { if (mSunTexturep) { diff --git a/linden/indra/newview/llvosky.h b/linden/indra/newview/llvosky.h index 492557f..1370824 100644 --- a/linden/indra/newview/llvosky.h +++ b/linden/indra/newview/llvosky.h @@ -493,7 +493,7 @@ public: // Graphical stuff for objects - maybe broken out into render class // later? - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/linden/indra/newview/llvosurfacepatch.cpp b/linden/indra/newview/llvosurfacepatch.cpp index 7aa5739..1671880 100644 --- a/linden/indra/newview/llvosurfacepatch.cpp +++ b/linden/indra/newview/llvosurfacepatch.cpp @@ -134,7 +134,7 @@ void LLVOSurfacePatch::setPixelAreaAndAngle(LLAgent &agent) } -void LLVOSurfacePatch::updateTextures(LLAgent &agent) +void LLVOSurfacePatch::updateTextures() { } @@ -177,19 +177,11 @@ LLDrawable *LLVOSurfacePatch::createDrawable(LLPipeline *pipeline) } -void LLVOSurfacePatch::updateGL() -{ - if (mPatchp) - { - mPatchp->updateGL(); - } -} - BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) { LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TERRAIN); - dirtySpatialGroup(TRUE); + dirtySpatialGroup(); S32 min_comp, max_comp, range; min_comp = lltrunc(mPatchp->getMinComposition()); @@ -1021,12 +1013,12 @@ U32 LLVOSurfacePatch::getPartitionType() const } LLTerrainPartition::LLTerrainPartition() -: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, GL_DYNAMIC_DRAW_ARB) +: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK) { mOcclusionEnabled = FALSE; - //mRenderByGroup = FALSE; // KL not for SD hybrid code + mRenderByGroup = FALSE; mInfiniteFarClip = TRUE; - //mBufferUsage = GL_DYNAMIC_DRAW_ARB; // and here too! + mBufferUsage = GL_DYNAMIC_DRAW_ARB; mDrawableType = LLPipeline::RENDER_TYPE_TERRAIN; mPartitionType = LLViewerRegion::PARTITION_TERRAIN; } diff --git a/linden/indra/newview/llvosurfacepatch.h b/linden/indra/newview/llvosurfacepatch.h index aaf4d41..d3b1447 100644 --- a/linden/indra/newview/llvosurfacepatch.h +++ b/linden/indra/newview/llvosurfacepatch.h @@ -64,7 +64,6 @@ public: virtual U32 getPartitionType() const; /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); - /*virtual*/ void updateGL(); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ BOOL updateLOD(); /*virtual*/ void updateFaceSize(S32 idx); @@ -75,7 +74,7 @@ public: LLStrider<LLVector2> &texCoords1p, LLStrider<U16> &indicesp); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); diff --git a/linden/indra/newview/llvotextbubble.cpp b/linden/indra/newview/llvotextbubble.cpp index de69aac..5943f9b 100644 --- a/linden/indra/newview/llvotextbubble.cpp +++ b/linden/indra/newview/llvotextbubble.cpp @@ -116,7 +116,7 @@ BOOL LLVOTextBubble::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) } -void LLVOTextBubble::updateTextures(LLAgent &agent) +void LLVOTextBubble::updateTextures() { // Update the image levels of all textures... diff --git a/linden/indra/newview/llvotextbubble.h b/linden/indra/newview/llvotextbubble.h index 45d4df2..7f84dbf 100644 --- a/linden/indra/newview/llvotextbubble.h +++ b/linden/indra/newview/llvotextbubble.h @@ -44,7 +44,7 @@ public: /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ BOOL updateLOD(); diff --git a/linden/indra/newview/llvotree.cpp b/linden/indra/newview/llvotree.cpp index 9ec002d..6a59253 100644 --- a/linden/indra/newview/llvotree.cpp +++ b/linden/indra/newview/llvotree.cpp @@ -482,7 +482,7 @@ void LLVOTree::setPixelAreaAndAngle(LLAgent &agent) #endif } -void LLVOTree::updateTextures(LLAgent &agent) +void LLVOTree::updateTextures() { if (mTreeImagep) { @@ -1318,9 +1318,9 @@ U32 LLVOTree::getPartitionType() const } LLTreePartition::LLTreePartition() -: LLSpatialPartition(0, FALSE, 0) +: LLSpatialPartition(0) { - // mRenderByGroup = FALSE; // SD hybrid + mRenderByGroup = FALSE; mDrawableType = LLPipeline::RENDER_TYPE_TREE; mPartitionType = LLViewerRegion::PARTITION_TREE; mSlopRatio = 0.f; diff --git a/linden/indra/newview/llvotree.h b/linden/indra/newview/llvotree.h index 7804ab3..855c612 100644 --- a/linden/indra/newview/llvotree.h +++ b/linden/indra/newview/llvotree.h @@ -69,7 +69,7 @@ public: // Graphical stuff for objects - maybe broken out into render class later? /*virtual*/ void render(LLAgent &agent); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/linden/indra/newview/llvotreenew.h b/linden/indra/newview/llvotreenew.h index 02f6d3a..4960d90 100644 --- a/linden/indra/newview/llvotreenew.h +++ b/linden/indra/newview/llvotreenew.h @@ -156,7 +156,7 @@ public: /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); /*virtual*/ void render(LLAgent &agent); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); diff --git a/linden/indra/newview/llvovolume.cpp b/linden/indra/newview/llvovolume.cpp index 77c9c33..13a0704 100644 --- a/linden/indra/newview/llvovolume.cpp +++ b/linden/indra/newview/llvovolume.cpp @@ -54,7 +54,6 @@ #include "llspatialpartition.h" #include "llhudmanager.h" #include "llflexibleobject.h" - #include "llsky.h" #include "lltexturefetch.h" #include "llviewercamera.h" @@ -68,9 +67,6 @@ const S32 MIN_QUIET_FRAMES_COALESCE = 30; const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; const F32 FORCE_CULL_AREA = 8.f; -const F32 MAX_LOD_DISTANCE = 24.f; -const S32 MAX_SCULPT_REZ = 128; - BOOL gAnimateTextures = TRUE; extern BOOL gHideSelectedObjects; @@ -95,7 +91,6 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mNumFaces = 0; mLODChanged = FALSE; mSculptChanged = FALSE; - mSpotLightPriority = 0.f; } LLVOVolume::~LLVOVolume() @@ -219,7 +214,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, std::string mask; mask = gDirUtilp->getDirDelimiter() + "*.slc"; gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), mask); -// llwarns << "Bogus TE data in " << getID() << ", crashing!" << llendl; +// llerrs << "Bogus TE data in " << getID() << ", crashing!" << llendl; llwarns << "Bogus TE data in " << getID() << llendl; } else if (res2 & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR)) @@ -319,6 +314,11 @@ void LLVOVolume::animateTextures() te->getScale(&scale_s, &scale_t); } + LLVector3 scale(scale_s, scale_t, 1.f); + LLVector3 trans(off_s+0.5f, off_t+0.5f, 0.f); + LLQuaternion quat; + quat.setQuat(rot, 0, 0, -1.f); + if (!facep->mTextureMatrix) { facep->mTextureMatrix = new LLMatrix4(); @@ -326,43 +326,7 @@ void LLVOVolume::animateTextures() LLMatrix4& tex_mat = *facep->mTextureMatrix; tex_mat.setIdentity(); - LLVector3 trans ; - - if(facep->isAtlasInUse()) - { - // - //if use atlas for animated texture - //apply the following transform to the animation matrix. - // - - F32 tcoord_xoffset = 0.f ; - F32 tcoord_yoffset = 0.f ; - F32 tcoord_xscale = 1.f ; - F32 tcoord_yscale = 1.f ; - if(facep->isAtlasInUse()) - { - const LLVector2* tmp = facep->getTexCoordOffset() ; - tcoord_xoffset = tmp->mV[0] ; - tcoord_yoffset = tmp->mV[1] ; - - tmp = facep->getTexCoordScale() ; - tcoord_xscale = tmp->mV[0] ; - tcoord_yscale = tmp->mV[1] ; - } - trans.set(LLVector3(tcoord_xoffset + tcoord_xscale * (off_s+0.5f), tcoord_yoffset + tcoord_yscale * (off_t+0.5f), 0.f)); - - tex_mat.translate(LLVector3(-(tcoord_xoffset + tcoord_xscale * 0.5f), -(tcoord_yoffset + tcoord_yscale * 0.5f), 0.f)); - } - else //non atlas - { - trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); - tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); - } - - LLVector3 scale(scale_s, scale_t, 1.f); - LLQuaternion quat; - quat.setQuat(rot, 0, 0, -1.f); - + tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); tex_mat.rotate(quat); LLMatrix4 mat; @@ -439,28 +403,30 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) return TRUE; } -void LLVOVolume::updateTextures(LLAgent &agent) // KL sd +void LLVOVolume::updateTextures() { const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds - if (mDrawable.notNull() && mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) + if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) { - if (mDrawable->isVisible()) - { - updateTextures(); - } + updateTextureVirtualSize(); } } -void LLVOVolume::updateTextures() +void LLVOVolume::updateTextureVirtualSize() { // Update the pixel area of all faces + if(mDrawable.isNull() || !mDrawable->isVisible()) + { + return ; + } + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) { return; } - if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull()) // || !mDrawable->isVisible()) + if (LLViewerImage::sDontLoadVolumeTextures || LLAppViewer::getTextureFetch()->mDebugPause) { return; } @@ -477,14 +443,15 @@ void LLVOVolume::updateTextures() LLFace* face = mDrawable->getFace(i); const LLTextureEntry *te = face->getTextureEntry(); LLViewerImage *imagep = face->getTexture(); - if (!imagep || !te || + if (!imagep || !te || face->mExtents[0] == face->mExtents[1]) { continue; } F32 vsize; - + F32 old_size = face->getVirtualSize(); + if (isHUDAttachment()) { F32 area = (F32) LLViewerCamera::getInstance()->getScreenPixelArea(); @@ -494,24 +461,21 @@ void LLVOVolume::updateTextures() } else { - vsize = getTextureVirtualSize(face); + vsize = face->getTextureVirtualSize(); } - mPixelArea = llmax(mPixelArea, face->getPixelArea()); - - F32 old_size = face->getVirtualSize(); + mPixelArea = llmax(mPixelArea, face->getPixelArea()); if (face->mTextureMatrix != NULL) { - if (vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE || - vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE) + if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || + (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE); } } face->setVirtualSize(vsize); - // imagep->addTextureStats(vsize); if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { if (vsize < min_vsize) min_vsize = vsize; @@ -539,46 +503,46 @@ void LLVOVolume::updateTextures() mSculptTexture = gImageList.getImage(id); if (mSculptTexture.notNull()) { - S32 lod = llmin(mLOD, 3); - F32 lodf = ((F32)(lod + 1.0f)/4.f); - F32 tex_size = lodf * MAX_SCULPT_REZ; - mSculptTexture->addTextureStats(2.f * tex_size * tex_size); mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), (S32)LLViewerImageBoostLevel::BOOST_SCULPTED)); - } - - S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture - S32 current_discard = mSculptLevel; + mSculptTexture->setForSculpt() ; + + if(!mSculptTexture->isCachedRawImageReady()) + { + S32 lod = llmin(mLOD, 3); + F32 lodf = ((F32)(lod + 1.0f)/4.f); + F32 tex_size = lodf * LLViewerImage::sMaxSculptRez ; + mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); + + //if the sculpty very close to the view point, load first + { + LLVector3 lookAt = getPositionAgent() - LLViewerCamera::getInstance()->getOrigin(); + F32 dist = lookAt.normVec() ; + F32 cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ; + mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ; + } + } + + S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture + S32 current_discard = mSculptLevel; - if (texture_discard >= 0 && //texture has some data available - (texture_discard < current_discard || //texture has more data than last rebuild - current_discard < 0)) //no previous rebuild - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - mSculptChanged = TRUE; - } + if (texture_discard >= 0 && //texture has some data available + (texture_discard < current_discard || //texture has more data than last rebuild + current_discard < 0)) //no previous rebuild + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); + mSculptChanged = TRUE; + } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) { setDebugText(llformat("T%d C%d V%d\n%dx%d", - texture_discard, current_discard, getVolume()->getSculptLevel(), - mSculptTexture->getHeight(), mSculptTexture->getWidth())); + texture_discard, current_discard, getVolume()->getSculptLevel(), + mSculptTexture->getHeight(), mSculptTexture->getWidth())); } + } } - if (getLightTextureID().notNull()) - { - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - LLUUID id = params->getLightTexture(); - mLightTexture = gImageList.getImage(id); - if (mLightTexture.notNull()) - { - F32 rad = getLightRadius(); - mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(), - LLVector3(rad,rad,rad), - *LLViewerCamera::getInstance())); - } - } if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { @@ -599,36 +563,6 @@ void LLVOVolume::updateTextures() } } -F32 LLVOVolume::getTextureVirtualSize(LLFace* face) -{ - //get area of circle around face - LLVector3 center = face->getPositionAgent(); - LLVector3 size = (face->mExtents[1] - face->mExtents[0]) * 0.5f; - - F32 face_area = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance()); - - face->setPixelArea(face_area); - - if (face_area <= 0) - { - return 0.f; - } - - //get area of circle in texture space - LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0]; - F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f; - if (texel_area <= 0) - { - // Probably animated, use default - texel_area = 1.f; - } - - //apply texel area to face area to get accurate ratio - face_area /= llclamp(texel_area, 1.f/64.f, 16.f); - - return face_area; -} - BOOL LLVOVolume::isActive() const { return !mStatic || mTextureAnimp || (mVolumeImpl && mVolumeImpl->isActive()); @@ -765,31 +699,21 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail // sculpt replaces generate() for sculpted surfaces void LLVOVolume::sculpt() -{ - U16 sculpt_height = 0; - U16 sculpt_width = 0; - S8 sculpt_components = 0; - const U8* sculpt_data = NULL; - +{ if (mSculptTexture.notNull()) - { - S32 discard_level; - S32 desired_discard = 0; // lower discard levels have MUCH less resolution - - discard_level = desired_discard; + { + U16 sculpt_height = 0; + U16 sculpt_width = 0; + S8 sculpt_components = 0; + const U8* sculpt_data = NULL; + + S32 discard_level = mSculptTexture->getCachedRawImageLevel() ; + LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; S32 max_discard = mSculptTexture->getMaxDiscardLevel(); if (discard_level > max_discard) discard_level = max_discard; // clamp to the best we can do - S32 best_discard = mSculptTexture->getDiscardLevel(); - if (discard_level < best_discard) - discard_level = best_discard; // clamp to what we have - - if (best_discard == -1) - discard_level = -1; // and if we have nothing, set to nothing - - S32 current_discard = getVolume()->getSculptLevel(); if(current_discard < -2) { @@ -811,28 +735,17 @@ void LLVOVolume::sculpt() if (current_discard == discard_level) // no work to do here return; - LLPointer<LLImageRaw> raw_image = new LLImageRaw(); - BOOL is_valid = mSculptTexture->readBackRaw(discard_level, raw_image, FALSE); - - sculpt_height = raw_image->getHeight(); - sculpt_width = raw_image->getWidth(); - sculpt_components = raw_image->getComponents(); - - if(is_valid) - { - is_valid = mSculptTexture->isValidForSculpt(discard_level, sculpt_width, sculpt_height, sculpt_components) ; - } - if(!is_valid) + if(!raw_image) { sculpt_width = 0; sculpt_height = 0; sculpt_data = NULL ; } else - { - if (raw_image->getDataSize() < sculpt_height * sculpt_width * sculpt_components) - llwarns << "Sculpt: image data size = " << raw_image->getDataSize() - << " < " << sculpt_height << " x " << sculpt_width << " x " <<sculpt_components << llendl; + { + sculpt_height = raw_image->getHeight(); + sculpt_width = raw_image->getWidth(); + sculpt_components = raw_image->getComponents(); sculpt_data = raw_image->getData(); } @@ -864,7 +777,7 @@ BOOL LLVOVolume::calcLOD() } //update face texture sizes on lod calculation - // updateTextureVirtualSize(); + updateTextureVirtualSize(); S32 cur_detail = 0; @@ -1318,15 +1231,28 @@ S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color) S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) { - S32 res = LLViewerObject::setTEColor(te, color); - if (res && mDrawable.notNull()) + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) { - //gPipeline.markTextured(mDrawable); - mDrawable->setState(LLDrawable::REBUILD_COLOR); - dirtyMesh(); - //mFaceMappingChanged = TRUE; + llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; } - return res; + else if (color != tep->getColor()) + { + if (color.mV[3] != tep->getColor().mV[3]) + { + gPipeline.markTextured(mDrawable); + } + retval = LLPrimitive::setTEColor(te, color); + if (mDrawable.notNull() && retval) + { + // These should only happen on updates which are not the initial update. + mDrawable->setState(LLDrawable::REBUILD_COLOR); + dirtyMesh(); + } + } + + return retval; } S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap) @@ -1392,7 +1318,7 @@ S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump) gPipeline.markTextured(mDrawable); mFaceMappingChanged = TRUE; } - return res; + return res; } S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags) @@ -1461,40 +1387,6 @@ void LLVOVolume::updateTEData() //---------------------------------------------------------------------------- -void LLVOVolume::setLightTextureID(LLUUID id) -{ - if (id.notNull()) - { - if (!hasLightTexture()) - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true); - } - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block && param_block->getLightTexture() != id) - { - param_block->setLightTexture(id); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - } - } - else - { - if (hasLightTexture()) - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); - } - } -} - -void LLVOVolume::setSpotLightParams(LLVector3 params) -{ - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block && param_block->getParams() != params) - { - param_block->setParams(params); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - } -} - void LLVOVolume::setIsLight(BOOL is_light) { if (is_light != getIsLight()) @@ -1621,77 +1513,6 @@ LLColor3 LLVOVolume::getLightColor() const } } -LLUUID LLVOVolume::getLightTextureID() const -{ - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getLightTexture(); - } - - return LLUUID::null; -} - - -LLVector3 LLVOVolume::getSpotLightParams() const -{ - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getParams(); - } - - return LLVector3(); -} - -F32 LLVOVolume::getSpotLightPriority() const -{ - return mSpotLightPriority; -} - -void LLVOVolume::updateSpotLightPriority() -{ - LLVector3 pos = mDrawable->getPositionAgent(); - LLVector3 at(0,0,-1); - at *= getRenderRotation(); - - F32 r = getLightRadius()*0.5f; - - pos += at * r; - - at = LLViewerCamera::getInstance()->getAtAxis(); - - pos -= at * r; - - mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); - // KL needed for S19? - if (mLightTexture.notNull()) - { - mLightTexture->addTextureStats(mSpotLightPriority); - mLightTexture->setBoostLevel(LLViewerImageBoostLevel::BOOST_CLOUDS); - } -} - - -LLViewerImage* LLVOVolume::getLightTexture() -{ - LLUUID id = getLightTextureID(); - - if (id.notNull()) - { - if (mLightTexture.isNull() || id != mLightTexture->getID()) - { - mLightTexture = gImageList.getImage(id); - } - } - else - { - mLightTexture = NULL; - } - - return mLightTexture; -} - F32 LLVOVolume::getLightIntensity() const { const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); @@ -1783,16 +1604,6 @@ BOOL LLVOVolume::isSculpted() const return FALSE; } -BOOL LLVOVolume::hasLightTexture() const -{ - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - return TRUE; - } - - return FALSE; -} - BOOL LLVOVolume::isVolumeGlobal() const { if (mVolumeImpl) @@ -2245,9 +2056,9 @@ U32 LLVOVolume::getPartitionType() const } LLVolumePartition::LLVolumePartition() -: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB) // KL +: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, FALSE) { - mLODPeriod = 32; // KL 32 in SD + mLODPeriod = 16; mDepthMask = FALSE; mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; mPartitionType = LLViewerRegion::PARTITION_VOLUME; @@ -2256,10 +2067,10 @@ LLVolumePartition::LLVolumePartition() } LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep) -: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK) // KL SD +: LLSpatialBridge(drawablep, LLVOVolume::VERTEX_DATA_MASK) { mDepthMask = FALSE; - mLODPeriod = 32; // KL 32 in SD + mLODPeriod = 16; mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; mPartitionType = LLViewerRegion::PARTITION_BRIDGE; @@ -2314,7 +2125,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U8 bump = (type == LLRenderPass::PASS_BUMP ? facep->getTextureEntry()->getBumpmap() : 0); - LLImageGL* tex = facep->getGLTexture(); // LLViewerImage* tex = facep->getTexture(); // KL SD + LLViewerImage* tex = facep->getTexture(); U8 glow = 0; @@ -2325,7 +2136,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, if (facep->mVertexBuffer.isNull()) { - llwarns << "WTF?" << llendl; + llerrs << "WTF?" << llendl; } if (idx >= 0 && @@ -2356,7 +2167,6 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 offset = facep->getIndicesStart(); U32 count = facep->getIndicesCount(); LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset,tex, - (LLImageGL*)facep->getTexture() == tex ? facep->getTexture() : NULL, facep->mVertexBuffer, fullbright, bump); draw_info->mGroup = group; draw_info->mVSize = facep->getVirtualSize(); @@ -2449,11 +2259,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) LLVOVolume* vobj = drawablep->getVOVolume(); llassert_always(vobj); - vobj->updateTextures(); + vobj->updateTextureVirtualSize(); vobj->preRebuild(); - drawablep->clearState(LLDrawable::HAS_ALPHA); // KL SD - //for each face for (S32 i = 0; i < drawablep->getNumFaces(); i++) { @@ -2522,7 +2330,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } else { - drawablep->setState(LLDrawable::HAS_ALPHA); // KL SD alpha_faces.push_back(facep); } } @@ -2546,7 +2353,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } else { //doesn't need normal - //facep->setState(LLFace::FULLBRIGHT); + facep->setState(LLFace::FULLBRIGHT); fullbright_faces.push_back(facep); } } @@ -2556,14 +2363,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //needs normal + binormal bump_faces.push_back(facep); } - else if (te->getShiny() && LLPipeline::sRenderBump || + else if ((te->getShiny() && LLPipeline::sRenderBump) || !te->getFullbright()) { //needs normal simple_faces.push_back(facep); } else { //doesn't need normal - // facep->setState(LLFace::FULLBRIGHT); + facep->setState(LLFace::FULLBRIGHT); fullbright_faces.push_back(facep); } } @@ -2611,7 +2418,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (LLPipeline::sDelayVBUpdate) { - group->setState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); // KL SD + group->setState(LLSpatialGroup::MESH_DIRTY); } mFaceList.clear(); @@ -2619,7 +2426,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { - if (group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY)) // KL SD + if (group->isState(LLSpatialGroup::MESH_DIRTY)) { S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ; @@ -2697,7 +2504,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) } } - group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); // KL SD + group->clearState(LLSpatialGroup::MESH_DIRTY); } } @@ -2723,7 +2530,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: LLSpatialGroup::buffer_map_t buffer_map; - LLImageGL* last_tex = NULL;// LLViewerImage* last_tex = NULL; // KL SD + LLViewerImage* last_tex = NULL; S32 buffer_index = 0; if (distance_sort) @@ -2735,7 +2542,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: { //pull off next face LLFace* facep = *face_iter; - LLImageGL* tex = facep->getGLTexture(); // LLViewerImage* tex = facep->getTexture(); // KL SD + LLViewerImage* tex = facep->getTexture(); if (distance_sort) { @@ -2760,7 +2567,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: ++i; while (i != faces.end() && - (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getGLTexture() == tex))) // KL SD getTexture + (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) { facep = *i; @@ -2843,11 +2650,6 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA; BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); - if ((mask & LLVertexBuffer::MAP_NORMAL) == 0) // KL SD - { //paranoia check to make sure GL doesn't try to read non-existant normals - fullbright = TRUE; - } - const LLTextureEntry* te = facep->getTextureEntry(); BOOL is_alpha = facep->getPoolType() == LLDrawPool::POOL_ALPHA ? TRUE : FALSE; @@ -2899,7 +2701,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } else { - // llassert(mask & LLVertexBuffer::MAP_NORMAL); + llassert(mask & LLVertexBuffer::MAP_NORMAL); registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } } @@ -2930,7 +2732,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } else { - // llassert(mask & LLVertexBuffer::MAP_NORMAL); + llassert(mask & LLVertexBuffer::MAP_NORMAL); registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } } @@ -2943,8 +2745,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: if (!is_alpha && !LLPipeline::sRenderDeferred) { - // llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); - facep->setPoolType(LLDrawPool::POOL_SIMPLE); // facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); + llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); + facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); if (!force_simple && te->getBumpmap()) { @@ -3023,7 +2825,7 @@ LLHUDPartition::LLHUDPartition() mPartitionType = LLViewerRegion::PARTITION_HUD; mDrawableType = LLPipeline::RENDER_TYPE_HUD; mSlopRatio = 0.f; - mLODPeriod = 32; // KL 32 in SD + mLODPeriod = 1; } void LLHUDPartition::shift(const LLVector3 &offset) diff --git a/linden/indra/newview/llvovolume.h b/linden/indra/newview/llvovolume.h index 4c6ad9a..a78aa37 100644 --- a/linden/indra/newview/llvovolume.h +++ b/linden/indra/newview/llvovolume.h @@ -130,7 +130,7 @@ public: BOOL getVolumeChanged() const { return mVolumeChanged; } - F32 getTextureVirtualSize(LLFace* face); + /*virtual*/ F32 getRadius() const { return mVObjRadius; }; const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; @@ -158,14 +158,14 @@ public: /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump); /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny); /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright); - /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump); // KL S19? + /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump); /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags); /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t); /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s); /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t); /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen); - /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media); // KL S19 + /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media); /*virtual*/ BOOL setMaterial(const U8 material); void setTexture(const S32 face); @@ -177,8 +177,8 @@ public: /*virtual*/ void updateFaceSize(S32 idx); /*virtual*/ BOOL updateLOD(); void updateRadius(); - /*virtual*/ void updateTextures(LLAgent &agent); - void updateTextures(); + /*virtual*/ void updateTextures(); + void updateTextureVirtualSize(); void updateFaceFlags(); void regenFaces(); @@ -196,18 +196,9 @@ public: void setLightRadius(F32 radius); void setLightFalloff(F32 falloff); void setLightCutoff(F32 cutoff); - void setLightTextureID(LLUUID id); - void setSpotLightParams(LLVector3 params); - BOOL getIsLight() const; LLColor3 getLightBaseColor() const; // not scaled by intensity LLColor3 getLightColor() const; // scaled by intensity - LLUUID getLightTextureID() const; - LLVector3 getSpotLightParams() const; - void updateSpotLightPriority(); - F32 getSpotLightPriority() const; - - LLViewerImage* getLightTexture(); F32 getLightIntensity() const; F32 getLightRadius() const; F32 getLightFalloff() const; @@ -217,8 +208,6 @@ public: U32 getVolumeInterfaceID() const; virtual BOOL isFlexible() const; virtual BOOL isSculpted() const; - virtual BOOL hasLightTexture() const; - BOOL isVolumeGlobal() const; BOOL canBeFlexible() const; BOOL setIsFlexible(BOOL is_flexible); @@ -244,14 +233,12 @@ private: BOOL mLODChanged; S32 mSculptLevel; BOOL mSculptChanged; - F32 mSpotLightPriority; LLMatrix4 mRelativeXform; LLMatrix3 mRelativeXformInvTrans; BOOL mVolumeChanged; F32 mVObjRadius; LLVolumeInterface *mVolumeImpl; LLPointer<LLViewerImage> mSculptTexture; - LLPointer<LLViewerImage> mLightTexture; // statics public: diff --git a/linden/indra/newview/llvowater.cpp b/linden/indra/newview/llvowater.cpp index 251667c..c66295a 100644 --- a/linden/indra/newview/llvowater.cpp +++ b/linden/indra/newview/llvowater.cpp @@ -101,7 +101,7 @@ void LLVOWater::setPixelAreaAndAngle(LLAgent &agent) // virtual -void LLVOWater::updateTextures(LLAgent &agent) +void LLVOWater::updateTextures() { } @@ -281,9 +281,9 @@ U32 LLVOVoidWater::getPartitionType() const } LLWaterPartition::LLWaterPartition() -: LLSpatialPartition(0, FALSE, 0) +: LLSpatialPartition(0) { - // mRenderByGroup = FALSE; // KL specified const SG branch not req here + mRenderByGroup = FALSE; mInfiniteFarClip = TRUE; mDrawableType = LLPipeline::RENDER_TYPE_WATER; mPartitionType = LLViewerRegion::PARTITION_WATER; diff --git a/linden/indra/newview/llvowater.h b/linden/indra/newview/llvowater.h index de2cb3e..55ce6d7 100644 --- a/linden/indra/newview/llvowater.h +++ b/linden/indra/newview/llvowater.h @@ -69,7 +69,7 @@ public: /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); - /*virtual*/ void updateTextures(LLAgent &agent); + /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area /*virtual*/ U32 getPartitionType() const; diff --git a/linden/indra/newview/llwaterparammanager.cpp b/linden/indra/newview/llwaterparammanager.cpp index 8ef11be..e01506e 100644 --- a/linden/indra/newview/llwaterparammanager.cpp +++ b/linden/indra/newview/llwaterparammanager.cpp @@ -407,7 +407,8 @@ void LLWaterParamManager::update(LLViewerCamera * cam) LLFloaterWater::instance()->syncMenu(); } - //stop_glerror(); + stop_glerror(); + // only do this if we're dealing with shaders if(gPipeline.canUseVertexShaders()) { diff --git a/linden/indra/newview/llwlparammanager.cpp b/linden/indra/newview/llwlparammanager.cpp index 09f7d01..31471d7 100644 --- a/linden/indra/newview/llwlparammanager.cpp +++ b/linden/indra/newview/llwlparammanager.cpp @@ -539,7 +539,8 @@ void LLWLParamManager::update(LLViewerCamera * cam) F32 camYaw = cam->getYaw(); - //stop_glerror(); + stop_glerror(); + // *TODO: potential optimization - this block may only need to be // executed some of the time. For example for water shaders only. { diff --git a/linden/indra/newview/llworld.h b/linden/indra/newview/llworld.h index 62374d5..2c5815c 100644 --- a/linden/indra/newview/llworld.h +++ b/linden/indra/newview/llworld.h @@ -2,7 +2,7 @@ * @file llworld.h * @brief Collection of viewer regions in the vacinity of the user. * - * Represents the whole world, so far as 3D functionality is concerned. + * Represents the whole world, so far as 3D functionality is conserned. * Always contains the region that the user's avatar is in along with * neighboring regions. As the user crosses region boundaries, new * regions are added to the world and distant ones are rolled up. @@ -152,8 +152,7 @@ public: public: typedef std::list<LLViewerRegion*> region_list_t; - region_list_t mActiveRegionList; // KL SD branch public not private - region_list_t& getRegionList() { return mActiveRegionList; } + const region_list_t& getRegionList() const { return mActiveRegionList; } // Returns lists of avatar IDs and their world-space positions within a given distance of a point. // All arguments are optional. Given containers will be emptied and then filled. @@ -164,6 +163,7 @@ public: const LLVector3d& relative_to = LLVector3d(), F32 radius = FLT_MAX) const; private: + region_list_t mActiveRegionList; region_list_t mRegionList; region_list_t mVisibleRegionList; region_list_t mCulledRegionList; diff --git a/linden/indra/newview/pipeline.cpp b/linden/indra/newview/pipeline.cpp index 53d7e49..8dce5cf 100644 --- a/linden/indra/newview/pipeline.cpp +++ b/linden/indra/newview/pipeline.cpp @@ -159,8 +159,6 @@ std::string gPoolNames[] = "POOL_ALPHA", }; -void drawBox(const LLVector3& c, const LLVector3& r); - U32 nhpo2(U32 v) { U32 r = 1; @@ -269,11 +267,11 @@ static const U32 gl_cube_face[] = void validate_framebuffer_object(); - void addDeferredAttachments(LLRenderTarget& target) { - target.addColorAttachment(GL_RGBA); //specular //target.addColorAttachment(GL_RGBA16F_ARB); //specular // KL - target.addColorAttachment(GL_RGBA); //normal+z //target.addColorAttachment(GL_RGBA16F_ARB); //normal+z + target.addColorAttachment(GL_RGBA16F_ARB); //specular + target.addColorAttachment(GL_RGBA16F_ARB); //normal+z + target.addColorAttachment(GL_RGBA16F_ARB); //position } LLPipeline::LLPipeline() : @@ -315,8 +313,6 @@ LLPipeline::LLPipeline() : mLightingDetail(0) { mNoiseMap = 0; - //mTrueNoiseMap = 0; // KL SD - mLightFunc = 0; // KL SD } void LLPipeline::init() @@ -366,11 +362,6 @@ void LLPipeline::init() LLViewerShaderMgr::instance()->setShaders(); stop_glerror(); - - for (U32 i = 0; i < 2; ++i) - { - mSpotLightFade[i] = 1.f; - } } LLPipeline::~LLPipeline() @@ -382,9 +373,6 @@ void LLPipeline::cleanup() { assertInitialized(); - mGroupQ1.clear() ; - mGroupQ2.clear() ; - for(pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ) { @@ -481,69 +469,33 @@ void LLPipeline::resizeScreenTexture() GLuint resX = gViewerWindow->getWindowDisplayWidth(); GLuint resY = gViewerWindow->getWindowDisplayHeight(); - allocateScreenBuffer(resX,resY); - } -} - -void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) -{ - - U32 samples = gSavedSettings.getU32("RenderFSAASamples"); U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor"); - if (res_mod > 1 && res_mod < resX && res_mod < resY) { resX /= res_mod; resY /= res_mod; } - if (gSavedSettings.getBOOL("RenderUIBuffer")) - { - //mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); - } + allocateScreenBuffer(resX,resY); + + llinfos << "RESIZED SCREEN TEXTURE: " << resX << "x" << resY << llendl; + } +} +void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) +{ + U32 samples = gSavedSettings.getU32("RenderFSAASamples"); if (LLPipeline::sRenderDeferred) { //allocate deferred rendering color buffers - mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); - mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + mDeferredScreen.allocate(resX, resY, GL_RGBA16F_ARB, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); addDeferredAttachments(mDeferredScreen); + mScreen.allocate(resX, resY, GL_RGBA16F_ARB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); - // always set viewport to desired size, since allocate resets the viewport - - mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); - - for (U32 i = 0; i < 3; i++) - { - mDeferredLight[i].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); - } - for (U32 i = 0; i < 2; i++) { - mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); - } - - F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale"); - - for (U32 i = 0; i < 4; i++) - { - mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE); - } - - - U32 width = nhpo2(U32(resX*scale))/2; - U32 height = width; - - for (U32 i = 4; i < 6; i++) - { - mShadow[i].allocate(width, height, 0, TRUE, FALSE); + mDeferredLight[i].allocate(resX, resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); } - - - - width = nhpo2(resX)/2; - height = nhpo2(resY)/2; - mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE); } else { @@ -553,23 +505,25 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) if (gGLManager.mHasFramebufferMultisample && samples > 1) { - mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); if (LLPipeline::sRenderDeferred) { + mSampleBuffer.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); addDeferredAttachments(mSampleBuffer); mDeferredScreen.setSampleBuffer(&mSampleBuffer); } + else + { + mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); + } mScreen.setSampleBuffer(&mSampleBuffer); - stop_glerror(); } - - if (LLPipeline::sRenderDeferred) + else if (LLPipeline::sRenderDeferred) { //share depth buffer between deferred targets mDeferredScreen.shareDepthBuffer(mScreen); - for (U32 i = 0; i < 3; i++) - { //share stencil buffer with screen space lightmap to stencil out sky + for (U32 i = 0; i < 2; i++) + { mDeferredScreen.shareDepthBuffer(mDeferredLight[i]); } } @@ -602,40 +556,17 @@ void LLPipeline::releaseGLBuffers() mNoiseMap = 0; } -/* if (mTrueNoiseMap) - { - LLImageGL::deleteTextures(1, &mTrueNoiseMap); - mTrueNoiseMap = 0; - } -*/ - if (mLightFunc) - { - LLImageGL::deleteTextures(1, &mLightFunc); - mLightFunc = 0; - } - mWaterRef.release(); mWaterDis.release(); mScreen.release(); mSampleBuffer.releaseSampleBuffer(); mDeferredScreen.release(); - mDeferredDepth.release(); - for (U32 i = 0; i < 3; i++) - { - mDeferredLight[i].release(); - } - - mGIMap.release(); - mGIMapPost[0].release(); - mGIMapPost[1].release(); - mHighlight.release(); -// mLuminanceMap.release(); - for (U32 i = 0; i < 6; i++) // KL 6 in SD + + for (U32 i = 0; i < 4; i++) { - mShadow[i].release(); + mSunShadow[i].release(); } - for (U32 i = 0; i < 3; i++) { mGlow[i].release(); @@ -658,13 +589,9 @@ void LLPipeline::createGLBuffers() mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE); } - mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE); stop_glerror(); - GLuint resX = gViewerWindow->getWindowDisplayWidth(); - GLuint resY = gViewerWindow->getWindowDisplayHeight(); - if (LLPipeline::sRenderGlow) { //screen space glow buffers const U32 glow_res = llmax(1, @@ -674,13 +601,20 @@ void LLPipeline::createGLBuffers() { mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE); } + } + GLuint resX = gViewerWindow->getWindowDisplayWidth(); + GLuint resY = gViewerWindow->getWindowDisplayHeight(); + allocateScreenBuffer(resX,resY); - } - if (sRenderDeferred) { + mSunShadow[0].allocate(1024,1024, 0, TRUE, FALSE); + mSunShadow[1].allocate(1024,1024, 0, TRUE, FALSE); + mSunShadow[2].allocate(1024,1024, 0, TRUE, FALSE); + mSunShadow[3].allocate(1024,1024, 0, TRUE, FALSE); + if (!mNoiseMap) { const U32 noiseRes = 128; @@ -700,83 +634,7 @@ void LLPipeline::createGLBuffers() 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_ALPHA, lightResX, lightResY, GL_ALPHA, GL_UNSIGNED_BYTE, lg); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); - - delete [] lg; -/* } - - if (gSavedSettings.getBOOL("RenderDeferredGI")) - { */ - mGIMap.allocate(1024,1024,GL_RGBA, TRUE, FALSE); - addDeferredAttachments(mGIMap); - - { - LLGLDepthTest depth(GL_TRUE); - gGL.setColorMask(true, true); - for (U32 i = 0; i < 2; i++) - { - mGIMapPost[i].allocate(128,128,GL_RGB16F_ARB, FALSE, FALSE); - mGIMapPost[i].addColorAttachment(GL_RGB16F_ARB); - mGIMapPost[i].addColorAttachment(GL_RGB16F_ARB); - mGIMapPost[i].addColorAttachment(GL_RGB16F_ARB); - - mGIMapPost[i].bindTarget(); - mGIMapPost[i].clear(); - mGIMapPost[i].flush(); - } - } - } - } //mLuminanceMap.allocate(128,128, GL_RGBA, FALSE, FALSE); } void LLPipeline::restoreGL() @@ -788,7 +646,7 @@ void LLPipeline::restoreGL() LLViewerShaderMgr::instance()->setShaders(); } - for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -842,7 +700,7 @@ void LLPipeline::unloadShaders() void LLPipeline::assertInitializedDoError() { - llwarns << "LLPipeline used when uninitialized." << llendl; + llerrs << "LLPipeline used when uninitialized." << llendl; } //============================================================================ @@ -905,7 +763,7 @@ public: for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) { LLDrawInfo* params = *j; - if (mTextures.find(params->mViewerTexture) != mTextures.end()) + if (mTextures.find(params->mTexture) != mTextures.end()) { group->setState(LLSpatialGroup::GEOM_DIRTY); } @@ -939,7 +797,7 @@ void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerImage*>& texture } LLOctreeDirtyTexture dirty(textures); - for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -1018,7 +876,7 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0) default: llassert(0); - llwarns << "Invalid Pool Type in LLPipeline::findPool() type=" << type << llendl; + llerrs << "Invalid Pool Type in LLPipeline::findPool() type=" << type << llendl; break; } @@ -1133,7 +991,7 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) #ifdef LL_RELEASE_FOR_DOWNLOAD llwarns << "Couldn't remove object from spatial group!" << llendl; #else - llwarns << "Couldn't remove object from spatial group!" << llendl; + llerrs << "Couldn't remove object from spatial group!" << llendl; #endif } } @@ -1148,31 +1006,6 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) break; } } - - { - 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) @@ -1229,7 +1062,7 @@ void LLPipeline::createObject(LLViewerObject* vobj) } else { - llwarns << "Redundant drawable creation!" << llendl; + llerrs << "Redundant drawable creation!" << llendl; } llassert(drawablep); @@ -1293,7 +1126,7 @@ void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep) } if (!drawablep) { - llwarns << "updateMove called with NULL drawablep" << llendl; + llerrs << "updateMove called with NULL drawablep" << llendl; return; } if (drawablep->isState(LLDrawable::EARLY_MOVE)) @@ -1324,8 +1157,7 @@ void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep) } if (!drawablep) { - llwarns << "updateMove called with NULL drawablep" << llendl; - return; + llerrs << "updateMove called with NULL drawablep" << llendl; } if (drawablep->isState(LLDrawable::EARLY_MOVE)) { @@ -1418,7 +1250,7 @@ void LLPipeline::updateMove() { LLFastTimer ot(LLFastTimer::FTM_OCTREE_BALANCE); - for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -1445,6 +1277,7 @@ F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera F32 dist = lookAt.length(); //ramp down distance for nearby objects + //shrink dist by dist/16. if (dist < 16.f) { dist /= 16.f; @@ -1465,7 +1298,7 @@ void LLPipeline::grabReferences(LLCullResult& result) BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera) { - for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -1497,7 +1330,7 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& BOOL res = TRUE; - for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -1560,7 +1393,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl LLGLDepthTest depth(GL_TRUE, GL_FALSE); - for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -1637,7 +1470,7 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) group->setVisible(); - if (!sSkipUpdate) // && !sShadowRender) KL? + if (!sSkipUpdate) { group->updateDistance(camera); } @@ -1728,78 +1561,6 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) return update_complete; } -void LLPipeline::updateGL() // KL SD -{ - while (!LLGLUpdate::sGLQ.empty()) - { - LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); - glu->updateGL(); - glu->mInQ = FALSE; - LLGLUpdate::sGLQ.pop_front(); - } -} // KL updateGL SD - -void LLPipeline::rebuildPriorityGroups() -{ - LLTimer update_timer; - LLMemType mt(LLMemType::MTYPE_PIPELINE); - - assertInitialized(); - - // Iterate through all drawables on the priority build queue, - for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin(); - iter != mGroupQ1.end(); ++iter) - { - LLSpatialGroup* group = *iter; - group->rebuildGeom(); - group->clearState(LLSpatialGroup::IN_BUILD_Q1); - } - - mGroupQ1.clear(); -} - -void LLPipeline::rebuildGroups() -{ - // 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()); // KL - - LLSpatialGroup::sg_vector_t::iterator iter; - for (iter = mGroupQ2.begin(); - iter != mGroupQ2.end(); ++iter) - { - LLSpatialGroup* group = *iter; - - if (group->isDead()) - { - continue; - } - - group->rebuildGeom(); - - if (group->mSpatialPartition->mRenderByGroup) - { - count++; - } - - group->clearState(LLSpatialGroup::IN_BUILD_Q2); - - if (count > min_count) - { - ++iter; - break; - } - } - - mGroupQ2.erase(mGroupQ2.begin(), iter); - - updateMovedList(mMovedBridge); -} - void LLPipeline::updateGeom(F32 max_dtime) { LLTimer update_timer; @@ -1914,16 +1675,6 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera) if (drawablep->isSpatialBridge()) { - LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable; - - if (root && root->getParent() && root->getVObj() && root->getVObj()->isAttachment()) - { - LLVOAvatar* av = root->getParent()->getVObj()->asAvatar(); - if (av->isImpostor()) - { - return; - } - } sCull->pushBridge((LLSpatialBridge*) drawablep); } else @@ -1940,7 +1691,7 @@ void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion) if (!drawablep) { - //llwarns << "Sending null drawable to moved list!" << llendl; + //llerrs << "Sending null drawable to moved list!" << llendl; return; } @@ -2025,7 +1776,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) } mShiftList.resize(0); - for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -2053,54 +1804,6 @@ void LLPipeline::markTextured(LLDrawable *drawablep) } } -void LLPipeline::markGLRebuild(LLGLUpdate* glu) -{ - if (glu && !glu->mInQ) - { - LLGLUpdate::sGLQ.push_back(glu); - glu->mInQ = TRUE; - } -} - -void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) -{ - LLMemType mt(LLMemType::MTYPE_PIPELINE); - //assert_main_thread(); - - if (group && !group->isDead() && group->mSpatialPartition) - { - if (priority) - { - if (!group->isState(LLSpatialGroup::IN_BUILD_Q1)) - { - 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)) - { - //llwarns << "Non-priority updates not yet supported!" << llendl; - if (std::find(mGroupQ2.begin(), mGroupQ2.end(), group) != mGroupQ2.end()) - { - llwarns << "WTF?" << llendl; - } - 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); @@ -2156,13 +1859,12 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) grabReferences(result); - //if (!LLPipeline::sShadowRender) { for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; group->checkOcclusion(); - if (sUseOcclusion > 1 && group->isState(LLSpatialGroup::OCCLUDED)) + if (sUseOcclusion && group->isState(LLSpatialGroup::OCCLUDED)) { markOccluder(group); } @@ -2175,15 +1877,12 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } } } - } - if (!LLPipeline::sShadowRender) - { for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; group->checkOcclusion(); - if (sUseOcclusion > 1 && group->isState(LLSpatialGroup::OCCLUDED)) + if (sUseOcclusion && group->isState(LLSpatialGroup::OCCLUDED)) { markOccluder(group); } @@ -2195,7 +1894,6 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } } - if (!LLPipeline::sShadowRender) { for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { @@ -2247,7 +1945,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera) { LLMemType mt(LLMemType::MTYPE_PIPELINE); - if (!sSkipUpdate && !sShadowRender && bridge->getSpatialGroup()->changeLOD()) + if (!sSkipUpdate && bridge->getSpatialGroup()->changeLOD()) { bool force_update = false; bridge->updateDistance(camera, force_update); @@ -2309,8 +2007,6 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) } } - if (!sShadowRender) - { LLSpatialGroup* group = drawablep->getSpatialGroup(); if (!group || group->changeLOD()) { @@ -2318,18 +2014,17 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) { if (!drawablep->isActive()) { - drawablep->updateDistance(camera, TRUE); + bool force_update = false; + drawablep->updateDistance(camera, force_update); } else if (drawablep->isAvatar()) { - drawablep->updateDistance(camera, TRUE); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility() + 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++) { @@ -2347,8 +2042,6 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) } } } - } - mNumVisibleFaces += drawablep->getNumFaces(); } @@ -2514,7 +2207,7 @@ void LLPipeline::postSort(LLCamera& camera) //rebuild groups sCull->assertDrawMapsEmpty(); - /*LLSpatialGroup::sNoDelete = FALSE; + LLSpatialGroup::sNoDelete = FALSE; for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { LLSpatialGroup* group = *i; @@ -2526,11 +2219,9 @@ void LLPipeline::postSort(LLCamera& camera) group->rebuildGeom(); } - LLSpatialGroup::sNoDelete = TRUE;*/ + LLSpatialGroup::sNoDelete = TRUE; - rebuildPriorityGroups(); - const S32 bin_count = 1024*8; static LLCullResult::drawinfo_list_t alpha_bins[bin_count]; @@ -2555,28 +2246,17 @@ void LLPipeline::postSort(LLCamera& camera) { 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) { 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()) @@ -2601,7 +2281,6 @@ void LLPipeline::postSort(LLCamera& camera) } } } - } if (!sShadowRender) { @@ -2699,7 +2378,7 @@ void LLPipeline::postSort(LLCamera& camera) } } - //LLSpatialGroup::sNoDelete = FALSE; + LLSpatialGroup::sNoDelete = FALSE; } @@ -2760,103 +2439,6 @@ void LLPipeline::renderHighlights() 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(); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - gGL.pushMatrix(); - glLoadIdentity(); - - gGL.getTexUnit(0)->bind(&mHighlight); - - LLVector2 tc1; - LLVector2 tc2; - - tc1.setVec(0,0); - tc2.setVec(2,2); - - gGL.begin(LLRender::TRIANGLES); - - F32 scale = gSavedSettings.getF32("RenderHighlightBrightness"); - LLColor4 color = gSavedSettings.getColor4("RenderHighlightColor"); - F32 thickness = gSavedSettings.getF32("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(); - glMatrixMode(GL_MODELVIEW); - gGL.popMatrix(); - - //gGL.setSceneBlendType(LLRender::BT_ALPHA); - } - if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) { gHighlightProgram.bind(); @@ -2879,7 +2461,7 @@ void LLPipeline::renderHighlights() LLFace *facep = mSelectedFaces[i]; if (!facep || facep->getDrawable()->isDead()) { - llwarns << "Bad face on selection" << llendl; + llerrs << "Bad face on selection" << llendl; return; } @@ -2952,7 +2534,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) { if (!verify()) { - llwarns << "Pipeline verification failed!" << llendl; + llerrs << "Pipeline verification failed!" << llendl; } } @@ -3001,9 +2583,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) stop_glerror(); LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools"); - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderForSelect"); - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDeferred"); - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) { LLDrawPool *poolp = *iter; @@ -3015,6 +2594,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING)) { + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderForSelect"); gObjectList.renderObjectsForSelect(camera, gViewerWindow->getVirtualWindowRect()); } else @@ -3078,8 +2658,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); if (depth > 3) { - - llwarns << "GL matrix stack corrupted!" << llendl; + llerrs << "GL matrix stack corrupted!" << llendl; } std::string msg = llformat("%s pass %d", gPoolNames[cur_type].c_str(), i); LLGLState::checkStates(msg); @@ -3150,13 +2729,21 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLVertexBuffer::unbind(); - if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred) { + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { // Render debugging beacons. gObjectList.renderObjectBeacons(); LLHUDObject::renderAll(); gObjectList.resetObjectBeacons(); } + else + { + // Make sure particle effects disappear + LLHUDObject::renderAllForTimer(); + } + } LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd"); @@ -3179,6 +2766,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) void LLPipeline::renderGeomDeferred(LLCamera& camera) { + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred"); LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY); LLFastTimer t2(LLFastTimer::FTM_POOLS); @@ -3245,20 +2833,17 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) poolp->endDeferredPass(i); LLVertexBuffer::unbind(); - if (gDebugGL || gDebugPipeline) - { GLint depth; glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); if (depth > 3) { - llwarns << "GL matrix stack corrupted!" << llendl; + llerrs << "GL matrix stack corrupted!" << llendl; } LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); } } - } else { // Skip all pools of this type @@ -3338,20 +2923,17 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) poolp->endPostDeferredPass(i); LLVertexBuffer::unbind(); - if (gDebugGL || gDebugPipeline) - { GLint depth; glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); if (depth > 3) { - llwarns << "GL matrix stack corrupted!" << llendl; + llerrs << "GL matrix stack corrupted!" << llendl; } LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); } } - } else { // Skip all pools of this type @@ -3385,6 +2967,11 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) LLHUDObject::renderAll(); gObjectList.resetObjectBeacons(); } + else + { + // Make sure particle effects disappear + LLHUDObject::renderAllForTimer(); + } if (occlude) { @@ -3488,7 +3075,7 @@ void LLPipeline::renderDebug() gGL.setColorMask(true, false); // Debug stuff. - for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -3505,7 +3092,7 @@ void LLPipeline::renderDebug() } } - for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { LLSpatialBridge* bridge = *i; if (!bridge->isDead() && !bridge->isState(LLSpatialGroup::OCCLUDED) && hasRenderType(bridge->mDrawableType)) @@ -3519,91 +3106,96 @@ void LLPipeline::renderDebug() if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) { - LLGLEnable blend(GL_BLEND); // kl sd - LLGLDepthTest depth(TRUE, FALSE); - LLGLDisable cull(GL_CULL_FACE); // kl - 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, + 1,1,0, + 0,1,1, + 1,0,1, + 1,1,1, + 1,0,0, + 0,1,0, + 0,0,1, + 0,0,0 }; for (U32 i = 0; i < 8; i++) { - if (i > 3) - { - gGL.color4fv(col+(i-4)*4); - + gGL.color3fv(col+i*3); + + gGL.begin(LLRender::LINES); + LLVector3* frust = mShadowCamera[i].mAgentFrustum; - gGL.begin(LLRender::TRIANGLE_STRIP); + 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.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); - gGL.end(); + if (i < 4) + { + LLVector3* ext = mShadowExtents[i]; - 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(); + LLVector3 box[] = + { + LLVector3(ext[0][0], ext[0][1], ext[0][2]), + LLVector3(ext[1][0], ext[0][1], ext[0][2]), + LLVector3(ext[1][0], ext[1][1], ext[0][2]), + LLVector3(ext[0][0], ext[1][1], ext[0][2]), + LLVector3(ext[0][0], ext[0][1], ext[1][2]), + LLVector3(ext[1][0], ext[0][1], ext[1][2]), + LLVector3(ext[1][0], ext[1][1], ext[1][2]), + LLVector3(ext[0][0], ext[1][1], ext[1][2]), + }; - 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(); + gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[1].mV); + gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[2].mV); + gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[3].mV); + gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[0].mV); + + gGL.vertex3fv(box[4].mV); gGL.vertex3fv(box[5].mV); + gGL.vertex3fv(box[5].mV); gGL.vertex3fv(box[6].mV); + gGL.vertex3fv(box[6].mV); gGL.vertex3fv(box[7].mV); + gGL.vertex3fv(box[7].mV); gGL.vertex3fv(box[4].mV); + + gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[4].mV); + gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[5].mV); + gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[6].mV); + gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[7].mV); } + gGL.end(); - if (i < 4) + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { - gGL.begin(LLRender::LINES); - - F32* c = col+i*4; - for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j) + LLViewerRegion* region = *iter; + for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++) { - - gGL.color3fv(c); - - for (U32 k = 0; k < mShadowFrustPoints[i].size(); ++k) + LLSpatialPartition* part = region->getSpatialPartition(j); + if (part) { - if (j != k) + if (hasRenderType(part->mDrawableType)) { - gGL.vertex3fv(mShadowFrustPoints[i][j].mV); - gGL.vertex3fv(mShadowFrustPoints[i][k].mV); + part->renderIntersectingBBoxes(&mShadowCamera[i]); } } - - if (!mShadowFrustOrigin[i].isExactlyZero()) - { - gGL.vertex3fv(mShadowFrustPoints[i][j].mV); - gGL.color4f(1,1,1,1); - gGL.vertex3fv(mShadowFrustOrigin[i].mV); } } - gGL.end(); } } - } if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION) { @@ -3638,55 +3230,6 @@ void LLPipeline::renderDebug() } } - if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_BUILD_QUEUE) - { - U32 count = 0; - U32 size = mBuildQ2.size(); - LLColor4 col; - - LLGLEnable blend(GL_BLEND); - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - gGL.getTexUnit(0)->bind(LLViewerImage::sWhiteImagep); - - 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(); - glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); - } - - F32 alpha = (F32) (size-count)/size; - - - LLVector2 c(1.f-alpha, alpha); - c.normVec(); - - - ++count; - col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.1f); - group->drawObjectBox(col); - - if (bridge) - { - gGL.popMatrix(); - } - } - } - gGL.flush(); } @@ -5120,7 +4663,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, sPickAvatar = FALSE; //LLToolMgr::getInstance()->inBuildMode() ? FALSE : TRUE; - for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -5177,7 +4720,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, //check against avatars sPickAvatar = TRUE; - for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -5254,7 +4797,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector3& start, co { LLDrawable* drawable = NULL; - for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -5317,7 +4860,7 @@ void LLPipeline::resetVertexBuffers() { sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); - for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -5428,18 +4971,18 @@ void validate_framebuffer_object() break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: // frame buffer not OK: probably means unsupported depth buffer format - llwarns << "Framebuffer Incomplete Dimensions." << llendl; + llerrs << "Framebuffer Incomplete Dimensions." << llendl; break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: // frame buffer not OK: probably means unsupported depth buffer format - llwarns << "Framebuffer Incomplete Attachment." << llendl; + llerrs << "Framebuffer Incomplete Attachment." << llendl; break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: /* choose different formats */ - llwarns << "Framebuffer unsupported." << llendl; + llerrs << "Framebuffer unsupported." << llendl; break; default: - llwarns << "Unknown framebuffer status." << llendl; + llerrs << "Unknown framebuffer status." << llendl; break; } } @@ -5757,202 +5300,46 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) } -void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRenderTarget* gi_source, LLRenderTarget* last_gi_post) //, U32 noise_map) +void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) { -/* if (noise_map == 0xFFFFFFFF) - { - noise_map = mNoiseMap; - } -*/ - LLFastTimer ftm(LLFastTimer::FTM_TEMP3); - LLGLState::checkTextureChannels(); - shader.bind(); S32 channel = 0; channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { mDeferredScreen.bindTexture(0,channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { mDeferredScreen.bindTexture(1, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { mDeferredScreen.bindTexture(2, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } - if (gi_source) - { - BOOL has_gi = FALSE; - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE); + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { - has_gi = TRUE; - gi_source->bindTexture(0, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR); - if (channel > -1) - { - has_gi = TRUE; - gi_source->bindTexture(1, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL); - if (channel > -1) - { - has_gi = TRUE; - gi_source->bindTexture(2, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS); - if (channel > -1) - { - has_gi = TRUE; - gi_source->bindTexture(1, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS); - if (channel > -1) - { - has_gi = TRUE; - gi_source->bindTexture(3, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE); - if (channel > -1) - { - has_gi = TRUE; - last_gi_post->bindTexture(0, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL); - if (channel > -1) - { - has_gi = TRUE; - last_gi_post->bindTexture(2, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS); - if (channel > -1) - { - has_gi = TRUE; - last_gi_post->bindTexture(1, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS); - if (channel > -1) - { - has_gi = TRUE; - last_gi_post->bindTexture(3, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH); - if (channel > -1) - { - has_gi = TRUE; - gGL.getTexUnit(channel)->bind(gi_source, TRUE); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - stop_glerror(); - - glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); - glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); - - stop_glerror(); - } - - if (has_gi) - { - U32 gi_samples = llclamp(gSavedSettings.getU32("RenderGISamples"), (U32) 1, (U32) 8); - - F32 range_x = llmin(mGIRange.mV[0], 1.f); - F32 range_y = llmin(mGIRange.mV[1], 1.f); - - LLVector2 scale(range_x,range_y); - - LLVector2 kern[25]; - - for (S32 i = 0; i < 5; ++i) - { - for (S32 j = 0; j < 5; ++j) - { - S32 idx = i*5+j; - kern[idx].mV[0] = (i-2)*0.5f; - kern[idx].mV[1] = (j-2)*0.5f; - kern[idx].scaleVec(scale); - } - } - - F32 gi_radius = mGILightRadius; //gSavedSettings.getF32("RenderGILightRadius"); - - shader.uniform2f("gi_scale", scale.mV[0], scale.mV[1]); - shader.uniform2fv("gi_kern", 25, (F32*) kern); - shader.uniformMatrix4fv("gi_mat", 1, FALSE, mGIMatrix.m); - shader.uniformMatrix4fv("gi_mat_proj", 1, FALSE, mGIMatrixProj.m); - shader.uniformMatrix4fv("gi_inv_proj", 1, FALSE, mGIInvProj.m); - shader.uniformMatrix4fv("gi_norm_mat", 1, FALSE, mGINormalMatrix.m); - shader.uniform1f("gi_radius", gi_radius); - shader.uniform1i("gi_samples", (GLint) gSavedSettings.getU32("RenderGISamples")); - shader.uniform1f("gi_intensity", gSavedSettings.getF32("RenderGIIntensity")/(gi_samples*gi_samples)); - shader.uniform3fv("gi_quad", 1, gSavedSettings.getVector3("RenderGIColorCurve").mV); - shader.uniform3fv("gi_spec", 1, gSavedSettings.getVector3("RenderGISpecularCurve").mV); - shader.uniform1f("gi_direction_weight", gSavedSettings.getF32("RenderGIDirectionWeight")); - shader.uniform1f("gi_light_offset", gSavedSettings.getF32("RenderGILightOffset")); - shader.uniform1f("gi_blend", gFrameIntervalSeconds); - } + mDeferredScreen.bindTexture(3, channel); } channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { - gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - 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("inv_proj", 1, FALSE, inv_proj.m); - shader.uniform4f("viewport", (F32) gGLViewport[0], - (F32) gGLViewport[1], - (F32) gGLViewport[2], - (F32) gGLViewport[3]); + gGL.getTexUnit(channel)->bind(&mDeferredScreen, TRUE); } channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NOISE); if (channel > -1) { - gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); // was noise_map KL - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC); - if (channel > -1) - { - gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); } stop_glerror(); @@ -5961,68 +5348,19 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen if (channel > -1) { mDeferredLight[light_index].bindTexture(0, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE); - if (channel > -1) - { - gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE); - if (channel > -1) - { - gi_source->bindTexture(0, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE); - if (channel > -1) - { - mDeferredLight[1].bindTexture(0, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } - - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE); - if (channel > -1) - { - mDeferredLight[2].bindTexture(0, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } - stop_glerror(); for (U32 i = 0; i < 4; i++) { - channel = shader.enableTexture(LLViewerShaderMgr::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(LLViewerShaderMgr::DEFERRED_SHADOW0+i); stop_glerror(); if (channel > -1) { stop_glerror(); - gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE); + gGL.getTexUnit(channel)->bind(&mSunShadow[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); @@ -6033,19 +5371,17 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen stop_glerror(); - F32 mat[16*6]; + F32 mat[64]; 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("shadow_matrix[0]", 6, FALSE, mat); - shader.uniformMatrix4fv("shadow_matrix", 6, FALSE, mat); + shader.uniformMatrix4fv("shadow_matrix[0]", 4, FALSE, mat); + shader.uniformMatrix4fv("shadow_matrix", 4, FALSE, mat); stop_glerror(); @@ -6094,23 +5430,8 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); shader.uniform1f("near_clip", LLViewerCamera::getInstance()->getNear()*2.f); shader.uniform1f("alpha_soften", gSavedSettings.getF32("RenderDeferredAlphaSoften")); - shader.uniform1f ("shadow_offset", gSavedSettings.getF32("RenderShadowOffset")); - shader.uniform1f("shadow_bias", gSavedSettings.getF32("RenderShadowBias")); -/* shader.uniform3fv("gi_quad", 1, gSavedSettings.getVector3("RenderGIColorCurve").mV); - shader.uniform3fv("lum_quad", 1, gSavedSettings.getVector3("RenderLuminanceColorCurve").mV); - shader.uniform3fv("gi_lum_quad", 1, gSavedSettings.getVector3("RenderGILuminanceColorCurve").mV); - shader.uniform3fv("sun_lum_quad", 1, gSavedSettings.getVector3("RenderSunLuminanceColorCurve").mV); - shader.uniform1f("lum_lod", gSavedSettings.getF32("RenderLuminanceDetail")); - shader.uniform1f("gi_range", gSavedSettings.getF32("RenderGIRange")); - - 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); - } */ } -// KL The Deffered Pipeline begins here! void LLPipeline::renderDeferredLighting() { if (!sCull) @@ -6118,12 +5439,6 @@ void LLPipeline::renderDeferredLighting() return; } - { - 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(GL_MULTISAMPLE_ARB); if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) @@ -6137,10 +5452,16 @@ void LLPipeline::renderDeferredLighting() glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); gGL.setColorMask(true, true); + + mDeferredLight[0].bindTarget(); + + //mDeferredLight[0].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), + // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); //draw a cube around every light LLVertexBuffer::unbind(); + glBlendFunc(GL_ONE, GL_ONE); LLGLEnable cull(GL_CULL_FACE); LLGLEnable blend(GL_BLEND); @@ -6152,34 +5473,8 @@ void LLPipeline::renderDeferredLighting() -1,-3, 3,1, }; - glVertexPointer(2, GL_FLOAT, 0, vert); - glColor3f(1,1,1); - //Set mSunDir KL This makes sense to have it here. Still calculated EVEN if Deferred Sun is FALSE! - { - setupHWLights(NULL); //to set mSunDir; - LLVector4 dir(mSunDir, 0.f); - glh::vec4f tc(dir.mV); - mat.mult_matrix_vec(tc); - glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0); - } - - if (gSavedSettings.getBOOL("RenderDeferredShadow")) - { - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - mDeferredLight[0].bindTarget(); -// KL Bind to 0 next section Deferred Sun ! - if (gSavedSettings.getBOOL("RenderDeferredSun")) - { //paint shadow/SSAO light map (direct lighting lightmap) - bindDeferredShader(gDeferredSunProgram, 0); - - glClearColor(1,1,1,1); - mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT); - glClearColor(0,0,0,0); + bindDeferredShader(gDeferredSunProgram); glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose(); @@ -6202,115 +5497,24 @@ void LLPipeline::renderDeferredLighting() gDeferredSunProgram.uniform3fv("offset", slice, offset); gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight()); - - { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_FALSE); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - stop_glerror(); - } - - unbindDeferredShader(gDeferredSunProgram); - } - else - { - mDeferredLight[0].clear(); - } - - mDeferredLight[0].flush(); - mDeferredLight[1].bindTarget(); - } -// KL Bind to 1 next section GI -/* if (gSavedSettings.getBOOL("RenderDeferredGI")) - { - { //get luminance map from previous frame's light map - LLGLEnable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - LLGLDepthTest depth(GL_FALSE); - LLGLDisable stencil(GL_STENCIL_TEST); - - //static F32 fade = 1.f; - - F32 fade = gSavedSettings.getF32("RenderLuminanceFade"); - { - gGL.setSceneBlendType(LLRender::BT_ALPHA); - gLuminanceGatherProgram.bind(); - gLuminanceGatherProgram.uniform2f("screen_res", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight()); - gLuminanceGatherProgram.uniform1f("fade", llclamp(fade, 0.f, 1.f)); - mLuminanceMap.bindTarget(); - gGL.getTexUnit(0)->bind(&mDeferredLight[0]); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - gLuminanceGatherProgram.unbind(); - mLuminanceMap.flush(); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); - glGenerateMipmapEXT(GL_TEXTURE_2D); - } - } - - { //paint noisy GI map (bounce lighting lightmap) - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_FALSE); - LLGLDisable test(GL_ALPHA_TEST); + setupHWLights(NULL); //to set mSunDir; - mGIMapPost[0].bindTarget(); - - bindDeferredShader(gDeferredGIProgram, 0, &mGIMap, 0);//, mTrueNoiseMap); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - unbindDeferredShader(gDeferredGIProgram); - mGIMapPost[0].flush(); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + LLVector4 dir(mSunDir, 0.f); - } + glh::vec4f tc(dir.mV); + mat.mult_matrix_vec(tc); + glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0); + glColor3f(1,1,1); - U32 pass_count = 0; - if (gSavedSettings.getBOOL("RenderDeferredBlurLight")) + glVertexPointer(2, GL_FLOAT, 0, vert); { - pass_count = llclamp(gSavedSettings.getU32("RenderGIBlurPasses"), (U32) 1, (U32) 128); - } - - for (U32 i = 0; i < pass_count; ++i) - { //gather/soften indirect lighting map - bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[0], NULL); //, mTrueNoiseMap); - - LLVector2 gauss[32]; // xweight, yweight, offset - - F32 sc = 1.f; - - F32 go = gSavedSettings.getF32("RenderGIGaussian"); - U32 kern_length = llclamp(gSavedSettings.getU32("RenderGIBlurSamples"), (U32) 1, (U32) 16)*2 - 1; - F32 blur_size = gSavedSettings.getF32("RenderGIBlurSize")*sc; - F32 dist_factor = gSavedSettings.getF32("RenderGIBlurDistFactor"); - - // sample symmetrically with the middle sample falling exactly on 0.0 - F32 x = -(kern_length/2.0f) + 0.5f; - - for (U32 i = 0; i < kern_length; i++) - { - gauss[i].mV[0] = llgaussian(x, go); - gauss[i].mV[1] = x; - x += 1.f; - } - // swap the x=0 position to the start of gauss[] so we can - // treat it specially as an optimization. - LLVector2 swap; - swap = gauss[kern_length/2]; - gauss[kern_length/2] = gauss[0]; - gauss[0] = swap; - llassert(gauss[0].mV[2] == 0.0f); - - gDeferredPostGIProgram.uniform2f("delta", 1.f, 0.f); - gDeferredPostGIProgram.uniform1f("dist_factor", dist_factor); - gDeferredPostGIProgram.uniform2fv("kern[0]", kern_length, gauss[0].mV); - gDeferredPostGIProgram.uniform2fv("kern", kern_length, gauss[0].mV); - gDeferredPostGIProgram.uniform1i("kern_length", kern_length); - gDeferredPostGIProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); - gDeferredPostGIProgram.uniform3fv("blur_quad", 1, gSavedSettings.getVector3("RenderGIBlurColorCurve").mV); - - mGIMapPost[1].bindTarget(); - { LLGLDisable blend(GL_BLEND); LLGLDepthTest depth(GL_FALSE); stop_glerror(); @@ -6318,39 +5522,15 @@ void LLPipeline::renderDeferredLighting() stop_glerror(); } - mGIMapPost[1].flush(); - unbindDeferredShader(gDeferredPostGIProgram); - - bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[1], NULL);//, mTrueNoiseMap); - mGIMapPost[0].bindTarget(); + unbindDeferredShader(gDeferredSunProgram); - gDeferredPostGIProgram.uniform2f("delta", 0.f, 1.f); - gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor); - gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); - gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); - - { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_FALSE); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - stop_glerror(); - } - mGIMapPost[0].flush(); - unbindDeferredShader(gDeferredPostGIProgram); - } - } */ + mDeferredLight[0].flush(); - if (gSavedSettings.getBOOL("RenderDeferredBlurLight")) - { //soften direct lighting lightmap //blur lightmap mDeferredLight[1].bindTarget(); - glClearColor(1,1,1,1); - mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT); - glClearColor(0,0,0,0); + //mDeferredLight[1].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), + // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); bindDeferredShader(gDeferredBlurLightProgram); @@ -6359,7 +5539,6 @@ void LLPipeline::renderDeferredLighting() LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian"); U32 kern_length = llclamp(gSavedSettings.getU32("RenderShadowBlurSamples"), (U32) 1, (U32) 16)*2 - 1; F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize"); - F32 dist_factor = gSavedSettings.getF32("RenderShadowBlurDistFactor"); // sample symmetrically with the middle sample falling exactly on 0.0 F32 x = -(kern_length/2.0f) + 0.5f; @@ -6380,12 +5559,11 @@ void LLPipeline::renderDeferredLighting() llassert(gauss[0].mV[2] == 0.0f); gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); - gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor); gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); - + { LLGLDisable blend(GL_BLEND); LLGLDepthTest depth(GL_FALSE); @@ -6401,7 +5579,6 @@ void LLPipeline::renderDeferredLighting() mDeferredLight[0].bindTarget(); gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); - gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor); gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); @@ -6411,12 +5588,11 @@ void LLPipeline::renderDeferredLighting() LLGLDisable blend(GL_BLEND); LLGLDepthTest depth(GL_FALSE); stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); // KL 4? + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); stop_glerror(); } mDeferredLight[0].flush(); unbindDeferredShader(gDeferredBlurLightProgram); - } stop_glerror(); glPopMatrix(); @@ -6425,26 +5601,15 @@ void LLPipeline::renderDeferredLighting() stop_glerror(); glPopMatrix(); 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); -/* if (gSavedSettings.getBOOL("RenderDeferredGI")) - { - mDeferredLight[1].bindTarget(); - mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT); - } - else - { */ mScreen.bindTarget(); mScreen.clear(GL_COLOR_BUFFER_BIT); -// } - - if (gSavedSettings.getBOOL("RenderDeferredAtmospheric")) - { //apply sunlight contribution - bindDeferredShader(gDeferredSoftenProgram, 0, &mGIMapPost[0]); // may not be using GI but still need this KL + + bindDeferredShader(gDeferredSoftenProgram); { LLGLDepthTest depth(GL_FALSE); LLGLDisable blend(GL_BLEND); @@ -6467,56 +5632,15 @@ void LLPipeline::renderDeferredLighting() } unbindDeferredShader(gDeferredSoftenProgram); - } -// KL this code is a tad buggered atm it obliterates local lights...... -/* { //render sky/water/hair/skirts - LLGLDisable blend(GL_BLEND); - LLGLDisable stencil(GL_STENCIL_TEST); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - U32 render_mask = mRenderTypeMask; - mRenderTypeMask = mRenderTypeMask & - ((1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_CLOUDS) | - (1 << LLPipeline::RENDER_TYPE_WL_SKY) | - (1 << LLPipeline::RENDER_TYPE_AVATAR) | - (1 << LLPipeline::RENDER_TYPE_WATER)); - - renderGeomPostDeferred(*LLViewerCamera::getInstance()); - mRenderTypeMask = render_mask; - } */ + bindDeferredShader(gDeferredLightProgram); - BOOL render_local = gSavedSettings.getBOOL("RenderDeferredLocalLights"); - BOOL render_fullscreen = gSavedSettings.getBOOL("RenderDeferredFullscreenLights"); - -/* - if (gSavedSettings.getBOOL("RenderDeferredGI")) - { - mDeferredLight[1].flush(); - mDeferredLight[2].bindTarget(); - mDeferredLight[2].clear(GL_COLOR_BUFFER_BIT); - } -*/ - if (render_local || render_fullscreen) - { - 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; F32 v[24]; glVertexPointer(3, GL_FLOAT, 0, v); - BOOL render_local = gSavedSettings.getBOOL("RenderDeferredLocalLights"); - { - bindDeferredShader(gDeferredLightProgram); LLGLDepthTest depth(GL_TRUE, GL_FALSE); for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) { @@ -6532,29 +5656,18 @@ void LLPipeline::renderDeferredLighting() F32* c = center.mV; F32 s = volume->getLightRadius()*1.5f; - LLColor3 col = volume->getLightColor(); - col *= volume->getLightIntensity(); - - if (col.magVecSquared() < 0.001f) - { - continue; - } - - if (s <= 0.001f) - { - continue; - } - if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0) { continue; } sVisibleLightCount++; - glh::vec3f tc(c); mat.mult_matrix_vec(tc); + LLColor3 col = volume->getLightColor(); + col *= volume->getLightIntensity(); + //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 @@ -6576,90 +5689,24 @@ void LLPipeline::renderDeferredLighting() LLViewerCamera::getInstance()->getOrigin().mV[2] > c[2] + s + 0.2f || LLViewerCamera::getInstance()->getOrigin().mV[2] < c[2] - s - 0.2f) { //draw box if camera is outside box - if (render_local) - { - if (volume->getLightTexture()) - { - drawablep->getVOVolume()->updateSpotLightPriority(); - spot_lights.push_back(drawablep); - continue; - } - glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_box_fan_indices(LLViewerCamera::getInstance(), center)); } - } - else if (render_fullscreen) + else { - if (volume->getLightTexture()) - { - 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); - - gDeferredSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); + unbindDeferredShader(gDeferredLightProgram); - for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter) + if (!fullscreen_lights.empty()) { - 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(gDeferredSpotLightProgram, drawablep); - - LLColor3 col = volume->getLightColor(); - col *= volume->getLightIntensity(); - - //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 - v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000 - v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001 - v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010 - v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011 - - v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100 - v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101 - v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110 - v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111 - - glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); - glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, get_box_fan_indices(LLViewerCamera::getInstance(), center)); - } - gDeferredSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); - unbindDeferredShader(gDeferredSpotLightProgram); - } - - { bindDeferredShader(gDeferredMultiLightProgram); - LLGLDepthTest depth(GL_FALSE); //full screen blit @@ -6671,14 +5718,11 @@ void LLPipeline::renderDeferredLighting() U32 count = 0; - const U32 max_count = 8; // KL poss 16? - LLVector4 light[max_count]; - LLVector4 col[max_count]; + LLVector4 light[16]; + LLVector4 col[16]; glVertexPointer(2, GL_FLOAT, 0, vert); - F32 far_z = 0.f; - while (!fullscreen_lights.empty()) { light[count] = fullscreen_lights.front(); @@ -6686,111 +5730,32 @@ void LLPipeline::renderDeferredLighting() 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()) + if (count == 16 || fullscreen_lights.empty()) { gDeferredMultiLightProgram.uniform1i("light_count", count); gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light); gDeferredMultiLightProgram.uniform4fv("light", count, (GLfloat*) light); gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col); gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col); - gDeferredMultiLightProgram.uniform1f("far_z", far_z); - far_z = 0.f; count = 0; glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); } } - unbindDeferredShader(gDeferredMultiLightProgram); - - bindDeferredShader(gDeferredMultiSpotLightProgram); - - gDeferredMultiSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); - - for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter) - { - 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(); - col *= volume->getLightIntensity(); - - glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); - glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - } - - gDeferredMultiSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); - unbindDeferredShader(gDeferredMultiSpotLightProgram); - glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); - } - } + unbindDeferredShader(gDeferredMultiLightProgram); + } glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - gGL.setColorMask(true, true); -/* - if (gSavedSettings.getBOOL("RenderDeferredGI")) - { - mDeferredLight[2].flush(); - mScreen.bindTarget(); - mScreen.clear(GL_COLOR_BUFFER_BIT); - - gGL.setSceneBlendType(LLRender::BT_ALPHA); - { //mix various light maps (local, sun, gi) + { //render non-deferred geometry LLGLDisable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - LLGLDepthTest depth(GL_FALSE); LLGLDisable stencil(GL_STENCIL_TEST); - - gViewerWindow->setupViewport(); - - bindDeferredShader(gDeferredPostProgram, 0, &mGIMapPost[0]); - - gDeferredPostProgram.bind(); - - LLVertexBuffer::unbind(); - - glVertexPointer(2, GL_FLOAT, 0, vert); - glColor3f(1,1,1); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - - glDrawArrays(GL_TRIANGLES, 0, 3); - - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - unbindDeferredShader(gDeferredPostProgram); - } - } -*/ - { //render non-deferred geometry (alpha, fullbright, glow) KL issues with render pipeline merge needs work.. here - LLGLDisable blend(GL_BLEND); - LLGLDisable stencil(GL_STENCIL_TEST); - gGL.setSceneBlendType(LLRender::BT_ALPHA); U32 render_mask = mRenderTypeMask; mRenderTypeMask = mRenderTypeMask & ((1 << LLPipeline::RENDER_TYPE_SKY) | @@ -6803,161 +5768,18 @@ void LLPipeline::renderDeferredLighting() (1 << LLPipeline::RENDER_TYPE_FULLBRIGHT) | (1 << LLPipeline::RENDER_TYPE_VOLUME) | (1 << LLPipeline::RENDER_TYPE_GLOW) | - (1 << LLPipeline::RENDER_TYPE_BUMP) | - (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA) | - (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK) | - (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY) | - (1 << LLPipeline::RENDER_TYPE_PASS_GLOW) | - (1 << LLPipeline::RENDER_TYPE_PASS_GRASS) | - (1 << LLPipeline::RENDER_TYPE_PASS_SHINY) | - (1 << LLPipeline::RENDER_TYPE_PASS_INVISIBLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY)); + (1 << LLPipeline::RENDER_TYPE_BUMP)); renderGeomPostDeferred(*LLViewerCamera::getInstance()); mRenderTypeMask = render_mask; } - mScreen.flush(); // We are FLUSHED alright ! end of deferred render YAY! + 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("proj_mat", 1, FALSE, screen_to_light.m); - shader.uniform1f("proj_near", near_clip); - shader.uniform3fv("proj_p", 1, p1.v); - shader.uniform3fv("proj_n", 1, n.v); - shader.uniform3fv("proj_origin", 1, screen_origin.v); - shader.uniform1f("proj_range", proj_range); - shader.uniform1f("proj_ambiance", params.mV[2]); - S32 s_idx = -1; - - for (U32 i = 0; i < 2; i++) - { - if (mShadowSpotLight[i] == drawablep) - { - s_idx = i; - } - } - - shader.uniform1i("proj_shadow_idx", s_idx); - - if (s_idx >= 0) - { - shader.uniform1f("shadow_fade", 1.f-mSpotLightFade[s_idx]); - } - else - { - shader.uniform1f("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; - } - } - } - - LLViewerImage* img = volume->getLightTexture(); - - S32 channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); - - if (channel > -1 && img) - { - gGL.getTexUnit(channel)->bind(img); - - F32 lod_range = logf(img->getWidth())/logf(2.f); - - shader.uniform1f("proj_focus", focus); - shader.uniform1f("proj_lod", lod_range); - shader.uniform1f("proj_ambient_lod", llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f)); - } -} - void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) { - LLFastTimer ftm(LLFastTimer::FTM_TEMP4); stop_glerror(); shader.disableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE); shader.disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE); @@ -6965,40 +5787,14 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE); shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE); shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE); - shader.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS); - for (U32 i = 0; i < 4; i++) { - if (shader.disableTexture(LLViewerShaderMgr::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(LLViewerShaderMgr::DEFERRED_SHADOW0+i) > -1) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); } } - shader.disableTexture(LLViewerShaderMgr::DEFERRED_NOISE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC); S32 channel = shader.disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); if (channel > -1) @@ -7012,8 +5808,6 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->activate(); shader.unbind(); - - LLGLState::checkTextureChannels(); } inline float sgn(float a) @@ -7153,15 +5947,15 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) } } - //LLSpatialPartition::sFreezeState = TRUE; - //LLPipeline::sSkipUpdate = TRUE; + LLSpatialPartition::sFreezeState = TRUE; + LLPipeline::sSkipUpdate = TRUE; LLGLUserClipPlane clip_plane(plane, mat, projection); static LLCullResult result; updateCull(camera, result, 1); stateSort(camera, result); renderGeom(camera); - //LLSpatialPartition::sFreezeState = FALSE; - //LLPipeline::sSkipUpdate = FALSE; + LLSpatialPartition::sFreezeState = FALSE; + LLPipeline::sSkipUpdate = FALSE; } } glCullFace(GL_BACK); @@ -7261,6 +6055,7 @@ glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up) dirN = dir; dirN.normVec(); + ret.m[ 0] = lftN[0]; ret.m[ 1] = upN[0]; @@ -7311,629 +6106,114 @@ glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max) return ret; } -void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, BOOL use_shader) +void LLPipeline::generateSunShadow(LLCamera& camera) { - LLFastTimer t(LLFastTimer::FTM_SHADOW_RENDER); - - //clip out geometry on the same side of water as the camera - static LLCullResult result; - S32 occlude = LLPipeline::sUseOcclusion; - LLPipeline::sUseOcclusion = 1; - LLPipeline::sShadowRender = TRUE; - - updateCull(shadow_cam, result); - stateSort(shadow_cam, result); - - U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP }; - LLGLEnable cull(GL_CULL_FACE); - - //generate shadow map - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadMatrixf(proj.m); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadMatrixf(view.m); - - stop_glerror(); - gGLLastMatrix = NULL; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - glColor4f(1,1,1,1); - - stop_glerror(); - - gGL.setColorMask(false, false); - if (use_shader) + if (!sRenderDeferred) { - gDeferredShadowProgram.bind(); + return; } - //glCullFace(GL_FRONT); - + //temporary hack to disable shadows but keep local lights + static BOOL clear = TRUE; + BOOL gen_shadow = gSavedSettings.getBOOL("RenderDeferredSunShadow"); + if (!gen_shadow) { - LLFastTimer ftm(LLFastTimer::FTM_SHADOW_SIMPLE); - LLGLDisable test(GL_ALPHA_TEST); - gGL.getTexUnit(0)->disable(); - for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i) + if (clear) { - renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + clear = FALSE; + for (U32 i = 0; i < 4; i++) + { + mSunShadow[i].bindTarget(); + mSunShadow[i].clear(); + mSunShadow[i].flush(); + } } - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - } - - if (use_shader) - { - gDeferredShadowProgram.unbind(); - renderGeomShadow(shadow_cam); - gDeferredShadowProgram.bind(); - } - else - { - renderGeomShadow(shadow_cam); - } - - { - LLFastTimer ftm(LLFastTimer::FTM_SHADOW_ALPHA); - LLGLEnable test(GL_ALPHA_TEST); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f); - renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE); - glColor4f(1,1,1,1); - renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + return; } + clear = TRUE; - //glCullFace(GL_BACK); + gGL.setColorMask(false, false); - if (use_shader) - { - gDeferredShadowProgram.unbind(); - } + //get sun view matrix - gGL.setColorMask(true, true); + F32 range = 128.f; - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - gGLLastMatrix = NULL; + //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(); - LLPipeline::sUseOcclusion = occlude; - LLPipeline::sShadowRender = FALSE; -} + glh::matrix4f view[4]; + glh::matrix4f proj[4]; + LLVector3 up; + //clip contains parallel split distances for 3 splits + LLVector3 clip = gSavedSettings.getVector3("RenderShadowClipPlanes"); -BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir) -{ - LLFastTimer ftm(LLFastTimer::FTM_TEMP2); - //get point cloud of intersection of frust and min, max + //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]); - //get set of planes - std::vector<LLPlane> ps; - - if (getVisibleExtents(camera, min, max)) - { - return FALSE; + const LLPickInfo& pick_info = gViewerWindow->getLastPick(); + + if (!pick_info.mPosGlobal.isExactlyZero()) + { //squish nearest frustum based on alt-zoom (tighten up nearest frustum when focusing on tiny object + F32 focus_dist = (F32) (pick_info.mPosGlobal + LLVector3d(pick_info.mObjectOffset) - gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin())).magVec(); + mSunClipPlanes.mV[0] = llclamp(focus_dist*focus_dist, 2.f, mSunClipPlanes.mV[0]); } + + // convenience array of 4 near clip plane distances + F32 dist[] = { 0.1f, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] }; - ps.push_back(LLPlane(min, LLVector3(-1,0,0))); - ps.push_back(LLPlane(min, LLVector3(0,-1,0))); - ps.push_back(LLPlane(min, LLVector3(0,0,-1))); - ps.push_back(LLPlane(max, LLVector3(1,0,0))); - ps.push_back(LLPlane(max, LLVector3(0,1,0))); - ps.push_back(LLPlane(max, LLVector3(0,0,1))); + //currently used for amount to extrude frusta corners for constructing shadow frusta + LLVector3 n = gSavedSettings.getVector3("RenderShadowNearDist"); + F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] }; - if (!light_dir.isExactlyZero()) + for (S32 j = 0; j < 4; j++) { - LLPlane ucp; - LLPlane mcp; + //restore render matrices + glh_set_current_modelview(saved_view); + glh_set_current_projection(saved_proj); - F32 maxd = -1.f; - F32 mind = 1.f; + //get center of far clip plane (for point of interest later) + LLVector3 center = camera.getOrigin() + camera.getAtAxis() * range; - for (U32 i = 0; i < ps.size(); ++i) - { //pick the plane most aligned to lightDir for user clip plane - LLVector3 n(ps[i].mV); - F32 da = n*light_dir; - if (da > maxd) - { - maxd = da; - ucp = ps[i]; - } + LLVector3 eye = camera.getOrigin(); - if (da < mind) - { - mind = da; - mcp = ps[i]; - } - } - - camera.setUserClipPlane(ucp); + //camera used for shadow cull/render + LLCamera shadow_cam; + + // perspective shadow map + glh::vec3f p[16]; //point cloud to be contained by shadow projection (light camera space) + glh::vec3f wp[16]; //point cloud to be contained by shadow projection (world space) + + LLVector3 lightDir = -mSunDir; + glh::vec3f light_dir(lightDir.mV); - ps.clear(); - ps.push_back(ucp); - ps.push_back(mcp); - } - - for (U32 i = 0; i < 6; i++) - { - ps.push_back(camera.getAgentPlane(i)); - } + //create light space camera matrix + LLVector3 at; + F32 dl = camera.getLeftAxis() * lightDir; + F32 du = camera.getUpAxis() * lightDir; - //get set of points where planes intersect and points are not above any plane - fp.clear(); - - for (U32 i = 0; i < ps.size(); ++i) - { - for (U32 j = 0; j < ps.size(); ++j) - { - for (U32 k = 0; k < ps.size(); ++k) - { - if (i == j || - i == k || - k == j) - { - continue; - } - - LLVector3 n1,n2,n3; - F32 d1,d2,d3; - - n1.setVec(ps[i].mV); - n2.setVec(ps[j].mV); - n3.setVec(ps[k].mV); - - d1 = ps[i].mV[3]; - d2 = ps[j].mV[3]; - d3 = ps[k].mV[3]; - - //get point of intersection of 3 planes "p" - LLVector3 p = (-d1*(n2%n3)-d2*(n3%n1)-d3*(n1%n2))/(n1*(n2%n3)); - - if (llround(p*n1+d1, 0.0001f) == 0.f && - llround(p*n2+d2, 0.0001f) == 0.f && - llround(p*n3+d3, 0.0001f) == 0.f) - { //point is on all three planes - BOOL found = TRUE; - for (U32 l = 0; l < ps.size() && found; ++l) - { - if (llround(ps[l].dist(p), 0.0001f) > 0.0f) - { //point is above some plane, not contained - found = FALSE; - } - } - - if (found) - { - fp.push_back(p); - } - } - } - } - } - - if (fp.empty()) - { - return FALSE; - } - - return TRUE; -} - -void LLPipeline::generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<LLVector3>& vpc) -{ -/* if (!gSavedSettings.getBOOL("RenderDeferredGI")) - { - return; - } */ - - LLVector3 up; - - if (lightDir.mV[2] > 0.5f) - { - up = LLVector3(1,0,0); - } - else - { - up = LLVector3(0, 0, 1); - } - - - F32 lrad = gSavedSettings.getF32("RenderGILightRadius"); - - F32 samples = (F32) gSavedSettings.getU32("RenderGISamples"); - - F32 gi_range = gSavedSettings.getF32("RenderGIRange"); - - U32 res = 1024; - - lrad = samples*gi_range/(res-samples)*0.5f; - - F32 lrange = lrad+gi_range*0.5f; - - LLVector3 pad(lrange,lrange,lrange); - - glh::matrix4f view = look(LLVector3(128.f,128.f,128.f), lightDir, up); - - LLVector3 cp = camera.getOrigin()+camera.getAtAxis()*(gi_range*0.5f); - - glh::vec3f scp(cp.mV); - view.mult_matrix_vec(scp); - cp.setVec(scp.v); - - F32 pix_width = lrange/(res*0.5f); - - //lrad = llround(lrad, pix_width); - - //move cp to the nearest pix_width - for (U32 i = 0; i < 3; i++) - { - cp.mV[i] = llround(cp.mV[i], pix_width); - } - - LLVector3 min = cp-pad; - LLVector3 max = cp+pad; - - //set mGIRange to range in tc space[0,1] that covers texture block of intersecting lights around a point - mGIRange.mV[0] = (max.mV[0]-min.mV[0])/res; - mGIRange.mV[1] = (max.mV[1]-min.mV[1])/res; - mGILightRadius = lrad; - - glh::matrix4f proj = gl_ortho(min.mV[0], max.mV[0], - min.mV[1], max.mV[1], - -max.mV[2], -min.mV[2]); - - LLCamera sun_cam = camera; - - glh::matrix4f eye_view = glh_get_current_modelview(); - - //get eye space to camera space matrix - mGIMatrix = view*eye_view.inverse(); - mGINormalMatrix = mGIMatrix.inverse().transpose(); - mGIInvProj = proj.inverse(); - mGIMatrixProj = proj*mGIMatrix; - - //translate and scale to [0,1] - glh::matrix4f trans(.5f, 0.f, 0.f, .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); - - mGIMatrixProj = trans*mGIMatrixProj; - - glh_set_current_modelview(view); - glh_set_current_projection(proj); - - LLViewerCamera::updateFrustumPlanes(sun_cam, TRUE, FALSE, TRUE); - - sun_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR); - static LLCullResult result; - - U32 type_mask = mRenderTypeMask; - - mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) | - (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | - (1<<LLPipeline::RENDER_TYPE_BUMP) | - (1<<LLPipeline::RENDER_TYPE_VOLUME) | - (1<<LLPipeline::RENDER_TYPE_TREE) | - (1<<LLPipeline::RENDER_TYPE_TERRAIN) | - (1<<LLPipeline::RENDER_TYPE_WATER) | - (1<<LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW) | - (1<<LLPipeline::RENDER_TYPE_AVATAR) | - (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) | - (1 << LLPipeline::RENDER_TYPE_PASS_SHINY)); - - - - S32 occlude = LLPipeline::sUseOcclusion; - LLPipeline::sUseOcclusion = 0; - LLPipeline::sShadowRender = TRUE; - - updateCull(sun_cam, result); - stateSort(sun_cam, result); - - LLGLEnable cull(GL_CULL_FACE); - - //generate GI map - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadMatrixf(proj.m); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadMatrixf(view.m); - - stop_glerror(); - gGLLastMatrix = NULL; - - mGIMap.clear(); - - { - LLGLEnable enable(GL_DEPTH_CLAMP_NV); - renderGeomDeferred(camera); - } - - mGIMap.flush(); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - gGLLastMatrix = NULL; - - LLPipeline::sUseOcclusion = occlude; - LLPipeline::sShadowRender = FALSE; - - - mRenderTypeMask = type_mask; - -} - -void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade) -{ - if (!gSavedSettings.getBOOL("renderhighlights")) // KL need this to make the mouseover Highlights toggle ^^ - { - return; - } - - 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(LLViewerImage::sNullImagep, LLColor4(1,1,1,fade)); - } - } - } - } -} - -void LLPipeline::generateHighlight(LLCamera& camera) -{ - if (!gSavedSettings.getBOOL("renderhighlights")) // KL need this to make the mouseover Highlights toggle ^^ - { - return; - } - //render highlighted object as white into offscreen render target - - if (mHighlightObject.notNull()) - { - mHighlightSet.insert(HighlightItem(mHighlightObject)); - } - - if (!mHighlightSet.empty()) - { - F32 transition = gFrameIntervalSeconds/gSavedSettings.getF32("RenderHighlightFadeTime"); - - LLGLDisable test(GL_ALPHA_TEST); - LLGLDepthTest depth(GL_FALSE); - mHighlight.bindTarget(); - disableLights(); - gGL.setColorMask(true, true); - mHighlight.clear(); - - gGL.getTexUnit(0)->bind(LLViewerImage::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->setupViewport(); - } -} - - -void LLPipeline::generateSunShadow(LLCamera& camera) -{ - if (!sRenderDeferred) - { - return; - } - - LLFastTimer ftm(LLFastTimer::FTM_TEMP1); - - //temporary hack to disable shadows but keep local lights - static BOOL clear = TRUE; - BOOL gen_shadow = gSavedSettings.getBOOL("RenderDeferredSunShadow"); - if (!gen_shadow) - { - if (clear) - { - clear = FALSE; - for (U32 i = 0; i < 6; i++) - { - mShadow[i].bindTarget(); - mShadow[i].clear(); - mShadow[i].flush(); - } - } - return; - } - clear = TRUE; - - U32 type_mask = mRenderTypeMask; - mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) | - (1<<LLPipeline::RENDER_TYPE_ALPHA) | - (1<<LLPipeline::RENDER_TYPE_GRASS) | - (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | - (1<<LLPipeline::RENDER_TYPE_BUMP) | - (1<<LLPipeline::RENDER_TYPE_VOLUME) | - (1<<LLPipeline::RENDER_TYPE_AVATAR) | - (1<<LLPipeline::RENDER_TYPE_TREE) | - (1<<LLPipeline::RENDER_TYPE_TERRAIN) | - (1<<LLPipeline::RENDER_TYPE_WATER) | - (1<<LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW) | - (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_BUMP) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) | - (1 << LLPipeline::RENDER_TYPE_PASS_SHINY)); - - 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 = gSavedSettings.getVector3("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 = gSavedSettings.getVector3("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 = gSavedSettings.getVector3("RenderShadowNearDist"); - //F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] }; - - 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(); - - - F32 near_clip = 0.f; - { - //get visible point cloud - std::vector<LLVector3> fp; - - LLVector3 min,max; - getVisiblePointCloud(camera,min,max,fp); - - if (fp.empty()) + //choose an at axis such that up will be most aligned with lightDir + if (dl*dl < du*du) { - mRenderTypeMask = type_mask; - return; + at = lightDir%camera.getLeftAxis(); } - - generateGI(camera, lightDir, fp); - - //get good split distances for frustum - for (U32 i = 0; i < fp.size(); ++i) + else { - glh::vec3f v(fp[i].mV); - saved_view.mult_matrix_vec(v); - fp[i].setVec(v.v); + at = lightDir%camera.getUpAxis(); } - min = fp[0]; - max = fp[0]; - - //get camera space bounding box - for (U32 i = 1; i < fp.size(); ++i) + if (at * camera.getAtAxis() < 0) { - update_min_max(min, max, fp[i]); + at = -at; } - - 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 = gSavedSettings.getVector3("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] }; - - for (S32 j = 0; j < 4; j++) - { - if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA)) - { - mShadowFrustPoints[j].clear(); - } - - //restore render matrices - glh_set_current_modelview(saved_view); - glh_set_current_projection(saved_proj); - - LLVector3 eye = camera.getOrigin(); + LLVector3 left = lightDir%at; + up = left%lightDir; + up.normVec(); - //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); @@ -7944,6 +6224,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera) LLVector3 pn = shadow_cam.getAtAxis(); + LLVector3 frust_center; + LLVector3 min, max; //construct 8 corners of split frustum section @@ -7954,19 +6236,21 @@ void LLPipeline::generateSunShadow(LLCamera& camera) F32 dp = delta*pn; frust[i] = eye + (delta*dist[j])/dp; frust[i+4] = eye + (delta*dist[j+1])/dp; + frust_center += frust[i] + frust[i+4]; } + + //get frustum center + frust_center /= 8.f; 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)) + if (gPipeline.getVisibleExtents(shadow_cam, min, max)) { //no possible shadow receivers if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) @@ -7976,16 +6260,6 @@ void LLPipeline::generateSunShadow(LLCamera& camera) 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; } @@ -7993,252 +6267,42 @@ void LLPipeline::generateSunShadow(LLCamera& camera) { mShadowExtents[j][0] = min; mShadowExtents[j][1] = max; - mShadowFrustPoints[j] = fp; } + view[j] = look(frust_center-lightDir*nearDist[j], lightDir, up); + F32 shadow_dist = nearDist[j]; - //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++) + for (U32 i = 0; i < 8; 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]); + //points in worldspace (wp) and light camera space (p) + //that must be included in shadow generation + wp[i] = glh::vec3f(frust[i].mV); + wp[i+8] = wp[i] - light_dir*shadow_dist; + view[j].mult_matrix_vec(wp[i], p[i]); + view[j].mult_matrix_vec(wp[i+8], p[i+8]); } - - // 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]; - } + min = LLVector3(p[0].v); + max = LLVector3(p[0].v); - 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; + LLVector3 fmin = min; + LLVector3 fmax = max; - for (U32 i = 0; i < wpf.size(); ++i) + for (U32 i = 1; i < 16; i++) + { //find camera space AABB of frustum in light camera space + update_min_max(min, max, LLVector3(p[i].v)); + if (i < 8) { - //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]; + update_min_max(fmin, fmax, LLVector3(p[i].v)); } } - //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] > gSavedSettings.getF32("RenderShadowErrorCutoff")) - { //just use ortho projection - mShadowFOV.mV[j] = -1.f; - origin.clearVec(); + //generate perspective matrix that contains frustum + //proj[j] = matrix_perspective(min, max); 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(gSavedSettings.getF32("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); - - if (fovx > cutoff || llround(fovz, 0.01f) > cutoff) - { - // llwarns << "WTF?" << llendl; - } - - 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); @@ -8247,7 +6311,9 @@ void LLPipeline::generateSunShadow(LLCamera& camera) LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); - shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR); + proj[j] = gl_ortho(fmin.mV[0], fmax.mV[0], + fmin.mV[1], fmax.mV[1], + -fmax.mV[2], -fmin.mV[2]); //translate and scale to from [-1, 1] to [0, 1] glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, @@ -8260,154 +6326,110 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view; + U32 type_mask = mRenderTypeMask; + mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) | + (1<<LLPipeline::RENDER_TYPE_ALPHA) | + (1<<LLPipeline::RENDER_TYPE_GRASS) | + (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | + (1<<LLPipeline::RENDER_TYPE_BUMP) | + (1<<LLPipeline::RENDER_TYPE_VOLUME) | + (1<<LLPipeline::RENDER_TYPE_AVATAR) | + (1<<LLPipeline::RENDER_TYPE_TREE) | + (1<<LLPipeline::RENDER_TYPE_TERRAIN) | + 0); + + //clip out geometry on the same side of water as the camera + static LLCullResult result; + S32 occlude = LLPipeline::sUseOcclusion; + LLPipeline::sUseOcclusion = 1; + LLPipeline::sShadowRender = TRUE; //hack to prevent LOD updates from using sun camera origin shadow_cam.setOrigin(camera.getOrigin()); - - stop_glerror(); - - mShadow[j].bindTarget(); - mShadow[j].getViewport(gGLViewport); - - { - LLGLDepthTest depth(GL_TRUE); - mShadow[j].clear(); - } - - { - LLGLEnable enable(GL_DEPTH_CLAMP_NV); - renderShadow(view[j], proj[j], shadow_cam, FALSE); - } - - mShadow[j].flush(); + updateCull(shadow_cam, result); + stateSort(shadow_cam, result); if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) { LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); mShadowCamera[j+4] = shadow_cam; } - } - - //llinfos << "Shadow error: " << error << " Slope: " << best_fit_slope << llendl; - - F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f); + LLFastTimer t(LLFastTimer::FTM_SHADOW_RENDER); - //update shadow targets - for (U32 i = 0; i < 2; i++) - { //for each current shadow - 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; - } + stop_glerror(); - LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume(); + mSunShadow[j].bindTarget(); + mSunShadow[j].getViewport(gGLViewport); - if (!volume) { - mShadowSpotLight[i] = NULL; - continue; + LLGLDepthTest depth(GL_TRUE); + mSunShadow[j].clear(); } - 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); + U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP }; + LLGLEnable cull(GL_CULL_FACE); - 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(); + //generate sun shadow map + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(proj[j].m); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf(view[j].m); - //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; + stop_glerror(); + gGLLastMatrix = NULL; - F32 fovy = fov * RAD_TO_DEG; - F32 aspect = width/height; + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - 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; + glColor4f(1,1,1,1); - LLCamera shadow_cam = camera; - shadow_cam.setFar(far_clip); - shadow_cam.setOrigin(origin); - - LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); - - shadow_cam.setOrigin(camera.getOrigin()); + glCullFace(GL_FRONT); stop_glerror(); - mShadow[i+4].bindTarget(); - mShadow[i+4].getViewport(gGLViewport); + gGL.setColorMask(false, false); + gDeferredShadowProgram.bind(); { - LLGLDepthTest depth(GL_TRUE); - mShadow[i+4].clear(); + LLFastTimer ftm(LLFastTimer::FTM_SHADOW_SIMPLE); + LLGLDisable test(GL_ALPHA_TEST); + 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); + } + + { + LLFastTimer ftm(LLFastTimer::FTM_SHADOW_ALPHA); + LLGLEnable test(GL_ALPHA_TEST); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f); + renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE); + glColor4f(1,1,1,1); + renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } + + gDeferredShadowProgram.unbind(); + + renderGeomShadow(shadow_cam); - renderShadow(view[i+4], proj[i+4], shadow_cam, FALSE); + gGL.setColorMask(true, true); - mShadow[i+4].flush(); + glCullFace(GL_BACK); + LLPipeline::sUseOcclusion = occlude; + LLPipeline::sShadowRender = FALSE; + mRenderTypeMask = type_mask; + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + gGLLastMatrix = NULL; + + mSunShadow[j].flush(); } if (!gSavedSettings.getBOOL("CameraOffset")) @@ -8425,8 +6447,6 @@ void LLPipeline::generateSunShadow(LLCamera& camera) glMatrixMode(GL_MODELVIEW); } gGL.setColorMask(true, false); - - mRenderTypeMask = type_mask; } void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture) @@ -8466,7 +6486,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (muted) { - mask = 1 << LLPipeline::RENDER_TYPE_INVISIBLE; // Peachy ;) + mask = 1 << LLPipeline::RENDER_TYPE_AVATAR; } else { @@ -8477,16 +6497,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) (1<<LLPipeline::RENDER_TYPE_SIMPLE) | (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | (1<<LLPipeline::RENDER_TYPE_ALPHA) | - (1<<LLPipeline::RENDER_TYPE_INVISIBLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_SIMPLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA) | - (1 << LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK) | - (1 << LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY) | - (1 << LLPipeline::RENDER_TYPE_PASS_SHINY) | - (1 << LLPipeline::RENDER_TYPE_PASS_INVISIBLE) | - (1 << LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY); + (1<<LLPipeline::RENDER_TYPE_INVISIBLE); } mask = mask & gPipeline.getRenderTypeMask(); @@ -8496,7 +6507,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) S32 occlusion = sUseOcclusion; sUseOcclusion = 0; sReflectionRender = sRenderDeferred ? FALSE : TRUE; - sShadowRender = TRUE; sImpostorRender = TRUE; markVisible(avatar->mDrawable, *LLViewerCamera::getInstance()); @@ -8576,7 +6586,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (LLPipeline::sRenderDeferred) { avatar->mImpostor.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE); - //addDeferredAttachments(avatar->mImpostor); + addDeferredAttachments(avatar->mImpostor); } else { @@ -8655,7 +6665,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) sUseOcclusion = occlusion; sReflectionRender = FALSE; sImpostorRender = FALSE; - sShadowRender = FALSE; gPipeline.mRenderTypeMask = saved_mask; glMatrixMode(GL_PROJECTION); diff --git a/linden/indra/newview/pipeline.h b/linden/indra/newview/pipeline.h index 7c56375..1ecb56e 100644 --- a/linden/indra/newview/pipeline.h +++ b/linden/indra/newview/pipeline.h @@ -129,8 +129,6 @@ public: void markMoved(LLDrawable *drawablep, BOOL damped_motion = FALSE); void markShift(LLDrawable *drawablep); void markTextured(LLDrawable *drawablep); - void markGLRebuild(LLGLUpdate* glu); - void markRebuild(LLSpatialGroup* group, BOOL priority = FALSE); void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE); //get the object between start and end that's closest to start. @@ -181,14 +179,10 @@ public: void updateMove(); BOOL visibleObjectsInFrustum(LLCamera& camera); BOOL getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max); - BOOL getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir = LLVector3(0,0,0)); void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane void createObjects(F32 max_dtime); void createObject(LLViewerObject* vobj); void updateGeom(F32 max_dtime); - void updateGL(); - void rebuildPriorityGroups(); - void rebuildGroups(); //calculate pixel area of given box from vantage point of given camera static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera); @@ -209,21 +203,12 @@ public: void renderGeomDeferred(LLCamera& camera); void renderGeomPostDeferred(LLCamera& camera); void renderGeomShadow(LLCamera& camera); - void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0, LLRenderTarget* gi_source = NULL, LLRenderTarget* last_gi_post = NULL); - void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep); - + void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0); void unbindDeferredShader(LLGLSLShader& shader); void renderDeferredLighting(); void generateWaterReflection(LLCamera& camera); void generateSunShadow(LLCamera& camera); - void generateHighlight(LLCamera& camera); - void renderHighlight(const LLViewerObject* obj, F32 fade); - void setHighlightObject(LLDrawable* obj) { mHighlightObject = obj; } - - - void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, BOOL use_shader = TRUE); - void generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<LLVector3>& vpc); // KL sd void renderHighlights(); void renderDebug(); @@ -331,27 +316,15 @@ public: RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE, RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER, RENDER_TYPE_WATER = LLDrawPool::POOL_WATER, - RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA, + RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA, RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW, - RENDER_TYPE_PASS_SIMPLE = LLRenderPass::PASS_SIMPLE, - RENDER_TYPE_PASS_GRASS = LLRenderPass::PASS_GRASS, - RENDER_TYPE_PASS_FULLBRIGHT = LLRenderPass::PASS_FULLBRIGHT, - RENDER_TYPE_PASS_INVISIBLE = LLRenderPass::PASS_INVISIBLE, - RENDER_TYPE_PASS_INVISI_SHINY = LLRenderPass::PASS_INVISI_SHINY, - RENDER_TYPE_PASS_FULLBRIGHT_SHINY = LLRenderPass::PASS_FULLBRIGHT_SHINY, - RENDER_TYPE_PASS_SHINY = LLRenderPass::PASS_SHINY, - RENDER_TYPE_PASS_BUMP = LLRenderPass::PASS_BUMP, - RENDER_TYPE_PASS_GLOW = LLRenderPass::PASS_GLOW, - RENDER_TYPE_PASS_ALPHA = LLRenderPass::PASS_ALPHA, - RENDER_TYPE_PASS_ALPHA_MASK = LLRenderPass::PASS_ALPHA_MASK, - RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, - RENDER_TYPE_PASS_ALPHA_SHADOW = LLRenderPass::PASS_ALPHA_SHADOW, + // Following are object types (only used in drawable mRenderType) RENDER_TYPE_HUD = LLDrawPool::NUM_POOL_TYPES, RENDER_TYPE_VOLUME, RENDER_TYPE_PARTICLES, RENDER_TYPE_CLOUDS, - RENDER_TYPE_HUD_PARTICLES // KL S19? + RENDER_TYPE_HUD_PARTICLES }; enum LLRenderDebugFeatureMask @@ -389,7 +362,8 @@ public: RENDER_DEBUG_SHAME = 0x0020000, RENDER_DEBUG_SHADOW_FRUSTA = 0x0040000, RENDER_DEBUG_SCULPTED = 0x0080000, - RENDER_DEBUG_BUILD_QUEUE = 0x0100000, + RENDER_DEBUG_AVATAR_VOLUME = 0x0100000, + RENDER_DEBUG_AGENT_TARGET = 0x0200000, }; public: @@ -448,36 +422,15 @@ public: //screen texture LLRenderTarget mScreen; LLRenderTarget mDeferredScreen; - LLRenderTarget mDeferredDepth; - LLRenderTarget mDeferredLight[3]; + LLRenderTarget mDeferredLight[2]; LLMultisampleBuffer mSampleBuffer; - LLRenderTarget mGIMap; - LLRenderTarget mGIMapPost[2]; - LLRenderTarget mLuminanceMap; - LLRenderTarget mHighlight; //sun shadow map - LLRenderTarget mShadow[6]; - std::vector<LLVector3> mShadowFrustPoints[4]; - LLVector4 mShadowError; - LLVector4 mShadowFOV; - LLVector3 mShadowFrustOrigin[4]; + LLRenderTarget mSunShadow[4]; LLCamera mShadowCamera[8]; LLVector3 mShadowExtents[4][2]; - glh::matrix4f mSunShadowMatrix[6]; - glh::matrix4f mGIMatrix; - glh::matrix4f mGIMatrixProj; - glh::matrix4f mGINormalMatrix; - glh::matrix4f mGIInvProj; - LLVector2 mGIRange; - F32 mGILightRadius; - - LLPointer<LLDrawable> mShadowSpotLight[2]; - F32 mSpotLightFade[2]; - LLPointer<LLDrawable> mTargetShadowSpotLight[2]; - + glh::matrix4f mSunShadowMatrix[4]; LLVector4 mSunClipPlanes; - LLVector4 mSunOrthoClipPlanes; LLVector2 mScreenScale; @@ -492,8 +445,6 @@ public: //noise map U32 mNoiseMap; - U32 mTrueNoiseMap; - U32 mLightFunc; LLColor4 mSunDiffuse; LLVector3 mSunDir; @@ -554,45 +505,12 @@ protected: // LLDrawable::drawable_list_t mBuildQ1; // priority LLDrawable::drawable_list_t mBuildQ2; // non-priority - LLSpatialGroup::sg_list_t mGroupQ1; //priority - LLSpatialGroup::sg_vector_t mGroupQ2; // non-priority - LLViewerObject::vobj_list_t mCreateQ; LLDrawable::drawable_set_t mActiveQ; LLDrawable::drawable_set_t mRetexturedList; - class HighlightItem - { - public: - const LLPointer<LLDrawable> mItem; - mutable F32 mFade; - - HighlightItem(LLDrawable* item) - : mItem(item), mFade(0) - { - } - - bool operator<(const HighlightItem& rhs) const - { - return mItem < rhs.mItem; - } - - bool operator==(const HighlightItem& rhs) const - { - return mItem == rhs.mItem; - } - - void incrFade(F32 val) const - { - mFade = llclamp(mFade+val, 0.f, 1.f); - } - }; - - std::set<HighlightItem> mHighlightSet; - LLPointer<LLDrawable> mHighlightObject; - ////////////////////////////////////////////////// // // Draw pools are responsible for storing all rendered data, diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_hardware_settings.xml b/linden/indra/newview/skins/default/xui/en-us/floater_hardware_settings.xml index e85eaa8..24a895b 100644 --- a/linden/indra/newview/skins/default/xui/en-us/floater_hardware_settings.xml +++ b/linden/indra/newview/skins/default/xui/en-us/floater_hardware_settings.xml @@ -64,35 +64,7 @@ tool_tip="Enabling this on modern hardware gives a performance gain. However, older hardware often has poor implementations of VBOs and you may get crashes when this is enabled." width="315" /> - <text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false" - bottom_delta="-20" drop_shadow_visible="true" enabled="true" follows="left|top" - font="SansSerifSmall" h_pad="0" halign="left" height="12" - left="10" mouse_opaque="true" name="Enable FBO:" v_pad="0" - width="128"> - Enable FBO: - </text> - <check_box bottom_delta="-5" control_name="RenderUseFBO" enabled="true" follows="left|top" - font="SansSerifSmall" height="16" initial_value="true" - label="Enable OpenGL Framebuffer Objects" left="148" - mouse_opaque="true" name="fbo" radio_style="false" - tool_tip="Enabling this will use OpenGL Framebuffer objects for some dynamic textures. Prerequisite for deferred rendering." - width="315" /> - - <text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false" - bottom_delta="-20" drop_shadow_visible="true" enabled="true" follows="left|top" - font="SansSerifSmall" h_pad="0" halign="left" height="12" - left="10" mouse_opaque="true" name="Deferred Rendering:" v_pad="0" - width="128"> - Deferred Rendering: - </text> - <check_box bottom_delta="-5" control_name="RenderDeferred" enabled="true" follows="left|top" - font="SansSerifSmall" height="16" initial_value="true" - label="Enable per-pixel lighting and shadows" left="148" - mouse_opaque="true" name="deferred" radio_style="false" - tool_tip="Enabling this will perform lighting calculations in screen space, enabling per pixel lighting for all lights and shadows from the sun/moon. Requires a fast graphics card. Might not be compatible with FSAA." - width="315" /> - - <slider bottom_delta="-21" can_edit_text="false" control_name="TextureMemory" + <slider bottom_delta="-21" can_edit_text="false" control_name="TextureMemory" decimal_digits="0" enabled="true" follows="left|top" height="16" increment="16" initial_val="32" label="Texture Memory (MB):" label_width="135" left="10" diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_tools.xml b/linden/indra/newview/skins/default/xui/en-us/floater_tools.xml index 1be2e58..0cb4a59 100644 --- a/linden/indra/newview/skins/default/xui/en-us/floater_tools.xml +++ b/linden/indra/newview/skins/default/xui/en-us/floater_tools.xml @@ -1036,47 +1036,25 @@ <text bg_visible="false" border_drop_shadow_visible="false" border_visible="false" bottom_delta="-21" drop_shadow_visible="true" follows="left|top" font="SansSerifSmall" h_pad="0" halign="left" height="10" left_delta="0" - mouse_opaque="true" name="label color" v_pad="0" width="57"> + mouse_opaque="true" name="label color" v_pad="0" width="58"> Color: </text> <color_swatch border_color="0.45098, 0.517647, 0.607843, 1" bottom_delta="-28" can_apply_immediately="true" color="0.5, 0.5, 0.5, 1" follows="left|top" - height="48" label="" left_delta="57" mouse_opaque="true" name="colorswatch" + height="48" label="" left_delta="67" mouse_opaque="true" name="colorswatch" tool_tip="Click to open Color Picker" width="32" /> - <text bg_visible="false" border_drop_shadow_visible="false" border_visible="false" - bottom_delta="28" drop_shadow_visible="true" follows="left|top" - font="SansSerifSmall" h_pad="0" height="10" left="144" - mouse_opaque="true" name="label texture" v_pad="0" width="58"> - Texture - </text> - <texture_picker allow_no_texture="true" bottom_delta="-28" can_apply_immediately="true" - default_image_name="Default" follows="left|top" height="48" label="" - left_delta="57" mouse_opaque="true" name="light texture control" - tool_tip="Click to choose a projection image (only has effect with deferred rendering enabled)" width="32" /> <spinner bottom_delta="-4" decimal_digits="3" follows="left|top" height="16" - increment="0.1" initial_val="0.5" label="Intensity:" label_width="55" - left="10" max_val="1" min_val="0" mouse_opaque="true" - name="Light Intensity" width="120" /> - <spinner bottom_delta="0" decimal_digits="3" follows="left|top" height="16" - increment="0.1" initial_val="0.5" label="FOV" label_width="55" - left="144" max_val="3" min_val="0" mouse_opaque="true" - name="Light FOV" width="120" /> + increment="0.1" initial_val="0.5" label="Intensity:" label_width="65" + left="10" max_val="1" min_val="0" mouse_opaque="true" + name="Light Intensity" width="128" /> <spinner bottom_delta="-20" decimal_digits="3" follows="left|top" height="16" - increment="0.1" initial_val="5" label="Radius" label_width="55" - left="10" max_val="20" min_val="0" mouse_opaque="true" - name="Light Radius" width="120" /> - <spinner bottom_delta="0" decimal_digits="3" follows="left|top" height="16" - increment="0.5" initial_val="0.5" label="Focus" label_width="55" - left="144" max_val="20" min_val="-20" mouse_opaque="true" - name="Light Focus" width="120" /> + increment="0.1" initial_val="5" label="Radius:" label_width="65" + left_delta="0" max_val="20" min_val="0" mouse_opaque="true" + name="Light Radius" width="128" /> <spinner bottom_delta="-20" decimal_digits="3" follows="left|top" height="16" - increment="0.25" initial_val="1" label="Falloff" label_width="55" - left="10" max_val="2" min_val="0" mouse_opaque="true" - name="Light Falloff" width="120" /> - <spinner bottom_delta="0" decimal_digits="3" follows="left|top" height="16" - increment="0.05" initial_val="1" label="Ambiance" label_width="55" - left="144" max_val="1" min_val="0" mouse_opaque="true" - name="Light Ambiance" width="120" /> + increment="0.25" initial_val="1" label="Falloff:" label_width="65" + left_delta="0" max_val="2" min_val="0" mouse_opaque="true" + name="Light Falloff" width="128" /> </panel> <!-- Texture sub-tab --> -- cgit v1.1 From 67f55bad571044535f1d8c3b3c3afb5078249fd3 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 15 Oct 2010 17:49:06 +0200 Subject: RED-595: Manual merge with weekly-webkit. Plus some white space fixes (TABs --> spaces) in install.xml. --- linden/doc/contributions.txt | 2 + linden/indra/cmake/FindLLQtWebkit.cmake | 62 ++++++++++++++++++++ linden/indra/cmake/WebKitLibPlugin.cmake | 38 ++++++------ linden/indra/llwindow/llwindow.h | 2 +- linden/indra/llwindow/llwindowsdl.cpp | 3 +- linden/indra/newview/linux_tools/wrapper.sh | 13 ++--- linden/indra/newview/llfloaterhtmlhelp.cpp | 2 +- linden/indra/newview/llmediactrl.cpp | 3 +- linden/indra/newview/llstartup.cpp | 4 -- linden/indra/newview/secondlife-i686.supp | 44 -------------- .../newview/skins/default/xui/zh/mime_types.xml | 9 --- linden/indra/newview/viewer_manifest.py | 6 +- linden/install.xml | 68 +++++++++++----------- 13 files changed, 132 insertions(+), 124 deletions(-) create mode 100644 linden/indra/cmake/FindLLQtWebkit.cmake (limited to 'linden') diff --git a/linden/doc/contributions.txt b/linden/doc/contributions.txt index 931794c..4d3f017 100644 --- a/linden/doc/contributions.txt +++ b/linden/doc/contributions.txt @@ -80,6 +80,7 @@ Aleric Inglewood RED-578 RED-579 RED-581 + RED-595 Alissa Sabre VWR-81 VWR-83 @@ -512,6 +513,7 @@ Robin Cornelius VWR-2488 VWR-9557 VWR-12838 + RED-595 Ryozu Kojima VWR-53 VWR-287 diff --git a/linden/indra/cmake/FindLLQtWebkit.cmake b/linden/indra/cmake/FindLLQtWebkit.cmake new file mode 100644 index 0000000..c747ec3 --- /dev/null +++ b/linden/indra/cmake/FindLLQtWebkit.cmake @@ -0,0 +1,62 @@ +# -*- cmake -*- + +# - Find llqtwebkit +# Find the llqtwebkit includes and library +# This module defines +# LLQTWEBKIT_INCLUDE_DIR, where to find llqtwebkit.h, etc. +# LLQTWEBKIT_LIBRARY, the llqtwebkit library with full path. +# LLQTWEBKIT_FOUND, If false, do not try to use llqtwebkit. +# also defined, but not for general use are +# LLQTWEBKIT_LIBRARIES, the libraries needed to use llqtwebkit. +# LLQTWEBKIT_LIBRARY_DIRS, where to find the llqtwebkit library. +# LLQTWEBKIT_DEFINITIONS - You should add_definitions(${LLQTWEBKIT_DEFINITIONS}) +# before compiling code that includes llqtwebkit library files. + +# Try to use pkg-config first. +# This allows to have two different libllqtwebkit packages installed: +# one for viewer 2.x and one for viewer 1.x. +include(FindPkgConfig) +if (PKG_CONFIG_FOUND) + if (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION) + set(_PACKAGE_ARGS libllqtwebkit>=${LLQtWebkit_FIND_VERSION} REQUIRED) + else (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION) + set(_PACKAGE_ARGS libllqtwebkit) + endif (LLQtWebkit_FIND_REQUIRED AND LLQtWebkit_FIND_VERSION) + if (NOT "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_LESS "2.8") + # As virtually nobody will have a pkg-config file for this, do this check always quiet. + # Unfortunately cmake 2.8 or higher is required for pkg_check_modules to have a 'QUIET'. + set(_PACKAGE_ARGS ${_PACKAGE_ARGS} QUIET) + endif () + pkg_check_modules(LLQTWEBKIT ${_PACKAGE_ARGS}) +endif (PKG_CONFIG_FOUND) +set(LLQTWEBKIT_DEFINITIONS ${LLQTWEBKIT_CFLAGS_OTHER}) + +find_path(LLQTWEBKIT_INCLUDE_DIR llqtwebkit.h NO_SYSTEM_ENVIRONMENT_PATH HINTS ${LLQTWEBKIT_INCLUDE_DIRS}) + +find_library(LLQTWEBKIT_LIBRARY NAMES llqtwebkit NO_SYSTEM_ENVIRONMENT_PATH HINTS ${LLQTWEBKIT_LIBRARY_DIRS}) + +if (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND) # If pkg-config couldn't find it, pretend we don't have pkg-config. + set(LLQTWEBKIT_LIBRARIES llqtwebkit) + get_filename_component(LLQTWEBKIT_LIBRARY_DIRS ${LLQTWEBKIT_LIBRARY} PATH) +endif (NOT PKG_CONFIG_FOUND OR NOT LLQTWEBKIT_FOUND) + +# Handle the QUIETLY and REQUIRED arguments and set LLQTWEBKIT_FOUND +# to TRUE if all listed variables are TRUE. +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + LLQTWEBKIT + DEFAULT_MSG + LLQTWEBKIT_LIBRARY + LLQTWEBKIT_INCLUDE_DIR + LLQTWEBKIT_LIBRARIES + LLQTWEBKIT_LIBRARY_DIRS + ) + +mark_as_advanced( + LLQTWEBKIT_LIBRARY + LLQTWEBKIT_INCLUDE_DIR + LLQTWEBKIT_LIBRARIES + LLQTWEBKIT_LIBRARY_DIRS + LLQTWEBKIT_DEFINITIONS + ) + diff --git a/linden/indra/cmake/WebKitLibPlugin.cmake b/linden/indra/cmake/WebKitLibPlugin.cmake index 23958fe..3eafe77 100644 --- a/linden/indra/cmake/WebKitLibPlugin.cmake +++ b/linden/indra/cmake/WebKitLibPlugin.cmake @@ -3,6 +3,7 @@ include(Linking) include(Prebuilt) if (STANDALONE) + find_package(LLQtWebkit REQUIRED QUIET) set(WEBKITLIBPLUGIN OFF CACHE BOOL "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.") else (STANDALONE) @@ -31,25 +32,26 @@ if (WINDOWS) elseif (DARWIN) set(WEBKIT_PLUGIN_LIBRARIES optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib - debug ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib + debug ${ARCH_PREBUILT_DIRS_DEBUG}/libllqtwebkit.dylib ) elseif (LINUX) - if (STANDALONE) - set(WEBKIT_PLUGIN_LIBRARIES llqtwebkit) - else (STANDALONE) + if (STANDALONE) + set(WEBKIT_PLUGIN_LIBRARIES ${LLQTWEBKIT_LIBRARY}) + else (STANDALONE) set(WEBKIT_PLUGIN_LIBRARIES - llqtwebkit - qgif - qjpeg - QtWebKit - QtOpenGL - QtNetwork - QtGui - QtCore - fontconfig - X11 - Xrender - GL - ) - endif (STANDALONE) + llqtwebkit + qgif + qjpeg + QtWebKit + QtOpenGL + QtNetwork + QtGui + QtCore + jpeg + fontconfig + X11 + Xrender + GL + ) + endif (STANDALONE) endif (WINDOWS) diff --git a/linden/indra/llwindow/llwindow.h b/linden/indra/llwindow/llwindow.h index 2e96294..5e93ab3 100644 --- a/linden/indra/llwindow/llwindow.h +++ b/linden/indra/llwindow/llwindow.h @@ -196,7 +196,7 @@ public: // return a platform-specific window reference (HWND on Windows, WindowRef on the Mac, Gtk window on Linux) virtual void *getPlatformWindow() = 0; -// return the platform-specific window reference we use to initialize llmozlib (HWND on Windows, WindowRef on the Mac, Gtk window on Linux) +// return the platform-specific window reference we use to initialize llqtwebkitlib (HWND on Windows, WindowRef on the Mac, Gtk window on Linux) virtual void *getMediaWindow(); // control platform's Language Text Input mechanisms. diff --git a/linden/indra/llwindow/llwindowsdl.cpp b/linden/indra/llwindow/llwindowsdl.cpp index fa53c84..16106af 100644 --- a/linden/indra/llwindow/llwindowsdl.cpp +++ b/linden/indra/llwindow/llwindowsdl.cpp @@ -1606,6 +1606,7 @@ void LLWindowSDL::processMiscNativeEvents() // the locale to protect it, as exotic/non-C locales // causes our code lots of general critical weirdness // and crashness. (SL-35450) + // Note: It is unknown if this is still needed now that we use webkit. static std::string saved_locale; saved_locale = ll_safe_string(setlocale(LC_ALL, NULL)); @@ -2433,7 +2434,7 @@ void *LLWindowSDL::getPlatformWindow() return rtnw; } #endif // LL_GTK && LL_LLMOZLIB_ENABLED - // Unixoid mozilla really needs GTK. + llassert(false); // Do we even GET here at all? Note that LL_LLMOZLIB_ENABLED is never defined! return NULL; } diff --git a/linden/indra/newview/linux_tools/wrapper.sh b/linden/indra/newview/linux_tools/wrapper.sh index 8c47434..a43ebd5 100755 --- a/linden/indra/newview/linux_tools/wrapper.sh +++ b/linden/indra/newview/linux_tools/wrapper.sh @@ -106,17 +106,16 @@ if [ -n "$LL_TCMALLOC" ]; then fi fi fi -BINARY_SYSTEM=$(expr match "$(file -b /bin/uname)" '\(.*executable\)') -BINARY_VIEWER=$(expr match "$(file -b ${RUN_PATH}/bin/do-not-directly-run-imprudence-bin)" '\(.*executable\)') -echo "viewer: $BINARY_VIEWER system: $BINARY_SYSTEM" -if ( [ "$BINARY_SYSTEM" == "ELF 64-bit LSB executable" ] && [ "$BINARY_VIEWER" == "ELF 64-bit LSB executable" ] ); then - export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib64:"`pwd`"/lib32:"`pwd`"/app_settings/mozilla-runtime-linux-x86_64:"${LD_LIBRARY_PATH}"' +export VIEWER_BINARY='do-not-directly-run-imprudence-bin' +BINARY_TYPE=$(expr match "$(file -b bin/$VIEWER_BINARY)" '\(.*executable\)') +if [ "${BINARY_TYPE}" == "ELF 64-bit LSB executable" ]; then + export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib64:"`pwd`"/lib32:"${LD_LIBRARY_PATH}"' else - export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"`pwd`"/app_settings/mozilla-runtime-linux-i686:"${LD_LIBRARY_PATH}"' + export SL_ENV='LD_LIBRARY_PATH="`pwd`"/lib:"${LD_LIBRARY_PATH}"' fi -export SL_CMD='$LL_WRAPPER bin/do-not-directly-run-imprudence-bin' +export SL_CMD='$LL_WRAPPER bin/$VIEWER_BINARY' export SL_OPT="`cat gridargs.dat` $@" # Run the program diff --git a/linden/indra/newview/llfloaterhtmlhelp.cpp b/linden/indra/newview/llfloaterhtmlhelp.cpp index 1777403..1ec964b 100644 --- a/linden/indra/newview/llfloaterhtmlhelp.cpp +++ b/linden/indra/newview/llfloaterhtmlhelp.cpp @@ -534,7 +534,7 @@ void LLFloaterHtmlHelp::onStatusTextChange( const EventType& eventIn ) // void LLFloaterHtmlHelp::onLocationChange( const EventType& eventIn ) { - llinfos << "MOZ> Location changed to " << eventIn.getStringValue() << llendl; + llinfos << "WEB> Location changed to " << eventIn.getStringValue() << llendl; mCurrentUrl = std::string( eventIn.getStringValue() ); } diff --git a/linden/indra/newview/llmediactrl.cpp b/linden/indra/newview/llmediactrl.cpp index 1530598..c3bcf85 100644 --- a/linden/indra/newview/llmediactrl.cpp +++ b/linden/indra/newview/llmediactrl.cpp @@ -199,8 +199,9 @@ BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) { mMediaSource->mouseUp(x, y); - // *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup, + // *HACK: media_plugin_webkit automatically takes focus on mouseup, // in addition to the onFocusReceived() call below. Undo this. JC + // RED-595: Is this really still the case for webkit? if (!mTakeFocusOnClick) { mMediaSource->focus(false); diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index bd22772..7bd5fff 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp @@ -199,10 +199,6 @@ #include <Security/Security.h> #endif -#if LL_LIBXUL_ENABLED -#include "llmozlib.h" -#endif // LL_LIBXUL_ENABLED - #if LL_WINDOWS #include "llwindebug.h" #include "lldxhardware.h" diff --git a/linden/indra/newview/secondlife-i686.supp b/linden/indra/newview/secondlife-i686.supp index 43d4483..d70cda3 100644 --- a/linden/indra/newview/secondlife-i686.supp +++ b/linden/indra/newview/secondlife-i686.supp @@ -41,50 +41,6 @@ # - After you build the viewer, replace the stripped # do-not-directly-run-secondlife-bin binary with an unstripped copy. -# Mozilla noise. - -{ - Cond:mozilla-runtime/*.so - Memcheck:Cond - obj:*/mozilla-runtime-*/*.so -} - -{ - Value4:mozilla-runtime/*.so - Memcheck:Value4 - obj:*/mozilla-runtime-*/*.so -} - -{ - Cond:mozilla-runtime/*/*.so - Memcheck:Cond - obj:*/mozilla-runtime-*/*/*.so -} - -{ - Value4:mozilla-runtime/*/*.so - Memcheck:Value4 - obj:*/mozilla-runtime-*/*/*.so -} - -{ - Cond:mozilla-runtime/libmozjs.so - Memcheck:Cond - obj:*/libmozjs.so -} - -{ - Cond:mozilla-runtime/libxul - Memcheck:Cond - obj:*/libxul.so -} - -{ - Value4:mozilla-runtime/libxul - Memcheck:Value4 - obj:*/libxul.so -} - # libcurl badness. { diff --git a/linden/indra/newview/skins/default/xui/zh/mime_types.xml b/linden/indra/newview/skins/default/xui/zh/mime_types.xml index fc5fae4..0cc6f2f 100644 --- a/linden/indra/newview/skins/default/xui/zh/mime_types.xml +++ b/linden/indra/newview/skins/default/xui/zh/mime_types.xml @@ -1,14 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <mimetypes name="default"> - <defaultlabel> - (未知) - </defaultlabel> - <defaultwidget> - æ—  - </defaultwidget> - <defaultimpl> - LLMediaImplLLMozLib - </defaultimpl> <widgetset name="web"> <label name="web_label"> 网页内容 diff --git a/linden/indra/newview/viewer_manifest.py b/linden/indra/newview/viewer_manifest.py index 314cb65..143d946 100755 --- a/linden/indra/newview/viewer_manifest.py +++ b/linden/indra/newview/viewer_manifest.py @@ -949,7 +949,6 @@ class Linux_i686Manifest(LinuxManifest): super(Linux_i686Manifest, self).construct() self.path("imprudence-stripped","bin/do-not-directly-run-imprudence-bin") - if (not self.standalone()) and self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"): self.path("libapr-1.so.0") self.path("libaprutil-1.so.0") @@ -1076,9 +1075,6 @@ class Linux_x86_64Manifest(LinuxManifest): self.path("featuretable_linux.txt") #self.path("secondlife-x86_64.supp") - if not self.standalone(): - self.path("app_settings/mozilla-runtime-linux-x86_64") - if (not self.standalone()) and self.prefix("../../libraries/x86_64-linux/lib_release_client", dst="lib64"): self.path("libapr-1.so.0") self.path("libaprutil-1.so.0") @@ -1090,7 +1086,7 @@ class Linux_x86_64Manifest(LinuxManifest): self.path("libuuid.so", "libuuid.so.1") self.path("libSDL-1.2.so.0") self.path("libELFIO.so") - self.path("libjpeg.so.7") + self.path("libjpeg.so.62") self.path("libpng12.so.0") self.path("libopenjpeg.so.2") self.path("libxml2.so.2") diff --git a/linden/install.xml b/linden/install.xml index 0c20157..b1efd11 100755 --- a/linden/install.xml +++ b/linden/install.xml @@ -74,13 +74,13 @@ <key>url</key> <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/SDL-1.2.5-linux-i686-gcc-4.1-20080915.tar.bz2</uri> </map> - <key>linux64</key> - <map> - <key>md5sum</key> - <string>214fe53a11b3cdef115d36cb95aae185</string> - <key>url</key> - <uri>http://imprudenceviewer.org/download/libs/SDL-1.2.12-linux64-20091230.tar.bz2</uri> - </map> + <key>linux64</key> + <map> + <key>md5sum</key> + <string>214fe53a11b3cdef115d36cb95aae185</string> + <key>url</key> + <uri>http://imprudenceviewer.org/download/libs/SDL-1.2.12-linux64-20091230.tar.bz2</uri> + </map> <key>windows</key> <map> <key>md5sum</key> @@ -295,7 +295,7 @@ </map> </map> </map> - <key>dbghelp</key> + <key>dbghelp</key> <map> <key>copyright</key> <string>Copyright Microsoft Corporation</string> @@ -327,9 +327,9 @@ <key>linux</key> <map> <key>md5sum</key> - <string>eb25444142d4102b0ce1b7ffaadb071e</string> + <string>bfcff12c0d5cef53aa2e04fa53299b23</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/dbusglib-linux-20080707.tar.bz2</uri> + <uri>http://github.com/downloads/AlericInglewood/imprudence/dbusglib-linux-20101012.tar.bz2</uri> </map> <key>linux64</key> <map> @@ -816,9 +816,9 @@ cairo: Copyright © 2002 University of Southern California, Copyright © 2005 Re <key>linux64</key> <map> <key>md5sum</key> - <string>64e7fa98568ef52b3b9d4a18b3515090</string> + <string>8b5f413bdefec7cfe3d9ad2d69986bdc</string> <key>url</key> - <uri>http://imprudenceviewer.org/download/libs/jpeglib-7-linux64-20091230.tar.bz2</uri> + <uri>http://github.com/downloads/AlericInglewood/imprudence/jpeglib-6b-linux64-20101012.tar.bz2</uri> </map> <key>windows</key> <map> @@ -1057,23 +1057,30 @@ Portions copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura <key>darwin</key> <map> <key>md5sum</key> - <string>becffca6bd8dcb239de284ea2a8b485b</string> + <string>34d9e4c93678a422cf80521bf0cd7628</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6+cookies-darwin-20100617.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20100914.tar.bz2</uri> </map> <key>linux</key> <map> <key>md5sum</key> - <string>414d72dd59e3d83c96f0e1531360792e</string> + <string>5d743c93b970abe685b185de83001a6e</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-20100618.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-linux-qt4.6-20100923.tar.bz2</uri> + </map> + <key>linux64</key> + <map> + <key>md5sum</key> + <string>863f7b31556b1d368651f85457f4e46d</string> + <key>url</key> + <uri>http://github.com/downloads/AlericInglewood/imprudence/llqtwebkit-linux64-20101012.1.tar.bz2</uri> </map> <key>windows</key> <map> <key>md5sum</key> - <string>df1bdd683128e060d60e435f65d8f7e8</string> + <string>4b8412833c00f8cdaba26808f0ddb404</string> <key>url</key> - <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.6-20100617.tar.bz2</uri> + <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.6-20100916.tar.bz2</uri> </map> </map> </map> @@ -1636,7 +1643,7 @@ Copyright (C) 2004-2005 Vladimir Berezniker @ http://public.xdi.org/=vmpn <key>url</key> <string>http://www.xfree86.org/4.4.0/LICENSE9.html#sgi</string> </map> - <key>MSDTW</key> + <key>MSDTW</key> <map> <key>text</key> <string>MICROSOFT SOFTWARE LICENSE TERMS @@ -1843,12 +1850,12 @@ Cass Everitt - cass@r3.nu <key>text</key> <string>on file</string> </map> - <key>hunspell</key> + <key>hunspell</key> <map> <key>url</key> <string>http://www.gnu.org/licenses/gpl.html</string> </map> - <key>hunspell-dictionaries</key> + <key>hunspell-dictionaries</key> <map> <key>url</key> <string>http://www.gnu.org/licenses/gpl.html</string> @@ -1864,13 +1871,13 @@ Cass Everitt - cass@r3.nu <key>text</key> <string>http://nyctergatis.com/jpeglib/</string> </map> - <key>jsoncpp</key> - <map> - <key>text</key> - <string>The json-cpp library and this documentation are in Public Domain. Retrieved from http://jsoncpp.sourceforge.net/ on 2009-09-04.</string> - <key>url</key> - <string>http://jsoncpp.sourceforge.net</string> - </map> + <key>jsoncpp</key> + <map> + <key>text</key> + <string>The json-cpp library and this documentation are in Public Domain. Retrieved from http://jsoncpp.sourceforge.net/ on 2009-09-04.</string> + <key>url</key> + <string>http://jsoncpp.sourceforge.net</string> + </map> <key>kdu</key> <map> <key>text</key> @@ -1911,11 +1918,6 @@ Cass Everitt - cass@r3.nu <key>text</key> <string>Multiple licenses. See package contents for details.</string> </map> - <key>mozillaPL</key> - <map> - <key>url</key> - <string>http://www.mozilla.org/MPL/MPL-1.1.html</string> - </map> <key>xiph-bsd</key> <map> <key>url</key> -- cgit v1.1 From 0bf2f0afa632a379a32f08cf9b3e77f76c3a13da Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 15 Oct 2010 17:58:59 +0200 Subject: Add missing semi-colon. --- linden/indra/llmath/llvolume.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linden') diff --git a/linden/indra/llmath/llvolume.cpp b/linden/indra/llmath/llvolume.cpp index b0b8a94..c4c3f07 100644 --- a/linden/indra/llmath/llvolume.cpp +++ b/linden/indra/llmath/llvolume.cpp @@ -4274,7 +4274,7 @@ LLFaceID LLVolume::generateFaceMask() } break; default: - llerrs << "Unknown profile!" << llendl + llerrs << "Unknown profile!" << llendl; break; } -- cgit v1.1 From 8a62086cb0a9a8ae746bffa57e785cc4ca5be3a5 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 15 Oct 2010 18:01:07 +0200 Subject: Comment out code to make it compile at all (with the latest llqtwebkit). --- linden/indra/llplugin/llpluginclassmedia.cpp | 4 ++++ linden/indra/media_plugins/webkit/media_plugin_webkit.cpp | 7 +++++++ 2 files changed, 11 insertions(+) (limited to 'linden') diff --git a/linden/indra/llplugin/llpluginclassmedia.cpp b/linden/indra/llplugin/llpluginclassmedia.cpp index 8664524..9f14920 100755 --- a/linden/indra/llplugin/llpluginclassmedia.cpp +++ b/linden/indra/llplugin/llpluginclassmedia.cpp @@ -724,6 +724,9 @@ void LLPluginClassMedia::setJavascriptEnabled(const bool enabled) LLPluginClassMedia::ETargetType getTargetTypeFromLLQtWebkit(int target_type) { + llassert(false); + return LLPluginClassMedia::TARGET_OTHER; +#if 0 // convert a LinkTargetType value from llqtwebkit to an ETargetType // so that we don't expose the llqtwebkit header in viewer code switch (target_type) @@ -740,6 +743,7 @@ LLPluginClassMedia::ETargetType getTargetTypeFromLLQtWebkit(int target_type) default: return LLPluginClassMedia::TARGET_OTHER; } +#endif } /* virtual */ diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp index ebf64f8..5058e0a 100755 --- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -323,8 +323,13 @@ private: // append details to agent string LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent ); +#if 0 // FIXME (webkit_plugins): this doesn't compile with latest version of llqtwebkit + // error: ‘class LLQtWebKit’ has no member named ‘setWindowOpenBehavior’ + // error: ‘WOB_SIMULATE_BLANK_HREF_CLICK’ is not a member of ‘LLQtWebKit’ + // Set up window open behavior LLQtWebKit::getInstance()->setWindowOpenBehavior(mBrowserWindowId, LLQtWebKit::WOB_SIMULATE_BLANK_HREF_CLICK); +#endif #if !LL_QTWEBKIT_USES_PIXMAPS // don't flip bitmap @@ -518,7 +523,9 @@ private: LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href"); message.setValue("uri", event.getStringValue()); message.setValue("target", event.getStringValue2()); +#if 0 // FIXME (webkit_plugins): error: ‘const class LLEmbeddedBrowserWindowEvent’ has no member named ‘getLinkType’ message.setValueU32("target_type", event.getLinkType()); +#endif sendMessage(message); } -- cgit v1.1 From b2d616b732943817b7e705fc8f6c4be9beee3def Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 15 Oct 2010 18:02:40 +0200 Subject: Rename LLRect::isNull to LLRect::isEmpty (a random thing I picked up from snowglobe 2.x). --- linden/indra/llmath/llrect.h | 4 ++-- linden/indra/llplugin/llpluginclassmedia.cpp | 4 ++-- linden/indra/llui/llpanel.cpp | 2 +- linden/indra/llui/llview.cpp | 4 ++-- linden/indra/newview/llviewerwindow.cpp | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'linden') diff --git a/linden/indra/llmath/llrect.h b/linden/indra/llmath/llrect.h index 9eb58db..33070c4 100644 --- a/linden/indra/llmath/llrect.h +++ b/linden/indra/llmath/llrect.h @@ -229,14 +229,14 @@ public: return mLeft <= mRight && mBottom <= mTop; } - bool isNull() const + bool isEmpty() const { return mLeft == mRight || mBottom == mTop; } bool notNull() const { - return !isNull(); + return !isEmpty(); } LLRectBase& unionWith(const LLRectBase &other) diff --git a/linden/indra/llplugin/llpluginclassmedia.cpp b/linden/indra/llplugin/llpluginclassmedia.cpp index 9f14920..5dc0c47 100755 --- a/linden/indra/llplugin/llpluginclassmedia.cpp +++ b/linden/indra/llplugin/llpluginclassmedia.cpp @@ -393,7 +393,7 @@ bool LLPluginClassMedia::textureValid(void) bool LLPluginClassMedia::getDirty(LLRect *dirty_rect) { - bool result = !mDirtyRect.isNull(); + bool result = !mDirtyRect.isEmpty(); if(dirty_rect != NULL) { @@ -793,7 +793,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) newDirtyRect.mBottom = temp; } - if(mDirtyRect.isNull()) + if(mDirtyRect.isEmpty()) { mDirtyRect = newDirtyRect; } diff --git a/linden/indra/llui/llpanel.cpp b/linden/indra/llui/llpanel.cpp index 26137d7..07e78ed 100644 --- a/linden/indra/llui/llpanel.cpp +++ b/linden/indra/llui/llpanel.cpp @@ -1171,7 +1171,7 @@ void LLLayoutStack::draw() LLLocalClipRect clip(clip_rect); // only force drawing invisible children if visible amount is non-zero - drawChild(panelp, 0, 0, !clip_rect.isNull()); + drawChild(panelp, 0, 0, !clip_rect.isEmpty()); } } diff --git a/linden/indra/llui/llview.cpp b/linden/indra/llui/llview.cpp index 1f76696..d4eda8f 100644 --- a/linden/indra/llui/llview.cpp +++ b/linden/indra/llui/llview.cpp @@ -1542,7 +1542,7 @@ void LLView::updateBoundingRect() LLRect child_bounding_rect = childp->getBoundingRect(); - if (local_bounding_rect.isNull()) + if (local_bounding_rect.isEmpty()) { // start out with bounding rect equal to first visible child's bounding rect local_bounding_rect = child_bounding_rect; @@ -1550,7 +1550,7 @@ void LLView::updateBoundingRect() else { // accumulate non-null children rectangles - if (!child_bounding_rect.isNull()) + if (!child_bounding_rect.isEmpty()) { local_bounding_rect.unionWith(child_bounding_rect); } diff --git a/linden/indra/newview/llviewerwindow.cpp b/linden/indra/newview/llviewerwindow.cpp index f4b738f..5cd730a 100644 --- a/linden/indra/newview/llviewerwindow.cpp +++ b/linden/indra/newview/llviewerwindow.cpp @@ -2817,7 +2817,7 @@ BOOL LLViewerWindow::handlePerFrameHover() // snap floaters to top of chat bar/button strip LLView* chatbar_and_buttons = gOverlayBar->getChild<LLView>("chatbar_and_buttons", TRUE); // find top of chatbar and state buttons, if either are visible - if (chatbar_and_buttons && !chatbar_and_buttons->getLocalBoundingRect().isNull()) + if (chatbar_and_buttons && !chatbar_and_buttons->getLocalBoundingRect().isEmpty()) { // convert top/left corner of chatbar/buttons container to gFloaterView-relative coordinates S32 top, left; -- cgit v1.1 From e6148fcb46922a570679ff12edbc364873dc54ac Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sat, 16 Oct 2010 13:36:40 +0200 Subject: Fix windows mime types and gstreamer plugin name. --- .../newview/skins/default/xui/en-us/mime_types.xml | 478 --------------------- .../skins/default/xui/en-us/mime_types_windows.xml | 14 +- linden/indra/newview/viewer_manifest.py | 2 +- 3 files changed, 8 insertions(+), 486 deletions(-) delete mode 100644 linden/indra/newview/skins/default/xui/en-us/mime_types.xml (limited to 'linden') diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types.xml deleted file mode 100644 index 360438a..0000000 --- a/linden/indra/newview/skins/default/xui/en-us/mime_types.xml +++ /dev/null @@ -1,478 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<mimetypes name="default"> - <defaultlabel> - (Unknown) - </defaultlabel> - <defaultwidget> - none - </defaultwidget> - <defaultimpl> - media_plugin_webkit - </defaultimpl> - <widgetset name="web"> - <label name="web_label"> - Web Content - </label> - <icon> - icn_media_web.tga - </icon> - <default_type> - text/html - </default_type> - <tooltip name="web_tooltip"> - This location has Web content - </tooltip> - <playtip name="web_playtip"> - Show Web content - </playtip> - <allow_resize> - true - </allow_resize> - <allow_looping> - false - </allow_looping> - </widgetset> - <widgetset name="movie"> - <label name="movie_label"> - Movie - </label> - <default_type> - video/* - </default_type> - <icon> - icn_media_movie.tga - </icon> - <tooltip name="movie_tooltip"> - There is a movie to play here - </tooltip> - <playtip name="movie_playtip"> - Play movie - </playtip> - <allow_resize> - false - </allow_resize> - <allow_looping> - true - </allow_looping> - </widgetset> - <widgetset name="image"> - <label name="image_label"> - Image - </label> - <icon> - icn_media_web.tga - </icon> - <default_type> - image/* - </default_type> - <tooltip name="image_tooltip"> - There is an image at this location - </tooltip> - <playtip name="image_playtip"> - View this location's image - </playtip> - <allow_resize> - false - </allow_resize> - <allow_looping> - false - </allow_looping> - </widgetset> - <widgetset name="audio"> - <label name="audio_label"> - Audio - </label> - <icon> - icn_media_web.tga - </icon> - <default_type> - audio/* - </default_type> - <tooltip name="audio_tooltip"> - There is audio at this location - </tooltip> - <playtip name="audio_playtip"> - Play this location's audio - </playtip> - <allow_resize> - false - </allow_resize> - <allow_looping> - true - </allow_looping> - </widgetset> - <scheme name="rtsp"> - <label name="rtsp_label"> - Real Time Streaming - </label> - <widgettype> - movie - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </scheme> - <mimetype name="blank"> - <label name="blank_label"> - - None - - </label> - <widgettype> - none - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype name="none/none"> - <label name="none/none_label"> - - None - - </label> - <widgettype> - none - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype name="audio/*"> - <label name="audio2_label"> - Audio - </label> - <widgettype> - audio - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> - <mimetype name="video/*"> - <label name="video2_label"> - Video - </label> - <widgettype> - movie - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> - <mimetype name="image/*"> - <label name="image2_label"> - Image - </label> - <widgettype> - image - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> - <label name="vnd.secondlife.qt.legacy_label"> - Movie (gstreamer) - </label> - <widgettype> - movie - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> - <mimetype name="application/javascript"> - <label name="application/javascript_label"> - Javascript - </label> - <widgettype> - web - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype name="application/ogg"> - <label name="application/ogg_label"> - Ogg Audio/Video - </label> - <widgettype> - audio - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> - <mimetype name="application/pdf"> - <label name="application/pdf_label"> - PDF Document - </label> - <widgettype> - image - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype name="application/postscript"> - <label name="application/postscript_label"> - Postscript Document - </label> - <widgettype> - image - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype name="application/rtf"> - <label name="application/rtf_label"> - Rich Text (RTF) - </label> - <widgettype> - image - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype name="application/smil"> - <label name="application/smil_label"> - Synchronized Multimedia Integration Language (SMIL) - </label> - <widgettype> - movie - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype name="application/xhtml+xml"> - <label name="application/xhtml+xml_label"> - Web Page (XHTML) - </label> - <widgettype> - web - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype name="application/x-director"> - <label name="application/x-director_label"> - Macromedia Director - </label> - <widgettype> - image - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype name="audio/mid"> - <label name="audio/mid_label"> - Audio (MIDI) - </label> - <widgettype> - audio - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> - <mimetype name="audio/mpeg"> - <label name="audio/mpeg_label"> - Audio (MP3) - </label> - <widgettype> - audio - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> - <mimetype name="audio/x-aiff"> - <label name="audio/x-aiff_label"> - Audio (AIFF) - </label> - <widgettype> - audio - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> - <mimetype name="audio/x-wav"> - <label name="audio/x-wav_label"> - Audio (WAV) - </label> - <widgettype> - audio - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> - <mimetype menu="1" name="image/bmp"> - <label name="image/bmp_label"> - Image (BMP) - </label> - <widgettype> - image - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype menu="1" name="image/gif"> - <label name="image/gif_label"> - Image (GIF) - </label> - <widgettype> - image - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype menu="1" name="image/jpeg"> - <label name="image/jpeg_label"> - Image (JPEG) - </label> - <widgettype> - image - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype menu="1" name="image/png"> - <label name="image/png_label"> - Image (PNG) - </label> - <widgettype> - image - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype name="image/svg+xml"> - <label name="image/svg+xml_label"> - Image (SVG) - </label> - <widgettype> - image - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype menu="1" name="image/tiff"> - <label name="image/tiff_label"> - Image (TIFF) - </label> - <widgettype> - image - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype menu="1" name="text/html"> - <label name="text/html_label"> - Web Page - </label> - <widgettype> - web - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype menu="1" name="text/plain"> - <label name="text/plain_label"> - Text - </label> - <widgettype> - text - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype name="text/xml"> - <label name="text/xml_label"> - XML - </label> - <widgettype> - text - </widgettype> - <impl> - media_plugin_webkit - </impl> - </mimetype> - <mimetype menu="1" name="video/mpeg"> - <label name="video/mpeg_label"> - Movie (MPEG) - </label> - <widgettype> - movie - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> - <mimetype name="video/mp4"> - <label name="video/mp4_label"> - Movie (MP4) - </label> - <widgettype> - movie - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> - <mimetype menu="1" name="video/gstreamer"> - <label name="video/gstreamer_label"> - Movie (gstreamer) - </label> - <widgettype> - movie - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> - <mimetype name="video/x-ms-asf"> - <label name="video/x-ms-asf_label"> - Movie (Windows Media ASF) - </label> - <widgettype> - movie - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> - <mimetype name="video/x-ms-wmv"> - <label name="video/x-ms-wmv_label"> - Movie (Windows Media WMV) - </label> - <widgettype> - movie - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> - <mimetype menu="1" name="video/x-msvideo"> - <label name="video/x-msvideo_label"> - Movie (AVI) - </label> - <widgettype> - movie - </widgettype> - <impl> - media_plugin_gstreamer010 - </impl> - </mimetype> -</mimetypes> diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml index d4d47cb..5ff3b19 100644 --- a/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml +++ b/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml @@ -274,7 +274,7 @@ audio </widgettype> <impl> - media_plugin_gstreamer010 + media_plugin_gstreamer </impl> </mimetype> <mimetype menu="1" name="image/bmp"> @@ -384,7 +384,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer010010 + media_plugin_gstreamer </impl> </mimetype> <mimetype name="video/mp4"> @@ -395,7 +395,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer010010 + media_plugin_gstreamer </impl> </mimetype> <mimetype menu="1" name="video/gstreamer"> @@ -406,7 +406,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer010010 + media_plugin_gstreamer </impl> </mimetype> <mimetype name="video/x-ms-asf"> @@ -417,7 +417,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer010010 + media_plugin_gstreamer </impl> </mimetype> <mimetype name="video/x-ms-wmv"> @@ -428,7 +428,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer010010 + media_plugin_gstreamer </impl> </mimetype> <mimetype menu="1" name="video/x-msvideo"> @@ -439,7 +439,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer010010 + media_plugin_gstreamer </impl> </mimetype> </mimetypes> diff --git a/linden/indra/newview/viewer_manifest.py b/linden/indra/newview/viewer_manifest.py index 143d946..65e615c 100755 --- a/linden/indra/newview/viewer_manifest.py +++ b/linden/indra/newview/viewer_manifest.py @@ -271,7 +271,7 @@ class WindowsManifest(ViewerManifest): # Media plugins - Gstreamer if self.prefix(src='../media_plugins/gstreamer/%s' % self.args['configuration'], dst="llplugin"): - self.path("media_plugin_gstreamer010.dll") + self.path("media_plugin_gstreamer010.dll", "media_plugin_gstreamer.dll") self.end_prefix() # For WebKit/Qt plugin runtimes -- cgit v1.1 From fa2df9d763270260ab4170507784190ae9066113 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 17 Oct 2010 00:26:00 +0200 Subject: Add LLQTWEBKIT_INCLUDE_DIR to indra/llplugin/CMakeLists.txt Make it find llqtwebkit.h with --standalone. --- linden/indra/llplugin/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linden') diff --git a/linden/indra/llplugin/CMakeLists.txt b/linden/indra/llplugin/CMakeLists.txt index 8eead94..73cd9a3 100644 --- a/linden/indra/llplugin/CMakeLists.txt +++ b/linden/indra/llplugin/CMakeLists.txt @@ -24,6 +24,7 @@ include_directories( ${LLRENDER_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS} + ${LLQTWEBKIT_INCLUDE_DIR} ) set(llplugin_SOURCE_FILES @@ -83,4 +84,4 @@ add_subdirectory(slplugin) # LL_TEST_ADDITIONAL_LIBRARIES "${CURL_LIBRARIES}" # ) # -# LL_ADD_PROJECT_UNIT_TESTS(llplugin "${llplugin_TEST_SOURCE_FILES}") \ No newline at end of file +# LL_ADD_PROJECT_UNIT_TESTS(llplugin "${llplugin_TEST_SOURCE_FILES}") -- cgit v1.1 From 13dc7326705ec9b8219bef3ee339de499626d237 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 17 Oct 2010 22:34:20 +0200 Subject: Find Qt4 with find_package on STANDALONE. If Qt is found in a non-standard place, you still have to set LD_LIBRARY_PATH yourself (to $QTDIR/lib) before running imprudence of course (or the webkit plugin will silently fail). --- linden/indra/cmake/WebKitLibPlugin.cmake | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'linden') diff --git a/linden/indra/cmake/WebKitLibPlugin.cmake b/linden/indra/cmake/WebKitLibPlugin.cmake index 3eafe77..9c56838 100644 --- a/linden/indra/cmake/WebKitLibPlugin.cmake +++ b/linden/indra/cmake/WebKitLibPlugin.cmake @@ -3,6 +3,16 @@ include(Linking) include(Prebuilt) if (STANDALONE) + # The minimal version, 4.4.3, is rather arbitrary: it's the version in Debian/Lenny. + find_package(Qt4 4.4.3 COMPONENTS QtCore QtGui QtNetwork QtOpenGL REQUIRED) + include(${QT_USE_FILE}) + set(QTDIR $ENV{QTDIR}) + if (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin") + message(FATAL_ERROR "\"${QT_BINARY_DIR}\" is unequal \"${QTDIR}/bin\"; " + "Qt is found by looking for qmake in your PATH. " + "Please set your PATH such that 'qmake' is found in \$QTDIR/bin, " + "or unset QTDIR if the found Qt is correct.") + endif (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin") find_package(LLQtWebkit REQUIRED QUIET) set(WEBKITLIBPLUGIN OFF CACHE BOOL "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.") @@ -36,7 +46,7 @@ elseif (DARWIN) ) elseif (LINUX) if (STANDALONE) - set(WEBKIT_PLUGIN_LIBRARIES ${LLQTWEBKIT_LIBRARY}) + set(WEBKIT_PLUGIN_LIBRARIES ${LLQTWEBKIT_LIBRARY} ${QT_LIBRARIES}) else (STANDALONE) set(WEBKIT_PLUGIN_LIBRARIES llqtwebkit -- cgit v1.1 From beb04d00cb01f3c81dcaef69751d526a38ce29e5 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Mon, 18 Oct 2010 23:39:16 +0200 Subject: Forgot QtWebKit and Qt plugins in last commit. Standalone now works (I have no idea why it worked before, since obviously I tested it before committing the previous commit). --- linden/indra/cmake/WebKitLibPlugin.cmake | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'linden') diff --git a/linden/indra/cmake/WebKitLibPlugin.cmake b/linden/indra/cmake/WebKitLibPlugin.cmake index 9c56838..a4befa4 100644 --- a/linden/indra/cmake/WebKitLibPlugin.cmake +++ b/linden/indra/cmake/WebKitLibPlugin.cmake @@ -4,7 +4,7 @@ include(Prebuilt) if (STANDALONE) # The minimal version, 4.4.3, is rather arbitrary: it's the version in Debian/Lenny. - find_package(Qt4 4.4.3 COMPONENTS QtCore QtGui QtNetwork QtOpenGL REQUIRED) + find_package(Qt4 4.4.3 COMPONENTS QtCore QtGui QtNetwork QtOpenGL QtWebKit REQUIRED) include(${QT_USE_FILE}) set(QTDIR $ENV{QTDIR}) if (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin") @@ -14,6 +14,18 @@ if (STANDALONE) "or unset QTDIR if the found Qt is correct.") endif (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin") find_package(LLQtWebkit REQUIRED QUIET) + # Add the plugins. + set(QT_PLUGIN_LIBRARIES) + foreach(qlibname qgif qjpeg) + find_library(QT_PLUGIN_${qlibname} ${qlibname} PATHS ${QT_PLUGINS_DIR}/imageformats NO_DEFAULT_PATH) + if (QT_PLUGIN_${qlibname}) + list(APPEND QT_PLUGIN_LIBRARIES ${QT_PLUGIN_${qlibname}}) + else (QT_PLUGIN_${qtlibname}) + message(FATAL_ERROR "Could not find the Qt plugin ${qlibname} in \"${QT_PLUGINS_DIR}/imageformats\"!") + endif (QT_PLUGIN_${qlibname}) + endforeach(qlibname) + # qjpeg depends on libjpeg + list(APPEND QT_PLUGIN_LIBRARIES jpeg) set(WEBKITLIBPLUGIN OFF CACHE BOOL "WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.") else (STANDALONE) @@ -46,7 +58,7 @@ elseif (DARWIN) ) elseif (LINUX) if (STANDALONE) - set(WEBKIT_PLUGIN_LIBRARIES ${LLQTWEBKIT_LIBRARY} ${QT_LIBRARIES}) + set(WEBKIT_PLUGIN_LIBRARIES ${LLQTWEBKIT_LIBRARY} ${QT_LIBRARIES} ${QT_PLUGIN_LIBRARIES}) else (STANDALONE) set(WEBKIT_PLUGIN_LIBRARIES llqtwebkit -- cgit v1.1 From 6f52903897ccb2ddd88049cd3137cf554ef45621 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Tue, 19 Oct 2010 21:14:03 +0200 Subject: Sync LLViewerMediaImpl::newSourceFromMediaType with SG2 Also renamed CookiesEnabled to BrowswerCookiesEnabled. Added BrowserJavascriptEnabled, BrowserPluginsEnabled and PluginAttachDebuggerToPlugins. --- linden/indra/newview/app_settings/settings.xml | 55 ++++++++++++++++++++------ linden/indra/newview/llpanelweb.cpp | 6 +-- linden/indra/newview/llviewermedia.cpp | 37 ++++++++++++++++- 3 files changed, 82 insertions(+), 16 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml index 57ed4c0..417ddc3 100644 --- a/linden/indra/newview/app_settings/settings.xml +++ b/linden/indra/newview/app_settings/settings.xml @@ -2612,6 +2612,39 @@ <key>Value</key> <integer>0</integer> </map> + <key>BrowserCookiesEnabled</key> + <map> + <key>Comment</key> + <string>Accept cookies from Web sites?</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BrowserJavascriptEnabled</key> + <map> + <key>Comment</key> + <string>Enable Javascript in the built-in Web browser?</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>BrowserPluginsEnabled</key> + <map> + <key>Comment</key> + <string>Enable Web plugins in the built-in Web browser?</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>BrowserProxyAddress</key> <map> <key>Comment</key> @@ -4050,17 +4083,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>CookiesEnabled</key> - <map> - <key>Comment</key> - <string>Accept cookies from Web sites?</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> <key>CreateToolCopyCenters</key> <map> <key>Comment</key> @@ -8460,6 +8482,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>PluginAttachDebuggerToPlugins</key> + <map> + <key>Comment</key> + <string>If true, attach a debugger session to each plugin process as it's launched.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>PrecachingDelay</key> <map> <key>Comment</key> diff --git a/linden/indra/newview/llpanelweb.cpp b/linden/indra/newview/llpanelweb.cpp index e2933f0..14df239 100644 --- a/linden/indra/newview/llpanelweb.cpp +++ b/linden/indra/newview/llpanelweb.cpp @@ -68,7 +68,7 @@ BOOL LLPanelWeb::postBuild() std::string value = gSavedSettings.getBOOL("UseExternalBrowser") ? "external" : "internal"; childSetValue("use_external_browser", value); - childSetValue("cookies_enabled", gSavedSettings.getBOOL("CookiesEnabled")); + childSetValue("cookies_enabled", gSavedSettings.getBOOL("BrowserCookiesEnabled")); childSetValue("web_proxy_enabled", gSavedSettings.getBOOL("BrowserProxyEnabled")); childSetValue("web_proxy_editor", gSavedSettings.getString("BrowserProxyAddress")); @@ -101,7 +101,7 @@ LLPanelWeb::~LLPanelWeb() void LLPanelWeb::apply() { - gSavedSettings.setBOOL("CookiesEnabled", childGetValue("cookies_enabled")); + gSavedSettings.setBOOL("BrowserCookiesEnabled", childGetValue("cookies_enabled")); gSavedSettings.setBOOL("BrowserProxyEnabled", childGetValue("web_proxy_enabled")); gSavedSettings.setString("BrowserProxyAddress", childGetValue("web_proxy_editor")); gSavedSettings.setS32("BrowserProxyPort", childGetValue("web_proxy_port")); @@ -224,4 +224,4 @@ void LLPanelWeb::onClickClear(void* user_data) { LLPanelWeb* self = (LLPanelWeb*)user_data; self->childSetValue("world_search_editor","") ; -} \ No newline at end of file +} diff --git a/linden/indra/newview/llviewermedia.cpp b/linden/indra/newview/llviewermedia.cpp index 8c5cf6a..57c2111 100644 --- a/linden/indra/newview/llviewermedia.cpp +++ b/linden/indra/newview/llviewermedia.cpp @@ -466,6 +466,19 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ std::string user_data_path = gDirUtilp->getOSUserAppDir(); user_data_path += gDirUtilp->getDirDelimiter(); + // Fix for EXT-5960 - make browser profile specific to user (cache, cookies etc.) + // If the linden username returned is blank, that can only mean we are + // at the login page displaying login Web page or Web browser test via Develop menu. + // In this case we just use whatever gDirUtilp->getOSUserAppDir() gives us (this + // is what we always used before this change) + std::string linden_user_dir = gDirUtilp->getLindenUserDir(); + if ( ! linden_user_dir.empty() ) + { + // gDirUtilp->getLindenUserDir() is whole path, not just Linden name + user_data_path = linden_user_dir; + user_data_path += gDirUtilp->getDirDelimiter(); + } + // See if the plugin executable exists llstat s; if(LLFile::stat(launcher_name, &s)) @@ -480,7 +493,22 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ { LLPluginClassMedia* media_source = new LLPluginClassMedia(owner); media_source->setSize(default_width, default_height); - if (media_source->init(launcher_name, plugin_name, false)) + media_source->setUserDataPath(user_data_path); + media_source->setLanguageCode(LLUI::getLanguage()); + + // collect 'cookies enabled' setting from prefs and send to embedded browser + bool cookies_enabled = gSavedSettings.getBOOL( "BrowserCookiesEnabled" ); + media_source->enable_cookies( cookies_enabled ); + + // collect 'plugins enabled' setting from prefs and send to embedded browser + bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" ); + media_source->setPluginsEnabled( plugins_enabled ); + + // collect 'javascript enabled' setting from prefs and send to embedded browser + bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" ); + media_source->setJavascriptEnabled( javascript_enabled ); + + if (media_source->init(launcher_name, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))) { return media_source; } @@ -491,7 +519,12 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ } } } - + + LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL; + LLSD args; + args["MIME_TYPE"] = media_type; + LLNotifications::instance().add("NoPlugin", args); + return NULL; } -- cgit v1.1 From b7a4a4ce26b3784770c9ff21496c9b6fc2e116ea Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Tue, 19 Oct 2010 21:17:41 +0200 Subject: Update WebKit Version in About floater. --- linden/indra/newview/llfloaterabout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linden') diff --git a/linden/indra/newview/llfloaterabout.cpp b/linden/indra/newview/llfloaterabout.cpp index 7aed095..f8db715 100644 --- a/linden/indra/newview/llfloaterabout.cpp +++ b/linden/indra/newview/llfloaterabout.cpp @@ -243,7 +243,7 @@ LLFloaterAbout::LLFloaterAbout() // TODO: Implement media plugin version query - support.append("Qt Webkit Version: 4.5.2 "); + support.append("Qt Webkit Version: 4.6 (version number hard-coded)"); support.append("\n"); if (gPacketsIn > 0) -- cgit v1.1 From 2f4e17af336c9a399a0274b7836f40fc7ff56e21 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Wed, 20 Oct 2010 18:31:42 +0200 Subject: LindenUserDir fixes. The LindenUserDir (~/.imprudence/first_last/) cannot be initialized before the user logged in. However, several singletons (that only can be initialized once) depend on this directory for initialization. Therefore we have to take care not to instantiate those singletons until after the user logged in. With regard to webit, this fixes the browser_profile (cache and cookies) directory that the builtin browser uses. --- linden/indra/llui/lltexteditor.cpp | 11 +++++- linden/indra/llvfs/lldir.cpp | 3 +- linden/indra/llvfs/lldir.h | 2 +- linden/indra/llvfs/lldir_linux.cpp | 2 +- linden/indra/llvfs/lldir_solaris.cpp | 2 +- linden/indra/newview/llappviewer.cpp | 20 ++++++---- linden/indra/newview/llimview.cpp | 2 +- linden/indra/newview/llmutelist.cpp | 2 +- linden/indra/newview/llstartup.cpp | 6 ++- linden/indra/newview/llurlhistory.cpp | 2 +- linden/indra/newview/llviewermedia.cpp | 2 +- linden/indra/newview/llviewerwindow.cpp | 70 ++++++++++++++++++--------------- linden/indra/newview/llviewerwindow.h | 1 + 13 files changed, 75 insertions(+), 50 deletions(-) (limited to 'linden') diff --git a/linden/indra/llui/lltexteditor.cpp b/linden/indra/llui/lltexteditor.cpp index fdf8bcf..004d063 100644 --- a/linden/indra/llui/lltexteditor.cpp +++ b/linden/indra/llui/lltexteditor.cpp @@ -57,6 +57,7 @@ #include "llimagegl.h" #include "llwindow.h" #include "lltextparser.h" +#include "lldir.h" #include <queue> #include "llmenugl.h" @@ -4205,7 +4206,10 @@ void LLTextEditor::appendColoredText(const std::string &new_text, const std::string& font_name) { LLColor4 lcolor=color; - if (mParseHighlights) + // If LindenUserDir is empty then we didn't login yet. + // In that case we can't instantiate LLTextParser, which + // is initialized per user. + if (mParseHighlights && !gDirUtilp->getLindenUserDir(true).empty()) { LLTextParser* highlight = LLTextParser::getInstance(); highlight->parseFullLineHighlights(new_text, &lcolor); @@ -4285,7 +4289,10 @@ void LLTextEditor::appendHighlightedText(const std::string &new_text, S32 highlight_part, LLStyleSP stylep) { - if (mParseHighlights) + // If LindenUserDir is empty then we didn't login yet. + // In that case we can't instantiate LLTextParser, which + // is initialized per user. + if (mParseHighlights && !gDirUtilp->getLindenUserDir(true).empty()) { LLTextParser* highlight = LLTextParser::getInstance(); diff --git a/linden/indra/llvfs/lldir.cpp b/linden/indra/llvfs/lldir.cpp index 5567fdd..cd1e98d 100644 --- a/linden/indra/llvfs/lldir.cpp +++ b/linden/indra/llvfs/lldir.cpp @@ -192,8 +192,9 @@ const std::string &LLDir::getOSUserAppDir() const return mOSUserAppDir; } -const std::string &LLDir::getLindenUserDir() const +const std::string &LLDir::getLindenUserDir(bool empty_ok) const { + llassert(empty_ok || !mLindenUserDir.empty()); return mLindenUserDir; } diff --git a/linden/indra/llvfs/lldir.h b/linden/indra/llvfs/lldir.h index 55574d6..766f351 100644 --- a/linden/indra/llvfs/lldir.h +++ b/linden/indra/llvfs/lldir.h @@ -92,7 +92,7 @@ class LLDir const std::string &getAppRODataDir() const; // Location of read-only data files const std::string &getOSUserDir() const; // Location of the os-specific user dir const std::string &getOSUserAppDir() const; // Location of the os-specific user app dir - const std::string &getLindenUserDir() const; // Location of the Linden user dir. + const std::string &getLindenUserDir(bool empty_ok = false) const; // Location of the Linden user dir. const std::string &getChatLogsDir() const; // Location of the chat logs dir. const std::string &getPerAccountChatLogsDir() const; // Location of the per account chat logs dir. const std::string &getTempDir() const; // Common temporary directory diff --git a/linden/indra/llvfs/lldir_linux.cpp b/linden/indra/llvfs/lldir_linux.cpp index ec0a4f4..5f1eabb 100644 --- a/linden/indra/llvfs/lldir_linux.cpp +++ b/linden/indra/llvfs/lldir_linux.cpp @@ -97,7 +97,7 @@ LLDir_Linux::LLDir_Linux() mAppRODataDir = tmp_str; mOSUserDir = getCurrentUserHome(tmp_str); mOSUserAppDir = ""; - mLindenUserDir = tmp_str; + mLindenUserDir = ""; char path [32]; /* Flawfinder: ignore */ diff --git a/linden/indra/llvfs/lldir_solaris.cpp b/linden/indra/llvfs/lldir_solaris.cpp index c647e2b..5132455 100644 --- a/linden/indra/llvfs/lldir_solaris.cpp +++ b/linden/indra/llvfs/lldir_solaris.cpp @@ -100,7 +100,7 @@ LLDir_Solaris::LLDir_Solaris() mAppRODataDir = strdup(tmp_str); mOSUserDir = getCurrentUserHome(tmp_str); mOSUserAppDir = ""; - mLindenUserDir = tmp_str; + mLindenUserDir = ""; char path [LL_MAX_PATH]; /* Flawfinder: ignore */ diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp index 9fad9f1..1d45575 100644 --- a/linden/indra/newview/llappviewer.cpp +++ b/linden/indra/newview/llappviewer.cpp @@ -1205,7 +1205,10 @@ bool LLAppViewer::cleanup() //reset balance for not playing the UI-Sound //when relogging into another account - gStatusBar->clearBalance(); + if (gStatusBar) + { + gStatusBar->clearBalance(); + } if (mQuitRequested) { @@ -3282,12 +3285,15 @@ void LLAppViewer::saveFinalSnapshot() gSavedSettings.setBOOL("ShowParcelOwners", FALSE); idle(); - std::string snap_filename = gDirUtilp->getLindenUserDir(); - snap_filename += gDirUtilp->getDirDelimiter(); - snap_filename += SCREEN_LAST_FILENAME; - // use full pixel dimensions of viewer window (not post-scale dimensions) - gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight(), FALSE, TRUE); - mSavedFinalSnapshot = TRUE; + std::string snap_filename = gDirUtilp->getLindenUserDir(true); + if (!snap_filename.empty()) + { + snap_filename += gDirUtilp->getDirDelimiter(); + snap_filename += SCREEN_LAST_FILENAME; + // use full pixel dimensions of viewer window (not post-scale dimensions) + gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight(), FALSE, TRUE); + mSavedFinalSnapshot = TRUE; + } } } diff --git a/linden/indra/newview/llimview.cpp b/linden/indra/newview/llimview.cpp index a6eaeb3..0b71030 100644 --- a/linden/indra/newview/llimview.cpp +++ b/linden/indra/newview/llimview.cpp @@ -1360,7 +1360,7 @@ void LLIMMgr::saveIgnoreGroup() { // llinfos << "saving ignore_groups.xml" << llendl; - std::string user_dir = gDirUtilp->getLindenUserDir(); + std::string user_dir = gDirUtilp->getLindenUserDir(true); if (!user_dir.empty()) { std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "ignore_groups.xml"); diff --git a/linden/indra/newview/llmutelist.cpp b/linden/indra/newview/llmutelist.cpp index 0e03509..fff5558 100644 --- a/linden/indra/newview/llmutelist.cpp +++ b/linden/indra/newview/llmutelist.cpp @@ -265,7 +265,7 @@ LLMuteList::~LLMuteList() // If we quit from the login screen we will not have an SL account // name. Don't try to save, otherwise we'll dump a file in // C:\Program Files\SecondLife\ JC - std::string user_dir = gDirUtilp->getLindenUserDir(); + std::string user_dir = gDirUtilp->getLindenUserDir(true); if (!user_dir.empty()) { std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml"); diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index 7bd5fff..fad3df2 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp @@ -839,7 +839,7 @@ bool idle_startup() LLToolMgr::getInstance()->initTools(); // Quickly get something onscreen to look at. - gViewerWindow->initWorldUI(); + gViewerWindow->pre_initWorldUI(); } gViewerWindow->setNormalControlsVisible( FALSE ); @@ -1823,6 +1823,10 @@ bool idle_startup() { LL_DEBUGS("AppInitStartupState") << "STATE_WORLD_INIT" << LL_ENDL; set_startup_status(0.40f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD); + + // Initialize the rest of the world. + gViewerWindow->initWorldUI(); + gDisconnected=FALSE; display_startup(); // We should have an agent id by this point. diff --git a/linden/indra/newview/llurlhistory.cpp b/linden/indra/newview/llurlhistory.cpp index fbd14bc..b187f3b 100644 --- a/linden/indra/newview/llurlhistory.cpp +++ b/linden/indra/newview/llurlhistory.cpp @@ -74,7 +74,7 @@ bool LLURLHistory::loadFile(const std::string& filename) // static bool LLURLHistory::saveFile(const std::string& filename) { - std::string temp_str = gDirUtilp->getLindenUserDir(); + std::string temp_str = gDirUtilp->getLindenUserDir(true); if( temp_str.empty() ) { llwarns << "Can't save " << filename diff --git a/linden/indra/newview/llviewermedia.cpp b/linden/indra/newview/llviewermedia.cpp index 57c2111..5c01b25 100644 --- a/linden/indra/newview/llviewermedia.cpp +++ b/linden/indra/newview/llviewermedia.cpp @@ -471,7 +471,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ // at the login page displaying login Web page or Web browser test via Develop menu. // In this case we just use whatever gDirUtilp->getOSUserAppDir() gives us (this // is what we always used before this change) - std::string linden_user_dir = gDirUtilp->getLindenUserDir(); + std::string linden_user_dir = gDirUtilp->getLindenUserDir(true); if ( ! linden_user_dir.empty() ) { // gDirUtilp->getLindenUserDir() is whole path, not just Linden name diff --git a/linden/indra/newview/llviewerwindow.cpp b/linden/indra/newview/llviewerwindow.cpp index 5cd730a..07fef53 100644 --- a/linden/indra/newview/llviewerwindow.cpp +++ b/linden/indra/newview/llviewerwindow.cpp @@ -1652,7 +1652,7 @@ void LLViewerWindow::adjustControlRectanglesForFirstUse(const LLRect& window) adjust_rect_top_center("FloaterCameraRect3", window); } -void LLViewerWindow::initWorldUI() +void LLViewerWindow::pre_initWorldUI() { pre_init_menus(); @@ -1672,9 +1672,45 @@ void LLViewerWindow::initWorldUI() gHoverView = new LLHoverView(std::string("gHoverView"), full_window); gHoverView->setVisible(TRUE); mRootView->addChild(gHoverView); - + gIMMgr = LLIMMgr::getInstance(); + // Make sure we only create menus once per session -- MC + if (!gMenuHolder) + { + init_menus(); + } + + if (!gFloaterTools) + { + gFloaterTools = new LLFloaterTools(); + gFloaterTools->setVisible(FALSE); + } + + // menu holder appears on top to get first pass at all mouse events + + mRootView->sendChildToFront(gMenuHolder); + + if ( gHUDView == NULL ) + { + LLRect hud_rect = full_window; + hud_rect.mBottom += 50; + if (gMenuBarView) + { + hud_rect.mTop -= gMenuBarView->getRect().getHeight(); + } + gHUDView = new LLHUDView(hud_rect); + // put behind everything else in the UI + mRootView->addChildAtEnd(gHUDView); + } +} + +void LLViewerWindow::initWorldUI() +{ + S32 height = mRootView->getRect().getHeight(); + S32 width = mRootView->getRect().getWidth(); + LLRect full_window(0, height, width, 0); + if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) { LLFloaterChat::getInstance(LLSD())->loadHistory(); @@ -1715,18 +1751,6 @@ void LLViewerWindow::initWorldUI() // Toolbox floater - // Make sure we only create menus once per session -- MC - if (!gMenuHolder) - { - init_menus(); - } - - if (!gFloaterTools) - { - gFloaterTools = new LLFloaterTools(); - gFloaterTools->setVisible(FALSE); - } - if (!gStatusBar) { // Status bar @@ -1744,24 +1768,6 @@ void LLViewerWindow::initWorldUI() } LLFloaterChatterBox::createInstance(LLSD()); - - - // menu holder appears on top to get first pass at all mouse events - - mRootView->sendChildToFront(gMenuHolder); - - if ( gHUDView == NULL ) - { - LLRect hud_rect = full_window; - hud_rect.mBottom += 50; - if (gMenuBarView) - { - hud_rect.mTop -= gMenuBarView->getRect().getHeight(); - } - gHUDView = new LLHUDView(hud_rect); - // put behind everything else in the UI - mRootView->addChildAtEnd(gHUDView); - } } // Destroy the UI diff --git a/linden/indra/newview/llviewerwindow.h b/linden/indra/newview/llviewerwindow.h index 85cdc52..ee8f3fe 100644 --- a/linden/indra/newview/llviewerwindow.h +++ b/linden/indra/newview/llviewerwindow.h @@ -143,6 +143,7 @@ public: void initBase(); void adjustRectanglesForFirstUse(const LLRect& window); void adjustControlRectanglesForFirstUse(const LLRect& window); + void pre_initWorldUI(); void initWorldUI(); // -- cgit v1.1 From b65b0ec23184885f212a78aa69edd152bdbd4588 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Thu, 21 Oct 2010 00:53:01 +0200 Subject: Add support for PluginAttachDebuggerToPlugins for linux Opens a terminal with a gdb session for newly started SLPlugin processes if PluginAttachDebuggerToPlugins is set to TRUE. --- linden/indra/llcommon/llprocesslauncher.h | 3 +++ linden/indra/llplugin/llpluginprocessparent.cpp | 11 +++++++++++ 2 files changed, 14 insertions(+) (limited to 'linden') diff --git a/linden/indra/llcommon/llprocesslauncher.h b/linden/indra/llcommon/llprocesslauncher.h index 036732f..9cdb0f6 100644 --- a/linden/indra/llcommon/llprocesslauncher.h +++ b/linden/indra/llcommon/llprocesslauncher.h @@ -80,6 +80,9 @@ private: HANDLE mProcessHandle; #else pid_t mProcessID; + +public: + pid_t getProcessID() const { return mProcessID; } #endif }; diff --git a/linden/indra/llplugin/llpluginprocessparent.cpp b/linden/indra/llplugin/llpluginprocessparent.cpp index 1bf34c5..8db6046 100755 --- a/linden/indra/llplugin/llpluginprocessparent.cpp +++ b/linden/indra/llplugin/llpluginprocessparent.cpp @@ -408,6 +408,17 @@ void LLPluginProcessParent::idle(void) mDebugger.addArgument("end tell"); mDebugger.launch(); + #elif LL_LINUX + + std::stringstream cmd; + + mDebugger.setExecutable("/usr/bin/gnome-terminal"); + mDebugger.addArgument("--geometry=165x24-0+0"); + mDebugger.addArgument("-e"); + cmd << "/usr/bin/gdb -n /proc/" << mProcess.getProcessID() << "/exe " << mProcess.getProcessID(); + mDebugger.addArgument(cmd.str()); + mDebugger.launch(); + #endif } -- cgit v1.1 From de1ece909c0125d0bd7aece788deeb0764bb070e Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 22 Oct 2010 00:33:41 +0200 Subject: LindenUserDir fixes, part 2. After the previous commit, the menu text - after logging in - had disappeared. This fixes that. --- linden/indra/newview/llstartup.cpp | 4 +-- linden/indra/newview/llviewerwindow.cpp | 55 +++++++++++++++------------------ linden/indra/newview/llviewerwindow.h | 2 +- 3 files changed, 28 insertions(+), 33 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index fad3df2..4683df1 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp @@ -839,7 +839,7 @@ bool idle_startup() LLToolMgr::getInstance()->initTools(); // Quickly get something onscreen to look at. - gViewerWindow->pre_initWorldUI(); + gViewerWindow->initWorldUI(); } gViewerWindow->setNormalControlsVisible( FALSE ); @@ -1825,7 +1825,7 @@ bool idle_startup() set_startup_status(0.40f, LLTrans::getString("LoginInitializingWorld"), gAgent.mMOTD); // Initialize the rest of the world. - gViewerWindow->initWorldUI(); + gViewerWindow->initWorldUI_postLogin(); gDisconnected=FALSE; display_startup(); diff --git a/linden/indra/newview/llviewerwindow.cpp b/linden/indra/newview/llviewerwindow.cpp index 07fef53..2af6fe3 100644 --- a/linden/indra/newview/llviewerwindow.cpp +++ b/linden/indra/newview/llviewerwindow.cpp @@ -1652,7 +1652,7 @@ void LLViewerWindow::adjustControlRectanglesForFirstUse(const LLRect& window) adjust_rect_top_center("FloaterCameraRect3", window); } -void LLViewerWindow::pre_initWorldUI() +void LLViewerWindow::initWorldUI() { pre_init_menus(); @@ -1681,16 +1681,13 @@ void LLViewerWindow::pre_initWorldUI() init_menus(); } + // Toolbox floater if (!gFloaterTools) { gFloaterTools = new LLFloaterTools(); gFloaterTools->setVisible(FALSE); } - // menu holder appears on top to get first pass at all mouse events - - mRootView->sendChildToFront(gMenuHolder); - if ( gHUDView == NULL ) { LLRect hud_rect = full_window; @@ -1705,12 +1702,34 @@ void LLViewerWindow::pre_initWorldUI() } } -void LLViewerWindow::initWorldUI() +// initWorldUI that wasn't before logging in. Some of this may require the access the 'LindenUserDir'. +void LLViewerWindow::initWorldUI_postLogin() { S32 height = mRootView->getRect().getHeight(); S32 width = mRootView->getRect().getWidth(); LLRect full_window(0, height, width, 0); + // The status base must be created before calling sendChildToFront below, + // or the text of the menu (after logging in) won't be visible. + if (!gStatusBar) + { + // Status bar + S32 menu_bar_height = gMenuBarView->getRect().getHeight(); + LLRect root_rect = mRootView->getRect(); + LLRect status_rect(0, root_rect.getHeight(), root_rect.getWidth(), root_rect.getHeight() - menu_bar_height); + gStatusBar = new LLStatusBar(std::string("status"), status_rect); + gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); + + gStatusBar->reshape(root_rect.getWidth(), gStatusBar->getRect().getHeight(), TRUE); + gStatusBar->translate(0, root_rect.getHeight() - gStatusBar->getRect().getHeight()); + // sync bg color with menu bar + gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor() ); + mRootView->addChild(gStatusBar); + } + + // Menu holder appears on top to get first pass at all mouse events + mRootView->sendChildToFront(gMenuHolder); + if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") ) { LLFloaterChat::getInstance(LLSD())->loadHistory(); @@ -1726,8 +1745,6 @@ void LLViewerWindow::initWorldUI() mRootView->addChild(gMorphView); gMorphView->setVisible(FALSE); - // *Note: this is where gFloaterMute used to be initialized. - LLWorldMapView::initClass(); adjust_rect_centered_partial_zoom("FloaterWorldMapRect2", full_window); @@ -1745,28 +1762,6 @@ void LLViewerWindow::initWorldUI() gFloaterTeleportHistory->setVisible(FALSE); } - // - // Tools for building - // - - // Toolbox floater - - if (!gStatusBar) - { - // Status bar - S32 menu_bar_height = gMenuBarView->getRect().getHeight(); - LLRect root_rect = mRootView->getRect(); - LLRect status_rect(0, root_rect.getHeight(), root_rect.getWidth(), root_rect.getHeight() - menu_bar_height); - gStatusBar = new LLStatusBar(std::string("status"), status_rect); - gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); - - gStatusBar->reshape(root_rect.getWidth(), gStatusBar->getRect().getHeight(), TRUE); - gStatusBar->translate(0, root_rect.getHeight() - gStatusBar->getRect().getHeight()); - // sync bg color with menu bar - gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor() ); - mRootView->addChild(gStatusBar); - } - LLFloaterChatterBox::createInstance(LLSD()); } diff --git a/linden/indra/newview/llviewerwindow.h b/linden/indra/newview/llviewerwindow.h index ee8f3fe..d26d820 100644 --- a/linden/indra/newview/llviewerwindow.h +++ b/linden/indra/newview/llviewerwindow.h @@ -143,8 +143,8 @@ public: void initBase(); void adjustRectanglesForFirstUse(const LLRect& window); void adjustControlRectanglesForFirstUse(const LLRect& window); - void pre_initWorldUI(); void initWorldUI(); + void initWorldUI_postLogin(); // // LLWindowCallback interface implementation -- cgit v1.1 From 5cc7263a9113244414493722bb7724275bf52ec8 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 22 Oct 2010 20:48:19 +0200 Subject: Fix the errors "QCursor: Cannot create bitmap cursor; invalid bitmap(s)" at start up of the webkit plugin. These are caused because builtin resources of QtWebKit weren't initialized. --- linden/indra/media_plugins/webkit/media_plugin_webkit.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linden') diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp index 5058e0a..d4c5deb 100755 --- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -34,6 +34,7 @@ */ #include "llqtwebkit.h" +#include <qglobal.h> // for Q_INIT_RESOURCE #include "linden_common.h" #include "indra_constants.h" // for indra keyboard codes @@ -720,6 +721,9 @@ MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_ mJavascriptEnabled = true; // default to on mPluginsEnabled = true; // default to on mUserAgent = "LLPluginMedia Web Browser"; + + // Initialize WebCore resource. + Q_INIT_RESOURCE(WebCore); } MediaPluginWebKit::~MediaPluginWebKit() -- cgit v1.1 From 1724c21bbcf349ceeb7cc5bb013ca498bb130fff Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Sat, 23 Oct 2010 07:12:35 -0700 Subject: Fixed copy_win_libs by removing glib dlls --- linden/indra/cmake/CopyWinLibs.cmake | 8 -------- 1 file changed, 8 deletions(-) (limited to 'linden') diff --git a/linden/indra/cmake/CopyWinLibs.cmake b/linden/indra/cmake/CopyWinLibs.cmake index 2bea40c..44d35ed 100644 --- a/linden/indra/cmake/CopyWinLibs.cmake +++ b/linden/indra/cmake/CopyWinLibs.cmake @@ -43,10 +43,6 @@ set(all_targets ${all_targets} ${out_targets}) set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug") set(plugintest_debug_files libeay32.dll - libglib-2.0-0.dll - libgmodule-2.0-0.dll - libgobject-2.0-0.dll - libgthread-2.0-0.dll qtcored4.dll qtguid4.dll qtnetworkd4.dll @@ -92,10 +88,6 @@ set(all_targets ${all_targets} ${out_targets}) set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") set(plugintest_release_files libeay32.dll - libglib-2.0-0.dll - libgmodule-2.0-0.dll - libgobject-2.0-0.dll - libgthread-2.0-0.dll qtcore4.dll qtgui4.dll qtnetwork4.dll -- cgit v1.1 From c6aac7d81149a50f895a0f06fdf08b65c8e4bd8c Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Mon, 25 Oct 2010 02:19:54 +0200 Subject: Added missing textures to artwork. Also fixed textures.xml by adding media_panel_scrollbg.png which is used in the MediaHUD as one of the media_*.png textures, but was lacking from textures.xml. --- linden/indra/newview/skins/default/textures/textures.xml | 1 + linden/install.xml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/skins/default/textures/textures.xml b/linden/indra/newview/skins/default/textures/textures.xml index f2189a4..60fb4e0 100644 --- a/linden/indra/newview/skins/default/textures/textures.xml +++ b/linden/indra/newview/skins/default/textures/textures.xml @@ -396,5 +396,6 @@ <texture name="media_btn_scrollup.png"/> <texture name="media_btn_stoploading.png"/> <texture name="media_panel_divider.png"/> + <texture name="media_panel_scrollbg.png"/> </textures> diff --git a/linden/install.xml b/linden/install.xml index 09a58e7..c564b2b 100755 --- a/linden/install.xml +++ b/linden/install.xml @@ -179,30 +179,30 @@ <key>darwin</key> <map> <key>md5sum</key> - <string>506d8203676998eab8ccbaaf7bc7415f</string> + <string>68fedbc3638d7f081edc59bdccbeffc2</string> <key>url</key> - <uri>http://imprudenceviewer.org/download/extras/imprudence-artwork-20101017.tar.bz2</uri> + <uri>http://github.com/downloads/AlericInglewood/imprudence/imprudence-artwork-20101025.tar.bz2</uri> </map> <key>linux</key> <map> <key>md5sum</key> - <string>506d8203676998eab8ccbaaf7bc7415f</string> + <string>68fedbc3638d7f081edc59bdccbeffc2</string> <key>url</key> - <uri>http://imprudenceviewer.org/download/extras/imprudence-artwork-20101017.tar.bz2</uri> + <uri>http://github.com/downloads/AlericInglewood/imprudence/imprudence-artwork-20101025.tar.bz2</uri> </map> <key>linux64</key> <map> <key>md5sum</key> - <string>506d8203676998eab8ccbaaf7bc7415f</string> + <string>68fedbc3638d7f081edc59bdccbeffc2</string> <key>url</key> - <uri>http://imprudenceviewer.org/download/extras/imprudence-artwork-20101017.tar.bz2</uri> + <uri>http://github.com/downloads/AlericInglewood/imprudence/imprudence-artwork-20101025.tar.bz2</uri> </map> <key>windows</key> <map> <key>md5sum</key> - <string>506d8203676998eab8ccbaaf7bc7415f</string> + <string>68fedbc3638d7f081edc59bdccbeffc2</string> <key>url</key> - <uri>http://imprudenceviewer.org/download/extras/imprudence-artwork-20101017.tar.bz2</uri> + <uri>http://github.com/downloads/AlericInglewood/imprudence/imprudence-artwork-20101025.tar.bz2</uri> </map> </map> </map> -- cgit v1.1 From 534779caf41bb0ec7480e2403d3dfc20f1aec06c Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Tue, 26 Oct 2010 19:59:06 +0200 Subject: Add missing skin thumbnail to artwork and move them to the right directory. --- linden/install.xml | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) (limited to 'linden') diff --git a/linden/install.xml b/linden/install.xml index c564b2b..4a6cb23 100755 --- a/linden/install.xml +++ b/linden/install.xml @@ -176,33 +176,12 @@ <string>creative commons attribution-share alike 3.0</string> <key>packages</key> <map> - <key>darwin</key> - <map> - <key>md5sum</key> - <string>68fedbc3638d7f081edc59bdccbeffc2</string> - <key>url</key> - <uri>http://github.com/downloads/AlericInglewood/imprudence/imprudence-artwork-20101025.tar.bz2</uri> - </map> - <key>linux</key> - <map> - <key>md5sum</key> - <string>68fedbc3638d7f081edc59bdccbeffc2</string> - <key>url</key> - <uri>http://github.com/downloads/AlericInglewood/imprudence/imprudence-artwork-20101025.tar.bz2</uri> - </map> - <key>linux64</key> - <map> - <key>md5sum</key> - <string>68fedbc3638d7f081edc59bdccbeffc2</string> - <key>url</key> - <uri>http://github.com/downloads/AlericInglewood/imprudence/imprudence-artwork-20101025.tar.bz2</uri> - </map> - <key>windows</key> + <key>common</key> <map> <key>md5sum</key> - <string>68fedbc3638d7f081edc59bdccbeffc2</string> + <string>a2cde4f24bdcc260b661e139846b8acd</string> <key>url</key> - <uri>http://github.com/downloads/AlericInglewood/imprudence/imprudence-artwork-20101025.tar.bz2</uri> + <uri>http://github.com/downloads/AlericInglewood/imprudence/imprudence-artwork-20101026.tar.bz2</uri> </map> </map> </map> -- cgit v1.1 From 447b85de620dd217cb13233d814de8e80e1b9eb7 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 26 Oct 2010 20:09:25 -0700 Subject: Set LL_GSTREAMER010_ENABLED to true for Linux-only until gstreamer loading can be sorted on windows --- linden/indra/cmake/GStreamer010Plugin.cmake | 2 ++ .../indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp | 4 ++-- linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'linden') diff --git a/linden/indra/cmake/GStreamer010Plugin.cmake b/linden/indra/cmake/GStreamer010Plugin.cmake index cafcd4c..878d3c0 100644 --- a/linden/indra/cmake/GStreamer010Plugin.cmake +++ b/linden/indra/cmake/GStreamer010Plugin.cmake @@ -8,6 +8,7 @@ if (STANDALONE) pkg_check_modules(GSTREAMER010_PLUGINS_BASE REQUIRED gstreamer-plugins-base-0.10) endif (STANDALONE) +if (LINUX) use_prebuilt_binary(gstreamer) # possible libxml should have its own .cmake file instead use_prebuilt_binary(libxml) @@ -18,6 +19,7 @@ endif (STANDALONE) ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/libxml2 ) +endif (LINUX) if (WINDOWS) # We don't need to explicitly link against gstreamer itself, because diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp index 1fee545..e194bf7 100755 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp @@ -33,7 +33,7 @@ * @endcond */ -///#if LL_GSTREAMER010_ENABLED +#if LL_GSTREAMER010_ENABLED #include "linden_common.h" @@ -569,4 +569,4 @@ void gst_slvideo_init_class (void) (const gchar *)"http://www.secondlife.com/" ); } -///#endif // LL_GSTREAMER010_ENABLED +#endif // LL_GSTREAMER010_ENABLED diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h index 0ad8cf1..5e8c72c 100755 --- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h @@ -36,7 +36,7 @@ #ifndef __GST_SLVIDEO_H__ #define __GST_SLVIDEO_H__ -///#if LL_GSTREAMER010_ENABLED +#if LL_GSTREAMER010_ENABLED extern "C" { #include <gst/gst.h> @@ -108,6 +108,6 @@ void gst_slvideo_init_class (void); G_END_DECLS -///#endif // LL_GSTREAMER010_ENABLED +#endif // LL_GSTREAMER010_ENABLED #endif /* __GST_SLVIDEO_H__ */ -- cgit v1.1 From 45438a88354927942315ad5c4872cc76515d1891 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 26 Oct 2010 20:26:00 -0700 Subject: Fixed media plugin test not compiling --- .../test_apps/llplugintest/llmediaplugintest.cpp | 37 +++++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-) (limited to 'linden') diff --git a/linden/indra/test_apps/llplugintest/llmediaplugintest.cpp b/linden/indra/test_apps/llplugintest/llmediaplugintest.cpp index 27cb52a..bc3703d 100644 --- a/linden/indra/test_apps/llplugintest/llmediaplugintest.cpp +++ b/linden/indra/test_apps/llplugintest/llmediaplugintest.cpp @@ -1169,8 +1169,8 @@ void LLMediaPluginTest::keyboard( int key ) exit( 0 ); }; - mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_DOWN, key, 0 ); - mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_UP, key, 0 ); + mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_DOWN, key, 0 , LLSD()); + mSelectedPanel->mMediaSource->keyEvent( LLPluginClassMedia::KEY_EVENT_UP, key, 0, LLSD()); }; //////////////////////////////////////////////////////////////////////////////// @@ -1529,7 +1529,21 @@ void LLMediaPluginTest::addMediaPanel( std::string url ) #elif LL_WINDOWS std::string launcher_name( "SLPlugin.exe" ); #endif - media_source->init( launcher_name, plugin_name ); + + // for this test app, use the cwd as the user data path (ugh). +#if LL_WINDOWS + std::string user_data_path = ".\\"; +#else + char cwd[ FILENAME_MAX ]; + if (NULL == getcwd( cwd, FILENAME_MAX - 1 )) + { + std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl; + return; + } + std::string user_data_path = std::string( cwd ) + "/"; +#endif + media_source->setUserDataPath(user_data_path); + media_source->init( launcher_name, plugin_name, false ); media_source->setDisableTimeout(mDisableTimeout); // make a new panel and save parameters @@ -1752,7 +1766,22 @@ void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url ) #elif LL_WINDOWS std::string launcher_name( "SLPlugin.exe" ); #endif - media_source->init( launcher_name, plugin_name ); + + // for this test app, use the cwd as the user data path (ugh). +#if LL_WINDOWS + std::string user_data_path = ".\\"; +#else + char cwd[ FILENAME_MAX ]; + if (NULL == getcwd( cwd, FILENAME_MAX - 1 )) + { + std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl; + return; + } + std::string user_data_path = std::string( cwd ) + "/"; +#endif + + media_source->setUserDataPath(user_data_path); + media_source->init( launcher_name, plugin_name, false ); media_source->setDisableTimeout(mDisableTimeout); // make a new panel and save parameters -- cgit v1.1 From 74749fc1ed3b6f6eda57739712c3e01ba126c7b6 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Wed, 27 Oct 2010 02:17:31 -0700 Subject: Fixed mime_types.xml not being copied on Windows (also fixes plugin dll copying error) --- linden/indra/newview/CMakeLists.txt | 39 ++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index e113d05..bec20d9 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt @@ -1525,6 +1525,7 @@ ADD_VIEWER_BUILD_TEST(llagentaccess viewer) # Don't do these for DARWIN or LINUX here -- they're taken care of by viewer_manifest.py if (WINDOWS) + get_target_property(BUILT_SLPLUGIN SLPlugin LOCATION) add_custom_command( TARGET ${VIEWER_BINARY_NAME} POST_BUILD @@ -1549,17 +1550,17 @@ if (WINDOWS) COMMENT "Copying WebKit Plugin to the runtime folder." ) - get_target_property(BUILT_GSTREAMER_PLUGIN media_plugin_gstreamer010 LOCATION) - add_custom_command( - TARGET ${VIEWER_BINARY_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - -E - copy_if_different - ${BUILT_GSTREAMER_PLUGIN} - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin - COMMENT "Copying Gstreamer Plugin to the runtime folder." - ) + #get_target_property(BUILT_GSTREAMER_PLUGIN media_plugin_gstreamer010 LOCATION) + # add_custom_command( + # TARGET ${VIEWER_BINARY_NAME} POST_BUILD + # COMMAND ${CMAKE_COMMAND} + # ARGS + # -E + # copy_if_different + # ${BUILT_GSTREAMER_PLUGIN} + # ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin + # COMMENT "Copying Gstreamer Plugin to the runtime folder." + # ) get_target_property(BUILT_QUICKTIME_PLUGIN media_plugin_quicktime LOCATION) add_custom_command( @@ -1573,8 +1574,20 @@ if (WINDOWS) COMMENT "Copying Quicktime Plugin to the runtime folder." ) - - + # Copying the mime_types.xml file to app_settings + set(mime_types_source "${CMAKE_SOURCE_DIR}/newview/skins/default/xui/en-us") + set(mime_types_dest "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings") + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_if_different + ${mime_types_source}/mime_types_windows.xml + ${mime_types_dest}/mime_types.xml + COMMENT "Copying mime_types_windows.xml to mime_types.xml." + ) + endif (WINDOWS) if (DARWIN) -- cgit v1.1 From d2a3064b8abc37853839441bdd1db0ce99ac5ef2 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Wed, 27 Oct 2010 02:38:23 -0700 Subject: Use quicktime instead of gstreamer on Windows --- .../skins/default/xui/en-us/mime_types_windows.xml | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml index 5ff3b19..abc7f1a 100644 --- a/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml +++ b/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml @@ -109,7 +109,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </scheme> <mimetype name="blank"> @@ -120,7 +120,7 @@ none </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </mimetype> <mimetype name="none/none"> @@ -163,7 +163,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </mimetype> <mimetype name="application/javascript"> @@ -214,7 +214,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </mimetype> <mimetype name="application/xhtml+xml"> @@ -241,7 +241,7 @@ audio </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </mimetype> <mimetype name="audio/mpeg"> @@ -252,7 +252,7 @@ audio </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </mimetype> <mimetype name="audio/x-aiff"> @@ -263,7 +263,7 @@ audio </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </mimetype> <mimetype name="audio/x-wav"> @@ -274,7 +274,7 @@ audio </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </mimetype> <mimetype menu="1" name="image/bmp"> @@ -384,7 +384,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </mimetype> <mimetype name="video/mp4"> @@ -395,7 +395,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </mimetype> <mimetype menu="1" name="video/gstreamer"> @@ -406,7 +406,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </mimetype> <mimetype name="video/x-ms-asf"> @@ -417,7 +417,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </mimetype> <mimetype name="video/x-ms-wmv"> @@ -428,7 +428,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </mimetype> <mimetype menu="1" name="video/x-msvideo"> @@ -439,7 +439,7 @@ movie </widgettype> <impl> - media_plugin_gstreamer + media_plugin_quicktime </impl> </mimetype> </mimetypes> -- cgit v1.1 From d3ecf0f84bdb72cc28df16d59c736b9ffba7a57f Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Wed, 27 Oct 2010 15:53:42 +0200 Subject: Remove the need for qglobal.h on non-standalone. --- linden/indra/media_plugins/webkit/media_plugin_webkit.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'linden') diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp index d4c5deb..d01cd9e 100755 --- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -34,7 +34,9 @@ */ #include "llqtwebkit.h" -#include <qglobal.h> // for Q_INIT_RESOURCE +#ifdef LL_STANDALONE +#include <qglobal.h> +#endif #include "linden_common.h" #include "indra_constants.h" // for indra keyboard codes @@ -80,6 +82,16 @@ extern "C" { } #endif +// We don't provide Qt headers, so define this here for non-standalone. +#ifndef QT_MANGLE_NAMESPACE +#define QT_MANGLE_NAMESPACE(name) name +#endif +#ifndef Q_INIT_RESOURCE +#define Q_INIT_RESOURCE(name) \ + do { extern int QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); \ + QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); } while (0) +#endif + //////////////////////////////////////////////////////////////////////////////// // class MediaPluginWebKit : -- cgit v1.1 From 190bd7d2b622efda788a7b1e7da5996c5095de54 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Wed, 27 Oct 2010 02:56:22 -0700 Subject: Load mime_types_windows.xml instead of mime_types.xml so we can fallback on the version in the skins directory correctly --- linden/indra/newview/CMakeLists.txt | 4 ++-- linden/indra/newview/llappviewer.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index bec20d9..6596d39 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt @@ -1584,8 +1584,8 @@ if (WINDOWS) -E copy_if_different ${mime_types_source}/mime_types_windows.xml - ${mime_types_dest}/mime_types.xml - COMMENT "Copying mime_types_windows.xml to mime_types.xml." + ${mime_types_dest}/mime_types_windows.xml + COMMENT "Copying mime_types_windows.xml to the runtime app_settings folder." ) endif (WINDOWS) diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp index 5b34e82..97deca0 100644 --- a/linden/indra/newview/llappviewer.cpp +++ b/linden/indra/newview/llappviewer.cpp @@ -724,7 +724,7 @@ bool LLAppViewer::init() #elif LL_LINUX mime_types_name = "mime_types_linux.xml"; #else - mime_types_name = "mime_types.xml"; + mime_types_name = "mime_types_windows.xml"; #endif LLMIMETypes::parseMIMETypes( mime_types_name ); -- cgit v1.1 From 6f2faa65f9841919566b567d74b258a1c559ec0e Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Wed, 27 Oct 2010 22:28:48 +0200 Subject: Load prebuilt glib when needed. Don't compile gstreamer plugin on windows. Also, darwin doesn't use quicktime, so disabled compiling that plugin for darwin. --- linden/indra/cmake/DBusGlib.cmake | 1 + linden/indra/cmake/GStreamer010Plugin.cmake | 14 ++++++++------ linden/indra/cmake/UI.cmake | 3 ++- linden/indra/media_plugins/CMakeLists.txt | 8 +++++--- 4 files changed, 16 insertions(+), 10 deletions(-) (limited to 'linden') diff --git a/linden/indra/cmake/DBusGlib.cmake b/linden/indra/cmake/DBusGlib.cmake index dfda0ad..b78a0b1 100644 --- a/linden/indra/cmake/DBusGlib.cmake +++ b/linden/indra/cmake/DBusGlib.cmake @@ -7,6 +7,7 @@ if (STANDALONE) pkg_check_modules(DBUSGLIB REQUIRED dbus-glib-1) elseif (LINUX) + use_prebuilt_binary(glib) # dbusglib needs glib use_prebuilt_binary(dbusglib) set(DBUSGLIB_FOUND ON FORCE BOOL) set(DBUSGLIB_INCLUDE_DIRS diff --git a/linden/indra/cmake/GStreamer010Plugin.cmake b/linden/indra/cmake/GStreamer010Plugin.cmake index 878d3c0..90ed35c 100644 --- a/linden/indra/cmake/GStreamer010Plugin.cmake +++ b/linden/indra/cmake/GStreamer010Plugin.cmake @@ -6,12 +6,13 @@ if (STANDALONE) pkg_check_modules(GSTREAMER010 REQUIRED gstreamer-0.10) pkg_check_modules(GSTREAMER010_PLUGINS_BASE REQUIRED gstreamer-plugins-base-0.10) -endif (STANDALONE) -if (LINUX) - use_prebuilt_binary(gstreamer) - # possible libxml should have its own .cmake file instead +else (STANDALONE) + + # Possibly libxml and glib should have their own .cmake file instead... + use_prebuilt_binary(glib) # gstreamer needs glib use_prebuilt_binary(libxml) + use_prebuilt_binary(gstreamer) set(GSTREAMER010_FOUND ON FORCE BOOL) set(GSTREAMER010_PLUGINS_BASE_FOUND ON FORCE BOOL) set(GSTREAMER010_INCLUDE_DIRS @@ -19,8 +20,9 @@ if (LINUX) ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/libxml2 ) -endif (LINUX) - + +endif (STANDALONE) + if (WINDOWS) # We don't need to explicitly link against gstreamer itself, because # LLMediaImplGStreamer probes for the system's copy at runtime. diff --git a/linden/indra/cmake/UI.cmake b/linden/indra/cmake/UI.cmake index 9d068c4..7a02dff 100644 --- a/linden/indra/cmake/UI.cmake +++ b/linden/indra/cmake/UI.cmake @@ -31,8 +31,9 @@ if (STANDALONE) add_definitions(${${pkg}_CFLAGS_OTHERS}) endforeach(pkg) else (STANDALONE) - use_prebuilt_binary(gtk-etc) if (LINUX) + use_prebuilt_binary(glib) # gtk-etc needs glib + use_prebuilt_binary(gtk-etc) set(UI_LIBRARIES atk-1.0 cairo diff --git a/linden/indra/media_plugins/CMakeLists.txt b/linden/indra/media_plugins/CMakeLists.txt index cc03d9c..c4f2555 100755 --- a/linden/indra/media_plugins/CMakeLists.txt +++ b/linden/indra/media_plugins/CMakeLists.txt @@ -4,10 +4,12 @@ add_subdirectory(base) add_subdirectory(webkit) -add_subdirectory(gstreamer010) +if (LINUX OR DARWIN) + add_subdirectory(gstreamer010) +endif (LINUX OR DARWIN) -if (WINDOWS OR DARWIN) +if (WINDOWS) add_subdirectory(quicktime) -endif (WINDOWS OR DARWIN) +endif (WINDOWS) add_subdirectory(example) -- cgit v1.1 From 686f5fdf0f710387c7aa84b41434f0bab8cd6875 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Thu, 28 Oct 2010 00:08:50 +0200 Subject: Only initialize WebCore resource(s) on linux. I searched the darwin and windows llqtwebkit tarballs and neither qInitResources_WebCore nor qInitResources_WebCore_QT_NAMESPACE exist in there... No idea why, but then we can't call it to initialize it now can we? --- linden/indra/media_plugins/webkit/media_plugin_webkit.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'linden') diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp index d01cd9e..0fb64bb 100755 --- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -34,9 +34,6 @@ */ #include "llqtwebkit.h" -#ifdef LL_STANDALONE -#include <qglobal.h> -#endif #include "linden_common.h" #include "indra_constants.h" // for indra keyboard codes @@ -82,14 +79,18 @@ extern "C" { } #endif -// We don't provide Qt headers, so define this here for non-standalone. -#ifndef QT_MANGLE_NAMESPACE +#ifdef LL_STANDALONE +#include <qglobal.h> +#elif defined(LL_LINUX) +// We don't provide Qt headers for non-standalone, therefore define this here. +// Our prebuilt is built with QT_NAMESPACE undefined. #define QT_MANGLE_NAMESPACE(name) name -#endif -#ifndef Q_INIT_RESOURCE #define Q_INIT_RESOURCE(name) \ do { extern int QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); \ QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); } while (0) +#else +// Apparently this symbol doesn't exist in the windows and Mac tar balls provided by LL. +#define Q_INIT_RESOURCE(name) /*nothing*/ #endif //////////////////////////////////////////////////////////////////////////////// -- cgit v1.1 From 230a5e1114988486540ac4840a63854d4298cfa2 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Thu, 28 Oct 2010 16:00:44 +0200 Subject: Remove explicit dependency of windows on media_plugin_gstreamer010 --- linden/indra/newview/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linden') diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index fb67423..829aa69 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt @@ -1350,7 +1350,7 @@ if (WINDOWS) DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit media_plugin_gstreamer010) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) # Removed media_plugin_gstreamer010 if (PACKAGE) add_custom_target(package ALL DEPENDS ${CMAKE_CFG_INTDIR}/touched.bat) -- cgit v1.1 From f10af893916d543fb29f2740ecfc8039b0a31b73 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Sat, 30 Oct 2010 14:16:00 -0700 Subject: Added conversion function for plugin EState to string info --- linden/indra/llplugin/llpluginprocessparent.cpp | 52 ++++++++++++++++++++++++- linden/indra/llplugin/llpluginprocessparent.h | 1 + 2 files changed, 52 insertions(+), 1 deletion(-) (limited to 'linden') diff --git a/linden/indra/llplugin/llpluginprocessparent.cpp b/linden/indra/llplugin/llpluginprocessparent.cpp index 8db6046..8fd18ef 100755 --- a/linden/indra/llplugin/llpluginprocessparent.cpp +++ b/linden/indra/llplugin/llpluginprocessparent.cpp @@ -1084,7 +1084,7 @@ std::string LLPluginProcessParent::getPluginVersion(void) void LLPluginProcessParent::setState(EState state) { - LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL; + LL_DEBUGS("Plugin") << "setting state to " << stateToString(state) << LL_ENDL; mState = state; }; @@ -1118,3 +1118,53 @@ bool LLPluginProcessParent::pluginLockedUp() return (mHeartbeat.getStarted() && mHeartbeat.hasExpired()); } +std::string LLPluginProcessParent::stateToString(EState state) +{ + std::string eng = "unknown plugin state"; + switch (state) + { + case STATE_UNINITIALIZED: + eng = "STATE_UNINITIALIZED"; + break; + case STATE_INITIALIZED: + eng = "STATE_INITIALIZED - init() has been called"; + break; + case STATE_LISTENING: + eng = "STATE_LISTENING - listening for incoming connection"; + break; + case STATE_LAUNCHED: + eng = "STATE_LAUNCHED - process has been launched"; + break; + case STATE_CONNECTED: + eng = "STATE_CONNECTED - process has connected"; + break; + case STATE_HELLO: + eng = "STATE_HELLO - first message from the plugin process has been received"; + break; + case STATE_LOADING: + eng = "STATE_LOADING - process has been asked to load the plugin"; + break; + case STATE_RUNNING: + eng = "STATE_RUNNING - plugin running"; + break; + case STATE_LAUNCH_FAILURE: + eng = "STATE_LAUNCH_FAILURE - failure before plugin loaded"; + break; + case STATE_ERROR: + eng = "STATE_ERROR - generic bailout state"; + break; + case STATE_CLEANUP: + eng = "STATE_CLEANUP - clean everything up"; + break; + case STATE_EXITING: + eng = "STATE_EXITING - tried to kill process, waiting for it to exit"; + break; + case STATE_DONE: + eng = "STATE_DONE - plugin done"; + break; + default: + break; + } + + return llformat("(%d) ", (S32)state) + eng; +} diff --git a/linden/indra/llplugin/llpluginprocessparent.h b/linden/indra/llplugin/llpluginprocessparent.h index a8929b1..95f5f70 100755 --- a/linden/indra/llplugin/llpluginprocessparent.h +++ b/linden/indra/llplugin/llpluginprocessparent.h @@ -147,6 +147,7 @@ private: }; EState mState; void setState(EState state); + std::string stateToString(EState state); bool pluginLockedUp(); bool pluginLockedUpOrQuit(); -- cgit v1.1 From c07d4360df2ba313fb8bd10f0cf2abccf5d485a9 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 29 Oct 2010 15:34:10 +0200 Subject: RED-595 was renamed to IMP-595 --- linden/indra/newview/llmediactrl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linden') diff --git a/linden/indra/newview/llmediactrl.cpp b/linden/indra/newview/llmediactrl.cpp index c3bcf85..8b60326 100644 --- a/linden/indra/newview/llmediactrl.cpp +++ b/linden/indra/newview/llmediactrl.cpp @@ -201,7 +201,7 @@ BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) // *HACK: media_plugin_webkit automatically takes focus on mouseup, // in addition to the onFocusReceived() call below. Undo this. JC - // RED-595: Is this really still the case for webkit? + // IMP-595: Is this really still the case for webkit? if (!mTakeFocusOnClick) { mMediaSource->focus(false); -- cgit v1.1 From 1fd8a0bf47b7131f7ffbcd96ab0c7ec32a56d3ab Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Fri, 29 Oct 2010 15:51:10 +0200 Subject: Delete piece of code that is redundant. --- linden/indra/media_plugins/webkit/media_plugin_webkit.cpp | 8 -------- 1 file changed, 8 deletions(-) (limited to 'linden') diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp index 0fb64bb..767090c 100755 --- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -337,14 +337,6 @@ private: // append details to agent string LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent ); -#if 0 // FIXME (webkit_plugins): this doesn't compile with latest version of llqtwebkit - // error: ‘class LLQtWebKit’ has no member named ‘setWindowOpenBehavior’ - // error: ‘WOB_SIMULATE_BLANK_HREF_CLICK’ is not a member of ‘LLQtWebKit’ - - // Set up window open behavior - LLQtWebKit::getInstance()->setWindowOpenBehavior(mBrowserWindowId, LLQtWebKit::WOB_SIMULATE_BLANK_HREF_CLICK); -#endif - #if !LL_QTWEBKIT_USES_PIXMAPS // don't flip bitmap LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true ); -- cgit v1.1 From 7e6a6ef92f15f4613acd6dcae9eab78f37866376 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sat, 30 Oct 2010 20:29:37 +0200 Subject: Make LLStringUtilBase<T>::null a constant. --- linden/indra/llcommon/llstring.h | 4 ++-- linden/indra/newview/llnamelistctrl.cpp | 2 +- linden/indra/newview/llnamelistctrl.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'linden') diff --git a/linden/indra/llcommon/llstring.h b/linden/indra/llcommon/llstring.h index 3c6cd43..bab89b1 100644 --- a/linden/indra/llcommon/llstring.h +++ b/linden/indra/llcommon/llstring.h @@ -209,7 +209,7 @@ public: ///////////////////////////////////////////////////////////////////////////////////////// // Static Utility functions that operate on std::strings - static std::basic_string<T> null; + static std::basic_string<T> const null; typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t; static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map); @@ -299,7 +299,7 @@ public: }; -template<class T> std::basic_string<T> LLStringUtilBase<T>::null; +template<class T> std::basic_string<T> const LLStringUtilBase<T>::null; typedef LLStringUtilBase<char> LLStringUtil; typedef LLStringUtilBase<llwchar> LLWStringUtil; diff --git a/linden/indra/newview/llnamelistctrl.cpp b/linden/indra/newview/llnamelistctrl.cpp index 453cf7f..e445df5 100644 --- a/linden/indra/newview/llnamelistctrl.cpp +++ b/linden/indra/newview/llnamelistctrl.cpp @@ -72,7 +72,7 @@ LLNameListCtrl::~LLNameListCtrl() // public BOOL LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos, - BOOL enabled, std::string& suffix) + BOOL enabled, const std::string& suffix) { //llinfos << "LLNameListCtrl::addNameItem " << agent_id << llendl; diff --git a/linden/indra/newview/llnamelistctrl.h b/linden/indra/newview/llnamelistctrl.h index 1b7795d..beb4ede 100644 --- a/linden/indra/newview/llnamelistctrl.h +++ b/linden/indra/newview/llnamelistctrl.h @@ -58,7 +58,7 @@ public: // Add a user to the list by name. It will be added, the name // requested from the cache, and updated as necessary. BOOL addNameItem(const LLUUID& agent_id, EAddPosition pos = ADD_BOTTOM, - BOOL enabled = TRUE, std::string& suffix = LLStringUtil::null); + BOOL enabled = TRUE, const std::string& suffix = LLStringUtil::null); BOOL addNameItem(LLScrollListItem* item, EAddPosition pos = ADD_BOTTOM); virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL); -- cgit v1.1 From 27cd3784b870deec313678d28de65bb8d7fe4626 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 31 Oct 2010 15:47:04 +0100 Subject: Fix llqtwebkit version incompatibility. This patch has the minimum changes needed to be compatible with LLQTWEBKIT_API_VERSION 2. From llqtwebkit.h: Version 2: indra/media_plugins/webkit/media_plugin_webkit.cpp: * Changed the usage of the event parameters in onClickLinkHref and onClickLinkNoFollow events slightly. The clicked URI for both should now be retrieved with getEventUri() instead of getStringValue(). The "target" string in onClickLinkHref is now retrieved with getStringValue() instead of getStringValue2(). * The contents of getStringValue2() in the onClickLinkHref event is now a unique ID for the window proxy the click targets. all changed files: * Removed the "link target type" concept, since it doesn't really belong here. Note that not all changes have been taken into account, since we need a LOT of code changes for MoaP before that gets relevant; most notably: "target" and "uuid" aren't used anywhere. The new LLEmbeddedBrowserWindowObserver::onWindowGeometryChangeRequested and LLEmbeddedBrowserWindowObserver::onRequestFilePicker are still not implemented. Version 1 introduced LLEmbeddedBrowserWindowObserver::onWindowCloseRequested which is also still not implemented. --- linden/indra/llplugin/llpluginclassmedia.cpp | 28 ---------------------- linden/indra/llplugin/llpluginclassmedia.h | 11 --------- .../media_plugins/webkit/media_plugin_webkit.cpp | 17 ++++++++++--- 3 files changed, 14 insertions(+), 42 deletions(-) (limited to 'linden') diff --git a/linden/indra/llplugin/llpluginclassmedia.cpp b/linden/indra/llplugin/llpluginclassmedia.cpp index 5dc0c47..85241be 100755 --- a/linden/indra/llplugin/llpluginclassmedia.cpp +++ b/linden/indra/llplugin/llpluginclassmedia.cpp @@ -150,7 +150,6 @@ void LLPluginClassMedia::reset() mProgressPercent = 0; mClickURL.clear(); mClickTarget.clear(); - mClickTargetType = TARGET_NONE; // media_time class mCurrentTime = 0.0f; @@ -722,30 +721,6 @@ void LLPluginClassMedia::setJavascriptEnabled(const bool enabled) sendMessage(message); } -LLPluginClassMedia::ETargetType getTargetTypeFromLLQtWebkit(int target_type) -{ - llassert(false); - return LLPluginClassMedia::TARGET_OTHER; -#if 0 - // convert a LinkTargetType value from llqtwebkit to an ETargetType - // so that we don't expose the llqtwebkit header in viewer code - switch (target_type) - { - case LLQtWebKit::LTT_TARGET_NONE: - return LLPluginClassMedia::TARGET_NONE; - - case LLQtWebKit::LTT_TARGET_BLANK: - return LLPluginClassMedia::TARGET_BLANK; - - case LLQtWebKit::LTT_TARGET_EXTERNAL: - return LLPluginClassMedia::TARGET_EXTERNAL; - - default: - return LLPluginClassMedia::TARGET_OTHER; - } -#endif -} - /* virtual */ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { @@ -998,15 +973,12 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { mClickURL = message.getValue("uri"); mClickTarget = message.getValue("target"); - U32 target_type = message.getValueU32("target_type"); - mClickTargetType = ::getTargetTypeFromLLQtWebkit(target_type); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF); } else if(message_name == "click_nofollow") { mClickURL = message.getValue("uri"); mClickTarget.clear(); - mClickTargetType = TARGET_NONE; mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW); } else if(message_name == "cookie_set") diff --git a/linden/indra/llplugin/llpluginclassmedia.h b/linden/indra/llplugin/llpluginclassmedia.h index abb7926..0004971 100755 --- a/linden/indra/llplugin/llpluginclassmedia.h +++ b/linden/indra/llplugin/llpluginclassmedia.h @@ -225,16 +225,6 @@ public: // This is valid after MEDIA_EVENT_CLICK_LINK_HREF std::string getClickTarget() const { return mClickTarget; }; - typedef enum - { - TARGET_NONE, // empty href target string - TARGET_BLANK, // target to open link in user's preferred browser - TARGET_EXTERNAL, // target to open link in external browser - TARGET_OTHER // nonempty and unsupported target type - }ETargetType; - - // This is valid after MEDIA_EVENT_CLICK_LINK_HREF - ETargetType getClickTargetType() const { return mClickTargetType; }; std::string getMediaName() const { return mMediaName; }; std::string getMediaDescription() const { return mMediaDescription; }; @@ -366,7 +356,6 @@ protected: std::string mLocation; std::string mClickURL; std::string mClickTarget; - ETargetType mClickTargetType; ///////////////////////////////////////// // media_time class diff --git a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp index 767090c..eed59a2 100755 --- a/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/linden/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -326,7 +326,11 @@ private: LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled ); // create single browser window +#if LLQTWEBKIT_API_VERSION >= 2 + mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow(mWidth, mHeight /*, mTarget*/ ); // We don't have mTarget yet. +#else mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight ); +#endif // tell LLQtWebKit about the size of the browser window LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); @@ -527,10 +531,14 @@ private: void onClickLinkHref(const EventType& event) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href"); +#if LLQTWEBKIT_API_VERSION >= 2 + message.setValue("uri", event.getEventUri()); + message.setValue("target", event.getStringValue()); + message.setValue("uuid", event.getStringValue2()); +#else + // This will work as long as we don't need "uuid", which will be needed for MoaP. message.setValue("uri", event.getStringValue()); message.setValue("target", event.getStringValue2()); -#if 0 // FIXME (webkit_plugins): error: ‘const class LLEmbeddedBrowserWindowEvent’ has no member named ‘getLinkType’ - message.setValueU32("target_type", event.getLinkType()); #endif sendMessage(message); } @@ -540,10 +548,13 @@ private: void onClickLinkNoFollow(const EventType& event) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow"); +#if LLQTWEBKIT_API_VERSION >= 2 + message.setValue("uri", event.getEventUri()); +#else message.setValue("uri", event.getStringValue()); +#endif sendMessage(message); } - //////////////////////////////////////////////////////////////////////////////// // virtual -- cgit v1.1 From 920cf3112be3f321d623c6d25fe67ded32f92627 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 31 Oct 2010 17:56:55 +0100 Subject: Install qtxmlpatterns4.dll on windows. --- linden/indra/newview/viewer_manifest.py | 1 + 1 file changed, 1 insertion(+) (limited to 'linden') diff --git a/linden/indra/newview/viewer_manifest.py b/linden/indra/newview/viewer_manifest.py index ab88920..d3ce9f2 100755 --- a/linden/indra/newview/viewer_manifest.py +++ b/linden/indra/newview/viewer_manifest.py @@ -282,6 +282,7 @@ class WindowsManifest(ViewerManifest): self.path("qtnetwork4.dll") self.path("qtopengl4.dll") self.path("qtwebkit4.dll") + self.path("qtxmlpatterns4.dll") self.path("ssleay32.dll") self.end_prefix() -- cgit v1.1 From 166d8afffe8e0f6b9168f06e41100680c827d0af Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 31 Oct 2010 19:06:40 +0100 Subject: Add headers from libdbus-1-dev_1.2.1-5+lenny1_i386.deb to dbusglib linux 32 bit package. The dbusglib package contains headers from both, libdbus-1 as well as libdbus-glib-1, but only the shared object file of the latter. This isn't entirely consistent with how we do this for other packages that we want to use the system provided ones for: then we link against prebuilts, but just don't install them. However, if that is working then it's very likely that this method will work too for a C library, so I guess it's ok like this. This package now contains the shared library from libdbus-glib-1-2_0.76-1_i386.deb (plus symlinks) and the headers from libdbus-glib-1-dev_0.76-1_i386.deb AND libdbus-1-dev_1.2.1-5+lenny1_i386.deb. --- linden/install.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linden') diff --git a/linden/install.xml b/linden/install.xml index 4a6cb23..4a5c827 100755 --- a/linden/install.xml +++ b/linden/install.xml @@ -306,9 +306,9 @@ <key>linux</key> <map> <key>md5sum</key> - <string>bfcff12c0d5cef53aa2e04fa53299b23</string> + <string>5bbf7e33dadc7d046dcf44883a9ec3d0</string> <key>url</key> - <uri>http://github.com/downloads/AlericInglewood/imprudence/dbusglib-linux-20101012.tar.bz2</uri> + <uri>http://github.com/downloads/AlericInglewood/imprudence/dbusglib-linux-20101031.tar.bz2</uri> </map> <key>linux64</key> <map> -- cgit v1.1 From 99626354e858db12bba14b44db4568cad6e5b1df Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Sun, 31 Oct 2010 14:47:04 -0700 Subject: Added missing qtxmlpatterns4.dll to CopyWinLibs.cmake --- linden/indra/cmake/CopyWinLibs.cmake | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'linden') diff --git a/linden/indra/cmake/CopyWinLibs.cmake b/linden/indra/cmake/CopyWinLibs.cmake index 44d35ed..a091a31 100644 --- a/linden/indra/cmake/CopyWinLibs.cmake +++ b/linden/indra/cmake/CopyWinLibs.cmake @@ -48,6 +48,7 @@ set(plugintest_debug_files qtnetworkd4.dll qtopengld4.dll qtwebkitd4.dll + qtxmlpatternsd4.dll ssleay32.dll ) copy_if_different( @@ -93,6 +94,7 @@ set(plugintest_release_files qtnetwork4.dll qtopengl4.dll qtwebkit4.dll + qtxmlpatterns4.dll ssleay32.dll ) copy_if_different( @@ -162,6 +164,7 @@ set(plugins_debug_files qtnetworkd4.dll qtopengld4.dll qtwebkitd4.dll + qtxmlpatternsd4.dll ssleay32.dll ) copy_if_different( @@ -181,6 +184,7 @@ set(plugins_release_files qtnetwork4.dll qtopengl4.dll qtwebkit4.dll + qtxmlpatterns4.dll ssleay32.dll ) copy_if_different( -- cgit v1.1 From 7ed48e0084567483064f29d05e1d8d9c3cc74c72 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 2 Nov 2010 10:25:20 -0700 Subject: Deleted OPENAL.cmake.imp file --- linden/indra/cmake/OPENAL.cmake.imp | 115 ------------------------------------ 1 file changed, 115 deletions(-) delete mode 100644 linden/indra/cmake/OPENAL.cmake.imp (limited to 'linden') diff --git a/linden/indra/cmake/OPENAL.cmake.imp b/linden/indra/cmake/OPENAL.cmake.imp deleted file mode 100644 index 60abef3..0000000 --- a/linden/indra/cmake/OPENAL.cmake.imp +++ /dev/null @@ -1,115 +0,0 @@ -# -*- cmake -*- - -include(Variables) -include(Linking) - -set(OPENAL ON CACHE BOOL "Enable OpenAL") - - -if (OPENAL) - - # message(STATUS "Building with OpenAL audio support") - - # OPENAL_LIB - use_prebuilt_binary(openal) - - if (WINDOWS) - set(OPENAL_LIB - optimized ${ARCH_PREBUILT_DIRS_RELEASE}/openal32.lib - debug ${ARCH_PREBUILT_DIRS_DEBUG}/openal32.lib - ) - - elseif (DARWIN) - # Look for for system's OpenAL.framework - find_library(OPENAL_LIB - NAMES openal.1 - PATHS ${ARCH_PREBUILT_DIRS_RELEASE} - NO_DEFAULT_PATH - ) - else (WINDOWS) - set(OPENAL_LIB openal) - endif (WINDOWS) - - if (NOT OPENAL_LIB) - message(FATAL_ERROR "OpenAL not found!") - else (NOT OPENAL_LIB) - # message(STATUS "OpenAL found: ${OPENAL_LIB}") - endif (NOT OPENAL_LIB) - - - - # OPENAL_INCLUDE_DIR - - if (DARWIN) - set(OPENAL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/AL) - else (DARWIN) - find_path(OPENAL_INCLUDE_DIR - NAMES al.h - PATHS ${LIBS_PREBUILT_DIR}/include/AL - ) - endif (DARWIN) - - if (NOT OPENAL_INCLUDE_DIR) - message(FATAL_ERROR "al.h not found!") - else (NOT OPENAL_INCLUDE_DIR) - # message(STATUS "al.h found in: ${OPENAL_INCLUDE_DIR}") - endif (NOT OPENAL_INCLUDE_DIR) - - - - # ALUT_LIB - - if (WINDOWS) - set(ALUT_LIB - optimized ${ARCH_PREBUILT_DIRS_RELEASE}/alut.lib - debug ${ARCH_PREBUILT_DIRS_DEBUG}/alut.lib - ) - elseif (DARWIN) - find_library( ALUT_LIB - NAMES alut.0 - PATHS ${ARCH_PREBUILT_DIRS_RELEASE} - NO_DEFAULT_PATH - ) - else (WINDOWS) - set(ALUT_LIB alut) - endif (WINDOWS) - - if (NOT ALUT_LIB) - message(FATAL_ERROR "ALUT not found!") - else (NOT ALUT_LIB) - # message(STATUS "ALUT found: ${ALUT_LIB}") - endif (NOT ALUT_LIB) - - - - # ALUT_INCLUDE_DIR - - find_path(ALUT_INCLUDE_DIR - NAMES alut.h - PATHS ${OPENAL_INCLUDE_DIR} - ) - - if (NOT ALUT_INCLUDE_DIR) - message(FATAL_ERROR "alut.h not found!") - else (NOT ALUT_INCLUDE_DIR) - # message(STATUS "alut.h found in: ${ALUT_INCLUDE_DIR}") - endif (NOT ALUT_INCLUDE_DIR) - - - - set(OPENAL_LIBRARIES - ${OPENAL_LIB} - ${ALUT_LIB} - ) - - set(OPENAL_INCLUDE_DIRS - ${OPENAL_INCLUDE_DIR} - ${ALUT_INCLUDE_DIR} - ) - - - set(OPENAL_FOUND TRUE CACHE BOOL - "Found OpenAL and ALUT libraries successfully" - ) - -endif (OPENAL) -- cgit v1.1 From 24a25e5dd4633512bfadfa3f8c8687120306c2b9 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 2 Nov 2010 10:25:48 -0700 Subject: Fixed streaming video on Windows by updating mime_types_window.xml to the version used in Viewer 2 --- .../skins/default/xui/en-us/mime_types_windows.xml | 45 +++++++++++++++++++--- 1 file changed, 39 insertions(+), 6 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml b/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml index abc7f1a..61067da 100644 --- a/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml +++ b/linden/indra/newview/skins/default/xui/en-us/mime_types_windows.xml @@ -120,7 +120,7 @@ none </widgettype> <impl> - media_plugin_quicktime + media_plugin_webkit </impl> </mimetype> <mimetype name="none/none"> @@ -130,6 +130,9 @@ <widgettype> none </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="audio/*"> <label name="audio2_label"> @@ -138,6 +141,9 @@ <widgettype> audio </widgettype> + <impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="video/*"> <label name="video2_label"> @@ -146,6 +152,9 @@ <widgettype> movie </widgettype> + <impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="image/*"> <label name="image2_label"> @@ -154,10 +163,13 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> <label name="vnd.secondlife.qt.legacy_label"> - Movie (gstreamer) + Movie (QuickTime) </label> <widgettype> movie @@ -173,6 +185,9 @@ <widgettype> web </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/ogg"> <label name="application/ogg_label"> @@ -181,6 +196,9 @@ <widgettype> audio </widgettype> + <impl> + media_plugin_quicktime + </impl> </mimetype> <mimetype name="application/pdf"> <label name="application/pdf_label"> @@ -189,6 +207,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/postscript"> <label name="application/postscript_label"> @@ -197,6 +218,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/rtf"> <label name="application/rtf_label"> @@ -205,6 +229,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/smil"> <label name="application/smil_label"> @@ -214,7 +241,7 @@ movie </widgettype> <impl> - media_plugin_quicktime + media_plugin_webkit </impl> </mimetype> <mimetype name="application/xhtml+xml"> @@ -224,6 +251,9 @@ <widgettype> web </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="application/x-director"> <label name="application/x-director_label"> @@ -232,6 +262,9 @@ <widgettype> image </widgettype> + <impl> + media_plugin_webkit + </impl> </mimetype> <mimetype name="audio/mid"> <label name="audio/mid_label"> @@ -398,9 +431,9 @@ media_plugin_quicktime </impl> </mimetype> - <mimetype menu="1" name="video/gstreamer"> - <label name="video/gstreamer_label"> - Movie (gstreamer) + <mimetype menu="1" name="video/quicktime"> + <label name="video/quicktime_label"> + Movie (QuickTime) </label> <widgettype> movie -- cgit v1.1 From 14dc0680a2d0b6bb8695a4021551ed74f57cb23c Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 2 Nov 2010 16:55:27 -0700 Subject: Uploaded the linux64 libraries created by Aleric to imprudenceviewer.org --- linden/install.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linden') diff --git a/linden/install.xml b/linden/install.xml index 4a5c827..a6a4670 100755 --- a/linden/install.xml +++ b/linden/install.xml @@ -181,7 +181,7 @@ <key>md5sum</key> <string>a2cde4f24bdcc260b661e139846b8acd</string> <key>url</key> - <uri>http://github.com/downloads/AlericInglewood/imprudence/imprudence-artwork-20101026.tar.bz2</uri> + <uri>http://imprudenceviewer.org/download/libs/imprudence-artwork-20101026.tar.bz2</uri> </map> </map> </map> @@ -308,7 +308,7 @@ <key>md5sum</key> <string>5bbf7e33dadc7d046dcf44883a9ec3d0</string> <key>url</key> - <uri>http://github.com/downloads/AlericInglewood/imprudence/dbusglib-linux-20101031.tar.bz2</uri> + <uri>http://imprudenceviewer.org/download/libs/dbusglib-linux-20101031.tar.bz2</uri> </map> <key>linux64</key> <map> @@ -797,7 +797,7 @@ cairo: Copyright © 2002 University of Southern California, Copyright © 2005 Re <key>md5sum</key> <string>8b5f413bdefec7cfe3d9ad2d69986bdc</string> <key>url</key> - <uri>http://github.com/downloads/AlericInglewood/imprudence/jpeglib-6b-linux64-20101012.tar.bz2</uri> + <uri>http://imprudenceviewer.org/download/libs/jpeglib-6b-linux64-20101012.tar.bz2</uri> </map> <key>windows</key> <map> @@ -1052,7 +1052,7 @@ Portions copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura <key>md5sum</key> <string>863f7b31556b1d368651f85457f4e46d</string> <key>url</key> - <uri>http://github.com/downloads/AlericInglewood/imprudence/llqtwebkit-linux64-20101012.1.tar.bz2</uri> + <uri>http://imprudenceviewer.org/download/libs/llqtwebkit-linux64-20101012.1.tar.bz2</uri> </map> <key>windows</key> <map> -- cgit v1.1