Compare commits

...

339 Commits

Author SHA1 Message Date
Siana Gearz
b03b4db7c7 Buddy search adjustment 2012-02-05 15:13:52 +01:00
Siana Gearz
859e2701f2 Restore LightShare compatibility 2012-02-05 13:52:50 +01:00
Siana Gearz
7b6ff27c4b Awesomize buddy search 2012-02-02 12:18:35 +01:00
Siana Gearz
2526d04397 Cosmetic fix llRegionSayTo 2012-02-02 11:31:46 +01:00
Siana Gearz
4ffa06ae07 More reliable preview perm checks 2012-02-02 09:52:34 +01:00
Siana Gearz
f68211d83e Awesomely fixed OpenAL for Linux 2012-02-02 09:06:12 +01:00
Siana Gearz
7694f915f5 Fix cache thinking once full, always full. 2012-02-02 08:43:01 +01:00
Siana Gearz
b5ec7fe015 Actually enable Region WindLight 2012-02-01 12:20:54 +01:00
Siana Gearz
55cce46454 Restoring preset loading 2012-02-01 09:59:31 +01:00
Siana Gearz
071745007a Partial port of Phoenix Windlight parts 2012-02-01 06:36:10 +01:00
Siana Gearz
b177324058 Merge branch 'master' of https://github.com/Shyotl/SingularityViewer 2012-01-29 04:54:36 +01:00
Shyotl
e7a20b04de El crappo. Failed to include this file in earlier commit. 2012-01-28 21:37:19 -06:00
Siana Gearz
5245547f28 Merge branch 'master' of https://github.com/Shyotl/SingularityViewer 2012-01-28 22:25:40 +01:00
Siana Gearz
ef696d895d Avoid tag detection spam from radar on every object update 2012-01-28 22:00:21 +01:00
Siana Gearz
a15e72dc03 Force translator off, remove its UI in chat, small adjustments 2012-01-28 21:52:26 +01:00
Siana Gearz
b7997a2677 Force single texture cache clear 2012-01-28 21:51:15 +01:00
Shyotl
c39ddb5991 Packager now conditionally includes fmodex/fmod.dll if project is set to use them. 2012-01-28 00:04:21 -06:00
Shyotl
9dd8f1b8ab Temporarily disable RenderDelayVBUpdate, as it's completely broken. 2012-01-27 21:40:34 -06:00
Shyotl
744b5b6404 Shiny HUD objects not fullbright. https://bitbucket.org/VirLinden/viewer-development-shining-fixes/changeset/c7fca203c70f 2012-01-27 21:28:27 -06:00
Siana Gearz
381d86adb7 Merge branch 'master' of git://github.com/Lirusaito/SingularityViewer 2012-01-28 03:26:52 +01:00
Siana Gearz
26858c026a Merge branch 'master' of https://github.com/Shyotl/SingularityViewer 2012-01-28 03:25:36 +01:00
Siana Gearz
c454044913 Merge branch 'master' of git://github.com/lkalif/SingularityViewer 2012-01-28 03:02:23 +01:00
Siana Gearz
6e57791397 Use NaCL nametag everywhere, even in radar 2012-01-28 03:00:42 +01:00
Lirusaito
1c5fc42772 This bar keeps us from clicking the bottom of the screen, why ever was it commented out? 2012-01-27 04:03:46 -05:00
Lirusaito
9bab3a362f Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-27 03:39:23 -05:00
Shyotl
fc65380f2a Added auto avatar muting(appearance only) based on avatar complexity (disabled by default). Added several missing debug views. 2012-01-27 02:36:26 -06:00
Shyotl
c1b749e12c Added some missed fasttimers, removed some old ones. 2012-01-27 02:31:57 -06:00
Lirusaito
d310ae3bc6 Changed three tabs to one space and two sets four spaces to avoid square character showing up in some cases. 2012-01-27 03:31:44 -05:00
Lirusaito
9ab0cd11e7 Changed name to Main (General) for easier support for older versions, while retaining the distinct new name. 2012-01-27 02:21:38 -05:00
Lirusaito
51c3f3253b Changed the name of Vanity's General tab to Main 2012-01-27 02:10:45 -05:00
Lirusaito
00c00b617c Changed spoof tag's name, added a heads up tooltip for enhanced boobs checkbox, fixed a large typo that made boob rebound have three decimal places, chopped the final bulk of preferences(may need another sweep through earlier ones) 2012-01-27 02:01:45 -05:00
Lirusaito
c0dd8cac46 Merge branch 'master' of git://github.com/lkalif/SingularityViewer 2012-01-26 23:30:41 -05:00
Lirusaito
8c35361878 Did some more chopping, added value boxes for volume controls that can be set, also made sure that the sliders stayed the same happy size. 2012-01-26 23:25:51 -05:00
Latif Khalifa
2e59ae1340 Implemented support for external script editor based on v3 code (part 2) 2012-01-27 05:25:18 +01:00
Latif Khalifa
856507a580 Implemented support for external script editor based on v3 code 2012-01-27 05:22:33 +01:00
Siana Gearz
8899dbef3c Fix plug-ins not working when path >32 characters 2012-01-27 05:08:15 +01:00
Lirusaito
8e4ea7e3b4 Removed all the scraps, commented out translations, since google decided to "be evil", Made the border around the radio smaller to look nicer. 2012-01-26 22:01:25 -05:00
Lirusaito
5524959f33 More sculpting away of old material, this one seemed to barely need follows 2012-01-26 20:27:42 -05:00
Lirusaito
39959712c1 Once again allowed for port values to reach their full potential, Extended input boxes, move some things left and right(no rearrangements), removal of old stuff. 2012-01-26 19:04:43 -05:00
Lirusaito
c652df10c6 Chopchopchop 2012-01-26 17:27:10 -05:00
Lirusaito
131dc84256 Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-26 17:10:44 -05:00
Shyotl
afed6dad84 Fix deferred on mac. VBO cleanup. https://bitbucket.org/VirLinden/viewer-development-shining-fixes/changeset/853c76596bdb 2012-01-26 16:09:47 -06:00
Lirusaito
b18033d023 Whoever modified this last is awesome, mostly two liners, not five lines per tag like normal ^*^ Chopped off boring stuffs. 2012-01-26 16:59:54 -05:00
Lirusaito
26bb68fcb7 Changed Texture offset increment to .01
Chopped some surrounding code, which shouldn't matter, didn't clean completely.
2012-01-26 16:29:25 -05:00
Lirusaito
2c4f850e5f Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-26 16:10:34 -05:00
Lirusaito
502fd90a8d Didn't really change much here, except a ton of repositioning due to the use of text_editors... these should be texts, most of them. 2012-01-26 16:07:04 -05:00
Lirusaito
f2c6ab27e3 Pulled all the oldstuff, moved some things to nicer spots and nicer sizes and changed the port range so that they can be anywhere within 16-bit unsigned number range. 2012-01-26 14:42:11 -05:00
Lirusaito
40bbeebd27 Fixed what I broke with custom checkbox. Returned the initial value of checkbox, as well. 2012-01-26 14:17:21 -05:00
Shyotl
f9d802f832 SH-2565 Move resetVertexBuffer operation to a consistent location (also avoid redundant resetting of vertex buffers on detail switches). Change assertion to a warning with count info. Fix bytes pooled debug display. Remove unused static vertex buffer. https://bitbucket.org/VirLinden/viewer-development-shining-fixes/changeset/56ac56c3cc9a 2012-01-26 12:55:24 -06:00
Shyotl
a6f95d21af LLFolderViewItem and LLFolderViewFolder migrated to llfolderviewitem.cpp/h. 2012-01-26 12:54:38 -06:00
Lirusaito
87f0edc652 Did a ton of stuff that makes General Preferences look prettier, added, changed and rephrased stuff relating to languages... Yay!
Removed old bulk.
2012-01-26 13:36:33 -05:00
Lirusaito
97c0800701 Moved strings to a more logical place, rearranged the layout of the top where grouping by row isn't important so that it is grouped by column to inherit left, changed the feathering sliders into spinners, because we're already using spinners everywhere else, and they're nicer.
And once more, removed all the bulk of old.
Should mention this is the joystick setup found in input preferences.
2012-01-26 06:57:36 -05:00
Lirusaito
da96043a24 Chopped off a ton of the old stuff, and added value fields... These don't seem to work right, however, no matter, the value fields help make more precise changes.
The existence of these were brought up to me by a phoenix user, not sure why showing them was set false.
2012-01-26 05:43:09 -05:00
Shyotl
f6fcf8ca38 Merge branch 'master' of git://github.com/siana/SingularityViewer.git 2012-01-26 00:14:38 -06:00
Lirusaito
43b826bd52 Merge branch 'master' of git://github.com/siana/SingularityViewer 2012-01-26 00:03:53 -05:00
Shyotl
cef03d52cb Un-inline LLFastTimer::NamedTimer::getCountAverage and LLFastTimer::NamedTimer::getCallAverage so some experimenting can be done in llfasttimer_class.cpp without massive recompiles. 2012-01-25 20:14:38 -06:00
Shyotl
29cdfdc13e Crashfix in LLAgent::teleportViaLocation if called before avatar is loaded (ex: doubleclicking the minimap) 2012-01-25 20:12:26 -06:00
Shyotl
2b8a5b4bd1 Allow tooltip to be refreshed when hovering over fasttimer bars. 2012-01-25 20:11:42 -06:00
Shyotl
910cb29a7f Truncating fasttimer times to integers in the hovertext is not very useful.. 2012-01-25 20:11:07 -06:00
Siana Gearz
3261332e0b ouch-i-feel-so-stupid build fix 2012-01-26 02:30:42 +01:00
Siana Gearz
6939d2d70b Build fixes 2012-01-25 23:45:18 +01:00
Siana Gearz
df65a3b7fc Merge branch 'master' of git://github.com/Lirusaito/SingularityViewer 2012-01-25 22:20:31 +01:00
Siana Gearz
7d9299d870 Merge branch 'master' of git://github.com/AlericInglewood/SingularityViewer 2012-01-25 22:18:21 +01:00
Lirusaito
00ae7c3cd3 Merge branch 'master' of git://github.com/siana/SingularityViewer 2012-01-25 15:52:32 -05:00
Lirusaito
769c4f43bd More cleaning up, some rephrasal of old stuff, changed some words to better suitsuit Singularity.
*yawn*
2012-01-25 15:45:23 -05:00
Siana Gearz
7fec659979 Update RLVa to 1.4.0-compatible 2012-01-25 21:11:33 +01:00
Lirusaito
d104d15c53 Yay, more cleaning! 2012-01-25 12:54:43 -05:00
Lirusaito
22137671da Stuff looks nicer than before, and removed a few more large archaic tag attributes. Also restored missing names, names for translating... wish they weren't so large... 2012-01-25 03:33:02 -05:00
Lirusaito
9577607c22 Merge branch 'master' of git://github.com/siana/SingularityViewer 2012-01-24 21:15:32 -05:00
Lirusaito
4340cee991 Merge branch 'master' of git://github.com/AlericInglewood/SingularityViewer 2012-01-24 21:15:15 -05:00
Siana Gearz
d385de9139 Merge branch 'master' of git://github.com/Shyotl/SingularityViewer
Conflicts:
	indra/newview/llstartup.cpp
	indra/newview/llviewerregion.cpp
2012-01-24 21:22:49 +01:00
Shyotl
c4e0122846 Call display_startup() periodically during initilization to avoid buggy drivers/windows from issuing vpu recover erroneously. 2012-01-23 20:36:25 -06:00
Shyotl
6374f012de new fasttimers, including ui. 2012-01-23 18:30:54 -06:00
Shyotl
7d4c2aa54f LLInventoryFilter migrated into llinventoryfilter.cpp/h 2012-01-22 21:46:10 -06:00
Shyotl
c5024ff04d Stab in the dark at fixing color corruption on 64bit builds. 2012-01-22 21:45:10 -06:00
Aleric Inglewood
63117686b1 Typo fix in comment. 2012-01-22 03:12:24 +01:00
Aleric Inglewood
f6bd78083d More merge fixes 2012-01-22 02:49:06 +01:00
Aleric Inglewood
f176aeed8d More 64-bit related compile errors. 2012-01-22 02:48:28 +01:00
Shyotl
51746dc751 Added wearable index handling to LLAgentWearables to scope out further changes. Index is still always zero for now, so behavior should not have changed. (marked with // TODO: MULTI-WEARABLE) 2012-01-21 19:02:19 -06:00
Aleric Inglewood
94d6ef126f Fix compiler error on 64-bit: error: cast from ‘char*’ to ‘U32 {aka unsigned int}’ loses precision 2012-01-22 01:56:35 +01:00
Aleric Inglewood
14f2df2a72 Remove compiler warning 'cast from pointer to integer of different size'. 2012-01-22 01:50:25 +01:00
Aleric Inglewood
82693aae35 linden_common.h must be included first for libcwd 2012-01-22 01:38:33 +01:00
Aleric Inglewood
c4e55464c9 Resolved collisions of merge with siana/master 2012-01-22 01:32:52 +01:00
Shyotl
4a4b786a60 New inventory observer implementation. 2012-01-21 04:54:39 -06:00
Shyotl
d7d65df9e0 HTTP inventory fetching enabled. 2012-01-21 02:37:22 -06:00
Shyotl
40400d696b Updated inv fetching impl. Haven't ticked on new caps. 2012-01-21 00:11:19 -06:00
Shyotl
4c201a9b83 Inv fetch migrated from LLInventoryModel to LLInventoryModelBackgroundFetch singleton. 2012-01-20 19:09:44 -06:00
Shyotl
b338506229 VBO updates from Vir Lindens shining fixes. VBO mapping perf improvement. Alpha rigged attachments render fix, hopefully. Crashfix in void pushWireframe. 2012-01-19 19:01:44 -06:00
Shyotl
7805508e8d SH-2827 crashfix. https://bitbucket.org/VirLinden/viewer-development-shining-fixes/changeset/806c10f621af 2012-01-19 10:36:56 -06:00
Shyotl
9837b0ea2e A little bit of code shuffling and member renaming in llinventoryview.cpp to line up with v3 a bit better. TO-DO: Many functions in LLInventoryView need to be migrated to something akin to v3s LLPanelMainInventory class. 2012-01-18 23:23:29 -06:00
Shyotl
60d5bb81f2 Tweak to CannotCopyWarning notification. Updated french notifications.xml a tiny bit. 2012-01-18 17:51:09 -06:00
Lirusaito
76cb68600c Rewrite of ancient xml preferences(The rest of the preferences still need this) so it takes up way less space and actually makes more sense...
last commit for a while do to illness.
2012-01-17 05:24:36 -05:00
Lirusaito
a6b270b02d Merge branch 'master' of git://github.com/lkalif/SingularityViewer 2012-01-16 23:14:13 -05:00
Lirusaito
f68a899185 Moved show avatar in Mouselook to Mouselook options... cause that's where it kinda should be... 2012-01-14 11:06:44 -05:00
Latif Khalifa
3299d27197 Added string needed to avoid modal error dialog with marketplace delivery 2012-01-14 16:16:52 +01:00
Siana Gearz
a39bf61977 Merge branch 'master' of git://github.com/Lirusaito/SingularityViewer 2012-01-14 13:54:24 +01:00
Siana Gearz
6a290864af Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-14 07:38:31 +01:00
Siana Gearz
20ab55752d Remove megaregion support 2012-01-14 06:46:16 +01:00
Lirusaito
4190816023 Removed the first configure command description and aligned the first two commands with the last two so it looks prettier. 2012-01-13 23:55:49 -05:00
Lirusaito
e33a15d410 Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-13 23:46:32 -05:00
Siana Gearz
419f7b41af Global lineending fixup 2012-01-14 05:42:53 +01:00
Shyotl
670b85a86f Migrated code out of drag and drop, and into LLGiveInventory. 2012-01-13 22:41:15 -06:00
Siana Gearz
e835d51bdf Revert "Crude port of megaregion mem corruption fix, by Rev"
This reverts commit 6b60fe40c6.
2012-01-14 05:33:05 +01:00
Siana Gearz
242134d2af Line ending unbotch 2012-01-14 05:32:22 +01:00
Shyotl
f0f2834cfe More stuff migrated to llinventoryfunctions.cpp 2012-01-13 21:05:53 -06:00
Shyotl
860bddb1f5 Added LLViewerInventoryType. Migrated some code to llinventoryfunctions.cpp. Pulled LLFolderViewEventListener out into itse own header. Misc tweaks to LLInventoryBridge and LLFolderBridge 2012-01-13 18:11:03 -06:00
Lirusaito
14f9cd57e1 Moved the button up one pixel, aligning it with voice and sound expand buttons, lowered Water preset text a bit, and lowered the water bar one pixel perfectly centering it with the button. 2012-01-13 17:43:15 -05:00
Lirusaito
063112bf59 Merge branch 'master' of git://github.com/siana/SingularityViewer 2012-01-13 15:59:52 -05:00
Siana Gearz
e764329701 Fixed up a merge botch 2012-01-13 21:59:00 +01:00
Lirusaito
27a17b332f Spelling fix 2012-01-13 15:51:58 -05:00
Lirusaito
373688cfb0 Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-13 15:50:16 -05:00
Siana Gearz
09d37d7dfd Merge branch 'master' of git://github.com/Lirusaito/SingularityViewer
Conflicts:
	indra/newview/skins/default/xui/en-us/wlfPanel_AdvSettings_expanded.xml
2012-01-13 19:18:22 +01:00
Siana Gearz
b2dd4f652e Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-13 19:14:43 +01:00
Siana Gearz
6bbff07e00 UI Purdyness 2012-01-13 19:14:14 +01:00
Lirusaito
09c7e66844 Spelling fix:
Query only has on r.
2012-01-13 03:23:20 -05:00
Shyotl
c371b82900 Added an optional val_width to slider and multi_slider_bar. When using this be sure it isn't truncating, as setting this value sets the textbox to a fixed width, with no consideration to the actual value it can contain. 2012-01-13 01:02:46 -06:00
Lirusaito
5da990e8fb Eep, did I leave that part of the test in?! 2012-01-13 00:52:13 -05:00
Lirusaito
b96beb478c Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-13 00:32:03 -05:00
Shyotl
ad3a16fd3b Merge branch 'master' of https://github.com/Lirusaito/SingularityViewer.git 2012-01-12 23:30:17 -06:00
Shyotl
21b6b89577 If this assert hits then I want your callstack, and so does Bao Linden. SH-2827 2012-01-12 23:28:38 -06:00
Shyotl
55a66737c0 Disable a certain octree error that likes to fire a bit frequently. 2012-01-12 23:24:44 -06:00
Lirusaito
198e499798 Fix for error: incomplete type ‘LLInventoryObserver’ used in nested name specifier presented by GCC 4.6.2 2012-01-13 00:18:37 -05:00
Lirusaito
9d3b276f61 Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-12 23:39:16 -05:00
Lirusaito
b0967463ca Take a good look at the Settings Panel in the release, see how icky it looks? Well, Boom! 2012-01-12 23:35:58 -05:00
Shyotl
1cc33caaa3 Pulled llinventorymodel apart into llinventorymodel, llinventoryobserver and llinventoryfunctions 2012-01-12 18:57:10 -06:00
Lirusaito
0777bedde8 Made it so the quick setting changer button never leaves its exact spot pixel for pixel;
Moved where exactly the bottom of the expanded panel was to match the unexpanded bottom;
Extended the bars of WindLight because their lack of capitalization on available real estate has been bugging me;
Changed the tooltip of the WindLight Water control to no longer _reflect the Sky_.
2012-01-12 17:48:43 -05:00
Lirusaito
be978ab76b A small change issued by Siana to correct a small problem. 2012-01-12 17:35:41 -05:00
Lirusaito
21a64b306d Added in two options under Help->Bug Reporting for reporting bugs with Singularity more easily:
Report Singularity Bug goes to the new issue page.
Singularity Issue Tracker goes to the issues list.
Spelling correction.
WebLaunchSinguIssue is called in these two new menu options.
2012-01-12 13:40:14 -05:00
Lirusaito
5a66c2bfba Added WebLaunchSinguIssue Notification, which will make sense in the next commit.
Also corrected location of Report Bug from in Tools to in Help under Bug Reporting.
2012-01-12 13:32:44 -05:00
Lirusaito
e5a27e6558 Added WebLaunchSinguIssue notification, but if feel my translation skills inadequate, so I'm just throwing this out here for someone like Nomade Zhao to correct and finish. 2012-01-12 13:25:20 -05:00
Lirusaito
6f3a92d772 Fixed spelling. 2012-01-12 13:10:27 -05:00
Siana Gearz
4feb69e342 Crouch toggle rewrite - removed garbage. 2012-01-12 06:35:42 +01:00
Siana Gearz
d2b2c501bc Merge branch 'master' of git://github.com/Lirusaito/SingularityViewer 2012-01-12 03:44:48 +01:00
Siana Gearz
465660e235 Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-12 01:42:59 +01:00
Siana Gearz
4eea8624b7 Fix keyboard shortcuts like ctrl+w for floaters 2012-01-12 01:37:13 +01:00
Lirusaito
09213950c3 May or may not fix a lack of AO stand animations caused by my last commit... probably does 2012-01-11 11:30:18 -05:00
Lirusaito
d93f0bb56a Rubber-band camera in crouchtoggle avoided. 2012-01-11 11:18:23 -05:00
Lirusaito
4de23007a5 Added crouch toggle, global bool called isCrouch, function agent_toggle_down bound to toggle_down.
Shift+crouch=toggle, crouch doesn't work while toggle crouched, at the moment.
Formatted keys.ini to be completely aligned.
2012-01-11 11:04:12 -05:00
Lirusaito
8543106f5e Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-11 02:28:14 -05:00
Shyotl
ced937cc46 Implemented CreateInventoryCategory sim caps support. (https://bitbucket.org/lindenlab/viewer-development/changeset/d327dcc8ae51) 2012-01-11 00:55:03 -06:00
Shyotl
9476aedaf6 Respect passed alpha value for checkerboard. 2012-01-11 00:50:39 -06:00
Shyotl
68bc6749e5 Hooked LLTrans into LLNotification stuffs. Also, fixed [CURRENCY] showing up in several places on the buy land window. 2012-01-11 00:49:14 -06:00
Lirusaito
c5d4ccc78d Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-09 17:59:17 -05:00
Shyotl
e847b105f2 CURRENCY added as a default token replacement within LLTrans. (Will be useful when strings are migrated from ui xmls to strings.xml). Also, fixed compile (missed llwindowcallbacks.cpp in my previous commit) 2012-01-09 16:54:13 -06:00
Lirusaito
d6e9b50b99 Spelling fix 2012-01-09 16:14:33 -05:00
Lirusaito
61beedd3d9 Changed style of comments with asterisks to avoid highlighting errors on //* with weak highlighters, change is to all files that could potentially break highlights
Most were needed, though some were just for possible problems with highlighting, should not affect performance whatsoever.
2012-01-09 05:40:03 -05:00
Lirusaito
35333f0105 Spelling fix 2012-01-09 05:20:12 -05:00
Lirusaito
be700d0719 Spelling fix, while changing comment styling. 2012-01-09 05:18:01 -05:00
Lirusaito
5dd2f5e2cf Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-09 05:10:15 -05:00
Shyotl
e9bd6a3b0d Better translation support relating to client initialization/login. 2012-01-09 01:40:30 -06:00
Lirusaito
d505e515e4 Moved parentheses into liru_assert_strip for usability. 2012-01-08 21:03:13 -05:00
Lirusaito
9fd813267e Added three macros, two to help the final one which exists to show file and line on llassert messages;
Changed the presentation of said messages to look nicer.
2012-01-08 18:21:43 -05:00
Lirusaito
f14e6cdb60 Pretty sure all I did was fix some things that didn't look nice to me or poor syntax highlighters, shouldn't affect performance... 2012-01-07 18:14:36 -05:00
Lirusaito
fe87ac0f3d Merge branch 'master' of git://github.com/siana/SingularityViewer 2012-01-07 18:14:15 -05:00
Siana Gearz
a6f36abab0 Semicolon care and feeding 2012-01-07 23:44:46 +01:00
Lirusaito
621e677898 Merge branch 'master' of git://github.com/siana/SingularityViewer 2012-01-07 17:09:43 -05:00
Lirusaito
626a94cf8f Merge branch 'master' of git://github.com/siana/SingularityViewer 2012-01-07 15:38:58 -05:00
Siana Gearz
d66074d2ea Merge branch 'master' of git://github.com/Shyotl/SingularityViewer 2012-01-07 21:36:24 +01:00
Shyotl
bf28f6514f Don't grey out 'properties' if selecting multiple items in inventory. 2012-01-06 13:49:24 -06:00
Shyotl
cf62e22409 gpu_table update 2012-01-06 13:48:21 -06:00
Lirusaito
900d063d4f Just fixed this file up a bit to look a bit nicer... Won't affect performance. 2012-01-06 11:18:31 -05:00
Siana Gearz
b911e86b02 Merge branch 'future' of git://github.com/Shyotl/SingularityViewer 2012-01-06 10:40:05 +01:00
Shyotl
54bfdb7704 Stippling removed. Emulated with a texture and some texcoord manipluation. (looks identical, and works with and without shaders) 2012-01-06 00:53:18 -06:00
Lirusaito
566152c230 Almost completely stripped, saving the final piece for tomorrow
((Double clicking from list of chat people on right of chats))
2012-01-05 21:56:48 -05:00
Shyotl
dcbf39bcfa (Loading...) text in ticker now goes away after 10 seconds. Some streams simply do not provide artist/title metadata. Only parse metadata every half second (opposed to every frame). Also fixed paused text getting clobbered. 2012-01-05 15:52:03 -06:00
Shyotl
c73913a864 Decided to allow width adjustment to ticker floater. It's a little wonky due to blocking height adjustment. LLFloater is kinda crappy and doesen't provide a real max_height/max_width mechanism to do this, so the behavior is a little wonky, but good enough for now. 2012-01-04 18:05:58 -06:00
Shyotl
d3ba4a2b80 Less hardcoded element manipluation for media ticker(allows more freedom for skins, etc). Added gridlines to visualizer. Added oscillator color to color tables (This process sucks, btw). 2012-01-04 03:55:53 -06:00
Shyotl
af7affa9dd Removed code for a case that will never occur (for oscillator). Also tiny bugfix related to iterating down wavedata buffers. 2012-01-03 21:31:21 -06:00
Shyotl
89e738003c Default RednerDelayVBUpdate to false. 2012-01-03 20:28:15 -06:00
Shyotl
a3f7399d7d Added media ticker to Singularity menu. Will be greyed out for anything not FMOD based. Consider implementing in other sound libraries as a to-do. FMOD Ex also displays an oscillator (making fmod3 do this is too dirty, so that's not going to be backported). 2012-01-03 20:27:56 -06:00
Shyotl
dff195d120 Several transparent ui-related components were writing to the depthbuffer for some silly reason. Don't do that since it messes with occlusion. 2011-12-30 19:15:21 -06:00
Shyotl
48552e3027 Set blendtype back to BT_ALPHA after postprocess, because ui assumes such [aka: glBlendFunc(GL_SOURCE_ALPHA, GL_ONE_MINUS_SOURCE_ALPHA)]. Also, line-ending fixup.. again. 2011-12-30 17:19:23 -06:00
Siana Gearz
c6ce417fac Attempt at fixing a Linux build botch in ReleaseSSE2 2011-12-29 13:39:59 +01:00
Siana Gearz
a7510d3b3a Merge git://github.com/Lirusaito/SingularityViewer 2011-12-28 04:28:49 +01:00
CobraElDiablo
aad10c9b8d SH-2516 Fix: Full Bright Geometry Rendering Increases Rapidly, Destroying Frame Rate. By Bao Linden 2011-12-28 04:27:04 +01:00
Shyotl
ca96e00135 Enable gl sync fence. Missed a vertexbuffer flush. moved LLMultiFloater out of llfloater.(h|cpp) and into its own header and source file, matching v2. 2011-12-26 23:40:18 -06:00
Inusaito Sayori
536189340d Merge branch 'master' of git://github.com/siana/SingularityViewer 2011-12-24 23:39:41 -05:00
Siana Gearz
23b97efb69 Prebuilt fetch now honors CMake-specified plattform 2011-12-25 05:21:37 +01:00
Siana Gearz
2c8e3bb0a3 More Linux build fixes 2011-12-25 04:28:17 +01:00
Inusaito Sayori
7a48cb9979 Merge branch 'master' of git://github.com/siana/SingularityViewer 2011-12-24 22:09:45 -05:00
Siana Gearz
2f5caa27fd Merge branch 'master' of git://github.com/TighMacFanatic/SingularityViewer 2011-12-25 03:37:03 +01:00
TighMacFanatic
d69f00741f Openjpeg compile fixes. 2011-12-24 15:07:52 -05:00
Siana Gearz
8c4a52e58d Merge branch 'future' of https://github.com/Shyotl/SingularityViewer 2011-12-24 20:12:47 +01:00
Siana Gearz
fd22d80dfd Merge branch 'future' of https://github.com/Shyotl/SingularityViewer
Conflicts:
	indra/newview/app_settings/shaders/class2/effects/gaussBlurF.glsl
	indra/newview/llmanipscale.cpp
	indra/newview/llmeshrepository.cpp
	indra/newview/llviewerregion.cpp
	indra/newview/llvovolume.cpp
2011-12-24 20:12:12 +01:00
TighMacFanatic
e071dc52fd Merge branch 'master' of https://github.com/siana/SingularityViewer 2011-12-24 13:52:14 -05:00
Shyotl
e1cbeb7e02 Oopsies. Undoing a change that shouldn't have made it into the previous commits. Was simply a part of an experiment. 2011-12-24 11:30:09 -06:00
Inusaito Sayori
9d367cf9f2 Spelling fix 2011-12-24 08:29:58 -05:00
Inusaito
3890e61fbc Merge branch 'master' of git://github.com/siana/SingularityViewer 2011-12-24 03:44:08 -05:00
Siana Gearz
3df853b74b Merge branch 'future' of git://github.com/TighMacFanatic/SingularityViewer 2011-12-24 09:00:31 +01:00
Siana Gearz
10bc483305 Merge branch 'master' of git://github.com/TighMacFanatic/SingularityViewer 2011-12-24 09:00:03 +01:00
Siana Gearz
f55fa45b73 No more spammy spam from inventory view, mini update to V3 2011-12-24 08:56:58 +01:00
Siana Gearz
acb24dd3e1 Some Resident scrubbing from IM headers, a-la V3 2011-12-24 08:56:20 +01:00
Inusaito Sayori
4b87c45298 Highlight for selected line should be visible without eyestrain. 2011-12-24 00:31:14 -05:00
Shyotl
a2fb56bf48 Removed soundgroups. Unneeded and redundant. Any potential usefulness is ursuped by LLAudioEngine's channel management, which I do not want to alter. 2011-12-23 18:29:13 -06:00
Shyotl
37095dc2cd Provide FMOD Ex with format hints. Use software mixing only. Fixed issue with channels being silently stolen due to maxchannels being too low (Wind and streaming audio + 30 sound sources were exceeding max channel count) 2011-12-23 18:00:54 -06:00
Siana Gearz
a57ac5a954 Make OpenJPEG respect our build settings 2011-12-23 23:23:55 +01:00
Siana Gearz
29045609a3 Attempt to fix linking on newer linux 2011-12-23 18:31:47 +01:00
Shyotl
b4dad425aa Fixed wind not mixing with other audio. Play no more than 30 world sounds at once (new sounds just muted until channels free up). Add fmod profiler support (SHEnableFMODExProfiler). Use FMOD_UNICODE on windows instead of loading files manually and sending raw data to fmod. Incl other misc cleanup. 2011-12-23 02:29:49 -06:00
Shyotl
c73414f1a1 A stab at fmodex support on windows. To use, install 'FMOD Ex Programmers API' to its defualt program files directory, and run develop.py with -DFMODEX:BOOL=ON set. That /should/ be all it takes. 2011-12-22 18:01:07 -06:00
Shyotl
6920bee5e2 Fmod metadata parsing. Innitial. 2011-12-21 01:23:04 -06:00
Shyotl
6a5e203884 Remove hardcoded var passing between LLPostProcess and its floater. Now driven through the xml file. 2011-12-17 00:20:54 -06:00
TighMacFanatic
6b1f44ed6d Fix for a rare error involving llSetPayPrice being used on a child prim. 2011-12-16 18:59:53 -05:00
TighMacFanatic
ab8cd3e5d5 #endif location fix 2011-12-16 18:44:51 -05:00
Shyotl
78f7cc0d64 Prim rotate tool was lacking colors on its 'rings' due to missing gGL.diffuseColor4fv calls. 2011-12-16 06:01:05 -06:00
Shyotl
b607650d5c V3 merge. Supposedly improves baked texture loading on other avatars. Also increase discard bias on ati if vram starts running out. 2011-12-16 05:57:48 -06:00
Shyotl
1bfa72fa7c V3 merge. Slight update. Fixes lighting oddities. 2011-12-16 01:50:57 -06:00
Shyotl
0030ca3af7 Fixed extra post-process shaders. Cleaned up and no longer using deprecated functions. 2011-12-16 01:46:20 -06:00
Shyotl
a53e08032f Prep for UI matrices. 2011-12-11 01:13:47 -06:00
Shyotl
62febda165 Disable rlva name substitution in LLHUDNameTag::setString. Was redundant and hosed up client tags. 2011-12-11 00:47:44 -06:00
Shyotl
a726de0e99 LLTexLayer now using shaders if applicable. Also added misc tidbits missed earlier. 2011-12-10 22:51:52 -06:00
Shyotl
918d527b14 Resolved nametag bubble image failing to load promptly. Also updated texture to that used in v3, as it looks cleaner. 2011-12-10 22:50:26 -06:00
Shyotl
5919c9a788 Resolved issue with nametag bubble vanishing due to incorrect blend states. 2011-12-10 22:47:43 -06:00
Shyotl
14f2248ea1 LLRenderTarget::copyContents more lenient to errors. 2011-12-10 22:46:26 -06:00
Shyotl
81499fc6ea -Font init cleanup. Now has a dedicated position in startup initilization. 2011-12-10 22:45:42 -06:00
Shyotl
ffb285c6ff Huge renderer update (WIP). Still plenty to do, especially pertaining to UI.
-Nametag bubble visbility is oddly inconsistent. May vanish with future planned UI merges...
-VBOs are PAINFULLY slow on ATI hardware. This repos self-compiled davep/shining-fixes branch, so I'll leave the ball in LL's court for now regarding that.
2011-12-09 14:02:29 -06:00
TighMacFanatic
e08e8cf131 Merge branch 'master' of https://github.com/siana/SingularityViewer 2011-12-03 13:03:39 -05:00
Siana Gearz
40b4b47023 Silly build fix 2011-12-03 18:52:04 +01:00
TighMacFanatic
2565caf62a Merge branch 'master' of https://github.com/siana/SingularityViewer 2011-12-03 11:52:29 -05:00
Siana Gearz
d63df79b85 Adding Neck and Root attachment points 2011-12-03 03:51:15 +01:00
Siana Gearz
697dd7e929 Preparing to add mesh upload. 2011-12-03 03:43:23 +01:00
TighMacFanatic
f613be9276 Added new water windlight 2011-12-02 10:41:53 -05:00
TighMacFanatic
f5a08b1c12 Merge branch 'master' of https://github.com/siana/SingularityViewer 2011-12-01 12:13:56 -05:00
TighMacFanatic
f40bbb1602 Merge branch 'master' of https://github.com/Shyotl/SingularityViewer 2011-12-01 12:13:42 -05:00
Siana Gearz
aeb766ee37 Attempt at work around OS X VBO slowness 2011-12-01 17:51:30 +01:00
Siana Gearz
cd67046b33 Silly way to clear stringstream on GCC 2011-12-01 17:41:50 +01:00
Siana Gearz
66f4c170cb Merge branch 'future' of https://github.com/Shyotl/SingularityViewer into renderer32 2011-12-01 16:51:43 +01:00
Siana Gearz
a485760028 Skipping first time dialogs enabled 2011-12-01 16:51:27 +01:00
Shyotl
0b5a2cd6a3 Un-break for compilers that don't yet support stringstream copying ala C++0x's MoveConstructible 2011-12-01 02:21:23 -06:00
Shyotl
8e7733b2ce Lazy shader update. attribute -> ATTRIBUTE, varying -> VARYING. Moved some shader preprocessor stuff from llviewershadermgr.cpp to llshadermgr.cpp to match LL (although it looks more messy) 2011-11-24 01:03:03 -06:00
Shyotl
08d2c17c65 Alphamask detection tweakage. 2011-11-24 00:31:45 -06:00
Shyotl
09f7136cf4 'Preserve texture scaling when animating textures when "size x" and "size y" parameters to llSetTextureAnim are zero.' https://bitbucket.org/davep/shining-fixes/changeset/db8a3f49c250 2011-11-23 23:44:04 -06:00
Shyotl
c4b77e247e LLInstanceTracker v3 merge 2011-11-23 23:40:31 -06:00
Shyotl
9f9daba33d Missed some glRotatef -> gGL.rotatef conversions. 2011-11-23 23:39:42 -06:00
Shyotl
dc3831c86b llmath v3 merge. 2011-11-23 23:04:54 -06:00
Siana Gearz
ab14f1908c Merge branch 'future' of https://github.com/Shyotl/SingularityViewer into renderer32 2011-11-24 04:43:47 +01:00
Shyotl
bf6e1d6c75 Unbork shadows. Apparently texture/texturProj do not return a vector for shadow samplers. 2011-11-23 21:30:32 -06:00
Shyotl
5d8d402403 Fix shader error dumping. (the error file was not being written to.) Also catch exceptions if shader log dir is inaccessable or otherwise unable to be cleared. 2011-11-23 21:29:42 -06:00
Siana Gearz
b8eb3076ce Merge branch 'future' of https://github.com/Shyotl/SingularityViewer into renderer32 2011-11-23 23:21:14 +01:00
TighMacFanatic
d16e48e128 Merge branch 'future' of https://github.com/Shyotl/SingularityViewer 2011-11-22 00:04:40 -05:00
Shyotl
e46c906a8b Invalid texure indexes now display as pink to better assist debugging. 2011-11-21 15:56:24 -06:00
Shyotl
83e8a9076b Several gl calls now wrapped via LLRender (gGL) as prep for future changes:
glMatrixMode -> gGL.matrixMode
..GL_MODELVIEW -> LLRender::MM_MODELVIEW
..GL_POJECTION -> LLRender::MM_PROJECTION
..GL_TEXTURE -> LLRender::MM_TEXTURE
glMultMatrix -> gGL.multMatrix
glLoadMatrixf -> gGL.loadMatrix
glPushMatrix -> gGL.pushMatrix
glPopMatrix -> gGL.popMatrix
glLoadIdentity -> gGL.loadIdentity
glRotatef -> gGL.rotatef
glTransformf -> gGL.transformf
glOrtho -> gGL.ortho
glColor3f -> gGL.diffuseColor3f
glColor3fv -> gGL.diffuseColor3fv
glColor4f -> gGL.diffuseColor4f
glColor4fv -> gGL.diffuseColor4fv
glColor4ubv -> gGL.diffuseColor4ubv
glLightModelfv(GL_LIGHT_MODEL_AMBIENT -> gGL.
2011-11-21 15:55:44 -06:00
TighMacFanatic
56b28756ad Merge branch 'master' of https://github.com/siana/SingularityViewer 2011-11-19 21:36:41 -05:00
TighMacFanatic
13fad75811 Merge branch 'future' of https://github.com/Shyotl/SingularityViewer 2011-11-19 21:36:32 -05:00
Shyotl
1cf367aae5 A little vectorization. gluProject replaced with vectorized glProjectf. Added LLMatrix4a::rotate4. Tweaked LLMatrix4a::rotate. Removed extra _mm_movehl_ps call in LLMatrix3a::setTranspose 2011-11-19 20:02:31 -06:00
Shyotl
70909f86c8 Changed some GL matricies to single precision. 2011-11-19 19:05:19 -06:00
Shyotl
1fd908b2c4 Removed maximum_alpha uniform (as it's always 1.0 anyhow) 2011-11-19 15:13:16 -06:00
Siana Gearz
f0108c17b9 Build floater fixes by Cale Flanagan +tinies 2011-11-14 06:36:46 +01:00
Siana Gearz
0566bde61b Merge branch 'master' of git://github.com/LightDrake/SingularityViewer 2011-11-14 06:13:47 +01:00
TighMacFanatic
a31fc8a612 Issue 14 - unlimited message lengths resolved. 2011-11-11 01:58:43 -05:00
TighMacFanatic
2ba9e16a6c Merge branch 'master' of https://github.com/siana/SingularityViewer 2011-11-10 12:27:02 -05:00
Siana Gearz
e6dce6ad7b #9 - region restart delay 2011-11-10 03:45:29 +01:00
TighMacFanatic
c87caebcf7 Merge branch 'master' of https://github.com/siana/SingularityViewer 2011-11-08 21:13:30 -05:00
Siana Gearz
121a557fe5 Fixes bug #79 2011-11-08 21:54:26 +01:00
Drake Arconis
6aa7f219cd Merge remote-tracking branch 'upstream/master' 2011-11-08 05:22:47 -05:00
TighMacFanatic
e9e05bec90 Merge branch 'master' of https://github.com/siana/SingularityViewer 2011-11-07 19:31:53 -05:00
Siana Gearz
8421661a89 Version 1.6.0(3) 2011-11-08 01:27:12 +01:00
Siana Gearz
7fea7c589d Make floating text draw distance tunable 2011-11-08 01:26:51 +01:00
TighMacFanatic
0e3b735a60 Merge branch 'future' of https://github.com/Shyotl/SingularityViewer 2011-11-07 18:44:33 -05:00
TighMacFanatic
236f5757a2 Fix paste bug in object size to clamp to new megaprim maximums. 2011-11-07 18:42:11 -05:00
unknown
0a44e3ee09 Merge branch 'master' of https://github.com/siana/SingularityViewer 2011-11-07 18:29:23 -05:00
Shyotl
ee5a9c97be Removing some shader warnings under gl 3.x context. 2011-11-07 16:43:30 -06:00
Shyotl
2126654979 Nuked some old redundant camera code. 2011-11-07 16:42:41 -06:00
Shyotl
df40a8c5cf Fade 'Press ESC to leave mouselook' away after a while. 2011-11-07 16:42:22 -06:00
Siana Gearz
34fb647903 Fix unable to delete links and make more purdy 2011-11-07 05:34:12 +01:00
Siana Gearz
5de4f1e2da Merge branch 'future' of https://github.com/Shyotl/SingularityViewer 2011-11-07 02:36:24 +01:00
Siana Gearz
18dd31f51a Fix outfit saving 2011-11-07 02:36:05 +01:00
Shyotl
40689f7d1e Fixed silly movement bug after taking high-res snapshots. 2011-11-06 16:29:43 -06:00
Siana Gearz
4ce0345842 Fix setting adult, mostly 2011-11-06 16:35:49 +01:00
Sovereign Engineer
844e38702a Merge remote-tracking branch 'upstream/master' 2011-11-03 14:32:35 -04:00
Siana Gearz
5f074c8c82 Fix most annoying minimap glitch 2011-11-02 18:37:56 +01:00
Siana Gearz
5c2b1d396b French! Huge thanks to Nomade Zhao! 2011-11-02 05:28:02 +01:00
Siana Gearz
b0b7837c4d Root prim gizmo fix 2011-11-02 04:42:23 +01:00
Siana Gearz
7789c5a703 Restore map overlay on SL 2011-11-01 18:14:43 +01:00
Shyotl
b64cb8d339 Lineending fixup 2011-10-31 20:44:43 -05:00
Shyotl
3891928092 vary_texture_index only needed in shaders when batching. 2011-10-31 20:44:33 -05:00
Shyotl
f5983208eb Hide the mouse cursor a bit better when grabbing items in mouselook. 2011-10-31 20:44:27 -05:00
Shyotl
0ef5931212 Added a bit of debug output for viewer tool states. 2011-10-31 20:43:56 -05:00
Shyotl
6964cec6f1 Merge branch 'master' of git://github.com/siana/SingularityViewer.git into future 2011-10-31 20:41:36 -05:00
Drake Arconis
a35ef93d19 Right Click Mouse Scroll Zoom and Xcode fix 2011-10-31 15:43:05 -04:00
Drake Arconis
e5f75d1e48 XCode fixes 2011-10-31 13:24:31 -04:00
Siana Gearz
231af66b90 Fixing for OS X 2011-10-31 16:00:05 +01:00
Siana Gearz
f386fc75df Did SELinux complain about THIS? 2011-10-31 05:24:00 +01:00
Siana Gearz
cc45a24aff Darwin doesn't use extension function pointer mechanism 2011-10-28 02:05:09 +02:00
Siana Gearz
e06d0b2e70 Whoopsie! 2011-10-27 23:02:35 +02:00
Siana Gearz
0281ac4afe There is no glext prebuilt on OS X 2011-10-27 22:39:28 +02:00
Brett Murphy
7227c01d79 updated install.xml with correct freetype package for mac-osx 2011-10-27 22:35:38 +02:00
Brett Murphy
c5abde1616 added ctrl-alt-p option for phantom avatar 2011-10-27 22:32:38 +02:00
Siana Gearz
c2a4951f20 Fix grid info fetch ignoring certificates 2011-10-26 21:35:19 +02:00
Shyotl
0fde15246b Moved some settings out of the main settings.xml and into settings_sh.xml where they belong. 2011-10-22 01:57:39 -05:00
Shyotl
b3423de80a Shaders dumped to logs/shader_dump directory if 'ShyotlDumpRawShaders' is true, or a shader throws an error of some sort. 2011-10-22 01:55:08 -05:00
Siana Gearz
743449e635 Tinies, custom OpenAL on Linux 2011-10-22 05:09:49 +02:00
Shyotl
405182025d Resolved warning about 8dcd4a48-2d37-4909-9f78-f7a9eb4ef903.j2c not being found. Also renamed it to transparent.j2c because I hate seeing local textures with uuid filenames... and because v2 renamed it too. 2011-10-21 21:46:35 -05:00
Siana Gearz
bd6d14d741 Merge branch 'future' of https://github.com/Shyotl/SingularityViewer 2011-10-22 01:17:59 +02:00
Shyotl
0e190cadcd LLWorld::destroyClass() wasn't releasing water texture refs. 2011-10-21 15:26:59 -05:00
Shyotl
408f5a4a51 SH-2564. Testing region visibility driven by spatial partitions. 2011-10-21 15:26:27 -05:00
Shyotl
53f5957b92 Animated faces with bumpmapping now behave as expected. 2011-10-21 15:03:46 -05:00
Shyotl
fb32a0be5a Failed to start tracking a new icon. (Inv_Invalid.png) 2011-10-21 14:52:13 -05:00
Shyotl
474e1ec7cc Particles (including clouds) vectorized a bit more. 2011-10-21 14:50:55 -05:00
Siana Gearz
1e9d09b82e Merge branch 'future' of https://github.com/Shyotl/SingularityViewer
Conflicts:
	indra/newview/llinventoryicon.cpp
2011-10-21 05:37:07 +02:00
Siana Gearz
c3b1bf4b76 Actually, tga loads more rapidly for some reason 2011-10-21 05:35:33 +02:00
Shyotl
e2d9c31f5e Fixed inventory icons for shirt and physic wearables. 2011-10-20 22:24:58 -05:00
Siana Gearz
7b81e9d248 Merge branch 'master' of github.com:siana/SingularityViewer 2011-10-21 04:56:21 +02:00
Siana Gearz
6e6c438e2a Merge branch 'future' of https://github.com/Shyotl/SingularityViewer 2011-10-21 04:55:08 +02:00
Siana Gearz
4606c7512e Icon mishaps, thx Cryo for spotting. +Standalone fix 2011-10-21 04:54:55 +02:00
Shyotl
88e373c960 The copy button in the face edit panel saves the texture params to a non-existant saved setting for some reason. This throws a crasloop prompt. Setting is never read back, so just commenting out this line. 2011-10-20 19:29:51 -05:00
Siana Gearz
f2deb39dac Merge branch 'future' of https://github.com/Shyotl/SingularityViewer
Conflicts:
	indra/newview/lldrawpoolbump.cpp
2011-10-21 01:42:12 +02:00
Shyotl
8a5793ce23 Selected face overlay no longer z-fights with the selected prim face. 2011-10-20 16:23:28 -05:00
unknown
a36c5f2ee6 Merge branch 'future' of https://github.com/Shyotl/SingularityViewer into future 2011-10-20 14:56:37 -04:00
Shyotl
c63bf31328 I don't trust this statement to work without the parentesis. 2011-10-20 13:46:56 -05:00
Shyotl
5d811163a6 gDeferredShadowAlphaMaskProgram should be unbound after renderpass 2011-10-20 13:45:28 -05:00
Shyotl
78a98cbf08 Bump shader needs to have texture0 sample assigned to index0, and texture1 as index1. Confirmed in LLDrawPoolBump::bindBumpMap. (This probably isn't required yet, but appears safe) 2011-10-20 13:45:00 -05:00
Shyotl
91348909b5 Shuffled gObjectSimpleWaterProgram and gObjectSimpleAlphaMaskProgram around 2011-10-20 13:43:25 -05:00
Shyotl
73f2543a6f Use LLGLShader::sIndexTextureChannels instead of mNumTextureImageUnits directly.. also check that channel value isn't invalid. Also make super-sure shaders are disabled on pre opengl 2.0 hardware. 2011-10-20 13:37:09 -05:00
unknown
d80458b726 Merge branch 'master' of https://github.com/siana/SingularityViewer 2011-10-20 14:36:59 -04:00
Shyotl
22385c44c8 Make legacy renderpath a bit more strict. 2011-10-20 13:30:29 -05:00
Shyotl
40261d3472 Invalid texunit was still bound after bumpmapping finished 2011-10-20 13:26:08 -05:00
Siana Gearz
06ff562cd2 Added Mobility Radeon 6 series 2011-10-20 20:23:29 +02:00
unknown
e7b023778a Merge branch 'master' of https://github.com/siana/SingularityViewer 2011-10-20 14:08:10 -04:00
Siana Gearz
3e12fe15bc Version 1.6.0(2) 2011-10-20 18:44:21 +02:00
Siana Gearz
95634e8276 Don't know why exactly this works, but fixes noshader and seems safe. 2011-10-20 13:10:11 +02:00
Siana Gearz
6c19346855 Bug fixing the repackager 2011-10-20 13:09:30 +02:00
unknown
2e4419a295 Merge branch 'future' of https://github.com/Shyotl/SingularityViewer 2011-10-19 16:12:15 -04:00
unknown
bdc95a1544 Merge branch 'future' of https://github.com/Shyotl/SingularityViewer into future 2011-10-19 16:09:24 -04:00
Siana Gearz
68e143de1b Merge branch 'future' of https://github.com/Shyotl/SingularityViewer 2011-10-19 18:11:58 +02:00
Shyotl
5d6aadb268 Prevent estimated vram value from being clobbered if glGetIntegerv memory query returns something too small. 2011-10-19 09:53:44 -05:00
Shyotl
4368c57243 Disabled reserved attrib having reserved locations in shaders. Conflicted with attrib location assumptions elsewhere. 2011-10-19 09:43:28 -05:00
Siana Gearz
ef54491760 GCC 4.6.1 fix 2011-10-19 05:33:09 +02:00
Shyotl
d88f696604 Brought over LLInventoryIcon 2011-10-18 19:44:08 -05:00
Shyotl
82b0171a86 Workaround for mac startup hardlock. (STORM-1641) 2011-10-18 09:33:20 -05:00
TighMacFanatic
ff786ad2c7 Merge branch 'future' of https://github.com/Shyotl/SingularityViewer into future 2011-10-13 18:16:40 -04:00
TighMacFanatic
c95696e8a0 Merge branch 'future' of https://github.com/siana/SingularityViewer into future 2011-10-13 18:13:16 -04:00
TighMacFanatic
4dbed63f0b Merge branch 'master' of https://github.com/siana/SingularityViewer into future 2011-10-13 18:13:04 -04:00
Aleric Inglewood
3de99315e2 Some AIFrameTimer code cleanup and comment fixes. 2011-08-14 15:42:46 +02:00
Aleric Inglewood
5945793031 Implementation of AIFrameTimer. 2011-08-13 17:32:50 +02:00
Aleric Inglewood
449e7b2a84 Merge remote-tracking branch 'origin/master' 2011-08-13 17:32:27 +02:00
Siana Gearz
cdebc1c5cc Version 1.5.10(2) 2011-08-09 03:57:57 +02:00
Aleric Inglewood
e95ee85804 Make LLFrameTimer thread-safe.
LLFrameTimer::sFrameTime is accessed by the texture
thread as well. Although the only consequences are
that it's possible for a timer in the texture thread
to time out too early (or to never time out when
it's started) when it reads this variable at the
same time as that it is updated, which is pretty
inlikely, it's just not-done to leave anything
thread-unsafe when it's known to be thread-unsafe.

This patch also adds a framework for AIFrameTimer, but
that isn't implemented yet.
2011-08-08 19:21:27 +02:00
Aleric Inglewood
5e69c9fa05 Merge remote-tracking branch 'origin/master' 2011-08-08 19:20:39 +02:00
Aleric Inglewood
370890b704 We use is_main_thread() for this. 2011-08-06 13:45:01 +02:00
1115 changed files with 80094 additions and 36160 deletions

View File

@@ -1,4 +0,0 @@
This is a modified version of openal-soft from GIT (56cc03860378e2758370b773b2a6f1b4e086b49a).
The modified source which this was built from is available here:
http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/openal-soft-linden-56cc03860378e2758370b773b2a6f1b4e086b49a.tar.bz2

View File

@@ -670,19 +670,19 @@
<key>EstateChangeInfo</key> <key>EstateChangeInfo</key>
<boolean>true</boolean> <boolean>true</boolean>
<key>FetchInventoryDescendents</key> <key>FetchInventoryDescendents2</key>
<boolean>false</boolean> <boolean>false</boolean>
<key>WebFetchInventoryDescendents</key> <key>WebFetchInventoryDescendents</key>
<boolean>false</boolean> <boolean>false</boolean>
<key>FetchInventory</key> <key>FetchInventory2</key>
<boolean>true</boolean> <boolean>true</boolean>
<key>FetchLibDescendents</key> <key>FetchLibDescendents2</key>
<boolean>true</boolean> <boolean>true</boolean>
<key>FetchLib</key> <key>FetchLib2</key>
<boolean>true</boolean> <boolean>true</boolean>
</map> </map>

View File

@@ -113,7 +113,7 @@ if (WINDOWS)
endif (WINDOWS) endif (WINDOWS)
set (GCC_EXTRA_OPTIMIZATION "-ffast-math -frounding-math") set (GCC_EXTRA_OPTIMIZATIONS "-ffast-math -frounding-math")
if (LINUX) if (LINUX)
set(CMAKE_SKIP_RPATH TRUE) set(CMAKE_SKIP_RPATH TRUE)
@@ -182,53 +182,29 @@ if (LINUX)
-pthread -pthread
) )
if (SERVER) add_definitions(-DAPPID=secondlife)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-60") add_definitions(-fvisibility=hidden)
if (EXISTS /etc/debian_version) # don't catch SIGCHLD in our base application class for the viewer - some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The viewer doesn't need to catch SIGCHLD anyway.
FILE(READ /etc/debian_version DEBIAN_VERSION) add_definitions(-DLL_IGNORE_SIGCHLD)
else (EXISTS /etc/debian_version) if (NOT STANDALONE)
set(DEBIAN_VERSION "") # this stops us requiring a really recent glibc at runtime
endif (EXISTS /etc/debian_version) add_definitions(-fno-stack-protector)
endif (NOT STANDALONE)
if (NOT DEBIAN_VERSION STREQUAL "3.1") if (${ARCH} STREQUAL "x86_64")
add_definitions(-DCTYPE_WORKAROUND) add_definitions(-DLINUX64=1 -pipe)
endif (NOT DEBIAN_VERSION STREQUAL "3.1") set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers")
set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers")
if (EXISTS /usr/lib/mysql4/mysql) set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers")
link_directories(/usr/lib/mysql4/mysql) set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers")
endif (EXISTS /usr/lib/mysql4/mysql) else (${ARCH} STREQUAL "x86_64")
add_definitions(
-msse2
-mfpmath=sse
)
endif (SERVER)
if (VIEWER)
add_definitions(-DAPPID=secondlife)
add_definitions(-fvisibility=hidden)
# don't catch SIGCHLD in our base application class for the viewer - some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The viewer doesn't need to catch SIGCHLD anyway.
add_definitions(-DLL_IGNORE_SIGCHLD)
if (NOT STANDALONE) if (NOT STANDALONE)
# this stops us requiring a really recent glibc at runtime set(MARCH_FLAG " -march=pentium4")
add_definitions(-fno-stack-protector)
endif (NOT STANDALONE) endif (NOT STANDALONE)
if (${ARCH} STREQUAL "x86_64") set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2}${MARCH_FLAG} -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}")
add_definitions(-DLINUX64=1 -pipe) set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2}${MARCH_FLAG} -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}")
set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}")
set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") endif (${ARCH} STREQUAL "x86_64")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers")
else (${ARCH} STREQUAL "x86_64")
if (NOT STANDALONE)
set(MARCH_FLAG " -march=pentium4")
endif (NOT STANDALONE)
set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2}${MARCH_FLAG} -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}")
set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2}${MARCH_FLAG} -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS})
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS})
endif (${ARCH} STREQUAL "x86_64")
endif (VIEWER)
set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG} -msse2") set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG} -msse2")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 ${CMAKE_CXX_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS_RELEASE "-O3 ${CMAKE_CXX_FLAGS_RELEASE}")
@@ -258,13 +234,13 @@ endif (DARWIN)
if (LINUX OR DARWIN) if (LINUX OR DARWIN)
set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs -Wno-non-virtual-dtor -Woverloaded-virtual") set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs")
if (NOT GCC_DISABLE_FATAL_WARNINGS) if (NOT GCC_DISABLE_FATAL_WARNINGS)
set(GCC_WARNINGS "${GCC_WARNINGS} -Werror") set(GCC_WARNINGS "${GCC_WARNINGS} -Werror")
endif (NOT GCC_DISABLE_FATAL_WARNINGS) endif (NOT GCC_DISABLE_FATAL_WARNINGS)
set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder") set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor -Woverloaded-virtual")
set(CMAKE_C_FLAGS "${GCC_WARNINGS} ${CMAKE_C_FLAGS}") set(CMAKE_C_FLAGS "${GCC_WARNINGS} ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${GCC_CXX_WARNINGS} ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${GCC_CXX_WARNINGS} ${CMAKE_CXX_FLAGS}")
@@ -298,10 +274,6 @@ if(1 EQUAL 1)
add_definitions(-DMESH_ENABLED=1) add_definitions(-DMESH_ENABLED=1)
endif(1 EQUAL 1) endif(1 EQUAL 1)
if(SERVER)
include_directories(${LIBS_PREBUILT_DIR}/include/havok)
endif(SERVER)
SET( CMAKE_EXE_LINKER_FLAGS_RELEASESSE2 SET( CMAKE_EXE_LINKER_FLAGS_RELEASESSE2
"${CMAKE_EXE_LINKER_FLAGS_RELEASE}" CACHE STRING "${CMAKE_EXE_LINKER_FLAGS_RELEASE}" CACHE STRING
"Flags used for linking binaries under SSE2 build." "Flags used for linking binaries under SSE2 build."

View File

@@ -6,6 +6,11 @@ set(DB_FIND_REQUIRED ON)
if (STANDALONE) if (STANDALONE)
include(FindBerkeleyDB) include(FindBerkeleyDB)
else (STANDALONE) else (STANDALONE)
set(DB_LIBRARIES db-4.2) if (LINUX)
# Need to add dependency pthread explicitely to support ld.gold.
set(DB_LIBRARIES db-4.2 pthread)
else (LINUX)
set(DB_LIBRARIES db-4.2)
endif (LINUX)
set(DB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) set(DB_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
endif (STANDALONE) endif (STANDALONE)

View File

@@ -35,7 +35,7 @@ set(cmake_SOURCE_FILES
FindNDOF.cmake FindNDOF.cmake
FindOpenJPEG.cmake FindOpenJPEG.cmake
FindXmlRpcEpi.cmake FindXmlRpcEpi.cmake
FMOD.cmake FMOD.cmake
FreeType.cmake FreeType.cmake
GStreamer010Plugin.cmake GStreamer010Plugin.cmake
GooglePerfTools.cmake GooglePerfTools.cmake
@@ -84,6 +84,10 @@ set(cmake_SOURCE_FILES
ZLIB.cmake ZLIB.cmake
) )
if(FMODEX)
list(APPEND cmake_SOURCE_FILES FMODEX.cmake)
endif(FMODEX)
source_group("Shared Rules" FILES ${cmake_SOURCE_FILES}) source_group("Shared Rules" FILES ${cmake_SOURCE_FILES})
set(master_SOURCE_FILES set(master_SOURCE_FILES

View File

@@ -243,12 +243,51 @@ set(all_targets ${all_targets} ${out_targets})
set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release") set(release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")
set(release_files set(release_files
libtcmalloc_minimal.dll libtcmalloc_minimal.dll
fmod.dll
libhunspell.dll libhunspell.dll
libapr-1.dll libapr-1.dll
libaprutil-1.dll libaprutil-1.dll
libapriconv-1.dll libapriconv-1.dll
) )
if(FMODEX)
find_path(FMODEX_BINARY_DIR fmodex.dll
${release_src_dir}
${FMODEX_SDK_DIR}/api
${FMODEX_SDK_DIR}
)
if(FMODEX_BINARY_DIR)
copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Release" out_targets fmodex.dll)
set(all_targets ${all_targets} ${out_targets})
copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2" out_targets fmodex.dll)
set(all_targets ${all_targets} ${out_targets})
copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo" out_targets fmodex.dll)
set(all_targets ${all_targets} ${out_targets})
copy_if_different("${FMODEX_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Debug" out_targets fmodex.dll)
set(all_targets ${all_targets} ${out_targets})
endif(FMODEX_BINARY_DIR)
endif(FMODEX)
if(FMOD)
find_path(FMOD_BINARY_DIR fmod.dll
${release_src_dir}
${FMOD_SDK_DIR}/api
${FMOD_SDK_DIR}
)
if(FMOD_BINARY_DIR)
copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Release" out_targets fmod.dll)
set(all_targets ${all_targets} ${out_targets})
copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/ReleaseSSE2" out_targets fmod.dll)
set(all_targets ${all_targets} ${out_targets})
copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo" out_targets fmod.dll)
set(all_targets ${all_targets} ${out_targets})
copy_if_different("${FMOD_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/Debug" out_targets fmod.dll)
set(all_targets ${all_targets} ${out_targets})
else(FMOD_BINARY_DIR)
list(APPEND release_files fmod.dll) #Required for compile. This will cause an error in copying binaries.
endif(FMOD_BINARY_DIR)
endif(FMOD)
copy_if_different( copy_if_different(
${release_src_dir} ${release_src_dir}

View File

@@ -6,6 +6,7 @@ set(install_dir "@CMAKE_SOURCE_DIR@/..")
set(scp "@SCP_EXECUTABLE@") set(scp "@SCP_EXECUTABLE@")
set(scripts_dir "@SCRIPTS_DIR@") set(scripts_dir "@SCRIPTS_DIR@")
set(sentinel_dir "@CMAKE_BINARY_DIR@/prepare") set(sentinel_dir "@CMAKE_BINARY_DIR@/prepare")
set(prebuilt_type "@PREBUILT_TYPE@")
# In proprietary mode we use scp for download. # In proprietary mode we use scp for download.
set(proprietary "@INSTALL_PROPRIETARY@") set(proprietary "@INSTALL_PROPRIETARY@")
@@ -19,7 +20,7 @@ foreach(package ${packages})
# This package is missing or out of date. # This package is missing or out of date.
message(STATUS "Obtaining${proprietary_message} prebuilt '${package}'") message(STATUS "Obtaining${proprietary_message} prebuilt '${package}'")
execute_process( execute_process(
COMMAND ${python} install.py --install-dir=${install_dir} ${scp_option} ${package} COMMAND ${python} install.py -p${prebuilt_type} --install-dir=${install_dir} ${scp_option} ${package}
WORKING_DIRECTORY ${scripts_dir} WORKING_DIRECTORY ${scripts_dir}
RESULT_VARIABLE result RESULT_VARIABLE result
) )

83
indra/cmake/FMODEX.cmake Normal file
View File

@@ -0,0 +1,83 @@
# -*- cmake -*-
include(Linking)
if(INSTALL_PROPRIETARY)
include(Prebuilt)
use_prebuilt_binary(fmodex)
endif(INSTALL_PROPRIETARY)
find_library(FMODEX_LIBRARY_RELEASE
NAMES fmodex fmodex_vc fmodexL_vc
PATHS
${ARCH_PREBUILT_DIRS_RELEASE}
)
find_library(FMODEX_LIBRARY_DEBUG
NAMES fmodex fmodex_vc fmodexL_vc
PATHS
${ARCH_PREBUILT_DIRS_DEBUG}
)
if (FMODEX_LIBRARY_RELEASE AND FMODEX_LIBRARY_DEBUG)
set(FMODEX_LIBRARY
debug ${FMODEX_LIBRARY_DEBUG}
optimized ${FMODEX_LIBRARY_RELEASE})
elseif (FMODEX_LIBRARY_RELEASE)
set(FMODEX_LIBRARY ${FMODEX_LIBRARY_RELEASE})
endif (FMODEX_LIBRARY_RELEASE AND FMODEX_LIBRARY_DEBUG)
if (NOT FMODEX_LIBRARY)
set(FMODEX_SDK_DIR CACHE PATH "Path to the FMOD Ex SDK.")
if (FMODEX_SDK_DIR)
find_library(FMODEX_LIBRARY
fmodex fmodex_vc fmodexL_vc
PATHS
${FMODEX_SDK_DIR}/api/lib
${FMODEX_SDK_DIR}/api
${FMODEX_SDK_DIR}/lib
${FMODEX_SDK_DIR}
)
endif(FMODEX_SDK_DIR)
if(WINDOWS AND NOT FMODEX_LIBRARY)
set(FMODEX_PROG_DIR "$ENV{PROGRAMFILES}/FMOD SoundSystem/FMOD Programmers API Windows")
find_library(FMODEX_LIBRARY
fmodex_vc fmodexL_vc
PATHS
${FMODEX_PROG_DIR}/api/lib
${FMODEX_PROG_DIR}/api
${FMODEX_PROG_DIR}
)
if(FMODEX_LIBRARY)
message(STATUS "Found fmodex in ${FMODEX_PROG_DIR}")
set(FMODEX_SDK_DIR ${FMODEX_PROG_DIR})
set(FMODEX_SDK_DIR ${FMODEX_PROG_DIR} CACHE PATH "Path to the FMOD Ex SDK." FORCE)
endif(FMODEX_LIBRARY)
endif(WINDOWS AND NOT FMODEX_LIBRARY)
endif (NOT FMODEX_LIBRARY)
find_path(FMODEX_INCLUDE_DIR fmod.h
${LIBS_PREBUILT_DIR}/include/fmodex
${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/fmodex
${FMODEX_SDK_DIR}/api/inc
${FMODEX_SDK_DIR}/inc
${FMODEX_SDK_DIR}
)
if (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
set(FMODEX ON CACHE BOOL "Use closed source FMOD Ex sound library.")
else (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
set(FMODEX_LIBRARY "")
set(FMODEX_INCLUDE_DIR "")
if (FMODEX)
message(STATUS "No support for FMOD Ex audio (need to set FMODEX_SDK_DIR?)")
endif (FMODEX)
set(FMODEX OFF CACHE BOOL "Use closed source FMOD Ex sound library.")
set(FMODEX OFF)
endif (FMODEX_LIBRARY AND FMODEX_INCLUDE_DIR)
if (FMODEX)
message(STATUS "Building with FMOD Ex audio support")
endif (FMODEX)

View File

@@ -18,7 +18,14 @@ set(LLCOMMON_INCLUDE_DIRS
${Boost_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
) )
set(LLCOMMON_LIBRARIES llcommon) if (LINUX)
# In order to support using ld.gold on linux, we need to explicitely
# specify all libraries that llcommon uses.
# llcommon uses `clock_gettime' which is provided by librt on linux.
set(LLCOMMON_LIBRARIES llcommon rt)
else (LINUX)
set(LLCOMMON_LIBRARIES llcommon)
endif (LINUX)
set(LLCOMMON_LINK_SHARED ON CACHE BOOL "Build the llcommon target as a shared library.") set(LLCOMMON_LINK_SHARED ON CACHE BOOL "Build the llcommon target as a shared library.")
if(LLCOMMON_LINK_SHARED) if(LLCOMMON_LINK_SHARED)

View File

@@ -5,4 +5,10 @@ set(LLPLUGIN_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llplugin ${LIBS_OPEN_DIR}/llplugin
) )
set(LLPLUGIN_LIBRARIES llplugin) if (LINUX)
# In order to support using ld.gold on linux, we need to explicitely
# specify all libraries that llplugin uses.
set(LLPLUGIN_LIBRARIES llplugin pthread)
else (LINUX)
set(LLPLUGIN_LIBRARIES llplugin)
endif (LINUX)

View File

@@ -1,10 +1,10 @@
# -*- cmake -*- # -*- cmake -*-
include(Prebuilt) include(Prebuilt)
if (NOT STANDALONE) if (NOT (STANDALONE OR DARWIN))
use_prebuilt_binary(glext) use_prebuilt_binary(glext)
# possible glh_linear should have its own .cmake file instead # possible glh_linear should have its own .cmake file instead
#use_prebuilt_binary(glh_linear) #use_prebuilt_binary(glh_linear)
# actually... not any longer, it's now in git -SG # actually... not any longer, it's now in git -SG
set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
endif (NOT STANDALONE) endif ()

View File

@@ -76,24 +76,16 @@ endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(DARWIN 1) set(DARWIN 1)
# NOTE: If specifying a different SDK with CMAKE_OSX_SYSROOT at configure #SDK Compiler and Deployment targets for XCode
# time you should also specify CMAKE_OSX_DEPLOYMENT_TARGET explicitly, if (${XCODE_VERSION} VERSION_LESS 4.0.0)
# otherwise CMAKE_OSX_SYSROOT will be overridden here. We can't just check
# for it being unset, as it gets set to the system default :(
# Default to building against the 10.5 SDK if no deployment target is
# specified.
if (NOT CMAKE_OSX_DEPLOYMENT_TARGET)
# NOTE: setting -isysroot is NOT adequate: http://lists.apple.com/archives/Xcode-users/2007/Oct/msg00696.html
# see http://public.kitware.com/Bug/view.php?id=9959 + poppy
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk) set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk)
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5) set(CMAKE_XCODE_ATTIBUTE_GCC_VERSION "4.2")
endif (NOT CMAKE_OSX_DEPLOYMENT_TARGET) else (${XCODE_VERSION} VERSION_LESS 4.0.0)
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.6.sdk)
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42")
endif (${XCODE_VERSION} VERSION_LESS 4.0.0)
# Use GCC 4.2 set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5)
if (${CMAKE_OSX_SYSROOT} MATCHES "10.5")
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "4.2")
endif (${CMAKE_OSX_SYSROOT} MATCHES "10.5")
# NOTE: To attempt an i386/PPC Universal build, add this on the configure line: # NOTE: To attempt an i386/PPC Universal build, add this on the configure line:
# -DCMAKE_OSX_ARCHITECTURES:STRING='i386;ppc' # -DCMAKE_OSX_ARCHITECTURES:STRING='i386;ppc'
@@ -118,6 +110,17 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
if (WINDOWS)
set(PREBUILT_TYPE windows)
elseif(DARWIN)
set(PREBUILT_TYPE darwin)
elseif(LINUX AND WORD_SIZE EQUAL 32)
set(PREBUILT_TYPE linux)
elseif(LINUX AND WORD_SIZE EQUAL 64)
set(PREBUILT_TYPE linux64)
endif(WINDOWS)
# Default deploy grid # Default deploy grid
set(GRID agni CACHE STRING "Target Grid") set(GRID agni CACHE STRING "Target Grid")

View File

@@ -775,9 +775,8 @@ Options:
-p | --project=NAME set the root project name. (Doesn't effect makefiles) -p | --project=NAME set the root project name. (Doesn't effect makefiles)
Commands: Commands:
build configure and build default target build configure and build default target
clean delete all build directories, does not affect sources clean delete all build directories, does not affect sources
configure configure project by running cmake (default command if none given)
configure configure project by running cmake (default if none given) configure configure project by running cmake (default if none given)
printbuilddirs print the build directory that will be used printbuilddirs print the build directory that will be used

View File

@@ -168,7 +168,10 @@ ARGUMENTS=[
dict(name='version', dict(name='version',
description="""This specifies the version of Second Life that is description="""This specifies the version of Second Life that is
being packaged up.""", being packaged up.""",
default=get_default_version) default=get_default_version),
dict(name='extra_libraries',
description="""List of extra libraries to include in package""",
default=None)
] ]
def usage(srctree=""): def usage(srctree=""):

View File

@@ -1,105 +1,84 @@
# Main CMakeLists.txt to build the OpenJPEG project using CMake (www.cmake.org) # -*- cmake -*-
# Written by Mathieu Malaterre
CMAKE_MINIMUM_REQUIRED(VERSION 2.6) project(openjpeg)
IF(COMMAND CMAKE_POLICY) include(00-Common)
CMAKE_POLICY(SET CMP0003 NEW)
ENDIF(COMMAND CMAKE_POLICY)
PROJECT(openjpeg)
# Do full dependency headers.
INCLUDE_REGULAR_EXPRESSION("^.*$")
#-----------------------------------------------------------------------------
# OPENJPEG version number, useful for packaging and doxygen doc: # OPENJPEG version number, useful for packaging and doxygen doc:
SET(OPENJPEG_VERSION_MAJOR 1) set(OPENJPEG_VERSION_MAJOR 1)
SET(OPENJPEG_VERSION_MINOR 4) set(OPENJPEG_VERSION_MINOR 4)
SET(OPENJPEG_VERSION_BUILD 0) set(OPENJPEG_VERSION_BUILD 0)
SET(OPENJPEG_VERSION set(OPENJPEG_VERSION
"${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}") "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}")
set(openjpeg_SOURCE_FILES
bio.c
cio.c
dwt.c
event.c
image.c
j2k.c
j2k_lib.c
jp2.c
jpt.c
mct.c
mqc.c
openjpeg.c
pi.c
raw.c
t1.c
t2.c
tcd.c
tgt.c
)
set(openjpeg_HEADER_FILES
bio.h
cio.h
dwt.h
event.h
fix.h
image.h
int.h
j2k.h
j2k_lib.h
jp2.h
jpt.h
mct.h
mqc.h
openjpeg.h
opj_includes.h
opj_malloc.h
pi.h
raw.h
t1.h
t1_luts.h
t2.h
tcd.h
tgt.h
)
IF(WINDOWS)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-DOPJ_STATIC)
ENDIF(WINDOWS)
set_source_files_properties(${openjpeg_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
list(APPEND openjpeg_SOURCE_FILES ${openjpeg_HEADER_FILES})
add_library (openjpeg ${openjpeg_SOURCE_FILES})
# This setting of SOVERSION assumes that any API change # This setting of SOVERSION assumes that any API change
# will increment either the minor or major version number of openjpeg # will increment either the minor or major version number of openjpeg
SET(OPENJPEG_LIBRARY_PROPERTIES set(OPENJPEG_LIBRARY_PROPERTIES
VERSION "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}" VERSION "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}"
SOVERSION "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}" SOVERSION "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}"
) )
# On Visual Studio 8 MS deprecated C. This removes all 1.276E1265 security set_target_properties(openjpeg PROPERTIES
# warnings
IF(WIN32)
IF(NOT BORLAND)
IF(NOT CYGWIN)
IF(NOT MINGW)
IF(NOT ITK_ENABLE_VISUAL_STUDIO_DEPRECATED_C_WARNINGS)
ADD_DEFINITIONS(
-D_CRT_FAR_MAPPINGS_NO_DEPRECATE
-D_CRT_IS_WCTYPE_NO_DEPRECATE
-D_CRT_MANAGED_FP_NO_DEPRECATE
-D_CRT_NONSTDC_NO_DEPRECATE
-D_CRT_SECURE_NO_DEPRECATE
-D_CRT_SECURE_NO_DEPRECATE_GLOBALS
-D_CRT_SETERRORMODE_BEEP_SLEEP_NO_DEPRECATE
-D_CRT_TIME_FUNCTIONS_NO_DEPRECATE
-D_CRT_VCCLRIT_NO_DEPRECATE
-D_SCL_SECURE_NO_DEPRECATE
)
ENDIF(NOT ITK_ENABLE_VISUAL_STUDIO_DEPRECATED_C_WARNINGS)
ENDIF(NOT MINGW)
ENDIF(NOT CYGWIN)
ENDIF(NOT BORLAND)
ENDIF(WIN32)
#-----------------------------------------------------------------------------
# Test for some required system information.
# INCLUDE (${CMAKE_ROOT}/Modules/CMakeBackwardCompatibilityC.cmake)
#-----------------------------------------------------------------------------
# Compiler specific flags:
IF(CMAKE_COMPILER_IS_GNUCC)
# For all builds, make sure openjpeg is std99 compliant:
# SET(CMAKE_C_FLAGS "-Wall -std=c99 ${CMAKE_C_FLAGS}") # FIXME: this setting prevented us from setting a coverage build.
# Do not use ffast-math for all build, it would produce incorrect results, only set for release:
SET(CMAKE_C_FLAGS_RELEASE "-ffast-math ${CMAKE_C_FLAGS_RELEASE}")
ENDIF(CMAKE_COMPILER_IS_GNUCC)
# Defines the source code for the library
SET(OPENJPEG_SRCS
bio.c
cio.c
dwt.c
event.c
image.c
j2k.c
j2k_lib.c
jp2.c
jpt.c
mct.c
mqc.c
openjpeg.c
pi.c
raw.c
t1.c
t2.c
tcd.c
tgt.c
)
# Pass proper definition to preprocessor to generate shared lib
IF(WIN32)
IF(BUILD_SHARED_LIBS)
ADD_DEFINITIONS(-DOPJ_EXPORTS)
ELSE(BUILD_SHARED_LIBS)
ADD_DEFINITIONS(-DOPJ_STATIC)
ENDIF(BUILD_SHARED_LIBS)
ENDIF(WIN32)
# Create the library
ADD_LIBRARY(openjpeg ${OPENJPEG_SRCS})
SET_TARGET_PROPERTIES(openjpeg PROPERTIES
${OPENJPEG_LIBRARY_PROPERTIES}) ${OPENJPEG_LIBRARY_PROPERTIES})

View File

@@ -527,7 +527,7 @@ static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int numres, DWT1DFN dwt_1
int w = tilec->x1 - tilec->x0; int w = tilec->x1 - tilec->x0;
h.mem = opj_aligned_malloc(dwt_decode_max_resolution(tr, numres) * sizeof(int)); h.mem = (int *)opj_aligned_malloc(dwt_decode_max_resolution(tr, numres) * sizeof(int));
v.mem = h.mem; v.mem = h.mem;
while( --numres) { while( --numres) {
@@ -570,7 +570,7 @@ static void v4dwt_interleave_h(v4dwt_t* restrict w, float* restrict a, int x, in
int count = w->sn; int count = w->sn;
int i, k; int i, k;
for(k = 0; k < 2; ++k){ for(k = 0; k < 2; ++k){
if (count + 3 * x < size && ((int) a & 0x0f) == 0 && ((int) bi & 0x0f) == 0 && (x & 0x0f) == 0) { if (count + 3 * x < size && ((long) a & 0x0f) == 0 && ((long) bi & 0x0f) == 0 && (x & 0x0f) == 0) {
/* Fast code path */ /* Fast code path */
for(i = 0; i < count; ++i){ for(i = 0; i < count; ++i){
int j = i; int j = i;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, Herv<EFBFBD> Drolon, FreeImage Team * Copyright (c) 2005, Hervé Drolon, FreeImage Team
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -26,41 +26,6 @@
#include "opj_includes.h" #include "opj_includes.h"
/* ==========================================================
Utility functions
==========================================================*/
#if !defined(_MSC_VER) && !defined(__MINGW32__)
static char*
i2a(unsigned i, char *a, unsigned r) {
if (i/r > 0) a = i2a(i/r,a,r);
*a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r];
return a+1;
}
/**
Transforms integer i into an ascii string and stores the result in a;
string is encoded in the base indicated by r.
@param i Number to be converted
@param a String result
@param r Base of value; must be in the range 2 - 36
@return Returns a
*/
static char *
_itoa(int i, char *a, int r) {
r = ((r < 2) || (r > 36)) ? 10 : r;
if(i < 0) {
*a = '-';
*i2a(-i, a+1, r) = 0;
}
else *i2a(i, a, r) = 0;
return a;
}
#endif /* !WIN32 */
/* ----------------------------------------------------------------------- */
opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, opj_event_mgr_t *event_mgr, void *context) { opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, opj_event_mgr_t *event_mgr, void *context) {
if(cinfo) { if(cinfo) {
opj_event_mgr_t *previous = cinfo->event_mgr; opj_event_mgr_t *previous = cinfo->event_mgr;

View File

@@ -236,7 +236,7 @@ static void j2k_read_unk(opj_j2k_t *j2k);
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
typedef struct j2k_prog_order{ typedef struct j2k_prog_order{
OPJ_PROG_ORDER enum_prog; OPJ_PROG_ORDER enum_prog;
char str_prog[4]; char str_prog[5];
}j2k_prog_order_t; }j2k_prog_order_t;
j2k_prog_order_t j2k_prog_order_list[] = { j2k_prog_order_t j2k_prog_order_list[] = {

View File

@@ -1,163 +1,163 @@
/* /*
* Copyright (c) 2005, Herv<72> Drolon, FreeImage Team * Copyright (c) 2005, Herv<72> Drolon, FreeImage Team
* Copyright (c) 2007, Callum Lerwick <seg@haxxed.com> * Copyright (c) 2007, Callum Lerwick <seg@haxxed.com>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef __OPJ_MALLOC_H #ifndef __OPJ_MALLOC_H
#define __OPJ_MALLOC_H #define __OPJ_MALLOC_H
/** /**
@file opj_malloc.h @file opj_malloc.h
@brief Internal functions @brief Internal functions
The functions in opj_malloc.h are internal utilities used for memory management. The functions in opj_malloc.h are internal utilities used for memory management.
*/ */
/** @defgroup MISC MISC - Miscellaneous internal functions */ /** @defgroup MISC MISC - Miscellaneous internal functions */
/*@{*/ /*@{*/
/** @name Exported functions */ /** @name Exported functions */
/*@{*/ /*@{*/
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/** /**
Allocate an uninitialized memory block Allocate an uninitialized memory block
@param size Bytes to allocate @param size Bytes to allocate
@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
*/ */
#ifdef ALLOC_PERF_OPT #ifdef ALLOC_PERF_OPT
void * OPJ_CALLCONV opj_malloc(size_t size); void * OPJ_CALLCONV opj_malloc(size_t size);
#else #else
#define opj_malloc(size) malloc(size) #define opj_malloc(size) malloc(size)
#endif #endif
/** /**
Allocate a memory block with elements initialized to 0 Allocate a memory block with elements initialized to 0
@param num Blocks to allocate @param num Blocks to allocate
@param size Bytes per block to allocate @param size Bytes per block to allocate
@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
*/ */
#ifdef ALLOC_PERF_OPT #ifdef ALLOC_PERF_OPT
void * OPJ_CALLCONV opj_calloc(size_t _NumOfElements, size_t _SizeOfElements); void * OPJ_CALLCONV opj_calloc(size_t _NumOfElements, size_t _SizeOfElements);
#else #else
#define opj_calloc(num, size) calloc(num, size) #define opj_calloc(num, size) calloc(num, size)
#endif #endif
/** /**
Allocate memory aligned to a 16 byte boundry Allocate memory aligned to a 16 byte boundry
@param size Bytes to allocate @param size Bytes to allocate
@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available @return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
*/ */
/* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */ /* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */
#ifdef WIN32 #ifdef WIN32
/* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */ /* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */
#ifdef __GNUC__ #ifdef __GNUC__
#include <mm_malloc.h> #include <mm_malloc.h>
#define HAVE_MM_MALLOC #define HAVE_MM_MALLOC
#else /* MSVC, Intel C++ */ #else /* MSVC, Intel C++ */
#include <malloc.h> #include <malloc.h>
#ifdef _mm_malloc #ifdef _mm_malloc
#define HAVE_MM_MALLOC #define HAVE_MM_MALLOC
#endif #endif
#endif #endif
#else /* Not WIN32 */ #else /* Not WIN32 */
#if defined(__sun) #if defined(__sun)
#define HAVE_MEMALIGN #define HAVE_MEMALIGN
/* Linux x86_64 and OSX always align allocations to 16 bytes */ /* Linux x86_64 and OSX always align allocations to 16 bytes */
#elif !defined(__amd64__) && !defined(__APPLE__) #elif !defined(__amd64__) && !defined(__APPLE__)
#define HAVE_MEMALIGN #define HAVE_MEMALIGN
#include <malloc.h> #include <malloc.h>
#endif #endif
#endif #endif
#define opj_aligned_malloc(size) malloc(size) #define opj_aligned_malloc(size) malloc(size)
#define opj_aligned_free(m) free(m) #define opj_aligned_free(m) free(m)
#ifdef HAVE_MM_MALLOC #ifdef HAVE_MM_MALLOC
#undef opj_aligned_malloc #undef opj_aligned_malloc
#define opj_aligned_malloc(size) _mm_malloc(size, 16) #define opj_aligned_malloc(size) _mm_malloc(size, 16)
#undef opj_aligned_free #undef opj_aligned_free
#define opj_aligned_free(m) _mm_free(m) #define opj_aligned_free(m) _mm_free(m)
#endif #endif
#ifdef HAVE_MEMALIGN #ifdef HAVE_MEMALIGN
extern void* memalign(size_t, size_t); extern void* memalign(size_t, size_t);
#undef opj_aligned_malloc #undef opj_aligned_malloc
#define opj_aligned_malloc(size) memalign(16, (size)) #define opj_aligned_malloc(size) memalign(16, (size))
#undef opj_aligned_free #undef opj_aligned_free
#define opj_aligned_free(m) free(m) #define opj_aligned_free(m) free(m)
#endif #endif
#ifdef HAVE_POSIX_MEMALIGN #ifdef HAVE_POSIX_MEMALIGN
#undef opj_aligned_malloc #undef opj_aligned_malloc
extern int posix_memalign(void**, size_t, size_t); extern int posix_memalign(void**, size_t, size_t);
static INLINE void* __attribute__ ((malloc)) opj_aligned_malloc(size_t size){ static INLINE void* __attribute__ ((malloc)) opj_aligned_malloc(size_t size){
void* mem = NULL; void* mem = NULL;
posix_memalign(&mem, 16, size); posix_memalign(&mem, 16, size);
return mem; return mem;
} }
#undef opj_aligned_free #undef opj_aligned_free
#define opj_aligned_free(m) free(m) #define opj_aligned_free(m) free(m)
#endif #endif
#ifdef ALLOC_PERF_OPT #ifdef ALLOC_PERF_OPT
#undef opj_aligned_malloc #undef opj_aligned_malloc
#define opj_aligned_malloc(size) opj_malloc(size) #define opj_aligned_malloc(size) opj_malloc(size)
#undef opj_aligned_free #undef opj_aligned_free
#define opj_aligned_free(m) opj_free(m) #define opj_aligned_free(m) opj_free(m)
#endif #endif
/** /**
Reallocate memory blocks. Reallocate memory blocks.
@param memblock Pointer to previously allocated memory block @param memblock Pointer to previously allocated memory block
@param size New size in bytes @param size New size in bytes
@return Returns a void pointer to the reallocated (and possibly moved) memory block @return Returns a void pointer to the reallocated (and possibly moved) memory block
*/ */
#ifdef ALLOC_PERF_OPT #ifdef ALLOC_PERF_OPT
void * OPJ_CALLCONV opj_realloc(void * _Memory, size_t NewSize); void * OPJ_CALLCONV opj_realloc(void * _Memory, size_t NewSize);
#else #else
#define opj_realloc(m, s) realloc(m, s) #define opj_realloc(m, s) realloc(m, s)
#endif #endif
/** /**
Deallocates or frees a memory block. Deallocates or frees a memory block.
@param memblock Previously allocated memory block to be freed @param memblock Previously allocated memory block to be freed
*/ */
#ifdef ALLOC_PERF_OPT #ifdef ALLOC_PERF_OPT
void OPJ_CALLCONV opj_free(void * _Memory); void OPJ_CALLCONV opj_free(void * _Memory);
#else #else
#define opj_free(m) free(m) #define opj_free(m) free(m)
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC poison malloc calloc realloc free #pragma GCC poison malloc calloc realloc free
#endif #endif
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/*@}*/ /*@}*/
/*@}*/ /*@}*/
#endif /* __OPJ_MALLOC_H */ #endif /* __OPJ_MALLOC_H */

View File

@@ -38,7 +38,7 @@ list(APPEND linux_crash_logger_SOURCE_FILES
${linux_crash_logger_HEADER_FILES} ${linux_crash_logger_HEADER_FILES}
) )
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lrt -lapr-1 -Wl,--as-needed") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
add_executable(linux-crash-logger ${linux_crash_logger_SOURCE_FILES}) add_executable(linux-crash-logger ${linux_crash_logger_SOURCE_FILES})
@@ -47,11 +47,18 @@ target_link_libraries(linux-crash-logger
${LLVFS_LIBRARIES} ${LLVFS_LIBRARIES}
${LLXML_LIBRARIES} ${LLXML_LIBRARIES}
${LLMESSAGE_LIBRARIES} ${LLMESSAGE_LIBRARIES}
${LLUI_LIBRARIES}
${LLVFS_LIBRARIES} ${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}
${UI_LIBRARIES} ${UI_LIBRARIES}
${DB_LIBRARIES} ${DB_LIBRARIES}
${XMLRPCEPI_LIBRARIES}
${CURL_LIBRARIES}
${APR_LIBRARIES}
${APRUTIL_LIBRARIES}
${CRYPTO_LIBRARIES}
rt
) )
add_custom_command( add_custom_command(

View File

@@ -5,16 +5,30 @@ project(llaudio)
include(00-Common) include(00-Common)
include(Audio) include(Audio)
include(LLAudio) include(LLAudio)
include(FMOD) if(FMODEX)
include(FMODEX)
if(FMODEX)
set(FMOD OFF)
endif(FMODEX)
endif(FMODEX)
if(NOT FMODEX)
include(FMOD)
endif(NOT FMODEX)
include(OPENAL) include(OPENAL)
include(LLCommon) include(LLCommon)
include(LLMath) include(LLMath)
include(LLMessage) include(LLMessage)
include(LLVFS) include(LLVFS)
if(FMODEX)
include_directories(${FMODEX_INCLUDE_DIR})
endif(FMODEX)
if(FMOD)
include_directories(${FMOD_INCLUDE_DIR})
endif(FMOD)
include_directories( include_directories(
${LLAUDIO_INCLUDE_DIRS} ${LLAUDIO_INCLUDE_DIRS}
${FMOD_INCLUDE_DIR}
${LLCOMMON_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS}
@@ -46,6 +60,19 @@ set(llaudio_HEADER_FILES
llwindgen.h llwindgen.h
) )
if (FMODEX)
list(APPEND llaudio_SOURCE_FILES
llaudioengine_fmodex.cpp
lllistener_fmodex.cpp
llstreamingaudio_fmodex.cpp
)
list(APPEND llaudio_HEADER_FILES
llaudioengine_fmodex.h
lllistener_fmodex.h
llstreamingaudio_fmodex.h
)
endif (FMODEX)
if (FMOD) if (FMOD)
list(APPEND llaudio_SOURCE_FILES list(APPEND llaudio_SOURCE_FILES
llaudioengine_fmod.cpp llaudioengine_fmod.cpp

View File

@@ -0,0 +1,782 @@
/**
* @file audioengine_FMODEX.cpp
* @brief Implementation of LLAudioEngine class abstracting the audio support as a FMOD 3D implementation
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llstreamingaudio.h"
#include "llstreamingaudio_fmodex.h"
#include "llaudioengine_fmodex.h"
#include "lllistener_fmodex.h"
#include "llerror.h"
#include "llmath.h"
#include "llrand.h"
#include "fmod.hpp"
#include "fmod_errors.h"
#include "lldir.h"
#include "llapr.h"
#include "sound_ids.h"
#if LL_WINDOWS //Some ugly code to make missing fmodex.dll not cause a fatal error.
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#include <DelayImp.h>
#pragma comment(lib, "delayimp.lib")
bool attemptDelayLoad()
{
__try
{
if( FAILED( __HrLoadAllImportsForDll( "fmodex.dll" ) ) )
return false;
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
return false;
}
return true;
}
#endif
FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels);
LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler)
{
mInited = false;
mWindGen = NULL;
mWindDSP = NULL;
mSystem = NULL;
mEnableProfiler = enable_profiler;
}
LLAudioEngine_FMODEX::~LLAudioEngine_FMODEX()
{
}
inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
{
if(result == FMOD_OK)
return false;
llwarns << string << " Error: " << FMOD_ErrorString(result) << llendl;
return true;
}
bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata)
{
#if LL_WINDOWS
if(!attemptDelayLoad())
return false;
#endif
U32 version;
FMOD_RESULT result;
int numdrivers;
FMOD_SPEAKERMODE speakermode;
FMOD_CAPS caps;
char name[256];
LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() initializing FMOD" << LL_ENDL;
result = FMOD::System_Create(&mSystem);
if(Check_FMOD_Error(result, "FMOD::System_Create"))
return false;
//will call LLAudioEngine_FMODEX::allocateListener, which needs a valid mSystem pointer.
LLAudioEngine::init(num_channels, userdata);
result = mSystem->getVersion(&version);
Check_FMOD_Error(result, "FMOD::System::getVersion");
if (version < FMOD_VERSION)
{
LL_WARNS("AppInit") << "Error : You are using the wrong FMOD version (" << version
<< ")! You should be using FMOD " << FMOD_VERSION << LL_ENDL;
}
#if LL_WINDOWS
//Is this block applicable to linux?
{
result = mSystem->getNumDrivers(&numdrivers);
Check_FMOD_Error(result, "FMOD::System::getNumDrivers");
if (numdrivers == 0)
{
result = mSystem->setOutput(FMOD_OUTPUTTYPE_NOSOUND);
Check_FMOD_Error(result, "FMOD::System::setOutput");
}
else
{
result = mSystem->getDriverCaps(0, &caps, 0, &speakermode);
Check_FMOD_Error(result,"FMOD::System::getDriverCaps");
/*
Set the user selected speaker mode.
*/
result = mSystem->setSpeakerMode(speakermode);
Check_FMOD_Error(result, "FMOD::System::setSpeakerMode");
if (caps & FMOD_CAPS_HARDWARE_EMULATED)
{
/*
The user has the 'Acceleration' slider set to off! This is really bad
for latency! You might want to warn the user about this.
*/
result = mSystem->setDSPBufferSize(1024, 10);
Check_FMOD_Error(result, "FMOD::System::setDSPBufferSize");
}
result = mSystem->getDriverInfo(0, name, 256, 0);
Check_FMOD_Error(result, "FMOD::System::getDriverInfo");
if (strstr(name, "SigmaTel"))
{
/*
Sigmatel sound devices crackle for some reason if the format is PCM 16bit.
PCM floating point output seems to solve it.
*/
result = mSystem->setSoftwareFormat(48000, FMOD_SOUND_FORMAT_PCMFLOAT, 0,0, FMOD_DSP_RESAMPLER_LINEAR);
Check_FMOD_Error(result,"FMOD::System::setSoftwareFormat");
}
}
}
#endif //LL_WINDOWS
// In this case, all sounds, PLUS wind and stream will be software.
result = mSystem->setSoftwareChannels(num_channels+2);
Check_FMOD_Error(result,"FMOD::System::setSoftwareChannels");
U32 fmod_flags = FMOD_INIT_NORMAL;
if(mEnableProfiler)
fmod_flags |= FMOD_INIT_ENABLE_PROFILE;
#if LL_LINUX
// If we don't set an output method, Linux FMOD always
// decides on OSS and fails otherwise. So we'll manually
// try ESD, then OSS, then ALSA.
// Why this order? See SL-13250, but in short, OSS emulated
// on top of ALSA is ironically more reliable than raw ALSA.
// Ack, and ESD has more reliable failure modes - but has worse
// latency - than all of them, so wins for now.
bool audio_ok = false;
if (!audio_ok)
{
if (NULL == getenv("LL_BAD_FMODEX_ESD")) /*Flawfinder: ignore*/
{
LL_DEBUGS("AppInit") << "Trying ESD audio output..." << LL_ENDL;
if(mSystem->SetOutput(FMOD_OUTPUTTYPE_ESD) == FMOD_OK &&
(result = mSystem->init(num_channels, fmod_flags, 0)) == FMOD_OK)
{
LL_DEBUGS("AppInit") << "ESD audio output initialized OKAY" << LL_ENDL;
audio_ok = true;
}
else
{
Check_FMOD_Error(result, "ESD audio output FAILED to initialize");
}
}
else
{
LL_DEBUGS("AppInit") << "ESD audio output SKIPPED" << LL_ENDL;
}
}
if (!audio_ok)
{
if (NULL == getenv("LL_BAD_FMODEX_OSS")) /*Flawfinder: ignore*/
{
LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL;
if(mSystem->SetOutput(FMOD_OUTPUTTYPE_OSS) == FMOD_OK &&
(result = mSystem->init(num_channels, fmod_flags, 0)) == FMOD_OK)
{
LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL;
audio_ok = true;
}
else
{
Check_FMOD_Error(result, "OSS audio output FAILED to initialize" << LL_ENDL;
}
}
else
{
LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
}
}
if (!audio_ok)
{
if (NULL == getenv("LL_BAD_FMODEX_ALSA")) /*Flawfinder: ignore*/
{
LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL;
if(mSystem->SetOutput(FMOD_OUTPUTTYPE_ALSA) &&
(result = mSystem->init(num_channels, fmod_flags, 0)) == FMOD_OK)
{
LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL;
audio_ok = true;
}
else
{
Check_FMOD_Error(result, "ALSA audio output FAILED to initialize");
}
} else
{
LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
}
}
if (!audio_ok)
{
LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL;
return false;
}
// On Linux, FMOD causes a SIGPIPE for some netstream error
// conditions (an FMOD bug); ignore SIGPIPE so it doesn't crash us.
// NOW FIXED in FMOD 3.x since 2006-10-01.
//signal(SIGPIPE, SIG_IGN);
// We're interested in logging which output method we
// ended up with, for QA purposes.
FMOD_OUTPUTTYPE output_type;
mSystem->getOutput(output_type);
switch (output_type)
{
case FSOUND_OUTPUT_NOSOUND:
LL_DEBUGS("AppInit") << "Audio output: NoSound" << LL_ENDL; break;
case FSOUND_OUTPUT_OSS:
LL_DEBUGS("AppInit") << "Audio output: OSS" << LL_ENDL; break;
case FSOUND_OUTPUT_ESD:
LL_DEBUGS("AppInit") << "Audio output: ESD" << LL_ENDL; break;
case FSOUND_OUTPUT_ALSA:
LL_DEBUGS("AppInit") << "Audio output: ALSA" << LL_ENDL; break;
default:
LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break;
};
#else // LL_LINUX
// initialize the FMOD engine
result = mSystem->init( num_channels + 2, fmod_flags, 0);
if (result == FMOD_ERR_OUTPUT_CREATEBUFFER)
{
/*
Ok, the speaker mode selected isn't supported by this soundcard. Switch it
back to stereo...
*/
result = mSystem->setSpeakerMode(FMOD_SPEAKERMODE_STEREO);
Check_FMOD_Error(result,"Error falling back to stereo mode");
/*
... and re-init.
*/
result = mSystem->init(100, FMOD_INIT_NORMAL, 0);
}
if(Check_FMOD_Error(result, "Error initializing FMOD"))
return false;
#endif
// set up our favourite FMOD-native streaming audio implementation if none has already been added
if (!getStreamingAudioImpl()) // no existing implementation added
setStreamingAudioImpl(new LLStreamingAudio_FMODEX(mSystem));
LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() FMOD initialized correctly" << LL_ENDL;
mInited = true;
return true;
}
std::string LLAudioEngine_FMODEX::getDriverName(bool verbose)
{
llassert_always(mSystem);
if (verbose)
{
U32 version;
if(!Check_FMOD_Error(mSystem->getVersion(&version), "FMOD::System::getVersion"))
{
return llformat("FMOD version %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF);
}
}
return "FMOD";
}
void LLAudioEngine_FMODEX::allocateListener(void)
{
mListenerp = (LLListener *) new LLListener_FMODEX(mSystem);
if (!mListenerp)
{
llwarns << "Listener creation failed" << llendl;
}
}
void LLAudioEngine_FMODEX::shutdown()
{
stopInternetStream();
LLAudioEngine::shutdown();
llinfos << "LLAudioEngine_FMODEX::shutdown() closing FMOD" << llendl;
mSystem->close();
mSystem->release();
llinfos << "LLAudioEngine_FMODEX::shutdown() done closing FMOD" << llendl;
delete mListenerp;
mListenerp = NULL;
}
LLAudioBuffer * LLAudioEngine_FMODEX::createBuffer()
{
return new LLAudioBufferFMODEX(mSystem);
}
LLAudioChannel * LLAudioEngine_FMODEX::createChannel()
{
return new LLAudioChannelFMODEX(mSystem);
}
bool LLAudioEngine_FMODEX::initWind()
{
mNextWindUpdate = 0.0;
if (!mWindDSP)
{
FMOD_DSP_DESCRIPTION dspdesc;
memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION)); //Set everything to zero
strncpy(dspdesc.name,"Wind Unit", sizeof(dspdesc.name)); //Set name to "Wind Unit"
dspdesc.read = &windCallback; //Assign callback.
if(Check_FMOD_Error(mSystem->createDSP(&dspdesc, &mWindDSP), "FMOD::createDSP"))
return false;
if(mWindGen)
delete mWindGen;
float frequency = 44100;
mWindDSP->getDefaults(&frequency,0,0,0);
mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency);
mWindDSP->setUserData((void*)mWindGen);
}
if (mWindDSP)
{
mSystem->playDSP(FMOD_CHANNEL_FREE, mWindDSP, false, 0);
return true;
}
return false;
}
void LLAudioEngine_FMODEX::cleanupWind()
{
if (mWindDSP)
{
mWindDSP->remove();
mWindDSP->release();
mWindDSP = NULL;
}
delete mWindGen;
mWindGen = NULL;
}
//-----------------------------------------------------------------------
void LLAudioEngine_FMODEX::updateWind(LLVector3 wind_vec, F32 camera_height_above_water)
{
LLVector3 wind_pos;
F64 pitch;
F64 center_freq;
if (!mEnableWind)
{
return;
}
if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL))
{
// wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up)
// need to convert this to the conventional orientation DS3D and OpenAL use
// where +X = right, +Y = up, +Z = backwards
wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]);
// cerr << "Wind update" << endl;
pitch = 1.0 + mapWindVecToPitch(wind_vec);
center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0));
mWindGen->mTargetFreq = (F32)center_freq;
mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
}
}
//-----------------------------------------------------------------------
void LLAudioEngine_FMODEX::setInternalGain(F32 gain)
{
if (!mInited)
{
return;
}
gain = llclamp( gain, 0.0f, 1.0f );
FMOD::ChannelGroup *master_group;
mSystem->getMasterChannelGroup(&master_group);
master_group->setVolume(gain);
LLStreamingAudioInterface *saimpl = getStreamingAudioImpl();
if ( saimpl )
{
// fmod likes its streaming audio channel gain re-asserted after
// master volume change.
saimpl->setGain(saimpl->getGain());
}
}
//
// LLAudioChannelFMODEX implementation
//
LLAudioChannelFMODEX::LLAudioChannelFMODEX(FMOD::System *system) : LLAudioChannel(), mSystemp(system), mChannelp(NULL), mLastSamplePos(0)
{
}
LLAudioChannelFMODEX::~LLAudioChannelFMODEX()
{
cleanup();
}
bool LLAudioChannelFMODEX::updateBuffer()
{
if (LLAudioChannel::updateBuffer())
{
// Base class update returned true, which means that we need to actually
// set up the channel for a different buffer.
LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentSourcep->getCurrentBuffer();
// Grab the FMOD sample associated with the buffer
FMOD::Sound *soundp = bufferp->getSound();
if (!soundp)
{
// This is bad, there should ALWAYS be a sound associated with a legit
// buffer.
llerrs << "No FMOD sound!" << llendl;
return false;
}
// Actually play the sound. Start it off paused so we can do all the necessary
// setup.
if(!mChannelp)
{
FMOD_RESULT result = getSystem()->playSound(FMOD_CHANNEL_FREE, soundp, true, &mChannelp);
Check_FMOD_Error(result, "FMOD::System::playSound");
}
//llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl;
}
// If we have a source for the channel, we need to update its gain.
if (mCurrentSourcep)
{
// SJB: warnings can spam and hurt framerate, disabling
FMOD_RESULT result;
result = mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain());
//Check_FMOD_Error(result, "FMOD::Channel::setVolume");
result = mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF);
/*if(Check_FMOD_Error(result, "FMOD::Channel::setMode"))
{
S32 index;
mChannelp->getIndex(&index);
llwarns << "Channel " << index << "Source ID: " << mCurrentSourcep->getID()
<< " at " << mCurrentSourcep->getPositionGlobal() << llendl;
}*/
}
return true;
}
void LLAudioChannelFMODEX::update3DPosition()
{
if (!mChannelp)
{
// We're not actually a live channel (i.e., we're not playing back anything)
return;
}
LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentBufferp;
if (!bufferp)
{
// We don't have a buffer associated with us (should really have been picked up
// by the above if.
return;
}
if (mCurrentSourcep->isAmbient())
{
// Ambient sound, don't need to do any positional updates.
set3DMode(false);
}
else
{
// Localized sound. Update the position and velocity of the sound.
set3DMode(true);
LLVector3 float_pos;
float_pos.setVec(mCurrentSourcep->getPositionGlobal());
FMOD_RESULT result = mChannelp->set3DAttributes((FMOD_VECTOR*)float_pos.mV, (FMOD_VECTOR*)mCurrentSourcep->getVelocity().mV);
Check_FMOD_Error(result, "FMOD::Channel::set3DAttributes");
}
}
void LLAudioChannelFMODEX::updateLoop()
{
if (!mChannelp)
{
// May want to clear up the loop/sample counters.
return;
}
//
// Hack: We keep track of whether we looped or not by seeing when the
// sample position looks like it's going backwards. Not reliable; may
// yield false negatives.
//
U32 cur_pos;
mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES);
if (cur_pos < (U32)mLastSamplePos)
{
mLoopedThisFrame = true;
}
mLastSamplePos = cur_pos;
}
void LLAudioChannelFMODEX::cleanup()
{
if (!mChannelp)
{
//llinfos << "Aborting cleanup with no channel handle." << llendl;
return;
}
//llinfos << "Cleaning up channel: " << mChannelID << llendl;
Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop");
mCurrentBufferp = NULL;
mChannelp = NULL;
}
void LLAudioChannelFMODEX::play()
{
if (!mChannelp)
{
llwarns << "Playing without a channel handle, aborting" << llendl;
return;
}
Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::pause");
getSource()->setPlayedOnce(true);
}
void LLAudioChannelFMODEX::playSynced(LLAudioChannel *channelp)
{
LLAudioChannelFMODEX *fmod_channelp = (LLAudioChannelFMODEX*)channelp;
if (!(fmod_channelp->mChannelp && mChannelp))
{
// Don't have channels allocated to both the master and the slave
return;
}
U32 cur_pos;
if(Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position"))
return;
cur_pos %= mCurrentBufferp->getLength();
// Try to match the position of our sync master
Check_FMOD_Error(mChannelp->setPosition(cur_pos,FMOD_TIMEUNIT_PCMBYTES),"Unable to set current position");
// Start us playing
play();
}
bool LLAudioChannelFMODEX::isPlaying()
{
if (!mChannelp)
{
return false;
}
bool paused, playing;
mChannelp->getPaused(&paused);
mChannelp->isPlaying(&playing);
return !paused && playing;
}
//
// LLAudioChannelFMODEX implementation
//
LLAudioBufferFMODEX::LLAudioBufferFMODEX(FMOD::System *system) : mSystemp(system), mSoundp(NULL)
{
}
LLAudioBufferFMODEX::~LLAudioBufferFMODEX()
{
if(mSoundp)
{
mSoundp->release();
mSoundp = NULL;
}
}
bool LLAudioBufferFMODEX::loadWAV(const std::string& filename)
{
// Try to open a wav file from disk. This will eventually go away, as we don't
// really want to block doing this.
if (filename.empty())
{
// invalid filename, abort.
return false;
}
if (!LLAPRFile::isExist(filename, LL_APR_RPB))
{
// File not found, abort.
return false;
}
if (mSoundp)
{
// If there's already something loaded in this buffer, clean it up.
mSoundp->release();
mSoundp = NULL;
}
FMOD_MODE base_mode = FMOD_LOOP_NORMAL | FMOD_SOFTWARE;
FMOD_CREATESOUNDEXINFO exinfo;
memset(&exinfo,0,sizeof(exinfo));
exinfo.cbsize = sizeof(exinfo);
exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV; //Hint to speed up loading.
// Load up the wav file into an fmod sample
#if LL_WINDOWS
FMOD_RESULT result = getSystem()->createSound((const char*)utf8str_to_utf16str(filename).c_str(), base_mode | FMOD_UNICODE, &exinfo, &mSoundp);
#else
FMOD_RESULT result = getSystem()->createSound(filename.c_str(), base_mode, &exinfo, &mSoundp);
#endif
if (result != FMOD_OK)
{
// We failed to load the file for some reason.
llwarns << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << llendl;
//
// If we EVER want to load wav files provided by end users, we need
// to rethink this!
//
// file is probably corrupt - remove it.
LLFile::remove(filename);
return false;
}
// Everything went well, return true
return true;
}
U32 LLAudioBufferFMODEX::getLength()
{
if (!mSoundp)
{
return 0;
}
U32 length;
mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES);
return length;
}
void LLAudioChannelFMODEX::set3DMode(bool use3d)
{
FMOD_MODE current_mode;
if(mChannelp->getMode(&current_mode) != FMOD_OK)
return;
FMOD_MODE new_mode = current_mode;
new_mode &= ~(use3d ? FMOD_2D : FMOD_3D);
new_mode |= use3d ? FMOD_3D : FMOD_2D;
if(current_mode != new_mode)
{
mChannelp->setMode(new_mode);
}
}
FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *originalbuffer, float *newbuffer, unsigned int length, int inchannels, int outchannels)
{
// originalbuffer = fmod's original mixbuffer.
// newbuffer = the buffer passed from the previous DSP unit.
// length = length in samples at this mix time.
// userdata = user parameter passed through in FSOUND_DSP_Create.
LLWindGen<LLAudioEngine_FMODEX::MIXBUFFERFORMAT> *windgen;
FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance;
thisdsp->getUserData((void **)&windgen);
S32 channels, configwidth, configheight;
thisdsp->getInfo(0, 0, &channels, &configwidth, &configheight);
windgen->windGenerate((LLAudioEngine_FMODEX::MIXBUFFERFORMAT *)newbuffer, length);
return FMOD_OK;
}

View File

@@ -0,0 +1,131 @@
/**
* @file audioengine_FMODEX.h
* @brief Definition of LLAudioEngine class abstracting the audio
* support as a FMOD 3D implementation
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_AUDIOENGINE_FMODEX_H
#define LL_AUDIOENGINE_FMODEX_H
#include "llaudioengine.h"
#include "lllistener_fmod.h"
#include "llwindgen.h"
//Stubs
class LLAudioStreamManagerFMODEX;
namespace FMOD
{
class System;
class Channel;
class Sound;
class DSP;
}
//Interfaces
class LLAudioEngine_FMODEX : public LLAudioEngine
{
public:
LLAudioEngine_FMODEX(bool enable_profiler);
virtual ~LLAudioEngine_FMODEX();
// initialization/startup/shutdown
virtual bool init(const S32 num_channels, void *user_data);
virtual std::string getDriverName(bool verbose);
virtual void allocateListener();
virtual void shutdown();
/*virtual*/ bool initWind();
/*virtual*/ void cleanupWind();
/*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water);
typedef F32 MIXBUFFERFORMAT;
FMOD::System *getSystem() const {return mSystem;}
protected:
/*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to.
/*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel.
/*virtual*/ void setInternalGain(F32 gain);
bool mInited;
LLWindGen<MIXBUFFERFORMAT> *mWindGen;
FMOD::DSP *mWindDSP;
FMOD::System *mSystem;
bool mEnableProfiler;
};
class LLAudioChannelFMODEX : public LLAudioChannel
{
public:
LLAudioChannelFMODEX(FMOD::System *audioengine);
virtual ~LLAudioChannelFMODEX();
protected:
/*virtual*/ void play();
/*virtual*/ void playSynced(LLAudioChannel *channelp);
/*virtual*/ void cleanup();
/*virtual*/ bool isPlaying();
/*virtual*/ bool updateBuffer();
/*virtual*/ void update3DPosition();
/*virtual*/ void updateLoop();
void set3DMode(bool use3d);
protected:
FMOD::System *getSystem() const {return mSystemp;}
FMOD::System *mSystemp;
FMOD::Channel *mChannelp;
S32 mLastSamplePos;
};
class LLAudioBufferFMODEX : public LLAudioBuffer
{
public:
LLAudioBufferFMODEX(FMOD::System *audioengine);
virtual ~LLAudioBufferFMODEX();
/*virtual*/ bool loadWAV(const std::string& filename);
/*virtual*/ U32 getLength();
friend class LLAudioChannelFMODEX;
protected:
FMOD::System *getSystem() const {return mSystemp;}
FMOD::System *mSystemp;
FMOD::Sound *getSound() const{ return mSoundp; }
FMOD::Sound *mSoundp;
};
#endif // LL_AUDIOENGINE_FMODEX_H

View File

@@ -0,0 +1,132 @@
/**
* @file listener_fmod.cpp
* @brief implementation of LISTENER class abstracting the audio
* support as a FMOD 3D implementation (windows only)
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llaudioengine.h"
#include "lllistener_fmodex.h"
#include "fmod.hpp"
//-----------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------
LLListener_FMODEX::LLListener_FMODEX(FMOD::System *system)
{
mSystem = system;
init();
}
//-----------------------------------------------------------------------
LLListener_FMODEX::~LLListener_FMODEX()
{
}
//-----------------------------------------------------------------------
void LLListener_FMODEX::init(void)
{
// do inherited
LLListener::init();
mDopplerFactor = 1.0f;
mRolloffFactor = 1.0f;
}
//-----------------------------------------------------------------------
void LLListener_FMODEX::translate(LLVector3 offset)
{
LLListener::translate(offset);
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
}
//-----------------------------------------------------------------------
void LLListener_FMODEX::setPosition(LLVector3 pos)
{
LLListener::setPosition(pos);
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
}
//-----------------------------------------------------------------------
void LLListener_FMODEX::setVelocity(LLVector3 vel)
{
LLListener::setVelocity(vel);
mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
}
//-----------------------------------------------------------------------
void LLListener_FMODEX::orient(LLVector3 up, LLVector3 at)
{
LLListener::orient(up, at);
// Welcome to the transition between right and left
// (coordinate systems, that is)
// Leaving the at vector alone results in a L/R reversal
// since DX is left-handed and we (LL, OpenGL, OpenAL) are right-handed
at = -at;
mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV);
}
//-----------------------------------------------------------------------
void LLListener_FMODEX::commitDeferredChanges()
{
mSystem->update();
}
void LLListener_FMODEX::setRolloffFactor(F32 factor)
{
mRolloffFactor = factor;
mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
}
F32 LLListener_FMODEX::getRolloffFactor()
{
return mRolloffFactor;
}
void LLListener_FMODEX::setDopplerFactor(F32 factor)
{
mDopplerFactor = factor;
mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
}
F32 LLListener_FMODEX::getDopplerFactor()
{
return mDopplerFactor;
}

View File

@@ -0,0 +1,71 @@
/**
* @file listener_fmod.h
* @brief Description of LISTENER class abstracting the audio support
* as an FMOD 3D implementation (windows and Linux)
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LISTENER_FMODEX_H
#define LL_LISTENER_FMODEX_H
#include "lllistener.h"
//Stubs
namespace FMOD
{
class System;
}
//Interfaces
class LLListener_FMODEX : public LLListener
{
public:
LLListener_FMODEX(FMOD::System *system);
virtual ~LLListener_FMODEX();
virtual void init();
virtual void translate(LLVector3 offset);
virtual void setPosition(LLVector3 pos);
virtual void setVelocity(LLVector3 vel);
virtual void orient(LLVector3 up, LLVector3 at);
virtual void commitDeferredChanges();
virtual void setDopplerFactor(F32 factor);
virtual F32 getDopplerFactor();
virtual void setRolloffFactor(F32 factor);
virtual F32 getRolloffFactor();
protected:
FMOD::System *mSystem;
F32 mDopplerFactor;
F32 mRolloffFactor;
};
#endif

View File

@@ -36,6 +36,8 @@
#include "stdtypes.h" // from llcommon #include "stdtypes.h" // from llcommon
class LLSD;
// Entirely abstract. Based exactly on the historic API. // Entirely abstract. Based exactly on the historic API.
class LLStreamingAudioInterface class LLStreamingAudioInterface
{ {
@@ -51,6 +53,11 @@ class LLStreamingAudioInterface
virtual void setGain(F32 vol) = 0; virtual void setGain(F32 vol) = 0;
virtual F32 getGain() = 0; virtual F32 getGain() = 0;
virtual std::string getURL() = 0; virtual std::string getURL() = 0;
virtual bool supportsMetaData() = 0;
virtual const LLSD *getMetaData() = 0;
virtual bool supportsWaveData() = 0;
virtual bool getWaveData(float* arr, S32 count, S32 stride = 1) = 0;
}; };
#endif // LL_STREAMINGAUDIO_H #endif // LL_STREAMINGAUDIO_H

View File

@@ -51,6 +51,8 @@ public:
const std::string& getURL() { return mInternetStreamURL; } const std::string& getURL() { return mInternetStreamURL; }
int getOpenState(); int getOpenState();
FSOUND_STREAM* getStream() { return mInternetStream; }
protected: protected:
FSOUND_STREAM* mInternetStream; FSOUND_STREAM* mInternetStream;
bool mReady; bool mReady;
@@ -66,7 +68,8 @@ protected:
LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() : LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() :
mCurrentInternetStreamp(NULL), mCurrentInternetStreamp(NULL),
mFMODInternetStreamChannel(-1), mFMODInternetStreamChannel(-1),
mGain(1.0f) mGain(1.0f),
mMetaData(NULL)
{ {
// Number of milliseconds of audio to buffer for the audio card. // Number of milliseconds of audio to buffer for the audio card.
// Must be larger than the usual Second Life frame stutter time. // Must be larger than the usual Second Life frame stutter time.
@@ -87,6 +90,17 @@ LLStreamingAudio_FMOD::~LLStreamingAudio_FMOD()
// nothing interesting/safe to do. // nothing interesting/safe to do.
} }
signed char F_CALLBACKAPI MetaDataCallback(char *name, char *value, void *userdata)
{
std::string szName(name);
if(szName == "TITLE" || szName=="TIT2" || szName=="Title")
(*(LLSD*)userdata)["TITLE"] = value;
if(szName == "ARTIST" || szName=="TPE1" || szName =="WM/AlbumTitle")
(*(LLSD*)userdata)["ARTIST"] = value;
else
(*(LLSD*)userdata)[std::string(name)] = value;
return true;
}
void LLStreamingAudio_FMOD::start(const std::string& url) void LLStreamingAudio_FMOD::start(const std::string& url)
{ {
@@ -104,6 +118,10 @@ void LLStreamingAudio_FMOD::start(const std::string& url)
llinfos << "Starting internet stream: " << url << llendl; llinfos << "Starting internet stream: " << url << llendl;
mCurrentInternetStreamp = new LLAudioStreamManagerFMOD(url); mCurrentInternetStreamp = new LLAudioStreamManagerFMOD(url);
mURL = url; mURL = url;
if(mCurrentInternetStreamp->getStream())
{
mMetaData = new LLSD;
}
} }
else else
{ {
@@ -154,6 +172,10 @@ void LLStreamingAudio_FMOD::update()
// Reset volume to previously set volume // Reset volume to previously set volume
setGain(getGain()); setGain(getGain());
FSOUND_SetPaused(mFMODInternetStreamChannel, false); FSOUND_SetPaused(mFMODInternetStreamChannel, false);
if(mCurrentInternetStreamp->getStream() && mMetaData)
{
FSOUND_Stream_Net_SetMetadataCallback(mCurrentInternetStreamp->getStream(),&MetaDataCallback, mMetaData);
}
} }
} }
} }
@@ -184,11 +206,17 @@ void LLStreamingAudio_FMOD::update()
// buffering // buffering
break; break;
} }
} }
void LLStreamingAudio_FMOD::stop() void LLStreamingAudio_FMOD::stop()
{ {
if(mMetaData)
{
if(mCurrentInternetStreamp && mCurrentInternetStreamp->getStream())
FSOUND_Stream_Net_SetMetadataCallback(mCurrentInternetStreamp->getStream(),NULL,NULL);
delete mMetaData;
mMetaData = NULL;
}
if (mFMODInternetStreamChannel != -1) if (mFMODInternetStreamChannel != -1)
{ {
FSOUND_SetPaused(mFMODInternetStreamChannel, true); FSOUND_SetPaused(mFMODInternetStreamChannel, true);

View File

@@ -55,6 +55,10 @@ class LLStreamingAudio_FMOD : public LLStreamingAudioInterface
/*virtual*/ F32 getGain(); /*virtual*/ F32 getGain();
/*virtual*/ std::string getURL(); /*virtual*/ std::string getURL();
/*virtual*/ bool supportsMetaData(){return true;}
/*virtual*/ const LLSD *getMetaData(){return mMetaData;} //return NULL if not playing.
/*virtual*/ bool supportsWaveData(){return false;}
/*virtual*/ bool getWaveData(float* arr, S32 count, S32 stride = 1){return false;}
private: private:
LLAudioStreamManagerFMOD *mCurrentInternetStreamp; LLAudioStreamManagerFMOD *mCurrentInternetStreamp;
int mFMODInternetStreamChannel; int mFMODInternetStreamChannel;
@@ -62,6 +66,8 @@ private:
std::string mURL; std::string mURL;
F32 mGain; F32 mGain;
LLSD *mMetaData;
}; };

View File

@@ -0,0 +1,448 @@
/**
* @file streamingaudio_fmod.cpp
* @brief LLStreamingAudio_FMODEX implementation
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llmath.h"
#include "fmod.hpp"
#include "fmod_errors.h"
#include "llstreamingaudio_fmodex.h"
class LLAudioStreamManagerFMODEX
{
public:
LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url);
FMOD::Channel* startStream();
bool stopStream(); // Returns true if the stream was successfully stopped.
bool ready();
const std::string& getURL() { return mInternetStreamURL; }
FMOD_OPENSTATE getOpenState();
protected:
FMOD::System* mSystem;
FMOD::Channel* mStreamChannel;
FMOD::Sound* mInternetStream;
bool mReady;
std::string mInternetStreamURL;
};
//---------------------------------------------------------------------------
// Internet Streaming
//---------------------------------------------------------------------------
LLStreamingAudio_FMODEX::LLStreamingAudio_FMODEX(FMOD::System *system) :
mSystem(system),
mCurrentInternetStreamp(NULL),
mFMODInternetStreamChannelp(NULL),
mGain(1.0f),
mMetaData(NULL)
{
// Number of milliseconds of audio to buffer for the audio card.
// Must be larger than the usual Second Life frame stutter time.
mSystem->setStreamBufferSize(200, FMOD_TIMEUNIT_MS);
// Here's where we set the size of the network buffer and some buffering
// parameters. In this case we want a network buffer of 16k, we want it
// to prebuffer 40% of that when we first connect, and we want it
// to rebuffer 80% of that whenever we encounter a buffer underrun.
// Leave the net buffer properties at the default.
//FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80);
}
LLStreamingAudio_FMODEX::~LLStreamingAudio_FMODEX()
{
// nothing interesting/safe to do.
}
void LLStreamingAudio_FMODEX::start(const std::string& url)
{
//if (!mInited)
//{
// llwarns << "startInternetStream before audio initialized" << llendl;
// return;
//}
// "stop" stream but don't clear url, etc. in case url == mInternetStreamURL
stop();
if (!url.empty())
{
llinfos << "Starting internet stream: " << url << llendl;
mCurrentInternetStreamp = new LLAudioStreamManagerFMODEX(mSystem,url);
mURL = url;
mMetaData = new LLSD;
}
else
{
llinfos << "Set internet stream to null" << llendl;
mURL.clear();
}
}
void LLStreamingAudio_FMODEX::update()
{
// Kill dead internet streams, if possible
std::list<LLAudioStreamManagerFMODEX *>::iterator iter;
for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
{
LLAudioStreamManagerFMODEX *streamp = *iter;
if (streamp->stopStream())
{
llinfos << "Closed dead stream" << llendl;
delete streamp;
mDeadStreams.erase(iter++);
}
else
{
iter++;
}
}
// Don't do anything if there are no streams playing
if (!mCurrentInternetStreamp)
{
return;
}
FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState();
if (open_state == FMOD_OPENSTATE_READY)
{
// Stream is live
// start the stream if it's ready
if (!mFMODInternetStreamChannelp &&
(mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream()))
{
// Reset volume to previously set volume
setGain(getGain());
mFMODInternetStreamChannelp->setPaused(false);
}
}
else if(open_state == FMOD_OPENSTATE_ERROR)
{
stop();
return;
}
if(mFMODInternetStreamChannelp)
{
if(!mMetaData)
mMetaData = new LLSD;
FMOD::Sound *sound = NULL;
if(mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound)
{
FMOD_TAG tag;
S32 tagcount, dirtytagcount;
if(sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount)
{
mMetaData->clear();
for(S32 i = 0; i < tagcount; ++i)
{
if(sound->getTag(NULL, i, &tag)!=FMOD_OK)
continue;
std::string name = tag.name;
switch(tag.type) //Crappy tag translate table.
{
case(FMOD_TAGTYPE_ID3V2):
if(name == "TIT2") name = "TITLE";
else if(name == "TPE1") name = "ARTIST";
break;
case(FMOD_TAGTYPE_ASF):
if(name == "Title") name = "TITLE";
else if(name == "WM/AlbumArtist") name = "ARTIST";
break;
default:
break;
}
switch(tag.datatype)
{
case(FMOD_TAGDATATYPE_INT):
(*mMetaData)[name]=*(LLSD::Integer*)(tag.data);
llinfos << tag.name << ": " << *(int*)(tag.data) << llendl;
break;
case(FMOD_TAGDATATYPE_FLOAT):
(*mMetaData)[name]=*(LLSD::Float*)(tag.data);
llinfos << tag.name << ": " << *(float*)(tag.data) << llendl;
break;
case(FMOD_TAGDATATYPE_STRING):
{
std::string out = rawstr_to_utf8(std::string((char*)tag.data,tag.datalen));
(*mMetaData)[name]=out;
llinfos << tag.name << ": " << out << llendl;
}
break;
case(FMOD_TAGDATATYPE_STRING_UTF16):
{
std::string out((char*)tag.data,tag.datalen);
(*mMetaData)[std::string(tag.name)]=out;
llinfos << tag.name << ": " << out << llendl;
}
break;
case(FMOD_TAGDATATYPE_STRING_UTF16BE):
{
std::string out((char*)tag.data,tag.datalen);
U16* buf = (U16*)out.c_str();
for(U32 j = 0; j < out.size()/2; ++j)
(((buf[j] & 0xff)<<8) | ((buf[j] & 0xff00)>>8));
(*mMetaData)[std::string(tag.name)]=out;
llinfos << tag.name << ": " << out << llendl;
}
default:
break;
}
}
}
}
}
}
void LLStreamingAudio_FMODEX::stop()
{
if(mMetaData)
{
delete mMetaData;
mMetaData = NULL;
}
if (mFMODInternetStreamChannelp)
{
mFMODInternetStreamChannelp->setPaused(true);
mFMODInternetStreamChannelp->setPriority(0);
mFMODInternetStreamChannelp = NULL;
}
if (mCurrentInternetStreamp)
{
llinfos << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << llendl;
if (mCurrentInternetStreamp->stopStream())
{
delete mCurrentInternetStreamp;
}
else
{
llwarns << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << llendl;
mDeadStreams.push_back(mCurrentInternetStreamp);
}
mCurrentInternetStreamp = NULL;
//mURL.clear();
}
}
void LLStreamingAudio_FMODEX::pause(int pauseopt)
{
if (pauseopt < 0)
{
pauseopt = mCurrentInternetStreamp ? 1 : 0;
}
if (pauseopt)
{
if (mCurrentInternetStreamp)
{
stop();
}
}
else
{
start(getURL());
}
}
// A stream is "playing" if it has been requested to start. That
// doesn't necessarily mean audio is coming out of the speakers.
int LLStreamingAudio_FMODEX::isPlaying()
{
if (mCurrentInternetStreamp)
{
return 1; // Active and playing
}
else if (!mURL.empty())
{
return 2; // "Paused"
}
else
{
return 0;
}
}
F32 LLStreamingAudio_FMODEX::getGain()
{
return mGain;
}
std::string LLStreamingAudio_FMODEX::getURL()
{
return mURL;
}
void LLStreamingAudio_FMODEX::setGain(F32 vol)
{
mGain = vol;
if (mFMODInternetStreamChannelp)
{
vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here?
mFMODInternetStreamChannelp->setVolume(vol);
}
}
/*virtual*/ bool LLStreamingAudio_FMODEX::getWaveData(float* arr, S32 count, S32 stride/*=1*/)
{
if(!mFMODInternetStreamChannelp || !mCurrentInternetStreamp)
return false;
static std::vector<float> local_array(count); //Have to have an extra buffer to mix channels. Bleh.
if(count > (S32)local_array.size()) //Expand the array if needed. Try to minimize allocation calls, so don't ever shrink.
local_array.resize(count);
if( mFMODInternetStreamChannelp->getWaveData(&local_array[0],count,0) == FMOD_OK &&
mFMODInternetStreamChannelp->getWaveData(&arr[0],count,1) == FMOD_OK )
{
for(S32 i = count-1;i>=0;i-=stride)
{
arr[i] += local_array[i];
arr[i] *= .5f;
}
return true;
}
return false;
}
///////////////////////////////////////////////////////
// manager of possibly-multiple internet audio streams
LLAudioStreamManagerFMODEX::LLAudioStreamManagerFMODEX(FMOD::System *system, const std::string& url) :
mSystem(system),
mStreamChannel(NULL),
mInternetStream(NULL),
mReady(false)
{
mInternetStreamURL = url;
FMOD_CREATESOUNDEXINFO exinfo;
memset(&exinfo,0,sizeof(exinfo));
exinfo.cbsize = sizeof(exinfo);
exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_MPEG; //Hint to speed up loading.
FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING, &exinfo, &mInternetStream);
if (result!= FMOD_OK)
{
llwarns << "Couldn't open fmod stream, error "
<< FMOD_ErrorString(result)
<< llendl;
mReady = false;
return;
}
mReady = true;
}
FMOD::Channel *LLAudioStreamManagerFMODEX::startStream()
{
// We need a live and opened stream before we try and play it.
if (!mInternetStream || getOpenState() != FMOD_OPENSTATE_READY)
{
llwarns << "No internet stream to start playing!" << llendl;
return NULL;
}
if(mStreamChannel)
return mStreamChannel; //Already have a channel for this stream.
mSystem->playSound(FMOD_CHANNEL_FREE, mInternetStream, true, &mStreamChannel);
return mStreamChannel;
}
bool LLAudioStreamManagerFMODEX::stopStream()
{
if (mInternetStream)
{
bool close = true;
switch (getOpenState())
{
case FMOD_OPENSTATE_CONNECTING:
close = false;
break;
/*case FSOUND_STREAM_NET_NOTCONNECTED:
case FSOUND_STREAM_NET_BUFFERING:
case FSOUND_STREAM_NET_READY:
case FSOUND_STREAM_NET_ERROR:*/
default:
close = true;
}
if (close)
{
mInternetStream->release();
mStreamChannel = NULL;
mInternetStream = NULL;
return true;
}
else
{
return false;
}
}
else
{
return true;
}
}
FMOD_OPENSTATE LLAudioStreamManagerFMODEX::getOpenState()
{
FMOD_OPENSTATE state;
mInternetStream->getOpenState(&state,NULL,NULL,NULL);
return state;
}

View File

@@ -0,0 +1,83 @@
/**
* @file streamingaudio_fmod.h
* @author Tofu Linden
* @brief Definition of LLStreamingAudio_FMOD implementation
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_STREAMINGAUDIO_FMOD_H
#define LL_STREAMINGAUDIO_FMOD_H
#include "stdtypes.h" // from llcommon
#include "llstreamingaudio.h"
//Stubs
class LLAudioStreamManagerFMODEX;
namespace FMOD
{
class System;
class Channel;
}
//Interfaces
class LLStreamingAudio_FMODEX : public LLStreamingAudioInterface
{
public:
LLStreamingAudio_FMODEX(FMOD::System *system);
/*virtual*/ ~LLStreamingAudio_FMODEX();
/*virtual*/ void start(const std::string& url);
/*virtual*/ void stop();
/*virtual*/ void pause(int pause);
/*virtual*/ void update();
/*virtual*/ int isPlaying();
/*virtual*/ void setGain(F32 vol);
/*virtual*/ F32 getGain();
/*virtual*/ std::string getURL();
/*virtual*/ bool supportsMetaData(){return true;}
/*virtual*/ const LLSD *getMetaData(){return mMetaData;} //return NULL if not playing.
/*virtual*/ bool supportsWaveData(){return true;}
/*virtual*/ bool getWaveData(float* arr, S32 count, S32 stride = 1);
private:
FMOD::System *mSystem;
LLAudioStreamManagerFMODEX *mCurrentInternetStreamp;
FMOD::Channel *mFMODInternetStreamChannelp;
std::list<LLAudioStreamManagerFMODEX *> mDeadStreams;
std::string mURL;
F32 mGain;
LLSD *mMetaData;
};
#endif // LL_STREAMINGAUDIO_FMOD_H

View File

@@ -133,10 +133,10 @@ BOOL decode_vorbis_file(LLVFS *vfs, const LLUUID &in_uuid, char *out_fname)
return(FALSE); return(FALSE);
} }
//********************************** // **********************************
LLAPRFile outfile ; LLAPRFile outfile ;
outfile.open(out_fname,LL_APR_WPB); outfile.open(out_fname,LL_APR_WPB);
//********************************** // **********************************
if (!outfile.getFileHandle()) if (!outfile.getFileHandle())
{ {
llwarning("unable to open vorbis destination file for writing",0); llwarning("unable to open vorbis destination file for writing",0);
@@ -308,9 +308,9 @@ BOOL decode_vorbis_file(LLVFS *vfs, const LLUUID &in_uuid, char *out_fname)
outfile.seek(SEEK_END,-fade_length*2); outfile.seek(SEEK_END,-fade_length*2);
outfile.write(pcmout,2*fade_length); //write back xfaded last 16 samples outfile.write(pcmout,2*fade_length); //write back xfaded last 16 samples
//******************* // *******************
outfile.close(); outfile.close();
//******************* // *******************
if ((36 == data_length) || (!(eof))) if ((36 == data_length) || (!(eof)))
{ {

View File

@@ -87,10 +87,10 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro
error_msg.clear(); error_msg.clear();
//******************************** // ********************************
LLAPRFile infile ; LLAPRFile infile ;
infile.open(in_fname,LL_APR_RB); infile.open(in_fname,LL_APR_RB);
//******************************** // ********************************
if (!infile.getFileHandle()) if (!infile.getFileHandle())
{ {
error_msg = "CannotUploadSoundFile"; error_msg = "CannotUploadSoundFile";
@@ -159,9 +159,9 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro
file_pos += (chunk_length + 8); file_pos += (chunk_length + 8);
chunk_length = 0; chunk_length = 0;
} }
//**************** // ****************
infile.close(); infile.close();
//**************** // ****************
if (!uncompressed_pcm) if (!uncompressed_pcm)
{ {

View File

@@ -33,6 +33,7 @@
#define WINDGEN_H #define WINDGEN_H
#include "llcommon.h" #include "llcommon.h"
#include "llrand.h"
template <class MIXBUFFERFORMAT_T> template <class MIXBUFFERFORMAT_T>
class LLWindGen class LLWindGen
@@ -60,7 +61,9 @@ public:
} }
const U32 getInputSamplingRate() { return mInputSamplingRate; } const U32 getInputSamplingRate() { return mInputSamplingRate; }
const F32 getNextSample();
const F32 getClampedSample(bool clamp, F32 sample);
// newbuffer = the buffer passed from the previous DSP unit. // newbuffer = the buffer passed from the previous DSP unit.
// numsamples = length in samples-per-channel at this mix time. // numsamples = length in samples-per-channel at this mix time.
// NOTE: generates L/R interleaved stereo // NOTE: generates L/R interleaved stereo
@@ -95,7 +98,7 @@ public:
// Start with white noise // Start with white noise
// This expression is fragile, rearrange it and it will break! // This expression is fragile, rearrange it and it will break!
next_sample = (F32)rand() * (1.0f / (F32)(RAND_MAX / (U16_MAX / 8))) + (F32)(S16_MIN / 8); next_sample = getNextSample();
// Apply a pinking filter // Apply a pinking filter
// Magic numbers taken from PKE method at http://www.firstpr.com.au/dsp/pink-noise/ // Magic numbers taken from PKE method at http://www.firstpr.com.au/dsp/pink-noise/
@@ -132,23 +135,13 @@ public:
for (U8 i=mSubSamples; i && numsamples; --i, --numsamples) for (U8 i=mSubSamples; i && numsamples; --i, --numsamples)
{ {
mLastSample = mLastSample + delta; mLastSample = mLastSample + delta;
S32 sample_right = (S32)(mLastSample * mCurrentPanGainR); MIXBUFFERFORMAT_T sample_right = (MIXBUFFERFORMAT_T)getClampedSample(clip, mLastSample * mCurrentPanGainR);
S32 sample_left = (S32)mLastSample - sample_right; MIXBUFFERFORMAT_T sample_left = (MIXBUFFERFORMAT_T)getClampedSample(clip, mLastSample - (F32)sample_right);
if (!clip) *cursamplep = sample_left;
{ ++cursamplep;
*cursamplep = (MIXBUFFERFORMAT_T)sample_left; *cursamplep = sample_right;
++cursamplep; ++cursamplep;
*cursamplep = (MIXBUFFERFORMAT_T)sample_right;
++cursamplep;
}
else
{
*cursamplep = (MIXBUFFERFORMAT_T)llclamp(sample_left, (S32)S16_MIN, (S32)S16_MAX);
++cursamplep;
*cursamplep = (MIXBUFFERFORMAT_T)llclamp(sample_right, (S32)S16_MIN, (S32)S16_MAX);
++cursamplep;
}
} }
} }
@@ -179,4 +172,9 @@ private:
F32 mLastSample; F32 mLastSample;
}; };
template<class T> inline const F32 LLWindGen<T>::getNextSample() { return (F32)rand() * (1.0f / (F32)(RAND_MAX / (U16_MAX / 8))) + (F32)(S16_MIN / 8); }
template<> inline const F32 LLWindGen<F32>::getNextSample() { return ll_frand()-.5f; }
template<class T> inline const F32 LLWindGen<T>::getClampedSample(bool clamp, F32 sample) { return clamp ? (F32)llclamp((S32)sample,(S32)S16_MIN,(S32)S16_MAX) : sample; }
template<> inline const F32 LLWindGen<F32>::getClampedSample(bool clamp, F32 sample) { return sample; }
#endif #endif

View File

@@ -195,15 +195,19 @@ void LLCharacter::requestStopMotion( LLMotion* motion)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// updateMotions() // updateMotions()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static LLFastTimer::DeclareTimer FTM_UPDATE_ANIMATION("Update Animation");
static LLFastTimer::DeclareTimer FTM_UPDATE_HIDDEN_ANIMATION("Update Hidden Anim");
void LLCharacter::updateMotions(e_update_t update_type) void LLCharacter::updateMotions(e_update_t update_type)
{ {
LLFastTimer t(LLFastTimer::FTM_UPDATE_ANIMATION);
if (update_type == HIDDEN_UPDATE) if (update_type == HIDDEN_UPDATE)
{ {
LLFastTimer t(FTM_UPDATE_HIDDEN_ANIMATION);
mMotionController.updateMotionsMinimal(); mMotionController.updateMotionsMinimal();
} }
else else
{ {
LLFastTimer t(FTM_UPDATE_ANIMATION);
// unpause if the number of outstanding pause requests has dropped to the initial one // unpause if the number of outstanding pause requests has dropped to the initial one
if (mMotionController.isPaused() && mPauseRequest->getNumRefs() == 1) if (mMotionController.isPaused() && mPauseRequest->getNumRefs() == 1)
{ {

View File

@@ -56,9 +56,7 @@ LLJoint::LLJoint()
mUpdateXform = TRUE; mUpdateXform = TRUE;
mJointNum = -1; mJointNum = -1;
touch(); touch();
#if MESH_ENABLED
mResetAfterRestoreOldXform = false; mResetAfterRestoreOldXform = false;
#endif //MESH_ENABLED
} }
@@ -242,7 +240,6 @@ void LLJoint::setPosition( const LLVector3& pos )
} }
} }
#if MESH_ENABLED
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// setPosition() // setPosition()
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@@ -278,7 +275,6 @@ void LLJoint::restoreToDefaultXform( void )
mXform = mDefaultXform; mXform = mDefaultXform;
setPosition( mXform.getPosition() ); setPosition( mXform.getPosition() );
} }
#endif //MESH_ENABLED
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// getWorldPosition() // getWorldPosition()

View File

@@ -86,19 +86,14 @@ protected:
// explicit transformation members // explicit transformation members
LLXformMatrix mXform; LLXformMatrix mXform;
#if MESH_ENABLED
LLXformMatrix mOldXform; LLXformMatrix mOldXform;
LLXformMatrix mDefaultXform; LLXformMatrix mDefaultXform;
LLUUID mId; LLUUID mId;
#endif //MESH_ENABLED
public: public:
U32 mDirtyFlags; U32 mDirtyFlags;
BOOL mUpdateXform; BOOL mUpdateXform;
#if MESH_ENABLED
BOOL mResetAfterRestoreOldXform; BOOL mResetAfterRestoreOldXform;
#endif //MESH_ENABLED
// describes the skin binding pose // describes the skin binding pose
LLVector3 mSkinOffset; LLVector3 mSkinOffset;
@@ -188,8 +183,6 @@ public:
S32 getJointNum() const { return mJointNum; } S32 getJointNum() const { return mJointNum; }
void setJointNum(S32 joint_num) { mJointNum = joint_num; } void setJointNum(S32 joint_num) { mJointNum = joint_num; }
#if MESH_ENABLED
void restoreOldXform( void ); void restoreOldXform( void );
void restoreToDefaultXform( void ); void restoreToDefaultXform( void );
void setDefaultFromCurrentXform( void ); void setDefaultFromCurrentXform( void );
@@ -204,7 +197,6 @@ public:
const BOOL doesJointNeedToBeReset( void ) const { return mResetAfterRestoreOldXform; } const BOOL doesJointNeedToBeReset( void ) const { return mResetAfterRestoreOldXform; }
//Setter for joint reset flag //Setter for joint reset flag
void setJointToBeReset( BOOL val ) { mResetAfterRestoreOldXform = val; } void setJointToBeReset( BOOL val ) { mResetAfterRestoreOldXform = val; }
#endif //MESH_ENABLED
// <edit> // <edit>
std::string exportString(U32 tabs = 0); std::string exportString(U32 tabs = 0);

View File

@@ -637,9 +637,9 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
motionp->fadeIn(); motionp->fadeIn();
} }
//********************** // **********************
// MOTION INACTIVE // MOTION INACTIVE
//********************** // **********************
if (motionp->isStopped() && mAnimTime > motionp->getStopTime() + motionp->getEaseOutDuration()) if (motionp->isStopped() && mAnimTime > motionp->getStopTime() + motionp->getEaseOutDuration())
{ {
// this motion has gone on too long, deactivate it // this motion has gone on too long, deactivate it
@@ -659,9 +659,9 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
} }
} }
//********************** // **********************
// MOTION EASE OUT // MOTION EASE OUT
//********************** // **********************
else if (motionp->isStopped() && mAnimTime > motionp->getStopTime()) else if (motionp->isStopped() && mAnimTime > motionp->getStopTime())
{ {
// is this the first iteration in the ease out phase? // is this the first iteration in the ease out phase?
@@ -684,9 +684,9 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature); update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature);
} }
//********************** // **********************
// MOTION ACTIVE // MOTION ACTIVE
//********************** // **********************
else if (mAnimTime > motionp->mActivationTimestamp + motionp->getEaseInDuration()) else if (mAnimTime > motionp->mActivationTimestamp + motionp->getEaseInDuration())
{ {
posep->setWeight(motionp->getFadeWeight()); posep->setWeight(motionp->getFadeWeight());
@@ -707,9 +707,9 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty
update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature); update_result = motionp->onUpdate(mAnimTime - motionp->mActivationTimestamp, last_joint_signature);
} }
//********************** // **********************
// MOTION EASE IN // MOTION EASE IN
//********************** // **********************
else if (mAnimTime >= motionp->mActivationTimestamp) else if (mAnimTime >= motionp->mActivationTimestamp)
{ {
if (mLastTime < motionp->mActivationTimestamp) if (mLastTime < motionp->mActivationTimestamp)

View File

@@ -15,6 +15,7 @@ include_directories(
) )
set(llcommon_SOURCE_FILES set(llcommon_SOURCE_FILES
aiframetimer.cpp
imageids.cpp imageids.cpp
indra_constants.cpp indra_constants.cpp
llapp.cpp llapp.cpp
@@ -35,7 +36,7 @@ set(llcommon_SOURCE_FILES
llerrorthread.cpp llerrorthread.cpp
llevent.cpp llevent.cpp
lleventtimer.cpp lleventtimer.cpp
llfasttimer.cpp llfasttimer_class.cpp
llfile.cpp llfile.cpp
llfindlocale.cpp llfindlocale.cpp
llfixedbuffer.cpp llfixedbuffer.cpp
@@ -54,6 +55,7 @@ set(llcommon_SOURCE_FILES
llmetrics.cpp llmetrics.cpp
llmortician.cpp llmortician.cpp
lloptioninterface.cpp lloptioninterface.cpp
llptrto.cpp
llprocesslauncher.cpp llprocesslauncher.cpp
llprocessor.cpp llprocessor.cpp
llqueuedthread.cpp llqueuedthread.cpp
@@ -89,6 +91,7 @@ set(llcommon_SOURCE_FILES
set(llcommon_HEADER_FILES set(llcommon_HEADER_FILES
CMakeLists.txt CMakeLists.txt
aiframetimer.h
aithreadsafe.h aithreadsafe.h
bitpack.h bitpack.h
ctype_workaround.h ctype_workaround.h
@@ -136,6 +139,7 @@ set(llcommon_HEADER_FILES
llextendedstatus.h llextendedstatus.h
lleventtimer.h lleventtimer.h
llfasttimer.h llfasttimer.h
llfasttimer_class.h
llfile.h llfile.h
llfindlocale.h llfindlocale.h
llfixedbuffer.h llfixedbuffer.h
@@ -171,6 +175,7 @@ set(llcommon_HEADER_FILES
llprocessor.h llprocessor.h
llptrskiplist.h llptrskiplist.h
llptrskipmap.h llptrskipmap.h
llptrto.h
llqueuedthread.h llqueuedthread.h
llrand.h llrand.h
llrefcount.h llrefcount.h

View File

@@ -0,0 +1,150 @@
/**
* @file aiframetimer.cpp
*
* Copyright (c) 2011, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 06/08/2011
* - Initial version, written by Aleric Inglewood @ SL
*/
#include "linden_common.h"
#include "aiframetimer.h"
static F64 const NEVER = 1e16; // 317 million years.
F64 AIFrameTimer::sNextExpiration;
AIFrameTimer::timer_list_type AIFrameTimer::sTimerList;
LLMutex AIFrameTimer::sMutex;
// Notes on thread-safety of AIRunningFrameTimer (continued from aiframetimer.h)
//
// Most notably, the constructor and init() should be called as follows:
// 1) The object is constructed (AIRunningFrameTimer::AIRunningFrameTimer).
// 2) The lock is obtained.
// 3) The object is inserted in the list (operator<(AIRunningFrameTimer const&, AIRunningFrameTimer const&)).
// 4) The object is initialized (AIRunningFrameTimer::init).
// 5) The lock is released.
// This assures that the object is not yet shared at the moment that it is initialized.
void AIFrameTimer::create(F64 expiration, signal_type::slot_type const& slot)
{
AIRunningFrameTimer new_timer(expiration, this);
sMutex.lock();
llassert(mHandle.mRunningTimer == sTimerList.end()); // Create may only be called when the timer isn't already running.
mHandle.init(sTimerList.insert(new_timer), slot);
sNextExpiration = sTimerList.begin()->expiration();
sMutex.unlock();
}
void AIFrameTimer::cancel(void)
{
// In order to stop us from returning from cancel() while
// the callback function is being called (which is done
// in AIFrameTimer::handleExpiration after obtaining the
// mHandle.mMutex lock), we start with trying to obtain
// it here and as such wait till the callback function
// returned.
mHandle.mMutex.lock();
// Next we have to grab this lock in order to stop
// AIFrameTimer::handleExpiration from even entering
// in the case we manage to get it first.
sMutex.lock();
if (mHandle.mRunningTimer != sTimerList.end())
{
sTimerList.erase(mHandle.mRunningTimer);
mHandle.mRunningTimer = sTimerList.end();
sNextExpiration = sTimerList.empty() ? NEVER : sTimerList.begin()->expiration();
}
sMutex.unlock();
mHandle.mMutex.unlock();
}
void AIFrameTimer::handleExpiration(F64 current_frame_time)
{
sMutex.lock();
for(;;)
{
if (sTimerList.empty())
{
// No running timers left.
sNextExpiration = NEVER;
break;
}
timer_list_type::iterator running_timer = sTimerList.begin();
sNextExpiration = running_timer->expiration();
if (sNextExpiration > current_frame_time)
{
// Didn't expire yet.
break;
}
// Obtain handle of running timer through the associated AIFrameTimer object.
// Note that if the AIFrameTimer object was destructed (when running_timer->getTimer()
// would return an invalid pointer) then it called cancel(), so we can't be here.
Handle& handle(running_timer->getTimer()->mHandle);
llassert_always(running_timer == handle.mRunningTimer);
// We're going to erase this timer, so stop cancel() from doing the same.
handle.mRunningTimer = sTimerList.end();
// We keep handle.mMutex during the callback to prevent the thread that
// owns the AIFrameTimer from deleting the callback function while we
// call it: in order to do so it first has to call cancel(), which will
// block until we release this mutex again, or we won't call the callback
// function here because the trylock fails.
//
// Assuming the main thread arrived here, there are two possible states
// for the other thread that tries to delete the call back function,
// right after calling the cancel() function too:
//
// 1. It hasn't obtained the first lock yet, we obtain the handle.mMutex
// lock and the other thread will stall on the first line of cancel().
// After do_callback returns, the other thread will do nothing because
// handle.mRunningTimer equals sTimerList.end(), exit the function and
// (possibly) delete the callback object, but that is ok as we already
// returned from the callback function.
//
// 2. It already called cancel() and hangs on the second line trying to
// obtain sMutex.lock(). The trylock below fails and we never call the
// callback function. We erase the running timer here and release sMutex
// at the end, after which the other thread does nothing because
// handle.mRunningTimer equals sTimerList.end(), exits the function and
// (possibly) deletes the callback object.
//
// Note that if the other thread actually obtained the sMutex then we
// can't be here: this is still inside the critical area of sMutex.
if (handle.mMutex.tryLock()) // If this fails then another thread is in the process of cancelling this timer, so do nothing.
{
sMutex.unlock();
running_timer->do_callback(); // May not throw exceptions.
sMutex.lock();
handle.mMutex.unlock(); // Allow other thread to return from cancel() and possibly delete the callback object.
}
// Erase the timer from the running list.
sTimerList.erase(running_timer);
}
sMutex.unlock();
}

View File

@@ -0,0 +1,136 @@
/**
* @file aiframetimer.h
* @brief Implementation of AIFrameTimer.
*
* Copyright (c) 2011, Aleric Inglewood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution.
*
* CHANGELOG
* and additional copyright holders.
*
* 05/08/2011
* Initial version, written by Aleric Inglewood @ SL
*/
#ifndef AIFRAMETIMER_H
#define AIFRAMETIMER_H
#include "llframetimer.h"
#include "llthread.h"
#include <boost/signals2.hpp>
#include <set>
class LL_COMMON_API AIFrameTimer
{
protected:
typedef boost::signals2::signal<void (void)> signal_type;
private:
// Use separate struct for this object because it is non-copyable.
struct Signal {
signal_type mSignal;
};
// Notes on Thread-Safety
//
// This is the type of the objects stored in AIFrameTimer::sTimerList, and as such leans
// for it's thread-safety on the same lock as is used for that std::multiset as follows.
// An arbitrary thread can create, insert and initialize this object. Other threads can
// not access it until that has completed.
//
// After creation two threads can access it: the thread that created it (owns the
// AIFrameTimer object, which has an mHandle that points to this object), or the main
// thread by finding it in sTimerList.
//
// See aiframetimer.cpp for more notes.
class AIRunningFrameTimer {
private:
F64 mExpire; // Time at which the timer expires, in seconds since application start (compared to LLFrameTimer::sFrameTime).
Signal* mCallback;
AIFrameTimer* mTimer;
public:
AIRunningFrameTimer(F64 expiration, AIFrameTimer* timer) : mExpire(LLFrameTimer::getElapsedSeconds() + expiration), mCallback(new Signal), mTimer(timer) { }
~AIRunningFrameTimer() { delete mCallback; }
void init(signal_type::slot_type const& slot) const { mCallback->mSignal.connect(slot); }
friend bool operator<(AIRunningFrameTimer const& ft1, AIRunningFrameTimer const& ft2) { return ft1.mExpire < ft2.mExpire; }
void do_callback(void) const { mCallback->mSignal(); }
F64 expiration(void) const { return mExpire; }
AIFrameTimer* getTimer(void) const { return mTimer; }
};
typedef std::multiset<AIRunningFrameTimer> timer_list_type;
static LLMutex sMutex; // Mutex for the two global variables below.
static timer_list_type sTimerList; // List with all running timers.
static F64 sNextExpiration; // Cache of smallest value in sTimerList.
friend class LLFrameTimer; // Access to sNextExpiration.
class Handle {
public:
timer_list_type::iterator mRunningTimer; // Points to the running timer, or to sTimerList.end() when not running.
// Access to this iterator is protected by the AIFrameTimer::sMutex!
LLMutex mMutex; // A mutex used to protect us from deletion of the callback object while
// calling the callback function in the case of simultaneous expiration
// and cancellation by the thread owning the AIFrameTimer (by calling
// AIFrameTimer::cancel).
// Constructor for a not-running timer.
Handle(void) : mRunningTimer(sTimerList.end()) { }
// Actual initialization used by AIFrameTimer::create.
void init(timer_list_type::iterator const& running_timer, signal_type::slot_type const& slot)
{
// Locking AIFrameTimer::sMutex is not neccessary here, because we're creating
// the object and no other thread knows of mRunningTimer at this point.
mRunningTimer = running_timer;
mRunningTimer->init(slot);
}
private:
// LLMutex has no assignment operator.
Handle& operator=(Handle const&) { return *this; }
};
Handle mHandle;
public:
// Construct an AIFrameTimer that is not running.
AIFrameTimer(void) { }
// Construction of a running AIFrameTimer with expiration time expiration in seconds, and callback slot.
AIFrameTimer(F64 expiration, signal_type::slot_type const& slot) { create(expiration, slot); }
// Destructing the AIFrameTimer object terminates the running timer (if still running).
// Note that cancel() must have returned BEFORE anything is destructed that would disallow the callback function to be called.
// So, if the AIFrameTimer is a member of an object whose callback function is called then cancel() has
// to be called manually (or from the destructor of THAT object), before that object is destructed.
// Cancel may be called multiple times.
~AIFrameTimer() { cancel(); }
void create(F64 expiration, signal_type::slot_type const& slot);
void cancel(void);
protected:
static void handleExpiration(F64 current_frame_time);
};
#endif

View File

@@ -124,7 +124,7 @@ public:
// NOTE: This next two funtions are only included here // NOTE: This next two funtions are only included here
// for those too familiar with the LLLinkedList template class. // for those too familiar with the LLLinkedList template class.
// They are depreciated. resetList() is unecessary while // They are deprecated. resetList() is unecessary while
// getCurrentData() is identical to getNextData() and has // getCurrentData() is identical to getNextData() and has
// a misleading name. // a misleading name.
// //
@@ -604,7 +604,7 @@ BOOL LLDoubleLinkedList<DATA_TYPE>::checkData(const DATA_TYPE *data)
// NOTE: This next two funtions are only included here // NOTE: This next two funtions are only included here
// for those too familiar with the LLLinkedList template class. // for those too familiar with the LLLinkedList template class.
// They are depreciated. resetList() is unecessary while // They are deprecated. resetList() is unecessary while
// getCurrentData() is identical to getNextData() and has // getCurrentData() is identical to getNextData() and has
// a misleading name. // a misleading name.
// //

View File

@@ -153,11 +153,6 @@ const char LAND_LAYER_CODE = 'L';
const char WATER_LAYER_CODE = 'W'; const char WATER_LAYER_CODE = 'W';
const char WIND_LAYER_CODE = '7'; const char WIND_LAYER_CODE = '7';
const char CLOUD_LAYER_CODE = '8'; const char CLOUD_LAYER_CODE = '8';
// Extended land layer for Aurora Sim
const char AURORA_LAND_LAYER_CODE = 'M';
const char AURORA_WATER_LAYER_CODE = 'X';
const char AURORA_WIND_LAYER_CODE = '9';
const char AURORA_CLOUD_LAYER_CODE = ':';
// keys // keys
// Bit masks for various keyboard modifier keys. // Bit masks for various keyboard modifier keys.

View File

@@ -249,7 +249,7 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
} }
// //
//******************************************************************************************************************************* // *******************************************************************************************************************************
//static components of LLAPRFile //static components of LLAPRFile
// //
@@ -504,5 +504,5 @@ bool LLAPRFile::removeDir(const std::string& dirname)
} }
// //
//end of static components of LLAPRFile //end of static components of LLAPRFile
//******************************************************************************************************************************* // *******************************************************************************************************************************
// //

View File

@@ -168,7 +168,7 @@ public:
apr_file_t* getFileHandle() {return mFile;} apr_file_t* getFileHandle() {return mFile;}
// //
//******************************************************************************************************************************* // *******************************************************************************************************************************
//static components //static components
// //
private: private:
@@ -185,7 +185,7 @@ public:
// Returns bytes read/written, 0 if read/write fails: // Returns bytes read/written, 0 if read/write fails:
static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes); static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes);
static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes); static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes);
//******************************************************************************************************************************* // *******************************************************************************************************************************
}; };
/** /**

View File

@@ -214,17 +214,16 @@ LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_
bool LLAssetType::lookupCanLink(EType asset_type) bool LLAssetType::lookupCanLink(EType asset_type)
{ {
//Check that enabling all these other types as linkable doesn't break things. //Check that enabling all these other types as linkable doesn't break things.
/*const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
const AssetEntry *entry = dict->lookup(asset_type); const AssetEntry *entry = dict->lookup(asset_type);
if (entry) if (entry)
{ {
return entry->mCanLink; return entry->mCanLink;
} }
return false; return false;
*/
return (asset_type == AT_CLOTHING || asset_type == AT_OBJECT || asset_type == AT_CATEGORY || /*return (asset_type == AT_CLOTHING || asset_type == AT_OBJECT || asset_type == AT_CATEGORY ||
asset_type == AT_BODYPART || asset_type == AT_GESTURE); asset_type == AT_BODYPART || asset_type == AT_GESTURE);*/
} }
// static // static

View File

@@ -43,6 +43,7 @@
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include "llfasttimer.h"
#include "lltimer.h" #include "lltimer.h"
#include "llstring.h" #include "llstring.h"
@@ -94,9 +95,11 @@ std::string LLDate::asRFC1123() const
return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT")); return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
} }
LLFastTimer::DeclareTimer FT_DATE_FORMAT("Date Format");
std::string LLDate::toHTTPDateString (std::string fmt) const std::string LLDate::toHTTPDateString (std::string fmt) const
{ {
LLFastTimer ft1(FT_DATE_FORMAT);
time_t locSeconds = (time_t) mSecondsSinceEpoch; time_t locSeconds = (time_t) mSecondsSinceEpoch;
struct tm * gmt = gmtime (&locSeconds); struct tm * gmt = gmtime (&locSeconds);
@@ -105,7 +108,7 @@ std::string LLDate::toHTTPDateString (std::string fmt) const
std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt) std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt)
{ {
// Return Epoch UTC date LLFastTimer ft1(FT_DATE_FORMAT);
// avoid calling setlocale() unnecessarily - it's expensive. // avoid calling setlocale() unnecessarily - it's expensive.
static std::string prev_locale = ""; static std::string prev_locale = "";

View File

@@ -107,7 +107,14 @@ const int LL_ERR_PRICE_MISMATCH = -23018;
#define llwarning(msg, num) llwarns << "Warning # " << num << ": " << msg << llendl; #define llwarning(msg, num) llwarns << "Warning # " << num << ": " << msg << llendl;
#define llassert_always(func) if (LL_UNLIKELY(!(func))) llerrs << "ASSERT (" << #func << ")" << llendl; #define liru_slashpos std::string(__FILE__).find_last_of("/\\")
#define liru_slashpos2 std::string(__FILE__).substr(0,liru_slashpos).find_last_of("/\\")
#define liru_assert_strip /*strip path down to lastlevel directory and filename for assert.*/\
(liru_slashpos == std::string::npos ? std::string(__FILE__)/*just filename, print as is*/\
: liru_slashpos2 == std::string::npos ? std::string(__FILE__)/*Apparently, we're in / or perhaps the top of the drive, print as is*/\
: std::string(__FILE__).substr(1+liru_slashpos2))/*print foo/bar.cpp or perhaps foo\bar.cpp*/
#define llassert_always(func) if (LL_UNLIKELY(!(func))) llerrs <<"\nASSERT(" #func ")\nfile:"<<liru_assert_strip<<" line:"<<__LINE__ << llendl;
#ifdef SHOW_ASSERT #ifdef SHOW_ASSERT
#define llassert(func) llassert_always(func) #define llassert(func) llassert_always(func)

View File

@@ -1,135 +0,0 @@
/**
* @file llfasttimer.cpp
* @brief Implementation of the fast timer.
*
* $LicenseInfo:firstyear=2004&license=viewergpl$
*
* Copyright (c) 2004-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llfasttimer.h"
#include "llmemory.h"
#include "llprocessor.h"
#if LL_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include "lltimer.h"
//////////////////////////////////////////////////////////////////////////////
// statics
LLFastTimer::EFastTimerType LLFastTimer::sCurType = LLFastTimer::FTM_OTHER;
int LLFastTimer::sCurDepth = 0;
U64 LLFastTimer::sStart[LLFastTimer::FTM_MAX_DEPTH];
U64 LLFastTimer::sCounter[LLFastTimer::FTM_NUM_TYPES];
U64 LLFastTimer::sCountHistory[LLFastTimer::FTM_HISTORY_NUM][LLFastTimer::FTM_NUM_TYPES];
U64 LLFastTimer::sCountAverage[LLFastTimer::FTM_NUM_TYPES];
U64 LLFastTimer::sCalls[LLFastTimer::FTM_NUM_TYPES];
U64 LLFastTimer::sCallHistory[LLFastTimer::FTM_HISTORY_NUM][LLFastTimer::FTM_NUM_TYPES];
U64 LLFastTimer::sCallAverage[LLFastTimer::FTM_NUM_TYPES];
S32 LLFastTimer::sCurFrameIndex = -1;
S32 LLFastTimer::sLastFrameIndex = -1;
int LLFastTimer::sPauseHistory = 0;
int LLFastTimer::sResetHistory = 0;
U64 LLFastTimer::sClockResolution = calc_clock_frequency(50U); // Resolution of get_clock_count()
U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
{
return sClockResolution >> 8;
}
void LLFastTimer::reset()
{
countsPerSecond(); // good place to calculate clock frequency
if (sCurDepth != 0)
{
llerrs << "LLFastTimer::Reset() when sCurDepth != 0" << llendl;
}
if (sPauseHistory)
{
sResetHistory = 1;
}
else if (sResetHistory)
{
sCurFrameIndex = -1;
sResetHistory = 0;
}
else if (sCurFrameIndex >= 0)
{
int hidx = sCurFrameIndex % FTM_HISTORY_NUM;
for (S32 i=0; i<FTM_NUM_TYPES; i++)
{
sCountHistory[hidx][i] = sCounter[i];
sCountAverage[i] = (sCountAverage[i]*sCurFrameIndex + sCounter[i]) / (sCurFrameIndex+1);
sCallHistory[hidx][i] = sCalls[i];
sCallAverage[i] = (sCallAverage[i]*sCurFrameIndex + sCalls[i]) / (sCurFrameIndex+1);
}
sLastFrameIndex = sCurFrameIndex;
}
else
{
for (S32 i=0; i<FTM_NUM_TYPES; i++)
{
sCountAverage[i] = 0;
sCallAverage[i] = 0;
}
}
sCurFrameIndex++;
for (S32 i=0; i<FTM_NUM_TYPES; i++)
{
sCounter[i] = 0;
sCalls[i] = 0;
}
sCurDepth = 0;
}
//////////////////////////////////////////////////////////////////////////////
//
// Important note: These implementations must be FAST!
//
// shift off lower 8 bits for lower resolution but longer term timing
// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
//LL_COMMON_API U64 get_clock_count(); // in lltimer.cpp
// On windows these use QueryPerformanceCounter, which is arguably fine and also works on amd architectures.
U32 LLFastTimer::getCPUClockCount32()
{
return get_clock_count() >> 8;
}
U64 LLFastTimer::getCPUClockCount64()
{
return get_clock_count();
}

View File

@@ -1,294 +1,35 @@
/** /**
* @file llfasttimer.h * @file llfasttimer.h
* @brief Declaration of a fast timer. * @brief Inline implementations of fast timers.
* *
* $LicenseInfo:firstyear=2004&license=viewergpl$ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
*
* Copyright (c) 2004-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code * Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab * Copyright (C) 2010, Linden Research, Inc.
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
* *
* There are special exceptions to the terms and conditions of the GPL as * This library is free software; you can redistribute it and/or
* it is applied to this Source Code. View the full text of the exception * modify it under the terms of the GNU Lesser General Public
* in the file doc/FLOSS-exception.txt in this software distribution, or * License as published by the Free Software Foundation;
* online at * version 2.1 of the License only.
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
* *
* By copying, modifying or distributing this software, you acknowledge * This library is distributed in the hope that it will be useful,
* that you have read and understood your obligations described above, * but WITHOUT ANY WARRANTY; without even the implied warranty of
* and agree to abide by those obligations. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* *
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * You should have received a copy of the GNU Lesser General Public
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * License along with this library; if not, write to the Free Software
* COMPLETENESS OR PERFORMANCE. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
#ifndef LL_LLFASTTIMER_H #ifndef LL_FASTTIMER_H
#define LL_LLFASTTIMER_H #define LL_FASTTIMER_H
#define FAST_TIMER_ON 1 // Implementation of getCPUClockCount32() and getCPUClockCount64 are now in llfastertimer_class.cpp.
class LL_COMMON_API LLFastTimer
{
public:
enum EFastTimerType
{
// high level
FTM_FRAME,
FTM_UPDATE,
FTM_RENDER,
FTM_SWAP,
FTM_CLIENT_COPY,
FTM_IDLE,
FTM_SLEEP,
// general timers
FT_STRING_FORMAT,
// common messaging components
FTM_PUMP,
FTM_CURL,
FTM_PUMPIO,
// common simulation components
FTM_UPDATE_ANIMATION,
FTM_UPDATE_TERRAIN,
FTM_UPDATE_PRIMITIVES,
FTM_UPDATE_PARTICLES,
FTM_SIMULATE_PARTICLES,
FTM_UPDATE_SKY,
FTM_UPDATE_TEXTURES,
FTM_UPDATE_WLPARAM,
FTM_UPDATE_WATER,
FTM_UPDATE_CLOUDS,
FTM_UPDATE_GRASS,
FTM_UPDATE_TREE,
FTM_UPDATE_AVATAR,
#if MESH_ENABLED
FTM_UPDATE_RIGGED_VOLUME,
FTM_SKIN_RIGGED,
FTM_RIGGED_OCTREE,
#endif //MESH_ENABLED
// common render components
FTM_SHADOW_GEOMETRY,
FTM_SHADOW_RENDER,
FTM_SHADOW_TERRAIN,
FTM_SHADOW_AVATAR,
FTM_SHADOW_SIMPLE,
FTM_SHADOW_ALPHA,
FTM_SHADOW_TREE,
FTM_RENDER_GEOMETRY,
FTM_RENDER_TERRAIN,
FTM_RENDER_SIMPLE,
FTM_RENDER_FULLBRIGHT,
FTM_RENDER_GLOW,
FTM_RENDER_GRASS,
FTM_RENDER_INVISIBLE,
FTM_RENDER_SHINY,
FTM_RENDER_BUMP,
FTM_RENDER_TREES,
FTM_RENDER_CHARACTERS,
FTM_RENDER_OCCLUSION,
FTM_RENDER_ALPHA,
FTM_RENDER_CLOUDS,
FTM_RENDER_HUD,
FTM_RENDER_PARTICLES,
FTM_RENDER_WATER,
FTM_RENDER_WL_SKY,
FTM_RENDER_FAKE_VBO_UPDATE,
FTM_RENDER_TIMER,
FTM_RENDER_UI,
FTM_RENDER_BLOOM,
FTM_RENDER_BLOOM_FBO,
FTM_RENDER_FONTS,
// deferred rendering
FTM_RENDER_DEFERRED,
FTM_BIND_DEFERRED,
FTM_SUN_SHADOW,
FTM_SOFTEN_SHADOW,
FTM_EDGE_DETECTION,
FTM_GI_TRACE,
FTM_GI_GATHER,
FTM_ATMOSPHERICS,
FTM_LOCAL_LIGHTS,
FTM_FULLSCREEN_LIGHTS,
FTM_PROJECTORS,
FTM_POST,
FTM_VISIBLE_CLOUD,
// newview specific
FTM_MESSAGES,
FTM_MOUSEHANDLER,
FTM_KEYHANDLER,
FTM_REBUILD,
FTM_STATESORT,
FTM_STATESORT_DRAWABLE,
FTM_STATESORT_POSTSORT,
#if MESH_ENABLED
FTM_MESH_UPDATE,
FTM_MESH_LOCK1,
FTM_MESH_LOCK2,
FTM_LOAD_MESH_LOD,
#endif //MESH_ENABLED
FTM_REBUILD_VBO,
FTM_REBUILD_VOLUME_VB,
FTM_REBUILD_BRIDGE_VB,
FTM_REBUILD_HUD_VB,
FTM_REBUILD_TERRAIN_VB,
FTM_REBUILD_WATER_VB,
FTM_REBUILD_TREE_VB,
FTM_REBUILD_PARTICLE_VB,
FTM_REBUILD_CLOUD_VB,
FTM_REBUILD_GRASS_VB,
FTM_REBUILD_NONE_VB,
FTM_REBUILD_OCCLUSION_VB,
FTM_POOLS,
FTM_POOLRENDER,
FTM_IDLE_CB,
FTM_WORLD_UPDATE,
FTM_UPDATE_MOVE,
FTM_OCTREE_BALANCE,
FTM_UPDATE_LIGHTS,
FTM_CULL,
FTM_CULL_REBOUND,
FTM_FRUSTUM_CULL,
FTM_GEO_UPDATE,
FTM_GEO_RESERVE,
FTM_GEO_LIGHT,
FTM_GEO_SHADOW,
FTM_GEO_SKY,
FTM_GEN_VOLUME,
FTM_GEN_TRIANGLES,
FTM_GEN_FLEX,
FTM_AUDIO_UPDATE,
FTM_RESET_DRAWORDER,
FTM_OBJECTLIST_UPDATE,
FTM_AVATAR_UPDATE,
FTM_JOINT_UPDATE,
FTM_ATTACHMENT_UPDATE,
FTM_LOD_UPDATE,
FTM_REGION_UPDATE,
FTM_CLEANUP,
FTM_NETWORK,
FTM_IDLE_NETWORK,
FTM_CREATE_OBJECT,
FTM_LOAD_AVATAR,
FTM_PROCESS_MESSAGES,
FTM_PROCESS_OBJECTS,
FTM_PROCESS_IMAGES,
FTM_IMAGE_UPDATE,
FTM_IMAGE_CREATE,
FTM_IMAGE_DECODE,
FTM_IMAGE_READBACK,
FTM_IMAGE_MARK_DIRTY,
FTM_PIPELINE,
FTM_VFILE_WAIT,
FTM_FLEXIBLE_UPDATE,
FTM_OCCLUSION_READBACK,
FTM_HUD_EFFECTS,
FTM_HUD_UPDATE,
FTM_INVENTORY,
FTM_AUTO_SELECT,
FTM_ARRANGE,
FTM_FILTER,
FTM_REFRESH,
FTM_SORT,
FTM_PICK,
FTM_STATEMACHINE,
// Temp
FTM_TEMP1,
FTM_TEMP2,
FTM_TEMP3,
FTM_TEMP4,
FTM_TEMP5,
FTM_TEMP6,
FTM_TEMP7,
FTM_TEMP8,
FTM_OTHER, // Special, used by display code
FTM_NUM_TYPES
};
enum { FTM_HISTORY_NUM = 60 };
enum { FTM_MAX_DEPTH = 64 };
public:
static EFastTimerType sCurType;
LLFastTimer(EFastTimerType type)
{
#if FAST_TIMER_ON
mType = type;
sCurType = type;
// These don't get counted, because they use CPU clockticks
//gTimerBins[gCurTimerBin]++;
//LLTimer::sNumTimerCalls++;
U64 cpu_clocks = getCPUClockCount32();
sStart[sCurDepth] = cpu_clocks;
sCurDepth++;
#endif
};
~LLFastTimer()
{
#if FAST_TIMER_ON
U64 end,delta;
int i;
// These don't get counted, because they use CPU clockticks
//gTimerBins[gCurTimerBin]++;
//LLTimer::sNumTimerCalls++;
end = getCPUClockCount32();
sCurDepth--;
delta = end - sStart[sCurDepth];
sCounter[mType] += delta;
sCalls[mType]++;
// Subtract delta from parents
for (i=0; i<sCurDepth; i++)
sStart[i] += delta;
#endif
}
static void reset();
static U64 countsPerSecond();
public:
static int sCurDepth;
static U64 sStart[FTM_MAX_DEPTH];
static U64 sCounter[FTM_NUM_TYPES];
static U64 sCalls[FTM_NUM_TYPES];
static U64 sCountAverage[FTM_NUM_TYPES];
static U64 sCallAverage[FTM_NUM_TYPES];
static U64 sCountHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES];
static U64 sCallHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES];
static int sPauseHistory;
static int sResetHistory;
static U32 getCPUClockCount32();
static U64 getCPUClockCount64();
static U64 sClockResolution;
static S32 sCurFrameIndex;
static S32 sLastFrameIndex;
EFastTimerType mType;
};
// pull in the actual class definition
#include "llfasttimer_class.h"
#endif // LL_LLFASTTIMER_H #endif // LL_LLFASTTIMER_H

View File

@@ -0,0 +1,812 @@
/**
* @file llfasttimer_class.cpp
* @brief Implementation of the fast timer.
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llfasttimer.h"
#include "llmemory.h"
#include "llprocessor.h"
#include "llsingleton.h"
#include "lltreeiterators.h"
#include "llsdserialize.h"
#include <boost/bind.hpp>
#if LL_WINDOWS
#include "lltimer.h"
#elif LL_LINUX || LL_SOLARIS
#include <sys/time.h>
#include <sched.h>
#include "lltimer.h"
#elif LL_DARWIN
#include <sys/time.h>
#include "lltimer.h" // get_clock_count()
#else
#error "architecture not supported"
#endif
//////////////////////////////////////////////////////////////////////////////
// statics
S32 LLFastTimer::sCurFrameIndex = -1;
S32 LLFastTimer::sLastFrameIndex = -1;
U64 LLFastTimer::sLastFrameTime = LLFastTimer::getCPUClockCount64();
bool LLFastTimer::sPauseHistory = 0;
bool LLFastTimer::sResetHistory = 0;
LLFastTimer::CurTimerData LLFastTimer::sCurTimerData;
BOOL LLFastTimer::sLog = FALSE;
std::string LLFastTimer::sLogName = "";
BOOL LLFastTimer::sMetricLog = FALSE;
LLMutex* LLFastTimer::sLogLock = NULL;
std::queue<LLSD> LLFastTimer::sLogQueue;
#define USE_RDTSC 0
#if LL_LINUX || LL_SOLARIS
U64 LLFastTimer::sClockResolution = 1000000000; // Nanosecond resolution
#else
U64 LLFastTimer::sClockResolution = 1000000; // Microsecond resolution
#endif
std::vector<LLFastTimer::FrameState>* LLFastTimer::sTimerInfos = NULL;
U64 LLFastTimer::sTimerCycles = 0;
U32 LLFastTimer::sTimerCalls = 0;
// FIXME: move these declarations to the relevant modules
// helper functions
typedef LLTreeDFSPostIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_bottom_up_iterator_t;
static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(LLFastTimer::NamedTimer& id)
{
return timer_tree_bottom_up_iterator_t(&id,
boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1),
boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1));
}
static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up()
{
return timer_tree_bottom_up_iterator_t();
}
typedef LLTreeDFSIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_dfs_iterator_t;
static timer_tree_dfs_iterator_t begin_timer_tree(LLFastTimer::NamedTimer& id)
{
return timer_tree_dfs_iterator_t(&id,
boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1),
boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1));
}
static timer_tree_dfs_iterator_t end_timer_tree()
{
return timer_tree_dfs_iterator_t();
}
// factory class that creates NamedTimers via static DeclareTimer objects
class NamedTimerFactory : public LLSingleton<NamedTimerFactory>
{
public:
NamedTimerFactory()
: mActiveTimerRoot(NULL),
mTimerRoot(NULL),
mAppTimer(NULL),
mRootFrameState(NULL)
{}
/*virtual */ void initSingleton()
{
mTimerRoot = new LLFastTimer::NamedTimer("root");
mActiveTimerRoot = new LLFastTimer::NamedTimer("Frame");
mActiveTimerRoot->setCollapsed(false);
mRootFrameState = new LLFastTimer::FrameState(mActiveTimerRoot);
mRootFrameState->mParent = &mTimerRoot->getFrameState();
mActiveTimerRoot->setParent(mTimerRoot);
mAppTimer = new LLFastTimer(mRootFrameState);
}
~NamedTimerFactory()
{
std::for_each(mTimers.begin(), mTimers.end(), DeletePairedPointer());
delete mAppTimer;
delete mActiveTimerRoot;
delete mTimerRoot;
delete mRootFrameState;
}
LLFastTimer::NamedTimer& createNamedTimer(const std::string& name)
{
timer_map_t::iterator found_it = mTimers.find(name);
if (found_it != mTimers.end())
{
return *found_it->second;
}
LLFastTimer::NamedTimer* timer = new LLFastTimer::NamedTimer(name);
timer->setParent(mTimerRoot);
mTimers.insert(std::make_pair(name, timer));
return *timer;
}
LLFastTimer::NamedTimer* getTimerByName(const std::string& name)
{
timer_map_t::iterator found_it = mTimers.find(name);
if (found_it != mTimers.end())
{
return found_it->second;
}
return NULL;
}
LLFastTimer::NamedTimer* getActiveRootTimer() { return mActiveTimerRoot; }
LLFastTimer::NamedTimer* getRootTimer() { return mTimerRoot; }
const LLFastTimer* getAppTimer() { return mAppTimer; }
LLFastTimer::FrameState& getRootFrameState() { return *mRootFrameState; }
typedef std::map<std::string, LLFastTimer::NamedTimer*> timer_map_t;
timer_map_t::iterator beginTimers() { return mTimers.begin(); }
timer_map_t::iterator endTimers() { return mTimers.end(); }
S32 timerCount() { return mTimers.size(); }
private:
timer_map_t mTimers;
LLFastTimer::NamedTimer* mActiveTimerRoot;
LLFastTimer::NamedTimer* mTimerRoot;
LLFastTimer* mAppTimer;
LLFastTimer::FrameState* mRootFrameState;
};
void update_cached_pointers_if_changed()
{
// detect when elements have moved and update cached pointers
static LLFastTimer::FrameState* sFirstTimerAddress = NULL;
if (&*(LLFastTimer::getFrameStateList().begin()) != sFirstTimerAddress)
{
LLFastTimer::DeclareTimer::updateCachedPointers();
}
sFirstTimerAddress = &*(LLFastTimer::getFrameStateList().begin());
}
LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open )
: mTimer(NamedTimerFactory::instance().createNamedTimer(name))
{
mTimer.setCollapsed(!open);
mFrameState = &mTimer.getFrameState();
update_cached_pointers_if_changed();
}
LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name)
: mTimer(NamedTimerFactory::instance().createNamedTimer(name))
{
mFrameState = &mTimer.getFrameState();
update_cached_pointers_if_changed();
}
// static
void LLFastTimer::DeclareTimer::updateCachedPointers()
{
// propagate frame state pointers to timer declarations
for (instance_iter it = beginInstances(); it != endInstances(); ++it)
{
// update cached pointer
it->mFrameState = &it->mTimer.getFrameState();
}
// also update frame states of timers on stack
LLFastTimer* cur_timerp = LLFastTimer::sCurTimerData.mCurTimer;
while(cur_timerp->mLastTimerData.mCurTimer != cur_timerp)
{
cur_timerp->mFrameState = &cur_timerp->mFrameState->mTimer->getFrameState();
cur_timerp = cur_timerp->mLastTimerData.mCurTimer;
}
}
//static
#if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
{
return sClockResolution >> 8;
}
#else // windows or x86-mac or x86-linux or x86-solaris
U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
{
#if USE_RDTSC || !LL_WINDOWS
//getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency()*1000000.0);
// we drop the low-order byte in our timers, so report a lower frequency
#else
// If we're not using RDTSC, each fasttimer tick is just a performance counter tick.
// Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency())
// since that would change displayed MHz stats for CPUs
static bool firstcall = true;
static U64 sCPUClockFrequency;
if (firstcall)
{
QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency);
firstcall = false;
}
#endif
return sCPUClockFrequency >> 8;
}
#endif
LLFastTimer::FrameState::FrameState(LLFastTimer::NamedTimer* timerp)
: mActiveCount(0),
mCalls(0),
mSelfTimeCounter(0),
mParent(NULL),
mLastCaller(NULL),
mMoveUpTree(false),
mTimer(timerp)
{}
LLFastTimer::NamedTimer::NamedTimer(const std::string& name)
: mName(name),
mCollapsed(true),
mParent(NULL),
mTotalTimeCounter(0),
mCountAverage(0),
mCallAverage(0),
mNeedsSorting(false)
{
info_list_t& frame_state_list = getFrameStateList();
mFrameStateIndex = frame_state_list.size();
getFrameStateList().push_back(FrameState(this));
mCountHistory = new U32[HISTORY_NUM];
memset(mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
mCallHistory = new U32[HISTORY_NUM];
memset(mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
}
LLFastTimer::NamedTimer::~NamedTimer()
{
delete[] mCountHistory;
delete[] mCallHistory;
}
std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx)
{
F64 ms_multiplier = 1000.0 / (F64)LLFastTimer::countsPerSecond();
if (history_idx < 0)
{
// by default, show average number of call
return llformat("%s (%.2f ms, %d calls)", getName().c_str(), (F32)((F32)getCountAverage() * ms_multiplier), (S32)getCallAverage());
}
else
{
return llformat("%s (%.2f ms, %d calls)", getName().c_str(), (F32)((F32)getHistoricalCount(history_idx) * ms_multiplier), (S32)getHistoricalCalls(history_idx));
}
}
void LLFastTimer::NamedTimer::setParent(NamedTimer* parent)
{
llassert_always(parent != this);
llassert_always(parent != NULL);
if (mParent)
{
// subtract our accumulated from previous parent
for (S32 i = 0; i < HISTORY_NUM; i++)
{
mParent->mCountHistory[i] -= mCountHistory[i];
}
// subtract average timing from previous parent
mParent->mCountAverage -= mCountAverage;
std::vector<NamedTimer*>& children = mParent->getChildren();
std::vector<NamedTimer*>::iterator found_it = std::find(children.begin(), children.end(), this);
if (found_it != children.end())
{
children.erase(found_it);
}
}
mParent = parent;
if (parent)
{
getFrameState().mParent = &parent->getFrameState();
parent->getChildren().push_back(this);
parent->mNeedsSorting = true;
}
}
S32 LLFastTimer::NamedTimer::getDepth()
{
S32 depth = 0;
NamedTimer* timerp = mParent;
while(timerp)
{
depth++;
timerp = timerp->mParent;
}
return depth;
}
// static
void LLFastTimer::NamedTimer::processTimes()
{
if (sCurFrameIndex < 0) return;
buildHierarchy();
accumulateTimings();
}
// sort timer info structs by depth first traversal order
struct SortTimersDFS
{
bool operator()(const LLFastTimer::FrameState& i1, const LLFastTimer::FrameState& i2)
{
return i1.mTimer->getFrameStateIndex() < i2.mTimer->getFrameStateIndex();
}
};
// sort child timers by name
struct SortTimerByName
{
bool operator()(const LLFastTimer::NamedTimer* i1, const LLFastTimer::NamedTimer* i2)
{
return i1->getName() < i2->getName();
}
};
//static
void LLFastTimer::NamedTimer::buildHierarchy()
{
if (sCurFrameIndex < 0 ) return;
// set up initial tree
{
for (instance_iter it = beginInstances(); it != endInstances(); ++it)
{
NamedTimer& timer = *it;
if (&timer == NamedTimerFactory::instance().getRootTimer()) continue;
// bootstrap tree construction by attaching to last timer to be on stack
// when this timer was called
if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer())
{
timer.setParent(timer.getFrameState().mLastCaller->mTimer);
// no need to push up tree on first use, flag can be set spuriously
timer.getFrameState().mMoveUpTree = false;
}
}
}
// bump timers up tree if they've been flagged as being in the wrong place
// do this in a bottom up order to promote descendants first before promoting ancestors
// this preserves partial order derived from current frame's observations
for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getRootTimer());
it != end_timer_tree_bottom_up();
++it)
{
NamedTimer* timerp = *it;
// skip root timer
if (timerp == NamedTimerFactory::instance().getRootTimer()) continue;
if (timerp->getFrameState().mMoveUpTree)
{
// since ancestors have already been visited, reparenting won't affect tree traversal
//step up tree, bringing our descendants with us
//llinfos << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() <<
// " to child of " << timerp->getParent()->getParent()->getName() << llendl;
timerp->setParent(timerp->getParent()->getParent());
timerp->getFrameState().mMoveUpTree = false;
// don't bubble up any ancestors until descendants are done bubbling up
it.skipAncestors();
}
}
// sort timers by time last called, so call graph makes sense
for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer());
it != end_timer_tree();
++it)
{
NamedTimer* timerp = (*it);
if (timerp->mNeedsSorting)
{
std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName());
}
timerp->mNeedsSorting = false;
}
}
//static
void LLFastTimer::NamedTimer::accumulateTimings()
{
U32 cur_time = getCPUClockCount32();
// walk up stack of active timers and accumulate current time while leaving timing structures active
LLFastTimer* cur_timer = sCurTimerData.mCurTimer;
// root defined by parent pointing to self
CurTimerData* cur_data = &sCurTimerData;
while(cur_timer->mLastTimerData.mCurTimer != cur_timer)
{
U32 cumulative_time_delta = cur_time - cur_timer->mStartTime;
U32 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
cur_data->mChildTime = 0;
cur_timer->mFrameState->mSelfTimeCounter += self_time_delta;
cur_timer->mStartTime = cur_time;
cur_data = &cur_timer->mLastTimerData;
cur_data->mChildTime += cumulative_time_delta;
cur_timer = cur_timer->mLastTimerData.mCurTimer;
}
// traverse tree in DFS post order, or bottom up
for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getActiveRootTimer());
it != end_timer_tree_bottom_up();
++it)
{
NamedTimer* timerp = (*it);
timerp->mTotalTimeCounter = timerp->getFrameState().mSelfTimeCounter;
for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
{
timerp->mTotalTimeCounter += (*child_it)->mTotalTimeCounter;
}
S32 cur_frame = sCurFrameIndex;
if (cur_frame >= 0)
{
// update timer history
int hidx = cur_frame % HISTORY_NUM;
timerp->mCountHistory[hidx] = timerp->mTotalTimeCounter;
timerp->mCountAverage = ((U64)timerp->mCountAverage * cur_frame + timerp->mTotalTimeCounter) / (cur_frame+1);
timerp->mCallHistory[hidx] = timerp->getFrameState().mCalls;
timerp->mCallAverage = ((U64)timerp->mCallAverage * cur_frame + timerp->getFrameState().mCalls) / (cur_frame+1);
}
}
}
U32 LLFastTimer::NamedTimer::getCountAverage() const
{
return mCountAverage;// (sCurFrameIndex <= 0 || mCountAverage <= 0) ? 0 : mCountAverage / llmin(sCurFrameIndex,(S32)HISTORY_NUM);
}
U32 LLFastTimer::NamedTimer::getCallAverage() const
{
return mCallAverage;// (sCurFrameIndex <= 0 || mCallAverage <= 0) ? 0 : mCallAverage / llmin(sCurFrameIndex,(S32)HISTORY_NUM);
}
// static
void LLFastTimer::NamedTimer::resetFrame()
{
if (sLog)
{ //output current frame counts to performance log
static S32 call_count = 0;
if (call_count % 100 == 0)
{
llinfos << "countsPerSecond (32 bit): " << countsPerSecond() << llendl;
llinfos << "get_clock_count (64 bit): " << get_clock_count() << llendl;
llinfos << "LLProcessorInfo().getCPUFrequency() " << LLProcessorInfo().getCPUFrequency() << llendl;
llinfos << "getCPUClockCount32() " << getCPUClockCount32() << llendl;
llinfos << "getCPUClockCount64() " << getCPUClockCount64() << llendl;
llinfos << "elapsed sec " << ((F64)getCPUClockCount64())/((F64)LLProcessorInfo().getCPUFrequency()*1000000.0) << llendl;
}
call_count++;
F64 iclock_freq = 1000.0 / countsPerSecond(); // good place to calculate clock frequency
F64 total_time = 0;
LLSD sd;
{
for (instance_iter it = beginInstances(); it != endInstances(); ++it)
{
NamedTimer& timer = *it;
FrameState& info = timer.getFrameState();
sd[timer.getName()]["Time"] = (LLSD::Real) (info.mSelfTimeCounter*iclock_freq);
sd[timer.getName()]["Calls"] = (LLSD::Integer) info.mCalls;
// computing total time here because getting the root timer's getCountHistory
// doesn't work correctly on the first frame
total_time = total_time + info.mSelfTimeCounter * iclock_freq;
}
}
sd["Total"]["Time"] = (LLSD::Real) total_time;
sd["Total"]["Calls"] = (LLSD::Integer) 1;
{
LLMutexLock lock(sLogLock);
sLogQueue.push(sd);
}
}
// tag timers by position in depth first traversal of tree
S32 index = 0;
for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer());
it != end_timer_tree();
++it)
{
NamedTimer* timerp = (*it);
timerp->mFrameStateIndex = index;
index++;
llassert_always(timerp->mFrameStateIndex < (S32)getFrameStateList().size());
}
// sort timers by DFS traversal order to improve cache coherency
std::sort(getFrameStateList().begin(), getFrameStateList().end(), SortTimersDFS());
// update pointers into framestatelist now that we've sorted it
DeclareTimer::updateCachedPointers();
// reset for next frame
{
for (instance_iter it = beginInstances(); it != endInstances(); ++it)
{
NamedTimer& timer = *it;
FrameState& info = timer.getFrameState();
info.mSelfTimeCounter = 0;
info.mCalls = 0;
info.mLastCaller = NULL;
info.mMoveUpTree = false;
// update parent pointer in timer state struct
if (timer.mParent)
{
info.mParent = &timer.mParent->getFrameState();
}
}
}
//sTimerCycles = 0;
//sTimerCalls = 0;
}
//static
void LLFastTimer::NamedTimer::reset()
{
resetFrame(); // reset frame data
// walk up stack of active timers and reset start times to current time
// effectively zeroing out any accumulated time
U32 cur_time = getCPUClockCount32();
// root defined by parent pointing to self
CurTimerData* cur_data = &sCurTimerData;
LLFastTimer* cur_timer = cur_data->mCurTimer;
while(cur_timer->mLastTimerData.mCurTimer != cur_timer)
{
cur_timer->mStartTime = cur_time;
cur_data->mChildTime = 0;
cur_data = &cur_timer->mLastTimerData;
cur_timer = cur_data->mCurTimer;
}
// reset all history
{
for (instance_iter it = beginInstances(); it != endInstances(); ++it)
{
NamedTimer& timer = *it;
if (&timer != NamedTimerFactory::instance().getRootTimer())
{
timer.setParent(NamedTimerFactory::instance().getRootTimer());
}
timer.mCountAverage = 0;
timer.mCallAverage = 0;
memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
}
}
sLastFrameIndex = 0;
sCurFrameIndex = 0;
}
//static
LLFastTimer::info_list_t& LLFastTimer::getFrameStateList()
{
if (!sTimerInfos)
{
sTimerInfos = new info_list_t();
}
return *sTimerInfos;
}
U32 LLFastTimer::NamedTimer::getHistoricalCount(S32 history_index) const
{
S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM;
return mCountHistory[history_idx];
}
U32 LLFastTimer::NamedTimer::getHistoricalCalls(S32 history_index ) const
{
S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM;
return mCallHistory[history_idx];
}
LLFastTimer::FrameState& LLFastTimer::NamedTimer::getFrameState() const
{
llassert_always(mFrameStateIndex >= 0);
if (this == NamedTimerFactory::instance().getActiveRootTimer())
{
return NamedTimerFactory::instance().getRootFrameState();
}
return getFrameStateList()[mFrameStateIndex];
}
// static
LLFastTimer::NamedTimer& LLFastTimer::NamedTimer::getRootNamedTimer()
{
return *NamedTimerFactory::instance().getActiveRootTimer();
}
std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::beginChildren()
{
return mChildren.begin();
}
std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::endChildren()
{
return mChildren.end();
}
std::vector<LLFastTimer::NamedTimer*>& LLFastTimer::NamedTimer::getChildren()
{
return mChildren;
}
//static
void LLFastTimer::nextFrame()
{
countsPerSecond(); // good place to calculate clock frequency
U64 frame_time = getCPUClockCount64();
if ((frame_time - sLastFrameTime) >> 8 > 0xffffffff)
{
llinfos << "Slow frame, fast timers inaccurate" << llendl;
}
if (!sPauseHistory)
{
NamedTimer::processTimes();
sLastFrameIndex = sCurFrameIndex++;
}
// get ready for next frame
NamedTimer::resetFrame();
sLastFrameTime = frame_time;
}
//static
void LLFastTimer::dumpCurTimes()
{
// accumulate timings, etc.
NamedTimer::processTimes();
F64 clock_freq = (F64)countsPerSecond();
F64 iclock_freq = 1000.0 / clock_freq; // clock_ticks -> milliseconds
// walk over timers in depth order and output timings
for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer());
it != end_timer_tree();
++it)
{
NamedTimer* timerp = (*it);
F64 total_time_ms = ((F64)timerp->getHistoricalCount(0) * iclock_freq);
// Don't bother with really brief times, keep output concise
if (total_time_ms < 0.1) continue;
std::ostringstream out_str;
for (S32 i = 0; i < timerp->getDepth(); i++)
{
out_str << "\t";
}
out_str << timerp->getName() << " "
<< std::setprecision(3) << total_time_ms << " ms, "
<< timerp->getHistoricalCalls(0) << " calls";
llinfos << out_str.str() << llendl;
}
}
//static
void LLFastTimer::reset()
{
NamedTimer::reset();
}
//static
void LLFastTimer::writeLog(std::ostream& os)
{
while (!sLogQueue.empty())
{
LLSD& sd = sLogQueue.front();
LLSDSerialize::toXML(sd, os);
LLMutexLock lock(sLogLock);
sLogQueue.pop();
}
}
//static
const LLFastTimer::NamedTimer* LLFastTimer::getTimerByName(const std::string& name)
{
return NamedTimerFactory::instance().getTimerByName(name);
}
LLFastTimer::LLFastTimer(LLFastTimer::FrameState* state)
: mFrameState(state)
{
U32 start_time = getCPUClockCount32();
mStartTime = start_time;
mFrameState->mActiveCount++;
LLFastTimer::sCurTimerData.mCurTimer = this;
LLFastTimer::sCurTimerData.mFrameState = mFrameState;
LLFastTimer::sCurTimerData.mChildTime = 0;
mLastTimerData = LLFastTimer::sCurTimerData;
}
//////////////////////////////////////////////////////////////////////////////
//
// Important note: These implementations must be FAST!
//
//LL_COMMON_API U64 get_clock_count(); // in lltimer.cpp
// These use QueryPerformanceCounter, which is arguably fine and also works on AMD architectures.
U32 LLFastTimer::getCPUClockCount32()
{
return (U32)(get_clock_count()>>8);
}
U64 LLFastTimer::getCPUClockCount64()
{
return get_clock_count();
}
#if LL_WINDOWS
std::string LLFastTimer::sClockType = "QueryPerformanceCounter";
#else
std::string LLFastTimer::sClockType = "gettimeofday";
#endif

View File

@@ -0,0 +1,277 @@
/**
* @file llfasttimer_class.h
* @brief Declaration of a fast timer.
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_FASTTIMER_CLASS_H
#define LL_FASTTIMER_CLASS_H
#include "llinstancetracker.h"
#define FAST_TIMER_ON 1
#define TIME_FAST_TIMERS 0
#define DEBUG_FAST_TIMER_THREADS 1
class LLMutex;
#include <queue>
#include "llsd.h"
LL_COMMON_API void assert_main_thread();
class LL_COMMON_API LLFastTimer
{
public:
class NamedTimer;
struct LL_COMMON_API FrameState
{
FrameState(NamedTimer* timerp);
U32 mSelfTimeCounter;
U32 mCalls;
FrameState* mParent; // info for caller timer
FrameState* mLastCaller; // used to bootstrap tree construction
NamedTimer* mTimer;
U16 mActiveCount; // number of timers with this ID active on stack
bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
};
// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
class LL_COMMON_API NamedTimer
: public LLInstanceTracker<NamedTimer>
{
friend class DeclareTimer;
public:
~NamedTimer();
enum { HISTORY_NUM = 300 };
const std::string& getName() const { return mName; }
NamedTimer* getParent() const { return mParent; }
void setParent(NamedTimer* parent);
S32 getDepth();
std::string getToolTip(S32 history_index = -1);
typedef std::vector<NamedTimer*>::const_iterator child_const_iter;
child_const_iter beginChildren();
child_const_iter endChildren();
std::vector<NamedTimer*>& getChildren();
void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
bool getCollapsed() const { return mCollapsed; }
U32 getCountAverage() const; //{ return mCountAverage }
U32 getCallAverage() const; //{ return mCallAverage }
U32 getHistoricalCount(S32 history_index = 0) const;
U32 getHistoricalCalls(S32 history_index = 0) const;
static NamedTimer& getRootNamedTimer();
S32 getFrameStateIndex() const { return mFrameStateIndex; }
FrameState& getFrameState() const;
private:
friend class LLFastTimer;
friend class NamedTimerFactory;
//
// methods
//
NamedTimer(const std::string& name);
// recursive call to gather total time from children
static void accumulateTimings();
// updates cumulative times and hierarchy,
// can be called multiple times in a frame, at any point
static void processTimes();
static void buildHierarchy();
static void resetFrame();
static void reset();
//
// members
//
S32 mFrameStateIndex;
std::string mName;
U32 mTotalTimeCounter;
U32 mCountAverage;
U32 mCallAverage;
U32* mCountHistory;
U32* mCallHistory;
// tree structure
NamedTimer* mParent; // NamedTimer of caller(parent)
std::vector<NamedTimer*> mChildren;
bool mCollapsed; // don't show children
bool mNeedsSorting; // sort children whenever child added
};
// used to statically declare a new named timer
class LL_COMMON_API DeclareTimer
: public LLInstanceTracker<DeclareTimer>
{
friend class LLFastTimer;
public:
DeclareTimer(const std::string& name, bool open);
DeclareTimer(const std::string& name);
static void updateCachedPointers();
private:
NamedTimer& mTimer;
FrameState* mFrameState;
};
public:
LLFastTimer(LLFastTimer::FrameState* state);
LL_FORCE_INLINE LLFastTimer(LLFastTimer::DeclareTimer& timer)
: mFrameState(timer.mFrameState)
{
#if TIME_FAST_TIMERS
U64 timer_start = getCPUClockCount64();
#endif
#if FAST_TIMER_ON
LLFastTimer::FrameState* frame_state = mFrameState;
mStartTime = getCPUClockCount32();
frame_state->mActiveCount++;
frame_state->mCalls++;
// keep current parent as long as it is active when we are
frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0);
LLFastTimer::CurTimerData* cur_timer_data = &LLFastTimer::sCurTimerData;
mLastTimerData = *cur_timer_data;
cur_timer_data->mCurTimer = this;
cur_timer_data->mFrameState = frame_state;
cur_timer_data->mChildTime = 0;
#endif
#if TIME_FAST_TIMERS
U64 timer_end = getCPUClockCount64();
sTimerCycles += timer_end - timer_start;
#endif
#if DEBUG_FAST_TIMER_THREADS
#if !LL_RELEASE
assert_main_thread();
#endif
#endif
}
LL_FORCE_INLINE ~LLFastTimer()
{
#if TIME_FAST_TIMERS
U64 timer_start = getCPUClockCount64();
#endif
#if FAST_TIMER_ON
LLFastTimer::FrameState* frame_state = mFrameState;
U32 total_time = getCPUClockCount32() - mStartTime;
frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime;
frame_state->mActiveCount--;
// store last caller to bootstrap tree creation
// do this in the destructor in case of recursion to get topmost caller
frame_state->mLastCaller = mLastTimerData.mFrameState;
// we are only tracking self time, so subtract our total time delta from parents
mLastTimerData.mChildTime += total_time;
LLFastTimer::sCurTimerData = mLastTimerData;
#endif
#if TIME_FAST_TIMERS
U64 timer_end = getCPUClockCount64();
sTimerCycles += timer_end - timer_start;
sTimerCalls++;
#endif
}
public:
static LLMutex* sLogLock;
static std::queue<LLSD> sLogQueue;
static BOOL sLog;
static BOOL sMetricLog;
static std::string sLogName;
static bool sPauseHistory;
static bool sResetHistory;
static U64 sTimerCycles;
static U32 sTimerCalls;
typedef std::vector<FrameState> info_list_t;
static info_list_t& getFrameStateList();
// call this once a frame to reset timers
static void nextFrame();
// dumps current cumulative frame stats to log
// call nextFrame() to reset timers
static void dumpCurTimes();
// call this to reset timer hierarchy, averages, etc.
static void reset();
static U64 countsPerSecond();
static S32 getLastFrameIndex() { return sLastFrameIndex; }
static S32 getCurFrameIndex() { return sCurFrameIndex; }
static void writeLog(std::ostream& os);
static const NamedTimer* getTimerByName(const std::string& name);
struct CurTimerData
{
LLFastTimer* mCurTimer;
FrameState* mFrameState;
U32 mChildTime;
};
static CurTimerData sCurTimerData;
static std::string sClockType;
public:
static U32 getCPUClockCount32();
static U64 getCPUClockCount64();
static U64 sClockResolution;
private:
static S32 sCurFrameIndex;
static S32 sLastFrameIndex;
static U64 sLastFrameTime;
static info_list_t* sTimerInfos;
U32 mStartTime;
LLFastTimer::FrameState* mFrameState;
LLFastTimer::CurTimerData mLastTimerData;
};
typedef class LLFastTimer LLFastTimer;
#endif // LL_LLFASTTIMER_H

View File

@@ -35,56 +35,59 @@
#include "u64.h" #include "u64.h"
#include "llframetimer.h" #include "llframetimer.h"
#include "aiframetimer.h"
#include "llaprpool.h"
// Local constants. // Local constants.
static F64 const USEC_PER_SECOND = 1000000.0; static F64 const USEC_PER_SECOND = 1000000.0;
static F64 const USEC_TO_SEC_F64 = 0.000001; static F64 const USEC_TO_SEC_F64 = 0.000001;
static F64 const NEVER = 1e16;
// Static members // Static members
U64 const LLFrameTimer::sStartTotalTime = totalTime(); // Application start in microseconds since epoch. U64 const LLFrameTimer::sStartTotalTime = totalTime(); // Application start in microseconds since epoch.
U64 LLFrameTimer::sTotalTime = LLFrameTimer::sStartTotalTime; // Current time in microseconds since epoch, updated at least once per frame. U64 LLFrameTimer::sTotalTime = LLFrameTimer::sStartTotalTime; // Current time in microseconds since epoch, updated at least once per frame.
F64 LLFrameTimer::sTotalSeconds = // Current time in seconds since epoch, updated together with LLFrameTimer::sTotalTime. F64 LLFrameTimer::sTotalSeconds = // Current time in seconds since epoch, updated together with LLFrameTimer::sTotalTime.
U64_to_F64(LLFrameTimer::sTotalTime) * USEC_TO_SEC_F64; U64_to_F64(LLFrameTimer::sTotalTime) * USEC_TO_SEC_F64;
F64 LLFrameTimer::sFrameTime = 0.0; // Current time in seconds since application start, updated together with LLFrameTimer::sTotalTime. F64 LLFrameTimer::sFrameTime = 0.0; // Current time in seconds since application start, updated together with LLFrameTimer::sTotalTime.
// Updated exactly once per frame: // Updated exactly once per frame:
S32 LLFrameTimer::sFrameCount = 0; // Current frame number (number of frames since application start). S32 LLFrameTimer::sFrameCount = 0; // Current frame number (number of frames since application start).
U64 LLFrameTimer::sPrevTotalTime = LLFrameTimer::sStartTotalTime; // Previous (frame) time in microseconds since epoch, updated once per frame. U64 LLFrameTimer::sPrevTotalTime = LLFrameTimer::sStartTotalTime; // Previous (frame) time in microseconds since epoch, updated once per frame.
U64 LLFrameTimer::sFrameDeltaTime = 0; // Microseconds between last two calls to LLFrameTimer::updateFrameTimeAndCount. U64 LLFrameTimer::sFrameDeltaTime = 0; // Microseconds between last two calls to LLFrameTimer::updateFrameTimeAndCount.
// Mutex for the above.
apr_thread_mutex_t* LLFrameTimer::sGlobalMutex;
// static // static
void LLFrameTimer::updateFrameTime() void LLFrameTimer::global_initialization(void)
{ {
apr_thread_mutex_create(&sGlobalMutex, APR_THREAD_MUTEX_UNNESTED, LLAPRRootPool::get()());
AIFrameTimer::sNextExpiration = NEVER;
}
// static
void LLFrameTimer::updateFrameTime(void)
{
llassert(is_main_thread());
sTotalTime = totalTime(); sTotalTime = totalTime();
sTotalSeconds = U64_to_F64(sTotalTime) * USEC_TO_SEC_F64; sTotalSeconds = U64_to_F64(sTotalTime) * USEC_TO_SEC_F64;
sFrameTime = U64_to_F64(sTotalTime - sStartTotalTime) * USEC_TO_SEC_F64; F64 new_frame_time = U64_to_F64(sTotalTime - sStartTotalTime) * USEC_TO_SEC_F64;
} apr_thread_mutex_lock(sGlobalMutex);
sFrameTime = new_frame_time;
apr_thread_mutex_unlock(sGlobalMutex);
}
// static // static
void LLFrameTimer::updateFrameTimeAndCount() void LLFrameTimer::updateFrameTimeAndCount(void)
{ {
updateFrameTime(); updateFrameTime();
sFrameDeltaTime = sTotalTime - sPrevTotalTime; sFrameDeltaTime = sTotalTime - sPrevTotalTime;
sPrevTotalTime = sTotalTime; sPrevTotalTime = sTotalTime;
++sFrameCount; ++sFrameCount;
}
void LLFrameTimer::reset(F32 expiration) // Handle AIFrameTimer expiration and callbacks.
{ if (AIFrameTimer::sNextExpiration <= sFrameTime)
llassert(!mPaused); {
mStartTime = sFrameTime; AIFrameTimer::handleExpiration(sFrameTime);
mExpiry = sFrameTime + expiration; }
}
void LLFrameTimer::start(F32 expiration)
{
reset(expiration);
mRunning = true; // Start, if not already started.
}
void LLFrameTimer::stop()
{
llassert(!mPaused);
mRunning = false;
} }
// Don't combine pause/unpause with start/stop // Don't combine pause/unpause with start/stop
@@ -95,38 +98,38 @@ void LLFrameTimer::stop()
// foo.unpause() // unpauses // foo.unpause() // unpauses
// F32 elapsed = foo.getElapsedTimeF32() // does not include time between pause() and unpause() // F32 elapsed = foo.getElapsedTimeF32() // does not include time between pause() and unpause()
// Note: elapsed would also be valid with no unpause() call (= time run until pause() called) // Note: elapsed would also be valid with no unpause() call (= time run until pause() called)
void LLFrameTimer::pause() void LLFrameTimer::pause(void)
{ {
llassert(is_main_thread());
if (!mPaused) if (!mPaused)
{ {
// Only the main thread writes to sFrameTime, so there is no need for locking.
mStartTime = sFrameTime - mStartTime; // Abuse mStartTime to store the elapsed time so far. mStartTime = sFrameTime - mStartTime; // Abuse mStartTime to store the elapsed time so far.
} }
mPaused = true; mPaused = true;
} }
void LLFrameTimer::unpause() void LLFrameTimer::unpause(void)
{ {
llassert(is_main_thread());
if (mPaused) if (mPaused)
{ {
// Only the main thread writes to sFrameTime, so there is no need for locking.
mStartTime = sFrameTime - mStartTime; // Set mStartTime consistent with the elapsed time so far. mStartTime = sFrameTime - mStartTime; // Set mStartTime consistent with the elapsed time so far.
} }
mPaused = false; mPaused = false;
} }
void LLFrameTimer::setTimerExpirySec(F32 expiration)
{
llassert(!mPaused);
mExpiry = mStartTime + expiration;
}
void LLFrameTimer::setExpiryAt(F64 seconds_since_epoch) void LLFrameTimer::setExpiryAt(F64 seconds_since_epoch)
{ {
llassert(is_main_thread());
llassert(!mPaused); llassert(!mPaused);
// Only the main thread writes to sFrameTime, so there is no need for locking.
mStartTime = sFrameTime; mStartTime = sFrameTime;
mExpiry = seconds_since_epoch - (USEC_TO_SEC_F64 * sStartTotalTime); mExpiry = seconds_since_epoch - (USEC_TO_SEC_F64 * sStartTotalTime);
} }
F64 LLFrameTimer::expiresAt() const F64 LLFrameTimer::expiresAt(void) const
{ {
F64 expires_at = U64_to_F64(sStartTotalTime) * USEC_TO_SEC_F64; F64 expires_at = U64_to_F64(sStartTotalTime) * USEC_TO_SEC_F64;
expires_at += mExpiry; expires_at += mExpiry;
@@ -135,31 +138,47 @@ F64 LLFrameTimer::expiresAt() const
bool LLFrameTimer::checkExpirationAndReset(F32 expiration) bool LLFrameTimer::checkExpirationAndReset(F32 expiration)
{ {
if (hasExpired()) llassert(!mPaused);
F64 frame_time = getElapsedSeconds();
if (frame_time >= mExpiry)
{ {
reset(expiration); mStartTime = frame_time;
mExpiry = mStartTime + expiration;
return true; return true;
} }
return false; return false;
} }
// static F32 LLFrameTimer::getElapsedTimeAndResetF32(void)
F32 LLFrameTimer::getFrameDeltaTimeF32()
{ {
llassert(mRunning && !mPaused);
F64 frame_time = getElapsedSeconds();
F32 elapsed_time = (F32)(frame_time - mStartTime);
mExpiry = mStartTime = frame_time;
return elapsed_time;
}
// static
// Return number of seconds between the last two frames.
F32 LLFrameTimer::getFrameDeltaTimeF32(void)
{
llassert(is_main_thread());
// Only the main thread writes to sFrameDeltaTime, so there is no need for locking.
return (F32)(U64_to_F64(sFrameDeltaTime) * USEC_TO_SEC_F64); return (F32)(U64_to_F64(sFrameDeltaTime) * USEC_TO_SEC_F64);
} }
// static
// static
// Return seconds since the current frame started // Return seconds since the current frame started
F32 LLFrameTimer::getCurrentFrameTime() F32 LLFrameTimer::getCurrentFrameTime(void)
{ {
llassert(is_main_thread());
// Only the main thread writes to sTotalTime, so there is no need for locking.
U64 frame_time = totalTime() - sTotalTime; U64 frame_time = totalTime() - sTotalTime;
return (F32)(U64_to_F64(frame_time) * USEC_TO_SEC_F64); return (F32)(U64_to_F64(frame_time) * USEC_TO_SEC_F64);
} }
// Glue code to avoid full class .h file #includes // Glue code to avoid full class .h file #includes
F32 getCurrentFrameTime() F32 getCurrentFrameTime(void)
{ {
return (F32)(LLFrameTimer::getCurrentFrameTime()); return (F32)(LLFrameTimer::getCurrentFrameTime());
} }

View File

@@ -43,88 +43,131 @@
#include "lltimer.h" #include "lltimer.h"
#include "timing.h" #include "timing.h"
#include <apr_thread_mutex.h>
class LL_COMMON_API LLFrameTimer class LL_COMMON_API LLFrameTimer
{ {
public: public:
// Create an LLFrameTimer and start it. After creation it is running and in the state expired (hasExpired will return true). // Create an LLFrameTimer and start it. After creation it is running and in the state expired (hasExpired will return true).
LLFrameTimer(void) : mStartTime(sFrameTime), mExpiry(0), mRunning(true), mPaused(false) { } LLFrameTimer(void) : mExpiry(0), mRunning(true), mPaused(false) { if (!sGlobalMutex) global_initialization(); setAge(0.0); }
// Atomic reads of static variables.
// Return the number of seconds since the start of the application. // Return the number of seconds since the start of the application.
static F64 getElapsedSeconds() static F64 getElapsedSeconds(void)
{ {
// Loses msec precision after ~4.5 hours... // Loses msec precision after ~4.5 hours...
return sFrameTime; apr_thread_mutex_lock(sGlobalMutex);
F64 res = sFrameTime;
apr_thread_mutex_unlock(sGlobalMutex);
return res;
} }
// Return a low precision usec since epoch. // Return a low precision usec since epoch.
static U64 getTotalTime() static U64 getTotalTime(void)
{ {
llassert(sTotalTime); // sTotalTime is only accessed by the main thread, so no locking is necessary.
return sTotalTime; llassert(is_main_thread());
//apr_thread_mutex_lock(sGlobalMutex);
U64 res = sTotalTime;
//apr_thread_mutex_unlock(sGlobalMutex);
llassert(res);
return res;
} }
// Return a low precision seconds since epoch. // Return a low precision seconds since epoch.
static F64 getTotalSeconds() static F64 getTotalSeconds(void)
{ {
return sTotalSeconds; // sTotalSeconds is only accessed by the main thread, so no locking is necessary.
llassert(is_main_thread());
//apr_thread_mutex_lock(sGlobalMutex);
F64 res = sTotalSeconds;
//apr_thread_mutex_unlock(sGlobalMutex);
return res;
}
// Return current frame number (the number of frames since application start).
static U32 getFrameCount(void)
{
// sFrameCount is only accessed by the main thread, so no locking is necessary.
llassert(is_main_thread());
//apr_thread_mutex_lock(sGlobalMutex);
U32 res = sFrameCount;
//apr_thread_mutex_unlock(sGlobalMutex);
return res;
} }
// Call this method once per frame to update the current frame time. // Call this method once per frame to update the current frame time.
// This is actually called at some other times as well. // This is actually called at some other times as well.
static void updateFrameTime(); static void updateFrameTime(void);
// Call this method once, and only once, per frame to update the current frame count and sFrameDeltaTime. // Call this method once, and only once, per frame to update the current frame count and sFrameDeltaTime.
static void updateFrameTimeAndCount(); static void updateFrameTimeAndCount(void);
// Return current frame number (the number of frames since application start).
static U32 getFrameCount() { return sFrameCount; }
// Return duration of last frame in seconds. // Return duration of last frame in seconds.
static F32 getFrameDeltaTimeF32(); static F32 getFrameDeltaTimeF32(void);
// Return seconds since the current frame started // Return seconds since the current frame started
static F32 getCurrentFrameTime(); static F32 getCurrentFrameTime(void);
// MANIPULATORS // MANIPULATORS
void reset(F32 expiration = 0.f); // Same as start() but leaves mRunning off when called after stop(). void reset(F32 expiration = 0.f) // Same as start() but leaves mRunning off when called after stop().
void start(F32 expiration = 0.f); // Reset and (re)start with expiration. {
void stop(); // Stop running. llassert(!mPaused);
mStartTime = getElapsedSeconds();
mExpiry = mStartTime + expiration;
}
void start(F32 expiration = 0.f) // Reset and (re)start with expiration.
{
reset(expiration);
mRunning = true; // Start, if not already started.
}
void stop(void) // Stop running.
{
llassert(!mPaused);
mRunning = false;
}
void pause(); // Mark elapsed time so far. void pause(); // Mark elapsed time so far.
void unpause(); // Move 'start' time in order to decrement time between pause and unpause from ElapsedTime. void unpause(); // Move 'start' time in order to decrement time between pause and unpause from ElapsedTime.
void setTimerExpirySec(F32 expiration); void setTimerExpirySec(F32 expiration) { llassert(!mPaused); mExpiry = mStartTime + expiration; }
void setExpiryAt(F64 seconds_since_epoch); void setExpiryAt(F64 seconds_since_epoch);
bool checkExpirationAndReset(F32 expiration); // Returns true when expired. Only resets if expired. bool checkExpirationAndReset(F32 expiration); // Returns true when expired. Only resets if expired.
F32 getElapsedTimeAndResetF32() { F32 t = getElapsedTimeF32(); reset(); return t; } F32 getElapsedTimeAndResetF32(void);
void setAge(const F64 age) { llassert(!mPaused); mStartTime = sFrameTime - age; } void setAge(const F64 age) { llassert(!mPaused); mStartTime = getElapsedSeconds() - age; }
// ACCESSORS // ACCESSORS
bool hasExpired() const { return sFrameTime >= mExpiry; } bool hasExpired() const { return getElapsedSeconds() >= mExpiry; }
F32 getElapsedTimeF32() const { llassert(mRunning); return mPaused ? (F32)mStartTime : (F32)(sFrameTime - mStartTime); } F32 getElapsedTimeF32() const { llassert(mRunning); return mPaused ? (F32)mStartTime : (F32)(getElapsedSeconds() - mStartTime); }
bool getStarted() const { return mRunning; } bool getStarted() const { return mRunning; }
// return the seconds since epoch when this timer will expire. // return the seconds since epoch when this timer will expire.
F64 expiresAt() const; F64 expiresAt() const;
protected: public:
// A single, high resolution timer that drives all LLFrameTimers // Do one-time initialization of the static members.
// *NOTE: no longer used. static void global_initialization(void);
//static LLTimer sInternalTimer;
protected:
// //
// Aplication constants // Application constants
// //
// Application start in microseconds since epoch. // Application start in microseconds since epoch.
static U64 const sStartTotalTime; static U64 const sStartTotalTime;
// //
// Data updated per frame // Global data.
// //
// More than one thread are accessing (some of) these variables, therefore we need locking.
static apr_thread_mutex_t* sGlobalMutex;
// Current time in seconds since application start, updated together with sTotalTime. // Current time in seconds since application start, updated together with sTotalTime.
static F64 sFrameTime; static F64 sFrameTime;

View File

@@ -194,7 +194,12 @@ public:
} }
protected: protected:
LLInstanceTracker(KEY key) { add_(key); } LLInstanceTracker(KEY key)
{
// make sure static data outlives all instances
getStatic();
add_(key);
}
virtual ~LLInstanceTracker() virtual ~LLInstanceTracker()
{ {
// it's unsafe to delete instances of this type while all instances are being iterated over. // it's unsafe to delete instances of this type while all instances are being iterated over.
@@ -282,7 +287,8 @@ public:
protected: protected:
LLInstanceTracker() LLInstanceTracker()
{ {
// it's safe but unpredictable to create instances of this type while all instances are being iterated over. I hate unpredictable. This assert will probably be turned on early in the next development cycle. // make sure static data outlives all instances
getStatic();
getSet_().insert(static_cast<T*>(this)); getSet_().insert(static_cast<T*>(this));
} }
virtual ~LLInstanceTracker() virtual ~LLInstanceTracker()

View File

@@ -134,4 +134,7 @@ private:
LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b); LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b);
LL_COMMON_API bool operator!=(const LLMD5& a, const LLMD5& b); LL_COMMON_API bool operator!=(const LLMD5& a, const LLMD5& b);
LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b);
LL_COMMON_API bool operator!=(const LLMD5& a, const LLMD5& b);
#endif // LL_LLMD5_H #endif // LL_LLMD5_H

File diff suppressed because it is too large Load Diff

View File

@@ -40,9 +40,6 @@
#endif #endif
#include "llerror.h" #include "llerror.h"
//----------------------------------------------------------------------------
#if LL_DEBUG #if LL_DEBUG
inline void* ll_aligned_malloc( size_t size, int align ) inline void* ll_aligned_malloc( size_t size, int align )
{ {
@@ -120,6 +117,10 @@ inline void ll_aligned_free_32(void *p)
#define ll_aligned_free_32 free #define ll_aligned_free_32 free
#endif // LL_DEBUG #endif // LL_DEBUG
#ifndef __DEBUG_PRIVATE_MEM__
#define __DEBUG_PRIVATE_MEM__ 0
#endif
class LL_COMMON_API LLMemory class LL_COMMON_API LLMemory
{ {
public: public:
@@ -130,10 +131,395 @@ public:
// Return value is zero if not known. // Return value is zero if not known.
static U64 getCurrentRSS(); static U64 getCurrentRSS();
static U32 getWorkingSetSize(); static U32 getWorkingSetSize();
static void* tryToAlloc(void* address, U32 size);
static void initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure);
static void updateMemoryInfo() ;
static void logMemoryInfo(BOOL update = FALSE);
static bool isMemoryPoolLow();
static U32 getAvailableMemKB() ;
static U32 getMaxMemKB() ;
static U32 getAllocatedMemKB() ;
private: private:
static char* reserveMem; static char* reserveMem;
static U32 sAvailPhysicalMemInKB ;
static U32 sMaxPhysicalMemInKB ;
static U32 sAllocatedMemInKB;
static U32 sAllocatedPageSizeInKB ;
static U32 sMaxHeapSizeInKB;
static BOOL sEnableMemoryFailurePrevention;
}; };
//----------------------------------------------------------------------------
class LLMutex ;
#if MEM_TRACK_MEM
class LL_COMMON_API LLMemTracker
{
private:
LLMemTracker() ;
~LLMemTracker() ;
public:
static void release() ;
static LLMemTracker* getInstance() ;
void track(const char* function, const int line) ;
void preDraw(BOOL pause) ;
void postDraw() ;
const char* getNextLine() ;
private:
static LLMemTracker* sInstance ;
char** mStringBuffer ;
S32 mCapacity ;
U32 mLastAllocatedMem ;
S32 mCurIndex ;
S32 mCounter;
S32 mDrawnIndex;
S32 mNumOfDrawn;
BOOL mPaused;
LLMutex* mMutexp ;
};
#define MEM_TRACK_RELEASE LLMemTracker::release() ;
#define MEM_TRACK LLMemTracker::getInstance()->track(__FUNCTION__, __LINE__) ;
#else // MEM_TRACK_MEM
#define MEM_TRACK_RELEASE
#define MEM_TRACK
#endif // MEM_TRACK_MEM
//----------------------------------------------------------------------------
//
//class LLPrivateMemoryPool defines a private memory pool for an application to use, so the application does not
//need to access the heap directly fro each memory allocation. Throught this, the allocation speed is faster,
//and reduces virtaul address space gragmentation problem.
//Note: this class is thread-safe by passing true to the constructor function. However, you do not need to do this unless
//you are sure the memory allocation and de-allocation will happen in different threads. To make the pool thread safe
//increases allocation and deallocation cost.
//
class LL_COMMON_API LLPrivateMemoryPool
{
friend class LLPrivateMemoryPoolManager ;
public:
class LL_COMMON_API LLMemoryBlock //each block is devided into slots uniformly
{
public:
LLMemoryBlock() ;
~LLMemoryBlock() ;
void init(char* buffer, U32 buffer_size, U32 slot_size) ;
void setBuffer(char* buffer, U32 buffer_size) ;
char* allocate() ;
void freeMem(void* addr) ;
bool empty() {return !mAllocatedSlots;}
bool isFull() {return mAllocatedSlots == mTotalSlots;}
bool isFree() {return !mTotalSlots;}
U32 getSlotSize()const {return mSlotSize;}
U32 getTotalSlots()const {return mTotalSlots;}
U32 getBufferSize()const {return mBufferSize;}
char* getBuffer() const {return mBuffer;}
//debug use
void resetBitMap() ;
private:
char* mBuffer;
U32 mSlotSize ; //when the block is not initialized, it is the buffer size.
U32 mBufferSize ;
U32 mUsageBits ;
U8 mTotalSlots ;
U8 mAllocatedSlots ;
U8 mDummySize ; //size of extra bytes reserved for mUsageBits.
public:
LLMemoryBlock* mPrev ;
LLMemoryBlock* mNext ;
LLMemoryBlock* mSelf ;
struct CompareAddress
{
bool operator()(const LLMemoryBlock* const& lhs, const LLMemoryBlock* const& rhs)
{
return (size_t)lhs->getBuffer() < (size_t)rhs->getBuffer();
}
};
};
class LL_COMMON_API LLMemoryChunk //is divided into memory blocks.
{
public:
LLMemoryChunk() ;
~LLMemoryChunk() ;
void init(char* buffer, U32 buffer_size, U32 min_slot_size, U32 max_slot_size, U32 min_block_size, U32 max_block_size) ;
void setBuffer(char* buffer, U32 buffer_size) ;
bool empty() ;
char* allocate(U32 size) ;
void freeMem(void* addr) ;
char* getBuffer() const {return mBuffer;}
U32 getBufferSize() const {return mBufferSize;}
U32 getAllocatedSize() const {return mAlloatedSize;}
bool containsAddress(const char* addr) const;
static U32 getMaxOverhead(U32 data_buffer_size, U32 min_slot_size,
U32 max_slot_size, U32 min_block_size, U32 max_block_size) ;
void dump() ;
private:
U32 getPageIndex(char const* addr) ;
U32 getBlockLevel(U32 size) ;
U16 getPageLevel(U32 size) ;
LLMemoryBlock* addBlock(U32 blk_idx) ;
void popAvailBlockList(U32 blk_idx) ;
void addToFreeSpace(LLMemoryBlock* blk) ;
void removeFromFreeSpace(LLMemoryBlock* blk) ;
void removeBlock(LLMemoryBlock* blk) ;
void addToAvailBlockList(LLMemoryBlock* blk) ;
U32 calcBlockSize(U32 slot_size);
LLMemoryBlock* createNewBlock(LLMemoryBlock* blk, U32 buffer_size, U32 slot_size, U32 blk_idx) ;
private:
LLMemoryBlock** mAvailBlockList ;//256 by mMinSlotSize
LLMemoryBlock** mFreeSpaceList;
LLMemoryBlock* mBlocks ; //index of blocks by address.
char* mBuffer ;
U32 mBufferSize ;
char* mDataBuffer ;
char* mMetaBuffer ;
U32 mMinBlockSize ;
U32 mMinSlotSize ;
U32 mMaxSlotSize ;
U32 mAlloatedSize ;
U16 mBlockLevels;
U16 mPartitionLevels;
public:
//form a linked list
LLMemoryChunk* mNext ;
LLMemoryChunk* mPrev ;
} ;
private:
LLPrivateMemoryPool(S32 type, U32 max_pool_size) ;
~LLPrivateMemoryPool() ;
char *allocate(U32 size) ;
void freeMem(void* addr) ;
void dump() ;
U32 getTotalAllocatedSize() ;
U32 getTotalReservedSize() {return mReservedPoolSize;}
S32 getType() const {return mType; }
bool isEmpty() const {return !mNumOfChunks; }
private:
void lock() ;
void unlock() ;
S32 getChunkIndex(U32 size) ;
LLMemoryChunk* addChunk(S32 chunk_index) ;
bool checkSize(U32 asked_size) ;
void removeChunk(LLMemoryChunk* chunk) ;
U16 findHashKey(const char* addr);
void addToHashTable(LLMemoryChunk* chunk) ;
void removeFromHashTable(LLMemoryChunk* chunk) ;
void rehash() ;
bool fillHashTable(U16 start, U16 end, LLMemoryChunk* chunk) ;
LLMemoryChunk* findChunk(const char* addr) ;
void destroyPool() ;
public:
enum
{
SMALL_ALLOCATION = 0, //from 8 bytes to 2KB(exclusive), page size 2KB, max chunk size is 4MB.
MEDIUM_ALLOCATION, //from 2KB to 512KB(exclusive), page size 32KB, max chunk size 4MB
LARGE_ALLOCATION, //from 512KB to 4MB(inclusive), page size 64KB, max chunk size 16MB
SUPER_ALLOCATION //allocation larger than 4MB.
};
enum
{
STATIC = 0 , //static pool(each alllocation stays for a long time) without threading support
VOLATILE, //Volatile pool(each allocation stays for a very short time) without threading support
STATIC_THREADED, //static pool with threading support
VOLATILE_THREADED, //volatile pool with threading support
MAX_TYPES
}; //pool types
private:
LLMutex* mMutexp ;
U32 mMaxPoolSize;
U32 mReservedPoolSize ;
LLMemoryChunk* mChunkList[SUPER_ALLOCATION] ; //all memory chunks reserved by this pool, sorted by address
U16 mNumOfChunks ;
U16 mHashFactor ;
S32 mType ;
class LLChunkHashElement
{
public:
LLChunkHashElement() {mFirst = NULL ; mSecond = NULL ;}
bool add(LLMemoryChunk* chunk) ;
void remove(LLMemoryChunk* chunk) ;
LLMemoryChunk* findChunk(const char* addr) ;
bool empty() {return !mFirst && !mSecond; }
bool full() {return mFirst && mSecond; }
bool hasElement(LLMemoryChunk* chunk) {return mFirst == chunk || mSecond == chunk;}
private:
LLMemoryChunk* mFirst ;
LLMemoryChunk* mSecond ;
};
std::vector<LLChunkHashElement> mChunkHashList ;
};
class LL_COMMON_API LLPrivateMemoryPoolManager
{
private:
LLPrivateMemoryPoolManager(BOOL enabled, U32 max_pool_size) ;
~LLPrivateMemoryPoolManager() ;
public:
static LLPrivateMemoryPoolManager* getInstance() ;
static void initClass(BOOL enabled, U32 pool_size) ;
static void destroyClass() ;
LLPrivateMemoryPool* newPool(S32 type) ;
void deletePool(LLPrivateMemoryPool* pool) ;
private:
std::vector<LLPrivateMemoryPool*> mPoolList ;
U32 mMaxPrivatePoolSize;
static LLPrivateMemoryPoolManager* sInstance ;
static BOOL sPrivatePoolEnabled;
static std::vector<LLPrivateMemoryPool*> sDanglingPoolList ;
public:
//debug and statistics info.
void updateStatistics() ;
U32 mTotalReservedSize ;
U32 mTotalAllocatedSize ;
public:
#if __DEBUG_PRIVATE_MEM__
static char* allocate(LLPrivateMemoryPool* poolp, U32 size, const char* function, const int line) ;
typedef std::map<char*, std::string> mem_allocation_info_t ;
static mem_allocation_info_t sMemAllocationTracker;
#else
static char* allocate(LLPrivateMemoryPool* poolp, U32 size) ;
#endif
static void freeMem(LLPrivateMemoryPool* poolp, void* addr) ;
};
//-------------------------------------------------------------------------------------
#if __DEBUG_PRIVATE_MEM__
#define ALLOCATE_MEM(poolp, size) LLPrivateMemoryPoolManager::allocate((poolp), (size), __FUNCTION__, __LINE__)
#else
#define ALLOCATE_MEM(poolp, size) LLPrivateMemoryPoolManager::allocate((poolp), (size))
//#define ALLOCATE_MEM(poolp, size) new char[size]
#endif
#define FREE_MEM(poolp, addr) LLPrivateMemoryPoolManager::freeMem((poolp), (addr))
//#define FREE_MEM(poolp, addr) delete[] addr;
//-------------------------------------------------------------------------------------
//
//the below singleton is used to test the private memory pool.
//
#if 0
class LL_COMMON_API LLPrivateMemoryPoolTester
{
private:
LLPrivateMemoryPoolTester() ;
~LLPrivateMemoryPoolTester() ;
public:
static LLPrivateMemoryPoolTester* getInstance() ;
static void destroy() ;
void run(S32 type) ;
private:
void correctnessTest() ;
void performanceTest() ;
void fragmentationtest() ;
void test(U32 min_size, U32 max_size, U32 stride, U32 times, bool random_deletion, bool output_statistics) ;
void testAndTime(U32 size, U32 times) ;
#if 0
public:
void* operator new(size_t size)
{
return (void*)sPool->allocate(size) ;
}
void operator delete(void* addr)
{
sPool->freeMem(addr) ;
}
void* operator new[](size_t size)
{
return (void*)sPool->allocate(size) ;
}
void operator delete[](void* addr)
{
sPool->freeMem(addr) ;
}
#endif
private:
static LLPrivateMemoryPoolTester* sInstance;
static LLPrivateMemoryPool* sPool ;
static LLPrivateMemoryPool* sThreadedPool ;
};
#if 0
//static
void* LLPrivateMemoryPoolTester::operator new(size_t size)
{
return (void*)sPool->allocate(size) ;
}
//static
void LLPrivateMemoryPoolTester::operator delete(void* addr)
{
sPool->free(addr) ;
}
//static
void* LLPrivateMemoryPoolTester::operator new[](size_t size)
{
return (void*)sPool->allocate(size) ;
}
//static
void LLPrivateMemoryPoolTester::operator delete[](void* addr)
{
sPool->free(addr) ;
}
#endif
#endif
//EVENTUALLY REMOVE THESE: //EVENTUALLY REMOVE THESE:
#include "llpointer.h" #include "llpointer.h"
#include "llrefcount.h" #include "llrefcount.h"

102
indra/llcommon/llptrto.cpp Normal file
View File

@@ -0,0 +1,102 @@
/**
* @file llptrto.cpp
* @author Nat Goodspeed
* @date 2008-08-20
* @brief Test for llptrto.h
*
* $LicenseInfo:firstyear=2008&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$
*/
// Precompiled header
#include "linden_common.h"
// associated header
#include "llptrto.h"
// STL headers
// std headers
// external library headers
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
// other Linden headers
#include "llmemory.h"
// a refcounted class
class RCFoo: public LLRefCount
{
public:
RCFoo() {}
};
// a refcounted subclass
class RCSubFoo: public RCFoo
{
public:
RCSubFoo() {}
};
// a refcounted class using the other refcount base class
class TSRCFoo: public LLThreadSafeRefCount
{
public:
TSRCFoo() {}
};
// a non-refcounted class
class Bar
{
public:
Bar() {}
};
// a non-refcounted subclass
class SubBar: public Bar
{
public:
SubBar() {}
};
int main(int argc, char *argv[])
{
// test LLPtrTo<>
BOOST_STATIC_ASSERT((boost::is_same<LLPtrTo<RCFoo>::type, LLPointer<RCFoo> >::value));
BOOST_STATIC_ASSERT((boost::is_same<LLPtrTo<RCSubFoo>::type, LLPointer<RCSubFoo> >::value));
BOOST_STATIC_ASSERT((boost::is_same<LLPtrTo<TSRCFoo>::type, LLPointer<TSRCFoo> >::value));
BOOST_STATIC_ASSERT((boost::is_same<LLPtrTo<Bar>::type, Bar*>::value));
BOOST_STATIC_ASSERT((boost::is_same<LLPtrTo<SubBar>::type, SubBar*>::value));
BOOST_STATIC_ASSERT((boost::is_same<LLPtrTo<int>::type, int*>::value));
// Test LLRemovePointer<>. Note that we remove both pointer variants from
// each kind of type, regardless of whether the variant makes sense.
BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer<RCFoo*>::type, RCFoo>::value));
BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer< LLPointer<RCFoo> >::type, RCFoo>::value));
BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer<RCSubFoo*>::type, RCSubFoo>::value));
BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer< LLPointer<RCSubFoo> >::type, RCSubFoo>::value));
BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer<TSRCFoo*>::type, TSRCFoo>::value));
BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer< LLPointer<TSRCFoo> >::type, TSRCFoo>::value));
BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer<Bar*>::type, Bar>::value));
BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer< LLPointer<Bar> >::type, Bar>::value));
BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer<SubBar*>::type, SubBar>::value));
BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer< LLPointer<SubBar> >::type, SubBar>::value));
BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer<int*>::type, int>::value));
BOOST_STATIC_ASSERT((boost::is_same<LLRemovePointer< LLPointer<int> >::type, int>::value));
return 0;
}

87
indra/llcommon/llptrto.h Normal file
View File

@@ -0,0 +1,87 @@
/**
* @file llptrto.h
* @author Nat Goodspeed
* @date 2008-08-19
* @brief LLPtrTo<TARGET> is a template helper to pick either TARGET* or -- when
* TARGET is a subclass of LLRefCount or LLThreadSafeRefCount --
* LLPointer<TARGET>. LLPtrTo<> chooses whichever pointer type is best.
*
* $LicenseInfo:firstyear=2008&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$
*/
#if ! defined(LL_LLPTRTO_H)
#define LL_LLPTRTO_H
#include "llpointer.h"
#include "llrefcount.h" // LLRefCount
#include "llthread.h" // LLThreadSafeRefCount
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/utility/enable_if.hpp>
/**
* LLPtrTo<TARGET>::type is either of two things:
*
* * When TARGET is a subclass of either LLRefCount or LLThreadSafeRefCount,
* LLPtrTo<TARGET>::type is LLPointer<TARGET>.
* * Otherwise, LLPtrTo<TARGET>::type is TARGET*.
*
* This way, a class template can use LLPtrTo<TARGET>::type to select an
* appropriate pointer type to store.
*/
template <class T, class ENABLE=void>
struct LLPtrTo
{
typedef T* type;
};
/// specialize for subclasses of LLRefCount
template <class T>
struct LLPtrTo<T, typename boost::enable_if< boost::is_base_of<LLRefCount, T> >::type>
{
typedef LLPointer<T> type;
};
/// specialize for subclasses of LLThreadSafeRefCount
template <class T>
struct LLPtrTo<T, typename boost::enable_if< boost::is_base_of<LLThreadSafeRefCount, T> >::type>
{
typedef LLPointer<T> type;
};
/**
* LLRemovePointer<PTRTYPE>::type gets you the underlying (pointee) type.
*/
template <typename PTRTYPE>
struct LLRemovePointer
{
typedef typename boost::remove_pointer<PTRTYPE>::type type;
};
/// specialize for LLPointer<SOMECLASS>
template <typename SOMECLASS>
struct LLRemovePointer< LLPointer<SOMECLASS> >
{
typedef SOMECLASS type;
};
#endif /* ! defined(LL_LLPTRTO_H) */

View File

@@ -38,7 +38,7 @@
//============================================================================ //============================================================================
// MAIN THREAD // MAIN THREAD
LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) : LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) :
LLThread(name), LLThread(name),
mThreaded(threaded), mThreaded(threaded),
mIdleThread(TRUE), mIdleThread(TRUE),
@@ -47,6 +47,11 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) :
{ {
if (mThreaded) if (mThreaded)
{ {
if(should_pause)
{
pause() ; //call this before start the thread.
}
start(); start();
} }
} }

View File

@@ -154,7 +154,7 @@ public:
static handle_t nullHandle() { return handle_t(0); } static handle_t nullHandle() { return handle_t(0); }
public: public:
LLQueuedThread(const std::string& name, bool threaded = true); LLQueuedThread(const std::string& name, bool threaded = true, bool should_pause = false);
virtual ~LLQueuedThread(); virtual ~LLQueuedThread();
virtual void shutdown(); virtual void shutdown();

View File

@@ -39,13 +39,11 @@
#include <iostream> #include <iostream>
#include "apr_base64.h" #include "apr_base64.h"
#if MESH_ENABLED
#ifdef LL_STANDALONE #ifdef LL_STANDALONE
# include <zlib.h> # include <zlib.h>
#else #else
# include "zlib/zlib.h" // for davep's dirty little zip functions # include "zlib/zlib.h" // for davep's dirty little zip functions
#endif #endif
#endif //MESH_ENABLED
#if !LL_WINDOWS #if !LL_WINDOWS
#include <netinet/in.h> // htonl & ntohl #include <netinet/in.h> // htonl & ntohl
@@ -1454,9 +1452,12 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option
} }
case LLSD::TypeUUID: case LLSD::TypeUUID:
{
ostr.put('u'); ostr.put('u');
ostr.write((const char*)(&(data.asUUID().mData)), UUID_BYTES); LLUUID value = data.asUUID();
ostr.write((const char*)(&value.mData), UUID_BYTES);
break; break;
}
case LLSD::TypeString: case LLSD::TypeString:
ostr.put('s'); ostr.put('s');
@@ -1996,8 +1997,6 @@ std::ostream& operator<<(std::ostream& s, const LLSD& llsd)
return s; return s;
} }
#if MESH_ENABLED
//dirty little zippers -- yell at davep if these are horrid //dirty little zippers -- yell at davep if these are horrid
//return a string containing gzipped bytes of binary serialized LLSD //return a string containing gzipped bytes of binary serialized LLSD
@@ -2173,4 +2172,3 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
free(result); free(result);
return true; return true;
} }
#endif //MESH_ENABLED

View File

@@ -788,9 +788,7 @@ public:
} }
}; };
#if MESH_ENABLED
//dirty little zip functions -- yell at davep //dirty little zip functions -- yell at davep
LL_COMMON_API std::string zip_llsd(LLSD& data); LL_COMMON_API std::string zip_llsd(LLSD& data);
LL_COMMON_API bool unzip_llsd(LLSD& data, std::istream& is, S32 size); LL_COMMON_API bool unzip_llsd(LLSD& data, std::istream& is, S32 size);
#endif //MESH_ENABLED
#endif // LL_LLSDSERIALIZE_H #endif // LL_LLSDSERIALIZE_H

View File

@@ -42,17 +42,17 @@ template <class Object> class LLStrider
U8* mBytep; U8* mBytep;
}; };
U32 mSkip; U32 mSkip;
U32 mTypeSize; //U32 mTypeSize;
public: public:
LLStrider() { mObjectp = NULL; mTypeSize = mSkip = sizeof(Object); } LLStrider() { mObjectp = NULL; /*mTypeSize = */mSkip = sizeof(Object); }
~LLStrider() { } ~LLStrider() { }
const LLStrider<Object>& operator = (Object *first) { mObjectp = first; return *this;} const LLStrider<Object>& operator = (Object *first) { mObjectp = first; return *this;}
void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));} void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));}
void setTypeSize (S32 typeBytes){ mTypeSize = (typeBytes ? typeBytes : sizeof(Object)); } //void setTypeSize (S32 typeBytes){ mTypeSize = (typeBytes ? typeBytes : sizeof(Object)); }
bool isStrided() const { return mTypeSize != mSkip; } //bool isStrided() const { return mTypeSize != mSkip; }
void skip(const U32 index) { mBytep += mSkip*index;} void skip(const U32 index) { mBytep += mSkip*index;}
U32 getSkip() const { return mSkip; } U32 getSkip() const { return mSkip; }
Object* get() { return mObjectp; } Object* get() { return mObjectp; }
@@ -61,7 +61,7 @@ public:
Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; } Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; }
Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; } Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; }
Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); } Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); }
void assignArray(U8* __restrict source, const size_t elem_size, const size_t elem_count) /*void assignArray(U8* __restrict source, const size_t elem_size, const size_t elem_count)
{ {
llassert_always(sizeof(Object) <= elem_size); llassert_always(sizeof(Object) <= elem_size);
@@ -125,7 +125,7 @@ public:
source+=elem_size; source+=elem_size;
} }
} }
} }*/
}; };
#endif // LL_LLSTRIDER_H #endif // LL_LLSTRIDER_H

View File

@@ -43,6 +43,9 @@
#include <winnls.h> // for WideCharToMultiByte #include <winnls.h> // for WideCharToMultiByte
#endif #endif
LLFastTimer::DeclareTimer FT_STRING_FORMAT("String Format");
std::string ll_safe_string(const char* in) std::string ll_safe_string(const char* in)
{ {
if(in) return std::string(in); if(in) return std::string(in);
@@ -1196,7 +1199,7 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
template<> template<>
S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions) S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
{ {
LLFastTimer ft(LLFastTimer::FT_STRING_FORMAT); LLFastTimer ft(FT_STRING_FORMAT);
S32 res = 0; S32 res = 0;
std::string output; std::string output;
@@ -1269,7 +1272,7 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
template<> template<>
S32 LLStringUtil::format(std::string& s, const LLSD& substitutions) S32 LLStringUtil::format(std::string& s, const LLSD& substitutions)
{ {
LLFastTimer ft(LLFastTimer::FT_STRING_FORMAT); LLFastTimer ft(FT_STRING_FORMAT);
S32 res = 0; S32 res = 0;
if (!substitutions.isMap()) if (!substitutions.isMap())

View File

@@ -111,7 +111,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
// after the LLCurl::Multi::run() function exits and we actually // after the LLCurl::Multi::run() function exits and we actually
// change this variable (which really SHOULD have been inside // change this variable (which really SHOULD have been inside
// the critical area of the mSignal lock)]. // the critical area of the mSignal lock)].
llinfos << "LLThread::staticRun() Exiting: " << name << llendl; lldebugs << "LLThread::staticRun() Exiting: " << name << llendl;
return NULL; return NULL;
} }

View File

@@ -36,7 +36,7 @@
const S32 LL_VERSION_MAJOR = 1; const S32 LL_VERSION_MAJOR = 1;
const S32 LL_VERSION_MINOR = 6; const S32 LL_VERSION_MINOR = 6;
const S32 LL_VERSION_PATCH = 0; const S32 LL_VERSION_PATCH = 0;
const S32 LL_VERSION_BUILD = 1; const S32 LL_VERSION_BUILD = 3;
const char * const LL_CHANNEL = "Singularity"; const char * const LL_CHANNEL = "Singularity";

View File

@@ -40,8 +40,8 @@
//============================================================================ //============================================================================
// Run on MAIN thread // Run on MAIN thread
LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) : LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) :
LLQueuedThread(name, threaded) LLQueuedThread(name, threaded, should_pause)
{ {
mDeleteMutex = new LLMutex; mDeleteMutex = new LLMutex;
} }

View File

@@ -89,7 +89,7 @@ private:
LLMutex* mDeleteMutex; LLMutex* mDeleteMutex;
public: public:
LLWorkerThread(const std::string& name, bool threaded = true); LLWorkerThread(const std::string& name, bool threaded = true, bool should_pause = false);
~LLWorkerThread(); ~LLWorkerThread();
/*virtual*/ S32 update(U32 max_time_ms); /*virtual*/ S32 update(U32 max_time_ms);

View File

@@ -347,7 +347,7 @@ bool LLCrashLogger::sendCrashLogs()
bool sent = false; bool sent = false;
//*TODO: Translate // *TODO: Translate
if(mCrashHost != "") if(mCrashHost != "")
{ {
sent = runCrashLogPost(mCrashHost, post_data, std::string("Sending to server"), 3, 5); sent = runCrashLogPost(mCrashHost, post_data, std::string("Sending to server"), 3, 5);

View File

@@ -45,6 +45,7 @@
#include "llimagepng.h" #include "llimagepng.h"
#include "llimagedxt.h" #include "llimagedxt.h"
#include "llimageworker.h" #include "llimageworker.h"
#include "llmemory.h"
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// LLImage // LLImage
@@ -53,12 +54,14 @@
//static //static
std::string LLImage::sLastErrorMessage; std::string LLImage::sLastErrorMessage;
LLMutex* LLImage::sMutex = NULL; LLMutex* LLImage::sMutex = NULL;
LLPrivateMemoryPool* LLImageBase::sPrivatePoolp = NULL ;
//static //static
void LLImage::initClass() void LLImage::initClass()
{ {
sMutex = new LLMutex; sMutex = new LLMutex;
LLImageJ2C::openDSO(); LLImageJ2C::openDSO();
LLImageBase::createPrivatePool() ;
} }
//static //static
@@ -67,6 +70,8 @@ void LLImage::cleanupClass()
LLImageJ2C::closeDSO(); LLImageJ2C::closeDSO();
delete sMutex; delete sMutex;
sMutex = NULL; sMutex = NULL;
LLImageBase::destroyPrivatePool() ;
} }
//static //static
@@ -105,6 +110,25 @@ LLImageBase::~LLImageBase()
deleteData(); // virtual deleteData(); // virtual
} }
//static
void LLImageBase::createPrivatePool()
{
if(!sPrivatePoolp)
{
sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC_THREADED) ;
}
}
//static
void LLImageBase::destroyPrivatePool()
{
if(sPrivatePoolp)
{
LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp) ;
sPrivatePoolp = NULL ;
}
}
// virtual // virtual
void LLImageBase::dump() void LLImageBase::dump()
{ {
@@ -138,7 +162,7 @@ void LLImageBase::sanityCheck()
// virtual // virtual
void LLImageBase::deleteData() void LLImageBase::deleteData()
{ {
delete[] mData; FREE_MEM(sPrivatePoolp, mData) ;
mData = NULL; mData = NULL;
mDataSize = 0; mDataSize = 0;
} }
@@ -164,14 +188,14 @@ U8* LLImageBase::allocateData(S32 size)
if (!mData || size != mDataSize) if (!mData || size != mDataSize)
{ {
deleteData(); // virtual deleteData(); // virtual
mBadBufferAllocation = FALSE ; mBadBufferAllocation = false ;
mData = new (std::nothrow) U8[size]; mData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
if (!mData) if (!mData)
{ {
llwarns << "allocate image data: " << size << llendl; llwarns << "allocate image data: " << size << llendl;
size = 0 ; size = 0 ;
mWidth = mHeight = 0 ; mWidth = mHeight = 0 ;
mBadBufferAllocation = TRUE ; mBadBufferAllocation = true ;
} }
mDataSize = size; mDataSize = size;
} }
@@ -186,7 +210,7 @@ U8* LLImageBase::reallocateData(S32 size)
return mData; return mData;
LLMemType mt1((LLMemType::EMemType)mMemType); LLMemType mt1((LLMemType::EMemType)mMemType);
U8 *new_datap = new (std::nothrow) U8[size]; U8 *new_datap = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
if (!new_datap) if (!new_datap)
{ {
llwarns << "Out of memory in LLImageBase::reallocateData" << llendl; llwarns << "Out of memory in LLImageBase::reallocateData" << llendl;
@@ -196,7 +220,7 @@ U8* LLImageBase::reallocateData(S32 size)
{ {
S32 bytes = llmin(mDataSize, size); S32 bytes = llmin(mDataSize, size);
memcpy(new_datap, mData, bytes); /* Flawfinder: ignore */ memcpy(new_datap, mData, bytes); /* Flawfinder: ignore */
delete[] mData; FREE_MEM(sPrivatePoolp, mData) ;
} }
mData = new_datap; mData = new_datap;
mDataSize = size; mDataSize = size;
@@ -276,11 +300,11 @@ LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
++sRawImageCount; ++sRawImageCount;
} }
LLImageRaw::LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only) /*LLImageRaw::LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only)
: LLImageBase(), mCacheEntries(0) : LLImageBase(), mCacheEntries(0)
{ {
createFromFile(filename, j2c_lowest_mip_only); createFromFile(filename, j2c_lowest_mip_only);
} }*/
LLImageRaw::~LLImageRaw() LLImageRaw::~LLImageRaw()
{ {
@@ -346,10 +370,11 @@ BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
return TRUE; return TRUE;
} }
#if 0
U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const
{ {
LLMemType mt1((LLMemType::EMemType)mMemType); LLMemType mt1(mMemType);
U8 *data = new (std::nothrow) U8[width*height*getComponents()]; U8 *data = new U8[width*height*getComponents()];
// Should do some simple bounds checking // Should do some simple bounds checking
if (!data) if (!data)
@@ -366,6 +391,7 @@ U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const
} }
return data; return data;
} }
#endif
BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height, BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
const U8 *data, U32 stride, BOOL reverse_y) const U8 *data, U32 stride, BOOL reverse_y)
@@ -856,11 +882,11 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
delete[] temp_buffer; delete[] temp_buffer;
} }
#if 0
//scale down image by not blending a pixel with its neighbors. //scale down image by not blending a pixel with its neighbors.
BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height) BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height)
{ {
LLMemType mt1((LLMemType::EMemType)mMemType); LLMemType mt1(mMemType);
S8 c = getComponents() ; S8 c = getComponents() ;
llassert((1 == c) || (3 == c) || (4 == c) ); llassert((1 == c) || (3 == c) || (4 == c) );
@@ -880,7 +906,7 @@ BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height)
ratio_x -= 1.0f ; ratio_x -= 1.0f ;
ratio_y -= 1.0f ; ratio_y -= 1.0f ;
U8* new_data = new (std::nothrow) U8[new_data_size] ; U8* new_data = allocateMemory(new_data_size) ;
llassert_always(new_data != NULL) ; llassert_always(new_data != NULL) ;
U8* old_data = getData() ; U8* old_data = getData() ;
@@ -902,6 +928,7 @@ BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height)
return TRUE ; return TRUE ;
} }
#endif
BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data ) BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
{ {
@@ -1222,7 +1249,7 @@ file_extensions[] =
{ "png", IMG_CODEC_PNG } { "png", IMG_CODEC_PNG }
}; };
#define NUM_FILE_EXTENSIONS LL_ARRAY_SIZE(file_extensions) #define NUM_FILE_EXTENSIONS LL_ARRAY_SIZE(file_extensions)
#if 0
static std::string find_file(std::string &name, S8 *codec) static std::string find_file(std::string &name, S8 *codec)
{ {
std::string tname; std::string tname;
@@ -1240,7 +1267,7 @@ static std::string find_file(std::string &name, S8 *codec)
} }
return std::string(""); return std::string("");
} }
#endif
EImageCodec LLImageBase::getCodecFromExtension(const std::string& exten) EImageCodec LLImageBase::getCodecFromExtension(const std::string& exten)
{ {
for (int i=0; i<(int)(NUM_FILE_EXTENSIONS); i++) for (int i=0; i<(int)(NUM_FILE_EXTENSIONS); i++)
@@ -1250,7 +1277,7 @@ EImageCodec LLImageBase::getCodecFromExtension(const std::string& exten)
} }
return IMG_CODEC_INVALID; return IMG_CODEC_INVALID;
} }
#if 0
bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip_only) bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip_only)
{ {
std::string name = filename; std::string name = filename;
@@ -1336,7 +1363,7 @@ bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip
return true; return true;
} }
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// LLImageFormatted // LLImageFormatted
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -1568,7 +1595,7 @@ void LLImageFormatted::appendData(U8 *data, S32 size)
S32 newsize = cursize + size; S32 newsize = cursize + size;
reallocateData(newsize); reallocateData(newsize);
memcpy(getData() + cursize, data, size); memcpy(getData() + cursize, data, size);
delete[] data; //Fixing leak from CommentCacheReadResponder FREE_MEM(LLImageBase::getPrivatePool(), data);
} }
} }
} }

View File

@@ -62,6 +62,7 @@ const S32 MAX_IMG_PACKET_SIZE = 1000;
class LLImageFormatted; class LLImageFormatted;
class LLImageRaw; class LLImageRaw;
class LLColor4U; class LLColor4U;
class LLPrivateMemoryPool;
typedef enum e_image_codec typedef enum e_image_codec
{ {
@@ -144,6 +145,9 @@ public:
static EImageCodec getCodecFromExtension(const std::string& exten); static EImageCodec getCodecFromExtension(const std::string& exten);
static void createPrivatePool() ;
static void destroyPrivatePool() ;
static LLPrivateMemoryPool* getPrivatePool() {return sPrivatePoolp;}
private: private:
U8 *mData; U8 *mData;
S32 mDataSize; S32 mDataSize;
@@ -155,6 +159,8 @@ private:
bool mBadBufferAllocation ; bool mBadBufferAllocation ;
bool mAllowOverSize ; bool mAllowOverSize ;
static LLPrivateMemoryPool* sPrivatePoolp ;
public: public:
S16 mMemType; // debug S16 mMemType; // debug
}; };
@@ -170,7 +176,7 @@ public:
LLImageRaw(U16 width, U16 height, S8 components); LLImageRaw(U16 width, U16 height, S8 components);
LLImageRaw(U8 *data, U16 width, U16 height, S8 components); LLImageRaw(U8 *data, U16 width, U16 height, S8 components);
// Construct using createFromFile (used by tools) // Construct using createFromFile (used by tools)
LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false); //LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false);
/*virtual*/ void deleteData(); /*virtual*/ void deleteData();
/*virtual*/ U8* allocateData(S32 size = -1); /*virtual*/ U8* allocateData(S32 size = -1);
@@ -178,7 +184,7 @@ public:
BOOL resize(U16 width, U16 height, S8 components); BOOL resize(U16 width, U16 height, S8 components);
U8 * getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const; //U8 * getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const;
BOOL setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height, BOOL setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
const U8 *data, U32 stride = 0, BOOL reverse_y = FALSE); const U8 *data, U32 stride = 0, BOOL reverse_y = FALSE);
@@ -190,7 +196,7 @@ public:
void contractToPowerOfTwo(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); void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE ); BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE );
BOOL scaleDownWithoutBlending( S32 new_width, S32 new_height) ; //BOOL scaleDownWithoutBlending( S32 new_width, S32 new_height) ;
// Fill the buffer with a constant color // Fill the buffer with a constant color
void fill( const LLColor4U& color ); void fill( const LLColor4U& color );
@@ -232,7 +238,7 @@ public:
protected: protected:
// Create an image from a local file (generally used in tools) // Create an image from a local file (generally used in tools)
bool createFromFile(const std::string& filename, bool j2c_lowest_mip_only = false); //bool createFromFile(const std::string& filename, bool j2c_lowest_mip_only = false);
void copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step ); void copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step );
void compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len ); void compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len );

View File

@@ -435,7 +435,7 @@ bool LLImageDXT::convertToDXR()
S32 nmips = calcNumMips(width,height); S32 nmips = calcNumMips(width,height);
S32 total_bytes = getDataSize(); S32 total_bytes = getDataSize();
U8* olddata = getData(); U8* olddata = getData();
U8* newdata = new (std::nothrow) U8[total_bytes]; U8* newdata = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), total_bytes);
if (!newdata) if (!newdata)
{ {
llerrs << "Out of memory in LLImageDXT::convertToDXR()" << llendl; llerrs << "Out of memory in LLImageDXT::convertToDXR()" << llendl;

View File

@@ -501,14 +501,14 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
} }
else else
{ {
U8 *data = new U8[file_size]; U8 *data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), file_size);
apr_size_t bytes_read = file_size; apr_size_t bytes_read = file_size;
apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
infile.close() ; infile.close() ;
if (s != APR_SUCCESS || (S32)bytes_read != file_size) if (s != APR_SUCCESS || (S32)bytes_read != file_size)
{ {
delete[] data; FREE_MEM(LLImageBase::getPrivatePool(), data);
setLastError("Unable to read entire file"); setLastError("Unable to read entire file");
res = FALSE; res = FALSE;
} }

View File

@@ -34,6 +34,7 @@
#include "llinventory.h" #include "llinventory.h"
#include "lldbstrings.h" #include "lldbstrings.h"
#include "llfasttimer.h"
#include "llinventorydefines.h" #include "llinventorydefines.h"
#include "llxorcipher.h" #include "llxorcipher.h"
#include "llsd.h" #include "llsd.h"
@@ -226,7 +227,7 @@ BOOL LLInventoryObject::importLegacyStream(std::istream& input_stream)
} }
// exportFile should be replaced with exportLegacyStream // exportFile should be replaced with exportLegacyStream
// not sure whether exportLegacyStream(llofstream(fp)) would work, fp may need to get icramented... // not sure whether exportLegacyStream(llofstream(fp)) would work, fp may need to get incremented...
BOOL LLInventoryObject::exportFile(LLFILE* fp, BOOL) const BOOL LLInventoryObject::exportFile(LLFILE* fp, BOOL) const
{ {
std::string uuid_str; std::string uuid_str;
@@ -1055,8 +1056,11 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate; sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate;
} }
LLFastTimer::DeclareTimer FTM_INVENTORY_SD_DESERIALIZE("Inventory SD Deserialize");
bool LLInventoryItem::fromLLSD(const LLSD& sd) bool LLInventoryItem::fromLLSD(const LLSD& sd)
{ {
LLFastTimer _(FTM_INVENTORY_SD_DESERIALIZE);
mInventoryType = LLInventoryType::IT_NONE; mInventoryType = LLInventoryType::IT_NONE;
mAssetUUID.setNull(); mAssetUUID.setNull();
std::string w; std::string w;

View File

@@ -67,7 +67,6 @@ const F32 PARCEL_PASS_HOURS_DEFAULT = 1.f;
// Number of "chunks" in which parcel overlay data is sent // Number of "chunks" in which parcel overlay data is sent
// Chunk 0 = southern rows, entire width // Chunk 0 = southern rows, entire width
// NOTE: NOT USABLE FOR VAR SIZED REGIONS!
const S32 PARCEL_OVERLAY_CHUNKS = 4; const S32 PARCEL_OVERLAY_CHUNKS = 4;
// Bottom three bits are a color index for the land overlay // Bottom three bits are a color index for the land overlay

View File

@@ -30,8 +30,8 @@
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
#include <iostream>
#include "linden_common.h" #include "linden_common.h"
#include <iostream>
#include "llsaleinfo.h" #include "llsaleinfo.h"

View File

@@ -75,10 +75,6 @@ set(llmath_HEADER_FILES
llvector4a.h llvector4a.h
llvector4a.inl llvector4a.inl
llvector4logical.h llvector4logical.h
llv4math.h
llv4matrix3.h
llv4matrix4.h
llv4vector3.h
llvolume.h llvolume.h
llvolumemgr.h llvolumemgr.h
llvolumeoctree.h llvolumeoctree.h

View File

@@ -531,13 +531,13 @@ inline void ll_remove_outliers(std::vector<VEC_TYPE>& data, F32 k)
i++; i++;
} }
S32 j = data.size()-1; S32 j = (S32)data.size()-1;
while (j > 0 && data[j] > max) while (j > 0 && data[j] > max)
{ {
j--; j--;
} }
if (j < data.size()-1) if (j < (S32)data.size()-1)
{ {
data.erase(data.begin()+j, data.end()); data.erase(data.begin()+j, data.end());
} }

View File

@@ -60,7 +60,7 @@ inline void LLMatrix3a::setTranspose(const LLMatrix3a& src)
const LLQuad srcCol1 = src.mColumns[1]; const LLQuad srcCol1 = src.mColumns[1];
const LLQuad unpacklo = _mm_unpacklo_ps( srcCol0, srcCol1 ); const LLQuad unpacklo = _mm_unpacklo_ps( srcCol0, srcCol1 );
mColumns[0] = _mm_movelh_ps( unpacklo, src.mColumns[2] ); mColumns[0] = _mm_movelh_ps( unpacklo, src.mColumns[2] );
mColumns[1] = _mm_shuffle_ps( _mm_movehl_ps( srcCol0, unpacklo ), src.mColumns[2], _MM_SHUFFLE(0, 1, 1, 0) ); mColumns[1] = _mm_shuffle_ps( unpacklo, src.mColumns[2], _MM_SHUFFLE(0, 1, 3, 2) );
mColumns[2] = _mm_shuffle_ps( _mm_unpackhi_ps( srcCol0, srcCol1 ), src.mColumns[2], _MM_SHUFFLE(0, 2, 1, 0) ); mColumns[2] = _mm_shuffle_ps( _mm_unpackhi_ps( srcCol0, srcCol1 ), src.mColumns[2], _MM_SHUFFLE(0, 2, 1, 0) );
} }

View File

@@ -104,25 +104,45 @@ public:
mMatrix[2].setAdd(a.mMatrix[2],d2); mMatrix[2].setAdd(a.mMatrix[2],d2);
mMatrix[3].setAdd(a.mMatrix[3],d3); mMatrix[3].setAdd(a.mMatrix[3],d3);
} }
inline void rotate(const LLVector4a& v, LLVector4a& res) //Singu Note: Don't mess with this. It's intentionally different from LL's.
// Note how res isn't manipulated until the very end.
inline void rotate(const LLVector4a& v, LLVector4a& res) const
{ {
res = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); LLVector4a x,y,z;
res.mul(mMatrix[0]);
LLVector4a y;
y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
y.mul(mMatrix[1]);
LLVector4a z; x = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0));
y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2));
x.mul(mMatrix[0]);
y.mul(mMatrix[1]);
z.mul(mMatrix[2]); z.mul(mMatrix[2]);
res.add(y); x.add(y);
res.add(z); res.setAdd(x,z);
}
inline void rotate4(const LLVector4a& v, LLVector4a& res) const
{
LLVector4a x,y,z,w;
x = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0));
y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2));
w = _mm_shuffle_ps(v, v, _MM_SHUFFLE(3, 3, 3, 3));
x.mul(mMatrix[0]);
y.mul(mMatrix[1]);
z.mul(mMatrix[2]);
w.mul(mMatrix[3]);
x.add(y);
z.add(w);
res.setAdd(x,z);
} }
inline void affineTransform(const LLVector4a& v, LLVector4a& res) inline void affineTransform(const LLVector4a& v, LLVector4a& res) const
{ {
LLVector4a x,y,z; LLVector4a x,y,z;

View File

@@ -691,7 +691,7 @@ public:
if (lt != 0x7) if (lt != 0x7)
{ {
OCT_ERRS << "!!! ELEMENT EXCEEDS RANGE OF SPATIAL PARTITION !!!" << llendl; //OCT_ERRS << "!!! ELEMENT EXCEEDS RANGE OF SPATIAL PARTITION !!!" << llendl;
return false; return false;
} }

View File

@@ -1,147 +0,0 @@
/**
* @file llv4math.h
* @brief LLV4* class header file - vector processor enabled math
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLV4MATH_H
#define LL_LLV4MATH_H
// *NOTE: We do not support SSE acceleration on Windows builds.
// Our minimum specification for the viewer includes 1 GHz Athlon processors,
// which covers the Athlon Thunderbird series that does not support SSE.
//
// Our header files include statements like this
// const F32 HAVOK_TIMESTEP = 1.f / 45.f;
// This creates "globals" that are included in each .obj file. If a single
// .cpp file has SSE code generation turned on (eg, llviewerjointmesh_sse.cpp)
// these globals will be initialized using SSE instructions. This causes SL
// to crash before main() on processors without SSE. Untangling all these
// headers/variables is too much work for the small performance gains of
// vectorization.
//
// Therefore we only support vectorization on builds where the everything is
// built with SSE or Altivec. See https://jira.secondlife.com/browse/VWR-1610
// and https://jira.lindenlab.com/browse/SL-47720 for details.
//
// Sorry the code is such a mess. JC
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4MATH - GNUC
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#if LL_GNUC && __GNUC__ >= 4 && __SSE__
#define LL_VECTORIZE 1
#if LL_DARWIN
#include <Accelerate/Accelerate.h>
#include <xmmintrin.h>
typedef vFloat V4F32;
#else
#include <xmmintrin.h>
typedef float V4F32 __attribute__((vector_size(16)));
#endif
#endif
#if LL_GNUC
#define LL_LLV4MATH_ALIGN_PREFIX
#define LL_LLV4MATH_ALIGN_POSTFIX __attribute__((aligned(16)))
#endif
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4MATH - MSVC
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Only vectorize if the entire Windows build uses SSE.
// _M_IX86_FP is set when SSE code generation is turned on, and I have
// confirmed this in VS2003, VS2003 SP1, and VS2005. JC
#if LL_MSVC && _M_IX86_FP
#define LL_VECTORIZE 1
#include <xmmintrin.h>
typedef __m128 V4F32;
#endif
#if LL_MSVC
#define LL_LLV4MATH_ALIGN_PREFIX __declspec(align(16))
#define LL_LLV4MATH_ALIGN_POSTFIX
#endif
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4MATH - default - no vectorization
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#if !LL_VECTORIZE
#define LL_VECTORIZE 0
struct V4F32 { F32 __pad__[4]; };
inline F32 llv4lerp(F32 a, F32 b, F32 w) { return ( b - a ) * w + a; }
#endif
#ifndef LL_LLV4MATH_ALIGN_PREFIX
# define LL_LLV4MATH_ALIGN_PREFIX
#endif
#ifndef LL_LLV4MATH_ALIGN_POSTFIX
# define LL_LLV4MATH_ALIGN_POSTFIX
#endif
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4MATH
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#define LLV4_NUM_AXIS 4
class LLV4Vector3;
class LLV4Matrix3;
class LLV4Matrix4;
#endif

View File

@@ -1,226 +0,0 @@
/**
* @file llviewerjointmesh.cpp
* @brief LLV4* class header file - vector processor enabled math
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLV4MATRIX3_H
#define LL_LLV4MATRIX3_H
#include "llv4math.h"
#include "llv4vector3.h"
#include "m3math.h" // for operator LLMatrix3()
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4Matrix3
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
LL_LLV4MATH_ALIGN_PREFIX
class LLV4Matrix3
{
public:
union {
F32 mMatrix[LLV4_NUM_AXIS][LLV4_NUM_AXIS];
V4F32 mV[LLV4_NUM_AXIS];
};
void lerp(const LLV4Matrix3 &a, const LLV4Matrix3 &b, const F32 &w);
void multiply(const LLVector3 &a, LLVector3& out) const;
void multiply(const LLVector4 &a, LLV4Vector3& out) const;
void multiply(const LLVector3 &a, LLV4Vector3& out) const;
const LLV4Matrix3& transpose();
const LLV4Matrix3& operator=(const LLMatrix3& a);
operator LLMatrix3() const { return (reinterpret_cast<const LLMatrix4*>(const_cast<const F32*>(&mMatrix[0][0])))->getMat3(); }
friend LLVector3 operator*(const LLVector3& a, const LLV4Matrix3& b);
}
LL_LLV4MATH_ALIGN_POSTFIX;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4Matrix3 - SSE
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#if LL_VECTORIZE
inline void LLV4Matrix3::lerp(const LLV4Matrix3 &a, const LLV4Matrix3 &b, const F32 &w)
{
__m128 vw = _mm_set1_ps(w);
mV[VX] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VX], a.mV[VX]), vw), a.mV[VX]); // ( b - a ) * w + a
mV[VY] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VY], a.mV[VY]), vw), a.mV[VY]);
mV[VZ] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VZ], a.mV[VZ]), vw), a.mV[VZ]);
}
inline void LLV4Matrix3::multiply(const LLVector3 &a, LLVector3& o) const
{
LLV4Vector3 j;
j.v = _mm_mul_ps(_mm_set1_ps(a.mV[VX]), mV[VX]); // ( ax * vx ) + ...
j.v = _mm_add_ps(j.v , _mm_mul_ps(_mm_set1_ps(a.mV[VY]), mV[VY]));
j.v = _mm_add_ps(j.v , _mm_mul_ps(_mm_set1_ps(a.mV[VZ]), mV[VZ]));
o.setVec(j.mV);
}
inline void LLV4Matrix3::multiply(const LLVector4 &a, LLV4Vector3& o) const
{
o.v = _mm_mul_ps(_mm_set1_ps(a.mV[VX]), mV[VX]); // ( ax * vx ) + ...
o.v = _mm_add_ps(o.v , _mm_mul_ps(_mm_set1_ps(a.mV[VY]), mV[VY]));
o.v = _mm_add_ps(o.v , _mm_mul_ps(_mm_set1_ps(a.mV[VZ]), mV[VZ]));
}
inline void LLV4Matrix3::multiply(const LLVector3 &a, LLV4Vector3& o) const
{
o.v = _mm_mul_ps(_mm_set1_ps(a.mV[VX]), mV[VX]); // ( ax * vx ) + ...
o.v = _mm_add_ps(o.v , _mm_mul_ps(_mm_set1_ps(a.mV[VY]), mV[VY]));
o.v = _mm_add_ps(o.v , _mm_mul_ps(_mm_set1_ps(a.mV[VZ]), mV[VZ]));
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4Matrix3
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#else
inline void LLV4Matrix3::lerp(const LLV4Matrix3 &a, const LLV4Matrix3 &b, const F32 &w)
{
mMatrix[VX][VX] = llv4lerp(a.mMatrix[VX][VX], b.mMatrix[VX][VX], w);
mMatrix[VX][VY] = llv4lerp(a.mMatrix[VX][VY], b.mMatrix[VX][VY], w);
mMatrix[VX][VZ] = llv4lerp(a.mMatrix[VX][VZ], b.mMatrix[VX][VZ], w);
mMatrix[VY][VX] = llv4lerp(a.mMatrix[VY][VX], b.mMatrix[VY][VX], w);
mMatrix[VY][VY] = llv4lerp(a.mMatrix[VY][VY], b.mMatrix[VY][VY], w);
mMatrix[VY][VZ] = llv4lerp(a.mMatrix[VY][VZ], b.mMatrix[VY][VZ], w);
mMatrix[VZ][VX] = llv4lerp(a.mMatrix[VZ][VX], b.mMatrix[VZ][VX], w);
mMatrix[VZ][VY] = llv4lerp(a.mMatrix[VZ][VY], b.mMatrix[VZ][VY], w);
mMatrix[VZ][VZ] = llv4lerp(a.mMatrix[VZ][VZ], b.mMatrix[VZ][VZ], w);
}
inline void LLV4Matrix3::multiply(const LLVector3 &a, LLVector3& o) const
{
o.setVec( a.mV[VX] * mMatrix[VX][VX] +
a.mV[VY] * mMatrix[VY][VX] +
a.mV[VZ] * mMatrix[VZ][VX],
a.mV[VX] * mMatrix[VX][VY] +
a.mV[VY] * mMatrix[VY][VY] +
a.mV[VZ] * mMatrix[VZ][VY],
a.mV[VX] * mMatrix[VX][VZ] +
a.mV[VY] * mMatrix[VY][VZ] +
a.mV[VZ] * mMatrix[VZ][VZ]);
}
inline void LLV4Matrix3::multiply(const LLVector4 &a, LLV4Vector3& o) const
{
o.setVec( a.mV[VX] * mMatrix[VX][VX] +
a.mV[VY] * mMatrix[VY][VX] +
a.mV[VZ] * mMatrix[VZ][VX],
a.mV[VX] * mMatrix[VX][VY] +
a.mV[VY] * mMatrix[VY][VY] +
a.mV[VZ] * mMatrix[VZ][VY],
a.mV[VX] * mMatrix[VX][VZ] +
a.mV[VY] * mMatrix[VY][VZ] +
a.mV[VZ] * mMatrix[VZ][VZ]);
}
inline void LLV4Matrix3::multiply(const LLVector3 &a, LLV4Vector3& o) const
{
o.setVec( a.mV[VX] * mMatrix[VX][VX] +
a.mV[VY] * mMatrix[VY][VX] +
a.mV[VZ] * mMatrix[VZ][VX],
a.mV[VX] * mMatrix[VX][VY] +
a.mV[VY] * mMatrix[VY][VY] +
a.mV[VZ] * mMatrix[VZ][VY],
a.mV[VX] * mMatrix[VX][VZ] +
a.mV[VY] * mMatrix[VY][VZ] +
a.mV[VZ] * mMatrix[VZ][VZ]);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4Matrix3
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#endif
inline const LLV4Matrix3& LLV4Matrix3::transpose()
{
#if LL_VECTORIZE && defined(_MM_TRANSPOSE4_PS)
_MM_TRANSPOSE4_PS(mV[VX], mV[VY], mV[VZ], mV[VW]);
return *this;
#else
F32 temp;
temp = mMatrix[VX][VY]; mMatrix[VX][VY] = mMatrix[VY][VX]; mMatrix[VY][VX] = temp;
temp = mMatrix[VX][VZ]; mMatrix[VX][VZ] = mMatrix[VZ][VX]; mMatrix[VZ][VX] = temp;
temp = mMatrix[VY][VZ]; mMatrix[VY][VZ] = mMatrix[VZ][VY]; mMatrix[VZ][VY] = temp;
#endif
return *this;
}
inline const LLV4Matrix3& LLV4Matrix3::operator=(const LLMatrix3& a)
{
memcpy(mMatrix[VX], a.mMatrix[VX], sizeof(F32) * 3 );
memcpy(mMatrix[VY], a.mMatrix[VY], sizeof(F32) * 3 );
memcpy(mMatrix[VZ], a.mMatrix[VZ], sizeof(F32) * 3 );
return *this;
}
inline LLVector3 operator*(const LLVector3& a, const LLV4Matrix3& b)
{
return LLVector3(
a.mV[VX] * b.mMatrix[VX][VX] +
a.mV[VY] * b.mMatrix[VY][VX] +
a.mV[VZ] * b.mMatrix[VZ][VX],
a.mV[VX] * b.mMatrix[VX][VY] +
a.mV[VY] * b.mMatrix[VY][VY] +
a.mV[VZ] * b.mMatrix[VZ][VY],
a.mV[VX] * b.mMatrix[VX][VZ] +
a.mV[VY] * b.mMatrix[VY][VZ] +
a.mV[VZ] * b.mMatrix[VZ][VZ] );
}
#endif

View File

@@ -1,255 +0,0 @@
/**
* @file llviewerjointmesh.cpp
* @brief LLV4* class header file - vector processor enabled math
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLV4MATRIX4_H
#define LL_LLV4MATRIX4_H
#include "llv4math.h"
#include "llv4matrix3.h" // just for operator LLV4Matrix3()
#include "llv4vector3.h"
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4Matrix4
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
LL_LLV4MATH_ALIGN_PREFIX
class LLV4Matrix4
{
public:
union {
F32 mMatrix[LLV4_NUM_AXIS][LLV4_NUM_AXIS];
V4F32 mV[LLV4_NUM_AXIS];
};
void lerp(const LLV4Matrix4 &a, const LLV4Matrix4 &b, const F32 &w);
void multiply(const LLVector3 &a, LLVector3& o) const;
void multiply(const LLVector3 &a, LLV4Vector3& o) const;
const LLV4Matrix4& transpose();
const LLV4Matrix4& translate(const LLVector3 &vec);
const LLV4Matrix4& translate(const LLV4Vector3 &vec);
const LLV4Matrix4& operator=(const LLMatrix4& a);
operator LLMatrix4() const { return *(reinterpret_cast<const LLMatrix4*>(const_cast<const F32*>(&mMatrix[0][0]))); }
operator LLV4Matrix3() const { return *(reinterpret_cast<const LLV4Matrix3*>(const_cast<const F32*>(&mMatrix[0][0]))); }
friend LLVector3 operator*(const LLVector3 &a, const LLV4Matrix4 &b);
}
LL_LLV4MATH_ALIGN_POSTFIX;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4Matrix4 - SSE
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#if LL_VECTORIZE
inline void LLV4Matrix4::lerp(const LLV4Matrix4 &a, const LLV4Matrix4 &b, const F32 &w)
{
__m128 vw = _mm_set1_ps(w);
mV[VX] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VX], a.mV[VX]), vw), a.mV[VX]); // ( b - a ) * w + a
mV[VY] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VY], a.mV[VY]), vw), a.mV[VY]);
mV[VZ] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VZ], a.mV[VZ]), vw), a.mV[VZ]);
mV[VW] = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(b.mV[VW], a.mV[VW]), vw), a.mV[VW]);
}
inline void LLV4Matrix4::multiply(const LLVector3 &a, LLVector3& o) const
{
LLV4Vector3 j;
j.v = _mm_add_ps(mV[VW], _mm_mul_ps(_mm_set1_ps(a.mV[VX]), mV[VX])); // ( ax * vx ) + vw
j.v = _mm_add_ps(j.v , _mm_mul_ps(_mm_set1_ps(a.mV[VY]), mV[VY]));
j.v = _mm_add_ps(j.v , _mm_mul_ps(_mm_set1_ps(a.mV[VZ]), mV[VZ]));
o.setVec(j.mV);
}
inline void LLV4Matrix4::multiply(const LLVector3 &a, LLV4Vector3& o) const
{
o.v = _mm_add_ps(mV[VW], _mm_mul_ps(_mm_set1_ps(a.mV[VX]), mV[VX])); // ( ax * vx ) + vw
o.v = _mm_add_ps(o.v , _mm_mul_ps(_mm_set1_ps(a.mV[VY]), mV[VY]));
o.v = _mm_add_ps(o.v , _mm_mul_ps(_mm_set1_ps(a.mV[VZ]), mV[VZ]));
}
inline const LLV4Matrix4& LLV4Matrix4::translate(const LLV4Vector3 &vec)
{
mV[VW] = _mm_add_ps(mV[VW], vec.v);
return (*this);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4Matrix4
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#else
inline void LLV4Matrix4::lerp(const LLV4Matrix4 &a, const LLV4Matrix4 &b, const F32 &w)
{
mMatrix[VX][VX] = llv4lerp(a.mMatrix[VX][VX], b.mMatrix[VX][VX], w);
mMatrix[VX][VY] = llv4lerp(a.mMatrix[VX][VY], b.mMatrix[VX][VY], w);
mMatrix[VX][VZ] = llv4lerp(a.mMatrix[VX][VZ], b.mMatrix[VX][VZ], w);
mMatrix[VY][VX] = llv4lerp(a.mMatrix[VY][VX], b.mMatrix[VY][VX], w);
mMatrix[VY][VY] = llv4lerp(a.mMatrix[VY][VY], b.mMatrix[VY][VY], w);
mMatrix[VY][VZ] = llv4lerp(a.mMatrix[VY][VZ], b.mMatrix[VY][VZ], w);
mMatrix[VZ][VX] = llv4lerp(a.mMatrix[VZ][VX], b.mMatrix[VZ][VX], w);
mMatrix[VZ][VY] = llv4lerp(a.mMatrix[VZ][VY], b.mMatrix[VZ][VY], w);
mMatrix[VZ][VZ] = llv4lerp(a.mMatrix[VZ][VZ], b.mMatrix[VZ][VZ], w);
mMatrix[VW][VX] = llv4lerp(a.mMatrix[VW][VX], b.mMatrix[VW][VX], w);
mMatrix[VW][VY] = llv4lerp(a.mMatrix[VW][VY], b.mMatrix[VW][VY], w);
mMatrix[VW][VZ] = llv4lerp(a.mMatrix[VW][VZ], b.mMatrix[VW][VZ], w);
}
inline void LLV4Matrix4::multiply(const LLVector3 &a, LLVector3& o) const
{
o.setVec( a.mV[VX] * mMatrix[VX][VX] +
a.mV[VY] * mMatrix[VY][VX] +
a.mV[VZ] * mMatrix[VZ][VX] +
mMatrix[VW][VX],
a.mV[VX] * mMatrix[VX][VY] +
a.mV[VY] * mMatrix[VY][VY] +
a.mV[VZ] * mMatrix[VZ][VY] +
mMatrix[VW][VY],
a.mV[VX] * mMatrix[VX][VZ] +
a.mV[VY] * mMatrix[VY][VZ] +
a.mV[VZ] * mMatrix[VZ][VZ] +
mMatrix[VW][VZ]);
}
inline void LLV4Matrix4::multiply(const LLVector3 &a, LLV4Vector3& o) const
{
o.setVec( a.mV[VX] * mMatrix[VX][VX] +
a.mV[VY] * mMatrix[VY][VX] +
a.mV[VZ] * mMatrix[VZ][VX] +
mMatrix[VW][VX],
a.mV[VX] * mMatrix[VX][VY] +
a.mV[VY] * mMatrix[VY][VY] +
a.mV[VZ] * mMatrix[VZ][VY] +
mMatrix[VW][VY],
a.mV[VX] * mMatrix[VX][VZ] +
a.mV[VY] * mMatrix[VY][VZ] +
a.mV[VZ] * mMatrix[VZ][VZ] +
mMatrix[VW][VZ]);
}
inline const LLV4Matrix4& LLV4Matrix4::translate(const LLV4Vector3 &vec)
{
mMatrix[3][0] += vec.mV[0];
mMatrix[3][1] += vec.mV[1];
mMatrix[3][2] += vec.mV[2];
return (*this);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4Matrix4
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#endif
inline const LLV4Matrix4& LLV4Matrix4::operator=(const LLMatrix4& a)
{
memcpy(mMatrix, a.mMatrix, sizeof(F32) * 16 );
return *this;
}
inline const LLV4Matrix4& LLV4Matrix4::transpose()
{
#if LL_VECTORIZE && defined(_MM_TRANSPOSE4_PS)
_MM_TRANSPOSE4_PS(mV[VX], mV[VY], mV[VZ], mV[VW]);
#else
LLV4Matrix4 mat;
mat.mMatrix[0][0] = mMatrix[0][0];
mat.mMatrix[1][0] = mMatrix[0][1];
mat.mMatrix[2][0] = mMatrix[0][2];
mat.mMatrix[3][0] = mMatrix[0][3];
mat.mMatrix[0][1] = mMatrix[1][0];
mat.mMatrix[1][1] = mMatrix[1][1];
mat.mMatrix[2][1] = mMatrix[1][2];
mat.mMatrix[3][1] = mMatrix[1][3];
mat.mMatrix[0][2] = mMatrix[2][0];
mat.mMatrix[1][2] = mMatrix[2][1];
mat.mMatrix[2][2] = mMatrix[2][2];
mat.mMatrix[3][2] = mMatrix[2][3];
mat.mMatrix[0][3] = mMatrix[3][0];
mat.mMatrix[1][3] = mMatrix[3][1];
mat.mMatrix[2][3] = mMatrix[3][2];
mat.mMatrix[3][3] = mMatrix[3][3];
*this = mat;
#endif
return *this;
}
inline const LLV4Matrix4& LLV4Matrix4::translate(const LLVector3 &vec)
{
mMatrix[3][0] += vec.mV[0];
mMatrix[3][1] += vec.mV[1];
mMatrix[3][2] += vec.mV[2];
return (*this);
}
inline LLVector3 operator*(const LLVector3 &a, const LLV4Matrix4 &b)
{
return LLVector3(a.mV[VX] * b.mMatrix[VX][VX] +
a.mV[VY] * b.mMatrix[VY][VX] +
a.mV[VZ] * b.mMatrix[VZ][VX] +
b.mMatrix[VW][VX],
a.mV[VX] * b.mMatrix[VX][VY] +
a.mV[VY] * b.mMatrix[VY][VY] +
a.mV[VZ] * b.mMatrix[VZ][VY] +
b.mMatrix[VW][VY],
a.mV[VX] * b.mMatrix[VX][VZ] +
a.mV[VY] * b.mMatrix[VY][VZ] +
a.mV[VZ] * b.mMatrix[VZ][VZ] +
b.mMatrix[VW][VZ]);
}
#endif

View File

@@ -1,86 +0,0 @@
/**
* @file llviewerjointmesh.cpp
* @brief LLV4* class header file - vector processor enabled math
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLV4VECTOR3_H
#define LL_LLV4VECTOR3_H
#include "llv4math.h"
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4Vector3
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
LL_LLV4MATH_ALIGN_PREFIX
class LLV4Vector3
{
public:
union {
F32 mV[LLV4_NUM_AXIS];
V4F32 v;
};
enum {
ALIGNMENT = 16
};
void setVec(F32 x, F32 y, F32 z);
void setVec(F32 a);
}
LL_LLV4MATH_ALIGN_POSTFIX;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LLV4Vector3
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
inline void LLV4Vector3::setVec(F32 x, F32 y, F32 z)
{
mV[VX] = x;
mV[VY] = y;
mV[VZ] = z;
}
inline void LLV4Vector3::setVec(F32 a)
{
#if LL_VECTORIZE
v = _mm_set1_ps(a);
#else
setVec(a, a, a);
#endif
}
#endif

View File

@@ -2079,15 +2079,14 @@ LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL ge
mFaceMask = 0x0; mFaceMask = 0x0;
mDetail = detail; mDetail = detail;
mSculptLevel = -2; mSculptLevel = -2;
#if MESH_ENABLED mSurfaceArea = 1.f; //only calculated for sculpts, defaults to 1 for all other prims
mIsMeshAssetLoaded = FALSE; mIsMeshAssetLoaded = FALSE;
mLODScaleBias.setVec(1,1,1); mLODScaleBias.setVec(1,1,1);
mHullPoints = NULL; mHullPoints = NULL;
mHullIndices = NULL; mHullIndices = NULL;
mNumHullPoints = 0; mNumHullPoints = 0;
mNumHullIndices = 0; mNumHullIndices = 0;
#endif //MESH_ENABLED
// set defaults // set defaults
if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE)
{ {
@@ -2139,12 +2138,10 @@ LLVolume::~LLVolume()
mProfilep = NULL; mProfilep = NULL;
mVolumeFaces.clear(); mVolumeFaces.clear();
#if MESH_ENABLED
ll_aligned_free_16(mHullPoints); ll_aligned_free_16(mHullPoints);
mHullPoints = NULL; mHullPoints = NULL;
ll_aligned_free_16(mHullIndices); ll_aligned_free_16(mHullIndices);
mHullIndices = NULL; mHullIndices = NULL;
#endif //MESH_ENABLED
} }
BOOL LLVolume::generate() BOOL LLVolume::generate()
@@ -2186,7 +2183,7 @@ BOOL LLVolume::generate()
mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);
} }
//******************************************************************** // ********************************************************************
//debug info, to be removed //debug info, to be removed
if((U32)(mPathp->mPath.size() * mProfilep->mProfile.size()) > (1u << 20)) if((U32)(mPathp->mPath.size() * mProfilep->mProfile.size()) > (1u << 20))
{ {
@@ -2198,7 +2195,7 @@ BOOL LLVolume::generate()
llerrs << "LLVolume corrupted!" << llendl ; llerrs << "LLVolume corrupted!" << llendl ;
} }
//******************************************************************** // ********************************************************************
BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split); BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split);
BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split); BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split);
@@ -2208,7 +2205,7 @@ BOOL LLVolume::generate()
S32 sizeS = mPathp->mPath.size(); S32 sizeS = mPathp->mPath.size();
S32 sizeT = mProfilep->mProfile.size(); S32 sizeT = mProfilep->mProfile.size();
//******************************************************************** // ********************************************************************
//debug info, to be removed //debug info, to be removed
if((U32)(sizeS * sizeT) > (1u << 20)) if((U32)(sizeS * sizeT) > (1u << 20))
{ {
@@ -2221,7 +2218,7 @@ BOOL LLVolume::generate()
llerrs << "LLVolume corrupted!" << llendl ; llerrs << "LLVolume corrupted!" << llendl ;
} }
//******************************************************************** // ********************************************************************
sNumMeshPoints -= mMesh.size(); sNumMeshPoints -= mMesh.size();
mMesh.resize(sizeT * sizeS); mMesh.resize(sizeT * sizeS);
@@ -2406,7 +2403,6 @@ bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs
return retval; return retval;
} }
#if MESH_ENABLED
bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
{ {
//input stream is now pointing at a zlib compressed block of LLSD //input stream is now pointing at a zlib compressed block of LLSD
@@ -2736,7 +2732,7 @@ void LLVolume::cacheOptimize()
mVolumeFaces[i].cacheOptimize(); mVolumeFaces[i].cacheOptimize();
} }
} }
#endif //MESH_ENABLED
S32 LLVolume::getNumFaces() const S32 LLVolume::getNumFaces() const
{ {
@@ -3157,6 +3153,8 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
{ {
F32 area = sculptGetSurfaceArea(); F32 area = sculptGetSurfaceArea();
mSurfaceArea = area;
const F32 SCULPT_MAX_AREA = 384.f; const F32 SCULPT_MAX_AREA = 384.f;
if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA) if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA)
@@ -3205,12 +3203,10 @@ bool LLVolumeParams::isSculpt() const
return mSculptID.notNull(); return mSculptID.notNull();
} }
#if MESH_ENABLED
bool LLVolumeParams::isMeshSculpt() const bool LLVolumeParams::isMeshSculpt() const
{ {
return isSculpt() && ((mSculptType & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH); return isSculpt() && ((mSculptType & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH);
} }
#endif //MESH_ENABLED
bool LLVolumeParams::operator==(const LLVolumeParams &params) const bool LLVolumeParams::operator==(const LLVolumeParams &params) const
{ {
@@ -4320,15 +4316,25 @@ S32 LLVolume::getNumTriangleIndices() const
} }
S32 LLVolume::getNumTriangles() const S32 LLVolume::getNumTriangles(S32* vcount) const
{ {
U32 triangle_count = 0; U32 triangle_count = 0;
U32 vertex_count = 0;
for (S32 i = 0; i < getNumVolumeFaces(); ++i) for (S32 i = 0; i < getNumVolumeFaces(); ++i)
{ {
triangle_count += getVolumeFace(i).mNumIndices/3; const LLVolumeFace& face = getVolumeFace(i);
triangle_count += face.mNumIndices/3;
vertex_count += face.mNumVertices;
} }
if (vcount)
{
*vcount = vertex_count;
}
return triangle_count; return triangle_count;
} }
@@ -4357,13 +4363,11 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
vertices.clear(); vertices.clear();
normals.clear(); normals.clear();
#if MESH_ENABLED
if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
{ {
return; return;
} }
#endif //MESH_ENABLED
S32 cur_index = 0; S32 cur_index = 0;
//for each face //for each face
for (face_list_t::iterator iter = mVolumeFaces.begin(); for (face_list_t::iterator iter = mVolumeFaces.begin();
@@ -4622,18 +4626,83 @@ S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& en
genBinormals(i); genBinormals(i);
} }
if (!face.mOctree) if (isUnique())
{ { //don't bother with an octree for flexi volumes
face.createOctree(); U32 tri_count = face.mNumIndices/3;
}
//LLVector4a* p = (LLVector4a*) face.mPositions;
LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, bi_normal); for (U32 j = 0; j < tri_count; ++j)
intersect.traverse(face.mOctree); {
if (intersect.mHitFace) U16 idx0 = face.mIndices[j*3+0];
U16 idx1 = face.mIndices[j*3+1];
U16 idx2 = face.mIndices[j*3+2];
const LLVector4a& v0 = face.mPositions[idx0];
const LLVector4a& v1 = face.mPositions[idx1];
const LLVector4a& v2 = face.mPositions[idx2];
F32 a,b,t;
if (LLTriangleRayIntersect(v0, v1, v2,
start, dir, a, b, t))
{
if ((t >= 0.f) && // if hit is after start
(t <= 1.f) && // and before end
(t < closest_t)) // and this hit is closer
{
closest_t = t;
hit_face = i;
if (intersection != NULL)
{
LLVector4a intersect = dir;
intersect.mul(closest_t);
intersect.add(start);
intersection->set(intersect.getF32ptr());
}
if (tex_coord != NULL)
{
LLVector2* tc = (LLVector2*) face.mTexCoords;
*tex_coord = ((1.f - a - b) * tc[idx0] +
a * tc[idx1] +
b * tc[idx2]);
}
if (normal!= NULL)
{
LLVector4* norm = (LLVector4*) face.mNormals;
*normal = ((1.f - a - b) * LLVector3(norm[idx0]) +
a * LLVector3(norm[idx1]) +
b * LLVector3(norm[idx2]));
}
if (bi_normal != NULL)
{
LLVector4* binormal = (LLVector4*) face.mBinormals;
*bi_normal = ((1.f - a - b) * LLVector3(binormal[idx0]) +
a * LLVector3(binormal[idx1]) +
b * LLVector3(binormal[idx2]));
}
}
}
}
}
else
{ {
hit_face = i; if (!face.mOctree)
{
face.createOctree();
}
LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, bi_normal);
intersect.traverse(face.mOctree);
if (intersect.mHitFace)
{
hit_face = i;
}
} }
} }
} }
@@ -5414,9 +5483,7 @@ LLVolumeFace::LLVolumeFace() :
mBinormals(NULL), mBinormals(NULL),
mTexCoords(NULL), mTexCoords(NULL),
mIndices(NULL), mIndices(NULL),
#if MESH_ENABLED
mWeights(NULL), mWeights(NULL),
#endif //MESH_ENABLED
mOctree(NULL) mOctree(NULL)
{ {
mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
@@ -5439,9 +5506,7 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)
mBinormals(NULL), mBinormals(NULL),
mTexCoords(NULL), mTexCoords(NULL),
mIndices(NULL), mIndices(NULL),
#if MESH_ENABLED
mWeights(NULL), mWeights(NULL),
#endif //MESH_ENABLED
mOctree(NULL) mOctree(NULL)
{ {
mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
@@ -5507,7 +5572,6 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
mBinormals = NULL; mBinormals = NULL;
} }
#if MESH_ENABLED
if (src.mWeights) if (src.mWeights)
{ {
allocateWeights(src.mNumVertices); allocateWeights(src.mNumVertices);
@@ -5518,8 +5582,8 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
ll_aligned_free_16(mWeights); ll_aligned_free_16(mWeights);
mWeights = NULL; mWeights = NULL;
} }
#endif //MESH_ENABLED
} }
if (mNumIndices) if (mNumIndices)
{ {
S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF; S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF;
@@ -5551,10 +5615,8 @@ void LLVolumeFace::freeData()
mIndices = NULL; mIndices = NULL;
ll_aligned_free_16(mBinormals); ll_aligned_free_16(mBinormals);
mBinormals = NULL; mBinormals = NULL;
#if MESH_ENABLED
ll_aligned_free_16(mWeights); ll_aligned_free_16(mWeights);
mWeights = NULL; mWeights = NULL;
#endif //MESH_ENABLED
delete mOctree; delete mOctree;
mOctree = NULL; mOctree = NULL;
@@ -6125,13 +6187,11 @@ void LLVolumeFace::cacheOptimize()
S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
LLVector2* tc = (LLVector2*) ll_aligned_malloc_16(size); LLVector2* tc = (LLVector2*) ll_aligned_malloc_16(size);
#if MESH_ENABLED
LLVector4a* wght = NULL; LLVector4a* wght = NULL;
if (mWeights) if (mWeights)
{ {
wght = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); wght = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
} }
#endif //MESH_ENABLED
LLVector4a* binorm = NULL; LLVector4a* binorm = NULL;
if (mBinormals) if (mBinormals)
@@ -6155,12 +6215,10 @@ void LLVolumeFace::cacheOptimize()
pos[cur_idx] = mPositions[idx]; pos[cur_idx] = mPositions[idx];
norm[cur_idx] = mNormals[idx]; norm[cur_idx] = mNormals[idx];
tc[cur_idx] = mTexCoords[idx]; tc[cur_idx] = mTexCoords[idx];
#if MESH_ENABLED
if (mWeights) if (mWeights)
{ {
wght[cur_idx] = mWeights[idx]; wght[cur_idx] = mWeights[idx];
} }
#endif //MESH_ENABLED
if (mBinormals) if (mBinormals)
{ {
binorm[cur_idx] = mBinormals[idx]; binorm[cur_idx] = mBinormals[idx];
@@ -6178,17 +6236,13 @@ void LLVolumeFace::cacheOptimize()
ll_aligned_free_16(mPositions); ll_aligned_free_16(mPositions);
ll_aligned_free_16(mNormals); ll_aligned_free_16(mNormals);
ll_aligned_free_16(mTexCoords); ll_aligned_free_16(mTexCoords);
#if MESH_ENABLED
ll_aligned_free_16(mWeights); ll_aligned_free_16(mWeights);
#endif //MESH_ENABLED
ll_aligned_free_16(mBinormals); ll_aligned_free_16(mBinormals);
mPositions = pos; mPositions = pos;
mNormals = norm; mNormals = norm;
mTexCoords = tc; mTexCoords = tc;
#if MESH_ENABLED
mWeights = wght; mWeights = wght;
#endif //MESH_ENABLED
mBinormals = binorm; mBinormals = binorm;
//std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks); //std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks);
@@ -6276,6 +6330,7 @@ void LLVolumeFace::swapData(LLVolumeFace& rhs)
llswap(rhs.mNumVertices, mNumVertices); llswap(rhs.mNumVertices, mNumVertices);
llswap(rhs.mNumIndices, mNumIndices); llswap(rhs.mNumIndices, mNumIndices);
} }
void LerpPlanarVertex(LLVolumeFace::VertexData& v0, void LerpPlanarVertex(LLVolumeFace::VertexData& v0,
LLVolumeFace::VertexData& v1, LLVolumeFace::VertexData& v1,
LLVolumeFace::VertexData& v2, LLVolumeFace::VertexData& v2,
@@ -6971,14 +7026,11 @@ void LLVolumeFace::allocateBinormals(S32 num_verts)
mBinormals = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); mBinormals = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
} }
#if MESH_ENABLED
void LLVolumeFace::allocateWeights(S32 num_verts) void LLVolumeFace::allocateWeights(S32 num_verts)
{ {
ll_aligned_free_16(mWeights); ll_aligned_free_16(mWeights);
mWeights = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); mWeights = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
} }
#endif //MESH_ENABLED
void LLVolumeFace::resizeIndices(S32 num_indices) void LLVolumeFace::resizeIndices(S32 num_indices)
{ {
@@ -7141,9 +7193,8 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
{ {
resizeVertices(num_vertices); resizeVertices(num_vertices);
resizeIndices(num_indices); resizeIndices(num_indices);
#if MESH_ENABLED
if (!volume->isMeshAssetLoaded()) if (!volume->isMeshAssetLoaded())
#endif //MESH_ENABLED
{ {
mEdge.resize(num_indices); mEdge.resize(num_indices);
} }

View File

@@ -191,21 +191,14 @@ const U8 LL_SCULPT_TYPE_SPHERE = 1;
const U8 LL_SCULPT_TYPE_TORUS = 2; const U8 LL_SCULPT_TYPE_TORUS = 2;
const U8 LL_SCULPT_TYPE_PLANE = 3; const U8 LL_SCULPT_TYPE_PLANE = 3;
const U8 LL_SCULPT_TYPE_CYLINDER = 4; const U8 LL_SCULPT_TYPE_CYLINDER = 4;
#if MESH_ENABLED
const U8 LL_SCULPT_TYPE_MESH = 5; const U8 LL_SCULPT_TYPE_MESH = 5;
const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE |
LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH; LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH;
#endif //MESH_ENABLED
#if !MESH_ENABLED
const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | LL_SCULPT_TYPE_CYLINDER;
#endif //!MESH_ENABLED
const U8 LL_SCULPT_FLAG_INVERT = 64; const U8 LL_SCULPT_FLAG_INVERT = 64;
const U8 LL_SCULPT_FLAG_MIRROR = 128; const U8 LL_SCULPT_FLAG_MIRROR = 128;
#if MESH_ENABLED
const S32 LL_SCULPT_MESH_MAX_FACES = 8; const S32 LL_SCULPT_MESH_MAX_FACES = 8;
#endif //MESH_ENABLED
class LLProfileParams class LLProfileParams
{ {
@@ -655,9 +648,7 @@ public:
const LLUUID& getSculptID() const { return mSculptID; } const LLUUID& getSculptID() const { return mSculptID; }
const U8& getSculptType() const { return mSculptType; } const U8& getSculptType() const { return mSculptType; }
bool isSculpt() const; bool isSculpt() const;
#if MESH_ENABLED bool isMeshSculpt() const;
bool isMeshSculpt() const;
#endif //MESH_ENABLED
BOOL isConvex() const; BOOL isConvex() const;
// 'begin' and 'end' should be in range [0, 1] (they will be clamped) // 'begin' and 'end' should be in range [0, 1] (they will be clamped)
@@ -865,9 +856,7 @@ public:
void resizeVertices(S32 num_verts); void resizeVertices(S32 num_verts);
void allocateBinormals(S32 num_verts); void allocateBinormals(S32 num_verts);
#if MESH_ENABLED
void allocateWeights(S32 num_verts); void allocateWeights(S32 num_verts);
#endif //MESH_ENABLED
void resizeIndices(S32 num_indices); void resizeIndices(S32 num_indices);
void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx); void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx);
@@ -939,12 +928,10 @@ public:
std::vector<S32> mEdge; std::vector<S32> mEdge;
#if MESH_ENABLED
//list of skin weights for rigged volumes //list of skin weights for rigged volumes
// format is mWeights[vertex_index].mV[influence] = <joint_index>.<weight> // format is mWeights[vertex_index].mV[influence] = <joint_index>.<weight>
// mWeights.size() should be empty or match mVertices.size() // mWeights.size() should be empty or match mVertices.size()
LLVector4a* mWeights; LLVector4a* mWeights;
#endif //MESH_ENABLED
LLOctreeNode<LLVolumeTriangle>* mOctree; LLOctreeNode<LLVolumeTriangle>* mOctree;
@@ -958,12 +945,7 @@ class LLVolume : public LLRefCount
{ {
friend class LLVolumeLODGroup; friend class LLVolumeLODGroup;
#if MESH_ENABLED
protected: protected:
#endif //MESH_ENABLED
#if !MESH_ENABLED
private:
#endif //!MESH_ENABLED
LLVolume(const LLVolume&); // Don't implement LLVolume(const LLVolume&); // Don't implement
~LLVolume(); // use unref ~LLVolume(); // use unref
@@ -989,6 +971,7 @@ public:
S32 getNumFaces() const; S32 getNumFaces() const;
S32 getNumVolumeFaces() const { return mVolumeFaces.size(); } S32 getNumVolumeFaces() const { return mVolumeFaces.size(); }
F32 getDetail() const { return mDetail; } F32 getDetail() const { return mDetail; }
F32 getSurfaceArea() const { return mSurfaceArea; }
const LLVolumeParams& getParams() const { return mParams; } const LLVolumeParams& getParams() const { return mParams; }
LLVolumeParams getCopyOfParams() const { return mParams; } LLVolumeParams getCopyOfParams() const { return mParams; }
const LLProfile& getProfile() const { return *mProfilep; } const LLProfile& getProfile() const { return *mProfilep; }
@@ -1016,7 +999,7 @@ public:
S32 getNumTriangleIndices() const; S32 getNumTriangleIndices() const;
static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts); static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);
S32 getNumTriangles() const; S32 getNumTriangles(S32* vcount = NULL) const;
void generateSilhouetteVertices(std::vector<LLVector3> &vertices, void generateSilhouetteVertices(std::vector<LLVector3> &vertices,
std::vector<LLVector3> &normals, std::vector<LLVector3> &normals,
@@ -1081,37 +1064,33 @@ private:
protected: protected:
BOOL generate(); BOOL generate();
void createVolumeFaces(); void createVolumeFaces();
#if MESH_ENABLED
public: public:
virtual bool unpackVolumeFaces(std::istream& is, S32 size); virtual bool unpackVolumeFaces(std::istream& is, S32 size);
virtual void setMeshAssetLoaded(BOOL loaded); virtual void setMeshAssetLoaded(BOOL loaded);
virtual BOOL isMeshAssetLoaded(); virtual BOOL isMeshAssetLoaded();
#endif //MESH_ENABLED
protected: protected:
BOOL mUnique; BOOL mUnique;
F32 mDetail; F32 mDetail;
S32 mSculptLevel; S32 mSculptLevel;
#if MESH_ENABLED F32 mSurfaceArea; //unscaled surface area
BOOL mIsMeshAssetLoaded; BOOL mIsMeshAssetLoaded;
#endif //MESH_ENABLED
LLVolumeParams mParams; LLVolumeParams mParams;
LLPath *mPathp; LLPath *mPathp;
LLProfile *mProfilep; LLProfile *mProfilep;
std::vector<Point> mMesh; std::vector<Point> mMesh;
BOOL mGenerateSingleFace; BOOL mGenerateSingleFace;
typedef std::vector<LLVolumeFace> face_list_t; typedef std::vector<LLVolumeFace> face_list_t;
face_list_t mVolumeFaces; face_list_t mVolumeFaces;
#if MESH_ENABLED
public: public:
LLVector4a* mHullPoints; LLVector4a* mHullPoints;
U16* mHullIndices; U16* mHullIndices;
S32 mNumHullPoints; S32 mNumHullPoints;
S32 mNumHullIndices; S32 mNumHullIndices;
#endif //MESH_ENABLED
}; };
std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params);

View File

@@ -154,7 +154,7 @@ void LLVolumeMgr::unrefVolume(LLVolume *volumep)
volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params); volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params);
if( iter == mVolumeLODGroups.end() ) if( iter == mVolumeLODGroups.end() )
{ {
llwarns << "Warning! Tried to cleanup unknown volume type! " << *params << llendl; llerrs << "Warning! Tried to cleanup unknown volume type! " << *params << llendl;
if (mDataMutex) if (mDataMutex)
{ {
mDataMutex->unlock(); mDataMutex->unlock();

View File

@@ -74,6 +74,7 @@ BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, c
return (grt & 0x7) ? false : true; return (grt & 0x7) ? false : true;
} }
LLVolumeOctreeListener::LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle>* node) LLVolumeOctreeListener::LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle>* node)
{ {
node->addListener(this); node->addListener(this);

View File

@@ -57,8 +57,8 @@ public:
{ {
U8 mV[LENGTHOFCOLOR4U]; U8 mV[LENGTHOFCOLOR4U];
U32 mAll; U32 mAll;
LLColor4* mSources; //LLColor4* mSources;
LLColor4U* mSourcesU; //LLColor4U* mSourcesU;
}; };

View File

@@ -39,13 +39,10 @@
const F32 MAX_OBJECT_Z = 4096.f; // should match REGION_HEIGHT_METERS, Pre-havok4: 768.f const F32 MAX_OBJECT_Z = 4096.f; // should match REGION_HEIGHT_METERS, Pre-havok4: 768.f
const F32 MIN_OBJECT_Z = -256.f; const F32 MIN_OBJECT_Z = -256.f;
const F32 DEFAULT_MAX_PRIM_SCALE = 256.f; const F32 DEFAULT_MAX_PRIM_SCALE = 256.f;
#if MESH_ENABLED
const F32 DEFAULT_MAX_PRIM_SCALE_NO_MESH = DEFAULT_MAX_PRIM_SCALE; const F32 DEFAULT_MAX_PRIM_SCALE_NO_MESH = DEFAULT_MAX_PRIM_SCALE;
#endif //MESH_ENABLED
const F32 MIN_PRIM_SCALE = 0.01f; const F32 MIN_PRIM_SCALE = 0.01f;
const F32 MAX_PRIM_SCALE = 65536.f; // something very high but not near FLT_MAX const F32 MAX_PRIM_SCALE = 65536.f; // something very high but not near FLT_MAX
class LLXform class LLXform
{ {
protected: protected:

View File

@@ -30,13 +30,13 @@
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
//***************************************************************************** // *****************************************************************************
// llclassifiedflags.cpp // llclassifiedflags.cpp
// //
// Some exported symbols and functions for dealing with classified flags. // Some exported symbols and functions for dealing with classified flags.
// //
// Copyright 2005, Linden Research, Inc // Copyright 2005, Linden Research, Inc
//***************************************************************************** // *****************************************************************************
#include "linden_common.h" #include "linden_common.h"

View File

@@ -395,7 +395,7 @@ U32 LLCurl::Easy::report(CURLcode code)
if (code == CURLE_OK) if (code == CURLE_OK)
{ {
check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_RESPONSE_CODE, &responseCode)); check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_RESPONSE_CODE, &responseCode));
//*TODO: get reason from first line of mHeaderOutput // *TODO: get reason from first line of mHeaderOutput
} }
else else
{ {
@@ -715,7 +715,7 @@ S32 LLCurl::Multi::process()
else else
{ {
response = 499; response = 499;
//*TODO: change to llwarns // *TODO: change to llwarns
llerrs << "cleaned up curl request completed!" << llendl; llerrs << "cleaned up curl request completed!" << llendl;
} }
if (response >= 400) if (response >= 400)

View File

@@ -91,6 +91,8 @@
#include "llsdserialize.h" #include "llsdserialize.h"
#include "lluuid.h" #include "lluuid.h"
#include "llfasttimer.h"
// spammy mode // spammy mode
//#define LL_SPEW_STREAM_OUT_DEBUGGING 1 //#define LL_SPEW_STREAM_OUT_DEBUGGING 1
@@ -314,6 +316,7 @@ LLFilterSD2XMLRPCResponse::~LLFilterSD2XMLRPCResponse()
} }
static LLFastTimer::DeclareTimer FTM_PROCESS_SD2XMLRPC_RESPONSE("SD2XMLRPC Response");
// virtual // virtual
LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl( LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl(
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
@@ -322,6 +325,8 @@ LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl(
LLSD& context, LLSD& context,
LLPumpIO* pump) LLPumpIO* pump)
{ {
LLFastTimer t(FTM_PROCESS_SD2XMLRPC_RESPONSE);
PUMP_DEBUG; PUMP_DEBUG;
// This pipe does not work if it does not have everyting. This // This pipe does not work if it does not have everyting. This
// could be addressed by making a stream parser for llsd which // could be addressed by making a stream parser for llsd which
@@ -388,6 +393,8 @@ LLFilterSD2XMLRPCRequest::~LLFilterSD2XMLRPCRequest()
{ {
} }
static LLFastTimer::DeclareTimer FTM_PROCESS_SD2XMLRPC_REQUEST("S22XMLRPC Request");
// virtual // virtual
LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl( LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl(
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
@@ -396,6 +403,7 @@ LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl(
LLSD& context, LLSD& context,
LLPumpIO* pump) LLPumpIO* pump)
{ {
LLFastTimer t(FTM_PROCESS_SD2XMLRPC_REQUEST);
// This pipe does not work if it does not have everyting. This // This pipe does not work if it does not have everyting. This
// could be addressed by making a stream parser for llsd which // could be addressed by making a stream parser for llsd which
// handled partial information. // handled partial information.
@@ -592,6 +600,8 @@ LLFilterXMLRPCResponse2LLSD::~LLFilterXMLRPCResponse2LLSD()
{ {
} }
static LLFastTimer::DeclareTimer FTM_PROCESS_XMLRPC2LLSD_RESPONSE("XMLRPC2LLSD Response");
LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl( LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl(
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
buffer_ptr_t& buffer, buffer_ptr_t& buffer,
@@ -599,6 +609,8 @@ LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl(
LLSD& context, LLSD& context,
LLPumpIO* pump) LLPumpIO* pump)
{ {
LLFastTimer t(FTM_PROCESS_XMLRPC2LLSD_RESPONSE);
PUMP_DEBUG; PUMP_DEBUG;
if(!eos) return STATUS_BREAK; if(!eos) return STATUS_BREAK;
if(!buffer) return STATUS_ERROR; if(!buffer) return STATUS_ERROR;
@@ -674,6 +686,7 @@ LLFilterXMLRPCRequest2LLSD::~LLFilterXMLRPCRequest2LLSD()
{ {
} }
static LLFastTimer::DeclareTimer FTM_PROCESS_XMLRPC2LLSD_REQUEST("XMLRPC2LLSD Request");
LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl( LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl(
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
buffer_ptr_t& buffer, buffer_ptr_t& buffer,
@@ -681,6 +694,7 @@ LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl(
LLSD& context, LLSD& context,
LLPumpIO* pump) LLPumpIO* pump)
{ {
LLFastTimer t(FTM_PROCESS_XMLRPC2LLSD_REQUEST);
PUMP_DEBUG; PUMP_DEBUG;
if(!eos) return STATUS_BREAK; if(!eos) return STATUS_BREAK;
if(!buffer) return STATUS_ERROR; if(!buffer) return STATUS_ERROR;

View File

@@ -51,6 +51,7 @@
#include "llstat.h" #include "llstat.h"
#include "llstl.h" #include "llstl.h"
#include "lltimer.h" #include "lltimer.h"
#include "llfasttimer.h"
#include <sstream> #include <sstream>
@@ -146,6 +147,7 @@ private:
LLSD mHeaders; LLSD mHeaders;
}; };
static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_PIPE("HTTP Pipe");
LLIOPipe::EStatus LLHTTPPipe::process_impl( LLIOPipe::EStatus LLHTTPPipe::process_impl(
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
buffer_ptr_t& buffer, buffer_ptr_t& buffer,
@@ -153,6 +155,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
LLSD& context, LLSD& context,
LLPumpIO* pump) LLPumpIO* pump)
{ {
LLFastTimer t(FTM_PROCESS_HTTP_PIPE);
PUMP_DEBUG; PUMP_DEBUG;
lldebugs << "LLSDHTTPServer::process_impl" << llendl; lldebugs << "LLSDHTTPServer::process_impl" << llendl;
@@ -434,6 +437,9 @@ protected:
/** /**
* LLHTTPResponseHeader * LLHTTPResponseHeader
*/ */
static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_HEADER("HTTP Header");
// virtual // virtual
LLIOPipe::EStatus LLHTTPResponseHeader::process_impl( LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
@@ -442,6 +448,7 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
LLSD& context, LLSD& context,
LLPumpIO* pump) LLPumpIO* pump)
{ {
LLFastTimer t(FTM_PROCESS_HTTP_HEADER);
PUMP_DEBUG; PUMP_DEBUG;
LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER); LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
if(eos) if(eos)
@@ -636,6 +643,8 @@ void LLHTTPResponder::markBad(
<< "</body>\n</html>\n"; << "</body>\n</html>\n";
} }
static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_RESPONDER("HTTP Responder");
// virtual // virtual
LLIOPipe::EStatus LLHTTPResponder::process_impl( LLIOPipe::EStatus LLHTTPResponder::process_impl(
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
@@ -644,6 +653,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
LLSD& context, LLSD& context,
LLPumpIO* pump) LLPumpIO* pump)
{ {
LLFastTimer t(FTM_PROCESS_HTTP_RESPONDER);
PUMP_DEBUG; PUMP_DEBUG;
LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER); LLMemType m1(LLMemType::MTYPE_IO_HTTP_SERVER);
LLIOPipe::EStatus status = STATUS_OK; LLIOPipe::EStatus status = STATUS_OK;

View File

@@ -42,6 +42,7 @@
#include "llmemtype.h" #include "llmemtype.h"
#include "llpumpio.h" #include "llpumpio.h"
#include "llthread.h" #include "llthread.h"
#include "llfasttimer.h"
// //
// constants // constants
@@ -290,6 +291,8 @@ LLIOSocketReader::~LLIOSocketReader()
//lldebugs << "Destroying LLIOSocketReader" << llendl; //lldebugs << "Destroying LLIOSocketReader" << llendl;
} }
static LLFastTimer::DeclareTimer FTM_PROCESS_SOCKET_READER("Socket Reader");
// virtual // virtual
LLIOPipe::EStatus LLIOSocketReader::process_impl( LLIOPipe::EStatus LLIOSocketReader::process_impl(
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
@@ -298,6 +301,7 @@ LLIOPipe::EStatus LLIOSocketReader::process_impl(
LLSD& context, LLSD& context,
LLPumpIO* pump) LLPumpIO* pump)
{ {
LLFastTimer t(FTM_PROCESS_SOCKET_READER);
PUMP_DEBUG; PUMP_DEBUG;
LLMemType m1(LLMemType::MTYPE_IO_TCP); LLMemType m1(LLMemType::MTYPE_IO_TCP);
if(!mSource) return STATUS_PRECONDITION_NOT_MET; if(!mSource) return STATUS_PRECONDITION_NOT_MET;
@@ -390,6 +394,7 @@ LLIOSocketWriter::~LLIOSocketWriter()
//lldebugs << "Destroying LLIOSocketWriter" << llendl; //lldebugs << "Destroying LLIOSocketWriter" << llendl;
} }
static LLFastTimer::DeclareTimer FTM_PROCESS_SOCKET_WRITER("Socket Writer");
// virtual // virtual
LLIOPipe::EStatus LLIOSocketWriter::process_impl( LLIOPipe::EStatus LLIOSocketWriter::process_impl(
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
@@ -398,6 +403,7 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(
LLSD& context, LLSD& context,
LLPumpIO* pump) LLPumpIO* pump)
{ {
LLFastTimer t(FTM_PROCESS_SOCKET_WRITER);
PUMP_DEBUG; PUMP_DEBUG;
LLMemType m1(LLMemType::MTYPE_IO_TCP); LLMemType m1(LLMemType::MTYPE_IO_TCP);
if(!mDestination) return STATUS_PRECONDITION_NOT_MET; if(!mDestination) return STATUS_PRECONDITION_NOT_MET;
@@ -542,6 +548,7 @@ void LLIOServerSocket::setResponseTimeout(F32 timeout_secs)
mResponseTimeout = timeout_secs; mResponseTimeout = timeout_secs;
} }
static LLFastTimer::DeclareTimer FTM_PROCESS_SERVER_SOCKET("Server Socket");
// virtual // virtual
LLIOPipe::EStatus LLIOServerSocket::process_impl( LLIOPipe::EStatus LLIOServerSocket::process_impl(
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
@@ -550,6 +557,7 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
LLSD& context, LLSD& context,
LLPumpIO* pump) LLPumpIO* pump)
{ {
LLFastTimer t(FTM_PROCESS_SERVER_SOCKET);
PUMP_DEBUG; PUMP_DEBUG;
LLMemType m1(LLMemType::MTYPE_IO_TCP); LLMemType m1(LLMemType::MTYPE_IO_TCP);
if(!pump) if(!pump)

View File

@@ -34,6 +34,7 @@
#include "linden_common.h" #include "linden_common.h"
#include "llioutil.h" #include "llioutil.h"
#include "llfasttimer.h"
/** /**
* LLIOFlush * LLIOFlush
@@ -49,6 +50,8 @@ LLIOPipe::EStatus LLIOFlush::process_impl(
return STATUS_OK; return STATUS_OK;
} }
static LLFastTimer::DeclareTimer FTM_PROCESS_SLEEP("IO Sleep");
/** /**
* @class LLIOSleep * @class LLIOSleep
*/ */
@@ -59,6 +62,7 @@ LLIOPipe::EStatus LLIOSleep::process_impl(
LLSD& context, LLSD& context,
LLPumpIO* pump) LLPumpIO* pump)
{ {
LLFastTimer t(FTM_PROCESS_SLEEP);
if(mSeconds > 0.0) if(mSeconds > 0.0)
{ {
if(pump) pump->sleepChain(mSeconds); if(pump) pump->sleepChain(mSeconds);
@@ -68,6 +72,7 @@ LLIOPipe::EStatus LLIOSleep::process_impl(
return STATUS_DONE; return STATUS_DONE;
} }
static LLFastTimer::DeclareTimer FTM_PROCESS_ADD_CHAIN("Add Chain");
/** /**
* @class LLIOAddChain * @class LLIOAddChain
*/ */
@@ -78,6 +83,7 @@ LLIOPipe::EStatus LLIOAddChain::process_impl(
LLSD& context, LLSD& context,
LLPumpIO* pump) LLPumpIO* pump)
{ {
LLFastTimer t(FTM_PROCESS_ADD_CHAIN);
pump->addChain(mChain, mTimeout); pump->addChain(mChain, mTimeout);
return STATUS_DONE; return STATUS_DONE;
} }

View File

@@ -191,18 +191,7 @@ LLPumpIO::LLPumpIO(void) :
LLPumpIO::~LLPumpIO() LLPumpIO::~LLPumpIO()
{ {
LLMemType m1(LLMemType::MTYPE_IO_PUMP); LLMemType m1(LLMemType::MTYPE_IO_PUMP);
#if LL_THREADS_APR cleanup();
if (mChainsMutex) apr_thread_mutex_destroy(mChainsMutex);
if (mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex);
#endif
mChainsMutex = NULL;
mCallbackMutex = NULL;
if(mPollset)
{
// lldebugs << "cleaning up pollset" << llendl;
apr_pollset_destroy(mPollset);
mPollset = NULL;
}
} }
bool LLPumpIO::addChain(const chain_t& chain, F32 timeout) bool LLPumpIO::addChain(const chain_t& chain, F32 timeout)
@@ -447,11 +436,13 @@ void LLPumpIO::pump()
pump(DEFAULT_POLL_TIMEOUT); pump(DEFAULT_POLL_TIMEOUT);
} }
static LLFastTimer::DeclareTimer FTM_PUMP_IO("Pump IO");
//timeout is in microseconds //timeout is in microseconds
void LLPumpIO::pump(const S32& poll_timeout) void LLPumpIO::pump(const S32& poll_timeout)
{ {
LLMemType m1(LLMemType::MTYPE_IO_PUMP); LLMemType m1(LLMemType::MTYPE_IO_PUMP);
LLFastTimer t1(LLFastTimer::FTM_PUMPIO); LLFastTimer t1(FTM_PUMP_IO);
//llinfos << "LLPumpIO::pump()" << llendl; //llinfos << "LLPumpIO::pump()" << llendl;
// Run any pending runners. // Run any pending runners.
@@ -779,6 +770,8 @@ bool LLPumpIO::respond(
return true; return true;
} }
static LLFastTimer::DeclareTimer FTM_PUMP_CALLBACK_CHAIN("Chain");
void LLPumpIO::callback() void LLPumpIO::callback()
{ {
LLMemType m1(LLMemType::MTYPE_IO_PUMP); LLMemType m1(LLMemType::MTYPE_IO_PUMP);
@@ -800,6 +793,7 @@ void LLPumpIO::callback()
callbacks_t::iterator end = mCallbacks.end(); callbacks_t::iterator end = mCallbacks.end();
for(; it != end; ++it) for(; it != end; ++it)
{ {
LLFastTimer t(FTM_PUMP_CALLBACK_CHAIN);
// it's always the first and last time for respone chains // it's always the first and last time for respone chains
(*it).mHead = (*it).mChainLinks.begin(); (*it).mHead = (*it).mChainLinks.begin();
(*it).mInit = true; (*it).mInit = true;
@@ -839,6 +833,22 @@ void LLPumpIO::initialize(void)
apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, mPool()); apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, mPool());
#endif #endif
} }
void LLPumpIO::cleanup()
{
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
#if LL_THREADS_APR
if (mChainsMutex) apr_thread_mutex_destroy(mChainsMutex);
if (mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex);
#endif
mChainsMutex = NULL;
mCallbackMutex = NULL;
if(mPollset)
{
// lldebugs << "cleaning up pollset" << llendl;
apr_pollset_destroy(mPollset);
mPollset = NULL;
}
}
void LLPumpIO::rebuildPollset() void LLPumpIO::rebuildPollset()
{ {

View File

@@ -397,6 +397,7 @@ protected:
protected: protected:
void initialize(); void initialize();
void cleanup();
/** /**
* @brief Given the internal state of the chains, rebuild the pollset * @brief Given the internal state of the chains, rebuild the pollset

Some files were not shown because too many files have changed in this diff Show More