summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorSimon Linden <simon@lindenlab.com>2014-07-18 22:28:33 +0000
committerSimon Linden <simon@lindenlab.com>2014-07-18 22:28:33 +0000
commit7714c7679da7c6c28c3f3f09af6b586a680dc26c (patch)
treef14c766b090f50cbb866123305f676e831ef483b /indra
parent1655887f30e40ea390b6dca9f64ac5e84309be05 (diff)
parentff3827f278d2d53f565bc585edc4db5bc5e5dc38 (diff)
Merge in downstream viewer-tiger
Diffstat (limited to 'indra')
-rwxr-xr-xindra/cmake/00-Common.cmake12
-rwxr-xr-xindra/cmake/APR.cmake6
-rwxr-xr-xindra/cmake/Audio.cmake6
-rwxr-xr-xindra/cmake/BerkeleyDB.cmake6
-rwxr-xr-xindra/cmake/Boost.cmake6
-rwxr-xr-xindra/cmake/BuildVersion.cmake5
-rwxr-xr-xindra/cmake/CARes.cmake6
-rwxr-xr-xindra/cmake/CURL.cmake6
-rwxr-xr-xindra/cmake/Copy3rdPartyLibs.cmake4
-rwxr-xr-xindra/cmake/DBusGlib.cmake4
-rwxr-xr-xindra/cmake/EXPAT.cmake6
-rwxr-xr-xindra/cmake/ExamplePlugin.cmake6
-rw-r--r--indra/cmake/FMODEX.cmake8
-rwxr-xr-xindra/cmake/FindJsonCpp.cmake4
-rwxr-xr-xindra/cmake/FreeType.cmake6
-rw-r--r--indra/cmake/GLEXT.cmake4
-rwxr-xr-xindra/cmake/GLH.cmake6
-rwxr-xr-xindra/cmake/GLOD.cmake4
-rwxr-xr-xindra/cmake/GStreamer010Plugin.cmake8
-rwxr-xr-xindra/cmake/Glui.cmake6
-rwxr-xr-xindra/cmake/GoogleBreakpad.cmake6
-rwxr-xr-xindra/cmake/GooglePerfTools.cmake6
-rwxr-xr-xindra/cmake/Hunspell.cmake6
-rwxr-xr-xindra/cmake/JPEG.cmake6
-rwxr-xr-xindra/cmake/JsonCpp.cmake6
-rw-r--r--[-rwxr-xr-x]indra/cmake/LLAddBuildTest.cmake10
-rwxr-xr-xindra/cmake/LLPrimitive.cmake15
-rwxr-xr-xindra/cmake/LLWindow.cmake6
-rwxr-xr-xindra/cmake/NDOF.cmake6
-rwxr-xr-xindra/cmake/OPENAL.cmake6
-rwxr-xr-xindra/cmake/OpenJPEG.cmake6
-rwxr-xr-xindra/cmake/OpenSSL.cmake6
-rwxr-xr-xindra/cmake/PNG.cmake6
-rwxr-xr-xindra/cmake/Prebuilt.cmake10
-rwxr-xr-xindra/cmake/PulseAudio.cmake4
-rwxr-xr-xindra/cmake/Tut.cmake4
-rwxr-xr-xindra/cmake/UI.cmake6
-rwxr-xr-xindra/cmake/Variables.cmake2
-rwxr-xr-xindra/cmake/ViewerMiscLibs.cmake4
-rwxr-xr-xindra/cmake/WebKitLibPlugin.cmake6
-rwxr-xr-xindra/cmake/XmlRpcEpi.cmake6
-rwxr-xr-xindra/cmake/ZLIB.cmake6
-rwxr-xr-xindra/edit-me-to-trigger-new-build.txt8
-rwxr-xr-xindra/integration_tests/llimage_libtest/CMakeLists.txt3
-rw-r--r--indra/integration_tests/llimage_libtest/filters/1970colorize.xml41
-rwxr-xr-xindra/integration_tests/llimage_libtest/filters/autocontrast.xml11
-rwxr-xr-xindra/integration_tests/llimage_libtest/filters/badtrip.xml36
-rw-r--r--indra/integration_tests/llimage_libtest/filters/blowhighlights.xml25
-rw-r--r--indra/integration_tests/llimage_libtest/filters/blur.xml7
-rwxr-xr-xindra/integration_tests/llimage_libtest/filters/brighten.xml11
-rw-r--r--indra/integration_tests/llimage_libtest/filters/colorize.xml24
-rw-r--r--indra/integration_tests/llimage_libtest/filters/colortransform.xml16
-rw-r--r--indra/integration_tests/llimage_libtest/filters/contrast.xml11
-rw-r--r--indra/integration_tests/llimage_libtest/filters/convolve.xml18
-rwxr-xr-xindra/integration_tests/llimage_libtest/filters/darken.xml11
-rw-r--r--indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml47
-rw-r--r--indra/integration_tests/llimage_libtest/filters/edges.xml24
-rw-r--r--indra/integration_tests/llimage_libtest/filters/focus.xml39
-rw-r--r--indra/integration_tests/llimage_libtest/filters/gamma.xml11
-rw-r--r--indra/integration_tests/llimage_libtest/filters/grayscale.xml14
-rw-r--r--indra/integration_tests/llimage_libtest/filters/heatwave.xml38
-rw-r--r--indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml20
-rw-r--r--indra/integration_tests/llimage_libtest/filters/julesverne.xml20
-rw-r--r--indra/integration_tests/llimage_libtest/filters/lensflare.xml131
-rwxr-xr-xindra/integration_tests/llimage_libtest/filters/lightleak.xml78
-rwxr-xr-xindra/integration_tests/llimage_libtest/filters/linearize.xml11
-rwxr-xr-xindra/integration_tests/llimage_libtest/filters/miniature.xml118
-rwxr-xr-xindra/integration_tests/llimage_libtest/filters/newsscreen.xml20
-rw-r--r--indra/integration_tests/llimage_libtest/filters/overcast.xml24
-rwxr-xr-xindra/integration_tests/llimage_libtest/filters/pixelate.xml35
-rwxr-xr-xindra/integration_tests/llimage_libtest/filters/posterize.xml11
-rw-r--r--indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml8
-rw-r--r--indra/integration_tests/llimage_libtest/filters/saturate.xml8
-rw-r--r--indra/integration_tests/llimage_libtest/filters/sepia.xml14
-rw-r--r--indra/integration_tests/llimage_libtest/filters/sharpen.xml7
-rw-r--r--indra/integration_tests/llimage_libtest/filters/slantedscreen.xml20
-rw-r--r--indra/integration_tests/llimage_libtest/filters/spotlight.xml45
-rw-r--r--indra/integration_tests/llimage_libtest/filters/stencilgradient.xml24
-rw-r--r--indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml22
-rw-r--r--indra/integration_tests/llimage_libtest/filters/stenciluniform.xml20
-rw-r--r--indra/integration_tests/llimage_libtest/filters/stencilvignette.xml24
-rwxr-xr-xindra/integration_tests/llimage_libtest/filters/thematrix.xml42
-rwxr-xr-xindra/integration_tests/llimage_libtest/filters/toycamera.xml46
-rw-r--r--indra/integration_tests/llimage_libtest/filters/verticalscreen.xml20
-rwxr-xr-xindra/integration_tests/llimage_libtest/filters/video.xml44
-rwxr-xr-xindra/integration_tests/llimage_libtest/llimage_libtest.cpp39
-rwxr-xr-x[-rw-r--r--]indra/llappearance/llavatarappearance.cpp28
-rwxr-xr-x[-rw-r--r--]indra/llappearance/llavatarappearance.h10
-rwxr-xr-x[-rw-r--r--]indra/llappearance/lldriverparam.cpp58
-rwxr-xr-x[-rw-r--r--]indra/llappearance/lldriverparam.h9
-rw-r--r--indra/llappearance/llpolymorph.cpp61
-rw-r--r--indra/llappearance/llpolymorph.h3
-rw-r--r--indra/llappearance/llpolyskeletaldistortion.cpp38
-rw-r--r--indra/llappearance/llpolyskeletaldistortion.h2
-rwxr-xr-x[-rw-r--r--]indra/llappearance/lltexglobalcolor.cpp28
-rwxr-xr-x[-rw-r--r--]indra/llappearance/lltexglobalcolor.h4
-rw-r--r--indra/llappearance/lltexlayer.cpp19
-rwxr-xr-x[-rw-r--r--]indra/llappearance/lltexlayerparams.cpp94
-rwxr-xr-x[-rw-r--r--]indra/llappearance/lltexlayerparams.h20
-rw-r--r--indra/llappearance/llviewervisualparam.cpp18
-rw-r--r--indra/llappearance/llviewervisualparam.h4
-rwxr-xr-x[-rw-r--r--]indra/llappearance/llwearable.cpp54
-rwxr-xr-x[-rw-r--r--]indra/llappearance/llwearable.h7
-rwxr-xr-x[-rw-r--r--]indra/llappearance/llwearabledata.cpp7
-rwxr-xr-xindra/llcharacter/llcharacter.cpp14
-rwxr-xr-xindra/llcharacter/llcharacter.h6
-rwxr-xr-xindra/llcharacter/lljoint.cpp42
-rwxr-xr-xindra/llcharacter/lljoint.h8
-rwxr-xr-xindra/llcharacter/llmotioncontroller.cpp7
-rwxr-xr-xindra/llcharacter/llvisualparam.cpp50
-rwxr-xr-xindra/llcharacter/llvisualparam.h11
-rwxr-xr-xindra/llcommon/CMakeLists.txt1
-rwxr-xr-xindra/llcommon/llerror.cpp444
-rwxr-xr-xindra/llcommon/llerror.h4
-rwxr-xr-xindra/llcommon/llerrorcontrol.h23
-rwxr-xr-xindra/llcommon/llhttpstatuscodes.h89
-rwxr-xr-xindra/llcommon/llinitparam.h3
-rwxr-xr-xindra/llcommon/llpointer.h126
-rwxr-xr-xindra/llcommon/llsd.cpp11
-rwxr-xr-xindra/llcommon/llsd.h5
-rwxr-xr-xindra/llcommon/llsdserialize.cpp67
-rwxr-xr-xindra/llcommon/llsdserialize.h28
-rwxr-xr-xindra/llcommon/llsdserialize_xml.cpp17
-rwxr-xr-xindra/llcommon/llsdutil.cpp2
-rwxr-xr-xindra/llcommon/llsys.cpp2
-rwxr-xr-xindra/llcommon/lluuid.h11
-rwxr-xr-xindra/llcommon/tests/llerror_test.cpp78
-rwxr-xr-xindra/llcommon/tests/stringize_test.cpp2
-rwxr-xr-xindra/llcommon/tests/wrapllerrs.h117
-rwxr-xr-xindra/llcorehttp/_httplibcurl.cpp2
-rwxr-xr-xindra/llcorehttp/_httpoprequest.cpp3
-rwxr-xr-xindra/llcrashlogger/llcrashlogger.cpp7
-rwxr-xr-xindra/llimage/CMakeLists.txt2
-rwxr-xr-xindra/llimage/llimage.cpp80
-rwxr-xr-xindra/llimage/llimage.h3
-rwxr-xr-xindra/llimage/llimagefilter.cpp939
-rwxr-xr-xindra/llimage/llimagefilter.h137
-rwxr-xr-xindra/llimage/llimagejpeg.h2
-rwxr-xr-xindra/llinventory/llfoldertype.cpp2
-rwxr-xr-xindra/llinventory/llinventory.cpp35
-rwxr-xr-xindra/llinventory/llinventory.h9
-rwxr-xr-xindra/llmath/llmath.h6
-rwxr-xr-xindra/llmath/lloctree.h15
-rwxr-xr-xindra/llmath/llquaternion.cpp447
-rwxr-xr-xindra/llmath/llquaternion.h50
-rwxr-xr-xindra/llmath/v3dmath.h63
-rwxr-xr-xindra/llmath/v3math.h34
-rwxr-xr-xindra/llmessage/CMakeLists.txt11
-rwxr-xr-xindra/llmessage/llares.cpp9
-rwxr-xr-xindra/llmessage/llares.h3
-rwxr-xr-xindra/llmessage/llavatarnamecache.cpp49
-rwxr-xr-xindra/llmessage/llavatarnamecache.h2
-rwxr-xr-xindra/llmessage/llcurl.cpp255
-rwxr-xr-xindra/llmessage/llcurl.h111
-rwxr-xr-xindra/llmessage/llhttpassetstorage.cpp23
-rwxr-xr-xindra/llmessage/llhttpclient.cpp188
-rwxr-xr-xindra/llmessage/llhttpclient.h26
-rwxr-xr-xindra/llmessage/llhttpclientadapter.cpp25
-rwxr-xr-xindra/llmessage/llhttpclientadapter.h8
-rwxr-xr-xindra/llmessage/llhttpconstants.cpp228
-rwxr-xr-xindra/llmessage/llhttpconstants.h225
-rwxr-xr-xindra/llmessage/llhttpnode.cpp33
-rwxr-xr-xindra/llmessage/llhttpnode.h30
-rwxr-xr-xindra/llmessage/lliohttpserver.cpp84
-rwxr-xr-xindra/llmessage/lliohttpserver.h12
-rwxr-xr-xindra/llmessage/lliosocket.cpp7
-rwxr-xr-xindra/llmessage/lliosocket.h3
-rwxr-xr-xindra/llmessage/llmime.cpp629
-rwxr-xr-xindra/llmessage/llmime.h292
-rwxr-xr-xindra/llmessage/llregionpresenceverifier.cpp153
-rwxr-xr-xindra/llmessage/llregionpresenceverifier.h98
-rwxr-xr-xindra/llmessage/llsdappservices.cpp10
-rwxr-xr-xindra/llmessage/llsdhttpserver.cpp2
-rwxr-xr-xindra/llmessage/llsdmessage.cpp20
-rwxr-xr-xindra/llmessage/llsdmessage.h6
-rwxr-xr-xindra/llmessage/llsdrpcclient.h8
-rwxr-xr-xindra/llmessage/lltrustedmessageservice.cpp8
-rwxr-xr-xindra/llmessage/lltrustedmessageservice.h4
-rwxr-xr-xindra/llmessage/llurlrequest.cpp69
-rwxr-xr-xindra/llmessage/llurlrequest.h54
-rwxr-xr-xindra/llmessage/message.cpp14
-rwxr-xr-xindra/llmessage/tests/llcurl_stub.cpp59
-rwxr-xr-xindra/llmessage/tests/llhttpclient_test.cpp33
-rwxr-xr-xindra/llmessage/tests/llhttpclientadapter_test.cpp81
-rwxr-xr-xindra/llmessage/tests/llhttpnode_stub.cpp107
-rwxr-xr-xindra/llmessage/tests/llmime_test.cpp445
-rwxr-xr-xindra/llmessage/tests/llregionpresenceverifier_test.cpp108
-rwxr-xr-xindra/llmessage/tests/lltrustedmessageservice_test.cpp1
-rwxr-xr-xindra/llplugin/llplugincookiestore.cpp9
-rwxr-xr-xindra/llplugin/llpluginprocessparent.cpp4
-rwxr-xr-xindra/llprimitive/llmodel.cpp2
-rwxr-xr-xindra/llrender/llgl.cpp1
-rwxr-xr-xindra/llrender/llimagegl.cpp65
-rwxr-xr-xindra/llrender/llimagegl.h3
-rwxr-xr-xindra/llui/llbadgeowner.cpp45
-rwxr-xr-xindra/llui/llbadgeowner.h8
-rwxr-xr-xindra/llui/llbutton.cpp2
-rwxr-xr-xindra/llui/llchatentry.cpp10
-rwxr-xr-xindra/llui/llfloater.cpp2
-rwxr-xr-xindra/llui/llfloater.h2
-rwxr-xr-xindra/llui/llfolderview.cpp28
-rwxr-xr-xindra/llui/llkeywords.cpp508
-rwxr-xr-xindra/llui/llkeywords.h115
-rwxr-xr-xindra/llui/lllineeditor.cpp1
-rwxr-xr-xindra/llui/llmenubutton.cpp1
-rwxr-xr-xindra/llui/llmenugl.cpp1
-rwxr-xr-xindra/llui/llmenugl.h17
-rwxr-xr-xindra/llui/llnotifications.cpp1
-rwxr-xr-xindra/llui/llnotifications.h8
-rw-r--r--indra/llui/llnotificationslistener.cpp27
-rwxr-xr-xindra/llui/llscrolllistctrl.cpp1
-rwxr-xr-xindra/llui/lltabcontainer.cpp21
-rwxr-xr-xindra/llui/lltextbase.cpp59
-rwxr-xr-xindra/llui/lltextbase.h42
-rwxr-xr-xindra/llui/lltexteditor.cpp130
-rwxr-xr-xindra/llui/lltexteditor.h56
-rwxr-xr-xindra/llui/lltextutil.cpp4
-rwxr-xr-xindra/llui/lltextutil.h2
-rwxr-xr-xindra/llui/lltoolbar.cpp1
-rwxr-xr-xindra/llui/llurlregistry.cpp11
-rwxr-xr-xindra/llui/llurlregistry.h4
-rwxr-xr-xindra/llui/llxuiparser.cpp2
-rwxr-xr-xindra/llvfs/llvfile.cpp2
-rwxr-xr-xindra/llvfs/tests/lldiriterator_test.cpp6
-rwxr-xr-xindra/llwindow/lldxhardware.cpp178
-rwxr-xr-xindra/llwindow/llwindow.cpp4
-rwxr-xr-xindra/llwindow/llwindowmacosx.cpp27
-rwxr-xr-xindra/llwindow/llwindowsdl.cpp4
-rwxr-xr-xindra/llwindow/llwindowwin32.cpp36
-rwxr-xr-xindra/llxml/llxmlnode.h2
-rwxr-xr-xindra/llxml/llxmlparser.h2
-rwxr-xr-xindra/newview/CMakeLists.txt58
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rwxr-xr-xindra/newview/app_settings/commands.xml32
-rwxr-xr-xindra/newview/app_settings/filters/Autocontrast.xml11
-rw-r--r--indra/newview/app_settings/filters/BlackAndWhite.xml21
-rw-r--r--indra/newview/app_settings/filters/Colors1970.xml47
-rw-r--r--indra/newview/app_settings/filters/Intense.xml8
-rw-r--r--indra/newview/app_settings/filters/LensFlare.xml131
-rwxr-xr-xindra/newview/app_settings/filters/Miniature.xml118
-rwxr-xr-xindra/newview/app_settings/filters/Newspaper.xml20
-rw-r--r--indra/newview/app_settings/filters/Sepia.xml32
-rw-r--r--indra/newview/app_settings/filters/Spotlight.xml47
-rwxr-xr-xindra/newview/app_settings/filters/Toycamera.xml46
-rwxr-xr-xindra/newview/app_settings/filters/Video.xml44
-rwxr-xr-xindra/newview/app_settings/keywords_lsl_default.xml18289
-rwxr-xr-xindra/newview/app_settings/llsd-lsl-syntax.rng390
-rwxr-xr-xindra/newview/app_settings/logcontrol.xml1
-rwxr-xr-xindra/newview/app_settings/settings.xml501
-rwxr-xr-xindra/newview/app_settings/toolbars.xml2
-rwxr-xr-xindra/newview/character/avatar_lad.xml14
-rwxr-xr-xindra/newview/featuretable_mac.txt6
-rwxr-xr-xindra/newview/installers/windows/installer_template.nsi187
-rwxr-xr-xindra/newview/installers/windows/lang_da.nsibin7108 -> 8026 bytes
-rwxr-xr-xindra/newview/installers/windows/lang_de.nsibin8260 -> 9346 bytes
-rwxr-xr-xindra/newview/installers/windows/lang_en-us.nsibin7542 -> 8120 bytes
-rwxr-xr-xindra/newview/installers/windows/lang_es.nsibin7846 -> 8764 bytes
-rwxr-xr-xindra/newview/installers/windows/lang_fr.nsibin8114 -> 9030 bytes
-rwxr-xr-xindra/newview/installers/windows/lang_it.nsibin7438 -> 8372 bytes
-rwxr-xr-xindra/newview/installers/windows/lang_ja.nsibin6302 -> 7288 bytes
-rwxr-xr-xindra/newview/installers/windows/lang_pl.nsibin7450 -> 8426 bytes
-rwxr-xr-xindra/newview/installers/windows/lang_pt-br.nsibin7832 -> 8788 bytes
-rwxr-xr-xindra/newview/installers/windows/lang_ru.nsibin7598 -> 8144 bytes
-rwxr-xr-xindra/newview/installers/windows/lang_tr.nsibin7722 -> 8266 bytes
-rwxr-xr-xindra/newview/installers/windows/lang_zh.nsibin5824 -> 6798 bytes
-rwxr-xr-xindra/newview/llaccountingcostmanager.cpp14
-rwxr-xr-xindra/newview/llaccountingcostmanager.h2
-rwxr-xr-xindra/newview/llagent.cpp385
-rwxr-xr-xindra/newview/llagent.h35
-rwxr-xr-xindra/newview/llagentcamera.cpp2
-rwxr-xr-xindra/newview/llagentwearables.cpp674
-rwxr-xr-xindra/newview/llagentwearables.h58
-rwxr-xr-xindra/newview/llagentwearablesfetch.cpp600
-rwxr-xr-xindra/newview/llagentwearablesfetch.h114
-rwxr-xr-xindra/newview/llaisapi.cpp867
-rwxr-xr-xindra/newview/llaisapi.h183
-rwxr-xr-xindra/newview/llappearancemgr.cpp1746
-rwxr-xr-xindra/newview/llappearancemgr.h95
-rwxr-xr-xindra/newview/llappviewer.cpp19
-rw-r--r--indra/newview/llappviewerwin32.cpp21
-rw-r--r--indra/newview/llappviewerwin32.h3
-rwxr-xr-xindra/newview/llassetuploadqueue.cpp81
-rwxr-xr-xindra/newview/llassetuploadresponders.cpp128
-rwxr-xr-xindra/newview/llassetuploadresponders.h41
-rwxr-xr-xindra/newview/llbreastmotion.cpp3
-rwxr-xr-xindra/newview/llchathistory.cpp47
-rwxr-xr-xindra/newview/llchathistory.h7
-rwxr-xr-xindra/newview/llchatitemscontainerctrl.cpp27
-rwxr-xr-xindra/newview/llchatitemscontainerctrl.h2
-rwxr-xr-xindra/newview/llchiclet.cpp1
-rwxr-xr-xindra/newview/llclassifiedstatsresponder.cpp13
-rwxr-xr-xindra/newview/llclassifiedstatsresponder.h8
-rwxr-xr-xindra/newview/llcolorswatch.h3
-rwxr-xr-xindra/newview/lldrawpoolbump.cpp2
-rwxr-xr-xindra/newview/llemote.cpp12
-rwxr-xr-xindra/newview/llestateinfomodel.cpp10
-rwxr-xr-xindra/newview/lleventpoll.cpp51
-rwxr-xr-x[-rw-r--r--]indra/newview/llfacebookconnect.cpp303
-rw-r--r--indra/newview/llfacebookconnect.h2
-rwxr-xr-xindra/newview/llfeaturemanager.cpp20
-rwxr-xr-xindra/newview/llfilepicker.cpp22
-rwxr-xr-xindra/newview/llfilepicker.h3
-rw-r--r--indra/newview/llflickrconnect.cpp509
-rw-r--r--indra/newview/llflickrconnect.h98
-rwxr-xr-xindra/newview/llfloaterabout.cpp37
-rwxr-xr-xindra/newview/llfloateravatarpicker.cpp15
-rw-r--r--indra/newview/llfloaterbigpreview.cpp110
-rw-r--r--indra/newview/llfloaterbigpreview.h54
-rwxr-xr-xindra/newview/llfloaterbuycurrencyhtml.cpp3
-rwxr-xr-xindra/newview/llfloaterbvhpreview.cpp2
-rwxr-xr-xindra/newview/llfloatercolorpicker.cpp14
-rw-r--r--indra/newview/llfloaterfacebook.cpp (renamed from indra/newview/llfloatersocial.cpp)578
-rw-r--r--indra/newview/llfloaterfacebook.h (renamed from indra/newview/llfloatersocial.h)80
-rw-r--r--indra/newview/llfloaterflickr.cpp798
-rw-r--r--indra/newview/llfloaterflickr.h135
-rwxr-xr-xindra/newview/llfloatergesture.cpp29
-rw-r--r--indra/newview/llfloatergotoline.cpp2
-rwxr-xr-xindra/newview/llfloaterhelpbrowser.cpp6
-rwxr-xr-x[-rw-r--r--]indra/newview/llfloaterimsession.cpp7
-rwxr-xr-xindra/newview/llfloatermodelpreview.cpp4
-rwxr-xr-xindra/newview/llfloatermodelpreview.h4
-rwxr-xr-xindra/newview/llfloatermodeluploadbase.cpp6
-rwxr-xr-xindra/newview/llfloatermodeluploadbase.h4
-rwxr-xr-xindra/newview/llfloaternamedesc.cpp6
-rwxr-xr-xindra/newview/llfloaterobjectweights.cpp2
-rwxr-xr-xindra/newview/llfloaterobjectweights.h2
-rwxr-xr-xindra/newview/llfloateropenobject.cpp20
-rwxr-xr-xindra/newview/llfloateropenobject.h11
-rwxr-xr-xindra/newview/llfloaterperms.cpp229
-rwxr-xr-xindra/newview/llfloaterperms.h55
-rwxr-xr-xindra/newview/llfloaterpreference.cpp9
-rwxr-xr-xindra/newview/llfloaterpreference.h1
-rwxr-xr-xindra/newview/llfloaterregiondebugconsole.cpp16
-rwxr-xr-xindra/newview/llfloaterregioninfo.cpp25
-rwxr-xr-xindra/newview/llfloaterreporter.cpp14
-rw-r--r--indra/newview/llfloaterscriptedprefs.cpp65
-rw-r--r--indra/newview/llfloaterscriptedprefs.h51
-rwxr-xr-xindra/newview/llfloaterscriptlimits.cpp63
-rwxr-xr-xindra/newview/llfloaterscriptlimits.h56
-rwxr-xr-xindra/newview/llfloatersearch.cpp3
-rwxr-xr-xindra/newview/llfloatersnapshot.cpp129
-rwxr-xr-xindra/newview/llfloatersnapshot.h2
-rwxr-xr-xindra/newview/llfloatertools.cpp6
-rwxr-xr-xindra/newview/llfloatertos.cpp68
-rw-r--r--indra/newview/llfloatertwitter.cpp827
-rw-r--r--indra/newview/llfloatertwitter.h139
-rwxr-xr-xindra/newview/llfloateruipreview.cpp7
-rwxr-xr-xindra/newview/llfloaterurlentry.cpp41
-rwxr-xr-xindra/newview/llfloaterurlentry.h2
-rwxr-xr-xindra/newview/llfloaterwebcontent.cpp55
-rwxr-xr-xindra/newview/llfloaterwebcontent.h4
-rwxr-xr-xindra/newview/llfriendcard.cpp5
-rwxr-xr-xindra/newview/llgesturemgr.cpp13
-rwxr-xr-xindra/newview/llgroupmgr.cpp26
-rwxr-xr-xindra/newview/llhomelocationresponder.cpp35
-rwxr-xr-xindra/newview/llhomelocationresponder.h6
-rwxr-xr-xindra/newview/llhttpretrypolicy.cpp142
-rwxr-xr-xindra/newview/llhttpretrypolicy.h98
-rw-r--r--indra/newview/llimagefiltersmanager.cpp115
-rw-r--r--indra/newview/llimagefiltersmanager.h55
-rwxr-xr-xindra/newview/llimpanel.cpp7
-rwxr-xr-xindra/newview/llimview.cpp65
-rwxr-xr-xindra/newview/llimview.h8
-rwxr-xr-xindra/newview/llinspectavatar.cpp5
-rwxr-xr-xindra/newview/llinventorybridge.cpp242
-rwxr-xr-xindra/newview/llinventorybridge.h5
-rwxr-xr-xindra/newview/llinventoryfunctions.cpp16
-rwxr-xr-xindra/newview/llinventoryfunctions.h7
-rwxr-xr-xindra/newview/llinventorymodel.cpp1274
-rwxr-xr-xindra/newview/llinventorymodel.h87
-rwxr-xr-xindra/newview/llinventorymodelbackgroundfetch.cpp120
-rwxr-xr-xindra/newview/llinventoryobserver.cpp181
-rwxr-xr-xindra/newview/llinventoryobserver.h63
-rwxr-xr-xindra/newview/llinventorypanel.cpp8
-rwxr-xr-xindra/newview/lllistcontextmenu.cpp1
-rwxr-xr-xindra/newview/lllocalbitmaps.cpp19
-rwxr-xr-xindra/newview/lllocalbitmaps.h1
-rwxr-xr-xindra/newview/lllocationinputctrl.cpp12
-rwxr-xr-xindra/newview/llmaniprotate.cpp29
-rwxr-xr-xindra/newview/llmanipscale.cpp713
-rwxr-xr-xindra/newview/llmanipscale.h53
-rwxr-xr-xindra/newview/llmaniptranslate.cpp13
-rwxr-xr-xindra/newview/llmaniptranslate.h2
-rwxr-xr-xindra/newview/llmarketplacefunctions.cpp66
-rwxr-xr-x[-rw-r--r--]indra/newview/llmaterialmgr.cpp13
-rwxr-xr-xindra/newview/llmediactrl.cpp20
-rwxr-xr-xindra/newview/llmediactrl.h4
-rwxr-xr-xindra/newview/llmediadataclient.cpp52
-rwxr-xr-xindra/newview/llmediadataclient.h29
-rwxr-xr-xindra/newview/llmeshrepository.cpp16
-rwxr-xr-xindra/newview/llnamelistctrl.cpp33
-rwxr-xr-xindra/newview/llnamelistctrl.h13
-rwxr-xr-xindra/newview/llpanelclassified.cpp10
-rwxr-xr-xindra/newview/llpanelcontents.cpp11
-rwxr-xr-xindra/newview/llpaneleditwearable.cpp44
-rwxr-xr-xindra/newview/llpanelgrouplandmoney.cpp33
-rwxr-xr-xindra/newview/llpanelgrouproles.cpp35
-rwxr-xr-xindra/newview/llpanelgrouproles.h5
-rwxr-xr-xindra/newview/llpanelland.cpp2
-rwxr-xr-xindra/newview/llpanellandmarks.cpp3
-rwxr-xr-xindra/newview/llpanellandmarks.h2
-rwxr-xr-xindra/newview/llpanellogin.cpp4
-rwxr-xr-xindra/newview/llpanelmarketplaceinboxinventory.cpp10
-rwxr-xr-xindra/newview/llpaneloutfitedit.cpp6
-rwxr-xr-xindra/newview/llpaneloutfitsinventory.cpp5
-rwxr-xr-xindra/newview/llpanelpeople.cpp6
-rwxr-xr-xindra/newview/llpanelpeople.h2
-rwxr-xr-xindra/newview/llpanelpick.h2
-rwxr-xr-xindra/newview/llpanelplaceinfo.cpp6
-rwxr-xr-xindra/newview/llpanelplaceinfo.h2
-rwxr-xr-xindra/newview/llpanelplaceprofile.cpp5
-rwxr-xr-xindra/newview/llpanelplaceprofile.h1
-rwxr-xr-xindra/newview/llpanelplaces.cpp9
-rwxr-xr-xindra/newview/llpanelplaces.h2
-rwxr-xr-xindra/newview/llpanelsnapshotoptions.cpp57
-rwxr-xr-xindra/newview/llpanelteleporthistory.cpp64
-rwxr-xr-xindra/newview/llpathfindingmanager.cpp178
-rwxr-xr-xindra/newview/llpathfindingnavmesh.cpp4
-rwxr-xr-xindra/newview/llpathfindingnavmesh.h2
-rwxr-xr-xindra/newview/llphysicsmotion.cpp8
-rwxr-xr-xindra/newview/llpreview.cpp9
-rwxr-xr-xindra/newview/llpreviewscript.cpp105
-rwxr-xr-xindra/newview/llpreviewscript.h20
-rwxr-xr-xindra/newview/llproductinforequest.cpp18
-rwxr-xr-xindra/newview/llremoteparcelrequest.cpp17
-rwxr-xr-xindra/newview/llremoteparcelrequest.h9
-rwxr-xr-xindra/newview/llscreenchannel.cpp8
-rw-r--r--indra/newview/llscripteditor.cpp289
-rw-r--r--indra/newview/llscripteditor.h70
-rwxr-xr-xindra/newview/llscrollingpanelparam.cpp6
-rwxr-xr-xindra/newview/llscrollingpanelparambase.cpp2
-rwxr-xr-xindra/newview/llsidepanelappearance.cpp2
-rwxr-xr-xindra/newview/llsidepanelinventory.cpp12
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp672
-rw-r--r--indra/newview/llsnapshotlivepreview.h40
-rwxr-xr-xindra/newview/llspatialpartition.cpp1
-rwxr-xr-xindra/newview/llspatialpartition.h16
-rwxr-xr-xindra/newview/llspeakers.cpp13
-rwxr-xr-xindra/newview/llstartup.cpp111
-rw-r--r--indra/newview/llsyntaxid.cpp330
-rw-r--r--indra/newview/llsyntaxid.h73
-rwxr-xr-xindra/newview/lltexturefetch.cpp273
-rwxr-xr-xindra/newview/lltexturefetch.h13
-rwxr-xr-xindra/newview/lltextureview.cpp10
-rwxr-xr-xindra/newview/lltoastimpanel.cpp1
-rwxr-xr-xindra/newview/lltoastnotifypanel.cpp9
-rwxr-xr-xindra/newview/lltooldraganddrop.cpp90
-rwxr-xr-xindra/newview/lltoolmorph.cpp22
-rwxr-xr-xindra/newview/lltoolpie.cpp12
-rwxr-xr-xindra/newview/lltranslate.cpp18
-rwxr-xr-xindra/newview/lltranslate.h7
-rw-r--r--indra/newview/lltwitterconnect.cpp503
-rw-r--r--indra/newview/lltwitterconnect.h99
-rwxr-xr-xindra/newview/lluploadfloaterobservers.cpp20
-rwxr-xr-xindra/newview/lluploadfloaterobservers.h19
-rwxr-xr-xindra/newview/llviewercontrol.cpp1
-rwxr-xr-xindra/newview/llviewerdisplayname.cpp14
-rwxr-xr-xindra/newview/llviewerfloaterreg.cpp20
-rw-r--r--indra/newview/llviewerfoldertype.cpp8
-rwxr-xr-xindra/newview/llviewerinventory.cpp839
-rwxr-xr-xindra/newview/llviewerinventory.h86
-rwxr-xr-xindra/newview/llviewermedia.cpp162
-rwxr-xr-xindra/newview/llviewermedia.h5
-rwxr-xr-xindra/newview/llviewermenu.cpp3
-rwxr-xr-xindra/newview/llviewermenufile.cpp15
-rwxr-xr-xindra/newview/llviewermessage.cpp111
-rwxr-xr-xindra/newview/llviewerobject.cpp26
-rwxr-xr-xindra/newview/llviewerobject.h1
-rwxr-xr-xindra/newview/llviewerobjectlist.cpp27
-rwxr-xr-xindra/newview/llviewerparcelmedia.cpp2
-rwxr-xr-xindra/newview/llviewerregion.cpp274
-rwxr-xr-xindra/newview/llviewerregion.h3
-rwxr-xr-xindra/newview/llviewershadermgr.cpp10
-rwxr-xr-xindra/newview/llviewershadermgr.h1
-rwxr-xr-xindra/newview/llviewerstats.cpp59
-rwxr-xr-xindra/newview/llviewerstats.h5
-rwxr-xr-xindra/newview/llviewertexlayer.cpp404
-rwxr-xr-x[-rw-r--r--]indra/newview/llviewertexlayer.h47
-rwxr-xr-xindra/newview/llviewertexture.cpp204
-rwxr-xr-xindra/newview/llviewertexture.h22
-rwxr-xr-x[-rw-r--r--]indra/newview/llviewerwearable.cpp50
-rwxr-xr-x[-rw-r--r--]indra/newview/llviewerwearable.h12
-rwxr-xr-xindra/newview/llviewerwindow.cpp42
-rwxr-xr-xindra/newview/llvoavatar.cpp434
-rwxr-xr-xindra/newview/llvoavatar.h21
-rwxr-xr-xindra/newview/llvoavatarself.cpp501
-rwxr-xr-xindra/newview/llvoavatarself.h31
-rwxr-xr-xindra/newview/llvoicechannel.cpp21
-rwxr-xr-xindra/newview/llvoicevivox.cpp48
-rwxr-xr-xindra/newview/llvoicevivox.h2
-rwxr-xr-xindra/newview/llvovolume.cpp173
-rwxr-xr-xindra/newview/llwearablelist.cpp1
-rwxr-xr-xindra/newview/llwebprofile.cpp52
-rwxr-xr-xindra/newview/llwindebug.cpp20
-rwxr-xr-xindra/newview/llwindebug.h1
-rwxr-xr-xindra/newview/llwlhandlers.cpp27
-rwxr-xr-xindra/newview/llwlhandlers.h14
-rwxr-xr-xindra/newview/llworld.cpp2
-rwxr-xr-xindra/newview/llxmlrpctransaction.cpp2
-rwxr-xr-xindra/newview/pipeline.cpp62
-rwxr-xr-xindra/newview/skins/default/colors.xml44
-rwxr-xr-xindra/newview/skins/default/textures/textures.xml10
-rw-r--r--indra/newview/skins/default/textures/toolbar_icons/flickr.pngbin0 -> 15530 bytes
-rw-r--r--indra/newview/skins/default/textures/toolbar_icons/twitter.pngbin0 -> 16051 bytes
-rwxr-xr-xindra/newview/skins/default/xui/da/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/de/panel_preferences_privacy.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_big_preview.xml25
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_buy_object.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_facebook.xml111
-rw-r--r--indra/newview/skins/default/xui/en/floater_flickr.xml (renamed from indra/newview/skins/default/xui/en/floater_social.xml)39
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_perm_prefs.xml108
-rw-r--r--indra/newview/skins/default/xui/en/floater_perms_default.xml503
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_region_debug_console.xml1
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_report_abuse.xml128
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_ed_prefs.xml359
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_snapshot.xml28
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_tools.xml20
-rw-r--r--indra/newview/skins/default/xui/en/floater_twitter.xml90
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_inventory_add.xml7
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_object.xml19
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_viewer.xml57
-rwxr-xr-xindra/newview/skins/default/xui/en/notifications.xml27
-rw-r--r--indra/newview/skins/default/xui/en/panel_facebook_account.xml (renamed from indra/newview/skins/default/xui/en/panel_social_account.xml)6
-rw-r--r--indra/newview/skins/default/xui/en/panel_facebook_friends.xml72
-rw-r--r--indra/newview/skins/default/xui/en/panel_facebook_photo.xml (renamed from indra/newview/skins/default/xui/en/panel_social_photo.xml)60
-rw-r--r--indra/newview/skins/default/xui/en/panel_facebook_place.xml (renamed from indra/newview/skins/default/xui/en/panel_social_place.xml)9
-rw-r--r--indra/newview/skins/default/xui/en/panel_facebook_status.xml (renamed from indra/newview/skins/default/xui/en/panel_social_status.xml)9
-rw-r--r--indra/newview/skins/default/xui/en/panel_flickr_account.xml75
-rw-r--r--indra/newview/skins/default/xui/en/panel_flickr_photo.xml245
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_place_profile.xml18
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_preferences_advanced.xml11
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_script_ed.xml30
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_snapshot_options.xml36
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_teleport_history_item.xml15
-rw-r--r--indra/newview/skins/default/xui/en/panel_twitter_account.xml75
-rw-r--r--indra/newview/skins/default/xui/en/panel_twitter_photo.xml193
-rw-r--r--indra/newview/skins/default/xui/en/script_editor.xml11
-rwxr-xr-xindra/newview/skins/default/xui/en/strings.xml57
-rwxr-xr-xindra/newview/skins/default/xui/es/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/fr/panel_preferences_privacy.xml4
-rwxr-xr-xindra/newview/skins/default/xui/it/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/ja/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pt/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/ru/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/tr/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/zh/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/tests/llhttpretrypolicy_test.cpp328
-rwxr-xr-xindra/newview/tests/llmediadataclient_test.cpp8
-rwxr-xr-xindra/newview/tests/llremoteparcelrequest_test.cpp16
-rwxr-xr-xindra/newview/tests/lltranslate_test.cpp12
-rwxr-xr-xindra/newview/viewer_manifest.py3
-rwxr-xr-xindra/test/llassetuploadqueue_tut.cpp4
-rwxr-xr-xindra/test/llblowfish_tut.cpp2
-rwxr-xr-xindra/test/llhttpnode_tut.cpp3
-rwxr-xr-xindra/test/llsd_new_tut.cpp55
-rwxr-xr-xindra/test/llsdmessagebuilder_tut.cpp2
-rwxr-xr-xindra/test/llsdtraits.h2
-rwxr-xr-xindra/test/lltemplatemessagebuilder_tut.cpp4
-rwxr-xr-xindra/test/lltut.h10
-rwxr-xr-xindra/test/message_tut.cpp3
-rwxr-xr-xindra/test/mock_http_client.cpp3
-rwxr-xr-xindra/test/mock_http_client.h23
-rwxr-xr-xindra/test/test.cpp62
-rwxr-xr-xindra/viewer_components/updater/llupdatechecker.cpp12
-rwxr-xr-xindra/viewer_components/updater/llupdatechecker.h7
567 files changed, 42081 insertions, 11953 deletions
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 1d78638143..6a0f7a214c 100755
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -174,12 +174,12 @@ if (LINUX)
endif (WORD_SIZE EQUAL 32)
add_definitions(-mfpmath=sse)
#add_definitions(-ftree-vectorize) # THIS CRASHES GCC 3.1-3.2
- if (NOT STANDALONE)
+ if (NOT USESYSTEMLIBS)
# this stops us requiring a really recent glibc at runtime
add_definitions(-fno-stack-protector)
# linking can be very memory-hungry, especially the final viewer link
set(CMAKE_CXX_LINK_FLAGS "-Wl,--no-keep-memory")
- endif (NOT STANDALONE)
+ endif (NOT USESYSTEMLIBS)
set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 ${CMAKE_CXX_FLAGS_RELEASE}")
@@ -226,14 +226,14 @@ if (LINUX OR DARWIN)
endif (LINUX OR DARWIN)
-if (STANDALONE)
- add_definitions(-DLL_STANDALONE=1)
+if (USESYSTEMLIBS)
+ add_definitions(-DLL_USESYSTEMLIBS=1)
if (LINUX AND ${ARCH} STREQUAL "i686")
add_definitions(-march=pentiumpro)
endif (LINUX AND ${ARCH} STREQUAL "i686")
-else (STANDALONE)
+else (USESYSTEMLIBS)
set(${ARCH}_linux_INCLUDES
ELFIO
atk-1.0
@@ -242,6 +242,6 @@ else (STANDALONE)
gtk-2.0
pango-1.0
)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
diff --git a/indra/cmake/APR.cmake b/indra/cmake/APR.cmake
index a87027f5f6..1a01671002 100755
--- a/indra/cmake/APR.cmake
+++ b/indra/cmake/APR.cmake
@@ -8,9 +8,9 @@ set(APR_FIND_REQUIRED ON)
set(APRUTIL_FIND_QUIETLY ON)
set(APRUTIL_FIND_REQUIRED ON)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindAPR)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(apr_suite)
if (WINDOWS)
if (LLCOMMON_LINK_SHARED)
@@ -52,4 +52,4 @@ else (STANDALONE)
list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES} uuid)
list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES} rt)
endif (LINUX)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/Audio.cmake b/indra/cmake/Audio.cmake
index d23bc2f9c6..876b7f82a8 100755
--- a/indra/cmake/Audio.cmake
+++ b/indra/cmake/Audio.cmake
@@ -1,13 +1,13 @@
# -*- cmake -*-
include(Prebuilt)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindPkgConfig)
pkg_check_modules(OGG REQUIRED ogg)
pkg_check_modules(VORBIS REQUIRED vorbis)
pkg_check_modules(VORBISENC REQUIRED vorbisenc)
pkg_check_modules(VORBISFILE REQUIRED vorbisfile)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(ogg-vorbis)
set(VORBIS_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
set(VORBISENC_INCLUDE_DIRS ${VORBIS_INCLUDE_DIRS})
@@ -32,7 +32,7 @@ else (STANDALONE)
set(VORBISENC_LIBRARIES vorbisenc)
set(VORBISFILE_LIBRARIES vorbisfile)
endif (WINDOWS)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
link_directories(
${VORBIS_LIBRARY_DIRS}
diff --git a/indra/cmake/BerkeleyDB.cmake b/indra/cmake/BerkeleyDB.cmake
index 57b53f46ff..5f6b644a15 100755
--- a/indra/cmake/BerkeleyDB.cmake
+++ b/indra/cmake/BerkeleyDB.cmake
@@ -3,9 +3,9 @@
set(DB_FIND_QUIETLY ON)
set(DB_FIND_REQUIRED ON)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindBerkeleyDB)
-else (STANDALONE)
+else (USESYSTEMLIBS)
if (LINUX)
# Need to add dependency pthread explicitely to support ld.gold.
use_prebuilt_binary(db)
@@ -14,4 +14,4 @@ else (STANDALONE)
set(DB_LIBRARIES db-4.2)
endif (LINUX)
set(DB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake
index cff762e1f0..50ac27d402 100755
--- a/indra/cmake/Boost.cmake
+++ b/indra/cmake/Boost.cmake
@@ -4,7 +4,7 @@ include(Prebuilt)
set(Boost_FIND_QUIETLY ON)
set(Boost_FIND_REQUIRED ON)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindBoost)
set(BOOST_CONTEXT_LIBRARY boost_context-mt)
@@ -14,7 +14,7 @@ if (STANDALONE)
set(BOOST_SIGNALS_LIBRARY boost_signals-mt)
set(BOOST_SYSTEM_LIBRARY boost_system-mt)
set(BOOST_THREAD_LIBRARY boost_thread-mt)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(boost)
set(Boost_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
set(BOOST_VERSION "1.52")
@@ -111,4 +111,4 @@ else (STANDALONE)
optimized boost_thread-mt
debug boost_thread-mt-d)
endif (WINDOWS)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/BuildVersion.cmake b/indra/cmake/BuildVersion.cmake
index e4b63dc7cb..e618a988b8 100755
--- a/indra/cmake/BuildVersion.cmake
+++ b/indra/cmake/BuildVersion.cmake
@@ -42,6 +42,11 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n
message(SEND_ERROR "Cannot get viewer version from '${VIEWER_VERSION_BASE_FILE}'")
endif ( EXISTS ${VIEWER_VERSION_BASE_FILE} )
+ if ("${VIEWER_VERSION_REVISION}" STREQUAL "")
+ message("Ultimate fallback, revision was blank or not set: will use 0")
+ set(VIEWER_VERSION_REVISION 0)
+ endif ("${VIEWER_VERSION_REVISION}" STREQUAL "")
+
set(VIEWER_CHANNEL_VERSION_DEFINES
"LL_VIEWER_CHANNEL=\"${VIEWER_CHANNEL}\""
"LL_VIEWER_VERSION_MAJOR=${VIEWER_VERSION_MAJOR}"
diff --git a/indra/cmake/CARes.cmake b/indra/cmake/CARes.cmake
index b0dac5b12f..baa55aa49d 100755
--- a/indra/cmake/CARes.cmake
+++ b/indra/cmake/CARes.cmake
@@ -5,9 +5,9 @@ include(Prebuilt)
set(CARES_FIND_QUIETLY ON)
set(CARES_FIND_REQUIRED ON)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindCARes)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(ares)
add_definitions("-DCARES_STATICLIB")
if (WINDOWS)
@@ -18,4 +18,4 @@ else (STANDALONE)
set(CARES_LIBRARIES cares)
endif (WINDOWS)
set(CARES_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/ares)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/CURL.cmake b/indra/cmake/CURL.cmake
index 9aba08e573..04afae594d 100755
--- a/indra/cmake/CURL.cmake
+++ b/indra/cmake/CURL.cmake
@@ -4,9 +4,9 @@ include(Prebuilt)
set(CURL_FIND_QUIETLY ON)
set(CURL_FIND_REQUIRED ON)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindCURL)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(curl)
if (WINDOWS)
set(CURL_LIBRARIES
@@ -16,4 +16,4 @@ else (STANDALONE)
set(CURL_LIBRARIES libcurl.a)
endif (WINDOWS)
set(CURL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index f98e88b697..4f1b6640c2 100755
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -374,9 +374,9 @@ copy_if_different(
)
set(third_party_targets ${third_party_targets} ${out_targets})
-if(NOT STANDALONE)
+if(NOT USESYSTEMLIBS)
add_custom_target(
stage_third_party_libs ALL
DEPENDS ${third_party_targets}
)
-endif(NOT STANDALONE)
+endif(NOT USESYSTEMLIBS)
diff --git a/indra/cmake/DBusGlib.cmake b/indra/cmake/DBusGlib.cmake
index 83c08d3350..d148a35a5b 100755
--- a/indra/cmake/DBusGlib.cmake
+++ b/indra/cmake/DBusGlib.cmake
@@ -1,7 +1,7 @@
# -*- cmake -*-
include(Prebuilt)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindPkgConfig)
pkg_check_modules(DBUSGLIB REQUIRED dbus-glib-1)
@@ -18,7 +18,7 @@ elseif (LINUX)
gobject-2.0
glib-2.0
)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
if (DBUSGLIB_FOUND)
set(DBUSGLIB ON CACHE BOOL "Build with dbus-glib message bus support.")
diff --git a/indra/cmake/EXPAT.cmake b/indra/cmake/EXPAT.cmake
index acb15dc623..c1155531ff 100755
--- a/indra/cmake/EXPAT.cmake
+++ b/indra/cmake/EXPAT.cmake
@@ -4,9 +4,9 @@ include(Prebuilt)
set(EXPAT_FIND_QUIETLY ON)
set(EXPAT_FIND_REQUIRED ON)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindEXPAT)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(expat)
if (WINDOWS)
set(EXPAT_LIBRARIES libexpatMT)
@@ -14,4 +14,4 @@ else (STANDALONE)
set(EXPAT_LIBRARIES expat)
endif (WINDOWS)
set(EXPAT_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/ExamplePlugin.cmake b/indra/cmake/ExamplePlugin.cmake
index 599787ad21..5d826c1f66 100755
--- a/indra/cmake/ExamplePlugin.cmake
+++ b/indra/cmake/ExamplePlugin.cmake
@@ -2,13 +2,13 @@
include(Linking)
include(Prebuilt)
-if (STANDALONE)
+if (USESYSTEMLIBS)
set(EXAMPLEPLUGIN OFF CACHE BOOL
"EXAMPLEPLUGIN support for the llplugin/llmedia test apps.")
-else (STANDALONE)
+else (USESYSTEMLIBS)
set(EXAMPLEPLUGIN ON CACHE BOOL
"EXAMPLEPLUGIN support for the llplugin/llmedia test apps.")
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
if (WINDOWS)
elseif (DARWIN)
diff --git a/indra/cmake/FMODEX.cmake b/indra/cmake/FMODEX.cmake
index 65bc1cabeb..720933d1b7 100644
--- a/indra/cmake/FMODEX.cmake
+++ b/indra/cmake/FMODEX.cmake
@@ -4,17 +4,17 @@
# When building using proprietary binaries though (i.e. having access to LL private servers),
# we always build with FMODEX.
# Open source devs should use the -DFMODEX:BOOL=ON then if they want to build with FMOD, whether
-# they are using STANDALONE or not.
+# they are using USESYSTEMLIBS or not.
if (INSTALL_PROPRIETARY)
set(FMODEX ON CACHE BOOL "Using FMOD Ex sound library.")
endif (INSTALL_PROPRIETARY)
if (FMODEX)
- if (STANDALONE)
+ if (USESYSTEMLIBS)
# In that case, we use the version of the library installed on the system
set(FMODEX_FIND_REQUIRED ON)
include(FindFMODEX)
- else (STANDALONE)
+ else (USESYSTEMLIBS)
if (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
# If the path have been specified in the arguments, use that
set(FMODEX_LIBRARIES ${FMODEX_LIBRARY})
@@ -41,6 +41,6 @@ if (FMODEX)
set(FMODEX_LIBRARIES ${FMODEX_LIBRARY})
set(FMODEX_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/fmodex)
endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
- endif (STANDALONE)
+ endif (USESYSTEMLIBS)
endif (FMODEX)
diff --git a/indra/cmake/FindJsonCpp.cmake b/indra/cmake/FindJsonCpp.cmake
index 0b056ada58..9398779cff 100755
--- a/indra/cmake/FindJsonCpp.cmake
+++ b/indra/cmake/FindJsonCpp.cmake
@@ -23,10 +23,10 @@ EXEC_PROGRAM(${CMAKE_CXX_COMPILER}
# Try to find a library that was compiled with the same compiler version as we currently use.
SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson_linux-gcc-${_gcc_COMPILER_VERSION}_libmt.so)
-IF (STANDALONE)
+IF (USESYSTEMLIBS)
# On standalone, assume that the system installed library was compiled with the used compiler.
SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson.so)
-ENDIF (STANDALONE)
+ENDIF (USESYSTEMLIBS)
FIND_LIBRARY(JSONCPP_LIBRARY
NAMES ${JSONCPP_NAMES}
PATHS /usr/lib /usr/local/lib
diff --git a/indra/cmake/FreeType.cmake b/indra/cmake/FreeType.cmake
index c9a90a9a8d..02c5b37f28 100755
--- a/indra/cmake/FreeType.cmake
+++ b/indra/cmake/FreeType.cmake
@@ -1,14 +1,14 @@
# -*- cmake -*-
include(Prebuilt)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindPkgConfig)
pkg_check_modules(FREETYPE REQUIRED freetype2)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(freetype)
set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
set(FREETYPE_LIBRARIES freetype)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
link_directories(${FREETYPE_LIBRARY_DIRS})
diff --git a/indra/cmake/GLEXT.cmake b/indra/cmake/GLEXT.cmake
index 0a3dd976b4..a749644202 100644
--- a/indra/cmake/GLEXT.cmake
+++ b/indra/cmake/GLEXT.cmake
@@ -1,8 +1,8 @@
# -*- cmake -*-
include(Prebuilt)
-if (NOT STANDALONE)
+if (NOT USESYSTEMLIBS)
use_prebuilt_binary(glext)
use_prebuilt_binary(glh_linear)
set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
-endif (NOT STANDALONE)
+endif (NOT USESYSTEMLIBS)
diff --git a/indra/cmake/GLH.cmake b/indra/cmake/GLH.cmake
index 911dbe4017..d5262f2efa 100755
--- a/indra/cmake/GLH.cmake
+++ b/indra/cmake/GLH.cmake
@@ -4,8 +4,8 @@ include(Prebuilt)
set(GLH_FIND_REQUIRED TRUE)
set(GLH_FIND_QUIETLY TRUE)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindGLH)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(glh_linear)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/GLOD.cmake b/indra/cmake/GLOD.cmake
index 6bdbaf621e..3683768af9 100755
--- a/indra/cmake/GLOD.cmake
+++ b/indra/cmake/GLOD.cmake
@@ -1,9 +1,9 @@
# -*- cmake -*-
include(Prebuilt)
-if (NOT STANDALONE)
+if (NOT USESYSTEMLIBS)
use_prebuilt_binary(GLOD)
-endif (NOT STANDALONE)
+endif (NOT USESYSTEMLIBS)
set(GLOD_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
set(GLOD_LIBRARIES GLOD)
diff --git a/indra/cmake/GStreamer010Plugin.cmake b/indra/cmake/GStreamer010Plugin.cmake
index d2d0699bcd..3fbc40ef8f 100755
--- a/indra/cmake/GStreamer010Plugin.cmake
+++ b/indra/cmake/GStreamer010Plugin.cmake
@@ -1,15 +1,15 @@
# -*- cmake -*-
include(Prebuilt)
-if (STANDALONE)
+if (USESYSTEMLIBS)
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)
+ # possible libxml2 should have its own .cmake file instead
+ use_prebuilt_binary(libxml2)
set(GSTREAMER010_FOUND ON FORCE BOOL)
set(GSTREAMER010_PLUGINS_BASE_FOUND ON FORCE BOOL)
set(GSTREAMER010_INCLUDE_DIRS
@@ -26,7 +26,7 @@ elseif (LINUX)
gthread-2.0
glib-2.0
)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
if (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND)
set(GSTREAMER010 ON CACHE BOOL "Build with GStreamer-0.10 streaming media support.")
diff --git a/indra/cmake/Glui.cmake b/indra/cmake/Glui.cmake
index f62a56856c..db353a91ec 100755
--- a/indra/cmake/Glui.cmake
+++ b/indra/cmake/Glui.cmake
@@ -2,14 +2,14 @@
include(Linking)
include(Prebuilt)
-if (STANDALONE)
+if (USESYSTEMLIBS)
set(GLUI OFF CACHE BOOL
"GLUI support for the llplugin/llmedia test apps.")
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(glui)
set(GLUI ON CACHE BOOL
"GLUI support for the llplugin/llmedia test apps.")
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
if (LINUX)
set(GLUI ON CACHE BOOL
diff --git a/indra/cmake/GoogleBreakpad.cmake b/indra/cmake/GoogleBreakpad.cmake
index 7f9ba4ea8e..829e1ac08a 100755
--- a/indra/cmake/GoogleBreakpad.cmake
+++ b/indra/cmake/GoogleBreakpad.cmake
@@ -1,10 +1,10 @@
# -*- cmake -*-
include(Prebuilt)
-if (STANDALONE)
+if (USESYSTEMLIBS)
set(BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED ON)
include(FindGoogleBreakpad)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(google_breakpad)
if (DARWIN)
set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler)
@@ -18,5 +18,5 @@ else (STANDALONE)
# yes, this does look dumb, no, it's not incorrect
#
set(BREAKPAD_INCLUDE_DIRECTORIES "${LIBS_PREBUILT_DIR}/include/google_breakpad" "${LIBS_PREBUILT_DIR}/include/google_breakpad/google_breakpad")
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake
index f3fd008e49..c1faeb9325 100755
--- a/indra/cmake/GooglePerfTools.cmake
+++ b/indra/cmake/GooglePerfTools.cmake
@@ -5,9 +5,9 @@ include(Prebuilt)
# set ON or OFF as desired.
set (USE_TCMALLOC OFF)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindGooglePerfTools)
-else (STANDALONE)
+else (USESYSTEMLIBS)
if (WINDOWS)
if (USE_TCMALLOC)
use_prebuilt_binary(gperftools)
@@ -34,7 +34,7 @@ else (STANDALONE)
${LIBS_PREBUILT_DIR}/include)
set(GOOGLE_PERFTOOLS_FOUND "YES")
endif (LINUX)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
if (GOOGLE_PERFTOOLS_FOUND)
# XXX Disable temporarily, until we have compilation issues on 64-bit
diff --git a/indra/cmake/Hunspell.cmake b/indra/cmake/Hunspell.cmake
index 0c9cf93316..ef74d95b2a 100755
--- a/indra/cmake/Hunspell.cmake
+++ b/indra/cmake/Hunspell.cmake
@@ -4,9 +4,9 @@ include(Prebuilt)
set(HUNSPELL_FIND_QUIETLY ON)
set(HUNSPELL_FIND_REQUIRED ON)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindHUNSPELL)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(libhunspell)
if (WINDOWS)
set(HUNSPELL_LIBRARY libhunspell)
@@ -19,4 +19,4 @@ else (STANDALONE)
endif()
set(HUNSPELL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/hunspell)
use_prebuilt_binary(dictionaries)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/JPEG.cmake b/indra/cmake/JPEG.cmake
index 4f99efd602..d6da22aecc 100755
--- a/indra/cmake/JPEG.cmake
+++ b/indra/cmake/JPEG.cmake
@@ -5,9 +5,9 @@ include(Linking)
set(JPEG_FIND_QUIETLY ON)
set(JPEG_FIND_REQUIRED ON)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindJPEG)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(jpeglib)
if (LINUX)
set(JPEG_LIBRARIES jpeg)
@@ -17,4 +17,4 @@ else (STANDALONE)
set(JPEG_LIBRARIES jpeglib)
endif (LINUX)
set(JPEG_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/JsonCpp.cmake b/indra/cmake/JsonCpp.cmake
index 7ad73e5683..0aab2d6634 100755
--- a/indra/cmake/JsonCpp.cmake
+++ b/indra/cmake/JsonCpp.cmake
@@ -5,9 +5,9 @@ include(Prebuilt)
set(JSONCPP_FIND_QUIETLY ON)
set(JSONCPP_FIND_REQUIRED ON)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindJsonCpp)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(jsoncpp)
if (WINDOWS)
set(JSONCPP_LIBRARIES
@@ -19,4 +19,4 @@ else (STANDALONE)
set(JSONCPP_LIBRARIES libjson_linux-gcc-4.1.3_libmt.a)
endif (WINDOWS)
set(JSONCPP_INCLUDE_DIR "${LIBS_PREBUILT_DIR}/include/jsoncpp" "${LIBS_PREBUILT_DIR}/include/json")
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 068aeea212..804624f5ec 100755..100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -202,9 +202,9 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})
SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
- if(STANDALONE)
+ if(USESYSTEMLIBS)
SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}")
- endif(STANDALONE)
+ endif(USESYSTEMLIBS)
# The following was copied to llcorehttp/CMakeLists.txt's texture_load target.
# Any changes made here should be replicated there.
@@ -275,10 +275,10 @@ MACRO(SET_TEST_PATH LISTVAR)
set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources ${SHARED_LIB_STAGING_DIR}/Release/Resources /usr/lib)
ELSE(WINDOWS)
# Linux uses a single staging directory anyway.
- IF (STANDALONE)
+ IF (USESYSTEMLIBS)
set(${LISTVAR} ${CMAKE_BINARY_DIR}/llcommon /usr/lib /usr/local/lib)
- ELSE (STANDALONE)
+ ELSE (USESYSTEMLIBS)
set(${LISTVAR} ${SHARED_LIB_STAGING_DIR} /usr/lib)
- ENDIF (STANDALONE)
+ ENDIF (USESYSTEMLIBS)
ENDIF(WINDOWS)
ENDMACRO(SET_TEST_PATH)
diff --git a/indra/cmake/LLPrimitive.cmake b/indra/cmake/LLPrimitive.cmake
index 0d87ff579a..67c2115237 100755
--- a/indra/cmake/LLPrimitive.cmake
+++ b/indra/cmake/LLPrimitive.cmake
@@ -6,21 +6,30 @@ include(Boost)
use_prebuilt_binary(colladadom)
use_prebuilt_binary(pcre)
-use_prebuilt_binary(libxml)
set(LLPRIMITIVE_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llprimitive
)
if (WINDOWS)
- set(LLPRIMITIVE_LIBRARIES
+ set(LLPRIMITIVE_LIBRARIES
debug llprimitive
optimized llprimitive
debug libcollada14dom22-d
optimized libcollada14dom22
${BOOST_SYSTEM_LIBRARIES}
)
+elseif (LINUX)
+ use_prebuilt_binary(libxml2)
+ set(LLPRIMITIVE_LIBRARIES
+ llprimitive
+ collada14dom
+ minizip
+ xml2
+ pcrecpp
+ pcre
+ )
else (WINDOWS)
- set(LLPRIMITIVE_LIBRARIES
+ set(LLPRIMITIVE_LIBRARIES
llprimitive
collada14dom
minizip
diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake
index ad732ef650..ba07a80f05 100755
--- a/indra/cmake/LLWindow.cmake
+++ b/indra/cmake/LLWindow.cmake
@@ -4,7 +4,7 @@ include(Variables)
include(GLEXT)
include(Prebuilt)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindSDL)
# This should be done by FindSDL. Sigh.
@@ -13,14 +13,14 @@ if (STANDALONE)
SDL_INCLUDE_DIR
SDL_LIBRARY
)
-else (STANDALONE)
+else (USESYSTEMLIBS)
if (LINUX)
use_prebuilt_binary(SDL)
set (SDL_FOUND TRUE)
set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux)
set (SDL_LIBRARY SDL directfb fusion direct)
endif (LINUX)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
if (SDL_FOUND)
include_directories(${SDL_INCLUDE_DIR})
diff --git a/indra/cmake/NDOF.cmake b/indra/cmake/NDOF.cmake
index be6fe415f2..e72845db53 100755
--- a/indra/cmake/NDOF.cmake
+++ b/indra/cmake/NDOF.cmake
@@ -4,10 +4,10 @@ include(Prebuilt)
set(NDOF ON CACHE BOOL "Use NDOF space navigator joystick library.")
if (NDOF)
- if (STANDALONE)
+ if (USESYSTEMLIBS)
set(NDOF_FIND_REQUIRED ON)
include(FindNDOF)
- else (STANDALONE)
+ else (USESYSTEMLIBS)
use_prebuilt_binary(ndofdev)
if (WINDOWS)
@@ -18,7 +18,7 @@ if (NDOF)
set(NDOF_INCLUDE_DIR ${ARCH_PREBUILT_DIRS}/include/ndofdev)
set(NDOF_FOUND 1)
- endif (STANDALONE)
+ endif (USESYSTEMLIBS)
endif (NDOF)
if (NDOF_FOUND)
diff --git a/indra/cmake/OPENAL.cmake b/indra/cmake/OPENAL.cmake
index a3e1fb924e..c084d68de7 100755
--- a/indra/cmake/OPENAL.cmake
+++ b/indra/cmake/OPENAL.cmake
@@ -10,14 +10,14 @@ endif (LINUX)
if (OPENAL)
set(OPENAL_LIB_INCLUDE_DIRS "${LIBS_PREBUILT_DIR}/include/AL")
- if (STANDALONE)
+ if (USESYSTEMLIBS)
include(FindPkgConfig)
include(FindOpenAL)
pkg_check_modules(OPENAL_LIB REQUIRED openal)
pkg_check_modules(FREEALUT_LIB REQUIRED freealut)
- else (STANDALONE)
+ else (USESYSTEMLIBS)
use_prebuilt_binary(openal_soft)
- endif (STANDALONE)
+ endif (USESYSTEMLIBS)
if(WINDOWS)
set(OPENAL_LIBRARIES
OpenAL32
diff --git a/indra/cmake/OpenJPEG.cmake b/indra/cmake/OpenJPEG.cmake
index fcc82c2f49..bf0bde2ba7 100755
--- a/indra/cmake/OpenJPEG.cmake
+++ b/indra/cmake/OpenJPEG.cmake
@@ -4,9 +4,9 @@ include(Prebuilt)
set(OPENJPEG_FIND_QUIETLY ON)
set(OPENJPEG_FIND_REQUIRED ON)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindOpenJPEG)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(openjpeg)
if(WINDOWS)
@@ -19,4 +19,4 @@ else (STANDALONE)
endif(WINDOWS)
set(OPENJPEG_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/openjpeg)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/OpenSSL.cmake b/indra/cmake/OpenSSL.cmake
index 2704912eb5..5b469f74f9 100755
--- a/indra/cmake/OpenSSL.cmake
+++ b/indra/cmake/OpenSSL.cmake
@@ -4,9 +4,9 @@ include(Prebuilt)
set(OpenSSL_FIND_QUIETLY ON)
set(OpenSSL_FIND_REQUIRED ON)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindOpenSSL)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(openSSL)
if (WINDOWS)
set(OPENSSL_LIBRARIES ssleay32 libeay32)
@@ -14,7 +14,7 @@ else (STANDALONE)
set(OPENSSL_LIBRARIES ssl crypto)
endif (WINDOWS)
set(OPENSSL_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
if (LINUX)
set(CRYPTO_LIBRARIES crypto)
diff --git a/indra/cmake/PNG.cmake b/indra/cmake/PNG.cmake
index 913c575672..173d59391e 100755
--- a/indra/cmake/PNG.cmake
+++ b/indra/cmake/PNG.cmake
@@ -4,9 +4,9 @@ include(Prebuilt)
set(PNG_FIND_QUIETLY ON)
set(PNG_FIND_REQUIRED ON)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindPNG)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(libpng)
if (WINDOWS)
set(PNG_LIBRARIES libpng15)
@@ -18,4 +18,4 @@ else (STANDALONE)
set(PNG_LIBRARIES png15)
set(PNG_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/libpng15)
endif()
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/Prebuilt.cmake b/indra/cmake/Prebuilt.cmake
index ac0cbde253..e548805148 100755
--- a/indra/cmake/Prebuilt.cmake
+++ b/indra/cmake/Prebuilt.cmake
@@ -17,11 +17,11 @@ endif(INSTALL_PROPRIETARY)
# of previous attempts is serialized in the file
# ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
macro (use_prebuilt_binary _binary)
- if (NOT DEFINED STANDALONE_${_binary})
- set(STANDALONE_${_binary} ${STANDALONE})
- endif (NOT DEFINED STANDALONE_${_binary})
+ if (NOT DEFINED USESYSTEMLIBS_${_binary})
+ set(USESYSTEMLIBS_${_binary} ${USESYSTEMLIBS})
+ endif (NOT DEFINED USESYSTEMLIBS_${_binary})
- if (NOT STANDALONE_${_binary})
+ if (NOT USESYSTEMLIBS_${_binary})
if("${${_binary}_installed}" STREQUAL "" AND EXISTS "${CMAKE_BINARY_DIR}/temp/${_binary}_installed")
file(READ ${CMAKE_BINARY_DIR}/temp/${_binary}_installed "${_binary}_installed")
if(DEBUG_PREBUILT)
@@ -52,7 +52,7 @@ macro (use_prebuilt_binary _binary)
"Failed to download or unpack prebuilt '${_binary}'."
" Process returned ${${_binary}_installed}.")
endif (NOT ${_binary}_installed EQUAL 0)
- endif (NOT STANDALONE_${_binary})
+ endif (NOT USESYSTEMLIBS_${_binary})
endmacro (use_prebuilt_binary _binary)
endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
diff --git a/indra/cmake/PulseAudio.cmake b/indra/cmake/PulseAudio.cmake
index 360a971058..cce27f1bdd 100755
--- a/indra/cmake/PulseAudio.cmake
+++ b/indra/cmake/PulseAudio.cmake
@@ -4,7 +4,7 @@ include(Prebuilt)
set(PULSEAUDIO OFF CACHE BOOL "Build with PulseAudio support, if available.")
if (PULSEAUDIO)
- if (STANDALONE)
+ if (USESYSTEMLIBS)
include(FindPkgConfig)
pkg_check_modules(PULSEAUDIO libpulse)
@@ -20,7 +20,7 @@ if (PULSEAUDIO)
set(PULSEAUDIO_LIBRARIES
# none needed!
)
- endif (STANDALONE)
+ endif (USESYSTEMLIBS)
endif (PULSEAUDIO)
if (PULSEAUDIO_FOUND)
diff --git a/indra/cmake/Tut.cmake b/indra/cmake/Tut.cmake
index 7488e9dcb0..e11a3c3314 100755
--- a/indra/cmake/Tut.cmake
+++ b/indra/cmake/Tut.cmake
@@ -1,6 +1,6 @@
# -*- cmake -*-
include(Prebuilt)
-if (NOT STANDALONE)
+if (NOT USESYSTEMLIBS)
use_prebuilt_binary(tut)
-endif(NOT STANDALONE)
+endif(NOT USESYSTEMLIBS)
diff --git a/indra/cmake/UI.cmake b/indra/cmake/UI.cmake
index d0fd4df03a..58acdc22bd 100755
--- a/indra/cmake/UI.cmake
+++ b/indra/cmake/UI.cmake
@@ -2,7 +2,7 @@
include(Prebuilt)
include(FreeType)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindPkgConfig)
if (LINUX)
@@ -31,7 +31,7 @@ if (STANDALONE)
list(APPEND UI_LIBRARIES ${${pkg}_LIBRARIES})
add_definitions(${${pkg}_CFLAGS_OTHERS})
endforeach(pkg)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(gtk-atk-pango-glib)
if (LINUX)
set(UI_LIBRARIES
@@ -59,7 +59,7 @@ else (STANDALONE)
foreach(include ${${LL_ARCH}_INCLUDES})
include_directories(${LIBS_PREBUILT_DIR}/include/${include})
endforeach(include)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
if (LINUX)
add_definitions(-DLL_GTK=1 -DLL_X11=1)
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index 22d0a7f0fe..963b1bd386 100755
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -183,7 +183,7 @@ if (XCODE_VERSION GREATER 4.2)
endif (XCODE_VERSION GREATER 4.2)
set(VERSION_BUILD "0" CACHE STRING "Revision number passed in from the outside")
-set(STANDALONE OFF CACHE BOOL "Do not use Linden-supplied prebuilt libraries.")
+set(USESYSTEMLIBS OFF CACHE BOOL "Use libraries from your system rather than Linden-supplied prebuilt libraries.")
set(UNATTENDED OFF CACHE BOOL "Should be set to ON for building with VC Express editions.")
set(USE_PRECOMPILED_HEADERS ON CACHE BOOL "Enable use of precompiled header directives where supported.")
diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake
index 5b00c989a4..d4be24799f 100755
--- a/indra/cmake/ViewerMiscLibs.cmake
+++ b/indra/cmake/ViewerMiscLibs.cmake
@@ -1,10 +1,10 @@
# -*- cmake -*-
include(Prebuilt)
-if (NOT STANDALONE)
+if (NOT USESYSTEMLIBS)
use_prebuilt_binary(libhunspell)
use_prebuilt_binary(libuuid)
use_prebuilt_binary(slvoice)
use_prebuilt_binary(fontconfig)
-endif(NOT STANDALONE)
+endif(NOT USESYSTEMLIBS)
diff --git a/indra/cmake/WebKitLibPlugin.cmake b/indra/cmake/WebKitLibPlugin.cmake
index d9df78bfc8..76f2c148db 100755
--- a/indra/cmake/WebKitLibPlugin.cmake
+++ b/indra/cmake/WebKitLibPlugin.cmake
@@ -2,7 +2,7 @@
include(Linking)
include(Prebuilt)
-if (STANDALONE)
+if (USESYSTEMLIBS)
# 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 QtWebKit REQUIRED)
include(${QT_USE_FILE})
@@ -28,11 +28,11 @@ if (STANDALONE)
list(APPEND QT_PLUGIN_LIBRARIES jpeg)
set(WEBKITLIBPLUGIN OFF CACHE BOOL
"WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(llqtwebkit)
set(WEBKITLIBPLUGIN ON CACHE BOOL
"WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
if (WINDOWS)
set(WEBKIT_PLUGIN_LIBRARIES
diff --git a/indra/cmake/XmlRpcEpi.cmake b/indra/cmake/XmlRpcEpi.cmake
index 5bd4848245..3a0caa0a06 100755
--- a/indra/cmake/XmlRpcEpi.cmake
+++ b/indra/cmake/XmlRpcEpi.cmake
@@ -4,9 +4,9 @@ include(Prebuilt)
set(XMLRPCEPI_FIND_QUIETLY ON)
set(XMLRPCEPI_FIND_REQUIRED ON)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindXmlRpcEpi)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(xmlrpc-epi)
if (WINDOWS)
set(XMLRPCEPI_LIBRARIES
@@ -17,4 +17,4 @@ else (STANDALONE)
set(XMLRPCEPI_LIBRARIES xmlrpc-epi)
endif (WINDOWS)
set(XMLRPCEPI_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/cmake/ZLIB.cmake b/indra/cmake/ZLIB.cmake
index 48e5130ad5..b99a8644c9 100755
--- a/indra/cmake/ZLIB.cmake
+++ b/indra/cmake/ZLIB.cmake
@@ -5,9 +5,9 @@ set(ZLIB_FIND_REQUIRED ON)
include(Prebuilt)
-if (STANDALONE)
+if (USESYSTEMLIBS)
include(FindZLIB)
-else (STANDALONE)
+else (USESYSTEMLIBS)
use_prebuilt_binary(zlib)
if (WINDOWS)
set(ZLIB_LIBRARIES
@@ -19,4 +19,4 @@ else (STANDALONE)
if (WINDOWS OR LINUX)
set(ZLIB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/zlib)
endif (WINDOWS OR LINUX)
-endif (STANDALONE)
+endif (USESYSTEMLIBS)
diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt
index beeb570496..c63ad74682 100755
--- a/indra/edit-me-to-trigger-new-build.txt
+++ b/indra/edit-me-to-trigger-new-build.txt
@@ -1,7 +1 @@
-Wed Nov 7 00:25:19 UTC 2012
-
-
-
-
-
-
+2014-02-25 10:34
diff --git a/indra/integration_tests/llimage_libtest/CMakeLists.txt b/indra/integration_tests/llimage_libtest/CMakeLists.txt
index 36a7d38bb7..8a83ac498f 100755
--- a/indra/integration_tests/llimage_libtest/CMakeLists.txt
+++ b/indra/integration_tests/llimage_libtest/CMakeLists.txt
@@ -7,6 +7,7 @@ project (llimage_libtest)
include(00-Common)
include(LLCommon)
include(LLImage)
+include(LLMath)
include(LLImageJ2COJ)
include(LLKDU)
include(LLVFS)
@@ -15,6 +16,7 @@ include_directories(
${LLCOMMON_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS}
${LLIMAGE_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
)
include_directories(SYSTEM
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
@@ -64,6 +66,7 @@ endif (DARWIN)
target_link_libraries(llimage_libtest
${LLCOMMON_LIBRARIES}
${LLVFS_LIBRARIES}
+ ${LLMATH_LIBRARIES}
${LLIMAGE_LIBRARIES}
${LLKDU_LIBRARIES}
${KDU_LIBRARY}
diff --git a/indra/integration_tests/llimage_libtest/filters/1970colorize.xml b/indra/integration_tests/llimage_libtest/filters/1970colorize.xml
new file mode 100644
index 0000000000..0dab2489a0
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/1970colorize.xml
@@ -0,0 +1,41 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.1</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>contrast</string>
+ <real>0.8</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>0.5</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ </array>
+ <array>
+ <string>blend</string>
+ <real>10.0</real>
+ <real>0.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>0.1</real>
+ <real>0.1</real>
+ <real>0.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/autocontrast.xml b/indra/integration_tests/llimage_libtest/filters/autocontrast.xml
new file mode 100755
index 0000000000..ec3d7561bd
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/autocontrast.xml
@@ -0,0 +1,11 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.01</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/badtrip.xml b/indra/integration_tests/llimage_libtest/filters/badtrip.xml
new file mode 100755
index 0000000000..14ee0baff3
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/badtrip.xml
@@ -0,0 +1,36 @@
+<llsd>
+ <array>
+ <array>
+ <string>grayscale</string>
+ </array>
+ <array>
+ <string>linearize</string>
+ <real>0.1</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>posterize</string>
+ <real>10.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>gradient</string>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>0.15</real>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml b/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml
new file mode 100644
index 0000000000..2474a1b953
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml
@@ -0,0 +1,25 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>uniform</string>
+ <string>add</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>gamma</string>
+ <real>0.25</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/blur.xml b/indra/integration_tests/llimage_libtest/filters/blur.xml
new file mode 100644
index 0000000000..addd056855
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/blur.xml
@@ -0,0 +1,7 @@
+<llsd>
+ <array>
+ <array>
+ <string>blur</string>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/brighten.xml b/indra/integration_tests/llimage_libtest/filters/brighten.xml
new file mode 100755
index 0000000000..9b4232229f
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/brighten.xml
@@ -0,0 +1,11 @@
+<llsd>
+ <array>
+ <array>
+ <string>brighten</string>
+ <real>0.5</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/colorize.xml b/indra/integration_tests/llimage_libtest/filters/colorize.xml
new file mode 100644
index 0000000000..72e58b0ffe
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/colorize.xml
@@ -0,0 +1,24 @@
+<llsd>
+ <array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>blend</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>10.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>0.5</real>
+ <real>0.5</real>
+ <real>0.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/colortransform.xml b/indra/integration_tests/llimage_libtest/filters/colortransform.xml
new file mode 100644
index 0000000000..de4bebcce2
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/colortransform.xml
@@ -0,0 +1,16 @@
+<llsd>
+ <array>
+ <array>
+ <string>colortransform</string>
+ <real>0.2125</real>
+ <real>0.7154</real>
+ <real>0.0721</real>
+ <real>0.2125</real>
+ <real>0.7154</real>
+ <real>0.0721</real>
+ <real>0.2125</real>
+ <real>0.7154</real>
+ <real>0.0721</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/contrast.xml b/indra/integration_tests/llimage_libtest/filters/contrast.xml
new file mode 100644
index 0000000000..00746b8a9e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/contrast.xml
@@ -0,0 +1,11 @@
+<llsd>
+ <array>
+ <array>
+ <string>contrast</string>
+ <real>1.5</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/convolve.xml b/indra/integration_tests/llimage_libtest/filters/convolve.xml
new file mode 100644
index 0000000000..6e65b5f88a
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/convolve.xml
@@ -0,0 +1,18 @@
+<llsd>
+ <array>
+ <array>
+ <string>convolve</string>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>4.0</real>
+ <real>1.0</real>
+ <real>4.0</real>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>4.0</real>
+ <real>1.0</real>
+ <real>4.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/darken.xml b/indra/integration_tests/llimage_libtest/filters/darken.xml
new file mode 100755
index 0000000000..5cec3589b6
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/darken.xml
@@ -0,0 +1,11 @@
+<llsd>
+ <array>
+ <array>
+ <string>darken</string>
+ <real>0.5</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml b/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml
new file mode 100644
index 0000000000..0e2e0ad68c
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml
@@ -0,0 +1,47 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>add</string>
+ <real>0.0</real>
+ <real>0.4</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>2.0</real>
+ </array>
+ <array>
+ <string>contrast</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>add</string>
+ <real>-0.8</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>2.0</real>
+ </array>
+ <array>
+ <string>contrast</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/edges.xml b/indra/integration_tests/llimage_libtest/filters/edges.xml
new file mode 100644
index 0000000000..a66b81d01e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/edges.xml
@@ -0,0 +1,24 @@
+<llsd>
+ <array>
+ <array>
+ <string>gradient</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>linearize</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>contrast</string>
+ <real>2.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/focus.xml b/indra/integration_tests/llimage_libtest/filters/focus.xml
new file mode 100644
index 0000000000..d8525fea62
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/focus.xml
@@ -0,0 +1,39 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>blend</string>
+ <real>0.0</real>
+ <real>0.4</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>0.5</real>
+ <real>2.0</real>
+ </array>
+ <array>
+ <string>sharpen</string>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>blend</string>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>0.5</real>
+ <real>2.0</real>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/gamma.xml b/indra/integration_tests/llimage_libtest/filters/gamma.xml
new file mode 100644
index 0000000000..19af09b046
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/gamma.xml
@@ -0,0 +1,11 @@
+<llsd>
+ <array>
+ <array>
+ <string>gamma</string>
+ <real>1.7</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/grayscale.xml b/indra/integration_tests/llimage_libtest/filters/grayscale.xml
new file mode 100644
index 0000000000..984312c4fd
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/grayscale.xml
@@ -0,0 +1,14 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>grayscale</string>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/heatwave.xml b/indra/integration_tests/llimage_libtest/filters/heatwave.xml
new file mode 100644
index 0000000000..a99f41c833
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/heatwave.xml
@@ -0,0 +1,38 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.1</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>contrast</string>
+ <real>0.8</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>fade</string>
+ <real>0.5</real>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>4.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>0.4</real>
+ <real>0.0</real>
+ <real>0.2</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml b/indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml
new file mode 100644
index 0000000000..21cab70e54
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml
@@ -0,0 +1,20 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>grayscale</string>
+ </array>
+ <array>
+ <string>screen</string>
+ <string>line</string>
+ <real>0.015</real>
+ <real>0.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/julesverne.xml b/indra/integration_tests/llimage_libtest/filters/julesverne.xml
new file mode 100644
index 0000000000..981e221da9
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/julesverne.xml
@@ -0,0 +1,20 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.1</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>grayscale</string>
+ </array>
+ <array>
+ <string>screen</string>
+ <string>line</string>
+ <real>0.02</real>
+ <real>0.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/lensflare.xml b/indra/integration_tests/llimage_libtest/filters/lensflare.xml
new file mode 100644
index 0000000000..0b5af9c82b
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/lensflare.xml
@@ -0,0 +1,131 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.01</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>gradient</string>
+ <string>add</string>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>-1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>-1.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>0.1</real>
+ <real>0.1</real>
+ <real>0.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>add</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>-1.0</real>
+ <real>1.0</real>
+ <real>1.5</real>
+ <real>5.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>0.6</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>add</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>-1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>5.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>0.6</real>
+ <real>0.6</real>
+ <real>0.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>add</string>
+ <real>0.0</real>
+ <real>0.5</real>
+ <real>0.5</real>
+ <real>-0.5</real>
+ <real>0.10</real>
+ <real>20.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>0.7</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>add</string>
+ <real>0.0</real>
+ <real>0.5</real>
+ <real>0.6</real>
+ <real>-0.6</real>
+ <real>0.05</real>
+ <real>20.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>0.7</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>add</string>
+ <real>0.0</real>
+ <real>0.5</real>
+ <real>0.4</real>
+ <real>-0.4</real>
+ <real>0.025</real>
+ <real>20.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>0.7</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/lightleak.xml b/indra/integration_tests/llimage_libtest/filters/lightleak.xml
new file mode 100755
index 0000000000..6fe496506e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/lightleak.xml
@@ -0,0 +1,78 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.01</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>brighten</string>
+ <real>0.1</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>gradient</string>
+ <string>add</string>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>-1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>-1.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>0.1</real>
+ <real>0.1</real>
+ <real>0.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>add</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>-1.0</real>
+ <real>1.0</real>
+ <real>1.5</real>
+ <real>5.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>0.8</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>add</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>-1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>5.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>0.8</real>
+ <real>0.8</real>
+ <real>0.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/linearize.xml b/indra/integration_tests/llimage_libtest/filters/linearize.xml
new file mode 100755
index 0000000000..23d0290e07
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/linearize.xml
@@ -0,0 +1,11 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.1</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/miniature.xml b/indra/integration_tests/llimage_libtest/filters/miniature.xml
new file mode 100755
index 0000000000..9aa8a87c6f
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/miniature.xml
@@ -0,0 +1,118 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.02</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>contrast</string>
+ <real>1.02</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>saturate</string>
+ <real>1.2</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>blend</string>
+ <real>0.0</real>
+ <real>0.25</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>0.25</real>
+ <real>2.0</real>
+ </array>
+ <array>
+ <string>sharpen</string>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>gradient</string>
+ <string>blend</string>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>-1.0</real>
+ <real>0.0</real>
+ <real>-0.25</real>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>gradient</string>
+ <string>blend</string>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.25</real>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ </array>
+</llsd> \ No newline at end of file
diff --git a/indra/integration_tests/llimage_libtest/filters/newsscreen.xml b/indra/integration_tests/llimage_libtest/filters/newsscreen.xml
new file mode 100755
index 0000000000..50ed27c6db
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/newsscreen.xml
@@ -0,0 +1,20 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>grayscale</string>
+ </array>
+ <array>
+ <string>screen</string>
+ <string>2Dsine</string>
+ <real>0.015</real>
+ <real>0.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/overcast.xml b/indra/integration_tests/llimage_libtest/filters/overcast.xml
new file mode 100644
index 0000000000..dce5ab3e9e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/overcast.xml
@@ -0,0 +1,24 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.1</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.3</real>
+ <real>0.0</real>
+ </array>
+ <array>
+ <string>saturate</string>
+ <real>0.35</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/pixelate.xml b/indra/integration_tests/llimage_libtest/filters/pixelate.xml
new file mode 100755
index 0000000000..f643419aa0
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/pixelate.xml
@@ -0,0 +1,35 @@
+<llsd>
+ <array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>darken</string>
+ <real>0.1</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>contrast</string>
+ <real>0.9</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>linearize</string>
+ <real>0.01</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>posterize</string>
+ <real>4.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd> \ No newline at end of file
diff --git a/indra/integration_tests/llimage_libtest/filters/posterize.xml b/indra/integration_tests/llimage_libtest/filters/posterize.xml
new file mode 100755
index 0000000000..4d03df3c66
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/posterize.xml
@@ -0,0 +1,11 @@
+<llsd>
+ <array>
+ <array>
+ <string>posterize</string>
+ <real>10.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml b/indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml
new file mode 100644
index 0000000000..e25029720f
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml
@@ -0,0 +1,8 @@
+<llsd>
+ <array>
+ <array>
+ <string>rotate</string>
+ <real>180.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/saturate.xml b/indra/integration_tests/llimage_libtest/filters/saturate.xml
new file mode 100644
index 0000000000..b77f07a037
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/saturate.xml
@@ -0,0 +1,8 @@
+<llsd>
+ <array>
+ <array>
+ <string>saturate</string>
+ <real>3.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/sepia.xml b/indra/integration_tests/llimage_libtest/filters/sepia.xml
new file mode 100644
index 0000000000..0304ead015
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/sepia.xml
@@ -0,0 +1,14 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>sepia</string>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/sharpen.xml b/indra/integration_tests/llimage_libtest/filters/sharpen.xml
new file mode 100644
index 0000000000..6d3f9ae1a2
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/sharpen.xml
@@ -0,0 +1,7 @@
+<llsd>
+ <array>
+ <array>
+ <string>sharpen</string>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/slantedscreen.xml b/indra/integration_tests/llimage_libtest/filters/slantedscreen.xml
new file mode 100644
index 0000000000..6cd1a96185
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/slantedscreen.xml
@@ -0,0 +1,20 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>grayscale</string>
+ </array>
+ <array>
+ <string>screen</string>
+ <string>line</string>
+ <real>0.015</real>
+ <real>45.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/spotlight.xml b/indra/integration_tests/llimage_libtest/filters/spotlight.xml
new file mode 100644
index 0000000000..203130bdee
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/spotlight.xml
@@ -0,0 +1,45 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.1</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>contrast</string>
+ <real>0.8</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>saturate</string>
+ <real>1.5</real>
+ </array>
+ <array>
+ <string>fade</string>
+ <real>1.0</real>
+ <real>0.25</real>
+ </array>
+ <array>
+ <string>saturate</string>
+ <real>0.8</real>
+ </array>
+ <array>
+ <string>contrast</string>
+ <real>1.1</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>brighten</string>
+ <real>30</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/stencilgradient.xml b/indra/integration_tests/llimage_libtest/filters/stencilgradient.xml
new file mode 100644
index 0000000000..d22809a9bf
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/stencilgradient.xml
@@ -0,0 +1,24 @@
+<llsd>
+ <array>
+ <array>
+ <string>stencil</string>
+ <string>gradient</string>
+ <string>blend</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>-1.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml b/indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml
new file mode 100644
index 0000000000..3ce428503d
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml
@@ -0,0 +1,22 @@
+<llsd>
+ <array>
+ <array>
+ <string>stencil</string>
+ <string>scanlines</string>
+ <string>blend</string>
+ <real>0.0</real>
+ <real>0.5</real>
+ <real>0.1</real>
+ <real>45.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/stenciluniform.xml b/indra/integration_tests/llimage_libtest/filters/stenciluniform.xml
new file mode 100644
index 0000000000..7d72f0ed93
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/stenciluniform.xml
@@ -0,0 +1,20 @@
+<llsd>
+ <array>
+ <array>
+ <string>stencil</string>
+ <string>uniform</string>
+ <string>blend</string>
+ <real>0.0</real>
+ <real>0.5</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/stencilvignette.xml b/indra/integration_tests/llimage_libtest/filters/stencilvignette.xml
new file mode 100644
index 0000000000..d30637fef5
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/stencilvignette.xml
@@ -0,0 +1,24 @@
+<llsd>
+ <array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>blend</string>
+ <real>0.0</real>
+ <real>0.5</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>10.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/thematrix.xml b/indra/integration_tests/llimage_libtest/filters/thematrix.xml
new file mode 100755
index 0000000000..af9a5eced8
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/thematrix.xml
@@ -0,0 +1,42 @@
+<llsd>
+ <array>
+ <array>
+ <string>grayscale</string>
+ </array>
+ <array>
+ <string>linearize</string>
+ <real>0.1</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>posterize</string>
+ <real>50.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>gradient</string>
+ </array>
+ <array>
+ <string>screen</string>
+ <string>line</string>
+ <real>0.025</real>
+ <real>90.0</real>
+ </array>
+ <array>
+ <string>colorize</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.1</real>
+ <real>0.2</real>
+ <real>0.2</real>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ </array>
+</llsd> \ No newline at end of file
diff --git a/indra/integration_tests/llimage_libtest/filters/toycamera.xml b/indra/integration_tests/llimage_libtest/filters/toycamera.xml
new file mode 100755
index 0000000000..4e76f6b2fb
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/toycamera.xml
@@ -0,0 +1,46 @@
+<llsd>
+ <array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>fade</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>1.2</real>
+ <real>3.0</real>
+ </array>
+ <array>
+ <string>linearize</string>
+ <real>0.05</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>grayscale</string>
+ </array>
+ <array>
+ <string>contrast</string>
+ <real>1.1</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>vignette</string>
+ <string>blend</string>
+ <real>1.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>0.0</real>
+ <real>0.5</real>
+ <real>2.0</real>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ </array>
+</llsd> \ No newline at end of file
diff --git a/indra/integration_tests/llimage_libtest/filters/verticalscreen.xml b/indra/integration_tests/llimage_libtest/filters/verticalscreen.xml
new file mode 100644
index 0000000000..0768d1d7e1
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/verticalscreen.xml
@@ -0,0 +1,20 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>grayscale</string>
+ </array>
+ <array>
+ <string>screen</string>
+ <string>line</string>
+ <real>0.015</real>
+ <real>90.0</real>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/filters/video.xml b/indra/integration_tests/llimage_libtest/filters/video.xml
new file mode 100755
index 0000000000..fe17f3950a
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/video.xml
@@ -0,0 +1,44 @@
+<llsd>
+ <array>
+ <array>
+ <string>linearize</string>
+ <real>0.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>darken</string>
+ <real>0.15</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>stencil</string>
+ <string>uniform</string>
+ <string>add</string>
+ <real>0.0</real>
+ <real>0.5</real>
+ </array>
+ <array>
+ <string>screen</string>
+ <string>line</string>
+ <real>0.02</real>
+ <real>0.0</real>
+ </array>
+ <array>
+ <string>gamma</string>
+ <real>0.25</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ <real>1.0</real>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ <array>
+ <string>blur</string>
+ </array>
+ </array>
+</llsd>
diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 034c816742..3d27b4a5b5 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -32,6 +32,7 @@
// Linden library includes
#include "llimage.h"
+#include "llimagefilter.h"
#include "llimagejpeg.h"
#include "llimagepng.h"
#include "llimagebmp.h"
@@ -39,6 +40,8 @@
#include "llimagej2c.h"
#include "lldir.h"
#include "lldiriterator.h"
+#include "v4coloru.h"
+#include "llsdserialize.h"
// system libraries
#include <iostream>
@@ -83,6 +86,8 @@ static const char USAGE[] = "\n"
" -rev, --reversible\n"
" Set the compression to be lossless (reversible in j2c parlance).\n"
" Only valid for output j2c images.\n"
+" -f, --filter <file>\n"
+" Apply the filter <file> to the input images.\n"
" -log, --logmetrics <metric>\n"
" Log performance data for <metric>. Results in <metric>.slp\n"
" Note: so far, only ImageCompressionTester has been tested.\n"
@@ -99,7 +104,7 @@ static bool sAllDone = false;
// Create an empty formatted image instance of the correct type from the filename
LLPointer<LLImageFormatted> create_image(const std::string &filename)
{
- std::string exten = gDirUtilp->getExtension(filename);
+ std::string exten = gDirUtilp->getExtension(filename);
LLPointer<LLImageFormatted> image = LLImageFormatted::createFromExtension(exten);
return image;
}
@@ -350,6 +355,7 @@ int main(int argc, char** argv)
int blocks_size = -1;
int levels = 0;
bool reversible = false;
+ std::string filter_name = "";
// Init whatever is necessary
ll_init_apr();
@@ -523,7 +529,26 @@ int main(int argc, char** argv)
break;
}
}
- else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a"))
+ else if (!strcmp(argv[arg], "--filter") || !strcmp(argv[arg], "-f"))
+ {
+ // '--filter' needs to be specified with a named filter argument
+ if ((arg + 1) < argc)
+ {
+ filter_name = argv[arg+1];
+ }
+ if (((arg + 1) >= argc) || (filter_name[0] == '-'))
+ {
+ // We don't have an argument left in the arg list or the next argument is another option
+ std::cout << "No --filter argument given, no filter will be applied" << std::endl;
+ }
+ else
+ {
+ arg += 1; // Skip that arg now we know it's a valid test name
+ if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list
+ break;
+ }
+ }
+ else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a"))
{
analyze_performance = true;
}
@@ -553,7 +578,10 @@ int main(int argc, char** argv)
fast_timer_log_thread = new LogThread(LLFastTimer::sLogName);
fast_timer_log_thread->start();
}
-
+
+ // Load the filter once and for all
+ LLImageFilter filter(filter_name);
+
// Perform action on each input file
std::list<std::string>::iterator in_file = input_filenames.begin();
std::list<std::string>::iterator out_file = output_filenames.begin();
@@ -568,7 +596,10 @@ int main(int argc, char** argv)
std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl;
continue;
}
-
+
+ // Apply the filter
+ filter.executeFilter(raw_image);
+
// Save file
if (out_file != out_end)
{
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index 41fcb6ce4b..6fdf9e2e07 100644..100755
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -498,29 +498,9 @@ void LLAvatarAppearance::computeBodySize()
mAvatarOffset.mV[VX] = 0.0f;
mAvatarOffset.mV[VY] = 0.0f;
- // Certain configurations of avatars can force the overall height (with offset) to go negative.
- // Enforce a constraint to make sure we don't go below 0.1 meters.
- // Camera positioning and other things start to break down when your avatar is "walking" while being fully underground
- if (new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] < 0.1f)
- {
- mAvatarOffset.mV[VZ] = -(new_body_size.mV[VZ] - 0.11f); // avoid floating point rounding making the above check continue to fail.
-
- llassert(new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] >= 0.1f);
-
- if (mWearableData && isSelf())
- {
- LLWearable* shape = mWearableData->getWearable(LLWearableType::WT_SHAPE, 0);
- if (shape)
- {
- shape->setVisualParamWeight(AVATAR_HOVER, mAvatarOffset.mV[VZ], false);
- }
- }
- }
-
if (new_body_size != mBodySize || old_offset != mAvatarOffset.mV[VZ])
{
mBodySize = new_body_size;
- bodySizeChanged();
}
}
@@ -1390,14 +1370,14 @@ BOOL LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name )
return TRUE;
}
-void LLAvatarAppearance::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL upload_bake )
+void LLAvatarAppearance::setClothesColor( ETextureIndex te, const LLColor4& new_color)
{
U32 param_name[3];
if( teToColorParams( te, param_name ) )
{
- setVisualParamWeight( param_name[0], new_color.mV[VX], upload_bake );
- setVisualParamWeight( param_name[1], new_color.mV[VY], upload_bake );
- setVisualParamWeight( param_name[2], new_color.mV[VZ], upload_bake );
+ setVisualParamWeight( param_name[0], new_color.mV[VX]);
+ setVisualParamWeight( param_name[1], new_color.mV[VY]);
+ setVisualParamWeight( param_name[2], new_color.mV[VZ]);
}
}
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index bce2540258..1e898026c0 100644..100755
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -107,7 +107,6 @@ public:
public:
virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent
virtual BOOL isValid() const;
- virtual BOOL isUsingServerBakes() const = 0;
virtual BOOL isUsingLocalAppearance() const = 0;
virtual BOOL isEditingAppearance() const = 0;
@@ -137,14 +136,13 @@ public:
typedef std::map<std::string, LLJoint*> joint_map_t;
joint_map_t mJointMap;
- void computeBodySize();
+ void computeBodySize();
protected:
static BOOL parseSkeletonFile(const std::string& filename);
virtual void buildCharacter();
virtual BOOL loadAvatar();
- virtual void bodySizeChanged() = 0;
BOOL setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
BOOL allocateCharacterJoints(U32 num);
@@ -225,7 +223,7 @@ public:
// Composites
//--------------------------------------------------------------------
public:
- virtual void invalidateComposite(LLTexLayerSet* layerset, BOOL upload_result) = 0;
+ virtual void invalidateComposite(LLTexLayerSet* layerset) = 0;
/********************************************************************************
** **
@@ -256,7 +254,7 @@ protected:
// Clothing colors (convenience functions to access visual parameters)
//--------------------------------------------------------------------
public:
- void setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake);
+ void setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color);
LLColor4 getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te);
static BOOL teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name);
@@ -265,7 +263,7 @@ public:
//--------------------------------------------------------------------
public:
LLColor4 getGlobalColor(const std::string& color_name ) const;
- virtual void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake) = 0;
+ virtual void onGlobalColorChanged(const LLTexGlobalColor* global_color) = 0;
protected:
LLTexGlobalColor* mTexSkinColor;
LLTexGlobalColor* mTexHairColor;
diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp
index c66a428374..e630c1118b 100644..100755
--- a/indra/llappearance/lldriverparam.cpp
+++ b/indra/llappearance/lldriverparam.cpp
@@ -152,19 +152,31 @@ void LLDriverParamInfo::toStream(std::ostream &out)
// LLDriverParam
//-----------------------------------------------------------------------------
-LLDriverParam::LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable /* = NULL */) :
+LLDriverParam::LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable /* = NULL */)
+ : LLViewerVisualParam(),
+ mDefaultVec(),
+ mDriven(),
mCurrentDistortionParam( NULL ),
mAvatarAppearance(appearance),
mWearablep(wearable)
{
llassert(mAvatarAppearance);
- if (mWearablep)
- {
- llassert(mAvatarAppearance->isSelf());
- }
+ llassert((mWearablep == NULL) || mAvatarAppearance->isSelf());
mDefaultVec.clear();
}
+LLDriverParam::LLDriverParam(const LLDriverParam& pOther)
+ : LLViewerVisualParam(pOther),
+ mDefaultVec(pOther.mDefaultVec),
+ mDriven(pOther.mDriven),
+ mCurrentDistortionParam(pOther.mCurrentDistortionParam),
+ mAvatarAppearance(pOther.mAvatarAppearance),
+ mWearablep(pOther.mWearablep)
+{
+ llassert(mAvatarAppearance);
+ llassert((mWearablep == NULL) || mAvatarAppearance->isSelf());
+}
+
LLDriverParam::~LLDriverParam()
{
}
@@ -178,7 +190,7 @@ BOOL LLDriverParam::setInfo(LLDriverParamInfo *info)
mID = info->mID;
info->mDriverParam = this;
- setWeight(getDefaultWeight(), FALSE );
+ setWeight(getDefaultWeight());
return TRUE;
}
@@ -186,16 +198,10 @@ BOOL LLDriverParam::setInfo(LLDriverParamInfo *info)
/*virtual*/ LLViewerVisualParam* LLDriverParam::cloneParam(LLWearable* wearable) const
{
llassert(wearable);
- LLDriverParam *new_param = new LLDriverParam(mAvatarAppearance, wearable);
- // FIXME DRANO this clobbers mWearablep, which means any code
- // currently using mWearablep is wrong, or at least untested.
- *new_param = *this;
- //new_param->mWearablep = wearable;
-// new_param->mDriven.clear(); // clear driven list to avoid overwriting avatar driven params from wearables.
- return new_param;
+ return new LLDriverParam(*this);
}
-void LLDriverParam::setWeight(F32 weight, BOOL upload_bake)
+void LLDriverParam::setWeight(F32 weight)
{
F32 min_weight = getMinWeight();
F32 max_weight = getMaxWeight();
@@ -254,7 +260,7 @@ void LLDriverParam::setWeight(F32 weight, BOOL upload_bake)
driven_weight = driven_min;
}
- setDrivenWeight(driven,driven_weight,upload_bake);
+ setDrivenWeight(driven,driven_weight);
continue;
}
else
@@ -278,13 +284,13 @@ void LLDriverParam::setWeight(F32 weight, BOOL upload_bake)
driven_weight = driven_min;
}
- setDrivenWeight(driven,driven_weight,upload_bake);
+ setDrivenWeight(driven,driven_weight);
continue;
}
}
driven_weight = getDrivenWeight(driven, mCurWeight);
- setDrivenWeight(driven,driven_weight,upload_bake);
+ setDrivenWeight(driven,driven_weight);
}
}
@@ -430,9 +436,9 @@ const LLViewerVisualParam* LLDriverParam::getDrivenParam(S32 index) const
//-----------------------------------------------------------------------------
// setAnimationTarget()
//-----------------------------------------------------------------------------
-void LLDriverParam::setAnimationTarget( F32 target_value, BOOL upload_bake )
+void LLDriverParam::setAnimationTarget( F32 target_value)
{
- LLVisualParam::setAnimationTarget(target_value, upload_bake);
+ LLVisualParam::setAnimationTarget(target_value);
for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
{
@@ -441,16 +447,16 @@ void LLDriverParam::setAnimationTarget( F32 target_value, BOOL upload_bake )
// this isn't normally necessary, as driver params handle interpolation of their driven params
// but texture params need to know to assume their final value at beginning of interpolation
- driven->mParam->setAnimationTarget(driven_weight, upload_bake);
+ driven->mParam->setAnimationTarget(driven_weight);
}
}
//-----------------------------------------------------------------------------
// stopAnimating()
//-----------------------------------------------------------------------------
-void LLDriverParam::stopAnimating(BOOL upload_bake)
+void LLDriverParam::stopAnimating()
{
- LLVisualParam::stopAnimating(upload_bake);
+ LLVisualParam::stopAnimating();
for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
{
@@ -530,7 +536,7 @@ void LLDriverParam::updateCrossDrivenParams(LLWearableType::EType driven_type)
LLWearable *wearable = mAvatarAppearance->getWearableData()->getTopWearable(driver_type);
if (wearable)
{
- wearable->setVisualParamWeight(mID, wearable->getVisualParamWeight(mID), false);
+ wearable->setVisualParamWeight(mID, wearable->getVisualParamWeight(mID));
}
}
}
@@ -593,7 +599,7 @@ F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight
return driven_weight;
}
-void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake)
+void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight)
{
bool use_self = false;
if(mWearablep &&
@@ -610,10 +616,10 @@ void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bo
if (use_self)
{
// call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values
- mAvatarAppearance->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, upload_bake );
+ mAvatarAppearance->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight);
}
else
{
- driven->mParam->setWeight( driven_weight, upload_bake );
+ driven->mParam->setWeight( driven_weight);
}
}
diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h
index 2420db76e7..f71c930e5e 100644..100755
--- a/indra/llappearance/lldriverparam.h
+++ b/indra/llappearance/lldriverparam.h
@@ -111,9 +111,9 @@ public:
// LLVisualParam Virtual functions
/*virtual*/ void apply( ESex sex ) {} // apply is called separately for each driven param.
- /*virtual*/ void setWeight(F32 weight, BOOL upload_bake);
- /*virtual*/ void setAnimationTarget( F32 target_value, BOOL upload_bake );
- /*virtual*/ void stopAnimating(BOOL upload_bake);
+ /*virtual*/ void setWeight(F32 weight);
+ /*virtual*/ void setAnimationTarget( F32 target_value);
+ /*virtual*/ void stopAnimating();
/*virtual*/ BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params);
/*virtual*/ void resetDrivenParams();
@@ -129,8 +129,9 @@ public:
const LLViewerVisualParam* getDrivenParam(S32 index) const;
protected:
+ LLDriverParam(const LLDriverParam& pOther);
F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight);
- void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake);
+ void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight);
LL_ALIGN_16(LLVector4a mDefaultVec); // temp holder
diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp
index ce8a0b0b76..e3992a080e 100644
--- a/indra/llappearance/llpolymorph.cpp
+++ b/indra/llappearance/llpolymorph.cpp
@@ -315,10 +315,27 @@ BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node)
// LLPolyMorphTarget()
//-----------------------------------------------------------------------------
LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh)
- : mMorphData(NULL), mMesh(poly_mesh),
- mVertMask(NULL),
- mLastSex(SEX_FEMALE),
- mNumMorphMasksPending(0)
+ : LLViewerVisualParam(),
+ mMorphData(NULL),
+ mMesh(poly_mesh),
+ mVertMask(NULL),
+ mLastSex(SEX_FEMALE),
+ mNumMorphMasksPending(0),
+ mVolumeMorphs()
+{
+}
+
+//-----------------------------------------------------------------------------
+// LLPolyMorphTarget()
+//-----------------------------------------------------------------------------
+LLPolyMorphTarget::LLPolyMorphTarget(const LLPolyMorphTarget& pOther)
+ : LLViewerVisualParam(pOther),
+ mMorphData(pOther.mMorphData),
+ mMesh(pOther.mMesh),
+ mVertMask(pOther.mVertMask == NULL ? NULL : new LLPolyVertexMask(*pOther.mVertMask)),
+ mLastSex(pOther.mLastSex),
+ mNumMorphMasksPending(pOther.mNumMorphMasksPending),
+ mVolumeMorphs(pOther.mVolumeMorphs)
{
}
@@ -327,10 +344,8 @@ LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh)
//-----------------------------------------------------------------------------
LLPolyMorphTarget::~LLPolyMorphTarget()
{
- if (mVertMask)
- {
- delete mVertMask;
- }
+ delete mVertMask;
+ mVertMask = NULL;
}
//-----------------------------------------------------------------------------
@@ -343,7 +358,7 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
return FALSE;
mInfo = info;
mID = info->mID;
- setWeight(getDefaultWeight(), FALSE );
+ setWeight(getDefaultWeight());
LLAvatarAppearance* avatarp = mMesh->getAvatar();
LLPolyMorphTargetInfo::volume_info_list_t::iterator iter;
@@ -385,9 +400,7 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
/*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const
{
- LLPolyMorphTarget *new_param = new LLPolyMorphTarget(mMesh);
- *new_param = *this;
- return new_param;
+ return new LLPolyMorphTarget(*this);
}
#if 0 // obsolete
@@ -722,10 +735,25 @@ void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S3
// LLPolyVertexMask()
//-----------------------------------------------------------------------------
LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data)
+ : mWeights(new F32[morph_data->mNumIndices]),
+ mMorphData(morph_data),
+ mWeightsGenerated(FALSE)
+{
+ llassert(mMorphData != NULL);
+ llassert(mMorphData->mNumIndices > 0);
+}
+
+//-----------------------------------------------------------------------------
+// LLPolyVertexMask()
+//-----------------------------------------------------------------------------
+LLPolyVertexMask::LLPolyVertexMask(const LLPolyVertexMask& pOther)
+ : mWeights(new F32[pOther.mMorphData->mNumIndices]),
+ mMorphData(pOther.mMorphData),
+ mWeightsGenerated(pOther.mWeightsGenerated)
{
- mWeights = new F32[morph_data->mNumIndices];
- mMorphData = morph_data;
- mWeightsGenerated = FALSE;
+ llassert(mMorphData != NULL);
+ llassert(mMorphData->mNumIndices > 0);
+ memcpy(mWeights, pOther.mWeights, sizeof(F32) * mMorphData->mNumIndices);
}
//-----------------------------------------------------------------------------
@@ -733,7 +761,8 @@ LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data)
//-----------------------------------------------------------------------------
LLPolyVertexMask::~LLPolyVertexMask()
{
- delete[] mWeights;
+ delete [] mWeights;
+ mWeights = NULL;
}
//-----------------------------------------------------------------------------
diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h
index ee380ae7c3..7e712f9e94 100644
--- a/indra/llappearance/llpolymorph.h
+++ b/indra/llappearance/llpolymorph.h
@@ -91,6 +91,7 @@ class LLPolyVertexMask
{
public:
LLPolyVertexMask(LLPolyMorphData* morph_data);
+ LLPolyVertexMask(const LLPolyVertexMask& pOther);
~LLPolyVertexMask();
void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights);
@@ -182,6 +183,8 @@ public:
void addPendingMorphMask() { mNumMorphMasksPending++; }
protected:
+ LLPolyMorphTarget(const LLPolyMorphTarget& pOther);
+
LLPolyMorphData* mMorphData;
LLPolyMesh* mMesh;
LLPolyVertexMask * mVertMask;
diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp
index a72b446ace..ea29cbd451 100644
--- a/indra/llappearance/llpolyskeletaldistortion.cpp
+++ b/indra/llappearance/llpolyskeletaldistortion.cpp
@@ -104,9 +104,25 @@ BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node)
// LLPolySkeletalDistortion()
//-----------------------------------------------------------------------------
LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLAvatarAppearance *avatarp)
+ : LLViewerVisualParam(),
+ mDefaultVec(),
+ mJointScales(),
+ mJointOffsets(),
+ mAvatar(avatarp)
+{
+ mDefaultVec.splat(0.001f);
+}
+
+//-----------------------------------------------------------------------------
+// LLPolySkeletalDistortion()
+//-----------------------------------------------------------------------------
+LLPolySkeletalDistortion::LLPolySkeletalDistortion(const LLPolySkeletalDistortion &pOther)
+ : LLViewerVisualParam(pOther),
+ mDefaultVec(pOther.mDefaultVec),
+ mJointScales(pOther.mJointScales),
+ mJointOffsets(pOther.mJointOffsets),
+ mAvatar(pOther.mAvatar)
{
- mAvatar = avatarp;
- mDefaultVec.splat(0.001f);
}
//-----------------------------------------------------------------------------
@@ -123,7 +139,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
return FALSE;
mInfo = info;
mID = info->mID;
- setWeight(getDefaultWeight(), FALSE );
+ setWeight(getDefaultWeight());
LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter;
for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++)
@@ -171,9 +187,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const
{
- LLPolySkeletalDistortion *new_param = new LLPolySkeletalDistortion(mAvatar);
- *new_param = *this;
- return new_param;
+ return new LLPolySkeletalDistortion(*this);
}
//-----------------------------------------------------------------------------
@@ -185,7 +199,7 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
{
LL_RECORD_BLOCK_TIME(FTM_POLYSKELETAL_DISTORTION_APPLY);
- F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
+ F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
LLJoint* joint;
joint_vec_map_t::iterator iter;
@@ -197,8 +211,10 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
joint = iter->first;
LLVector3 newScale = joint->getScale();
LLVector3 scaleDelta = iter->second;
- newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta);
- joint->setScale(newScale);
+ newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta);
+ //An aspect of attached mesh objects (which contain joint offsets) that need to be cleaned up when detached
+ joint->storeScaleForReset( newScale );
+ joint->setScale(newScale);
}
for (iter = mJointOffsets.begin();
@@ -207,8 +223,8 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
{
joint = iter->first;
LLVector3 newPosition = joint->getPosition();
- LLVector3 positionDelta = iter->second;
- newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);
+ LLVector3 positionDelta = iter->second;
+ newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);
joint->setPosition(newPosition);
}
diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h
index 24c9e9ae48..ea2adb8a87 100644
--- a/indra/llappearance/llpolyskeletaldistortion.h
+++ b/indra/llappearance/llpolyskeletaldistortion.h
@@ -118,6 +118,8 @@ public:
/*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;};
protected:
+ LLPolySkeletalDistortion(const LLPolySkeletalDistortion& pOther);
+
LL_ALIGN_16(LLVector4a mDefaultVec);
typedef std::map<LLJoint*, LLVector3> joint_vec_map_t;
joint_vec_map_t mJointScales;
diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp
index 186c537659..3df2254b14 100644..100755
--- a/indra/llappearance/lltexglobalcolor.cpp
+++ b/indra/llappearance/lltexglobalcolor.cpp
@@ -90,22 +90,36 @@ const std::string& LLTexGlobalColor::getName() const
//-----------------------------------------------------------------------------
// LLTexParamGlobalColor
//-----------------------------------------------------------------------------
-LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) :
- LLTexLayerParamColor(tex_global_color->getAvatarAppearance()),
+LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color)
+ : LLTexLayerParamColor(tex_global_color->getAvatarAppearance()),
mTexGlobalColor(tex_global_color)
{
}
+//-----------------------------------------------------------------------------
+// LLTexParamGlobalColor
+//-----------------------------------------------------------------------------
+LLTexParamGlobalColor::LLTexParamGlobalColor(const LLTexParamGlobalColor& pOther)
+ : LLTexLayerParamColor(pOther),
+ mTexGlobalColor(pOther.mTexGlobalColor)
+{
+}
+
+//-----------------------------------------------------------------------------
+// ~LLTexParamGlobalColor
+//-----------------------------------------------------------------------------
+LLTexParamGlobalColor::~LLTexParamGlobalColor()
+{
+}
+
/*virtual*/ LLViewerVisualParam* LLTexParamGlobalColor::cloneParam(LLWearable* wearable) const
{
- LLTexParamGlobalColor *new_param = new LLTexParamGlobalColor(mTexGlobalColor);
- *new_param = *this;
- return new_param;
+ return new LLTexParamGlobalColor(*this);
}
-void LLTexParamGlobalColor::onGlobalColorChanged(bool upload_bake)
+void LLTexParamGlobalColor::onGlobalColorChanged()
{
- mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor, upload_bake);
+ mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor);
}
//-----------------------------------------------------------------------------
diff --git a/indra/llappearance/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h
index 2867479876..3b426053de 100644..100755
--- a/indra/llappearance/lltexglobalcolor.h
+++ b/indra/llappearance/lltexglobalcolor.h
@@ -73,9 +73,11 @@ class LLTexParamGlobalColor : public LLTexLayerParamColor
{
public:
LLTexParamGlobalColor(LLTexGlobalColor *tex_color);
+ virtual ~LLTexParamGlobalColor();
/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
protected:
- /*virtual*/ void onGlobalColorChanged(bool upload_bake);
+ LLTexParamGlobalColor(const LLTexParamGlobalColor& pOther);
+ /*virtual*/ void onGlobalColorChanged();
private:
LLTexGlobalColor* mTexGlobalColor;
};
diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
index f6abaa5eb3..2cf86bb4fe 100644
--- a/indra/llappearance/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -1560,10 +1560,13 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
}
U32 cache_index = alpha_mask_crc.getCRC();
- U8* alpha_data = get_if_there(mAlphaCache,cache_index,(U8*)NULL);
- if (!alpha_data)
+ U8* alpha_data = NULL;
+ // We believe we need to generate morph masks, do not assume that the cached version is accurate.
+ // We can get bad morph masks during login, on minimize, and occasional gl errors.
+ // We should only be doing this when we believe something has changed with respect to the user's appearance.
{
- // clear out a slot if we have filled our cache
+ LL_DEBUGS("Avatar") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL;
+ // clear out a slot if we have filled our cache
S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1;
while ((S32)mAlphaCache.size() >= max_cache_entries)
{
@@ -1783,13 +1786,11 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
{
U32 num_wearables = updateWearableCache();
- for (U32 i = 0; i < num_wearables; i++)
+ U32 i = num_wearables - 1; // For rendering morph masks, we only want to use the top wearable
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
{
- LLTexLayer *layer = getLayer(i);
- if (layer)
- {
- layer->addAlphaMask(data, originX, originY, width, height);
- }
+ layer->addAlphaMask(data, originX, originY, width, height);
}
}
diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp
index f1f7d07fa9..ff682d6906 100644..100755
--- a/indra/llappearance/lltexlayerparams.cpp
+++ b/indra/llappearance/lltexlayerparams.cpp
@@ -40,7 +40,8 @@
//-----------------------------------------------------------------------------
// LLTexLayerParam
//-----------------------------------------------------------------------------
-LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
+LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer)
+ : LLViewerVisualParam(),
mTexLayer(layer),
mAvatarAppearance(NULL)
{
@@ -54,12 +55,19 @@ LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
}
}
-LLTexLayerParam::LLTexLayerParam(LLAvatarAppearance *appearance) :
+LLTexLayerParam::LLTexLayerParam(LLAvatarAppearance *appearance)
+ : LLViewerVisualParam(),
mTexLayer(NULL),
mAvatarAppearance(appearance)
{
}
+LLTexLayerParam::LLTexLayerParam(const LLTexLayerParam& pOther)
+ : LLViewerVisualParam(pOther),
+ mTexLayer(pOther.mTexLayer),
+ mAvatarAppearance(pOther.mAvatarAppearance)
+{
+}
BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_appearance)
{
@@ -112,9 +120,11 @@ void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes)
}
}
-LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) :
- LLTexLayerParam(layer),
+LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer)
+ : LLTexLayerParam(layer),
mCachedProcessedTexture(NULL),
+ mStaticImageTGA(),
+ mStaticImageRaw(),
mNeedsCreateTexture(FALSE),
mStaticImageInvalid(FALSE),
mAvgDistortionVec(1.f, 1.f, 1.f),
@@ -123,9 +133,11 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) :
sInstances.push_front(this);
}
-LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance) :
- LLTexLayerParam(appearance),
+LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance)
+ : LLTexLayerParam(appearance),
mCachedProcessedTexture(NULL),
+ mStaticImageTGA(),
+ mStaticImageRaw(),
mNeedsCreateTexture(FALSE),
mStaticImageInvalid(FALSE),
mAvgDistortionVec(1.f, 1.f, 1.f),
@@ -134,6 +146,18 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance) :
sInstances.push_front(this);
}
+LLTexLayerParamAlpha::LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther)
+ : LLTexLayerParam(pOther),
+ mCachedProcessedTexture(pOther.mCachedProcessedTexture),
+ mStaticImageTGA(pOther.mStaticImageTGA),
+ mStaticImageRaw(pOther.mStaticImageRaw),
+ mNeedsCreateTexture(pOther.mNeedsCreateTexture),
+ mStaticImageInvalid(pOther.mStaticImageInvalid),
+ mAvgDistortionVec(pOther.mAvgDistortionVec),
+ mCachedEffectiveWeight(pOther.mCachedEffectiveWeight)
+{
+ sInstances.push_front(this);
+}
LLTexLayerParamAlpha::~LLTexLayerParamAlpha()
{
@@ -143,9 +167,7 @@ LLTexLayerParamAlpha::~LLTexLayerParamAlpha()
/*virtual*/ LLViewerVisualParam* LLTexLayerParamAlpha::cloneParam(LLWearable* wearable) const
{
- LLTexLayerParamAlpha *new_param = new LLTexLayerParamAlpha(mTexLayer);
- *new_param = *this;
- return new_param;
+ return new LLTexLayerParamAlpha(*this);
}
void LLTexLayerParamAlpha::deleteCaches()
@@ -161,7 +183,7 @@ BOOL LLTexLayerParamAlpha::getMultiplyBlend() const
return ((LLTexLayerParamAlphaInfo *)getInfo())->mMultiplyBlend;
}
-void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake)
+void LLTexLayerParamAlpha::setWeight(F32 weight)
{
if (mIsAnimating || mTexLayer == NULL)
{
@@ -179,35 +201,35 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL upload_bake)
if ((mAvatarAppearance->getSex() & getSex()) &&
(mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
{
- mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
+ mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet());
mTexLayer->invalidateMorphMasks();
}
}
}
-void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL upload_bake)
+void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value)
{
// do not animate dummy parameters
if (mIsDummy)
{
- setWeight(target_value, upload_bake);
+ setWeight(target_value);
return;
}
mTargetWeight = target_value;
- setWeight(target_value, upload_bake);
+ setWeight(target_value);
mIsAnimating = TRUE;
if (mNext)
{
- mNext->setAnimationTarget(target_value, upload_bake);
+ mNext->setAnimationTarget(target_value);
}
}
-void LLTexLayerParamAlpha::animate(F32 delta, BOOL upload_bake)
+void LLTexLayerParamAlpha::animate(F32 delta)
{
if (mNext)
{
- mNext->animate(delta, upload_bake);
+ mNext->animate(delta);
}
}
@@ -399,27 +421,31 @@ BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node)
-LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer) :
- LLTexLayerParam(layer),
+LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer)
+ : LLTexLayerParam(layer),
mAvgDistortionVec(1.f, 1.f, 1.f)
{
}
-LLTexLayerParamColor::LLTexLayerParamColor(LLAvatarAppearance *appearance) :
- LLTexLayerParam(appearance),
+LLTexLayerParamColor::LLTexLayerParamColor(LLAvatarAppearance *appearance)
+ : LLTexLayerParam(appearance),
mAvgDistortionVec(1.f, 1.f, 1.f)
{
}
+LLTexLayerParamColor::LLTexLayerParamColor(const LLTexLayerParamColor& pOther)
+ : LLTexLayerParam(pOther),
+ mAvgDistortionVec(pOther.mAvgDistortionVec)
+{
+}
+
LLTexLayerParamColor::~LLTexLayerParamColor()
{
}
/*virtual*/ LLViewerVisualParam* LLTexLayerParamColor::cloneParam(LLWearable* wearable) const
{
- LLTexLayerParamColor *new_param = new LLTexLayerParamColor(mTexLayer);
- *new_param = *this;
- return new_param;
+ return new LLTexLayerParamColor(*this);
}
LLColor4 LLTexLayerParamColor::getNetColor() const
@@ -450,14 +476,14 @@ LLColor4 LLTexLayerParamColor::getNetColor() const
}
}
-void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
+
+void LLTexLayerParamColor::setWeight(F32 weight)
{
if (mIsAnimating)
{
return;
}
- const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo();
F32 min_weight = getMinWeight();
F32 max_weight = getMaxWeight();
F32 new_weight = llclamp(weight, min_weight, max_weight);
@@ -467,6 +493,8 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
{
mCurWeight = new_weight;
+ const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo();
+
if (info->mNumColors <= 0)
{
// This will happen when we set the default weight the first time.
@@ -475,10 +503,10 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
if ((mAvatarAppearance->getSex() & getSex()) && (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
{
- onGlobalColorChanged(upload_bake);
+ onGlobalColorChanged();
if (mTexLayer)
{
- mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet(), upload_bake);
+ mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet());
}
}
@@ -486,23 +514,23 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL upload_bake)
}
}
-void LLTexLayerParamColor::setAnimationTarget(F32 target_value, BOOL upload_bake)
+void LLTexLayerParamColor::setAnimationTarget(F32 target_value)
{
// set value first then set interpolating flag to ignore further updates
mTargetWeight = target_value;
- setWeight(target_value, upload_bake);
+ setWeight(target_value);
mIsAnimating = TRUE;
if (mNext)
{
- mNext->setAnimationTarget(target_value, upload_bake);
+ mNext->setAnimationTarget(target_value);
}
}
-void LLTexLayerParamColor::animate(F32 delta, BOOL upload_bake)
+void LLTexLayerParamColor::animate(F32 delta)
{
if (mNext)
{
- mNext->animate(delta, upload_bake);
+ mNext->animate(delta);
}
}
diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h
index b38d28d3eb..0cb2dedbff 100644..100755
--- a/indra/llappearance/lltexlayerparams.h
+++ b/indra/llappearance/lltexlayerparams.h
@@ -52,6 +52,8 @@ public:
/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0;
protected:
+ LLTexLayerParam(const LLTexLayerParam& pOther);
+
LLTexLayerInterface* mTexLayer;
LLAvatarAppearance* mAvatarAppearance;
};
@@ -83,9 +85,9 @@ public:
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex avatar_sex ) {}
- /*virtual*/ void setWeight(F32 weight, BOOL upload_bake);
- /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake);
- /*virtual*/ void animate(F32 delta, BOOL upload_bake);
+ /*virtual*/ void setWeight(F32 weight);
+ /*virtual*/ void setAnimationTarget(F32 target_value);
+ /*virtual*/ void animate(F32 delta);
// LLViewerVisualParam Virtual functions
/*virtual*/ F32 getTotalDistortion() { return 1.f; }
@@ -102,6 +104,8 @@ public:
BOOL getMultiplyBlend() const;
private:
+ LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther);
+
LLPointer<LLGLTexture> mCachedProcessedTexture;
LLPointer<LLImageTGA> mStaticImageTGA;
LLPointer<LLImageRaw> mStaticImageRaw;
@@ -174,9 +178,9 @@ public:
// LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex avatar_sex ) {}
- /*virtual*/ void setWeight(F32 weight, BOOL upload_bake);
- /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake);
- /*virtual*/ void animate(F32 delta, BOOL upload_bake);
+ /*virtual*/ void setWeight(F32 weight);
+ /*virtual*/ void setAnimationTarget(F32 target_value);
+ /*virtual*/ void animate(F32 delta);
// LLViewerVisualParam Virtual functions
@@ -190,7 +194,9 @@ public:
// New functions
LLColor4 getNetColor() const;
protected:
- virtual void onGlobalColorChanged(bool upload_bake) {}
+ LLTexLayerParamColor(const LLTexLayerParamColor& pOther);
+
+ virtual void onGlobalColorChanged() {}
private:
LL_ALIGN_16(LLVector4a mAvgDistortionVec);
} LL_ALIGN_POSTFIX(16);
diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp
index cc81bcf118..af8394b60c 100644
--- a/indra/llappearance/llviewervisualparam.cpp
+++ b/indra/llappearance/llviewervisualparam.cpp
@@ -123,6 +123,22 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node)
// LLViewerVisualParam()
//-----------------------------------------------------------------------------
LLViewerVisualParam::LLViewerVisualParam()
+ : LLVisualParam()
+{
+}
+
+//-----------------------------------------------------------------------------
+// LLViewerVisualParam()
+//-----------------------------------------------------------------------------
+LLViewerVisualParam::LLViewerVisualParam(const LLViewerVisualParam& pOther)
+ : LLVisualParam(pOther)
+{
+}
+
+//-----------------------------------------------------------------------------
+// ~LLViewerVisualParam()
+//-----------------------------------------------------------------------------
+LLViewerVisualParam::~LLViewerVisualParam()
{
}
@@ -137,7 +153,7 @@ BOOL LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info)
return FALSE;
mInfo = info;
mID = info->mID;
- setWeight(getDefaultWeight(), FALSE );
+ setWeight(getDefaultWeight());
return TRUE;
}
diff --git a/indra/llappearance/llviewervisualparam.h b/indra/llappearance/llviewervisualparam.h
index 2826e6c316..1a710c0ca6 100644
--- a/indra/llappearance/llviewervisualparam.h
+++ b/indra/llappearance/llviewervisualparam.h
@@ -70,7 +70,7 @@ class LLViewerVisualParam : public LLVisualParam
{
public:
LLViewerVisualParam();
- /*virtual*/ ~LLViewerVisualParam(){};
+ virtual ~LLViewerVisualParam();
// Special: These functions are overridden by child classes
LLViewerVisualParamInfo *getInfo() const { return (LLViewerVisualParamInfo*)mInfo; };
@@ -105,6 +105,8 @@ public:
BOOL getCrossWearable() const { return getInfo()->mCrossWearable; }
+protected:
+ LLViewerVisualParam(const LLViewerVisualParam& pOther);
} LL_ALIGN_POSTFIX(16);
#endif // LL_LLViewerVisualParam_H
diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp
index 389505fa34..4bce3f99ed 100644..100755
--- a/indra/llappearance/llwearable.cpp
+++ b/indra/llappearance/llwearable.cpp
@@ -43,9 +43,32 @@ S32 LLWearable::sCurrentDefinitionVersion = 1;
// Private local functions
static std::string terse_F32_to_string(F32 f);
+LLWearable::LLWearable()
+ : mDefinitionVersion(-1),
+ mName(),
+ mDescription(),
+ mPermissions(),
+ mSaleInfo(),
+ mType(LLWearableType::WT_NONE),
+ mSavedVisualParamMap(),
+ mVisualParamIndexMap(),
+ mTEMap(),
+ mSavedTEMap()
+{
+}
+
// virtual
LLWearable::~LLWearable()
{
+ for (visual_param_index_map_t::iterator vpIter = mVisualParamIndexMap.begin(); vpIter != mVisualParamIndexMap.end(); ++vpIter)
+ {
+ LLVisualParam* vp = vpIter->second;
+ vp->clearNextParam();
+ delete vp;
+ vpIter->second = NULL;
+ }
+
+ destroyTextures();
}
const std::string& LLWearable::getTypeLabel() const
@@ -525,7 +548,7 @@ void LLWearable::revertValues()
LLVisualParam *param = getVisualParam(id);
if(param && !dynamic_cast<LLDriverParam*>(param) )
{
- setVisualParamWeight(id, value, TRUE);
+ setVisualParamWeight(id, value);
}
}
@@ -537,7 +560,7 @@ void LLWearable::revertValues()
LLVisualParam *param = getVisualParam(id);
if(param && dynamic_cast<LLDriverParam*>(param) )
{
- setVisualParamWeight(id, value, TRUE);
+ setVisualParamWeight(id, value);
}
}
@@ -620,17 +643,10 @@ void LLWearable::syncImages(te_map_t &src, te_map_t &dst)
void LLWearable::destroyTextures()
{
- for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter )
- {
- LLLocalTextureObject *lto = iter->second;
- delete lto;
- }
+ std::for_each(mTEMap.begin(), mTEMap.end(), DeletePairedPointer());
mTEMap.clear();
- for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter )
- {
- LLLocalTextureObject *lto = iter->second;
- delete lto;
- }
+
+ std::for_each(mSavedTEMap.begin(), mSavedTEMap.end(), DeletePairedPointer());
mSavedTEMap.clear();
}
@@ -647,12 +663,12 @@ void LLWearable::addVisualParam(LLVisualParam *param)
}
-void LLWearable::setVisualParamWeight(S32 param_index, F32 value, BOOL upload_bake)
+void LLWearable::setVisualParamWeight(S32 param_index, F32 value)
{
if( is_in_map(mVisualParamIndexMap, param_index ) )
{
LLVisualParam *wearable_param = mVisualParamIndexMap[param_index];
- wearable_param->setWeight(value, upload_bake);
+ wearable_param->setWeight(value);
}
else
{
@@ -693,14 +709,14 @@ void LLWearable::getVisualParams(visual_param_vec_t &list)
}
}
-void LLWearable::animateParams(F32 delta, BOOL upload_bake)
+void LLWearable::animateParams(F32 delta)
{
for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin();
iter != mVisualParamIndexMap.end();
++iter)
{
LLVisualParam *param = (LLVisualParam*) iter->second;
- param->animate(delta, upload_bake);
+ param->animate(delta);
}
}
@@ -718,14 +734,14 @@ LLColor4 LLWearable::getClothesColor(S32 te) const
return color;
}
-void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake )
+void LLWearable::setClothesColor( S32 te, const LLColor4& new_color)
{
U32 param_name[3];
if( LLAvatarAppearance::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) )
{
for( U8 index = 0; index < 3; index++ )
{
- setVisualParamWeight(param_name[index], new_color.mV[index], upload_bake);
+ setVisualParamWeight(param_name[index], new_color.mV[index]);
}
}
}
@@ -744,7 +760,7 @@ void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp)
S32 param_id = param->getID();
F32 weight = getVisualParamWeight(param_id);
- avatarp->setVisualParamWeight( param_id, weight, FALSE );
+ avatarp->setVisualParamWeight( param_id, weight);
}
}
}
diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h
index 132c153bcd..406fc7e883 100644..100755
--- a/indra/llappearance/llwearable.h
+++ b/indra/llappearance/llwearable.h
@@ -46,6 +46,7 @@ class LLWearable
// Constructors and destructors
//--------------------------------------------------------------------
public:
+ LLWearable();
virtual ~LLWearable();
//--------------------------------------------------------------------
@@ -94,14 +95,14 @@ public:
void setLocalTextureObject(S32 index, LLLocalTextureObject &lto);
void addVisualParam(LLVisualParam *param);
- void setVisualParamWeight(S32 index, F32 value, BOOL upload_bake);
+ void setVisualParamWeight(S32 index, F32 value);
F32 getVisualParamWeight(S32 index) const;
LLVisualParam* getVisualParam(S32 index) const;
void getVisualParams(visual_param_vec_t &list);
- void animateParams(F32 delta, BOOL upload_bake);
+ void animateParams(F32 delta);
LLColor4 getClothesColor(S32 te) const;
- void setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake );
+ void setClothesColor( S32 te, const LLColor4& new_color);
virtual void revertValues();
virtual void saveValues();
diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp
index 089370dbc4..cf1ee435a8 100644..100755
--- a/indra/llappearance/llwearabledata.cpp
+++ b/indra/llappearance/llwearabledata.cpp
@@ -119,13 +119,6 @@ U32 LLWearableData::pushWearable(const LLWearableType::EType type,
void LLWearableData::wearableUpdated(LLWearable *wearable, BOOL removed)
{
wearable->setUpdated();
- // FIXME DRANO avoid updating params via wearables when rendering server-baked appearance.
-#if 0
- if (mAvatarAppearance->isUsingServerBakes() && !mAvatarAppearance->isUsingLocalAppearance())
- {
- return;
- }
-#endif
if (!removed)
{
pullCrossWearableValues(wearable->getType());
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp
index 82ddfa01ec..4df975ecc5 100755
--- a/indra/llcharacter/llcharacter.cpp
+++ b/indra/llcharacter/llcharacter.cpp
@@ -287,13 +287,13 @@ void LLCharacter::removeAnimationData(std::string name)
//-----------------------------------------------------------------------------
// setVisualParamWeight()
//-----------------------------------------------------------------------------
-BOOL LLCharacter::setVisualParamWeight(const LLVisualParam* which_param, F32 weight, BOOL upload_bake)
+BOOL LLCharacter::setVisualParamWeight(const LLVisualParam* which_param, F32 weight)
{
S32 index = which_param->getID();
visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index);
if (index_iter != mVisualParamIndexMap.end())
{
- index_iter->second->setWeight(weight, upload_bake);
+ index_iter->second->setWeight(weight);
return TRUE;
}
return FALSE;
@@ -302,7 +302,7 @@ BOOL LLCharacter::setVisualParamWeight(const LLVisualParam* which_param, F32 wei
//-----------------------------------------------------------------------------
// setVisualParamWeight()
//-----------------------------------------------------------------------------
-BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake)
+BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight)
{
std::string tname(param_name);
LLStringUtil::toLower(tname);
@@ -310,7 +310,7 @@ BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL
visual_param_name_map_t::iterator name_iter = mVisualParamNameMap.find(tableptr);
if (name_iter != mVisualParamNameMap.end())
{
- name_iter->second->setWeight(weight, upload_bake);
+ name_iter->second->setWeight(weight);
return TRUE;
}
LL_WARNS() << "LLCharacter::setVisualParamWeight() Invalid visual parameter: " << param_name << LL_ENDL;
@@ -320,12 +320,12 @@ BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL
//-----------------------------------------------------------------------------
// setVisualParamWeight()
//-----------------------------------------------------------------------------
-BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake)
+BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight)
{
visual_param_index_map_t::iterator index_iter = mVisualParamIndexMap.find(index);
if (index_iter != mVisualParamIndexMap.end())
{
- index_iter->second->setWeight(weight, upload_bake);
+ index_iter->second->setWeight(weight);
return TRUE;
}
LL_WARNS() << "LLCharacter::setVisualParamWeight() Invalid visual parameter index: " << index << LL_ENDL;
@@ -395,7 +395,7 @@ void LLCharacter::clearVisualParamWeights()
{
if (param->isTweakable())
{
- param->setWeight( param->getDefaultWeight(), FALSE );
+ param->setWeight( param->getDefaultWeight());
}
}
}
diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index b10a8a5f34..d4e3b76386 100755
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -190,9 +190,9 @@ public:
void addVisualParam(LLVisualParam *param);
void addSharedVisualParam(LLVisualParam *param);
- virtual BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight, BOOL upload_bake = FALSE );
- virtual BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL upload_bake = FALSE );
- virtual BOOL setVisualParamWeight(S32 index, F32 weight, BOOL upload_bake = FALSE );
+ virtual BOOL setVisualParamWeight(const LLVisualParam *which_param, F32 weight);
+ virtual BOOL setVisualParamWeight(const char* param_name, F32 weight);
+ virtual BOOL setVisualParamWeight(S32 index, F32 weight);
// get visual param weight by param or name
F32 getVisualParamWeight(LLVisualParam *distortion);
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index 1492cc172c..dbd6d48a95 100755
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -48,8 +48,11 @@ void LLJoint::init()
mParent = NULL;
mXform.setScaleChildOffset(TRUE);
mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
+ mOldXform.setScaleChildOffset(TRUE);
+ mOldXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
mUpdateXform = TRUE;
+ mResetAfterRestoreOldXform = false;
}
LLJoint::LLJoint() :
@@ -57,7 +60,6 @@ LLJoint::LLJoint() :
{
init();
touch();
- mResetAfterRestoreOldXform = false;
}
LLJoint::LLJoint(S32 joint_num) :
@@ -65,7 +67,6 @@ LLJoint::LLJoint(S32 joint_num) :
{
init();
touch();
- mResetAfterRestoreOldXform = false;
}
@@ -78,7 +79,6 @@ LLJoint::LLJoint(const std::string &name, LLJoint *parent) :
{
init();
mUpdateXform = FALSE;
- // *TODO: mResetAfterRestoreOldXform is not initialized!!!
setName(name);
if (parent)
@@ -239,11 +239,8 @@ const LLVector3& LLJoint::getPosition()
//--------------------------------------------------------------------
void LLJoint::setPosition( const LLVector3& pos )
{
-// if (mXform.getPosition() != pos)
- {
- mXform.setPosition(pos);
- touch(MATRIX_DIRTY | POSITION_DIRTY);
- }
+ mXform.setPosition(pos);
+ touch(MATRIX_DIRTY | POSITION_DIRTY);
}
@@ -251,38 +248,37 @@ void LLJoint::setPosition( const LLVector3& pos )
// setPosition()
//--------------------------------------------------------------------
void LLJoint::setDefaultFromCurrentXform( void )
-{
+{
mDefaultXform = mXform;
- touch(MATRIX_DIRTY | POSITION_DIRTY);
-
}
//--------------------------------------------------------------------
// storeCurrentXform()
//--------------------------------------------------------------------
void LLJoint::storeCurrentXform( const LLVector3& pos )
-{
+{
mOldXform = mXform;
- mResetAfterRestoreOldXform = true;
+ mResetAfterRestoreOldXform = true;
setPosition( pos );
+ touch(ALL_DIRTY);
}
+
//--------------------------------------------------------------------
-// restoreOldXform()
+// storeScaleForReset()
//--------------------------------------------------------------------
-void LLJoint::restoreOldXform( void )
+void LLJoint::storeScaleForReset( const LLVector3& scale )
{
- mResetAfterRestoreOldXform = false;
- mXform = mOldXform;
+ mOldXform.setScale( scale );
}
//--------------------------------------------------------------------
// restoreOldXform()
//--------------------------------------------------------------------
-void LLJoint::restoreToDefaultXform( void )
+void LLJoint::restoreOldXform( void )
{
mXform = mDefaultXform;
- setPosition( mXform.getPosition() );
+ mResetAfterRestoreOldXform = false;
+ mDirtyFlags = ALL_DIRTY;
}
-
//--------------------------------------------------------------------
// getWorldPosition()
//--------------------------------------------------------------------
@@ -299,8 +295,6 @@ LLVector3 LLJoint::getLastWorldPosition()
{
return mXform.getWorldPosition();
}
-
-
//--------------------------------------------------------------------
// setWorldPosition()
//--------------------------------------------------------------------
@@ -404,7 +398,7 @@ void LLJoint::setWorldRotation( const LLQuaternion& rot )
//--------------------------------------------------------------------
const LLVector3& LLJoint::getScale()
{
- return mXform.getScale();
+ return mXform.getScale();
}
//--------------------------------------------------------------------
@@ -413,7 +407,7 @@ const LLVector3& LLJoint::getScale()
void LLJoint::setScale( const LLVector3& scale )
{
// if (mXform.getScale() != scale)
- {
+ {
mXform.setScale(scale);
touch();
}
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index 6efa13aeb5..b65d6979d4 100755
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -83,6 +83,7 @@ protected:
LLXformMatrix mDefaultXform;
LLUUID mId;
+
public:
U32 mDirtyFlags;
BOOL mUpdateXform;
@@ -159,7 +160,7 @@ public:
// get/set local scale
const LLVector3& getScale();
void setScale( const LLVector3& scale );
-
+ void storeScaleForReset( const LLVector3& scale );
// get/set world matrix
const LLMatrix4 &getWorldMatrix();
void setWorldMatrix( const LLMatrix4& mat );
@@ -184,7 +185,6 @@ public:
S32 getJointNum() const { return mJointNum; }
void restoreOldXform( void );
- void restoreToDefaultXform( void );
void setDefaultFromCurrentXform( void );
void storeCurrentXform( const LLVector3& pos );
@@ -195,8 +195,8 @@ public:
//If the old transform flag has been set, then the reset logic in avatar needs to be aware(test) of it
const BOOL doesJointNeedToBeReset( void ) const { return mResetAfterRestoreOldXform; }
- //Setter for joint reset flag
- void setJointToBeReset( BOOL val ) { mResetAfterRestoreOldXform = val; }
+ void setJointResetFlag( bool val ) { mResetAfterRestoreOldXform = val; }
+
};
#endif // LL_LLJOINT_H
diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp
index 50ccfd75fb..e02b139608 100755
--- a/indra/llcharacter/llmotioncontroller.cpp
+++ b/indra/llcharacter/llmotioncontroller.cpp
@@ -172,6 +172,13 @@ void LLMotionController::deleteAllMotions()
for_each(mAllMotions.begin(), mAllMotions.end(), DeletePairedPointer());
mAllMotions.clear();
+
+ // stinson 05/12/20014 : Ownership of the LLMotion pointers is transferred from
+ // mAllMotions to mDeprecatedMotions in method
+ // LLMotionController::deprecateMotionInstance(). Thus, we should also clean
+ // up the mDeprecatedMotions list as well.
+ for_each(mDeprecatedMotions.begin(), mDeprecatedMotions.end(), DeletePointer());
+ mDeprecatedMotions.clear();
}
//-----------------------------------------------------------------------------
diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp
index 0df7fb2bc3..2235496ac5 100755
--- a/indra/llcharacter/llvisualparam.cpp
+++ b/indra/llcharacter/llvisualparam.cpp
@@ -159,26 +159,42 @@ void LLVisualParamInfo::toStream(std::ostream &out)
//-----------------------------------------------------------------------------
// LLVisualParam()
//-----------------------------------------------------------------------------
-LLVisualParam::LLVisualParam()
- :
- mCurWeight( 0.f ),
+LLVisualParam::LLVisualParam()
+ : mCurWeight( 0.f ),
mLastWeight( 0.f ),
mNext( NULL ),
mTargetWeight( 0.f ),
mIsAnimating( FALSE ),
+ mIsDummy(FALSE),
mID( -1 ),
mInfo( 0 ),
- mIsDummy(FALSE),
mParamLocation(LOC_UNKNOWN)
{
}
//-----------------------------------------------------------------------------
+// LLVisualParam()
+//-----------------------------------------------------------------------------
+LLVisualParam::LLVisualParam(const LLVisualParam& pOther)
+ : mCurWeight(pOther.mCurWeight),
+ mLastWeight(pOther.mLastWeight),
+ mNext(pOther.mNext),
+ mTargetWeight(pOther.mTargetWeight),
+ mIsAnimating(pOther.mIsAnimating),
+ mIsDummy(pOther.mIsDummy),
+ mID(pOther.mID),
+ mInfo(pOther.mInfo),
+ mParamLocation(pOther.mParamLocation)
+{
+}
+
+//-----------------------------------------------------------------------------
// ~LLVisualParam()
//-----------------------------------------------------------------------------
LLVisualParam::~LLVisualParam()
{
delete mNext;
+ mNext = NULL;
}
/*
@@ -220,7 +236,7 @@ BOOL LLVisualParam::parseData(LLXmlTreeNode *node)
//-----------------------------------------------------------------------------
// setWeight()
//-----------------------------------------------------------------------------
-void LLVisualParam::setWeight(F32 weight, BOOL upload_bake)
+void LLVisualParam::setWeight(F32 weight)
{
if (mIsAnimating)
{
@@ -238,19 +254,19 @@ void LLVisualParam::setWeight(F32 weight, BOOL upload_bake)
if (mNext)
{
- mNext->setWeight(weight, upload_bake);
+ mNext->setWeight(weight);
}
}
//-----------------------------------------------------------------------------
// setAnimationTarget()
//-----------------------------------------------------------------------------
-void LLVisualParam::setAnimationTarget(F32 target_value, BOOL upload_bake)
+void LLVisualParam::setAnimationTarget(F32 target_value)
{
// don't animate dummy parameters
if (mIsDummy)
{
- setWeight(target_value, upload_bake);
+ setWeight(target_value);
mTargetWeight = mCurWeight;
return;
}
@@ -270,7 +286,7 @@ void LLVisualParam::setAnimationTarget(F32 target_value, BOOL upload_bake)
if (mNext)
{
- mNext->setAnimationTarget(target_value, upload_bake);
+ mNext->setAnimationTarget(target_value);
}
}
@@ -285,26 +301,34 @@ void LLVisualParam::setNextParam( LLVisualParam *next )
}
//-----------------------------------------------------------------------------
+// clearNextParam()
+//-----------------------------------------------------------------------------
+void LLVisualParam::clearNextParam()
+{
+ mNext = NULL;
+}
+
+//-----------------------------------------------------------------------------
// animate()
//-----------------------------------------------------------------------------
-void LLVisualParam::animate( F32 delta, BOOL upload_bake )
+void LLVisualParam::animate( F32 delta)
{
if (mIsAnimating)
{
F32 new_weight = ((mTargetWeight - mCurWeight) * delta) + mCurWeight;
- setWeight(new_weight, upload_bake);
+ setWeight(new_weight);
}
}
//-----------------------------------------------------------------------------
// stopAnimating()
//-----------------------------------------------------------------------------
-void LLVisualParam::stopAnimating(BOOL upload_bake)
+void LLVisualParam::stopAnimating()
{
if (mIsAnimating && isTweakable())
{
mIsAnimating = FALSE;
- setWeight(mTargetWeight, upload_bake);
+ setWeight(mTargetWeight);
}
}
diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h
index a4d9f93e56..c6b97d7e8b 100755
--- a/indra/llcharacter/llvisualparam.h
+++ b/indra/llcharacter/llvisualparam.h
@@ -120,10 +120,10 @@ public:
//virtual BOOL parseData( LLXmlTreeNode *node ) = 0;
virtual void apply( ESex avatar_sex ) = 0;
// Default functions
- virtual void setWeight(F32 weight, BOOL upload_bake);
- virtual void setAnimationTarget( F32 target_value, BOOL upload_bake );
- virtual void animate(F32 delta, BOOL upload_bake);
- virtual void stopAnimating(BOOL upload_bake);
+ virtual void setWeight(F32 weight);
+ virtual void setAnimationTarget( F32 target_value);
+ virtual void animate(F32 delta);
+ virtual void stopAnimating();
virtual BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params);
virtual void resetDrivenParams();
@@ -155,6 +155,7 @@ public:
LLVisualParam* getNextParam() { return mNext; }
void setNextParam( LLVisualParam *next );
+ void clearNextParam();
virtual void setAnimating(BOOL is_animating) { mIsAnimating = is_animating && !mIsDummy; }
BOOL getAnimating() const { return mIsAnimating; }
@@ -165,6 +166,8 @@ public:
EParamLocation getParamLocation() const { return mParamLocation; }
protected:
+ LLVisualParam(const LLVisualParam& pOther);
+
F32 mCurWeight; // current weight
F32 mLastWeight; // last weight
LLVisualParam* mNext; // next param in a shared chain
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 5856e06b67..8eeb186936 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -158,7 +158,6 @@ set(llcommon_HEADER_FILES
llhandle.h
llhash.h
llheartbeat.h
- llhttpstatuscodes.h
llindexedvector.h
llinitparam.h
llinstancetracker.h
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index a7963174ad..22cd861c72 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -47,6 +47,7 @@
#include "lllivefile.h"
#include "llsd.h"
#include "llsdserialize.h"
+#include "llsingleton.h"
#include "llstl.h"
#include "lltimer.h"
@@ -356,30 +357,31 @@ namespace
typedef std::map<std::string, LLError::ELevel> LevelMap;
- typedef std::vector<LLError::Recorder*> Recorders;
+ typedef std::vector<LLError::RecorderPtr> Recorders;
typedef std::vector<LLError::CallSite*> CallSiteVector;
- class Globals
+ class Globals : public LLSingleton<Globals>
{
public:
+ Globals();
+
std::ostringstream messageStream;
bool messageStreamInUse;
void addCallSite(LLError::CallSite&);
void invalidateCallSites();
-
- static Globals& get();
- // return the one instance of the globals
private:
CallSiteVector callSites;
-
- Globals()
- : messageStreamInUse(false)
- { }
-
};
+ Globals::Globals()
+ : messageStream(),
+ messageStreamInUse(false),
+ callSites()
+ {
+ }
+
void Globals::addCallSite(LLError::CallSite& site)
{
callSites.push_back(&site);
@@ -396,25 +398,17 @@ namespace
callSites.clear();
}
-
- Globals& Globals::get()
- {
- /* This pattern, of returning a reference to a static function
- variable, is to ensure that this global is constructed before
- it is used, no matter what the global initialization sequence
- is.
- See C++ FAQ Lite, sections 10.12 through 10.14
- */
- static Globals* globals = new Globals;
- return *globals;
- }
}
namespace LLError
{
- class Settings
+ class SettingsConfig : public LLRefCount
{
+ friend class Settings;
+
public:
+ virtual ~SettingsConfig();
+
bool mPrintLocation;
LLError::ELevel mDefaultLevel;
@@ -429,81 +423,86 @@ namespace LLError
LLError::TimeFunction mTimeFunction;
Recorders mRecorders;
- Recorder* mFileRecorder;
- Recorder* mFixedBufferRecorder;
+ RecorderPtr mFileRecorder;
+ RecorderPtr mFixedBufferRecorder;
std::string mFileRecorderFileName;
int mShouldLogCallCounter;
- static Settings& get();
+ private:
+ SettingsConfig();
+ };
+
+ typedef LLPointer<SettingsConfig> SettingsConfigPtr;
+
+ class Settings : public LLSingleton<Settings>
+ {
+ public:
+ Settings();
+
+ SettingsConfigPtr getSettingsConfig();
- static void reset();
- static Settings* saveAndReset();
- static void restore(Settings*);
+ void reset();
+ SettingsStoragePtr saveAndReset();
+ void restore(SettingsStoragePtr pSettingsStorage);
private:
- Settings()
- : mPrintLocation(false),
- mDefaultLevel(LLError::LEVEL_DEBUG),
- mCrashFunction(),
- mTimeFunction(NULL),
- mFileRecorder(NULL),
- mFixedBufferRecorder(NULL),
- mShouldLogCallCounter(0)
- { }
-
- ~Settings()
- {
- for_each(mRecorders.begin(), mRecorders.end(), DeletePointer());
- mRecorders.clear();
- }
-
- static Settings*& getPtr();
+ SettingsConfigPtr mSettingsConfig;
};
- Settings& Settings::get()
+ SettingsConfig::SettingsConfig()
+ : LLRefCount(),
+ mPrintLocation(false),
+ mDefaultLevel(LLError::LEVEL_DEBUG),
+ mFunctionLevelMap(),
+ mClassLevelMap(),
+ mFileLevelMap(),
+ mTagLevelMap(),
+ mUniqueLogMessages(),
+ mCrashFunction(NULL),
+ mTimeFunction(NULL),
+ mRecorders(),
+ mFileRecorder(),
+ mFixedBufferRecorder(),
+ mFileRecorderFileName(),
+ mShouldLogCallCounter(0)
{
- Settings* p = getPtr();
- if (!p)
- {
- reset();
- p = getPtr();
- }
- return *p;
}
-
- void Settings::reset()
+
+ SettingsConfig::~SettingsConfig()
{
- Globals::get().invalidateCallSites();
-
- Settings*& p = getPtr();
- delete p;
- p = new Settings();
+ mRecorders.clear();
+ }
+
+ Settings::Settings()
+ : LLSingleton<Settings>(),
+ mSettingsConfig(new SettingsConfig())
+ {
+ }
+
+ SettingsConfigPtr Settings::getSettingsConfig()
+ {
+ return mSettingsConfig;
}
- Settings* Settings::saveAndReset()
+ void Settings::reset()
{
- Globals::get().invalidateCallSites();
-
- Settings*& p = getPtr();
- Settings* originalSettings = p;
- p = new Settings();
- return originalSettings;
+ Globals::getInstance()->invalidateCallSites();
+ mSettingsConfig = new SettingsConfig();
}
- void Settings::restore(Settings* originalSettings)
+ SettingsStoragePtr Settings::saveAndReset()
{
- Globals::get().invalidateCallSites();
-
- Settings*& p = getPtr();
- delete p;
- p = originalSettings;
+ SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get());
+ reset();
+ return oldSettingsConfig;
}
- Settings*& Settings::getPtr()
+ void Settings::restore(SettingsStoragePtr pSettingsStorage)
{
- static Settings* currentSettings = NULL;
- return currentSettings;
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get()));
+ mSettingsConfig = newSettingsConfig;
}
}
@@ -604,7 +603,7 @@ namespace
void commonInit(const std::string& dir, bool log_to_stderr = true)
{
- LLError::Settings::reset();
+ LLError::Settings::getInstance()->reset();
LLError::setDefaultLevel(LLError::LEVEL_INFO);
LLError::setFatalFunction(LLError::crashAndLoop);
@@ -613,11 +612,13 @@ namespace
// log_to_stderr is only false in the unit and integration tests to keep builds quieter
if (log_to_stderr && shouldLogToStderr())
{
- LLError::addRecorder(new RecordToStderr(stderrLogWantsTime()));
+ LLError::RecorderPtr recordToStdErr(new RecordToStderr(stderrLogWantsTime()));
+ LLError::addRecorder(recordToStdErr);
}
#if LL_WINDOWS
- LLError::addRecorder(new RecordToWinDebug);
+ LLError::RecorderPtr recordToWinDebug(new RecordToWinDebug());
+ LLError::addRecorder(recordToWinDebug);
#endif
LogControlFile& e = LogControlFile::fromDirectory(dir);
@@ -645,7 +646,8 @@ namespace LLError
}
commonInit(dir);
#if !LL_WINDOWS
- addRecorder(new RecordToSyslog(identity));
+ LLError::RecorderPtr recordToSyslog(new RecordToSyslog(identity));
+ addRecorder(recordToSyslog);
#endif
}
@@ -656,72 +658,67 @@ namespace LLError
void setPrintLocation(bool print)
{
- Settings& s = Settings::get();
- s.mPrintLocation = print;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mPrintLocation = print;
}
void setFatalFunction(const FatalFunction& f)
{
- Settings& s = Settings::get();
- s.mCrashFunction = f;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mCrashFunction = f;
}
FatalFunction getFatalFunction()
{
- Settings& s = Settings::get();
- return s.mCrashFunction;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ return s->mCrashFunction;
}
void setTimeFunction(TimeFunction f)
{
- Settings& s = Settings::get();
- s.mTimeFunction = f;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mTimeFunction = f;
}
void setDefaultLevel(ELevel level)
{
- Globals& g = Globals::get();
- Settings& s = Settings::get();
- g.invalidateCallSites();
- s.mDefaultLevel = level;
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mDefaultLevel = level;
}
ELevel getDefaultLevel()
{
- Settings& s = Settings::get();
- return s.mDefaultLevel;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ return s->mDefaultLevel;
}
void setFunctionLevel(const std::string& function_name, ELevel level)
{
- Globals& g = Globals::get();
- Settings& s = Settings::get();
- g.invalidateCallSites();
- s.mFunctionLevelMap[function_name] = level;
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mFunctionLevelMap[function_name] = level;
}
void setClassLevel(const std::string& class_name, ELevel level)
{
- Globals& g = Globals::get();
- Settings& s = Settings::get();
- g.invalidateCallSites();
- s.mClassLevelMap[class_name] = level;
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mClassLevelMap[class_name] = level;
}
void setFileLevel(const std::string& file_name, ELevel level)
{
- Globals& g = Globals::get();
- Settings& s = Settings::get();
- g.invalidateCallSites();
- s.mFileLevelMap[file_name] = level;
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mFileLevelMap[file_name] = level;
}
void setTagLevel(const std::string& tag_name, ELevel level)
{
- Globals& g = Globals::get();
- Settings& s = Settings::get();
- g.invalidateCallSites();
- s.mTagLevelMap[tag_name] = level;
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mTagLevelMap[tag_name] = level;
}
LLError::ELevel decodeLevel(std::string name)
@@ -765,15 +762,14 @@ namespace LLError
{
void configure(const LLSD& config)
{
- Globals& g = Globals::get();
- Settings& s = Settings::get();
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
- g.invalidateCallSites();
- s.mFunctionLevelMap.clear();
- s.mClassLevelMap.clear();
- s.mFileLevelMap.clear();
- s.mTagLevelMap.clear();
- s.mUniqueLogMessages.clear();
+ s->mFunctionLevelMap.clear();
+ s->mClassLevelMap.clear();
+ s->mFileLevelMap.clear();
+ s->mTagLevelMap.clear();
+ s->mUniqueLogMessages.clear();
setPrintLocation(config["print-location"]);
setDefaultLevel(decodeLevel(config["default-level"]));
@@ -786,10 +782,10 @@ namespace LLError
ELevel level = decodeLevel(entry["level"]);
- setLevels(s.mFunctionLevelMap, entry["functions"], level);
- setLevels(s.mClassLevelMap, entry["classes"], level);
- setLevels(s.mFileLevelMap, entry["files"], level);
- setLevels(s.mTagLevelMap, entry["tags"], level);
+ setLevels(s->mFunctionLevelMap, entry["functions"], level);
+ setLevels(s->mClassLevelMap, entry["classes"], level);
+ setLevels(s->mFileLevelMap, entry["files"], level);
+ setLevels(s->mTagLevelMap, entry["tags"], level);
}
}
}
@@ -803,10 +799,12 @@ namespace LLError
mWantsLevel(true),
mWantsLocation(false),
mWantsFunctionName(true)
- {}
+ {
+ }
Recorder::~Recorder()
- { }
+ {
+ }
bool Recorder::wantsTime()
{
@@ -837,25 +835,25 @@ namespace LLError
return mWantsFunctionName;
}
- void addRecorder(Recorder* recorder)
+ void addRecorder(RecorderPtr recorder)
{
- if (recorder == NULL)
+ if (!recorder)
{
return;
}
- Settings& s = Settings::get();
- s.mRecorders.push_back(recorder);
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mRecorders.push_back(recorder);
}
- void removeRecorder(Recorder* recorder)
+ void removeRecorder(RecorderPtr recorder)
{
- if (recorder == NULL)
+ if (!recorder)
{
return;
}
- Settings& s = Settings::get();
- s.mRecorders.erase(std::remove(s.mRecorders.begin(), s.mRecorders.end(), recorder),
- s.mRecorders.end());
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder),
+ s->mRecorders.end());
}
}
@@ -863,51 +861,47 @@ namespace LLError
{
void logToFile(const std::string& file_name)
{
- LLError::Settings& s = LLError::Settings::get();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
- removeRecorder(s.mFileRecorder);
- delete s.mFileRecorder;
- s.mFileRecorder = NULL;
- s.mFileRecorderFileName.clear();
+ removeRecorder(s->mFileRecorder);
+ s->mFileRecorder.reset();
+ s->mFileRecorderFileName.clear();
if (file_name.empty())
{
return;
}
- RecordToFile* f = new RecordToFile(file_name);
- if (!f->okay())
+ RecorderPtr recordToFile(new RecordToFile(file_name));
+ if (boost::dynamic_pointer_cast<RecordToFile>(recordToFile)->okay())
{
- delete f;
- return;
+ s->mFileRecorderFileName = file_name;
+ s->mFileRecorder = recordToFile;
+ addRecorder(recordToFile);
}
-
- s.mFileRecorderFileName = file_name;
- s.mFileRecorder = f;
- addRecorder(f);
}
void logToFixedBuffer(LLLineBuffer* fixedBuffer)
{
- LLError::Settings& s = LLError::Settings::get();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
- removeRecorder(s.mFixedBufferRecorder);
- delete s.mFixedBufferRecorder;
- s.mFixedBufferRecorder = NULL;
+ removeRecorder(s->mFixedBufferRecorder);
+ s->mFixedBufferRecorder.reset();
if (!fixedBuffer)
{
return;
}
- s.mFixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
- addRecorder(s.mFixedBufferRecorder);
+ RecorderPtr recordToFixedBuffer(new RecordToFixedBuffer(fixedBuffer));
+ s->mFixedBufferRecorder = recordToFixedBuffer;
+ addRecorder(recordToFixedBuffer);
}
std::string logFileName()
{
- LLError::Settings& s = LLError::Settings::get();
- return s.mFileRecorderFileName;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ return s->mFileRecorderFileName;
}
}
@@ -916,24 +910,24 @@ namespace
void writeToRecorders(const LLError::CallSite& site, const std::string& message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true)
{
LLError::ELevel level = site.mLevel;
- LLError::Settings& s = LLError::Settings::get();
+ LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig();
- for (Recorders::const_iterator i = s.mRecorders.begin();
- i != s.mRecorders.end();
+ for (Recorders::const_iterator i = s->mRecorders.begin();
+ i != s->mRecorders.end();
++i)
{
- LLError::Recorder* r = *i;
+ LLError::RecorderPtr r = *i;
std::ostringstream message_stream;
- if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation))
+ if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s->mPrintLocation))
{
message_stream << site.mLocationString << " ";
}
- if (show_time && r->wantsTime() && s.mTimeFunction != NULL)
+ if (show_time && r->wantsTime() && s->mTimeFunction != NULL)
{
- message_stream << s.mTimeFunction() << " ";
+ message_stream << s->mTimeFunction() << " ";
}
if (show_level && r->wantsLevel())
@@ -1060,10 +1054,9 @@ namespace LLError
return false;
}
- Globals& g = Globals::get();
- Settings& s = Settings::get();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
- s.mShouldLogCallCounter++;
+ s->mShouldLogCallCounter++;
const std::string& class_name = className(site.mClassInfo);
std::string function_name = functionName(site.mFunction);
@@ -1077,21 +1070,21 @@ namespace LLError
function_name = class_name + "::" + function_name;
}
- ELevel compareLevel = s.mDefaultLevel;
+ ELevel compareLevel = s->mDefaultLevel;
// The most specific match found will be used as the log level,
// since the computation short circuits.
// So, in increasing order of importance:
// Default < Tags < File < Class < Function
- checkLevelMap(s.mFunctionLevelMap, function_name, compareLevel)
- || checkLevelMap(s.mClassLevelMap, class_name, compareLevel)
- || checkLevelMap(s.mFileLevelMap, abbreviateFile(site.mFile), compareLevel)
+ checkLevelMap(s->mFunctionLevelMap, function_name, compareLevel)
+ || checkLevelMap(s->mClassLevelMap, class_name, compareLevel)
+ || checkLevelMap(s->mFileLevelMap, abbreviateFile(site.mFile), compareLevel)
|| (site.mTagCount > 0
- ? checkLevelMap(s.mTagLevelMap, site.mTags, site.mTagCount, compareLevel)
+ ? checkLevelMap(s->mTagLevelMap, site.mTags, site.mTagCount, compareLevel)
: false);
site.mCached = true;
- g.addCallSite(site);
+ Globals::getInstance()->addCallSite(site);
return site.mShouldLog = site.mLevel >= compareLevel;
}
@@ -1101,12 +1094,12 @@ namespace LLError
LogLock lock;
if (lock.ok())
{
- Globals& g = Globals::get();
+ Globals* g = Globals::getInstance();
- if (!g.messageStreamInUse)
+ if (!g->messageStreamInUse)
{
- g.messageStreamInUse = true;
- return &g.messageStream;
+ g->messageStreamInUse = true;
+ return &g->messageStream;
}
}
@@ -1131,13 +1124,12 @@ namespace LLError
message[127] = '\0' ;
}
- Globals& g = Globals::get();
-
- if (out == &g.messageStream)
+ Globals* g = Globals::getInstance();
+ if (out == &g->messageStream)
{
- g.messageStream.clear();
- g.messageStream.str("");
- g.messageStreamInUse = false;
+ g->messageStream.clear();
+ g->messageStream.str("");
+ g->messageStreamInUse = false;
}
else
{
@@ -1154,15 +1146,15 @@ namespace LLError
return;
}
- Globals& g = Globals::get();
- Settings& s = Settings::get();
+ Globals* g = Globals::getInstance();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
std::string message = out->str();
- if (out == &g.messageStream)
+ if (out == &g->messageStream)
{
- g.messageStream.clear();
- g.messageStream.str("");
- g.messageStreamInUse = false;
+ g->messageStream.clear();
+ g->messageStream.str("");
+ g->messageStreamInUse = false;
}
else
{
@@ -1178,8 +1170,8 @@ namespace LLError
if (site.mPrintOnce)
{
- std::map<std::string, unsigned int>::iterator messageIter = s.mUniqueLogMessages.find(message);
- if (messageIter != s.mUniqueLogMessages.end())
+ std::map<std::string, unsigned int>::iterator messageIter = s->mUniqueLogMessages.find(message);
+ if (messageIter != s->mUniqueLogMessages.end())
{
messageIter->second++;
unsigned int num_messages = messageIter->second;
@@ -1195,7 +1187,7 @@ namespace LLError
else
{
message_stream << "ONCE: ";
- s.mUniqueLogMessages[message] = 1;
+ s->mUniqueLogMessages[message] = 1;
}
}
@@ -1203,23 +1195,23 @@ namespace LLError
writeToRecorders(site, message_stream.str());
- if (site.mLevel == LEVEL_ERROR && s.mCrashFunction)
+ if (site.mLevel == LEVEL_ERROR && s->mCrashFunction)
{
- s.mCrashFunction(message_stream.str());
+ s->mCrashFunction(message_stream.str());
}
}
}
namespace LLError
{
- Settings* saveAndResetSettings()
+ SettingsStoragePtr saveAndResetSettings()
{
- return Settings::saveAndReset();
+ return Settings::getInstance()->saveAndReset();
}
- void restoreSettings(Settings* s)
+ void restoreSettings(SettingsStoragePtr pSettingsStorage)
{
- return Settings::restore(s);
+ return Settings::getInstance()->restore(pSettingsStorage);
}
std::string removePrefix(std::string& s, const std::string& p)
@@ -1265,8 +1257,8 @@ namespace LLError
int shouldLogCallCount()
{
- Settings& s = Settings::get();
- return s.mShouldLogCallCounter;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ return s->mShouldLogCallCounter;
}
#if LL_WINDOWS
@@ -1375,15 +1367,9 @@ namespace LLError
#endif
//static
- void LLCallStacks::push(const char* function, const int line)
+ void LLCallStacks::allocateStackBuffer()
{
- CallStacksLogLock lock;
- if (!lock.ok())
- {
- return;
- }
-
- if(!sBuffer)
+ if(sBuffer == NULL)
{
sBuffer = new char*[512] ;
sBuffer[0] = new char[512 * 128] ;
@@ -1393,6 +1379,31 @@ namespace LLError
}
sIndex = 0 ;
}
+ }
+
+ void LLCallStacks::freeStackBuffer()
+ {
+ if(sBuffer != NULL)
+ {
+ delete [] sBuffer[0] ;
+ delete [] sBuffer ;
+ sBuffer = NULL ;
+ }
+ }
+
+ //static
+ void LLCallStacks::push(const char* function, const int line)
+ {
+ CallStacksLogLock lock;
+ if (!lock.ok())
+ {
+ return;
+ }
+
+ if(sBuffer == NULL)
+ {
+ allocateStackBuffer();
+ }
if(sIndex > 511)
{
@@ -1424,15 +1435,9 @@ namespace LLError
return;
}
- if(!sBuffer)
+ if(sBuffer == NULL)
{
- sBuffer = new char*[512] ;
- sBuffer[0] = new char[512 * 128] ;
- for(S32 i = 1 ; i < 512 ; i++)
- {
- sBuffer[i] = sBuffer[i-1] + 128 ;
- }
- sIndex = 0 ;
+ allocateStackBuffer();
}
if(sIndex > 511)
@@ -1463,11 +1468,9 @@ namespace LLError
LL_INFOS() << " *************** END OF LL CALL STACKS *************** " << LL_ENDL;
}
- if(sBuffer)
+ if(sBuffer != NULL)
{
- delete[] sBuffer[0] ;
- delete[] sBuffer ;
- sBuffer = NULL ;
+ freeStackBuffer();
}
}
@@ -1477,5 +1480,10 @@ namespace LLError
sIndex = 0 ;
}
+ //static
+ void LLCallStacks::cleanup()
+ {
+ freeStackBuffer();
+ }
}
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index bc80e64423..63040e1772 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -261,6 +261,9 @@ namespace LLError
private:
static char** sBuffer ;
static S32 sIndex ;
+
+ static void allocateStackBuffer();
+ static void freeStackBuffer();
public:
static void push(const char* function, const int line) ;
@@ -268,6 +271,7 @@ namespace LLError
static void print() ;
static void clear() ;
static void end(std::ostringstream* _out) ;
+ static void cleanup();
};
}
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index aab695094c..56ac52e5de 100755
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -29,7 +29,10 @@
#define LL_LLERRORCONTROL_H
#include "llerror.h"
+#include "llpointer.h"
+#include "llrefcount.h"
#include "boost/function.hpp"
+#include "boost/shared_ptr.hpp"
#include <string>
class LLSD;
@@ -156,16 +159,14 @@ namespace LLError
mWantsFunctionName;
};
+ typedef boost::shared_ptr<Recorder> RecorderPtr;
+
/**
- * @NOTE: addRecorder() conveys ownership to the underlying Settings
- * object -- when destroyed, it will @em delete the passed Recorder*!
- */
- LL_COMMON_API void addRecorder(Recorder*);
- /**
- * @NOTE: removeRecorder() reclaims ownership of the Recorder*: its
- * lifespan becomes the caller's problem.
+ * @NOTE: addRecorder() and removeRecorder() uses the boost::shared_ptr to allow for shared ownership
+ * while still ensuring that the allocated memory is eventually freed
*/
- LL_COMMON_API void removeRecorder(Recorder*);
+ LL_COMMON_API void addRecorder(RecorderPtr);
+ LL_COMMON_API void removeRecorder(RecorderPtr);
// each error message is passed to each recorder via recordMessage()
LL_COMMON_API void logToFile(const std::string& filename);
@@ -182,9 +183,9 @@ namespace LLError
Utilities for use by the unit tests of LLError itself.
*/
- class Settings;
- LL_COMMON_API Settings* saveAndResetSettings();
- LL_COMMON_API void restoreSettings(Settings *);
+ typedef LLPointer<LLRefCount> SettingsStoragePtr;
+ LL_COMMON_API SettingsStoragePtr saveAndResetSettings();
+ LL_COMMON_API void restoreSettings(SettingsStoragePtr pSettingsStorage);
LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
LL_COMMON_API int shouldLogCallCount();
diff --git a/indra/llcommon/llhttpstatuscodes.h b/indra/llcommon/llhttpstatuscodes.h
deleted file mode 100755
index 0173461dad..0000000000
--- a/indra/llcommon/llhttpstatuscodes.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * @file llhttpstatuscodes.h
- * @brief Constants for HTTP status codes
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_HTTP_STATUS_CODES_H
-#define LL_HTTP_STATUS_CODES_H
-
-#include "stdtypes.h"
-
-// Standard errors from HTTP spec:
-// http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1
-const S32 HTTP_CONTINUE = 100;
-const S32 HTTP_SWITCHING_PROTOCOLS = 101;
-
-// Success
-const S32 HTTP_OK = 200;
-const S32 HTTP_CREATED = 201;
-const S32 HTTP_ACCEPTED = 202;
-const S32 HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
-const S32 HTTP_NO_CONTENT = 204;
-const S32 HTTP_RESET_CONTENT = 205;
-const S32 HTTP_PARTIAL_CONTENT = 206;
-
-// Redirection
-const S32 HTTP_MULTIPLE_CHOICES = 300;
-const S32 HTTP_MOVED_PERMANENTLY = 301;
-const S32 HTTP_FOUND = 302;
-const S32 HTTP_SEE_OTHER = 303;
-const S32 HTTP_NOT_MODIFIED = 304;
-const S32 HTTP_USE_PROXY = 305;
-const S32 HTTP_TEMPORARY_REDIRECT = 307;
-
-// Client Error
-const S32 HTTP_BAD_REQUEST = 400;
-const S32 HTTP_UNAUTHORIZED = 401;
-const S32 HTTP_PAYMENT_REQUIRED = 402;
-const S32 HTTP_FORBIDDEN = 403;
-const S32 HTTP_NOT_FOUND = 404;
-const S32 HTTP_METHOD_NOT_ALLOWED = 405;
-const S32 HTTP_NOT_ACCEPTABLE = 406;
-const S32 HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
-const S32 HTTP_REQUEST_TIME_OUT = 408;
-const S32 HTTP_CONFLICT = 409;
-const S32 HTTP_GONE = 410;
-const S32 HTTP_LENGTH_REQUIRED = 411;
-const S32 HTTP_PRECONDITION_FAILED = 412;
-const S32 HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
-const S32 HTTP_REQUEST_URI_TOO_LARGE = 414;
-const S32 HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
-const S32 HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
-const S32 HTTP_EXPECTATION_FAILED = 417;
-
-// Server Error
-const S32 HTTP_INTERNAL_SERVER_ERROR = 500;
-const S32 HTTP_NOT_IMPLEMENTED = 501;
-const S32 HTTP_BAD_GATEWAY = 502;
-const S32 HTTP_SERVICE_UNAVAILABLE = 503;
-const S32 HTTP_GATEWAY_TIME_OUT = 504;
-const S32 HTTP_VERSION_NOT_SUPPORTED = 505;
-
-// We combine internal process errors with status codes
-// These status codes should not be sent over the wire
-// and indicate something went wrong internally.
-// If you get these they are not normal.
-const S32 HTTP_INTERNAL_ERROR = 499;
-
-#endif
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index 2532566319..7aa87fcd0e 100755
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -31,6 +31,7 @@
#include <vector>
#include <list>
#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/unordered_map.hpp>
@@ -629,7 +630,7 @@ namespace LLInitParam
UserData* mUserData;
};
- typedef ParamDescriptor* ParamDescriptorPtr;
+ typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr;
// each derived Block class keeps a static data structure maintaining offsets to various params
class LL_COMMON_API BlockDescriptor
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index c9ebc70d19..9a6453ea48 100755
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -166,6 +166,132 @@ protected:
Type* mPointer;
};
+template <class Type> class LLConstPointer
+{
+public:
+ LLConstPointer() :
+ mPointer(NULL)
+ {
+ }
+
+ LLConstPointer(const Type* ptr) :
+ mPointer(ptr)
+ {
+ ref();
+ }
+
+ LLConstPointer(const LLConstPointer<Type>& ptr) :
+ mPointer(ptr.mPointer)
+ {
+ ref();
+ }
+
+ // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+ template<typename Subclass>
+ LLConstPointer(const LLConstPointer<Subclass>& ptr) :
+ mPointer(ptr.get())
+ {
+ ref();
+ }
+
+ ~LLConstPointer()
+ {
+ unref();
+ }
+
+ const Type* get() const { return mPointer; }
+ const Type* operator->() const { return mPointer; }
+ const Type& operator*() const { return *mPointer; }
+
+ operator BOOL() const { return (mPointer != NULL); }
+ operator bool() const { return (mPointer != NULL); }
+ bool operator!() const { return (mPointer == NULL); }
+ bool isNull() const { return (mPointer == NULL); }
+ bool notNull() const { return (mPointer != NULL); }
+
+ operator const Type*() const { return mPointer; }
+ bool operator !=(const Type* ptr) const { return (mPointer != ptr); }
+ bool operator ==(const Type* ptr) const { return (mPointer == ptr); }
+ bool operator ==(const LLConstPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
+ bool operator < (const LLConstPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
+ bool operator > (const LLConstPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
+
+ LLConstPointer<Type>& operator =(const Type* ptr)
+ {
+ if( mPointer != ptr )
+ {
+ unref();
+ mPointer = ptr;
+ ref();
+ }
+
+ return *this;
+ }
+
+ LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr)
+ {
+ if( mPointer != ptr.mPointer )
+ {
+ unref();
+ mPointer = ptr.mPointer;
+ ref();
+ }
+ return *this;
+ }
+
+ // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+ template<typename Subclass>
+ LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr)
+ {
+ if( mPointer != ptr.get() )
+ {
+ unref();
+ mPointer = ptr.get();
+ ref();
+ }
+ return *this;
+ }
+
+ // Just exchange the pointers, which will not change the reference counts.
+ static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b)
+ {
+ const Type* temp = a.mPointer;
+ a.mPointer = b.mPointer;
+ b.mPointer = temp;
+ }
+
+protected:
+#ifdef LL_LIBRARY_INCLUDE
+ void ref();
+ void unref();
+#else
+ void ref()
+ {
+ if (mPointer)
+ {
+ mPointer->ref();
+ }
+ }
+
+ void unref()
+ {
+ if (mPointer)
+ {
+ const Type *tempp = mPointer;
+ mPointer = NULL;
+ tempp->unref();
+ if (mPointer != NULL)
+ {
+ LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
+ unref();
+ }
+ }
+ }
+#endif
+protected:
+ const Type* mPointer;
+};
+
template<typename Type>
class LLCopyOnWritePointer : public LLPointer<Type>
{
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index f962485284..d8bbb3a74f 100755
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -126,7 +126,9 @@ public:
virtual UUID asUUID() const { return LLUUID(); }
virtual Date asDate() const { return LLDate(); }
virtual URI asURI() const { return LLURI(); }
- virtual Binary asBinary() const { return std::vector<U8>(); }
+ virtual const Binary& asBinary() const { static const std::vector<U8> empty; return empty; }
+
+ virtual const String& asStringRef() const { static const std::string empty; return empty; }
virtual bool has(const String&) const { return false; }
virtual LLSD get(const String&) const { return LLSD(); }
@@ -270,6 +272,7 @@ namespace
virtual LLSD::Date asDate() const { return LLDate(mValue); }
virtual LLSD::URI asURI() const { return LLURI(mValue); }
virtual int size() const { return mValue.size(); }
+ virtual const LLSD::String& asStringRef() const { return mValue; }
};
LLSD::Integer ImplString::asInteger() const
@@ -348,7 +351,7 @@ namespace
public:
ImplBinary(const LLSD::Binary& v) : Base(v) { }
- virtual LLSD::Binary asBinary() const{ return mValue; }
+ virtual const LLSD::Binary& asBinary() const{ return mValue; }
};
@@ -840,7 +843,9 @@ LLSD::String LLSD::asString() const { return safe(impl).asString(); }
LLSD::UUID LLSD::asUUID() const { return safe(impl).asUUID(); }
LLSD::Date LLSD::asDate() const { return safe(impl).asDate(); }
LLSD::URI LLSD::asURI() const { return safe(impl).asURI(); }
-LLSD::Binary LLSD::asBinary() const { return safe(impl).asBinary(); }
+const LLSD::Binary& LLSD::asBinary() const { return safe(impl).asBinary(); }
+
+const LLSD::String& LLSD::asStringRef() const { return safe(impl).asStringRef(); }
// const char * helpers
LLSD::LLSD(const char* v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index deb87d7497..7b9b1285f5 100755
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -249,7 +249,10 @@ public:
UUID asUUID() const;
Date asDate() const;
URI asURI() const;
- Binary asBinary() const;
+ const Binary& asBinary() const;
+
+ // asStringRef on any non-string type will return a ref to an empty string.
+ const String& asStringRef() const;
operator Boolean() const { return asBoolean(); }
operator Integer() const { return asInteger(); }
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 04d7a6ed56..d49ff0feb5 100755
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -34,7 +34,7 @@
#include <iostream>
#include "apr_base64.h"
-#ifdef LL_STANDALONE
+#ifdef LL_USESYSTEMLIBS
# include <zlib.h>
#else
# include "zlib/zlib.h" // for davep's dirty little zip functions
@@ -873,7 +873,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
{
/**
* Undefined: '!'<br>
- * Boolean: 't' for true 'f' for false<br>
+ * Boolean: '1' for true '0' for false<br>
* Integer: 'i' + 4 bytes network byte order<br>
* Real: 'r' + 8 bytes IEEE double<br>
* UUID: 'u' + 16 byte unsigned integer<br>
@@ -1261,12 +1261,37 @@ std::string LLSDNotationFormatter::escapeString(const std::string& in)
// virtual
S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
{
+ S32 rv = format_impl(data, ostr, options, 0);
+ return rv;
+}
+
+S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const
+{
S32 format_count = 1;
+ std::string pre;
+ std::string post;
+
+ if (options & LLSDFormatter::OPTIONS_PRETTY)
+ {
+ for (U32 i = 0; i < level; i++)
+ {
+ pre += " ";
+ }
+ post = "\n";
+ }
+
switch(data.type())
{
case LLSD::TypeMap:
{
+ if (0 != level) ostr << post << pre;
ostr << "{";
+ std::string inner_pre;
+ if (options & LLSDFormatter::OPTIONS_PRETTY)
+ {
+ inner_pre = pre + " ";
+ }
+
bool need_comma = false;
LLSD::map_const_iterator iter = data.beginMap();
LLSD::map_const_iterator end = data.endMap();
@@ -1274,18 +1299,18 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti
{
if(need_comma) ostr << ",";
need_comma = true;
- ostr << '\'';
+ ostr << post << inner_pre << '\'';
serialize_string((*iter).first, ostr);
ostr << "':";
- format_count += format((*iter).second, ostr);
+ format_count += format_impl((*iter).second, ostr, options, level + 2);
}
- ostr << "}";
+ ostr << post << pre << "}";
break;
}
case LLSD::TypeArray:
{
- ostr << "[";
+ ostr << post << pre << "[";
bool need_comma = false;
LLSD::array_const_iterator iter = data.beginArray();
LLSD::array_const_iterator end = data.endArray();
@@ -1293,7 +1318,7 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti
{
if(need_comma) ostr << ",";
need_comma = true;
- format_count += format(*iter, ostr);
+ format_count += format_impl(*iter, ostr, options, level + 1);
}
ostr << "]";
break;
@@ -1343,7 +1368,7 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti
case LLSD::TypeString:
ostr << '\'';
- serialize_string(data.asString(), ostr);
+ serialize_string(data.asStringRef(), ostr);
ostr << '\'';
break;
@@ -1360,9 +1385,26 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti
case LLSD::TypeBinary:
{
// *FIX: memory inefficient.
- std::vector<U8> buffer = data.asBinary();
+ const std::vector<U8>& buffer = data.asBinary();
ostr << "b(" << buffer.size() << ")\"";
- if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
+ if(buffer.size())
+ {
+ if (options & LLSDFormatter::OPTIONS_PRETTY_BINARY)
+ {
+ std::ios_base::fmtflags old_flags = ostr.flags();
+ ostr.setf( std::ios::hex, std::ios::basefield );
+ ostr << "0x";
+ for (int i = 0; i < buffer.size(); i++)
+ {
+ ostr << (int) buffer[i];
+ }
+ ostr.flags(old_flags);
+ }
+ else
+ {
+ ostr.write((const char*)&buffer[0], buffer.size());
+ }
+ }
ostr << "\"";
break;
}
@@ -1460,7 +1502,7 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option
case LLSD::TypeString:
ostr.put('s');
- formatString(data.asString(), ostr);
+ formatString(data.asStringRef(), ostr);
break;
case LLSD::TypeDate:
@@ -1478,9 +1520,8 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option
case LLSD::TypeBinary:
{
- // *FIX: memory inefficient.
ostr.put('b');
- std::vector<U8> buffer = data.asBinary();
+ const std::vector<U8>& buffer = data.asBinary();
U32 size_nbo = htonl(buffer.size());
ostr.write((const char*)(&size_nbo), sizeof(U32));
if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index e7a5507385..23a0c8cfb1 100755
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -416,7 +416,8 @@ public:
typedef enum e_formatter_options_type
{
OPTIONS_NONE = 0,
- OPTIONS_PRETTY = 1
+ OPTIONS_PRETTY = 1,
+ OPTIONS_PRETTY_BINARY = 2
} EFormatterOptions;
/**
@@ -507,6 +508,17 @@ public:
* @return Returns The number of LLSD objects fomatted out
*/
virtual S32 format(const LLSD& data, std::ostream& ostr, U32 options = LLSDFormatter::OPTIONS_NONE) const;
+
+protected:
+
+ /**
+ * @brief Implementation to format the data. This is called recursively.
+ *
+ * @param data The data to write.
+ * @param ostr The destination stream for the data.
+ * @return Returns The number of LLSD objects fomatted out
+ */
+ S32 format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const;
};
@@ -634,7 +646,7 @@ protected:
* </code>
*
* *NOTE - formerly this class inherited from its template parameter Formatter,
- * but all insnatiations passed in LLRefCount subclasses. This conflicted with
+ * but all instantiations passed in LLRefCount subclasses. This conflicted with
* the auto allocation intended for this class template (demonstrated in the
* example above). -brad
*/
@@ -720,6 +732,18 @@ public:
LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
return f->format(sd, str, LLSDFormatter::OPTIONS_NONE);
}
+ static S32 toPrettyNotation(const LLSD& sd, std::ostream& str)
+ {
+ LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
+ return f->format(sd, str, LLSDFormatter::OPTIONS_PRETTY);
+ }
+ static S32 toPrettyBinaryNotation(const LLSD& sd, std::ostream& str)
+ {
+ LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
+ return f->format(sd, str,
+ LLSDFormatter::OPTIONS_PRETTY |
+ LLSDFormatter::OPTIONS_PRETTY_BINARY);
+ }
static S32 fromNotation(LLSD& sd, std::istream& str, S32 max_bytes)
{
LLPointer<LLSDNotationParser> p = new LLSDNotationParser;
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index 4e2af0e589..8d72a1c329 100755
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -35,7 +35,7 @@
extern "C"
{
-#ifdef LL_STANDALONE
+#ifdef LL_USESYSTEMLIBS
# include <expat.h>
#else
# include "expat/expat.h"
@@ -168,8 +168,8 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti
break;
case LLSD::TypeString:
- if(data.asString().empty()) ostr << pre << "<string />" << post;
- else ostr << pre << "<string>" << escapeString(data.asString()) <<"</string>" << post;
+ if(data.asStringRef().empty()) ostr << pre << "<string />" << post;
+ else ostr << pre << "<string>" << escapeString(data.asStringRef()) <<"</string>" << post;
break;
case LLSD::TypeDate:
@@ -182,7 +182,7 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti
case LLSD::TypeBinary:
{
- LLSD::Binary buffer = data.asBinary();
+ const LLSD::Binary& buffer = data.asBinary();
if(buffer.empty())
{
ostr << pre << "<binary />" << post;
@@ -375,13 +375,10 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
{
break;
}
+ count = get_till_eol(input, (char *)buffer, BUFFER_SIZE);
+ if (!count)
{
-
- count = get_till_eol(input, (char *)buffer, BUFFER_SIZE);
- if (!count)
- {
- break;
- }
+ break;
}
status = XML_ParseBuffer(mParser, count, false);
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index 803417d368..562fd26658 100755
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -182,7 +182,7 @@ char* ll_pretty_print_sd_ptr(const LLSD* sd)
char* ll_pretty_print_sd(const LLSD& sd)
{
- const U32 bufferSize = 10 * 1024;
+ const U32 bufferSize = 100 * 1024;
static char buffer[bufferSize];
std::ostringstream stream;
//stream.rdbuf()->pubsetbuf(buffer, bufferSize);
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 07fe259e47..06e118aa44 100755
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -33,7 +33,7 @@
#include "llsys.h"
#include <iostream>
-#ifdef LL_STANDALONE
+#ifdef LL_USESYSTEMLIBS
# include <zlib.h>
#else
# include "zlib/zlib.h"
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index 0699dcda83..dd8660a3c8 100755
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -132,10 +132,14 @@ public:
};
typedef std::vector<LLUUID> uuid_vec_t;
+typedef std::set<LLUUID> uuid_set_t;
-
-// Helper structure for ordering lluuids in stl containers.
-// eg: std::map<LLUUID, LLWidget*, lluuid_less> widget_map;
+// Helper structure for ordering lluuids in stl containers. eg:
+// std::map<LLUUID, LLWidget*, lluuid_less> widget_map;
+//
+// (isn't this the default behavior anyway? I think we could
+// everywhere replace these with uuid_set_t, but someone should
+// verify.)
struct lluuid_less
{
bool operator()(const LLUUID& lhs, const LLUUID& rhs) const
@@ -145,7 +149,6 @@ struct lluuid_less
};
typedef std::set<LLUUID, lluuid_less> uuid_list_t;
-
/*
* Sub-classes for keeping transaction IDs and asset IDs
* straight.
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index b28c5ba4b3..a5aaff10c5 100755
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -56,9 +56,9 @@ namespace tut
{
public:
TestRecorder() { mWantsTime = false; }
- ~TestRecorder() { LLError::removeRecorder(this); }
+ virtual ~TestRecorder() { }
- void recordMessage(LLError::ELevel level,
+ virtual void recordMessage(LLError::ELevel level,
const std::string& message)
{
mMessages.push_back(message);
@@ -85,15 +85,11 @@ namespace tut
struct ErrorTestData
{
- // addRecorder() expects to be able to later delete the passed
- // Recorder*. Even though removeRecorder() reclaims ownership, passing
- // a pointer to a data member rather than a heap Recorder subclass
- // instance would just be Wrong.
- TestRecorder* mRecorder;
- LLError::Settings* mPriorErrorSettings;
+ LLError::RecorderPtr mRecorder;
+ LLError::SettingsStoragePtr mPriorErrorSettings;
ErrorTestData():
- mRecorder(new TestRecorder)
+ mRecorder(new TestRecorder())
{
fatalWasCalled = false;
@@ -106,13 +102,32 @@ namespace tut
~ErrorTestData()
{
LLError::removeRecorder(mRecorder);
- delete mRecorder;
LLError::restoreSettings(mPriorErrorSettings);
}
+ int countMessages()
+ {
+ return boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->countMessages();
+ }
+
+ void clearMessages()
+ {
+ boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->clearMessages();
+ }
+
+ void setWantsTime(bool t)
+ {
+ boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->setWantsTime(t);
+ }
+
+ std::string message(int n)
+ {
+ return boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->message(n);
+ }
+
void ensure_message_count(int expectedCount)
{
- ensure_equals("message count", mRecorder->countMessages(), expectedCount);
+ ensure_equals("message count", countMessages(), expectedCount);
}
void ensure_message_contains(int n, const std::string& expectedText)
@@ -120,7 +135,7 @@ namespace tut
std::ostringstream test_name;
test_name << "testing message " << n;
- ensure_contains(test_name.str(), mRecorder->message(n), expectedText);
+ ensure_contains(test_name.str(), message(n), expectedText);
}
void ensure_message_does_not_contain(int n, const std::string& expectedText)
@@ -128,7 +143,7 @@ namespace tut
std::ostringstream test_name;
test_name << "testing message " << n;
- ensure_does_not_contain(test_name.str(), mRecorder->message(n), expectedText);
+ ensure_does_not_contain(test_name.str(), message(n), expectedText);
}
};
@@ -385,15 +400,15 @@ namespace
}
typedef std::string (*LogFromFunction)(bool);
- void testLogName(tut::TestRecorder* recorder, LogFromFunction f,
+ void testLogName(LLError::RecorderPtr recorder, LogFromFunction f,
const std::string& class_name = "")
{
- recorder->clearMessages();
+ boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->clearMessages();
std::string name = f(false);
f(true);
- std::string messageWithoutName = recorder->message(0);
- std::string messageWithName = recorder->message(1);
+ std::string messageWithoutName = boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(0);
+ std::string messageWithName = boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(1);
ensure_has(name + " logged without name",
messageWithoutName, name);
@@ -528,12 +543,12 @@ namespace tut
{
LLError::setTimeFunction(roswell);
- mRecorder->setWantsTime(false);
+ setWantsTime(false);
ufoSighting();
ensure_message_contains(0, "ufo");
ensure_message_does_not_contain(0, roswell());
- mRecorder->setWantsTime(true);
+ setWantsTime(true);
ufoSighting();
ensure_message_contains(1, "ufo");
ensure_message_contains(1, roswell());
@@ -545,13 +560,13 @@ namespace tut
{
LLError::setPrintLocation(true);
LLError::setTimeFunction(roswell);
- mRecorder->setWantsTime(true);
+ setWantsTime(true);
std::string location,
function;
writeReturningLocationAndFunction(location, function);
ensure_equals("order is location time type function message",
- mRecorder->message(0),
+ message(0),
location + roswell() + " INFO: " + function + ": apple");
}
@@ -559,19 +574,19 @@ namespace tut
// multiple recorders
void ErrorTestObject::test<11>()
{
- TestRecorder* altRecorder(new TestRecorder);
+ LLError::RecorderPtr altRecorder(new TestRecorder());
LLError::addRecorder(altRecorder);
LL_INFOS() << "boo" << LL_ENDL;
ensure_message_contains(0, "boo");
- ensure_equals("alt recorder count", altRecorder->countMessages(), 1);
- ensure_contains("alt recorder message 0", altRecorder->message(0), "boo");
+ ensure_equals("alt recorder count", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 1);
+ ensure_contains("alt recorder message 0", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(0), "boo");
LLError::setTimeFunction(roswell);
- TestRecorder* anotherRecorder(new TestRecorder);
- anotherRecorder->setWantsTime(true);
+ LLError::RecorderPtr anotherRecorder(new TestRecorder());
+ boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->setWantsTime(true);
LLError::addRecorder(anotherRecorder);
LL_INFOS() << "baz" << LL_ENDL;
@@ -579,10 +594,13 @@ namespace tut
std::string when = roswell();
ensure_message_does_not_contain(1, when);
- ensure_equals("alt recorder count", altRecorder->countMessages(), 2);
- ensure_does_not_contain("alt recorder message 1", altRecorder->message(1), when);
- ensure_equals("another recorder count", anotherRecorder->countMessages(), 1);
- ensure_contains("another recorder message 0", anotherRecorder->message(0), when);
+ ensure_equals("alt recorder count", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 2);
+ ensure_does_not_contain("alt recorder message 1", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(1), when);
+ ensure_equals("another recorder count", boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->countMessages(), 1);
+ ensure_contains("another recorder message 0", boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->message(0), when);
+
+ LLError::removeRecorder(altRecorder);
+ LLError::removeRecorder(anotherRecorder);
}
}
diff --git a/indra/llcommon/tests/stringize_test.cpp b/indra/llcommon/tests/stringize_test.cpp
index 3e4ca548e5..2a4ed44a67 100755
--- a/indra/llcommon/tests/stringize_test.cpp
+++ b/indra/llcommon/tests/stringize_test.cpp
@@ -95,7 +95,7 @@ namespace tut
ensure_equals(stringize(f), "3.14159");
ensure_equals(stringize(d), "3.14159");
ensure_equals(stringize(abc), "abc def");
- ensure_equals(stringize(def), "def ghi"); //Will generate llwarns due to narrowing.
+ ensure_equals(stringize(def), "def ghi"); //Will generate LL_WARNS() due to narrowing.
ensure_equals(stringize(llsd), "{'abc':'abc def','d':r3.14159,'i':i34}");
}
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index 3137bd8fea..785197ba11 100755
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -38,6 +38,7 @@
#include "stringize.h"
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
#include <list>
#include <string>
#include <stdexcept>
@@ -81,72 +82,29 @@ struct WrapLLErrs
}
std::string error;
- LLError::Settings* mPriorErrorSettings;
+ LLError::SettingsStoragePtr mPriorErrorSettings;
LLError::FatalFunction mPriorFatal;
};
/**
- * LLError::addRecorder() accepts ownership of the passed Recorder* -- it
- * expects to be able to delete it later. CaptureLog isa Recorder whose
- * pointer we want to be able to pass without any ownership implications.
- * For such cases, instantiate a new RecorderProxy(yourRecorder) and pass
- * that. Your heap RecorderProxy might later be deleted, but not yourRecorder.
- */
-class RecorderProxy: public LLError::Recorder
-{
-public:
- RecorderProxy(LLError::Recorder* recorder):
- mRecorder(recorder)
- {}
-
- virtual void recordMessage(LLError::ELevel level, const std::string& message)
- {
- mRecorder->recordMessage(level, message);
- }
-
- virtual bool wantsTime()
- {
- return mRecorder->wantsTime();
- }
-
-private:
- LLError::Recorder* mRecorder;
-};
-
-/**
* Capture log messages. This is adapted (simplified) from the one in
* llerror_test.cpp.
*/
-class CaptureLog : public LLError::Recorder, public boost::noncopyable
+class CaptureLogRecorder : public LLError::Recorder, public boost::noncopyable
{
public:
- CaptureLog(LLError::ELevel level=LLError::LEVEL_DEBUG):
- // Mostly what we're trying to accomplish by saving and resetting
- // LLError::Settings is to bypass the default RecordToStderr and
- // RecordToWinDebug Recorders. As these are visible only inside
- // llerror.cpp, we can't just call LLError::removeRecorder() with
- // each. For certain tests we need to produce, capture and examine
- // DEBUG log messages -- but we don't want to spam the user's console
- // with that output. If it turns out that saveAndResetSettings() has
- // some bad effect, give up and just let the DEBUG level log messages
- // display.
- mOldSettings(LLError::saveAndResetSettings()),
- mProxy(new RecorderProxy(this))
+ CaptureLogRecorder()
+ : LLError::Recorder(),
+ boost::noncopyable(),
+ mMessages()
{
- LLError::setFatalFunction(wouldHaveCrashed);
- LLError::setDefaultLevel(level);
- LLError::addRecorder(mProxy);
}
- ~CaptureLog()
+ virtual ~CaptureLogRecorder()
{
- LLError::removeRecorder(mProxy);
- delete mProxy;
- LLError::restoreSettings(mOldSettings);
}
- void recordMessage(LLError::ELevel level,
- const std::string& message)
+ virtual void recordMessage(LLError::ELevel level, const std::string& message)
{
mMessages.push_back(message);
}
@@ -154,7 +112,7 @@ public:
/// Don't assume the message we want is necessarily the LAST log message
/// emitted by the underlying code; search backwards through all messages
/// for the sought string.
- std::string messageWith(const std::string& search, bool required=true)
+ std::string messageWith(const std::string& search, bool required)
{
for (MessageList::const_reverse_iterator rmi(mMessages.rbegin()), rmend(mMessages.rend());
rmi != rmend; ++rmi)
@@ -187,14 +145,63 @@ public:
return out;
}
+private:
typedef std::list<std::string> MessageList;
MessageList mMessages;
- LLError::Settings* mOldSettings;
- LLError::Recorder* mProxy;
+};
+
+/**
+ * Capture log messages. This is adapted (simplified) from the one in
+ * llerror_test.cpp.
+ */
+class CaptureLog : public boost::noncopyable
+{
+public:
+ CaptureLog(LLError::ELevel level=LLError::LEVEL_DEBUG)
+ // Mostly what we're trying to accomplish by saving and resetting
+ // LLError::Settings is to bypass the default RecordToStderr and
+ // RecordToWinDebug Recorders. As these are visible only inside
+ // llerror.cpp, we can't just call LLError::removeRecorder() with
+ // each. For certain tests we need to produce, capture and examine
+ // DEBUG log messages -- but we don't want to spam the user's console
+ // with that output. If it turns out that saveAndResetSettings() has
+ // some bad effect, give up and just let the DEBUG level log messages
+ // display.
+ : boost::noncopyable(),
+ mOldSettings(LLError::saveAndResetSettings()),
+ mRecorder(new CaptureLogRecorder())
+ {
+ LLError::setFatalFunction(wouldHaveCrashed);
+ LLError::setDefaultLevel(level);
+ LLError::addRecorder(mRecorder);
+ }
+
+ ~CaptureLog()
+ {
+ LLError::removeRecorder(mRecorder);
+ LLError::restoreSettings(mOldSettings);
+ }
+
+ /// Don't assume the message we want is necessarily the LAST log message
+ /// emitted by the underlying code; search backwards through all messages
+ /// for the sought string.
+ std::string messageWith(const std::string& search, bool required=true)
+ {
+ return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->messageWith(search, required);
+ }
+
+ std::ostream& streamto(std::ostream& out) const
+ {
+ return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->streamto(out);
+ }
+
+private:
+ LLError::SettingsStoragePtr mOldSettings;
+ LLError::RecorderPtr mRecorder;
};
inline
-std::ostream& operator<<(std::ostream& out, const CaptureLog& log)
+std::ostream& operator<<(std::ostream& out, const CaptureLogRecorder& log)
{
return log.streamto(out);
}
diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index fc257fb0c1..e56bc84174 100755
--- a/indra/llcorehttp/_httplibcurl.cpp
+++ b/indra/llcorehttp/_httplibcurl.cpp
@@ -31,7 +31,7 @@
#include "_httpoprequest.h"
#include "_httppolicy.h"
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
namespace LLCore
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index 926031501e..43dd069bc6 100755
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -44,7 +44,7 @@
#include "_httplibcurl.h"
#include "_httpinternal.h"
-#include "llhttpstatuscodes.h"
+#include "llhttpconstants.h"
#include "llproxy.h"
namespace
@@ -531,6 +531,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, (void *) NULL);
check_curl_easy_code(code, CURLOPT_POSTFIELDS);
mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
+ // *TODO: Should this be 'Keep-Alive' ?
mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
}
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index c40deb2b72..7a97c16ea7 100755
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -52,17 +52,20 @@ BOOL gSent = false;
class LLCrashLoggerResponder : public LLHTTPClient::Responder
{
+ LOG_CLASS(LLCrashLoggerResponder);
public:
LLCrashLoggerResponder()
{
}
- virtual void error(U32 status, const std::string& reason)
+protected:
+ virtual void httpFailure()
{
+ LL_WARNS() << dumpResponse() << LL_ENDL;
gBreak = true;
}
- virtual void result(const LLSD& content)
+ virtual void httpSuccess()
{
gBreak = true;
gSent = true;
diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt
index e837b0cac2..293ada7548 100755
--- a/indra/llimage/CMakeLists.txt
+++ b/indra/llimage/CMakeLists.txt
@@ -27,6 +27,7 @@ set(llimage_SOURCE_FILES
llimage.cpp
llimagedimensionsinfo.cpp
llimagedxt.cpp
+ llimagefilter.cpp
llimagej2c.cpp
llimagejpeg.cpp
llimagepng.cpp
@@ -42,6 +43,7 @@ set(llimage_HEADER_FILES
llimagebmp.h
llimagedimensionsinfo.h
llimagedxt.h
+ llimagefilter.h
llimagej2c.h
llimagejpeg.h
llimagepng.h
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 1ca1bf55a6..d336eeaabc 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -452,18 +452,8 @@ void LLImageRaw::verticalFlip()
void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
{
// Find new sizes
- S32 new_width = MIN_IMAGE_SIZE;
- S32 new_height = MIN_IMAGE_SIZE;
-
- while( (new_width < getWidth()) && (new_width < max_dim) )
- {
- new_width <<= 1;
- }
-
- while( (new_height < getHeight()) && (new_height < max_dim) )
- {
- new_height <<= 1;
- }
+ S32 new_width = expandDimToPowerOfTwo(getWidth(), max_dim);
+ S32 new_height = expandDimToPowerOfTwo(getHeight(), max_dim);
scale( new_width, new_height, scale_image );
}
@@ -471,55 +461,61 @@ void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image)
{
// Find new sizes
- S32 new_width = max_dim;
- S32 new_height = max_dim;
-
- while( (new_width > getWidth()) && (new_width > MIN_IMAGE_SIZE) )
- {
- new_width >>= 1;
- }
-
- while( (new_height > getHeight()) && (new_height > MIN_IMAGE_SIZE) )
- {
- new_height >>= 1;
- }
+ S32 new_width = contractDimToPowerOfTwo(getWidth(), MIN_IMAGE_SIZE);
+ S32 new_height = contractDimToPowerOfTwo(getHeight(), MIN_IMAGE_SIZE);
scale( new_width, new_height, scale_image );
}
-void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
+// static
+S32 LLImageRaw::biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim)
{
// Strong bias towards rounding down (to save bandwidth)
// No bias would mean THRESHOLD == 1.5f;
- const F32 THRESHOLD = 1.75f;
-
+ const F32 THRESHOLD = 1.75f;
+
// Find new sizes
- S32 larger_w = max_dim; // 2^n >= mWidth
- S32 smaller_w = max_dim; // 2^(n-1) <= mWidth
- while( (smaller_w > getWidth()) && (smaller_w > MIN_IMAGE_SIZE) )
+ S32 larger_dim = max_dim; // 2^n >= curr_dim
+ S32 smaller_dim = max_dim; // 2^(n-1) <= curr_dim
+ while( (smaller_dim > curr_dim) && (smaller_dim > MIN_IMAGE_SIZE) )
{
- larger_w = smaller_w;
- smaller_w >>= 1;
+ larger_dim = smaller_dim;
+ smaller_dim >>= 1;
}
- S32 new_width = ( (F32)getWidth() / smaller_w > THRESHOLD ) ? larger_w : smaller_w;
+ return ( ((F32)curr_dim / (F32)smaller_dim) > THRESHOLD ) ? larger_dim : smaller_dim;
+}
+// static
+S32 LLImageRaw::expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim)
+{
+ S32 new_dim = MIN_IMAGE_SIZE;
+ while( (new_dim < curr_dim) && (new_dim < max_dim) )
+ {
+ new_dim <<= 1;
+ }
+ return new_dim;
+}
- S32 larger_h = max_dim; // 2^m >= mHeight
- S32 smaller_h = max_dim; // 2^(m-1) <= mHeight
- while( (smaller_h > getHeight()) && (smaller_h > MIN_IMAGE_SIZE) )
+// static
+S32 LLImageRaw::contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim)
+{
+ S32 new_dim = MAX_IMAGE_SIZE;
+ while( (new_dim > curr_dim) && (new_dim > min_dim) )
{
- larger_h = smaller_h;
- smaller_h >>= 1;
+ new_dim >>= 1;
}
- S32 new_height = ( (F32)getHeight() / smaller_h > THRESHOLD ) ? larger_h : smaller_h;
+ return new_dim;
+}
+void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
+{
+ // Find new sizes
+ S32 new_width = biasedDimToPowerOfTwo(getWidth(),max_dim);
+ S32 new_height = biasedDimToPowerOfTwo(getHeight(),max_dim);
scale( new_width, new_height );
}
-
-
-
// Calculates (U8)(255*(a/255.f)*(b/255.f) + 0.5f). Thanks, Jim Blinn!
inline U8 LLImageRaw::fastFractionalMult( U8 a, U8 b )
{
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index bf441a008a..cd3f76f1fd 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -209,6 +209,9 @@ public:
void verticalFlip();
+ static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
+ static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
+ static S32 contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim = MIN_IMAGE_SIZE);
void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
new file mode 100755
index 0000000000..3d0c488768
--- /dev/null
+++ b/indra/llimage/llimagefilter.cpp
@@ -0,0 +1,939 @@
+/**
+ * @file llimagefilter.cpp
+ * @brief Simple Image Filtering. See https://wiki.lindenlab.com/wiki/SL_Viewer_Image_Filters for complete documentation.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2014, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llimagefilter.h"
+
+#include "llmath.h"
+#include "v3color.h"
+#include "v4coloru.h"
+#include "m3math.h"
+#include "v3math.h"
+#include "llsdserialize.h"
+#include "llstring.h"
+
+//---------------------------------------------------------------------------
+// LLImageFilter
+//---------------------------------------------------------------------------
+
+LLImageFilter::LLImageFilter(const std::string& file_path) :
+ mFilterData(LLSD::emptyArray()),
+ mImage(NULL),
+ mHistoRed(NULL),
+ mHistoGreen(NULL),
+ mHistoBlue(NULL),
+ mHistoBrightness(NULL),
+ mStencilBlendMode(STENCIL_BLEND_MODE_BLEND),
+ mStencilShape(STENCIL_SHAPE_UNIFORM),
+ mStencilGamma(1.0),
+ mStencilMin(0.0),
+ mStencilMax(1.0)
+{
+ // Load filter description from file
+ llifstream filter_xml(file_path);
+ if (filter_xml.is_open())
+ {
+ // Load and parse the file
+ LLPointer<LLSDParser> parser = new LLSDXMLParser();
+ parser->parse(filter_xml, mFilterData, LLSDSerialize::SIZE_UNLIMITED);
+ filter_xml.close();
+ }
+}
+
+LLImageFilter::~LLImageFilter()
+{
+ mImage = NULL;
+ ll_aligned_free_16(mHistoRed);
+ ll_aligned_free_16(mHistoGreen);
+ ll_aligned_free_16(mHistoBlue);
+ ll_aligned_free_16(mHistoBrightness);
+}
+
+/*
+ *TODO
+ * Rename stencil to mask
+ * Improve perf: use LUT for alpha blending in uniform case
+ * Add gradient coloring as a filter
+ */
+
+//============================================================================
+// Apply the filter data to the image passed as parameter
+//============================================================================
+
+void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
+{
+ mImage = raw_image;
+
+ //std::cout << "Filter : size = " << mFilterData.size() << std::endl;
+ for (S32 i = 0; i < mFilterData.size(); ++i)
+ {
+ std::string filter_name = mFilterData[i][0].asString();
+ // Dump out the filter values (for debug)
+ //std::cout << "Filter : name = " << mFilterData[i][0].asString() << ", params = ";
+ //for (S32 j = 1; j < mFilterData[i].size(); ++j)
+ //{
+ // std::cout << mFilterData[i][j].asString() << ", ";
+ //}
+ //std::cout << std::endl;
+
+ if (filter_name == "stencil")
+ {
+ // Get the shape of the stencil, that is how the procedural alpha is computed geometrically
+ std::string filter_shape = mFilterData[i][1].asString();
+ EStencilShape shape = STENCIL_SHAPE_UNIFORM;
+ if (filter_shape == "uniform")
+ {
+ shape = STENCIL_SHAPE_UNIFORM;
+ }
+ else if (filter_shape == "gradient")
+ {
+ shape = STENCIL_SHAPE_GRADIENT;
+ }
+ else if (filter_shape == "vignette")
+ {
+ shape = STENCIL_SHAPE_VIGNETTE;
+ }
+ else if (filter_shape == "scanlines")
+ {
+ shape = STENCIL_SHAPE_SCAN_LINES;
+ }
+ // Get the blend mode of the stencil, that is how the effect is blended in the background through the stencil
+ std::string filter_mode = mFilterData[i][2].asString();
+ EStencilBlendMode mode = STENCIL_BLEND_MODE_BLEND;
+ if (filter_mode == "blend")
+ {
+ mode = STENCIL_BLEND_MODE_BLEND;
+ }
+ else if (filter_mode == "add")
+ {
+ mode = STENCIL_BLEND_MODE_ADD;
+ }
+ else if (filter_mode == "add_back")
+ {
+ mode = STENCIL_BLEND_MODE_ABACK;
+ }
+ else if (filter_mode == "fade")
+ {
+ mode = STENCIL_BLEND_MODE_FADE;
+ }
+ // Get the float params: mandatory min, max then the optional parameters (4 max)
+ F32 min = (F32)(mFilterData[i][3].asReal());
+ F32 max = (F32)(mFilterData[i][4].asReal());
+ F32 params[4] = {0.0, 0.0, 0.0, 0.0};
+ for (S32 j = 5; (j < mFilterData[i].size()) && (j < 9); j++)
+ {
+ params[j-5] = (F32)(mFilterData[i][j].asReal());
+ }
+ // Set the stencil
+ setStencil(shape,mode,min,max,params);
+ }
+ else if (filter_name == "sepia")
+ {
+ filterSepia();
+ }
+ else if (filter_name == "grayscale")
+ {
+ filterGrayScale();
+ }
+ else if (filter_name == "saturate")
+ {
+ filterSaturate((float)(mFilterData[i][1].asReal()));
+ }
+ else if (filter_name == "rotate")
+ {
+ filterRotate((float)(mFilterData[i][1].asReal()));
+ }
+ else if (filter_name == "gamma")
+ {
+ LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+ filterGamma((float)(mFilterData[i][1].asReal()),color);
+ }
+ else if (filter_name == "colorize")
+ {
+ LLColor3 color((float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()));
+ LLColor3 alpha((F32)(mFilterData[i][4].asReal()),(float)(mFilterData[i][5].asReal()),(float)(mFilterData[i][6].asReal()));
+ filterColorize(color,alpha);
+ }
+ else if (filter_name == "contrast")
+ {
+ LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+ filterContrast((float)(mFilterData[i][1].asReal()),color);
+ }
+ else if (filter_name == "brighten")
+ {
+ LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+ filterBrightness((float)(mFilterData[i][1].asReal()),color);
+ }
+ else if (filter_name == "darken")
+ {
+ LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+ filterBrightness((float)(-mFilterData[i][1].asReal()),color);
+ }
+ else if (filter_name == "linearize")
+ {
+ LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+ filterLinearize((float)(mFilterData[i][1].asReal()),color);
+ }
+ else if (filter_name == "posterize")
+ {
+ LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+ filterEqualize((S32)(mFilterData[i][1].asReal()),color);
+ }
+ else if (filter_name == "screen")
+ {
+ std::string screen_name = mFilterData[i][1].asString();
+ EScreenMode mode = SCREEN_MODE_2DSINE;
+ if (screen_name == "2Dsine")
+ {
+ mode = SCREEN_MODE_2DSINE;
+ }
+ else if (screen_name == "line")
+ {
+ mode = SCREEN_MODE_LINE;
+ }
+ filterScreen(mode,(F32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal()));
+ }
+ else if (filter_name == "blur")
+ {
+ LLMatrix3 kernel;
+ for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++)
+ for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+ kernel.mMatrix[i][j] = 1.0;
+ convolve(kernel,true,false);
+ }
+ else if (filter_name == "sharpen")
+ {
+ LLMatrix3 kernel;
+ for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
+ for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+ kernel.mMatrix[k][j] = -1.0;
+ kernel.mMatrix[1][1] = 9.0;
+ convolve(kernel,false,false);
+ }
+ else if (filter_name == "gradient")
+ {
+ LLMatrix3 kernel;
+ for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
+ for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+ kernel.mMatrix[k][j] = -1.0;
+ kernel.mMatrix[1][1] = 8.0;
+ convolve(kernel,false,true);
+ }
+ else if (filter_name == "convolve")
+ {
+ LLMatrix3 kernel;
+ S32 index = 1;
+ bool normalize = (mFilterData[i][index++].asReal() > 0.0);
+ bool abs_value = (mFilterData[i][index++].asReal() > 0.0);
+ for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
+ for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+ kernel.mMatrix[k][j] = mFilterData[i][index++].asReal();
+ convolve(kernel,normalize,abs_value);
+ }
+ else if (filter_name == "colortransform")
+ {
+ LLMatrix3 transform;
+ S32 index = 1;
+ for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
+ for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+ transform.mMatrix[k][j] = mFilterData[i][index++].asReal();
+ transform.transpose();
+ colorTransform(transform);
+ }
+ else
+ {
+ llwarns << "Filter unknown, cannot execute filter command : " << filter_name << llendl;
+ }
+ }
+}
+
+//============================================================================
+// Filter Primitives
+//============================================================================
+
+void LLImageFilter::blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue)
+{
+ F32 inv_alpha = 1.0 - alpha;
+ switch (mStencilBlendMode)
+ {
+ case STENCIL_BLEND_MODE_BLEND:
+ // Classic blend of incoming color with the background image
+ pixel[VRED] = inv_alpha * pixel[VRED] + alpha * red;
+ pixel[VGREEN] = inv_alpha * pixel[VGREEN] + alpha * green;
+ pixel[VBLUE] = inv_alpha * pixel[VBLUE] + alpha * blue;
+ break;
+ case STENCIL_BLEND_MODE_ADD:
+ // Add incoming color to the background image
+ pixel[VRED] = llclampb(pixel[VRED] + alpha * red);
+ pixel[VGREEN] = llclampb(pixel[VGREEN] + alpha * green);
+ pixel[VBLUE] = llclampb(pixel[VBLUE] + alpha * blue);
+ break;
+ case STENCIL_BLEND_MODE_ABACK:
+ // Add back background image to the incoming color
+ pixel[VRED] = llclampb(inv_alpha * pixel[VRED] + red);
+ pixel[VGREEN] = llclampb(inv_alpha * pixel[VGREEN] + green);
+ pixel[VBLUE] = llclampb(inv_alpha * pixel[VBLUE] + blue);
+ break;
+ case STENCIL_BLEND_MODE_FADE:
+ // Fade incoming color to black
+ pixel[VRED] = alpha * red;
+ pixel[VGREEN] = alpha * green;
+ pixel[VBLUE] = alpha * blue;
+ break;
+ }
+}
+
+void LLImageFilter::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue)
+{
+ const S32 components = mImage->getComponents();
+ llassert( components >= 1 && components <= 4 );
+
+ S32 width = mImage->getWidth();
+ S32 height = mImage->getHeight();
+
+ U8* dst_data = mImage->getData();
+ for (S32 j = 0; j < height; j++)
+ {
+ for (S32 i = 0; i < width; i++)
+ {
+ // Blend LUT value
+ blendStencil(getStencilAlpha(i,j), dst_data, lut_red[dst_data[VRED]], lut_green[dst_data[VGREEN]], lut_blue[dst_data[VBLUE]]);
+ dst_data += components;
+ }
+ }
+}
+
+void LLImageFilter::colorTransform(const LLMatrix3 &transform)
+{
+ const S32 components = mImage->getComponents();
+ llassert( components >= 1 && components <= 4 );
+
+ S32 width = mImage->getWidth();
+ S32 height = mImage->getHeight();
+
+ U8* dst_data = mImage->getData();
+ for (S32 j = 0; j < height; j++)
+ {
+ for (S32 i = 0; i < width; i++)
+ {
+ // Compute transform
+ LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE]));
+ LLVector3 dst = src * transform;
+ dst.clamp(0.0f,255.0f);
+
+ // Blend result
+ blendStencil(getStencilAlpha(i,j), dst_data, dst.mV[VRED], dst.mV[VGREEN], dst.mV[VBLUE]);
+ dst_data += components;
+ }
+ }
+}
+
+void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value)
+{
+ const S32 components = mImage->getComponents();
+ llassert( components >= 1 && components <= 4 );
+
+ // Compute normalization factors
+ F32 kernel_min = 0.0;
+ F32 kernel_max = 0.0;
+ for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++)
+ {
+ for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+ {
+ if (kernel.mMatrix[i][j] >= 0.0)
+ kernel_max += kernel.mMatrix[i][j];
+ else
+ kernel_min += kernel.mMatrix[i][j];
+ }
+ }
+ if (abs_value)
+ {
+ kernel_max = llabs(kernel_max);
+ kernel_min = llabs(kernel_min);
+ kernel_max = llmax(kernel_max,kernel_min);
+ kernel_min = 0.0;
+ }
+ F32 kernel_range = kernel_max - kernel_min;
+
+ // Allocate temporary buffers and initialize algorithm's data
+ S32 width = mImage->getWidth();
+ S32 height = mImage->getHeight();
+
+ U8* dst_data = mImage->getData();
+
+ S32 buffer_size = width * components;
+ llassert_always(buffer_size > 0);
+ std::vector<U8> even_buffer(buffer_size);
+ std::vector<U8> odd_buffer(buffer_size);
+
+ U8* south_data = dst_data + buffer_size;
+ U8* east_west_data;
+ U8* north_data;
+
+ // Line 0 : we set the line to 0 (debatable)
+ memcpy( &even_buffer[0], dst_data, buffer_size ); /* Flawfinder: ignore */
+ for (S32 i = 0; i < width; i++)
+ {
+ blendStencil(getStencilAlpha(i,0), dst_data, 0, 0, 0);
+ dst_data += components;
+ }
+ south_data += buffer_size;
+
+ // All other lines
+ for (S32 j = 1; j < (height-1); j++)
+ {
+ // We need to buffer 2 lines. We flip north and east-west (current) to avoid moving too much memory around
+ if (j % 2)
+ {
+ memcpy( &odd_buffer[0], dst_data, buffer_size ); /* Flawfinder: ignore */
+ east_west_data = &odd_buffer[0];
+ north_data = &even_buffer[0];
+ }
+ else
+ {
+ memcpy( &even_buffer[0], dst_data, buffer_size ); /* Flawfinder: ignore */
+ east_west_data = &even_buffer[0];
+ north_data = &odd_buffer[0];
+ }
+ // First pixel : set to 0
+ blendStencil(getStencilAlpha(0,j), dst_data, 0, 0, 0);
+ dst_data += components;
+ // Set pointers to kernel
+ U8* NW = north_data;
+ U8* N = NW+components;
+ U8* NE = N+components;
+ U8* W = east_west_data;
+ U8* C = W+components;
+ U8* E = C+components;
+ U8* SW = south_data;
+ U8* S = SW+components;
+ U8* SE = S+components;
+ // All other pixels
+ for (S32 i = 1; i < (width-1); i++)
+ {
+ // Compute convolution
+ LLVector3 dst;
+ dst.mV[VRED] = (kernel.mMatrix[0][0]*NW[VRED] + kernel.mMatrix[0][1]*N[VRED] + kernel.mMatrix[0][2]*NE[VRED] +
+ kernel.mMatrix[1][0]*W[VRED] + kernel.mMatrix[1][1]*C[VRED] + kernel.mMatrix[1][2]*E[VRED] +
+ kernel.mMatrix[2][0]*SW[VRED] + kernel.mMatrix[2][1]*S[VRED] + kernel.mMatrix[2][2]*SE[VRED]);
+ dst.mV[VGREEN] = (kernel.mMatrix[0][0]*NW[VGREEN] + kernel.mMatrix[0][1]*N[VGREEN] + kernel.mMatrix[0][2]*NE[VGREEN] +
+ kernel.mMatrix[1][0]*W[VGREEN] + kernel.mMatrix[1][1]*C[VGREEN] + kernel.mMatrix[1][2]*E[VGREEN] +
+ kernel.mMatrix[2][0]*SW[VGREEN] + kernel.mMatrix[2][1]*S[VGREEN] + kernel.mMatrix[2][2]*SE[VGREEN]);
+ dst.mV[VBLUE] = (kernel.mMatrix[0][0]*NW[VBLUE] + kernel.mMatrix[0][1]*N[VBLUE] + kernel.mMatrix[0][2]*NE[VBLUE] +
+ kernel.mMatrix[1][0]*W[VBLUE] + kernel.mMatrix[1][1]*C[VBLUE] + kernel.mMatrix[1][2]*E[VBLUE] +
+ kernel.mMatrix[2][0]*SW[VBLUE] + kernel.mMatrix[2][1]*S[VBLUE] + kernel.mMatrix[2][2]*SE[VBLUE]);
+ if (abs_value)
+ {
+ dst.mV[VRED] = llabs(dst.mV[VRED]);
+ dst.mV[VGREEN] = llabs(dst.mV[VGREEN]);
+ dst.mV[VBLUE] = llabs(dst.mV[VBLUE]);
+ }
+ if (normalize)
+ {
+ dst.mV[VRED] = (dst.mV[VRED] - kernel_min)/kernel_range;
+ dst.mV[VGREEN] = (dst.mV[VGREEN] - kernel_min)/kernel_range;
+ dst.mV[VBLUE] = (dst.mV[VBLUE] - kernel_min)/kernel_range;
+ }
+ dst.clamp(0.0f,255.0f);
+
+ // Blend result
+ blendStencil(getStencilAlpha(i,j), dst_data, dst.mV[VRED], dst.mV[VGREEN], dst.mV[VBLUE]);
+
+ // Next pixel
+ dst_data += components;
+ NW += components;
+ N += components;
+ NE += components;
+ W += components;
+ C += components;
+ E += components;
+ SW += components;
+ S += components;
+ SE += components;
+ }
+ // Last pixel : set to 0
+ blendStencil(getStencilAlpha(width-1,j), dst_data, 0, 0, 0);
+ dst_data += components;
+ south_data += buffer_size;
+ }
+
+ // Last line
+ for (S32 i = 0; i < width; i++)
+ {
+ blendStencil(getStencilAlpha(i,0), dst_data, 0, 0, 0);
+ dst_data += components;
+ }
+}
+
+void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const F32 angle)
+{
+ const S32 components = mImage->getComponents();
+ llassert( components >= 1 && components <= 4 );
+
+ S32 width = mImage->getWidth();
+ S32 height = mImage->getHeight();
+
+ F32 wave_length_pixels = wave_length * (F32)(height) / 2.0;
+ F32 sin = sinf(angle*DEG_TO_RAD);
+ F32 cos = cosf(angle*DEG_TO_RAD);
+
+ // Precompute the gamma table : gives us the gray level to use when cutting outside the screen (prevents strong aliasing on the screen)
+ U8 gamma[256];
+ for (S32 i = 0; i < 256; i++)
+ {
+ F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,1.0/4.0)));
+ gamma[i] = (U8)(255.0 * gamma_i);
+ }
+
+ U8* dst_data = mImage->getData();
+ for (S32 j = 0; j < height; j++)
+ {
+ for (S32 i = 0; i < width; i++)
+ {
+ // Compute screen value
+ F32 value = 0.0;
+ F32 di = 0.0;
+ F32 dj = 0.0;
+ switch (mode)
+ {
+ case SCREEN_MODE_2DSINE:
+ di = cos*i + sin*j;
+ dj = -sin*i + cos*j;
+ value = (sinf(2*F_PI*di/wave_length_pixels)*sinf(2*F_PI*dj/wave_length_pixels)+1.0)*255.0/2.0;
+ break;
+ case SCREEN_MODE_LINE:
+ dj = sin*i - cos*j;
+ value = (sinf(2*F_PI*dj/wave_length_pixels)+1.0)*255.0/2.0;
+ break;
+ }
+ U8 dst_value = (dst_data[VRED] >= (U8)(value) ? gamma[dst_data[VRED] - (U8)(value)] : 0);
+
+ // Blend result
+ blendStencil(getStencilAlpha(i,j), dst_data, dst_value, dst_value, dst_value);
+ dst_data += components;
+ }
+ }
+}
+
+//============================================================================
+// Procedural Stencils
+//============================================================================
+void LLImageFilter::setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params)
+{
+ mStencilShape = shape;
+ mStencilBlendMode = mode;
+ mStencilMin = llmin(llmax(min, -1.0f), 1.0f);
+ mStencilMax = llmin(llmax(max, -1.0f), 1.0f);
+
+ // Each shape will interpret the 4 params differenly.
+ // We compute each systematically, though, clearly, values are meaningless when the shape doesn't correspond to the parameters
+ mStencilCenterX = (S32)(mImage->getWidth() + params[0] * (F32)(mImage->getHeight()))/2;
+ mStencilCenterY = (S32)(mImage->getHeight() + params[1] * (F32)(mImage->getHeight()))/2;
+ mStencilWidth = (S32)(params[2] * (F32)(mImage->getHeight()))/2;
+ mStencilGamma = (params[3] <= 0.0 ? 1.0 : params[3]);
+
+ mStencilWavelength = (params[0] <= 0.0 ? 10.0 : params[0] * (F32)(mImage->getHeight()) / 2.0);
+ mStencilSine = sinf(params[1]*DEG_TO_RAD);
+ mStencilCosine = cosf(params[1]*DEG_TO_RAD);
+
+ mStencilStartX = ((F32)(mImage->getWidth()) + params[0] * (F32)(mImage->getHeight()))/2.0;
+ mStencilStartY = ((F32)(mImage->getHeight()) + params[1] * (F32)(mImage->getHeight()))/2.0;
+ F32 end_x = ((F32)(mImage->getWidth()) + params[2] * (F32)(mImage->getHeight()))/2.0;
+ F32 end_y = ((F32)(mImage->getHeight()) + params[3] * (F32)(mImage->getHeight()))/2.0;
+ mStencilGradX = end_x - mStencilStartX;
+ mStencilGradY = end_y - mStencilStartY;
+ mStencilGradN = mStencilGradX*mStencilGradX + mStencilGradY*mStencilGradY;
+}
+
+F32 LLImageFilter::getStencilAlpha(S32 i, S32 j)
+{
+ F32 alpha = 1.0; // That init actually takes care of the STENCIL_SHAPE_UNIFORM case...
+ if (mStencilShape == STENCIL_SHAPE_VIGNETTE)
+ {
+ // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges
+ // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0
+ F32 d_center_square = (i - mStencilCenterX)*(i - mStencilCenterX) + (j - mStencilCenterY)*(j - mStencilCenterY);
+ alpha = powf(F_E, -(powf((d_center_square/(mStencilWidth*mStencilWidth)),mStencilGamma)/2.0f));
+ }
+ else if (mStencilShape == STENCIL_SHAPE_SCAN_LINES)
+ {
+ // alpha varies according to a squared sine function.
+ F32 d = mStencilSine*i - mStencilCosine*j;
+ alpha = (sinf(2*F_PI*d/mStencilWavelength) > 0.0 ? 1.0 : 0.0);
+ }
+ else if (mStencilShape == STENCIL_SHAPE_GRADIENT)
+ {
+ alpha = (((F32)(i) - mStencilStartX)*mStencilGradX + ((F32)(j) - mStencilStartY)*mStencilGradY) / mStencilGradN;
+ alpha = llclampf(alpha);
+ }
+
+ // We rescale alpha between min and max
+ return (mStencilMin + alpha * (mStencilMax - mStencilMin));
+}
+
+//============================================================================
+// Histograms
+//============================================================================
+
+U32* LLImageFilter::getBrightnessHistogram()
+{
+ if (!mHistoBrightness)
+ {
+ computeHistograms();
+ }
+ return mHistoBrightness;
+}
+
+void LLImageFilter::computeHistograms()
+{
+ const S32 components = mImage->getComponents();
+ llassert( components >= 1 && components <= 4 );
+
+ // Allocate memory for the histograms
+ if (!mHistoRed)
+ {
+ mHistoRed = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+ }
+ if (!mHistoGreen)
+ {
+ mHistoGreen = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+ }
+ if (!mHistoBlue)
+ {
+ mHistoBlue = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+ }
+ if (!mHistoBrightness)
+ {
+ mHistoBrightness = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+ }
+
+ // Initialize them
+ for (S32 i = 0; i < 256; i++)
+ {
+ mHistoRed[i] = 0;
+ mHistoGreen[i] = 0;
+ mHistoBlue[i] = 0;
+ mHistoBrightness[i] = 0;
+ }
+
+ // Compute them
+ S32 pixels = mImage->getWidth() * mImage->getHeight();
+ U8* dst_data = mImage->getData();
+ for (S32 i = 0; i < pixels; i++)
+ {
+ mHistoRed[dst_data[VRED]]++;
+ mHistoGreen[dst_data[VGREEN]]++;
+ mHistoBlue[dst_data[VBLUE]]++;
+ // Note: this is a very simple shorthand for brightness but it's OK for our use
+ S32 brightness = ((S32)(dst_data[VRED]) + (S32)(dst_data[VGREEN]) + (S32)(dst_data[VBLUE])) / 3;
+ mHistoBrightness[brightness]++;
+ // next pixel...
+ dst_data += components;
+ }
+}
+
+//============================================================================
+// Secondary Filters
+//============================================================================
+
+void LLImageFilter::filterGrayScale()
+{
+ LLMatrix3 gray_scale;
+ LLVector3 luminosity(0.2125, 0.7154, 0.0721);
+ gray_scale.setRows(luminosity, luminosity, luminosity);
+ gray_scale.transpose();
+ colorTransform(gray_scale);
+}
+
+void LLImageFilter::filterSepia()
+{
+ LLMatrix3 sepia;
+ sepia.setRows(LLVector3(0.3588, 0.7044, 0.1368),
+ LLVector3(0.2990, 0.5870, 0.1140),
+ LLVector3(0.2392, 0.4696, 0.0912));
+ sepia.transpose();
+ colorTransform(sepia);
+}
+
+void LLImageFilter::filterSaturate(F32 saturation)
+{
+ // Matrix to Lij
+ LLMatrix3 r_a;
+ LLMatrix3 r_b;
+
+ // 45 degre rotation around z
+ r_a.setRows(LLVector3( OO_SQRT2, OO_SQRT2, 0.0),
+ LLVector3(-OO_SQRT2, OO_SQRT2, 0.0),
+ LLVector3( 0.0, 0.0, 1.0));
+ // 54.73 degre rotation around y
+ float oo_sqrt3 = 1.0f / F_SQRT3;
+ float sin_54 = F_SQRT2 * oo_sqrt3;
+ r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54),
+ LLVector3(0.0, 1.0, 0.0),
+ LLVector3(sin_54, 0.0, oo_sqrt3));
+
+ // Coordinate conversion
+ LLMatrix3 Lij = r_b * r_a;
+ LLMatrix3 Lij_inv = Lij;
+ Lij_inv.transpose();
+
+ // Local saturation transform
+ LLMatrix3 s;
+ s.setRows(LLVector3(saturation, 0.0, 0.0),
+ LLVector3(0.0, saturation, 0.0),
+ LLVector3(0.0, 0.0, 1.0));
+
+ // Global saturation transform
+ LLMatrix3 transfo = Lij_inv * s * Lij;
+ colorTransform(transfo);
+}
+
+void LLImageFilter::filterRotate(F32 angle)
+{
+ // Matrix to Lij
+ LLMatrix3 r_a;
+ LLMatrix3 r_b;
+
+ // 45 degre rotation around z
+ r_a.setRows(LLVector3( OO_SQRT2, OO_SQRT2, 0.0),
+ LLVector3(-OO_SQRT2, OO_SQRT2, 0.0),
+ LLVector3( 0.0, 0.0, 1.0));
+ // 54.73 degre rotation around y
+ float oo_sqrt3 = 1.0f / F_SQRT3;
+ float sin_54 = F_SQRT2 * oo_sqrt3;
+ r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54),
+ LLVector3(0.0, 1.0, 0.0),
+ LLVector3(sin_54, 0.0, oo_sqrt3));
+
+ // Coordinate conversion
+ LLMatrix3 Lij = r_b * r_a;
+ LLMatrix3 Lij_inv = Lij;
+ Lij_inv.transpose();
+
+ // Local color rotation transform
+ LLMatrix3 r;
+ angle *= DEG_TO_RAD;
+ r.setRows(LLVector3( cosf(angle), sinf(angle), 0.0),
+ LLVector3(-sinf(angle), cosf(angle), 0.0),
+ LLVector3( 0.0, 0.0, 1.0));
+
+ // Global color rotation transform
+ LLMatrix3 transfo = Lij_inv * r * Lij;
+ colorTransform(transfo);
+}
+
+void LLImageFilter::filterGamma(F32 gamma, const LLColor3& alpha)
+{
+ U8 gamma_red_lut[256];
+ U8 gamma_green_lut[256];
+ U8 gamma_blue_lut[256];
+
+ for (S32 i = 0; i < 256; i++)
+ {
+ F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,1.0/gamma)));
+ // Blend in with alpha values
+ gamma_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * 255.0 * gamma_i);
+ gamma_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * 255.0 * gamma_i);
+ gamma_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * 255.0 * gamma_i);
+ }
+
+ colorCorrect(gamma_red_lut,gamma_green_lut,gamma_blue_lut);
+}
+
+void LLImageFilter::filterLinearize(F32 tail, const LLColor3& alpha)
+{
+ // Get the histogram
+ U32* histo = getBrightnessHistogram();
+
+ // Compute cumulated histogram
+ U32 cumulated_histo[256];
+ cumulated_histo[0] = histo[0];
+ for (S32 i = 1; i < 256; i++)
+ {
+ cumulated_histo[i] = cumulated_histo[i-1] + histo[i];
+ }
+
+ // Compute min and max counts minus tail
+ tail = llclampf(tail);
+ S32 total = cumulated_histo[255];
+ S32 min_c = (S32)((F32)(total) * tail);
+ S32 max_c = (S32)((F32)(total) * (1.0 - tail));
+
+ // Find min and max values
+ S32 min_v = 0;
+ while (cumulated_histo[min_v] < min_c)
+ {
+ min_v++;
+ }
+ S32 max_v = 255;
+ while (cumulated_histo[max_v] > max_c)
+ {
+ max_v--;
+ }
+
+ // Compute linear lookup table
+ U8 linear_red_lut[256];
+ U8 linear_green_lut[256];
+ U8 linear_blue_lut[256];
+ if (max_v == min_v)
+ {
+ // Degenerated binary split case
+ for (S32 i = 0; i < 256; i++)
+ {
+ U8 value_i = (i < min_v ? 0 : 255);
+ // Blend in with alpha values
+ linear_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+ linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+ linear_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
+ }
+ }
+ else
+ {
+ // Linearize between min and max
+ F32 slope = 255.0 / (F32)(max_v - min_v);
+ F32 translate = -min_v * slope;
+ for (S32 i = 0; i < 256; i++)
+ {
+ U8 value_i = (U8)(llclampb((S32)(slope*i + translate)));
+ // Blend in with alpha values
+ linear_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+ linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+ linear_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
+ }
+ }
+
+ // Apply lookup table
+ colorCorrect(linear_red_lut,linear_green_lut,linear_blue_lut);
+}
+
+void LLImageFilter::filterEqualize(S32 nb_classes, const LLColor3& alpha)
+{
+ // Regularize the parameter: must be between 2 and 255
+ nb_classes = llmax(nb_classes,2);
+ nb_classes = llclampb(nb_classes);
+
+ // Get the histogram
+ U32* histo = getBrightnessHistogram();
+
+ // Compute cumulated histogram
+ U32 cumulated_histo[256];
+ cumulated_histo[0] = histo[0];
+ for (S32 i = 1; i < 256; i++)
+ {
+ cumulated_histo[i] = cumulated_histo[i-1] + histo[i];
+ }
+
+ // Compute deltas
+ S32 total = cumulated_histo[255];
+ S32 delta_count = total / nb_classes;
+ S32 current_count = delta_count;
+ S32 delta_value = 256 / (nb_classes - 1);
+ S32 current_value = 0;
+
+ // Compute equalized lookup table
+ U8 equalize_red_lut[256];
+ U8 equalize_green_lut[256];
+ U8 equalize_blue_lut[256];
+ for (S32 i = 0; i < 256; i++)
+ {
+ // Blend in current_value with alpha values
+ equalize_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * current_value);
+ equalize_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * current_value);
+ equalize_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * current_value);
+ if (cumulated_histo[i] >= current_count)
+ {
+ current_count += delta_count;
+ current_value += delta_value;
+ current_value = llclampb(current_value);
+ }
+ }
+
+ // Apply lookup table
+ colorCorrect(equalize_red_lut,equalize_green_lut,equalize_blue_lut);
+}
+
+void LLImageFilter::filterColorize(const LLColor3& color, const LLColor3& alpha)
+{
+ U8 red_lut[256];
+ U8 green_lut[256];
+ U8 blue_lut[256];
+
+ F32 red_composite = 255.0 * alpha.mV[0] * color.mV[0];
+ F32 green_composite = 255.0 * alpha.mV[1] * color.mV[1];
+ F32 blue_composite = 255.0 * alpha.mV[2] * color.mV[2];
+
+ for (S32 i = 0; i < 256; i++)
+ {
+ red_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[0]) * (F32)(i) + red_composite)));
+ green_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[1]) * (F32)(i) + green_composite)));
+ blue_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[2]) * (F32)(i) + blue_composite)));
+ }
+
+ colorCorrect(red_lut,green_lut,blue_lut);
+}
+
+void LLImageFilter::filterContrast(F32 slope, const LLColor3& alpha)
+{
+ U8 contrast_red_lut[256];
+ U8 contrast_green_lut[256];
+ U8 contrast_blue_lut[256];
+
+ F32 translate = 128.0 * (1.0 - slope);
+
+ for (S32 i = 0; i < 256; i++)
+ {
+ U8 value_i = (U8)(llclampb((S32)(slope*i + translate)));
+ // Blend in with alpha values
+ contrast_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+ contrast_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+ contrast_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
+ }
+
+ colorCorrect(contrast_red_lut,contrast_green_lut,contrast_blue_lut);
+}
+
+void LLImageFilter::filterBrightness(F32 add, const LLColor3& alpha)
+{
+ U8 brightness_red_lut[256];
+ U8 brightness_green_lut[256];
+ U8 brightness_blue_lut[256];
+
+ S32 add_value = (S32)(add * 255.0);
+
+ for (S32 i = 0; i < 256; i++)
+ {
+ U8 value_i = (U8)(llclampb(i + add_value));
+ // Blend in with alpha values
+ brightness_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+ brightness_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+ brightness_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
+ }
+
+ colorCorrect(brightness_red_lut,brightness_green_lut,brightness_blue_lut);
+}
+
+//============================================================================
diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h
new file mode 100755
index 0000000000..16ec395f76
--- /dev/null
+++ b/indra/llimage/llimagefilter.h
@@ -0,0 +1,137 @@
+/**
+ * @file llimagefilter.h
+ * @brief Simple Image Filtering. See https://wiki.lindenlab.com/wiki/SL_Viewer_Image_Filters for complete documentation.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2014, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLIMAGEFILTER_H
+#define LL_LLIMAGEFILTER_H
+
+#include "llsd.h"
+#include "llimage.h"
+
+class LLImageRaw;
+class LLColor4U;
+class LLColor3;
+class LLMatrix3;
+
+typedef enum e_stencil_blend_mode
+{
+ STENCIL_BLEND_MODE_BLEND = 0,
+ STENCIL_BLEND_MODE_ADD = 1,
+ STENCIL_BLEND_MODE_ABACK = 2,
+ STENCIL_BLEND_MODE_FADE = 3
+} EStencilBlendMode;
+
+typedef enum e_stencil_shape
+{
+ STENCIL_SHAPE_UNIFORM = 0,
+ STENCIL_SHAPE_GRADIENT = 1,
+ STENCIL_SHAPE_VIGNETTE = 2,
+ STENCIL_SHAPE_SCAN_LINES = 3
+} EStencilShape;
+
+typedef enum e_screen_mode
+{
+ SCREEN_MODE_2DSINE = 0,
+ SCREEN_MODE_LINE = 1
+} EScreenMode;
+
+//============================================================================
+// LLImageFilter
+//============================================================================
+
+class LLImageFilter
+{
+public:
+ LLImageFilter(const std::string& file_path);
+ ~LLImageFilter();
+
+ void executeFilter(LLPointer<LLImageRaw> raw_image);
+
+private:
+ // Filter Operations : Transforms
+ void filterGrayScale(); // Convert to grayscale
+ void filterSepia(); // Convert to sepia
+ void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates
+ void filterRotate(F32 angle); // Rotates hue according to angle, angle in degrees
+
+ // Filter Operations : Color Corrections
+ // When specified, the LLColor3 alpha parameter indicates the intensity of the effect for each color channel
+ // acting in effect as an alpha blending factor different for each channel. For instance (1.0,0.0,0.0) will apply
+ // the effect only to the Red channel. Intermediate values blends the effect with the source color.
+ void filterGamma(F32 gamma, const LLColor3& alpha); // Apply gamma to each channel
+ void filterLinearize(F32 tail, const LLColor3& alpha); // Use histogram to linearize constrast between min and max values minus tail
+ void filterEqualize(S32 nb_classes, const LLColor3& alpha); // Use histogram to equalize constrast between nb_classes throughout the image
+ void filterColorize(const LLColor3& color, const LLColor3& alpha); // Colorize with color and alpha per channel
+ void filterContrast(F32 slope, const LLColor3& alpha); // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast
+ void filterBrightness(F32 add, const LLColor3& alpha); // Change brightness according to add: > 0 brighter, < 0 darker
+
+ // Filter Primitives
+ void colorTransform(const LLMatrix3 &transform);
+ void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
+ void filterScreen(EScreenMode mode, const F32 wave_length, const F32 angle);
+ void blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue);
+ void convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value);
+
+ // Procedural Stencils
+ void setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params);
+ F32 getStencilAlpha(S32 i, S32 j);
+
+ // Histograms
+ U32* getBrightnessHistogram();
+ void computeHistograms();
+
+ LLSD mFilterData;
+ LLPointer<LLImageRaw> mImage;
+
+ // Histograms (if we ever happen to need them)
+ U32 *mHistoRed;
+ U32 *mHistoGreen;
+ U32 *mHistoBlue;
+ U32 *mHistoBrightness;
+
+ // Current Stencil Settings
+ EStencilBlendMode mStencilBlendMode;
+ EStencilShape mStencilShape;
+ F32 mStencilMin;
+ F32 mStencilMax;
+
+ S32 mStencilCenterX;
+ S32 mStencilCenterY;
+ S32 mStencilWidth;
+ F32 mStencilGamma;
+
+ F32 mStencilWavelength;
+ F32 mStencilSine;
+ F32 mStencilCosine;
+
+ F32 mStencilStartX;
+ F32 mStencilStartY;
+ F32 mStencilGradX;
+ F32 mStencilGradY;
+ F32 mStencilGradN;
+};
+
+
+#endif
diff --git a/indra/llimage/llimagejpeg.h b/indra/llimage/llimagejpeg.h
index 5b596d9fa4..2142660c81 100755
--- a/indra/llimage/llimagejpeg.h
+++ b/indra/llimage/llimagejpeg.h
@@ -33,7 +33,7 @@
#include "llwin32headerslean.h"
extern "C" {
-#ifdef LL_STANDALONE
+#ifdef LL_USESYSTEMLIBS
# include <jpeglib.h>
# include <jerror.h>
#else
diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp
index 8b568ea560..5f8aaae20b 100755
--- a/indra/llinventory/llfoldertype.cpp
+++ b/indra/llinventory/llfoldertype.cpp
@@ -92,7 +92,7 @@ LLFolderDictionary::LLFolderDictionary()
addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", TRUE));
- addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", FALSE));
+ addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE));
addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", FALSE));
addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE));
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 7fb2a801b2..11647c5518 100755
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -51,6 +51,7 @@ static const std::string INV_DESC_LABEL("desc");
static const std::string INV_PERMISSIONS_LABEL("permissions");
static const std::string INV_SHADOW_ID_LABEL("shadow_id");
static const std::string INV_ASSET_ID_LABEL("asset_id");
+static const std::string INV_LINKED_ID_LABEL("linked_id");
static const std::string INV_SALE_INFO_LABEL("sale_info");
static const std::string INV_FLAGS_LABEL("flags");
static const std::string INV_CREATION_DATE_LABEL("created_at");
@@ -257,13 +258,6 @@ BOOL LLInventoryObject::exportLegacyStream(std::ostream& output_stream, BOOL) co
return TRUE;
}
-
-void LLInventoryObject::removeFromServer()
-{
- // don't do nothin'
- LL_WARNS() << "LLInventoryObject::removeFromServer() called. Doesn't do anything." << LL_ENDL;
-}
-
void LLInventoryObject::updateParentOnServer(BOOL) const
{
// don't do nothin'
@@ -276,7 +270,7 @@ void LLInventoryObject::updateServer(BOOL) const
LL_WARNS() << "LLInventoryObject::updateServer() called. Doesn't do anything." << LL_ENDL;
}
-inline
+// static
void LLInventoryObject::correctInventoryName(std::string& name)
{
LLStringUtil::replaceNonstandardASCII(name, ' ');
@@ -435,12 +429,17 @@ U32 LLInventoryItem::getCRC32() const
return crc;
}
+// static
+void LLInventoryItem::correctInventoryDescription(std::string& desc)
+{
+ LLStringUtil::replaceNonstandardASCII(desc, ' ');
+ LLStringUtil::replaceChar(desc, '|', ' ');
+}
void LLInventoryItem::setDescription(const std::string& d)
{
std::string new_desc(d);
- LLStringUtil::replaceNonstandardASCII(new_desc, ' ');
- LLStringUtil::replaceChar(new_desc, '|', ' ');
+ LLInventoryItem::correctInventoryDescription(new_desc);
if( new_desc != mDescription )
{
disclaimMem(mDescription);
@@ -1068,11 +1067,16 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
LLTrace::BlockTimerStatHandle FTM_INVENTORY_SD_DESERIALIZE("Inventory SD Deserialize");
-bool LLInventoryItem::fromLLSD(const LLSD& sd)
+bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
{
LL_RECORD_BLOCK_TIME(FTM_INVENTORY_SD_DESERIALIZE);
- mInventoryType = LLInventoryType::IT_NONE;
- mAssetUUID.setNull();
+ if (is_new)
+ {
+ // If we're adding LLSD to an existing object, need avoid
+ // clobbering these fields.
+ mInventoryType = LLInventoryType::IT_NONE;
+ mAssetUUID.setNull();
+ }
std::string w;
w = INV_ITEM_ID_LABEL;
@@ -1129,6 +1133,11 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd)
{
mAssetUUID = sd[w];
}
+ w = INV_LINKED_ID_LABEL;
+ if (sd.has(w))
+ {
+ mAssetUUID = sd[w];
+ }
w = INV_ASSET_TYPE_LABEL;
if (sd.has(w))
{
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index aa0b4cc24c..70b200e139 100755
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -48,6 +48,7 @@ class LLInventoryObject : public LLRefCount, public LLTrace::MemTrackable<LLInve
{
public:
typedef std::list<LLPointer<LLInventoryObject> > object_list_t;
+ typedef std::list<LLConstPointer<LLInventoryObject> > const_object_list_t;
//--------------------------------------------------------------------
// Initialization
@@ -86,22 +87,19 @@ public:
void setType(LLAssetType::EType type);
virtual void setCreationDate(time_t creation_date_utc); // only stored for items
-private:
// in place correction for inventory name string
- void correctInventoryName(std::string& name);
+ static void correctInventoryName(std::string& name);
//--------------------------------------------------------------------
// File Support
// Implemented here so that a minimal information set can be transmitted
// between simulator and viewer.
//--------------------------------------------------------------------
-public:
// virtual BOOL importFile(LLFILE* fp);
virtual BOOL exportFile(LLFILE* fp, BOOL include_asset_key = TRUE) const;
virtual BOOL importLegacyStream(std::istream& input_stream);
virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const;
- virtual void removeFromServer();
virtual void updateParentOnServer(BOOL) const;
virtual void updateServer(BOOL) const;
@@ -174,6 +172,7 @@ public:
//--------------------------------------------------------------------
public:
void setAssetUUID(const LLUUID& asset_id);
+ static void correctInventoryDescription(std::string& name);
void setDescription(const std::string& new_desc);
void setSaleInfo(const LLSaleInfo& sale_info);
void setPermissions(const LLPermissions& perm);
@@ -212,7 +211,7 @@ public:
void unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size);
LLSD asLLSD() const;
void asLLSD( LLSD& sd ) const;
- bool fromLLSD(const LLSD& sd);
+ bool fromLLSD(const LLSD& sd, bool is_new = true);
//--------------------------------------------------------------------
// Member Variables
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index 29db799154..a8b27ad189 100755
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llmath.h
* @brief Useful math constants and macros.
*
@@ -73,6 +73,7 @@ const F32 F_E = 2.71828182845904523536f;
const F32 F_SQRT2 = 1.4142135623730950488016887242097f;
const F32 F_SQRT3 = 1.73205080756888288657986402541f;
const F32 OO_SQRT2 = 0.7071067811865475244008443621049f;
+const F32 OO_SQRT3 = 0.577350269189625764509f;
const F32 DEG_TO_RAD = 0.017453292519943295769236907684886f;
const F32 RAD_TO_DEG = 57.295779513082320876798154814105f;
const F32 F_APPROXIMATELY_ZERO = 0.00001f;
@@ -84,6 +85,9 @@ const F32 OO_LN2 = 1.4426950408889634073599246810019f;
const F32 F_ALMOST_ZERO = 0.0001f;
const F32 F_ALMOST_ONE = 1.0f - F_ALMOST_ZERO;
+const F32 GIMBAL_THRESHOLD = 0.000436f; // sets the gimballock threshold 0.025 away from +/-90 degrees
+// formula: GIMBAL_THRESHOLD = sin(DEG_TO_RAD * gimbal_threshold_angle);
+
// BUG: Eliminate in favor of F_APPROXIMATELY_ZERO above?
const F32 FP_MAG_THRESHOLD = 0.0000001f;
diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h
index 02220c41d8..7b5240c651 100755
--- a/indra/llmath/lloctree.h
+++ b/indra/llmath/lloctree.h
@@ -36,6 +36,8 @@
extern U32 gOctreeMaxCapacity;
+extern float gOctreeMinSize;
+
/*#define LL_OCTREE_PARANOIA_CHECK 0
#if LL_DARWIN
#define LL_OCTREE_MAX_CAPACITY 32
@@ -106,6 +108,7 @@ public:
: mParent((oct_node*)parent),
mOctant(octant)
{
+ llassert(size[0] >= gOctreeMinSize*0.5f);
//always keep a NULL terminated list to avoid out of bounds exceptions in debug builds
mData.push_back(NULL);
mDataEnd = &mData[0];
@@ -213,7 +216,7 @@ public:
F32 size = mSize[0];
F32 p_size = size * 2.f;
- return (radius <= 0.001f && size <= 0.001f) ||
+ return (radius <= gOctreeMinSize && size <= gOctreeMinSize) ||
(radius <= p_size && radius > size);
}
@@ -319,7 +322,7 @@ public:
//is it here?
if (isInside(data->getPositionGroup()))
{
- if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) ||
+ if (((getElementCount() < gOctreeMaxCapacity || getSize()[0] <= gOctreeMinSize) && contains(data->getBinRadius()) ||
(data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity)))
{ //it belongs here
mData.push_back(NULL);
@@ -356,8 +359,9 @@ public:
LLVector4a val;
val.setSub(center, getCenter());
val.setAbs(val);
-
- S32 lt = val.lessThan(LLVector4a::getEpsilon()).getGatheredBits() & 0x7;
+ LLVector4a min_diff(gOctreeMinSize);
+
+ S32 lt = val.lessThan(min_diff).getGatheredBits() & 0x7;
if( lt == 0x7 )
{
@@ -389,6 +393,7 @@ public:
}
#endif
+ llassert(size[0] >= gOctreeMinSize*0.5f);
//make the new kid
child = new LLOctreeNode<T>(center, size, this);
addChild(child);
@@ -796,6 +801,8 @@ public:
this->setSize(size2);
this->updateMinMax();
+ llassert(size[0] >= gOctreeMinSize);
+
//copy our children to a new branch
LLOctreeNode<T>* newnode = new LLOctreeNode<T>(center, size, this);
diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp
index 7381d5eb99..47374c287f 100755
--- a/indra/llmath/llquaternion.cpp
+++ b/indra/llmath/llquaternion.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llquaternion.cpp
* @brief LLQuaternion class implementation.
*
@@ -58,34 +58,40 @@ LLQuaternion::LLQuaternion(const LLMatrix3 &mat)
LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec)
{
- LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
- v.normalize();
-
- F32 c, s;
- c = cosf(angle*0.5f);
- s = sinf(angle*0.5f);
-
- mQ[VX] = v.mV[VX] * s;
- mQ[VY] = v.mV[VY] * s;
- mQ[VZ] = v.mV[VZ] * s;
- mQ[VW] = c;
- normalize();
+ F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
+ if (mag > FP_MAG_THRESHOLD)
+ {
+ angle *= 0.5;
+ F32 c = cosf(angle);
+ F32 s = sinf(angle) / mag;
+ mQ[VX] = vec.mV[VX] * s;
+ mQ[VY] = vec.mV[VY] * s;
+ mQ[VZ] = vec.mV[VZ] * s;
+ mQ[VW] = c;
+ }
+ else
+ {
+ loadIdentity();
+ }
}
LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec)
{
- LLVector3 v(vec);
- v.normalize();
-
- F32 c, s;
- c = cosf(angle*0.5f);
- s = sinf(angle*0.5f);
-
- mQ[VX] = v.mV[VX] * s;
- mQ[VY] = v.mV[VY] * s;
- mQ[VZ] = v.mV[VZ] * s;
- mQ[VW] = c;
- normalize();
+ F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
+ if (mag > FP_MAG_THRESHOLD)
+ {
+ angle *= 0.5;
+ F32 c = cosf(angle);
+ F32 s = sinf(angle) / mag;
+ mQ[VX] = vec.mV[VX] * s;
+ mQ[VY] = vec.mV[VY] * s;
+ mQ[VZ] = vec.mV[VZ] * s;
+ mQ[VW] = c;
+ }
+ else
+ {
+ loadIdentity();
+ }
}
LLQuaternion::LLQuaternion(const LLVector3 &x_axis,
@@ -136,57 +142,61 @@ void LLQuaternion::quantize8(F32 lower, F32 upper)
const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, F32 x, F32 y, F32 z)
{
- LLVector3 vec(x, y, z);
- vec.normalize();
-
- angle *= 0.5f;
- F32 c, s;
- c = cosf(angle);
- s = sinf(angle);
-
- mQ[VX] = vec.mV[VX]*s;
- mQ[VY] = vec.mV[VY]*s;
- mQ[VZ] = vec.mV[VZ]*s;
- mQ[VW] = c;
-
- normalize();
+ F32 mag = sqrtf(x * x + y * y + z * z);
+ if (mag > FP_MAG_THRESHOLD)
+ {
+ angle *= 0.5;
+ F32 c = cosf(angle);
+ F32 s = sinf(angle) / mag;
+ mQ[VX] = x * s;
+ mQ[VY] = y * s;
+ mQ[VZ] = z * s;
+ mQ[VW] = c;
+ }
+ else
+ {
+ loadIdentity();
+ }
return (*this);
}
const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector3 &vec)
{
- LLVector3 v(vec);
- v.normalize();
-
- angle *= 0.5f;
- F32 c, s;
- c = cosf(angle);
- s = sinf(angle);
-
- mQ[VX] = v.mV[VX]*s;
- mQ[VY] = v.mV[VY]*s;
- mQ[VZ] = v.mV[VZ]*s;
- mQ[VW] = c;
-
- normalize();
+ F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
+ if (mag > FP_MAG_THRESHOLD)
+ {
+ angle *= 0.5;
+ F32 c = cosf(angle);
+ F32 s = sinf(angle) / mag;
+ mQ[VX] = vec.mV[VX] * s;
+ mQ[VY] = vec.mV[VY] * s;
+ mQ[VZ] = vec.mV[VZ] * s;
+ mQ[VW] = c;
+ }
+ else
+ {
+ loadIdentity();
+ }
return (*this);
}
const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector4 &vec)
{
- LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
- v.normalize();
-
- F32 c, s;
- c = cosf(angle*0.5f);
- s = sinf(angle*0.5f);
-
- mQ[VX] = v.mV[VX]*s;
- mQ[VY] = v.mV[VY]*s;
- mQ[VZ] = v.mV[VZ]*s;
- mQ[VW] = c;
-
- normalize();
+ F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
+ if (mag > FP_MAG_THRESHOLD)
+ {
+ angle *= 0.5;
+ F32 c = cosf(angle);
+ F32 s = sinf(angle) / mag;
+ mQ[VX] = vec.mV[VX] * s;
+ mQ[VY] = vec.mV[VY] * s;
+ mQ[VZ] = vec.mV[VZ] * s;
+ mQ[VW] = c;
+ }
+ else
+ {
+ loadIdentity();
+ }
return (*this);
}
@@ -219,68 +229,80 @@ const LLQuaternion& LLQuaternion::set(const LLMatrix4 &mat)
// deprecated
const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z)
{
- LLVector3 vec(x, y, z);
- vec.normalize();
-
- angle *= 0.5f;
- F32 c, s;
- c = cosf(angle);
- s = sinf(angle);
-
- mQ[VX] = vec.mV[VX]*s;
- mQ[VY] = vec.mV[VY]*s;
- mQ[VZ] = vec.mV[VZ]*s;
- mQ[VW] = c;
-
- normalize();
+ F32 mag = sqrtf(x * x + y * y + z * z);
+ if (mag > FP_MAG_THRESHOLD)
+ {
+ angle *= 0.5;
+ F32 c = cosf(angle);
+ F32 s = sinf(angle) / mag;
+ mQ[VX] = x * s;
+ mQ[VY] = y * s;
+ mQ[VZ] = z * s;
+ mQ[VW] = c;
+ }
+ else
+ {
+ loadIdentity();
+ }
return (*this);
}
// deprecated
const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec)
{
- LLVector3 v(vec);
- v.normalize();
-
- angle *= 0.5f;
- F32 c, s;
- c = cosf(angle);
- s = sinf(angle);
-
- mQ[VX] = v.mV[VX]*s;
- mQ[VY] = v.mV[VY]*s;
- mQ[VZ] = v.mV[VZ]*s;
- mQ[VW] = c;
-
- normalize();
+ F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
+ if (mag > FP_MAG_THRESHOLD)
+ {
+ angle *= 0.5;
+ F32 c = cosf(angle);
+ F32 s = sinf(angle) / mag;
+ mQ[VX] = vec.mV[VX] * s;
+ mQ[VY] = vec.mV[VY] * s;
+ mQ[VZ] = vec.mV[VZ] * s;
+ mQ[VW] = c;
+ }
+ else
+ {
+ loadIdentity();
+ }
return (*this);
}
const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec)
{
- LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
- v.normalize();
-
- F32 c, s;
- c = cosf(angle*0.5f);
- s = sinf(angle*0.5f);
-
- mQ[VX] = v.mV[VX]*s;
- mQ[VY] = v.mV[VY]*s;
- mQ[VZ] = v.mV[VZ]*s;
- mQ[VW] = c;
-
- normalize();
+ F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
+ if (mag > FP_MAG_THRESHOLD)
+ {
+ angle *= 0.5;
+ F32 c = cosf(angle);
+ F32 s = sinf(angle) / mag;
+ mQ[VX] = vec.mV[VX] * s;
+ mQ[VY] = vec.mV[VY] * s;
+ mQ[VZ] = vec.mV[VZ] * s;
+ mQ[VW] = c;
+ }
+ else
+ {
+ loadIdentity();
+ }
return (*this);
}
const LLQuaternion& LLQuaternion::setQuat(F32 roll, F32 pitch, F32 yaw)
{
- LLMatrix3 rot_mat(roll, pitch, yaw);
- rot_mat.orthogonalize();
- *this = rot_mat.quaternion();
-
- normalize();
+ roll *= 0.5f;
+ pitch *= 0.5f;
+ yaw *= 0.5f;
+ F32 sinX = sinf(roll);
+ F32 cosX = cosf(roll);
+ F32 sinY = sinf(pitch);
+ F32 cosY = cosf(pitch);
+ F32 sinZ = sinf(yaw);
+ F32 cosZ = cosf(yaw);
+ mQ[VW] = cosX * cosY * cosZ - sinX * sinY * sinZ;
+ mQ[VX] = sinX * cosY * cosZ + cosX * sinY * sinZ;
+ mQ[VY] = cosX * sinY * cosZ - sinX * cosY * sinZ;
+ mQ[VZ] = cosX * cosY * sinZ + sinX * sinY * cosZ;
return (*this);
}
@@ -425,68 +447,44 @@ LLMatrix4 LLQuaternion::getMatrix4(void) const
// calculate the shortest rotation from a to b
void LLQuaternion::shortestArc(const LLVector3 &a, const LLVector3 &b)
{
- // Make a local copy of both vectors.
- LLVector3 vec_a = a;
- LLVector3 vec_b = b;
-
- // Make sure neither vector is zero length. Also normalize
- // the vectors while we are at it.
- F32 vec_a_mag = vec_a.normalize();
- F32 vec_b_mag = vec_b.normalize();
- if (vec_a_mag < F_APPROXIMATELY_ZERO ||
- vec_b_mag < F_APPROXIMATELY_ZERO)
- {
- // Can't calculate a rotation from this.
- // Just return ZERO_ROTATION instead.
- loadIdentity();
- return;
- }
-
- // Create an axis to rotate around, and the cos of the angle to rotate.
- LLVector3 axis = vec_a % vec_b;
- F32 cos_theta = vec_a * vec_b;
-
- // Check the angle between the vectors to see if they are parallel or anti-parallel.
- if (cos_theta > 1.0 - F_APPROXIMATELY_ZERO)
- {
- // a and b are parallel. No rotation is necessary.
- loadIdentity();
- }
- else if (cos_theta < -1.0 + F_APPROXIMATELY_ZERO)
+ F32 ab = a * b; // dotproduct
+ LLVector3 c = a % b; // crossproduct
+ F32 cc = c * c; // squared length of the crossproduct
+ if (ab * ab + cc) // test if the arguments have sufficient magnitude
{
- // a and b are anti-parallel.
- // Rotate 180 degrees around some orthogonal axis.
- // Find the projection of the x-axis onto a, and try
- // using the vector between the projection and the x-axis
- // as the orthogonal axis.
- LLVector3 proj = vec_a.mV[VX] / (vec_a * vec_a) * vec_a;
- LLVector3 ortho_axis(1.f, 0.f, 0.f);
- ortho_axis -= proj;
-
- // Turn this into an orthonormal axis.
- F32 ortho_length = ortho_axis.normalize();
- // If the axis' length is 0, then our guess at an orthogonal axis
- // was wrong (a is parallel to the x-axis).
- if (ortho_length < F_APPROXIMATELY_ZERO)
+ if (cc > 0.0f) // test if the arguments are (anti)parallel
{
- // Use the z-axis instead.
- ortho_axis.setVec(0.f, 0.f, 1.f);
+ F32 s = sqrtf(ab * ab + cc) + ab; // note: don't try to optimize this line
+ F32 m = 1.0f / sqrtf(cc + s * s); // the inverted magnitude of the quaternion
+ mQ[VX] = c.mV[VX] * m;
+ mQ[VY] = c.mV[VY] * m;
+ mQ[VZ] = c.mV[VZ] * m;
+ mQ[VW] = s * m;
+ return;
+ }
+ if (ab < 0.0f) // test if the angle is bigger than PI/2 (anti parallel)
+ {
+ c = a - b; // the arguments are anti-parallel, we have to choose an axis
+ F32 m = sqrtf(c.mV[VX] * c.mV[VX] + c.mV[VY] * c.mV[VY]); // the length projected on the XY-plane
+ if (m > FP_MAG_THRESHOLD)
+ {
+ mQ[VX] = -c.mV[VY] / m; // return the quaternion with the axis in the XY-plane
+ mQ[VY] = c.mV[VX] / m;
+ mQ[VZ] = 0.0f;
+ mQ[VW] = 0.0f;
+ return;
+ }
+ else // the vectors are parallel to the Z-axis
+ {
+ mQ[VX] = 1.0f; // rotate around the X-axis
+ mQ[VY] = 0.0f;
+ mQ[VZ] = 0.0f;
+ mQ[VW] = 0.0f;
+ return;
+ }
}
-
- // Construct a quaternion from this orthonormal axis.
- mQ[VX] = ortho_axis.mV[VX];
- mQ[VY] = ortho_axis.mV[VY];
- mQ[VZ] = ortho_axis.mV[VZ];
- mQ[VW] = 0.f;
- }
- else
- {
- // a and b are NOT parallel or anti-parallel.
- // Return the rotation between these vectors.
- F32 theta = (F32)acos(cos_theta);
-
- setAngleAxis(theta, axis);
}
+ loadIdentity();
}
// constrains rotation to a cone angle specified in radians
@@ -838,79 +836,82 @@ LLQuaternion::Order StringToOrder( const char *str )
void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const
{
- F32 cos_a = mQ[VW];
- if (cos_a > 1.0f) cos_a = 1.0f;
- if (cos_a < -1.0f) cos_a = -1.0f;
-
- F32 sin_a = (F32) sqrt( 1.0f - cos_a * cos_a );
-
- if ( fabs( sin_a ) < 0.0005f )
- sin_a = 1.0f;
- else
- sin_a = 1.f/sin_a;
-
- F32 temp_angle = 2.0f * (F32) acos( cos_a );
- if (temp_angle > F_PI)
+ F32 v = sqrtf(mQ[VX] * mQ[VX] + mQ[VY] * mQ[VY] + mQ[VZ] * mQ[VZ]); // length of the vector-component
+ if (v > FP_MAG_THRESHOLD)
{
- // The (angle,axis) pair should never have angles outside [PI, -PI]
- // since we want the _shortest_ (angle,axis) solution.
- // Since acos is defined for [0, PI], and we multiply by 2.0, we
- // can push the angle outside the acceptible range.
- // When this happens we set the angle to the other portion of a
- // full 2PI rotation, and negate the axis, which reverses the
- // direction of the rotation (by the right-hand rule).
- *angle = 2.f * F_PI - temp_angle;
- vec.mV[VX] = - mQ[VX] * sin_a;
- vec.mV[VY] = - mQ[VY] * sin_a;
- vec.mV[VZ] = - mQ[VZ] * sin_a;
+ F32 oomag = 1.0f / v;
+ F32 w = mQ[VW];
+ if (mQ[VW] < 0.0f)
+ {
+ w = -w; // make VW positive
+ oomag = -oomag; // invert the axis
+ }
+ vec.mV[VX] = mQ[VX] * oomag; // normalize the axis
+ vec.mV[VY] = mQ[VY] * oomag;
+ vec.mV[VZ] = mQ[VZ] * oomag;
+ *angle = 2.0f * atan2f(v, w); // get the angle
}
else
{
- *angle = temp_angle;
- vec.mV[VX] = mQ[VX] * sin_a;
- vec.mV[VY] = mQ[VY] * sin_a;
- vec.mV[VZ] = mQ[VZ] * sin_a;
+ *angle = 0.0f; // no rotation
+ vec.mV[VX] = 0.0f; // around some dummy axis
+ vec.mV[VY] = 0.0f;
+ vec.mV[VZ] = 1.0f;
}
}
-
// quaternion does not need to be normalized
void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const
{
- LLMatrix3 rot_mat(*this);
- rot_mat.orthogonalize();
- rot_mat.getEulerAngles(roll, pitch, yaw);
-
-// // NOTE: LLQuaternion's are actually inverted with respect to
-// // the matrices, so this code also assumes inverted quaternions
-// // (-x, -y, -z, w). The result is that roll,pitch,yaw are applied
-// // in reverse order (yaw,pitch,roll).
-// F32 x = -mQ[VX], y = -mQ[VY], z = -mQ[VZ], w = mQ[VW];
-// F64 m20 = 2.0*(x*z-y*w);
-// if (1.0f - fabsf(m20) < F_APPROXIMATELY_ZERO)
-// {
-// *roll = 0.0f;
-// *pitch = (F32)asin(m20);
-// *yaw = (F32)atan2(2.0*(x*y-z*w), 1.0 - 2.0*(x*x+z*z));
-// }
-// else
-// {
-// *roll = (F32)atan2(-2.0*(y*z+x*w), 1.0-2.0*(x*x+y*y));
-// *pitch = (F32)asin(m20);
-// *yaw = (F32)atan2(-2.0*(x*y+z*w), 1.0-2.0*(y*y+z*z));
-// }
+ F32 sx = 2 * (mQ[VX] * mQ[VW] - mQ[VY] * mQ[VZ]); // sine of the roll
+ F32 sy = 2 * (mQ[VY] * mQ[VW] + mQ[VX] * mQ[VZ]); // sine of the pitch
+ F32 ys = mQ[VW] * mQ[VW] - mQ[VY] * mQ[VY]; // intermediate cosine 1
+ F32 xz = mQ[VX] * mQ[VX] - mQ[VZ] * mQ[VZ]; // intermediate cosine 2
+ F32 cx = ys - xz; // cosine of the roll
+ F32 cy = sqrtf(sx * sx + cx * cx); // cosine of the pitch
+ if (cy > GIMBAL_THRESHOLD) // no gimbal lock
+ {
+ *roll = atan2f(sx, cx);
+ *pitch = atan2f(sy, cy);
+ *yaw = atan2f(2 * (mQ[VZ] * mQ[VW] - mQ[VX] * mQ[VY]), ys + xz);
+ }
+ else // gimbal lock
+ {
+ if (sy > 0)
+ {
+ *pitch = F_PI_BY_TWO;
+ *yaw = 2 * atan2f(mQ[VZ] + mQ[VX], mQ[VW] + mQ[VY]);
+ }
+ else
+ {
+ *pitch = -F_PI_BY_TWO;
+ *yaw = 2 * atan2f(mQ[VZ] - mQ[VX], mQ[VW] - mQ[VY]);
+ }
+ *roll = 0;
+ }
}
// Saves space by using the fact that our quaternions are normalized
LLVector3 LLQuaternion::packToVector3() const
{
+ F32 x = mQ[VX];
+ F32 y = mQ[VY];
+ F32 z = mQ[VZ];
+ F32 w = mQ[VW];
+ F32 mag = sqrtf(x * x + y * y + z * z + w * w);
+ if (mag > FP_MAG_THRESHOLD)
+ {
+ x /= mag;
+ y /= mag;
+ z /= mag; // no need to normalize w, it's not used
+ }
if( mQ[VW] >= 0 )
{
- return LLVector3( mQ[VX], mQ[VY], mQ[VZ] );
+ return LLVector3( x, y , z );
}
else
{
- return LLVector3( -mQ[VX], -mQ[VY], -mQ[VZ] );
+ return LLVector3( -x, -y, -z );
}
}
diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h
index ca0dfe206b..e56929ed0f 100755
--- a/indra/llmath/llquaternion.h
+++ b/indra/llmath/llquaternion.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llquaternion.h
* @brief LLQuaternion class header file.
*
@@ -304,43 +304,29 @@ inline const LLQuaternion& LLQuaternion::setQuat(const F32 *q)
return (*this);
}
-// There may be a cheaper way that avoids the sqrt.
-// Does sin_a = VX*VX + VY*VY + VZ*VZ?
-// Copied from Matrix and Quaternion FAQ 1.12
inline void LLQuaternion::getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const
{
- F32 cos_a = mQ[VW];
- if (cos_a > 1.0f) cos_a = 1.0f;
- if (cos_a < -1.0f) cos_a = -1.0f;
-
- F32 sin_a = (F32) sqrt( 1.0f - cos_a * cos_a );
-
- if ( fabs( sin_a ) < 0.0005f )
- sin_a = 1.0f;
- else
- sin_a = 1.f/sin_a;
-
- F32 temp_angle = 2.0f * (F32) acos( cos_a );
- if (temp_angle > F_PI)
+ F32 v = sqrtf(mQ[VX] * mQ[VX] + mQ[VY] * mQ[VY] + mQ[VZ] * mQ[VZ]); // length of the vector-component
+ if (v > FP_MAG_THRESHOLD)
{
- // The (angle,axis) pair should never have angles outside [PI, -PI]
- // since we want the _shortest_ (angle,axis) solution.
- // Since acos is defined for [0, PI], and we multiply by 2.0, we
- // can push the angle outside the acceptible range.
- // When this happens we set the angle to the other portion of a
- // full 2PI rotation, and negate the axis, which reverses the
- // direction of the rotation (by the right-hand rule).
- *angle = 2.f * F_PI - temp_angle;
- *x = - mQ[VX] * sin_a;
- *y = - mQ[VY] * sin_a;
- *z = - mQ[VZ] * sin_a;
+ F32 oomag = 1.0f / v;
+ F32 w = mQ[VW];
+ if (w < 0.0f)
+ {
+ w = -w; // make VW positive
+ oomag = -oomag; // invert the axis
+ }
+ *x = mQ[VX] * oomag; // normalize the axis
+ *y = mQ[VY] * oomag;
+ *z = mQ[VZ] * oomag;
+ *angle = 2.0f * atan2f(v, w); // get the angle
}
else
{
- *angle = temp_angle;
- *x = mQ[VX] * sin_a;
- *y = mQ[VY] * sin_a;
- *z = mQ[VZ] * sin_a;
+ *angle = 0.0f; // no rotation
+ *x = 0.0f; // around some dummy axis
+ *y = 0.0f;
+ *z = 1.0f;
}
}
diff --git a/indra/llmath/v3dmath.h b/indra/llmath/v3dmath.h
index cab4c93a9f..4938273d5b 100755
--- a/indra/llmath/v3dmath.h
+++ b/indra/llmath/v3dmath.h
@@ -72,17 +72,22 @@ class LLVector3d
BOOL clamp(const F64 min, const F64 max); // Clamps all values to (min,max), returns TRUE if data changed
BOOL abs(); // sets all values to absolute value of original value (first octant), returns TRUE if changed
- inline const LLVector3d& clearVec(); // Clears LLVector3d to (0, 0, 0, 1)
+ inline const LLVector3d& clear(); // Clears LLVector3d to (0, 0, 0, 1)
+ inline const LLVector3d& clearVec(); // deprecated
inline const LLVector3d& setZero(); // Zero LLVector3d to (0, 0, 0, 0)
inline const LLVector3d& zeroVec(); // deprecated
- inline const LLVector3d& setVec(const F64 x, const F64 y, const F64 z); // Sets LLVector3d to (x, y, z, 1)
- inline const LLVector3d& setVec(const LLVector3d &vec); // Sets LLVector3d to vec
- inline const LLVector3d& setVec(const F64 *vec); // Sets LLVector3d to vec
- inline const LLVector3d& setVec(const LLVector3 &vec);
+ inline const LLVector3d& set(const F64 x, const F64 y, const F64 z); // Sets LLVector3d to (x, y, z, 1)
+ inline const LLVector3d& set(const LLVector3d &vec); // Sets LLVector3d to vec
+ inline const LLVector3d& set(const F64 *vec); // Sets LLVector3d to vec
+ inline const LLVector3d& set(const LLVector3 &vec);
+ inline const LLVector3d& setVec(const F64 x, const F64 y, const F64 z); // deprecated
+ inline const LLVector3d& setVec(const LLVector3d &vec); // deprecated
+ inline const LLVector3d& setVec(const F64 *vec); // deprecated
+ inline const LLVector3d& setVec(const LLVector3 &vec); // deprecated
- F64 magVec() const; // Returns magnitude of LLVector3d
- F64 magVecSquared() const; // Returns magnitude squared of LLVector3d
- inline F64 normVec(); // Normalizes and returns the magnitude of LLVector3d
+ F64 magVec() const; // deprecated
+ F64 magVecSquared() const; // deprecated
+ inline F64 normVec(); // deprecated
F64 length() const; // Returns magnitude of LLVector3d
F64 lengthSquared() const; // Returns magnitude squared of LLVector3d
@@ -127,7 +132,15 @@ class LLVector3d
typedef LLVector3d LLGlobalVec;
-const LLVector3d &LLVector3d::setVec(const LLVector3 &vec)
+inline const LLVector3d &LLVector3d::set(const LLVector3 &vec)
+{
+ mdV[0] = vec.mV[0];
+ mdV[1] = vec.mV[1];
+ mdV[2] = vec.mV[2];
+ return *this;
+}
+
+inline const LLVector3d &LLVector3d::setVec(const LLVector3 &vec)
{
mdV[0] = vec.mV[0];
mdV[1] = vec.mV[1];
@@ -184,6 +197,14 @@ inline BOOL LLVector3d::isFinite() const
// Clear and Assignment Functions
+inline const LLVector3d& LLVector3d::clear(void)
+{
+ mdV[0] = 0.f;
+ mdV[1] = 0.f;
+ mdV[2]= 0.f;
+ return (*this);
+}
+
inline const LLVector3d& LLVector3d::clearVec(void)
{
mdV[0] = 0.f;
@@ -208,6 +229,30 @@ inline const LLVector3d& LLVector3d::zeroVec(void)
return (*this);
}
+inline const LLVector3d& LLVector3d::set(const F64 x, const F64 y, const F64 z)
+{
+ mdV[VX] = x;
+ mdV[VY] = y;
+ mdV[VZ] = z;
+ return (*this);
+}
+
+inline const LLVector3d& LLVector3d::set(const LLVector3d &vec)
+{
+ mdV[0] = vec.mdV[0];
+ mdV[1] = vec.mdV[1];
+ mdV[2] = vec.mdV[2];
+ return (*this);
+}
+
+inline const LLVector3d& LLVector3d::set(const F64 *vec)
+{
+ mdV[0] = vec[0];
+ mdV[1] = vec[1];
+ mdV[2] = vec[2];
+ return (*this);
+}
+
inline const LLVector3d& LLVector3d::setVec(const F64 x, const F64 y, const F64 z)
{
mdV[VX] = x;
diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h
index c807a30f7b..f3fbce4843 100755
--- a/indra/llmath/v3math.h
+++ b/indra/llmath/v3math.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file v3math.h
* @brief LLVector3 class header file.
*
@@ -159,9 +159,7 @@ F32 dist_vec(const LLVector3 &a, const LLVector3 &b); // Returns distance betwe
F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b);// Returns distance squared between a and b
F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b);// Returns distance squared between a and b ignoring Z component
LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b); // Returns vector a projected on vector b
-// Returns a vector in direction of a, such that when projected onto b, gives you the same value as b
-// in other words: projected_vec(inverse_projected_vec(a, b), b) == b;
-LLVector3 inverse_projected_vec(const LLVector3 &a, const LLVector3 &b);
+LLVector3 inverse_projected_vec(const LLVector3 &a, const LLVector3 &b); // Returns vector a scaled such that projected_vec(inverse_projected_vec(a, b), b) == b;
LLVector3 parallel_component(const LLVector3 &a, const LLVector3 &b); // Returns vector a projected on vector b (same as projected_vec)
LLVector3 orthogonal_component(const LLVector3 &a, const LLVector3 &b); // Returns component of vector a not parallel to vector b (same as projected_vec)
LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u); // Returns a vector that is a linear interpolation between a and b
@@ -493,9 +491,15 @@ inline F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b)
inline LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b)
{
- LLVector3 project_axis = b;
- project_axis.normalize();
- return project_axis * (a * project_axis);
+ F32 bb = b * b;
+ if (bb > FP_MAG_THRESHOLD * FP_MAG_THRESHOLD)
+ {
+ return ((a * b) / bb) * b;
+ }
+ else
+ {
+ return b.zero;
+ }
}
inline LLVector3 inverse_projected_vec(const LLVector3& a, const LLVector3& b)
@@ -571,15 +575,13 @@ inline void update_min_max(LLVector3& min, LLVector3& max, const F32* pos)
inline F32 angle_between(const LLVector3& a, const LLVector3& b)
{
- LLVector3 an = a;
- LLVector3 bn = b;
- an.normalize();
- bn.normalize();
- F32 cosine = an * bn;
- F32 angle = (cosine >= 1.0f) ? 0.0f :
- (cosine <= -1.0f) ? F_PI :
- (F32)acos(cosine);
- return angle;
+ F32 ab = a * b; // dotproduct
+ if (ab == -0.0f)
+ {
+ ab = 0.0f; // get rid of negative zero
+ }
+ LLVector3 c = a % b; // crossproduct
+ return atan2f(sqrtf(c * c), ab); // return the angle
}
inline BOOL are_parallel(const LLVector3 &a, const LLVector3 &b, F32 epsilon)
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index ca48e613d2..8bd134dc84 100755
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -44,6 +44,7 @@ set(llmessage_SOURCE_FILES
llhttpassetstorage.cpp
llhttpclient.cpp
llhttpclientadapter.cpp
+ llhttpconstants.cpp
llhttpnode.cpp
llhttpsender.cpp
llinstantmessage.cpp
@@ -59,7 +60,6 @@ set(llmessage_SOURCE_FILES
llmessagetemplate.cpp
llmessagetemplateparser.cpp
llmessagethrottle.cpp
- llmime.cpp
llnamevalue.cpp
llnullcipher.cpp
llpacketack.cpp
@@ -68,7 +68,6 @@ set(llmessage_SOURCE_FILES
llpartdata.cpp
llproxy.cpp
llpumpio.cpp
- llregionpresenceverifier.cpp
llsdappservices.cpp
llsdhttpserver.cpp
llsdmessage.cpp
@@ -138,6 +137,7 @@ set(llmessage_HEADER_FILES
llhttpclient.h
llhttpclientinterface.h
llhttpclientadapter.h
+ llhttpconstants.h
llhttpnode.h
llhttpnodeadapter.h
llhttpsender.h
@@ -156,7 +156,6 @@ set(llmessage_HEADER_FILES
llmessagetemplate.h
llmessagetemplateparser.h
llmessagethrottle.h
- llmime.h
llmsgvariabletype.h
llnamevalue.h
llnullcipher.h
@@ -169,7 +168,6 @@ set(llmessage_HEADER_FILES
llqueryflags.h
llregionflags.h
llregionhandle.h
- llregionpresenceverifier.h
llsdappservices.h
llsdhttpserver.h
llsdmessage.h
@@ -233,17 +231,15 @@ target_link_libraries(
# tests
if (LL_TESTS)
SET(llmessage_TEST_SOURCE_FILES
- # llhttpclientadapter.cpp
- llmime.cpp
llnamevalue.cpp
lltrustedmessageservice.cpp
lltemplatemessagedispatcher.cpp
- llregionpresenceverifier.cpp
)
LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
# set(TEST_DEBUG on)
set(test_libs
+ ${CURL_LIBRARIES}
${LLMESSAGE_LIBRARIES}
${WINDOWS_LIBRARIES}
${LLVFS_LIBRARIES}
@@ -270,6 +266,7 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(llavatarnamecache "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llhttpclientadapter "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")
endif (LL_TESTS)
diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp
index 81e28121fd..9f90ae1544 100755
--- a/indra/llmessage/llares.cpp
+++ b/indra/llmessage/llares.cpp
@@ -610,6 +610,15 @@ LLAres *ll_init_ares()
return gAres;
}
+void ll_cleanup_ares()
+{
+ if (gAres != NULL)
+ {
+ delete gAres;
+ gAres = NULL;
+ }
+}
+
LLDnsRecord::LLDnsRecord(LLResType type, const std::string &name,
unsigned ttl)
: LLRefCount(),
diff --git a/indra/llmessage/llares.h b/indra/llmessage/llares.h
index 800781ee88..c727363b60 100755
--- a/indra/llmessage/llares.h
+++ b/indra/llmessage/llares.h
@@ -39,7 +39,7 @@
# pragma warning(pop)
#endif
-#ifdef LL_STANDALONE
+#ifdef LL_USESYSTEMLIBS
# include <ares.h>
#else
# include <ares/ares.h>
@@ -578,5 +578,6 @@ extern LLAres *gAres;
* thread safe.
*/
extern LLAres *ll_init_ares();
+extern void ll_cleanup_ares();
#endif // LL_LLARES_H
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index 31dd264021..d02a60b7b2 100755
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -121,7 +121,7 @@ namespace LLAvatarNameCache
// Erase expired names from cache
void eraseUnrefreshed();
- bool expirationFromCacheControl(LLSD headers, F64 *expires);
+ bool expirationFromCacheControl(const LLSD& headers, F64 *expires);
}
/* Sample response:
@@ -165,33 +165,31 @@ namespace LLAvatarNameCache
class LLAvatarNameResponder : public LLHTTPClient::Responder
{
+ LOG_CLASS(LLAvatarNameResponder);
private:
// need to store agent ids that are part of this request in case of
// an error, so we can flag them as unavailable
std::vector<LLUUID> mAgentIDs;
- // Need the headers to look up Expires: and Retry-After:
- LLSD mHeaders;
-
public:
LLAvatarNameResponder(const std::vector<LLUUID>& agent_ids)
- : mAgentIDs(agent_ids),
- mHeaders()
+ : mAgentIDs(agent_ids)
{ }
- /*virtual*/ void completedHeader(U32 status, const std::string& reason,
- const LLSD& headers)
- {
- mHeaders = headers;
- }
-
- /*virtual*/ void result(const LLSD& content)
+protected:
+ /*virtual*/ void httpSuccess()
{
+ const LLSD& content = getContent();
+ if (!content.isMap())
+ {
+ failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
+ return;
+ }
// Pull expiration out of headers if available
- F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(mHeaders);
+ F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(getResponseHeaders());
F64 now = LLFrameTimer::getTotalSeconds();
- LLSD agents = content["agents"];
+ const LLSD& agents = content["agents"];
LLSD::array_const_iterator it = agents.beginArray();
for ( ; it != agents.endArray(); ++it)
{
@@ -212,7 +210,7 @@ public:
}
// Same logic as error response case
- LLSD unresolved_agents = content["bad_ids"];
+ const LLSD& unresolved_agents = content["bad_ids"];
S32 num_unresolved = unresolved_agents.size();
if (num_unresolved > 0)
{
@@ -236,14 +234,13 @@ public:
<< LL_ENDL;
}
- /*virtual*/ void error(U32 status, const std::string& reason)
+ /*virtual*/ void httpFailure()
{
// If there's an error, it might be caused by PeopleApi,
// or when loading textures on startup and using a very slow
// network, this query may time out.
// What we should do depends on whether or not we have a cached name
- LL_WARNS("AvNameCache") << "LLAvatarNameResponder::error " << status << " " << reason
- << LL_ENDL;
+ LL_WARNS("AvNameCache") << dumpResponse() << LL_ENDL;
// Add dummy records for any agent IDs in this request that we do not have cached already
std::vector<LLUUID>::const_iterator it = mAgentIDs.begin();
@@ -700,7 +697,7 @@ void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_na
sCache[agent_id] = av_name;
}
-F64 LLAvatarNameCache::nameExpirationFromHeaders(LLSD headers)
+F64 LLAvatarNameCache::nameExpirationFromHeaders(const LLSD& headers)
{
F64 expires = 0.0;
if (expirationFromCacheControl(headers, &expires))
@@ -716,17 +713,21 @@ F64 LLAvatarNameCache::nameExpirationFromHeaders(LLSD headers)
}
}
-bool LLAvatarNameCache::expirationFromCacheControl(LLSD headers, F64 *expires)
+bool LLAvatarNameCache::expirationFromCacheControl(const LLSD& headers, F64 *expires)
{
bool fromCacheControl = false;
F64 now = LLFrameTimer::getTotalSeconds();
// Allow the header to override the default
- LLSD cache_control_header = headers["cache-control"];
- if (cache_control_header.isDefined())
+ std::string cache_control;
+ if (headers.has(HTTP_IN_HEADER_CACHE_CONTROL))
+ {
+ cache_control = headers[HTTP_IN_HEADER_CACHE_CONTROL].asString();
+ }
+
+ if (!cache_control.empty())
{
S32 max_age = 0;
- std::string cache_control = cache_control_header.asString();
if (max_age_from_cache_control(cache_control, &max_age))
{
*expires = now + (F64)max_age;
diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h
index 3a19cee3ed..ea016b3125 100755
--- a/indra/llmessage/llavatarnamecache.h
+++ b/indra/llmessage/llavatarnamecache.h
@@ -90,7 +90,7 @@ namespace LLAvatarNameCache
// Compute name expiration time from HTTP Cache-Control header,
// or return default value, in seconds from epoch.
- F64 nameExpirationFromHeaders(LLSD headers);
+ F64 nameExpirationFromHeaders(const LLSD& headers);
void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb);
}
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index 147940c983..73df47b933 100755
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -49,6 +49,7 @@
#include "llproxy.h"
#include "llsdserialize.h"
#include "llstl.h"
+#include "llstring.h"
#include "llthread.h"
#include "lltimer.h"
@@ -100,7 +101,7 @@ void check_curl_code(CURLcode code)
{
// linux appears to throw a curl error once per session for a bad initialization
// at a pretty random time (when enabling cookies).
- LL_INFOS() << "curl error detected: " << curl_easy_strerror(code) << LL_ENDL;
+ LL_WARNS("curl") << "curl error detected: " << curl_easy_strerror(code) << LL_ENDL;
}
}
@@ -110,7 +111,7 @@ void check_curl_multi_code(CURLMcode code)
{
// linux appears to throw a curl error once per session for a bad initialization
// at a pretty random time (when enabling cookies).
- LL_INFOS() << "curl multi error detected: " << curl_multi_strerror(code) << LL_ENDL;
+ LL_WARNS("curl") << "curl multi error detected: " << curl_multi_strerror(code) << LL_ENDL;
}
}
@@ -135,6 +136,7 @@ std::string LLCurl::getVersionString()
//////////////////////////////////////////////////////////////////////////////
LLCurl::Responder::Responder()
+ : mHTTPMethod(HTTP_INVALID), mStatus(HTTP_INTERNAL_ERROR)
{
}
@@ -144,22 +146,30 @@ LLCurl::Responder::~Responder()
}
// virtual
-void LLCurl::Responder::errorWithContent(
- U32 status,
- const std::string& reason,
- const LLSD&)
+void LLCurl::Responder::httpFailure()
{
- error(status, reason);
+ LL_WARNS("curl") << dumpResponse() << LL_ENDL;
}
-// virtual
-void LLCurl::Responder::error(U32 status, const std::string& reason)
+std::string LLCurl::Responder::dumpResponse() const
{
- LL_INFOS() << mURL << " [" << status << "]: " << reason << LL_ENDL;
+ std::ostringstream s;
+ s << "[" << httpMethodAsVerb(mHTTPMethod) << ":" << mURL << "] "
+ << "[status:" << mStatus << "] "
+ << "[reason:" << mReason << "] ";
+
+ if (mResponseHeaders.has(HTTP_IN_HEADER_CONTENT_TYPE))
+ {
+ s << "[content-type:" << mResponseHeaders[HTTP_IN_HEADER_CONTENT_TYPE] << "] ";
+ }
+
+ s << "[content:" << mContent << "]";
+
+ return s.str();
}
// virtual
-void LLCurl::Responder::result(const LLSD& content)
+void LLCurl::Responder::httpSuccess()
{
}
@@ -168,44 +178,109 @@ void LLCurl::Responder::setURL(const std::string& url)
mURL = url;
}
+void LLCurl::Responder::successResult(const LLSD& content)
+{
+ setResult(HTTP_OK, "", content);
+ httpSuccess();
+}
+
+void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
+{
+ setResult(status, reason, content);
+ httpFailure();
+}
+
+void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
+{
+ setResult(status, reason, content);
+ httpCompleted();
+}
+
+void LLCurl::Responder::setResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
+{
+ mStatus = status;
+ mReason = reason;
+ mContent = content;
+}
+
+void LLCurl::Responder::setHTTPMethod(EHTTPMethod method)
+{
+ mHTTPMethod = method;
+}
+
+void LLCurl::Responder::setResponseHeader(const std::string& header, const std::string& value)
+{
+ mResponseHeaders[header] = value;
+}
+
+const std::string& LLCurl::Responder::getResponseHeader(const std::string& header) const
+{
+ if (mResponseHeaders.has(header))
+ {
+ return mResponseHeaders[header].asStringRef();
+ }
+ static const std::string empty;
+ return empty;
+}
+
+bool LLCurl::Responder::hasResponseHeader(const std::string& header) const
+{
+ if (mResponseHeaders.has(header)) return true;
+ return false;
+}
+
// virtual
void LLCurl::Responder::completedRaw(
- U32 status,
- const std::string& reason,
const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer)
{
- LLSD content;
LLBufferStream istr(channels, buffer.get());
- const bool emit_errors = false;
- if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(content, istr, emit_errors))
+ const bool emit_parse_errors = false;
+
+ std::string debug_body("(empty)");
+ bool parsed=true;
+ if (EOF == istr.peek())
+ {
+ parsed=false;
+ }
+ // Try to parse body as llsd, no matter what 'content-type' says.
+ else if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(mContent, istr, emit_parse_errors))
+ {
+ parsed=false;
+ char body[1025];
+ body[1024] = '\0';
+ istr.seekg(0, std::ios::beg);
+ istr.get(body,1024);
+ if (strlen(body) > 0)
+ {
+ mContent = body;
+ debug_body = body;
+ }
+ }
+
+ // Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
+ if (!parsed && (HTTP_CONTENT_LLSD_XML == getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE)))
{
- LL_INFOS() << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << LL_ENDL;
- content["reason"] = reason;
+ LL_WARNS() << "Failed to deserialize . " << mURL << " [status:" << mStatus << "] "
+ << "(" << mReason << ") body: " << debug_body << LL_ENDL;
}
- completed(status, reason, content);
+ httpCompleted();
}
// virtual
-void LLCurl::Responder::completed(U32 status, const std::string& reason, const LLSD& content)
+void LLCurl::Responder::httpCompleted()
{
- if (isGoodStatus(status))
+ if (isGoodStatus())
{
- result(content);
+ httpSuccess();
}
else
{
- errorWithContent(status, reason, content);
+ httpFailure();
}
}
-//virtual
-void LLCurl::Responder::completedHeader(U32 status, const std::string& reason, const LLSD& content)
-{
-
-}
-
//////////////////////////////////////////////////////////////////////////////
std::set<CURL*> LLCurl::Easy::sFreeHandles;
@@ -274,6 +349,36 @@ void LLCurl::Easy::releaseEasyHandle(CURL* handle)
}
}
+//static
+void LLCurl::Easy::deleteAllActiveHandles()
+{
+ LLMutexLock lock(sHandleMutexp) ;
+ LL_CHECK_MEMORY
+ for (std::set<CURL*>::iterator activeHandle = sActiveHandles.begin(); activeHandle != sActiveHandles.end(); ++activeHandle)
+ {
+ CURL* curlHandle = *activeHandle;
+ LLCurl::deleteEasyHandle(curlHandle);
+ LL_CHECK_MEMORY
+ }
+
+ sFreeHandles.clear();
+}
+
+//static
+void LLCurl::Easy::deleteAllFreeHandles()
+{
+ LLMutexLock lock(sHandleMutexp) ;
+ LL_CHECK_MEMORY
+ for (std::set<CURL*>::iterator freeHandle = sFreeHandles.begin(); freeHandle != sFreeHandles.end(); ++freeHandle)
+ {
+ CURL* curlHandle = *freeHandle;
+ LLCurl::deleteEasyHandle(curlHandle);
+ LL_CHECK_MEMORY
+ }
+
+ sFreeHandles.clear();
+}
+
LLCurl::Easy::Easy()
: mHeaders(NULL),
mCurlEasyHandle(NULL)
@@ -289,7 +394,8 @@ LLCurl::Easy* LLCurl::Easy::getEasy()
if (!easy->mCurlEasyHandle)
{
// this can happen if we have too many open files (fails in c-ares/ares_init.c)
- LL_WARNS() << "allocEasyHandle() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << LL_ENDL;
+ LL_WARNS("curl") << "allocEasyHandle() returned NULL! Easy handles: "
+ << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << LL_ENDL;
delete easy;
return NULL;
}
@@ -317,10 +423,14 @@ LLCurl::Easy::~Easy()
for_each(mStrings.begin(), mStrings.end(), DeletePointerArray());
LL_CHECK_MEMORY
if (mResponder && LLCurl::sNotQuitting) //aborted
- {
- std::string reason("Request timeout, aborted.") ;
- mResponder->completedRaw(408, //HTTP_REQUEST_TIME_OUT, timeout, abort
- reason, mChannels, mOutput);
+ {
+ // HTTP_REQUEST_TIME_OUT, timeout, abort
+ // *TODO: This looks like improper use of the 408 status code.
+ // See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.9
+ // This status code should be returned by the *server* when:
+ // "The client did not produce a request within the time that the server was prepared to wait."
+ mResponder->setResult(HTTP_REQUEST_TIME_OUT, "Request timeout, aborted.");
+ mResponder->completedRaw(mChannels, mOutput);
LL_CHECK_MEMORY
}
mResponder = NULL;
@@ -384,9 +494,9 @@ void LLCurl::Easy::getTransferInfo(LLCurl::TransferInfo* info)
check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_SPEED_DOWNLOAD, &info->mSpeedDownload));
}
-U32 LLCurl::Easy::report(CURLcode code)
+S32 LLCurl::Easy::report(CURLcode code)
{
- U32 responseCode = 0;
+ S32 responseCode = 0;
std::string responseReason;
if (code == CURLE_OK)
@@ -396,14 +506,15 @@ U32 LLCurl::Easy::report(CURLcode code)
}
else
{
- responseCode = 499;
+ responseCode = HTTP_INTERNAL_ERROR;
responseReason = strerror(code) + " : " + mErrorBuffer;
setopt(CURLOPT_FRESH_CONNECT, TRUE);
}
if (mResponder)
{
- mResponder->completedRaw(responseCode, responseReason, mChannels, mOutput);
+ mResponder->setResult(responseCode, responseReason);
+ mResponder->completedRaw(mChannels, mOutput);
mResponder = NULL;
}
@@ -440,9 +551,31 @@ void LLCurl::Easy::setoptString(CURLoption option, const std::string& value)
check_curl_code(result);
}
+void LLCurl::Easy::slist_append(const std::string& header, const std::string& value)
+{
+ std::string pair(header);
+ if (value.empty())
+ {
+ pair += ":";
+ }
+ else
+ {
+ pair += ": ";
+ pair += value;
+ }
+ slist_append(pair.c_str());
+}
+
void LLCurl::Easy::slist_append(const char* str)
{
- mHeaders = curl_slist_append(mHeaders, str);
+ if (str)
+ {
+ mHeaders = curl_slist_append(mHeaders, str);
+ if (!mHeaders)
+ {
+ LL_WARNS() << "curl_slist_append() call returned NULL appending " << str << LL_ENDL;
+ }
+ }
}
size_t curlReadCallback(char* data, size_t size, size_t nmemb, void* user_data)
@@ -530,8 +663,9 @@ void LLCurl::Easy::prepRequest(const std::string& url,
if (!post)
{
- slist_append("Connection: keep-alive");
- slist_append("Keep-alive: 300");
+ // *TODO: Should this be set to 'Keep-Alive' ?
+ slist_append(HTTP_OUT_HEADER_CONNECTION, "keep-alive");
+ slist_append(HTTP_OUT_HEADER_KEEP_ALIVE, "300");
// Accept and other headers
for (std::vector<std::string>::const_iterator iter = headers.begin();
iter != headers.end(); ++iter)
@@ -810,7 +944,7 @@ S32 LLCurl::Multi::process()
++processed;
if (msg->msg == CURLMSG_DONE)
{
- U32 response = 0;
+ S32 response = 0;
Easy* easy = NULL ;
{
@@ -829,7 +963,7 @@ S32 LLCurl::Multi::process()
}
else
{
- response = 499;
+ response = HTTP_INTERNAL_ERROR;
//*TODO: change to LL_WARNS()
LL_ERRS() << "cleaned up curl request completed!" << LL_ENDL;
}
@@ -1128,13 +1262,13 @@ bool LLCurlRequest::getByteRange(const std::string& url,
easy->setopt(CURLOPT_HTTPGET, 1);
if (length > 0)
{
- std::string range = llformat("Range: bytes=%d-%d", offset,offset+length-1);
- easy->slist_append(range.c_str());
+ std::string range = llformat("bytes=%d-%d", offset,offset+length-1);
+ easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
}
else if (offset > 0)
{
- std::string range = llformat("Range: bytes=%d-", offset);
- easy->slist_append(range.c_str());
+ std::string range = llformat("bytes=%d-", offset);
+ easy->slist_append(HTTP_OUT_HEADER_RANGE, range);
}
easy->setHeaders();
bool res = addEasy(easy);
@@ -1161,7 +1295,7 @@ bool LLCurlRequest::post(const std::string& url,
easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
- easy->slist_append("Content-Type: application/llsd+xml");
+ easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
easy->setHeaders();
LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
@@ -1189,7 +1323,7 @@ bool LLCurlRequest::post(const std::string& url,
easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
- easy->slist_append("Content-Type: application/octet-stream");
+ easy->slist_append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_OCTET_STREAM);
easy->setHeaders();
LL_DEBUGS() << "POSTING: " << bytes << " bytes." << LL_ENDL;
@@ -1561,6 +1695,14 @@ void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void*
}
}
+void LLCurlEasyRequest::slist_append(const std::string& header, const std::string& value)
+{
+ if (isValid() && mEasy)
+ {
+ mEasy->slist_append(header, value);
+ }
+}
+
void LLCurlEasyRequest::slist_append(const char* str)
{
if (isValid() && mEasy)
@@ -1745,17 +1887,14 @@ void LLCurl::cleanupClass()
#endif
LL_CHECK_MEMORY
-
- for (std::set<CURL*>::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter)
- {
- CURL* curl = *iter;
- LLCurl::deleteEasyHandle(curl);
- }
-
+ Easy::deleteAllFreeHandles();
+ LL_CHECK_MEMORY
+ Easy::deleteAllActiveHandles();
LL_CHECK_MEMORY
- Easy::sFreeHandles.clear();
-
+ // Free the template easy handle
+ curl_easy_cleanup(sCurlTemplateStandardHandle);
+ sCurlTemplateStandardHandle = NULL;
LL_CHECK_MEMORY
delete Easy::sHandleMutexp ;
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index fc9761ff9f..385d9fffa8 100755
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -39,6 +39,7 @@
#include <curl/curl.h> // TODO: remove dependency
#include "llbuffer.h"
+#include "llhttpconstants.h"
#include "lliopipe.h"
#include "llsd.h"
#include "llqueuedthread.h"
@@ -76,59 +77,92 @@ public:
Responder();
virtual ~Responder();
+ virtual bool followRedir()
+ {
+ return false;
+ }
+
/**
* @brief return true if the status code indicates success.
*/
- static bool isGoodStatus(U32 status)
- {
- return((200 <= status) && (status < 300));
- }
-
- virtual void errorWithContent(
- U32 status,
- const std::string& reason,
- const LLSD& content);
- //< called by completed() on bad status
+ bool isGoodStatus() const { return isHttpGoodStatus(mStatus); }
- virtual void error(U32 status, const std::string& reason);
- //< called by default error(status, reason, content)
-
- virtual void result(const LLSD& content);
- //< called by completed for good status codes.
+ S32 getStatus() const { return mStatus; }
+ const std::string& getReason() const { return mReason; }
+ const LLSD& getContent() const { return mContent; }
+ bool hasResponseHeader(const std::string& header) const;
+ const std::string& getResponseHeader(const std::string& header) const;
+ const LLSD& getResponseHeaders() const { return mResponseHeaders; }
+ const std::string& getURL() const { return mURL; }
+ EHTTPMethod getHTTPMethod() const { return mHTTPMethod; }
+
+ // This formats response information for use in log spam. Includes content spam.
+ std::string dumpResponse() const;
+ // Allows direct triggering of success/error with different results.
+ void completeResult(S32 status, const std::string& reason, const LLSD& content = LLSD());
+ void successResult(const LLSD& content);
+ void failureResult(S32 status, const std::string& reason, const LLSD& content = LLSD());
+
+ // The default implementation will try to parse body content as an LLSD, however
+ // it should not spam about parsing failures unless the server sent a
+ // Content-Type: application/llsd+xml header.
virtual void completedRaw(
- U32 status,
- const std::string& reason,
const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer);
/**< Override point for clients that may want to use this
class when the response is some other format besides LLSD
*/
+
+
+ // The http* methods are not public since these should be triggered internally
+ // after status, reason, content, etc have been set.
+ // If you need to trigger a completion method, use the *Result methods, above.
+ protected:
+ // These methods are the preferred way to process final results.
+ // By default, when one of these is called the following information will be resolved:
+ // * HTTP status code - getStatus()
+ // * Reason string - getReason()
+ // * Content - getContent()
+ // * Response Headers - getResponseHeaders()
+
+ // By default, httpSuccess is triggered whenever httpCompleted is called with a 2xx status code.
+ virtual void httpSuccess();
+ //< called by completed for good status codes.
- virtual void completed(
- U32 status,
- const std::string& reason,
- const LLSD& content);
- /**< The default implemetnation calls
+ // By default, httpFailure is triggered whenever httpCompleted is called with a non-2xx status code.
+ virtual void httpFailure();
+ //< called by httpCompleted() on bad status
+
+ // httpCompleted does not generally need to be overridden, unless
+ // you don't care about the status code (which determine httpFailure or httpSuccess)
+ // or if you want to re-interpret what a 'good' vs' bad' status code is.
+ virtual void httpCompleted();
+ /**< The default implementation calls
either:
- * result(), or
- * error()
+ * httpSuccess(), or
+ * httpFailure()
*/
-
- // Override to handle parsing of the header only. Note: this is the only place where the contents
- // of the header can be parsed. In the ::completed call above only the body is contained in the LLSD.
- virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content);
-
- // Used internally to set the url for debugging later.
- void setURL(const std::string& url);
- virtual bool followRedir()
- {
- return false;
- }
+ public:
+ void setHTTPMethod(EHTTPMethod method);
+ void setURL(const std::string& url);
+ void setResult(S32 status, const std::string& reason, const LLSD& content = LLSD());
+ void setResponseHeader(const std::string& header, const std::string& value);
private:
+ // These can be accessed by the get* methods. Treated as 'read-only' during completion handlers.
+ EHTTPMethod mHTTPMethod;
std::string mURL;
+ LLSD mResponseHeaders;
+
+ protected:
+ // These should also generally be treated as 'read-only' during completion handlers
+ // and should be accessed by the get* methods. The exception to this rule would
+ // be when overriding the completedRaw method in preparation for calling httpCompleted().
+ S32 mStatus;
+ std::string mReason;
+ LLSD mContent;
};
typedef LLPointer<Responder> ResponderPtr;
@@ -227,10 +261,11 @@ public:
// Copies the string so that it is guaranteed to stick around
void setoptString(CURLoption option, const std::string& value);
+ void slist_append(const std::string& header, const std::string& value);
void slist_append(const char* str);
void setHeaders();
- U32 report(CURLcode);
+ S32 report(CURLcode);
void getTransferInfo(LLCurl::TransferInfo* info);
void prepRequest(const std::string& url, const std::vector<std::string>& headers, LLCurl::ResponderPtr, S32 time_out = 0, bool post = false);
@@ -269,6 +304,9 @@ private:
static std::set<CURL*> sFreeHandles;
static std::set<CURL*> sActiveHandles;
static LLMutex* sHandleMutexp ;
+
+ static void deleteAllActiveHandles();
+ static void deleteAllFreeHandles();
};
class LLCurl::Multi
@@ -486,6 +524,7 @@ public:
void setWriteCallback(curl_write_callback callback, void* userdata);
void setReadCallback(curl_read_callback callback, void* userdata);
void setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata);
+ void slist_append(const std::string& header, const std::string& value);
void slist_append(const char* str);
void sendRequest(const std::string& url);
void requestComplete();
diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp
index 095da6f0f9..a30140e8f3 100755
--- a/indra/llmessage/llhttpassetstorage.cpp
+++ b/indra/llmessage/llhttpassetstorage.cpp
@@ -38,7 +38,7 @@
#include "llvfs.h"
#include "llxfer.h"
-#ifdef LL_STANDALONE
+#ifdef LL_USESYSTEMLIBS
# include <zlib.h>
#else
# include "zlib/zlib.h"
@@ -54,13 +54,6 @@ const F32 GET_URL_TO_FILE_TIMEOUT = 1800.0f;
const S32 COMPRESSED_INPUT_BUFFER_SIZE = 4096;
-const S32 HTTP_OK = 200;
-const S32 HTTP_PUT_OK = 201;
-const S32 HTTP_NO_CONTENT = 204;
-const S32 HTTP_MISSING = 404;
-const S32 HTTP_SERVER_BAD_GATEWAY = 502;
-const S32 HTTP_SERVER_TEMP_UNAVAILABLE = 503;
-
/////////////////////////////////////////////////////////////////////////////////
// LLTempAssetData
// An asset not stored on central asset store, but on a simulator node somewhere.
@@ -955,7 +948,7 @@ void LLHTTPAssetStorage::checkForTimeouts()
{
if (curl_msg->data.result == CURLE_OK &&
( curl_result == HTTP_OK
- || curl_result == HTTP_PUT_OK
+ || curl_result == HTTP_CREATED
|| curl_result == HTTP_NO_CONTENT))
{
LL_INFOS() << "Success uploading " << req->getUUID() << " to " << req->mURLBuffer << LL_ENDL;
@@ -966,8 +959,8 @@ void LLHTTPAssetStorage::checkForTimeouts()
}
else if (curl_msg->data.result == CURLE_COULDNT_CONNECT ||
curl_msg->data.result == CURLE_OPERATION_TIMEOUTED ||
- curl_result == HTTP_SERVER_BAD_GATEWAY ||
- curl_result == HTTP_SERVER_TEMP_UNAVAILABLE)
+ curl_result == HTTP_BAD_GATEWAY ||
+ curl_result == HTTP_SERVICE_UNAVAILABLE)
{
LL_WARNS() << "Re-requesting upload for " << req->getUUID() << ". Received upload error to " << req->mURLBuffer <<
" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << LL_ENDL;
@@ -988,8 +981,8 @@ void LLHTTPAssetStorage::checkForTimeouts()
if (!(curl_msg->data.result == CURLE_COULDNT_CONNECT ||
curl_msg->data.result == CURLE_OPERATION_TIMEOUTED ||
- curl_result == HTTP_SERVER_BAD_GATEWAY ||
- curl_result == HTTP_SERVER_TEMP_UNAVAILABLE))
+ curl_result == HTTP_BAD_GATEWAY ||
+ curl_result == HTTP_SERVICE_UNAVAILABLE))
{
// shared upload finished callback
// in the base class, this is called from processUploadComplete
@@ -1021,7 +1014,7 @@ void LLHTTPAssetStorage::checkForTimeouts()
LL_WARNS() << "Failure downloading " << req->mURLBuffer <<
" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << LL_ENDL;
- xfer_result = (curl_result == HTTP_MISSING) ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
+ xfer_result = (curl_result == HTTP_NOT_FOUND) ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
if (req->mVFile)
{
@@ -1243,7 +1236,7 @@ S32 LLHTTPAssetStorage::getURLToFile(const LLUUID& uuid, LLAssetType::EType asse
}
else
{
- xfer_result = curl_result == HTTP_MISSING ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
+ xfer_result = curl_result == HTTP_NOT_FOUND ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED;
LL_INFOS() << "Failure downloading " << req.mURLBuffer <<
" with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << LL_ENDL;
}
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 31a499b370..200116337d 100755
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -54,7 +54,7 @@ namespace
{
public:
LLHTTPClientURLAdaptor(LLCurl::ResponderPtr responder)
- : LLURLRequestComplete(), mResponder(responder), mStatus(499),
+ : LLURLRequestComplete(), mResponder(responder), mStatus(HTTP_INTERNAL_ERROR),
mReason("LLURLRequest complete w/no status")
{
}
@@ -63,7 +63,7 @@ namespace
{
}
- virtual void httpStatus(U32 status, const std::string& reason)
+ virtual void httpStatus(S32 status, const std::string& reason)
{
LLURLRequestComplete::httpStatus(status,reason);
@@ -74,30 +74,33 @@ namespace
virtual void complete(const LLChannelDescriptors& channels,
const buffer_ptr_t& buffer)
{
+ // *TODO: Re-interpret mRequestStatus codes?
+ // Would like to detect curl errors, such as
+ // connection errors, write erros, etc.
if (mResponder.get())
{
- // Allow clients to parse headers before we attempt to parse
- // the body and provide completed/result/error calls.
- mResponder->completedHeader(mStatus, mReason, mHeaderOutput);
- mResponder->completedRaw(mStatus, mReason, channels, buffer);
+ mResponder->setResult(mStatus, mReason);
+ mResponder->completedRaw(channels, buffer);
}
}
virtual void header(const std::string& header, const std::string& value)
{
- mHeaderOutput[header] = value;
+ if (mResponder.get())
+ {
+ mResponder->setResponseHeader(header, value);
+ }
}
private:
LLCurl::ResponderPtr mResponder;
- U32 mStatus;
+ S32 mStatus;
std::string mReason;
- LLSD mHeaderOutput;
};
class Injector : public LLIOPipe
{
public:
- virtual const char* contentType() = 0;
+ virtual const std::string& contentType() = 0;
};
class LLSDInjector : public Injector
@@ -106,7 +109,7 @@ namespace
LLSDInjector(const LLSD& sd) : mSD(sd) {}
virtual ~LLSDInjector() {}
- const char* contentType() { return "application/llsd+xml"; }
+ const std::string& contentType() { return HTTP_CONTENT_LLSD_XML; }
virtual EStatus process_impl(const LLChannelDescriptors& channels,
buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -124,9 +127,9 @@ namespace
{
public:
RawInjector(const U8* data, S32 size) : mData(data), mSize(size) {}
- virtual ~RawInjector() {delete mData;}
+ virtual ~RawInjector() {delete [] mData;}
- const char* contentType() { return "application/octet-stream"; }
+ const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
virtual EStatus process_impl(const LLChannelDescriptors& channels,
buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -147,7 +150,7 @@ namespace
FileInjector(const std::string& filename) : mFilename(filename) {}
virtual ~FileInjector() {}
- const char* contentType() { return "application/octet-stream"; }
+ const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
virtual EStatus process_impl(const LLChannelDescriptors& channels,
buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -180,7 +183,7 @@ namespace
VFileInjector(const LLUUID& uuid, LLAssetType::EType asset_type) : mUUID(uuid), mAssetType(asset_type) {}
virtual ~VFileInjector() {}
- const char* contentType() { return "application/octet-stream"; }
+ const std::string& contentType() { return HTTP_CONTENT_OCTET_STREAM; }
virtual EStatus process_impl(const LLChannelDescriptors& channels,
buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
@@ -213,7 +216,7 @@ void LLHTTPClient::setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback cal
static void request(
const std::string& url,
- LLURLRequest::ERequestAction method,
+ EHTTPMethod method,
Injector* body_injector,
LLCurl::ResponderPtr responder,
const F32 timeout = HTTP_REQUEST_EXPIRY_SECS,
@@ -225,7 +228,7 @@ static void request(
{
if (responder)
{
- responder->completed(U32_MAX, "No pump", LLSD());
+ responder->completeResult(HTTP_INTERNAL_ERROR, "No pump");
}
delete body_injector;
return;
@@ -237,90 +240,82 @@ static void request(
{
if (responder)
{
- responder->completed(498, "Internal Error - curl failure", LLSD());
+ responder->completeResult(HTTP_INTERNAL_CURL_ERROR, "Internal Error - curl failure");
}
- delete req ;
+ delete req;
delete body_injector;
- return ;
+ return;
}
req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req);
-
- LL_DEBUGS() << LLURLRequest::actionAsVerb(method) << " " << url << " "
- << headers << LL_ENDL;
+ LL_DEBUGS("LLHTTPClient") << httpMethodAsVerb(method) << " " << url << " " << headers << LL_ENDL;
// Insert custom headers if the caller sent any
if (headers.isMap())
{
- if (headers.has("Cookie"))
+ if (headers.has(HTTP_OUT_HEADER_COOKIE))
{
req->allowCookies();
}
- LLSD::map_const_iterator iter = headers.beginMap();
- LLSD::map_const_iterator end = headers.endMap();
+ LLSD::map_const_iterator iter = headers.beginMap();
+ LLSD::map_const_iterator end = headers.endMap();
- for (; iter != end; ++iter)
- {
- std::ostringstream header;
- //if the header is "Pragma" with no value
- //the caller intends to force libcurl to drop
- //the Pragma header it so gratuitously inserts
- //Before inserting the header, force libcurl
- //to not use the proxy (read: llurlrequest.cpp)
- static const std::string PRAGMA("Pragma");
- if ((iter->first == PRAGMA) && (iter->second.asString().empty()))
- {
- req->useProxy(false);
- }
- header << iter->first << ": " << iter->second.asString() ;
- LL_DEBUGS() << "header = " << header.str() << LL_ENDL;
- req->addHeader(header.str().c_str());
- }
- }
+ for (; iter != end; ++iter)
+ {
+ //if the header is "Pragma" with no value
+ //the caller intends to force libcurl to drop
+ //the Pragma header it so gratuitously inserts
+ //Before inserting the header, force libcurl
+ //to not use the proxy (read: llurlrequest.cpp)
+ if ((iter->first == HTTP_OUT_HEADER_PRAGMA) && (iter->second.asString().empty()))
+ {
+ req->useProxy(false);
+ }
+ LL_DEBUGS("LLHTTPClient") << "header = " << iter->first
+ << ": " << iter->second.asString() << LL_ENDL;
+ req->addHeader(iter->first, iter->second.asString());
+ }
+ }
// Check to see if we have already set Accept or not. If no one
// set it, set it to application/llsd+xml since that's what we
// almost always want.
- if( method != LLURLRequest::HTTP_PUT && method != LLURLRequest::HTTP_POST )
+ if( method != HTTP_PUT && method != HTTP_POST )
{
- static const std::string ACCEPT("Accept");
- if(!headers.has(ACCEPT))
+ if(!headers.has(HTTP_OUT_HEADER_ACCEPT))
{
- req->addHeader("Accept: application/llsd+xml");
+ req->addHeader(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML);
}
}
if (responder)
{
responder->setURL(url);
+ responder->setHTTPMethod(method);
}
req->setCallback(new LLHTTPClientURLAdaptor(responder));
- if (method == LLURLRequest::HTTP_POST && gMessageSystem)
+ if (method == HTTP_POST && gMessageSystem)
{
- req->addHeader(llformat("X-SecondLife-UDP-Listen-Port: %d",
- gMessageSystem->mPort).c_str());
- }
+ req->addHeader("X-SecondLife-UDP-Listen-Port", llformat("%d",
+ gMessageSystem->mPort));
+ }
- if (method == LLURLRequest::HTTP_PUT || method == LLURLRequest::HTTP_POST)
+ if (method == HTTP_PUT || method == HTTP_POST || method == HTTP_PATCH)
{
- static const std::string CONTENT_TYPE("Content-Type");
- if(!headers.has(CONTENT_TYPE))
+ if(!headers.has(HTTP_OUT_HEADER_CONTENT_TYPE))
{
// If the Content-Type header was passed in, it has
// already been added as a header through req->addHeader
// in the loop above. We defer to the caller's wisdom, but
// if they did not specify a Content-Type, then ask the
// injector.
- req->addHeader(
- llformat(
- "Content-Type: %s",
- body_injector->contentType()).c_str());
+ req->addHeader(HTTP_OUT_HEADER_CONTENT_TYPE, body_injector->contentType());
}
- chain.push_back(LLIOPipe::ptr_t(body_injector));
+ chain.push_back(LLIOPipe::ptr_t(body_injector));
}
chain.push_back(LLIOPipe::ptr_t(req));
@@ -342,9 +337,9 @@ void LLHTTPClient::getByteRange(
if(offset > 0 || bytes > 0)
{
std::string range = llformat("bytes=%d-%d", offset, offset+bytes-1);
- headers["Range"] = range;
+ headers[HTTP_OUT_HEADER_RANGE] = range;
}
- request(url,LLURLRequest::HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
+ request(url,HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
}
void LLHTTPClient::head(
@@ -354,18 +349,18 @@ void LLHTTPClient::head(
const F32 timeout,
bool follow_redirects /* = true */)
{
- request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
+ request(url, HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
}
void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout,
bool follow_redirects /* = true */)
{
- request(url, LLURLRequest::HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
+ request(url, HTTP_GET, NULL, responder, timeout, headers, follow_redirects);
}
void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const LLSD& headers,
const F32 timeout, bool follow_redirects /* = true */)
{
- request(url, LLURLRequest::HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
+ request(url, HTTP_HEAD, NULL, responder, timeout, headers, follow_redirects);
}
void LLHTTPClient::getHeaderOnly(const std::string& url, ResponderPtr responder, const F32 timeout,
bool follow_redirects /* = true */)
@@ -408,7 +403,7 @@ public:
return content;
}
- std::string asString()
+ const std::string& asString()
{
return mBuffer;
}
@@ -437,7 +432,7 @@ private:
*/
static LLSD blocking_request(
const std::string& url,
- LLURLRequest::ERequestAction method,
+ EHTTPMethod method,
const LLSD& body,
const LLSD& headers = LLSD(),
const F32 timeout = 5
@@ -480,11 +475,11 @@ static LLSD blocking_request(
}
// * Setup specific method / "verb" for the URI (currently only GET and POST supported + poppy)
- if (method == LLURLRequest::HTTP_GET)
+ if (method == HTTP_GET)
{
curl_easy_setopt(curlp, CURLOPT_HTTPGET, 1);
}
- else if (method == LLURLRequest::HTTP_POST)
+ else if (method == HTTP_POST)
{
curl_easy_setopt(curlp, CURLOPT_POST, 1);
//serialize to ostr then copy to str - need to because ostr ptr is unstable :(
@@ -493,18 +488,20 @@ static LLSD blocking_request(
body_str = ostr.str();
curl_easy_setopt(curlp, CURLOPT_POSTFIELDS, body_str.c_str());
//copied from PHP libs, correct?
- headers_list = curl_slist_append(headers_list, "Content-Type: application/llsd+xml");
+ headers_list = curl_slist_append(headers_list,
+ llformat("%s: %s", HTTP_OUT_HEADER_CONTENT_TYPE.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
// copied from llurlrequest.cpp
// it appears that apache2.2.3 or django in etch is busted. If
// we do not clear the expect header, we get a 500. May be
// limited to django/mod_wsgi.
- headers_list = curl_slist_append(headers_list, "Expect:");
+ headers_list = curl_slist_append(headers_list, llformat("%s:", HTTP_OUT_HEADER_EXPECT.c_str()).c_str());
}
// * Do the action using curl, handle results
LL_DEBUGS() << "HTTP body: " << body_str << LL_ENDL;
- headers_list = curl_slist_append(headers_list, "Accept: application/llsd+xml");
+ headers_list = curl_slist_append(headers_list,
+ llformat("%s: %s", HTTP_OUT_HEADER_ACCEPT.c_str(), HTTP_CONTENT_LLSD_XML.c_str()).c_str());
CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, headers_list);
if ( curl_result != CURLE_OK )
{
@@ -513,11 +510,11 @@ static LLSD blocking_request(
LLSD response = LLSD::emptyMap();
S32 curl_success = curl_easy_perform(curlp);
- S32 http_status = 499;
+ S32 http_status = HTTP_INTERNAL_ERROR;
curl_easy_getinfo(curlp, CURLINFO_RESPONSE_CODE, &http_status);
response["status"] = http_status;
// if we get a non-404 and it's not a 200 OR maybe it is but you have error bits,
- if ( http_status != 404 && (http_status != 200 || curl_success != 0) )
+ if ( http_status != HTTP_NOT_FOUND && (http_status != HTTP_OK || curl_success != 0) )
{
// We expect 404s, don't spam for them.
LL_WARNS() << "CURL REQ URL: " << url << LL_ENDL;
@@ -547,12 +544,12 @@ static LLSD blocking_request(
LLSD LLHTTPClient::blockingGet(const std::string& url)
{
- return blocking_request(url, LLURLRequest::HTTP_GET, LLSD());
+ return blocking_request(url, HTTP_GET, LLSD());
}
LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body)
{
- return blocking_request(url, LLURLRequest::HTTP_POST, body);
+ return blocking_request(url, HTTP_POST, body);
}
void LLHTTPClient::put(
@@ -562,7 +559,17 @@ void LLHTTPClient::put(
const LLSD& headers,
const F32 timeout)
{
- request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder, timeout, headers);
+ request(url, HTTP_PUT, new LLSDInjector(body), responder, timeout, headers);
+}
+
+void LLHTTPClient::patch(
+ const std::string& url,
+ const LLSD& body,
+ ResponderPtr responder,
+ const LLSD& headers,
+ const F32 timeout)
+{
+ request(url, HTTP_PATCH, new LLSDInjector(body), responder, timeout, headers);
}
void LLHTTPClient::post(
@@ -572,7 +579,7 @@ void LLHTTPClient::post(
const LLSD& headers,
const F32 timeout)
{
- request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder, timeout, headers);
+ request(url, HTTP_POST, new LLSDInjector(body), responder, timeout, headers);
}
void LLHTTPClient::postRaw(
@@ -583,7 +590,7 @@ void LLHTTPClient::postRaw(
const LLSD& headers,
const F32 timeout)
{
- request(url, LLURLRequest::HTTP_POST, new RawInjector(data, size), responder, timeout, headers);
+ request(url, HTTP_POST, new RawInjector(data, size), responder, timeout, headers);
}
void LLHTTPClient::postFile(
@@ -593,7 +600,7 @@ void LLHTTPClient::postFile(
const LLSD& headers,
const F32 timeout)
{
- request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder, timeout, headers);
+ request(url, HTTP_POST, new FileInjector(filename), responder, timeout, headers);
}
void LLHTTPClient::postFile(
@@ -604,7 +611,7 @@ void LLHTTPClient::postFile(
const LLSD& headers,
const F32 timeout)
{
- request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout, headers);
+ request(url, HTTP_POST, new VFileInjector(uuid, asset_type), responder, timeout, headers);
}
// static
@@ -614,7 +621,7 @@ void LLHTTPClient::del(
const LLSD& headers,
const F32 timeout)
{
- request(url, LLURLRequest::HTTP_DELETE, NULL, responder, timeout, headers);
+ request(url, HTTP_DELETE, NULL, responder, timeout, headers);
}
// static
@@ -626,8 +633,21 @@ void LLHTTPClient::move(
const F32 timeout)
{
LLSD headers = hdrs;
- headers["Destination"] = destination;
- request(url, LLURLRequest::HTTP_MOVE, NULL, responder, timeout, headers);
+ headers[HTTP_OUT_HEADER_DESTINATION] = destination;
+ request(url, HTTP_MOVE, NULL, responder, timeout, headers);
+}
+
+// static
+void LLHTTPClient::copy(
+ const std::string& url,
+ const std::string& destination,
+ ResponderPtr responder,
+ const LLSD& hdrs,
+ const F32 timeout)
+{
+ LLSD headers = hdrs;
+ headers[HTTP_OUT_HEADER_DESTINATION] = destination;
+ request(url, HTTP_COPY, NULL, responder, timeout, headers);
}
diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h
index 5de257a4f6..b18258fd7b 100755
--- a/indra/llmessage/llhttpclient.h
+++ b/indra/llmessage/llhttpclient.h
@@ -79,6 +79,14 @@ public:
ResponderPtr,
const LLSD& headers = LLSD(),
const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
+
+ static void patch(
+ const std::string& url,
+ const LLSD& body,
+ ResponderPtr,
+ const LLSD& headers = LLSD(),
+ const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
+
static void getHeaderOnly(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS,
bool follow_redirects = true);
static void getHeaderOnly(const std::string& url, ResponderPtr, const LLSD& headers,
@@ -118,7 +126,7 @@ public:
const LLSD& headers = LLSD(),
const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
///< sends a DELETE method, but we can't call it delete in c++
-
+
/**
* @brief Send a MOVE webdav method
*
@@ -135,6 +143,22 @@ public:
const LLSD& headers = LLSD(),
const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
+ /**
+ * @brief Send a COPY webdav method
+ *
+ * @param url The complete serialized (and escaped) url to get.
+ * @param destination The complete serialized destination url.
+ * @param responder The responder that will handle the result.
+ * @param headers A map of key:value headers to pass to the request
+ * @param timeout The number of seconds to give the server to respond.
+ */
+ static void copy(
+ const std::string& url,
+ const std::string& destination,
+ ResponderPtr responder,
+ const LLSD& headers = LLSD(),
+ const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);
+
//@}
/**
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index dcd2d79d67..b56a804f94 100755
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -35,18 +35,18 @@ void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr respo
{
LLSD empty_pragma_header;
// Pragma is required to stop curl adding "no-cache"
- // Space is required to stop llurlrequest from turnning off proxying
- empty_pragma_header["Pragma"] = " ";
+ // Space is required to stop llurlrequest from turning off proxying
+ empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " ";
LLHTTPClient::get(url, responder, empty_pragma_header);
}
void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers)
{
LLSD empty_pragma_header = headers;
- if (!empty_pragma_header.has("Pragma"))
+ if (!empty_pragma_header.has(HTTP_OUT_HEADER_PRAGMA))
{
- // as above
- empty_pragma_header["Pragma"] = " ";
+ // as above
+ empty_pragma_header[HTTP_OUT_HEADER_PRAGMA] = " ";
}
LLHTTPClient::get(url, responder, empty_pragma_header);
}
@@ -56,3 +56,18 @@ void LLHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::
LLHTTPClient::put(url, body, responder);
}
+void LLHTTPClientAdapter::put(
+ const std::string& url,
+ const LLSD& body,
+ LLCurl::ResponderPtr responder,
+ const LLSD& headers)
+{
+ LLHTTPClient::put(url, body, responder, headers);
+}
+
+void LLHTTPClientAdapter::del(
+ const std::string& url,
+ LLCurl::ResponderPtr responder)
+{
+ LLHTTPClient::del(url, responder);
+}
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
index aae6426a59..270282c66f 100755
--- a/indra/llmessage/llhttpclientadapter.h
+++ b/indra/llmessage/llhttpclientadapter.h
@@ -37,6 +37,14 @@ public:
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);
+ virtual void put(
+ const std::string& url,
+ const LLSD& body,
+ LLCurl::ResponderPtr responder,
+ const LLSD& headers);
+ virtual void del(
+ const std::string& url,
+ LLCurl::ResponderPtr responder);
};
#endif
diff --git a/indra/llmessage/llhttpconstants.cpp b/indra/llmessage/llhttpconstants.cpp
new file mode 100755
index 0000000000..01f4a080b0
--- /dev/null
+++ b/indra/llmessage/llhttpconstants.cpp
@@ -0,0 +1,228 @@
+/**
+ * @file llhttpconstants.cpp
+ * @brief Implementation of the HTTP request / response constant lookups
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ *
+ * Copyright (c) 2013, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llhttpconstants.h"
+#include "lltimer.h"
+
+// for curl_getdate() (apparently parsing RFC 1123 dates is hard)
+#include <curl/curl.h>
+
+// Outgoing headers. Do *not* use these to check incoming headers.
+// For incoming headers, use the lower-case headers, below.
+const std::string HTTP_OUT_HEADER_ACCEPT("Accept");
+const std::string HTTP_OUT_HEADER_ACCEPT_CHARSET("Accept-Charset");
+const std::string HTTP_OUT_HEADER_ACCEPT_ENCODING("Accept-Encoding");
+const std::string HTTP_OUT_HEADER_ACCEPT_LANGUAGE("Accept-Language");
+const std::string HTTP_OUT_HEADER_ACCEPT_RANGES("Accept-Ranges");
+const std::string HTTP_OUT_HEADER_AGE("Age");
+const std::string HTTP_OUT_HEADER_ALLOW("Allow");
+const std::string HTTP_OUT_HEADER_AUTHORIZATION("Authorization");
+const std::string HTTP_OUT_HEADER_CACHE_CONTROL("Cache-Control");
+const std::string HTTP_OUT_HEADER_CONNECTION("Connection");
+const std::string HTTP_OUT_HEADER_CONTENT_DESCRIPTION("Content-Description");
+const std::string HTTP_OUT_HEADER_CONTENT_ENCODING("Content-Encoding");
+const std::string HTTP_OUT_HEADER_CONTENT_ID("Content-ID");
+const std::string HTTP_OUT_HEADER_CONTENT_LANGUAGE("Content-Language");
+const std::string HTTP_OUT_HEADER_CONTENT_LENGTH("Content-Length");
+const std::string HTTP_OUT_HEADER_CONTENT_LOCATION("Content-Location");
+const std::string HTTP_OUT_HEADER_CONTENT_MD5("Content-MD5");
+const std::string HTTP_OUT_HEADER_CONTENT_RANGE("Content-Range");
+const std::string HTTP_OUT_HEADER_CONTENT_TRANSFER_ENCODING("Content-Transfer-Encoding");
+const std::string HTTP_OUT_HEADER_CONTENT_TYPE("Content-Type");
+const std::string HTTP_OUT_HEADER_COOKIE("Cookie");
+const std::string HTTP_OUT_HEADER_DATE("Date");
+const std::string HTTP_OUT_HEADER_DESTINATION("Destination");
+const std::string HTTP_OUT_HEADER_ETAG("ETag");
+const std::string HTTP_OUT_HEADER_EXPECT("Expect");
+const std::string HTTP_OUT_HEADER_EXPIRES("Expires");
+const std::string HTTP_OUT_HEADER_FROM("From");
+const std::string HTTP_OUT_HEADER_HOST("Host");
+const std::string HTTP_OUT_HEADER_IF_MATCH("If-Match");
+const std::string HTTP_OUT_HEADER_IF_MODIFIED_SINCE("If-Modified-Since");
+const std::string HTTP_OUT_HEADER_IF_NONE_MATCH("If-None-Match");
+const std::string HTTP_OUT_HEADER_IF_RANGE("If-Range");
+const std::string HTTP_OUT_HEADER_IF_UNMODIFIED_SINCE("If-Unmodified-Since");
+const std::string HTTP_OUT_HEADER_KEEP_ALIVE("Keep-Alive");
+const std::string HTTP_OUT_HEADER_LAST_MODIFIED("Last-Modified");
+const std::string HTTP_OUT_HEADER_LOCATION("Location");
+const std::string HTTP_OUT_HEADER_MAX_FORWARDS("Max-Forwards");
+const std::string HTTP_OUT_HEADER_MIME_VERSION("MIME-Version");
+const std::string HTTP_OUT_HEADER_PRAGMA("Pragma");
+const std::string HTTP_OUT_HEADER_PROXY_AUTHENTICATE("Proxy-Authenticate");
+const std::string HTTP_OUT_HEADER_PROXY_AUTHORIZATION("Proxy-Authorization");
+const std::string HTTP_OUT_HEADER_RANGE("Range");
+const std::string HTTP_OUT_HEADER_REFERER("Referer");
+const std::string HTTP_OUT_HEADER_RETRY_AFTER("Retry-After");
+const std::string HTTP_OUT_HEADER_SERVER("Server");
+const std::string HTTP_OUT_HEADER_SET_COOKIE("Set-Cookie");
+const std::string HTTP_OUT_HEADER_TE("TE");
+const std::string HTTP_OUT_HEADER_TRAILER("Trailer");
+const std::string HTTP_OUT_HEADER_TRANSFER_ENCODING("Transfer-Encoding");
+const std::string HTTP_OUT_HEADER_UPGRADE("Upgrade");
+const std::string HTTP_OUT_HEADER_USER_AGENT("User-Agent");
+const std::string HTTP_OUT_HEADER_VARY("Vary");
+const std::string HTTP_OUT_HEADER_VIA("Via");
+const std::string HTTP_OUT_HEADER_WARNING("Warning");
+const std::string HTTP_OUT_HEADER_WWW_AUTHENTICATE("WWW-Authenticate");
+
+// Incoming headers are normalized to lower-case.
+const std::string HTTP_IN_HEADER_ACCEPT_LANGUAGE("accept-language");
+const std::string HTTP_IN_HEADER_CACHE_CONTROL("cache-control");
+const std::string HTTP_IN_HEADER_CONTENT_LENGTH("content-length");
+const std::string HTTP_IN_HEADER_CONTENT_LOCATION("content-location");
+const std::string HTTP_IN_HEADER_CONTENT_TYPE("content-type");
+const std::string HTTP_IN_HEADER_HOST("host");
+const std::string HTTP_IN_HEADER_LOCATION("location");
+const std::string HTTP_IN_HEADER_RETRY_AFTER("retry-after");
+const std::string HTTP_IN_HEADER_SET_COOKIE("set-cookie");
+const std::string HTTP_IN_HEADER_USER_AGENT("user-agent");
+const std::string HTTP_IN_HEADER_X_FORWARDED_FOR("x-forwarded-for");
+
+const std::string HTTP_CONTENT_LLSD_XML("application/llsd+xml");
+const std::string HTTP_CONTENT_OCTET_STREAM("application/octet-stream");
+const std::string HTTP_CONTENT_XML("application/xml");
+const std::string HTTP_CONTENT_JSON("application/json");
+const std::string HTTP_CONTENT_TEXT_HTML("text/html");
+const std::string HTTP_CONTENT_TEXT_HTML_UTF8("text/html; charset=utf-8");
+const std::string HTTP_CONTENT_TEXT_PLAIN_UTF8("text/plain; charset=utf-8");
+const std::string HTTP_CONTENT_TEXT_LLSD("text/llsd");
+const std::string HTTP_CONTENT_TEXT_XML("text/xml");
+const std::string HTTP_CONTENT_TEXT_LSL("text/lsl");
+const std::string HTTP_CONTENT_TEXT_PLAIN("text/plain");
+const std::string HTTP_CONTENT_IMAGE_X_J2C("image/x-j2c");
+const std::string HTTP_CONTENT_IMAGE_J2C("image/j2c");
+const std::string HTTP_CONTENT_IMAGE_JPEG("image/jpeg");
+const std::string HTTP_CONTENT_IMAGE_PNG("image/png");
+const std::string HTTP_CONTENT_IMAGE_BMP("image/bmp");
+
+const std::string HTTP_NO_CACHE("no-cache");
+const std::string HTTP_NO_CACHE_CONTROL("no-cache, max-age=0");
+
+const std::string HTTP_VERB_INVALID("(invalid)");
+const std::string HTTP_VERB_HEAD("HEAD");
+const std::string HTTP_VERB_GET("GET");
+const std::string HTTP_VERB_PUT("PUT");
+const std::string HTTP_VERB_POST("POST");
+const std::string HTTP_VERB_DELETE("DELETE");
+const std::string HTTP_VERB_MOVE("MOVE");
+const std::string HTTP_VERB_OPTIONS("OPTIONS");
+const std::string HTTP_VERB_PATCH("PATCH");
+const std::string HTTP_VERB_COPY("COPY");
+
+const std::string& httpMethodAsVerb(EHTTPMethod method)
+{
+ static const std::string VERBS[] =
+ {
+ HTTP_VERB_INVALID,
+ HTTP_VERB_HEAD,
+ HTTP_VERB_GET,
+ HTTP_VERB_PUT,
+ HTTP_VERB_POST,
+ HTTP_VERB_DELETE,
+ HTTP_VERB_MOVE,
+ HTTP_VERB_OPTIONS,
+ HTTP_VERB_PATCH,
+ HTTP_VERB_COPY
+ };
+ if(((S32)method <=0) || ((S32)method >= HTTP_METHOD_COUNT))
+ {
+ return VERBS[0];
+ }
+ return VERBS[method];
+}
+
+bool isHttpInformationalStatus(S32 status)
+{
+ // Check for status 1xx.
+ return((100 <= status) && (status < 200));
+}
+
+bool isHttpGoodStatus(S32 status)
+{
+ // Check for status 2xx.
+ return((200 <= status) && (status < 300));
+}
+
+bool isHttpRedirectStatus(S32 status)
+{
+ // Check for status 3xx.
+ return((300 <= status) && (status < 400));
+}
+
+bool isHttpClientErrorStatus(S32 status)
+{
+ // Status 499 is sometimes used for re-interpreted status 2xx errors
+ // based on body content. Treat these as potentially retryable 'server' status errors,
+ // since we do not have enough context to know if this will always fail.
+ if (HTTP_INTERNAL_ERROR == status) return false;
+
+ // Check for status 5xx.
+ return((400 <= status) && (status < 500));
+}
+
+bool isHttpServerErrorStatus(S32 status)
+{
+ // Status 499 is sometimes used for re-interpreted status 2xx errors.
+ // Allow retry of these, since we don't have enough information in this
+ // context to know if this will always fail.
+ if (HTTP_INTERNAL_ERROR == status) return true;
+
+ // Check for status 5xx.
+ return((500 <= status) && (status < 600));
+}
+
+// Parses 'Retry-After' header contents and returns seconds until retry should occur.
+bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait)
+{
+ // *TODO: This needs testing! Not in use yet.
+ // Examples of Retry-After headers:
+ // Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
+ // Retry-After: 120
+
+ // Check for number of seconds version, first:
+ char* end = 0;
+ // Parse as double
+ double seconds = std::strtod(retry_after.c_str(), &end);
+ if ( end != 0 && *end == 0 )
+ {
+ // Successful parse
+ seconds_to_wait = (F32) seconds;
+ return true;
+ }
+
+ // Parse rfc1123 date.
+ time_t date = curl_getdate(retry_after.c_str(), NULL );
+ if (-1 == date) return false;
+
+ seconds_to_wait = (F64)date - LLTimer::getTotalSeconds();
+
+ return true;
+}
+
diff --git a/indra/llmessage/llhttpconstants.h b/indra/llmessage/llhttpconstants.h
new file mode 100755
index 0000000000..4aa3cc6394
--- /dev/null
+++ b/indra/llmessage/llhttpconstants.h
@@ -0,0 +1,225 @@
+/**
+ * @file llhttpconstants.h
+ * @brief Constants for HTTP requests and responses
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2001-2013, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_HTTP_CONSTANTS_H
+#define LL_HTTP_CONSTANTS_H
+
+#include "stdtypes.h"
+
+/////// HTTP STATUS CODES ///////
+
+// Standard errors from HTTP spec:
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1
+const S32 HTTP_CONTINUE = 100;
+const S32 HTTP_SWITCHING_PROTOCOLS = 101;
+
+// Success
+const S32 HTTP_OK = 200;
+const S32 HTTP_CREATED = 201;
+const S32 HTTP_ACCEPTED = 202;
+const S32 HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
+const S32 HTTP_NO_CONTENT = 204;
+const S32 HTTP_RESET_CONTENT = 205;
+const S32 HTTP_PARTIAL_CONTENT = 206;
+
+// Redirection
+const S32 HTTP_MULTIPLE_CHOICES = 300;
+const S32 HTTP_MOVED_PERMANENTLY = 301;
+const S32 HTTP_FOUND = 302;
+const S32 HTTP_SEE_OTHER = 303;
+const S32 HTTP_NOT_MODIFIED = 304;
+const S32 HTTP_USE_PROXY = 305;
+const S32 HTTP_TEMPORARY_REDIRECT = 307;
+
+// Client Error
+const S32 HTTP_BAD_REQUEST = 400;
+const S32 HTTP_UNAUTHORIZED = 401;
+const S32 HTTP_PAYMENT_REQUIRED = 402;
+const S32 HTTP_FORBIDDEN = 403;
+const S32 HTTP_NOT_FOUND = 404;
+const S32 HTTP_METHOD_NOT_ALLOWED = 405;
+const S32 HTTP_NOT_ACCEPTABLE = 406;
+const S32 HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
+const S32 HTTP_REQUEST_TIME_OUT = 408;
+const S32 HTTP_CONFLICT = 409;
+const S32 HTTP_GONE = 410;
+const S32 HTTP_LENGTH_REQUIRED = 411;
+const S32 HTTP_PRECONDITION_FAILED = 412;
+const S32 HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
+const S32 HTTP_REQUEST_URI_TOO_LARGE = 414;
+const S32 HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
+const S32 HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
+const S32 HTTP_EXPECTATION_FAILED = 417;
+
+// Server Error
+const S32 HTTP_INTERNAL_SERVER_ERROR = 500;
+const S32 HTTP_NOT_IMPLEMENTED = 501;
+const S32 HTTP_BAD_GATEWAY = 502;
+const S32 HTTP_SERVICE_UNAVAILABLE = 503;
+const S32 HTTP_GATEWAY_TIME_OUT = 504;
+const S32 HTTP_VERSION_NOT_SUPPORTED = 505;
+
+// We combine internal process errors with status codes
+// These status codes should not be sent over the wire
+// and indicate something went wrong internally.
+// If you get these they are not normal.
+const S32 HTTP_INTERNAL_CURL_ERROR = 498;
+const S32 HTTP_INTERNAL_ERROR = 499;
+
+
+////// HTTP Methods //////
+
+extern const std::string HTTP_VERB_INVALID;
+extern const std::string HTTP_VERB_HEAD;
+extern const std::string HTTP_VERB_GET;
+extern const std::string HTTP_VERB_PUT;
+extern const std::string HTTP_VERB_POST;
+extern const std::string HTTP_VERB_DELETE;
+extern const std::string HTTP_VERB_MOVE;
+extern const std::string HTTP_VERB_OPTIONS;
+
+enum EHTTPMethod
+{
+ HTTP_INVALID = 0,
+ HTTP_HEAD,
+ HTTP_GET,
+ HTTP_PUT,
+ HTTP_POST,
+ HTTP_DELETE,
+ HTTP_MOVE, // Caller will need to set 'Destination' header
+ HTTP_OPTIONS,
+ HTTP_PATCH,
+ HTTP_COPY,
+ HTTP_METHOD_COUNT
+};
+
+const std::string& httpMethodAsVerb(EHTTPMethod method);
+bool isHttpInformationalStatus(S32 status);
+bool isHttpGoodStatus(S32 status);
+bool isHttpRedirectStatus(S32 status);
+bool isHttpClientErrorStatus(S32 status);
+bool isHttpServerErrorStatus(S32 status);
+
+// Parses 'Retry-After' header contents and returns seconds until retry should occur.
+bool getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait);
+
+//// HTTP Headers /////
+
+// Outgoing headers. Do *not* use these to check incoming headers.
+// For incoming headers, use the lower-case headers, below.
+extern const std::string HTTP_OUT_HEADER_ACCEPT;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_CHARSET;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_ENCODING;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_LANGUAGE;
+extern const std::string HTTP_OUT_HEADER_ACCEPT_RANGES;
+extern const std::string HTTP_OUT_HEADER_AGE;
+extern const std::string HTTP_OUT_HEADER_ALLOW;
+extern const std::string HTTP_OUT_HEADER_AUTHORIZATION;
+extern const std::string HTTP_OUT_HEADER_CACHE_CONTROL;
+extern const std::string HTTP_OUT_HEADER_CONNECTION;
+extern const std::string HTTP_OUT_HEADER_CONTENT_DESCRIPTION;
+extern const std::string HTTP_OUT_HEADER_CONTENT_ENCODING;
+extern const std::string HTTP_OUT_HEADER_CONTENT_ID;
+extern const std::string HTTP_OUT_HEADER_CONTENT_LANGUAGE;
+extern const std::string HTTP_OUT_HEADER_CONTENT_LENGTH;
+extern const std::string HTTP_OUT_HEADER_CONTENT_LOCATION;
+extern const std::string HTTP_OUT_HEADER_CONTENT_MD5;
+extern const std::string HTTP_OUT_HEADER_CONTENT_RANGE;
+extern const std::string HTTP_OUT_HEADER_CONTENT_TRANSFER_ENCODING;
+extern const std::string HTTP_OUT_HEADER_CONTENT_TYPE;
+extern const std::string HTTP_OUT_HEADER_COOKIE;
+extern const std::string HTTP_OUT_HEADER_DATE;
+extern const std::string HTTP_OUT_HEADER_DESTINATION;
+extern const std::string HTTP_OUT_HEADER_ETAG;
+extern const std::string HTTP_OUT_HEADER_EXPECT;
+extern const std::string HTTP_OUT_HEADER_EXPIRES;
+extern const std::string HTTP_OUT_HEADER_FROM;
+extern const std::string HTTP_OUT_HEADER_HOST;
+extern const std::string HTTP_OUT_HEADER_IF_MATCH;
+extern const std::string HTTP_OUT_HEADER_IF_MODIFIED_SINCE;
+extern const std::string HTTP_OUT_HEADER_IF_NONE_MATCH;
+extern const std::string HTTP_OUT_HEADER_IF_RANGE;
+extern const std::string HTTP_OUT_HEADER_IF_UNMODIFIED_SINCE;
+extern const std::string HTTP_OUT_HEADER_KEEP_ALIVE;
+extern const std::string HTTP_OUT_HEADER_LAST_MODIFIED;
+extern const std::string HTTP_OUT_HEADER_LOCATION;
+extern const std::string HTTP_OUT_HEADER_MAX_FORWARDS;
+extern const std::string HTTP_OUT_HEADER_MIME_VERSION;
+extern const std::string HTTP_OUT_HEADER_PRAGMA;
+extern const std::string HTTP_OUT_HEADER_PROXY_AUTHENTICATE;
+extern const std::string HTTP_OUT_HEADER_PROXY_AUTHORIZATION;
+extern const std::string HTTP_OUT_HEADER_RANGE;
+extern const std::string HTTP_OUT_HEADER_REFERER;
+extern const std::string HTTP_OUT_HEADER_RETRY_AFTER;
+extern const std::string HTTP_OUT_HEADER_SERVER;
+extern const std::string HTTP_OUT_HEADER_SET_COOKIE;
+extern const std::string HTTP_OUT_HEADER_TE;
+extern const std::string HTTP_OUT_HEADER_TRAILER;
+extern const std::string HTTP_OUT_HEADER_TRANSFER_ENCODING;
+extern const std::string HTTP_OUT_HEADER_UPGRADE;
+extern const std::string HTTP_OUT_HEADER_USER_AGENT;
+extern const std::string HTTP_OUT_HEADER_VARY;
+extern const std::string HTTP_OUT_HEADER_VIA;
+extern const std::string HTTP_OUT_HEADER_WARNING;
+extern const std::string HTTP_OUT_HEADER_WWW_AUTHENTICATE;
+
+// Incoming headers are normalized to lower-case.
+extern const std::string HTTP_IN_HEADER_ACCEPT_LANGUAGE;
+extern const std::string HTTP_IN_HEADER_CACHE_CONTROL;
+extern const std::string HTTP_IN_HEADER_CONTENT_LENGTH;
+extern const std::string HTTP_IN_HEADER_CONTENT_LOCATION;
+extern const std::string HTTP_IN_HEADER_CONTENT_TYPE;
+extern const std::string HTTP_IN_HEADER_HOST;
+extern const std::string HTTP_IN_HEADER_LOCATION;
+extern const std::string HTTP_IN_HEADER_RETRY_AFTER;
+extern const std::string HTTP_IN_HEADER_SET_COOKIE;
+extern const std::string HTTP_IN_HEADER_USER_AGENT;
+extern const std::string HTTP_IN_HEADER_X_FORWARDED_FOR;
+
+//// HTTP Content Types ////
+
+extern const std::string HTTP_CONTENT_LLSD_XML;
+extern const std::string HTTP_CONTENT_OCTET_STREAM;
+extern const std::string HTTP_CONTENT_XML;
+extern const std::string HTTP_CONTENT_JSON;
+extern const std::string HTTP_CONTENT_TEXT_HTML;
+extern const std::string HTTP_CONTENT_TEXT_HTML_UTF8;
+extern const std::string HTTP_CONTENT_TEXT_PLAIN_UTF8;
+extern const std::string HTTP_CONTENT_TEXT_LLSD;
+extern const std::string HTTP_CONTENT_TEXT_XML;
+extern const std::string HTTP_CONTENT_TEXT_LSL;
+extern const std::string HTTP_CONTENT_TEXT_PLAIN;
+extern const std::string HTTP_CONTENT_IMAGE_X_J2C;
+extern const std::string HTTP_CONTENT_IMAGE_J2C;
+extern const std::string HTTP_CONTENT_IMAGE_JPEG;
+extern const std::string HTTP_CONTENT_IMAGE_PNG;
+extern const std::string HTTP_CONTENT_IMAGE_BMP;
+
+//// HTTP Cache Settings ////
+extern const std::string HTTP_NO_CACHE;
+extern const std::string HTTP_NO_CACHE_CONTROL;
+
+#endif
diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp
index f1f4a95005..f235965879 100755
--- a/indra/llmessage/llhttpnode.cpp
+++ b/indra/llmessage/llhttpnode.cpp
@@ -30,9 +30,15 @@
#include <boost/tokenizer.hpp>
#include "llstl.h"
-#include "lliohttpserver.h" // for string constants
+#include "llhttpconstants.h"
-static const std::string CONTEXT_WILDCARD("wildcard");
+const std::string CONTEXT_HEADERS("headers");
+const std::string CONTEXT_PATH("path");
+const std::string CONTEXT_QUERY_STRING("query-string");
+const std::string CONTEXT_REQUEST("request");
+const std::string CONTEXT_RESPONSE("response");
+const std::string CONTEXT_VERB("verb");
+const std::string CONTEXT_WILDCARD("wildcard");
/**
* LLHTTPNode
@@ -173,21 +179,23 @@ LLSD LLHTTPNode::simpleDel(const LLSD&) const
void LLHTTPNode::options(ResponsePtr response, const LLSD& context) const
{
//LL_INFOS() << "options context: " << context << LL_ENDL;
+ LL_DEBUGS("LLHTTPNode") << "context: " << context << LL_ENDL;
// default implementation constructs an url to the documentation.
+ // *TODO: Check for 'Host' header instead of 'host' header?
std::string host(
- context[CONTEXT_REQUEST][CONTEXT_HEADERS]["host"].asString());
+ context[CONTEXT_REQUEST][CONTEXT_HEADERS][HTTP_IN_HEADER_HOST].asString());
if(host.empty())
{
- response->status(400, "Bad Request -- need Host header");
+ response->status(HTTP_BAD_REQUEST, "Bad Request -- need Host header");
return;
}
std::ostringstream ostr;
ostr << "http://" << host << "/web/server/api";
- ostr << context[CONTEXT_REQUEST]["path"].asString();
+ ostr << context[CONTEXT_REQUEST][CONTEXT_PATH].asString();
static const std::string DOC_HEADER("X-Documentation-URL");
response->addHeader(DOC_HEADER, ostr.str());
- response->status(200, "OK");
+ response->status(HTTP_OK, "OK");
}
@@ -389,17 +397,17 @@ void LLHTTPNode::Response::statusUnknownError(S32 code)
void LLHTTPNode::Response::notFound(const std::string& message)
{
- status(404, message);
+ status(HTTP_NOT_FOUND, message);
}
void LLHTTPNode::Response::notFound()
{
- status(404, "Not Found");
+ status(HTTP_NOT_FOUND, "Not Found");
}
void LLHTTPNode::Response::methodNotAllowed()
{
- status(405, "Method Not Allowed");
+ status(HTTP_METHOD_NOT_ALLOWED, "Method Not Allowed");
}
void LLHTTPNode::Response::addHeader(
@@ -467,7 +475,7 @@ LLSimpleResponse::~LLSimpleResponse()
void LLSimpleResponse::result(const LLSD& result)
{
- status(200, "OK");
+ status(HTTP_OK, "OK");
}
void LLSimpleResponse::extendedResult(S32 code, const std::string& body, const LLSD& headers)
@@ -475,6 +483,11 @@ void LLSimpleResponse::extendedResult(S32 code, const std::string& body, const L
status(code,body);
}
+void LLSimpleResponse::extendedResult(S32 code, const LLSD& r, const LLSD& headers)
+{
+ status(code,"(LLSD)");
+}
+
void LLSimpleResponse::status(S32 code, const std::string& message)
{
mCode = code;
diff --git a/indra/llmessage/llhttpnode.h b/indra/llmessage/llhttpnode.h
index 148647ddde..1144d88be1 100755
--- a/indra/llmessage/llhttpnode.h
+++ b/indra/llmessage/llhttpnode.h
@@ -31,6 +31,17 @@
#include "llrefcount.h"
#include "llsd.h"
+// common strings use for populating the context. basically 'request',
+// 'wildcard', and 'headers'.
+extern const std::string CONTEXT_HEADERS;
+extern const std::string CONTEXT_PATH;
+extern const std::string CONTEXT_QUERY_STRING;
+extern const std::string CONTEXT_REQUEST;
+extern const std::string CONTEXT_RESPONSE;
+extern const std::string CONTEXT_VERB;
+extern const std::string CONTEXT_WILDCARD;
+
+
class LLChainIOFactory;
/**
@@ -60,6 +71,8 @@ class LLChainIOFactory;
*/
class LLHTTPNode
{
+protected:
+ LOG_CLASS(LLHTTPNode);
public:
LLHTTPNode();
virtual ~LLHTTPNode();
@@ -100,7 +113,12 @@ public:
/**
* @brief return status code and message with headers.
*/
- virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers) = 0;
+ virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers = LLSD()) = 0;
+
+ /**
+ * @brief return status code and LLSD result with headers.
+ */
+ virtual void extendedResult(S32 code, const LLSD& result, const LLSD& headers = LLSD()) = 0;
/**
* @brief return status code and reason string on http header,
@@ -118,7 +136,7 @@ public:
virtual void methodNotAllowed();
/**
- * @breif Add a name: value http header.
+ * @brief Add a name: value http header.
*
* No effort is made to ensure the response is a valid http
* header.
@@ -187,15 +205,15 @@ public:
name, and return true if the name will construct to a valid url.
For convenience, the <code>getChild()</code> method above will
automatically insert the name in
- context["request"]["wildcard"][key] if this method returns true.
+ context[CONTEXT_REQUEST][CONTEXT_WILDCARD][key] if this method returns true.
For example, the node "agent/<agent_id>/detail" will set
- context["request"]["wildcard"]["agent_id"] eqaul to the value
+ context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["agent_id"] eqaul to the value
found during traversal.
*/
const LLHTTPNode* traverse(const std::string& path, LLSD& context) const;
/**< find a node, if any, that can service this path
- set up context["request"] information
+ set up context[CONTEXT_REQUEST] information
*/
//@}
@@ -287,7 +305,7 @@ public:
void result(const LLSD& result);
void extendedResult(S32 code, const std::string& body, const LLSD& headers);
-
+ void extendedResult(S32 code, const LLSD& result, const LLSD& headers);
void status(S32 code, const std::string& message);
void print(std::ostream& out) const;
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index 23813c6edb..d9042fa8b0 100755
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -33,6 +33,7 @@
#include "llapr.h"
#include "llbuffer.h"
#include "llbufferstream.h"
+#include "llhttpconstants.h"
#include "llfasttimer.h"
#include "llhttpnode.h"
#include "lliopipe.h"
@@ -50,15 +51,6 @@
#include <boost/tokenizer.hpp>
static const char HTTP_VERSION_STR[] = "HTTP/1.0";
-const std::string CONTEXT_REQUEST("request");
-const std::string CONTEXT_RESPONSE("response");
-const std::string CONTEXT_VERB("verb");
-const std::string CONTEXT_HEADERS("headers");
-const std::string HTTP_VERB_GET("GET");
-const std::string HTTP_VERB_PUT("PUT");
-const std::string HTTP_VERB_POST("POST");
-const std::string HTTP_VERB_DELETE("DELETE");
-const std::string HTTP_VERB_OPTIONS("OPTIONS");
static LLIOHTTPServer::timing_callback_t sTimingCallback = NULL;
static void* sTimingCallbackData = NULL;
@@ -103,7 +95,7 @@ private:
// from LLHTTPNode::Response
virtual void result(const LLSD&);
virtual void extendedResult(S32 code, const std::string& body, const LLSD& headers);
-
+ virtual void extendedResult(S32 code, const LLSD& body, const LLSD& headers);
virtual void status(S32 code, const std::string& message);
void nullPipe();
@@ -123,7 +115,8 @@ private:
STATE_LOCKED,
STATE_GOOD_RESULT,
STATE_STATUS_RESULT,
- STATE_EXTENDED_RESULT
+ STATE_EXTENDED_RESULT,
+ STATE_EXTENDED_LLSD_RESULT
};
State mState;
@@ -133,7 +126,7 @@ private:
void lockChain(LLPumpIO*);
void unlockChain();
- LLSD mGoodResult;
+ LLSD mResult;
S32 mStatusCode;
std::string mStatusMessage;
LLSD mHeaders;
@@ -194,7 +187,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
}
else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
{
- std::stringstream strstrm;
+ std::ostringstream strstrm;
strstrm << istr.rdbuf();
input = strstrm.str();
}
@@ -210,7 +203,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
}
else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
{
- std::stringstream strstrm;
+ std::ostringstream strstrm;
strstrm << istr.rdbuf();
input = strstrm.str();
}
@@ -245,12 +238,12 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
// Log all HTTP transactions.
// TODO: Add a way to log these to their own file instead of indra.log
// It is just too spammy to be in indra.log.
- LL_DEBUGS() << verb << " " << context[CONTEXT_REQUEST]["path"].asString()
+ LL_DEBUGS() << verb << " " << context[CONTEXT_REQUEST][CONTEXT_PATH].asString()
<< " " << mStatusCode << " " << mStatusMessage << " " << delta
<< "s" << LL_ENDL;
// Log Internal Server Errors
- //if(mStatusCode == 500)
+ //if(mStatusCode == HTTP_INTERNAL_SERVER_ERROR)
//{
// LL_WARNS() << "LLHTTPPipe::process_impl:500:Internal Server Error"
// << LL_ENDL;
@@ -272,10 +265,10 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
case STATE_GOOD_RESULT:
{
LLSD headers = mHeaders;
- headers["Content-Type"] = "application/llsd+xml";
+ headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
LLBufferStream ostr(channels, buffer.get());
- LLSDSerialize::toXML(mGoodResult, ostr);
+ LLSDSerialize::toXML(mResult, ostr);
return STATUS_DONE;
}
@@ -283,7 +276,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
case STATE_STATUS_RESULT:
{
LLSD headers = mHeaders;
- headers["Content-Type"] = "text/plain";
+ headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_TEXT_PLAIN;
context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
context[CONTEXT_RESPONSE]["statusMessage"] = mStatusMessage;
@@ -301,6 +294,17 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
return STATUS_DONE;
}
+ case STATE_EXTENDED_LLSD_RESULT:
+ {
+ LLSD headers = mHeaders;
+ headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
+ context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
+ context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
+ LLBufferStream ostr(channels, buffer.get());
+ LLSDSerialize::toXML(mResult, ostr);
+
+ return STATUS_DONE;
+ }
default:
LL_WARNS() << "LLHTTPPipe::process_impl: unexpected state "
<< mState << LL_ENDL;
@@ -336,12 +340,28 @@ void LLHTTPPipe::Response::result(const LLSD& r)
return;
}
- mPipe->mStatusCode = 200;
+ mPipe->mStatusCode = HTTP_OK;
mPipe->mStatusMessage = "OK";
- mPipe->mGoodResult = r;
+ mPipe->mResult = r;
mPipe->mState = STATE_GOOD_RESULT;
mPipe->mHeaders = mHeaders;
- mPipe->unlockChain();
+ mPipe->unlockChain();
+}
+
+void LLHTTPPipe::Response::extendedResult(S32 code, const LLSD& r, const LLSD& headers)
+{
+ if(! mPipe)
+ {
+ LL_WARNS() << "LLHTTPPipe::Response::extendedResult: NULL pipe" << LL_ENDL;
+ return;
+ }
+
+ mPipe->mStatusCode = code;
+ mPipe->mStatusMessage = "(LLSD)";
+ mPipe->mResult = r;
+ mPipe->mHeaders = headers;
+ mPipe->mState = STATE_EXTENDED_LLSD_RESULT;
+ mPipe->unlockChain();
}
void LLHTTPPipe::Response::extendedResult(S32 code, const std::string& body, const LLSD& headers)
@@ -455,9 +475,9 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
std::string message = context[CONTEXT_RESPONSE]["statusMessage"];
int code = context[CONTEXT_RESPONSE]["statusCode"];
- if (code < 200)
+ if (code < HTTP_OK)
{
- code = 200;
+ code = HTTP_OK;
message = "OK";
}
@@ -466,7 +486,7 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
S32 content_length = buffer->countAfter(channels.in(), NULL);
if(0 < content_length)
{
- ostr << "Content-Length: " << content_length << "\r\n";
+ ostr << HTTP_OUT_HEADER_CONTENT_LENGTH << ": " << content_length << "\r\n";
}
// *NOTE: This guard can go away once the LLSD static map
// iterator is available. Phoenix. 2008-05-09
@@ -772,7 +792,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
std::string name(buf, pos_colon - buf);
std::string value(pos_colon + 2);
LLStringUtil::toLower(name);
- if("content-length" == name)
+ if(HTTP_IN_HEADER_CONTENT_LENGTH == name)
{
LL_DEBUGS() << "Content-Length: " << value << LL_ENDL;
mContentLength = atoi(value.c_str());
@@ -847,12 +867,12 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
// HTTP headers.
LLPumpIO::chain_t chain;
chain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
- context[CONTEXT_REQUEST]["path"] = mPath;
- context[CONTEXT_REQUEST]["query-string"] = mQuery;
- context[CONTEXT_REQUEST]["remote-host"]
- = mBuildContext["remote-host"];
- context[CONTEXT_REQUEST]["remote-port"]
- = mBuildContext["remote-port"];
+ context[CONTEXT_REQUEST][CONTEXT_PATH] = mPath;
+ context[CONTEXT_REQUEST][CONTEXT_QUERY_STRING] = mQuery;
+ context[CONTEXT_REQUEST][CONTEXT_REMOTE_HOST]
+ = mBuildContext[CONTEXT_REMOTE_HOST];
+ context[CONTEXT_REQUEST][CONTEXT_REMOTE_PORT]
+ = mBuildContext[CONTEXT_REMOTE_PORT];
context[CONTEXT_REQUEST][CONTEXT_HEADERS] = mHeaders;
const LLChainIOFactory* protocolHandler
diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h
index 5c1b0531ff..a23eafe58a 100755
--- a/indra/llmessage/lliohttpserver.h
+++ b/indra/llmessage/lliohttpserver.h
@@ -33,18 +33,6 @@
class LLPumpIO;
-// common strings use for populating the context. bascally 'request',
-// 'wildcard', and 'headers'.
-extern const std::string CONTEXT_REQUEST;
-extern const std::string CONTEXT_RESPONSE;
-extern const std::string CONTEXT_VERB;
-extern const std::string CONTEXT_HEADERS;
-extern const std::string HTTP_VERB_GET;
-extern const std::string HTTP_VERB_PUT;
-extern const std::string HTTP_VERB_POST;
-extern const std::string HTTP_VERB_DELETE;
-extern const std::string HTTP_VERB_OPTIONS;
-
class LLIOHTTPServer
{
public:
diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp
index 4b8d1b44f6..b7460df508 100755
--- a/indra/llmessage/lliosocket.cpp
+++ b/indra/llmessage/lliosocket.cpp
@@ -40,6 +40,9 @@
// constants
//
+const std::string CONTEXT_REMOTE_HOST("remote-host");
+const std::string CONTEXT_REMOTE_PORT("remote-port");
+
static const S32 LL_DEFAULT_LISTEN_BACKLOG = 10;
static const S32 LL_SEND_BUFFER_SIZE = 40000;
static const S32 LL_RECV_BUFFER_SIZE = 40000;
@@ -620,8 +623,8 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
apr_sockaddr_ip_get(&remote_host_string, remote_addr);
LLSD context;
- context["remote-host"] = remote_host_string;
- context["remote-port"] = remote_addr->port;
+ context[CONTEXT_REMOTE_HOST] = remote_host_string;
+ context[CONTEXT_REMOTE_PORT] = remote_addr->port;
LLPumpIO::chain_t chain;
chain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(llsocket)));
diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h
index ec998552d0..f840f0275c 100755
--- a/indra/llmessage/lliosocket.h
+++ b/indra/llmessage/lliosocket.h
@@ -43,6 +43,9 @@
#include "apr_network_io.h"
#include "llchainio.h"
+extern const std::string CONTEXT_REMOTE_HOST;
+extern const std::string CONTEXT_REMOTE_PORT;
+
class LLHost;
/**
diff --git a/indra/llmessage/llmime.cpp b/indra/llmessage/llmime.cpp
deleted file mode 100755
index 9d9c4ebd68..0000000000
--- a/indra/llmessage/llmime.cpp
+++ /dev/null
@@ -1,629 +0,0 @@
-/**
- * @file llmime.cpp
- * @author Phoenix
- * @date 2006-12-20
- * @brief Implementation of mime tools.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llmime.h"
-
-#include <vector>
-
-#include "llmemorystream.h"
-
-/**
- * Useful constants.
- */
-// Headers specified in rfc-2045 will be canonicalized below.
-static const std::string CONTENT_LENGTH("Content-Length");
-static const std::string CONTENT_TYPE("Content-Type");
-static const S32 KNOWN_HEADER_COUNT = 6;
-static const std::string KNOWN_HEADER[KNOWN_HEADER_COUNT] =
-{
- CONTENT_LENGTH,
- CONTENT_TYPE,
- std::string("MIME-Version"),
- std::string("Content-Transfer-Encoding"),
- std::string("Content-ID"),
- std::string("Content-Description"),
-};
-
-// parser helpers
-static const std::string MULTIPART("multipart");
-static const std::string BOUNDARY("boundary");
-static const std::string END_OF_CONTENT_PARAMETER("\r\n ;\t");
-static const std::string SEPARATOR_PREFIX("--");
-//static const std::string SEPARATOR_SUFFIX("\r\n");
-
-/*
-Content-Type: multipart/mixed; boundary="segment"
-Content-Length: 24832
-
---segment
-Content-Type: image/j2c
-Content-Length: 23715
-
-<data>
-
---segment
-Content-Type: text/xml; charset=UTF-8
-
-<meta data>
-EOF
-
-*/
-
-/**
- * LLMimeIndex
- */
-
-/**
- * @class LLMimeIndex::Impl
- * @brief Implementation details of the mime index class.
- * @see LLMimeIndex
- */
-class LLMimeIndex::Impl
-{
-public:
- Impl() : mOffset(-1), mUseCount(1)
- {}
- Impl(LLSD headers, S32 offset) :
- mHeaders(headers), mOffset(offset), mUseCount(1)
- {}
-public:
- LLSD mHeaders;
- S32 mOffset;
- S32 mUseCount;
-
- typedef std::vector<LLMimeIndex> sub_part_t;
- sub_part_t mAttachments;
-};
-
-LLSD LLMimeIndex::headers() const
-{
- return mImpl->mHeaders;
-}
-
-S32 LLMimeIndex::offset() const
-{
- return mImpl->mOffset;
-}
-
-S32 LLMimeIndex::contentLength() const
-{
- // Find the content length in the headers.
- S32 length = -1;
- LLSD content_length = mImpl->mHeaders[CONTENT_LENGTH];
- if(content_length.isDefined())
- {
- length = content_length.asInteger();
- }
- return length;
-}
-
-std::string LLMimeIndex::contentType() const
-{
- std::string type;
- LLSD content_type = mImpl->mHeaders[CONTENT_TYPE];
- if(content_type.isDefined())
- {
- type = content_type.asString();
- }
- return type;
-}
-
-bool LLMimeIndex::isMultipart() const
-{
- bool multipart = false;
- LLSD content_type = mImpl->mHeaders[CONTENT_TYPE];
- if(content_type.isDefined())
- {
- std::string type = content_type.asString();
- int comp = type.compare(0, MULTIPART.size(), MULTIPART);
- if(0 == comp)
- {
- multipart = true;
- }
- }
- return multipart;
-}
-
-S32 LLMimeIndex::subPartCount() const
-{
- return mImpl->mAttachments.size();
-}
-
-LLMimeIndex LLMimeIndex::subPart(S32 index) const
-{
- LLMimeIndex part;
- if((index >= 0) && (index < (S32)mImpl->mAttachments.size()))
- {
- part = mImpl->mAttachments[index];
- }
- return part;
-}
-
-LLMimeIndex::LLMimeIndex() : mImpl(new LLMimeIndex::Impl)
-{
-}
-
-LLMimeIndex::LLMimeIndex(LLSD headers, S32 content_offset) :
- mImpl(new LLMimeIndex::Impl(headers, content_offset))
-{
-}
-
-LLMimeIndex::LLMimeIndex(const LLMimeIndex& mime) :
- mImpl(mime.mImpl)
-{
- ++mImpl->mUseCount;
-}
-
-LLMimeIndex::~LLMimeIndex()
-{
- if(0 == --mImpl->mUseCount)
- {
- delete mImpl;
- }
-}
-
-LLMimeIndex& LLMimeIndex::operator=(const LLMimeIndex& mime)
-{
- // Increment use count first so that we handle self assignment
- // automatically.
- ++mime.mImpl->mUseCount;
- if(0 == --mImpl->mUseCount)
- {
- delete mImpl;
- }
- mImpl = mime.mImpl;
- return *this;
-}
-
-bool LLMimeIndex::attachSubPart(LLMimeIndex sub_part)
-{
- // *FIX: Should we check for multi-part?
- if(mImpl->mAttachments.size() < S32_MAX)
- {
- mImpl->mAttachments.push_back(sub_part);
- return true;
- }
- return false;
-}
-
-/**
- * LLMimeParser
- */
-/**
- * @class LLMimeParser::Impl
- * @brief Implementation details of the mime parser class.
- * @see LLMimeParser
- */
-class LLMimeParser::Impl
-{
-public:
- // @brief Constructor.
- Impl();
-
- // @brief Reset this for a new parse.
- void reset();
-
- /**
- * @brief Parse a mime entity to find the index information.
- *
- * This method will scan the istr until a single complete mime
- * entity is read, an EOF, or limit bytes have been scanned. The
- * istr will be modified by this parsing, so pass in a temporary
- * stream or rewind/reset the stream after this call.
- * @param istr An istream which contains a mime entity.
- * @param limit The maximum number of bytes to scan.
- * @param separator The multipart separator if it is known.
- * @param is_subpart Set true if parsing a multipart sub part.
- * @param index[out] The parsed output.
- * @return Returns true if an index was parsed and no errors occurred.
- */
- bool parseIndex(
- std::istream& istr,
- S32 limit,
- const std::string& separator,
- bool is_subpart,
- LLMimeIndex& index);
-
-protected:
- /**
- * @brief parse the headers.
- *
- * At the end of a successful parse, mScanCount will be at the
- * start of the content.
- * @param istr The input stream.
- * @param limit maximum number of bytes to process
- * @param headers[out] A map of the headers found.
- * @return Returns true if the parse was successful.
- */
- bool parseHeaders(std::istream& istr, S32 limit, LLSD& headers);
-
- /**
- * @brief Figure out the separator string from a content type header.
- *
- * @param multipart_content_type The content type value from the headers.
- * @return Returns the separator string.
- */
- std::string findSeparator(std::string multipart_content_type);
-
- /**
- * @brief Scan through istr past the separator.
- *
- * @param istr The input stream.
- * @param limit Maximum number of bytes to scan.
- * @param separator The multipart separator.
- */
- void scanPastSeparator(
- std::istream& istr,
- S32 limit,
- const std::string& separator);
-
- /**
- * @brief Scan through istr past the content of the current mime part.
- *
- * @param istr The input stream.
- * @param limit Maximum number of bytes to scan.
- * @param headers The headers for this mime part.
- * @param separator The multipart separator if known.
- */
- void scanPastContent(
- std::istream& istr,
- S32 limit,
- LLSD headers,
- const std::string separator);
-
- /**
- * @brief Eat CRLF.
- *
- * This method has no concept of the limit, so ensure you have at
- * least 2 characters left to eat before hitting the limit. This
- * method will increment mScanCount as it goes.
- * @param istr The input stream.
- * @return Returns true if CRLF was found and consumed off of istr.
- */
- bool eatCRLF(std::istream& istr);
-
- // @brief Returns true if parsing should continue.
- bool continueParse() const { return (!mError && mContinue); }
-
- // @brief anonymous enumeration for parse buffer size.
- enum
- {
- LINE_BUFFER_LENGTH = 1024
- };
-
-protected:
- S32 mScanCount;
- bool mContinue;
- bool mError;
- char mBuffer[LINE_BUFFER_LENGTH];
-};
-
-LLMimeParser::Impl::Impl()
-{
- reset();
-}
-
-void LLMimeParser::Impl::reset()
-{
- mScanCount = 0;
- mContinue = true;
- mError = false;
- mBuffer[0] = '\0';
-}
-
-bool LLMimeParser::Impl::parseIndex(
- std::istream& istr,
- S32 limit,
- const std::string& separator,
- bool is_subpart,
- LLMimeIndex& index)
-{
- LLSD headers;
- bool parsed_something = false;
- if(parseHeaders(istr, limit, headers))
- {
- parsed_something = true;
- LLMimeIndex mime(headers, mScanCount);
- index = mime;
- if(index.isMultipart())
- {
- // Figure out the separator, scan past it, and recurse.
- std::string ct = headers[CONTENT_TYPE].asString();
- std::string sep = findSeparator(ct);
- scanPastSeparator(istr, limit, sep);
- while(continueParse() && parseIndex(istr, limit, sep, true, mime))
- {
- index.attachSubPart(mime);
- }
- }
- else
- {
- // Scan to the end of content.
- scanPastContent(istr, limit, headers, separator);
- if(is_subpart)
- {
- scanPastSeparator(istr, limit, separator);
- }
- }
- }
- if(mError) return false;
- return parsed_something;
-}
-
-bool LLMimeParser::Impl::parseHeaders(
- std::istream& istr,
- S32 limit,
- LLSD& headers)
-{
- while(continueParse())
- {
- // Get the next line.
- // We subtract 1 from the limit so that we make sure
- // not to read past limit when we get() the newline.
- S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1);
- istr.getline(mBuffer, max_get, '\r');
- mScanCount += (S32)istr.gcount();
- int c = istr.get();
- if(EOF == c)
- {
- mContinue = false;
- return false;
- }
- ++mScanCount;
- if(c != '\n')
- {
- mError = true;
- return false;
- }
- if(mScanCount >= limit)
- {
- mContinue = false;
- }
-
- // Check if that's the end of headers.
- if('\0' == mBuffer[0])
- {
- break;
- }
-
- // Split out the name and value.
- // *NOTE: The use of strchr() here is safe since mBuffer is
- // guaranteed to be NULL terminated from the call to getline()
- // above.
- char* colon = strchr(mBuffer, ':');
- if(!colon)
- {
- mError = true;
- return false;
- }
-
- // Cononicalize the name part, and store the name: value in
- // the headers structure. We do this by iterating through
- // 'known' headers and replacing the value found with the
- // correct one.
- // *NOTE: Not so efficient, but iterating through a small
- // subset should not be too much of an issue.
- std::string name(mBuffer, colon++ - mBuffer);
- while(isspace(*colon)) ++colon;
- std::string value(colon);
- for(S32 ii = 0; ii < KNOWN_HEADER_COUNT; ++ii)
- {
- if(0 == LLStringUtil::compareInsensitive(name, KNOWN_HEADER[ii]))
- {
- name = KNOWN_HEADER[ii];
- break;
- }
- }