Compare commits

..

162 Commits

Author SHA1 Message Date
Siana Gearz
8e19372adf Merge branch 'V2Baking' of git://github.com/Shyotl/SingularityViewer into V2Baking
Conflicts:
	indra/llrender/llshadermgr.cpp
	indra/newview/llmorphview.cpp
	indra/newview/lltexlayer.cpp
	indra/newview/lltexlayer.h
	indra/newview/lltoolmorph.cpp
	indra/newview/llvoavatar.cpp
	indra/newview/llvoavatar.h
2012-01-06 14:18:46 +01:00
Siana Gearz
b911e86b02 Merge branch 'future' of git://github.com/Shyotl/SingularityViewer 2012-01-06 10:40:05 +01: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
6381e4d9a4 Merge branch 'future' into V2Baking 2011-10-31 20:41:58 -05:00
Shyotl
6964cec6f1 Merge branch 'master' of git://github.com/siana/SingularityViewer.git into future 2011-10-31 20:41:36 -05:00
Shyotl
d9f674218f Lineending fixup 2011-10-31 20:38:41 -05:00
Shyotl
693e3a0555 vary_texture_index only needed in shaders when batching. 2011-10-31 20:38:29 -05:00
Shyotl
8376e890b2 Hide the mouse cursor a bit better when grabbing items in mouselook. 2011-10-31 20:37:11 -05:00
Shyotl
33827bf8b0 Added a bit of debug output for viewer tool states. 2011-10-31 20:36:47 -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
Shyotl
06349951d2 Added tracking of requested(and pending) attachments. Moved Ascent code out of attach/detach functions and into their own for better manageability. 2011-10-27 21:41:19 -05: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
4d68dc7c57 LLTexLayer refactored. Tried to keep behavior changes as minimal as possible. Consider as base slate for changes required for multi-wearables. 2011-10-25 16:50:39 -05:00
Shyotl
722e7d09ff Innitial commit. Majority of texture baking moved into LLVOAvatarSelf. Very WIP. Not advisable to build off of this, although it does compile and mostly work. 2011-10-22 20:36:04 -05: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
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
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
Siana Gearz
cdebc1c5cc Version 1.5.10(2) 2011-08-09 03:57:57 +02:00
848 changed files with 56731 additions and 22771 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

@@ -113,7 +113,7 @@ if (WINDOWS)
endif (WINDOWS)
set (GCC_EXTRA_OPTIMIZATION "-ffast-math -frounding-math")
set (GCC_EXTRA_OPTIMIZATIONS "-ffast-math -frounding-math")
if (LINUX)
set(CMAKE_SKIP_RPATH TRUE)
@@ -182,53 +182,29 @@ if (LINUX)
-pthread
)
if (SERVER)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-60")
if (EXISTS /etc/debian_version)
FILE(READ /etc/debian_version DEBIAN_VERSION)
else (EXISTS /etc/debian_version)
set(DEBIAN_VERSION "")
endif (EXISTS /etc/debian_version)
if (NOT DEBIAN_VERSION STREQUAL "3.1")
add_definitions(-DCTYPE_WORKAROUND)
endif (NOT DEBIAN_VERSION STREQUAL "3.1")
if (EXISTS /usr/lib/mysql4/mysql)
link_directories(/usr/lib/mysql4/mysql)
endif (EXISTS /usr/lib/mysql4/mysql)
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)
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)
# this stops us requiring a really recent glibc at runtime
add_definitions(-fno-stack-protector)
endif (NOT STANDALONE)
if (${ARCH} STREQUAL "x86_64")
add_definitions(-DLINUX64=1 -pipe)
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")
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")
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)
# this stops us requiring a really recent glibc at runtime
add_definitions(-fno-stack-protector)
set(MARCH_FLAG " -march=pentium4")
endif (NOT STANDALONE)
if (${ARCH} STREQUAL "x86_64")
add_definitions(-DLINUX64=1 -pipe)
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")
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")
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_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")
set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG} -msse2")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 ${CMAKE_CXX_FLAGS_RELEASE}")
@@ -258,13 +234,13 @@ endif (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)
set(GCC_WARNINGS "${GCC_WARNINGS} -Werror")
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_CXX_FLAGS "${GCC_CXX_WARNINGS} ${CMAKE_CXX_FLAGS}")
@@ -298,10 +274,6 @@ if(1 EQUAL 1)
add_definitions(-DMESH_ENABLED=1)
endif(1 EQUAL 1)
if(SERVER)
include_directories(${LIBS_PREBUILT_DIR}/include/havok)
endif(SERVER)
SET( CMAKE_EXE_LINKER_FLAGS_RELEASESSE2
"${CMAKE_EXE_LINKER_FLAGS_RELEASE}" CACHE STRING
"Flags used for linking binaries under SSE2 build."

View File

@@ -6,6 +6,11 @@ set(DB_FIND_REQUIRED ON)
if (STANDALONE)
include(FindBerkeleyDB)
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)
endif (STANDALONE)

View File

@@ -35,7 +35,7 @@ set(cmake_SOURCE_FILES
FindNDOF.cmake
FindOpenJPEG.cmake
FindXmlRpcEpi.cmake
FMOD.cmake
FMOD.cmake
FreeType.cmake
GStreamer010Plugin.cmake
GooglePerfTools.cmake
@@ -84,6 +84,10 @@ set(cmake_SOURCE_FILES
ZLIB.cmake
)
if(FMODEX)
list(APPEND cmake_SOURCE_FILES FMODEX.cmake)
endif(FMODEX)
source_group("Shared Rules" FILES ${cmake_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_files
libtcmalloc_minimal.dll
fmod.dll
libhunspell.dll
libapr-1.dll
libaprutil-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(
${release_src_dir}

View File

@@ -6,6 +6,7 @@ set(install_dir "@CMAKE_SOURCE_DIR@/..")
set(scp "@SCP_EXECUTABLE@")
set(scripts_dir "@SCRIPTS_DIR@")
set(sentinel_dir "@CMAKE_BINARY_DIR@/prepare")
set(prebuilt_type "@PREBUILT_TYPE@")
# In proprietary mode we use scp for download.
set(proprietary "@INSTALL_PROPRIETARY@")
@@ -19,7 +20,7 @@ foreach(package ${packages})
# This package is missing or out of date.
message(STATUS "Obtaining${proprietary_message} prebuilt '${package}'")
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}
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}
)
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.")
if(LLCOMMON_LINK_SHARED)

View File

@@ -5,4 +5,10 @@ set(LLPLUGIN_INCLUDE_DIRS
${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 -*-
include(Prebuilt)
if (NOT STANDALONE)
if (NOT (STANDALONE OR DARWIN))
use_prebuilt_binary(glext)
# possible glh_linear should have its own .cmake file instead
#use_prebuilt_binary(glh_linear)
# actually... not any longer, it's now in git -SG
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")
set(DARWIN 1)
# NOTE: If specifying a different SDK with CMAKE_OSX_SYSROOT at configure
# time you should also specify CMAKE_OSX_DEPLOYMENT_TARGET explicitly,
# 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
#SDK Compiler and Deployment targets for XCode
if (${XCODE_VERSION} VERSION_LESS 4.0.0)
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk)
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5)
endif (NOT CMAKE_OSX_DEPLOYMENT_TARGET)
set(CMAKE_XCODE_ATTIBUTE_GCC_VERSION "4.2")
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
if (${CMAKE_OSX_SYSROOT} MATCHES "10.5")
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "4.2")
endif (${CMAKE_OSX_SYSROOT} MATCHES "10.5")
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.5)
# NOTE: To attempt an i386/PPC Universal build, add this on the configure line:
# -DCMAKE_OSX_ARCHITECTURES:STRING='i386;ppc'
@@ -118,6 +110,17 @@ if (${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
set(GRID agni CACHE STRING "Target Grid")

View File

@@ -1,105 +1,84 @@
# Main CMakeLists.txt to build the OpenJPEG project using CMake (www.cmake.org)
# Written by Mathieu Malaterre
# -*- cmake -*-
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
project(openjpeg)
IF(COMMAND CMAKE_POLICY)
CMAKE_POLICY(SET CMP0003 NEW)
ENDIF(COMMAND CMAKE_POLICY)
include(00-Common)
PROJECT(openjpeg)
# Do full dependency headers.
INCLUDE_REGULAR_EXPRESSION("^.*$")
#-----------------------------------------------------------------------------
# OPENJPEG version number, useful for packaging and doxygen doc:
SET(OPENJPEG_VERSION_MAJOR 1)
SET(OPENJPEG_VERSION_MINOR 4)
SET(OPENJPEG_VERSION_BUILD 0)
SET(OPENJPEG_VERSION
set(OPENJPEG_VERSION_MAJOR 1)
set(OPENJPEG_VERSION_MINOR 4)
set(OPENJPEG_VERSION_BUILD 0)
set(OPENJPEG_VERSION
"${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
# 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}"
SOVERSION "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}"
)
# On Visual Studio 8 MS deprecated C. This removes all 1.276E1265 security
# 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
set_target_properties(openjpeg 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;
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;
while( --numres) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Herv<EFBFBD> Drolon, FreeImage Team
* Copyright (c) 2005, Hervé Drolon, FreeImage Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,41 +26,6 @@
#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) {
if(cinfo) {
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{
OPJ_PROG_ORDER enum_prog;
char str_prog[4];
char str_prog[5];
}j2k_prog_order_t;
j2k_prog_order_t j2k_prog_order_list[] = {

View File

@@ -38,7 +38,7 @@ list(APPEND linux_crash_logger_SOURCE_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})
@@ -47,11 +47,18 @@ target_link_libraries(linux-crash-logger
${LLVFS_LIBRARIES}
${LLXML_LIBRARIES}
${LLMESSAGE_LIBRARIES}
${LLUI_LIBRARIES}
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES}
${UI_LIBRARIES}
${DB_LIBRARIES}
${XMLRPCEPI_LIBRARIES}
${CURL_LIBRARIES}
${APR_LIBRARIES}
${APRUTIL_LIBRARIES}
${CRYPTO_LIBRARIES}
rt
)
add_custom_command(

View File

@@ -5,16 +5,30 @@ project(llaudio)
include(00-Common)
include(Audio)
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(LLCommon)
include(LLMath)
include(LLMessage)
include(LLVFS)
if(FMODEX)
include_directories(${FMODEX_INCLUDE_DIR})
endif(FMODEX)
if(FMOD)
include_directories(${FMOD_INCLUDE_DIR})
endif(FMOD)
include_directories(
${LLAUDIO_INCLUDE_DIRS}
${FMOD_INCLUDE_DIR}
${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
@@ -46,6 +60,19 @@ set(llaudio_HEADER_FILES
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)
list(APPEND llaudio_SOURCE_FILES
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
class LLSD;
// Entirely abstract. Based exactly on the historic API.
class LLStreamingAudioInterface
{
@@ -51,6 +53,7 @@ class LLStreamingAudioInterface
virtual void setGain(F32 vol) = 0;
virtual F32 getGain() = 0;
virtual std::string getURL() = 0;
virtual const LLSD *getMetaData() = 0; //return NULL if not supported.
};
#endif // LL_STREAMINGAUDIO_H

View File

@@ -51,6 +51,8 @@ public:
const std::string& getURL() { return mInternetStreamURL; }
int getOpenState();
FSOUND_STREAM* getStream() { return mInternetStream; }
protected:
FSOUND_STREAM* mInternetStream;
bool mReady;
@@ -66,7 +68,8 @@ protected:
LLStreamingAudio_FMOD::LLStreamingAudio_FMOD() :
mCurrentInternetStreamp(NULL),
mFMODInternetStreamChannel(-1),
mGain(1.0f)
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.
@@ -87,6 +90,17 @@ LLStreamingAudio_FMOD::~LLStreamingAudio_FMOD()
// 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)
{
@@ -104,6 +118,10 @@ void LLStreamingAudio_FMOD::start(const std::string& url)
llinfos << "Starting internet stream: " << url << llendl;
mCurrentInternetStreamp = new LLAudioStreamManagerFMOD(url);
mURL = url;
if(mCurrentInternetStreamp->getStream())
{
mMetaData = new LLSD;
}
}
else
{
@@ -154,6 +172,10 @@ void LLStreamingAudio_FMOD::update()
// Reset volume to previously set volume
setGain(getGain());
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
break;
}
}
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)
{
FSOUND_SetPaused(mFMODInternetStreamChannel, true);

View File

@@ -54,6 +54,7 @@ class LLStreamingAudio_FMOD : public LLStreamingAudioInterface
/*virtual*/ void setGain(F32 vol);
/*virtual*/ F32 getGain();
/*virtual*/ std::string getURL();
/*virtual*/ const LLSD *getMetaData(){return mMetaData;} //return NULL if not supported.
private:
LLAudioStreamManagerFMOD *mCurrentInternetStreamp;
@@ -62,6 +63,8 @@ private:
std::string mURL;
F32 mGain;
LLSD *mMetaData;
};

View File

@@ -0,0 +1,427 @@
/**
* @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);
}
}
///////////////////////////////////////////////////////
// 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,80 @@
/**
* @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*/ const LLSD *getMetaData(){return mMetaData;} //return NULL if not supported.
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

@@ -33,6 +33,7 @@
#define WINDGEN_H
#include "llcommon.h"
#include "llrand.h"
template <class MIXBUFFERFORMAT_T>
class LLWindGen
@@ -60,7 +61,9 @@ public:
}
const U32 getInputSamplingRate() { return mInputSamplingRate; }
const F32 getNextSample();
const F32 getClampedSample(bool clamp, F32 sample);
// newbuffer = the buffer passed from the previous DSP unit.
// numsamples = length in samples-per-channel at this mix time.
// NOTE: generates L/R interleaved stereo
@@ -95,7 +98,7 @@ public:
// Start with white noise
// 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
// 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)
{
mLastSample = mLastSample + delta;
S32 sample_right = (S32)(mLastSample * mCurrentPanGainR);
S32 sample_left = (S32)mLastSample - sample_right;
MIXBUFFERFORMAT_T sample_right = (MIXBUFFERFORMAT_T)getClampedSample(clip, mLastSample * mCurrentPanGainR);
MIXBUFFERFORMAT_T sample_left = (MIXBUFFERFORMAT_T)getClampedSample(clip, mLastSample - (F32)sample_right);
if (!clip)
{
*cursamplep = (MIXBUFFERFORMAT_T)sample_left;
++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;
}
*cursamplep = sample_left;
++cursamplep;
*cursamplep = sample_right;
++cursamplep;
}
}
@@ -179,4 +172,9 @@ private:
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

View File

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

View File

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

View File

@@ -153,10 +153,10 @@ const char LAND_LAYER_CODE = 'L';
const char WATER_LAYER_CODE = 'W';
const char WIND_LAYER_CODE = '7';
const char CLOUD_LAYER_CODE = '8';
// Extended land layer for Aurora Sim
// 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_WATER_LAYER_CODE = 'X';
const char AURORA_WIND_LAYER_CODE = '9';
const char AURORA_CLOUD_LAYER_CODE = ':';
// keys

View File

@@ -72,11 +72,9 @@ public:
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,
@@ -136,14 +134,21 @@ public:
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_FACE_GET_GEOM,
FTM_FACE_GEOM_POSITION,
FTM_FACE_GEOM_NORMAL,
FTM_FACE_GEOM_TEXTURE,
FTM_FACE_GEOM_COLOR,
FTM_FACE_GEOM_EMISSIVE,
FTM_FACE_GEOM_WEIGHTS,
FTM_FACE_GEOM_BINORMAL,
FTM_FACE_GEOM_INDEX,
FTM_REBUILD_BRIDGE_VB,
FTM_REBUILD_HUD_VB,
FTM_REBUILD_TERRAIN_VB,
@@ -217,6 +222,13 @@ public:
FTM_TEMP6,
FTM_TEMP7,
FTM_TEMP8,
FTM_TEMP9,
FTM_TEMP10,
FTM_TEMP11,
FTM_TEMP12,
FTM_TEMP13,
FTM_TEMP14,
FTM_TEMP15,
FTM_OTHER, // Special, used by display code

View File

@@ -194,7 +194,12 @@ public:
}
protected:
LLInstanceTracker(KEY key) { add_(key); }
LLInstanceTracker(KEY key)
{
// make sure static data outlives all instances
getStatic();
add_(key);
}
virtual ~LLInstanceTracker()
{
// it's unsafe to delete instances of this type while all instances are being iterated over.
@@ -282,7 +287,8 @@ public:
protected:
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));
}
virtual ~LLInstanceTracker()

File diff suppressed because it is too large Load Diff

View File

@@ -40,9 +40,6 @@
#endif
#include "llerror.h"
//----------------------------------------------------------------------------
#if LL_DEBUG
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
#endif // LL_DEBUG
#ifndef __DEBUG_PRIVATE_MEM__
#define __DEBUG_PRIVATE_MEM__ 0
#endif
class LL_COMMON_API LLMemory
{
public:
@@ -130,14 +131,399 @@ public:
// Return value is zero if not known.
static U64 getCurrentRSS();
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:
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 (U32)lhs->getBuffer() < (U32)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(U32 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:
#include "llpointer.h"
#include "llrefcount.h"
#include "llsingleton.h"
#include "llsafehandle.h"
#endif
#endif

View File

@@ -39,13 +39,11 @@
#include <iostream>
#include "apr_base64.h"
#if MESH_ENABLED
#ifdef LL_STANDALONE
# include <zlib.h>
#else
# include "zlib/zlib.h" // for davep's dirty little zip functions
#endif
#endif //MESH_ENABLED
#if !LL_WINDOWS
#include <netinet/in.h> // htonl & ntohl
@@ -1999,8 +1997,6 @@ std::ostream& operator<<(std::ostream& s, const LLSD& llsd)
return s;
}
#if MESH_ENABLED
//dirty little zippers -- yell at davep if these are horrid
//return a string containing gzipped bytes of binary serialized LLSD
@@ -2176,4 +2172,3 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
free(result);
return true;
}
#endif //MESH_ENABLED

View File

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

View File

@@ -42,17 +42,17 @@ template <class Object> class LLStrider
U8* mBytep;
};
U32 mSkip;
U32 mTypeSize;
//U32 mTypeSize;
public:
LLStrider() { mObjectp = NULL; mTypeSize = mSkip = sizeof(Object); }
LLStrider() { mObjectp = NULL; /*mTypeSize = */mSkip = sizeof(Object); }
~LLStrider() { }
const LLStrider<Object>& operator = (Object *first) { mObjectp = first; return *this;}
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;}
U32 getSkip() const { return mSkip; }
Object* get() { return mObjectp; }
@@ -61,7 +61,7 @@ public:
Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; }
Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; }
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);
@@ -125,7 +125,7 @@ public:
source+=elem_size;
}
}
}
}*/
};
#endif // LL_LLSTRIDER_H

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
// change this variable (which really SHOULD have been inside
// the critical area of the mSignal lock)].
llinfos << "LLThread::staticRun() Exiting: " << name << llendl;
lldebugs << "LLThread::staticRun() Exiting: " << name << llendl;
return NULL;
}

View File

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

View File

@@ -45,6 +45,7 @@
#include "llimagepng.h"
#include "llimagedxt.h"
#include "llimageworker.h"
#include "llmemory.h"
//---------------------------------------------------------------------------
// LLImage
@@ -53,12 +54,14 @@
//static
std::string LLImage::sLastErrorMessage;
LLMutex* LLImage::sMutex = NULL;
LLPrivateMemoryPool* LLImageBase::sPrivatePoolp = NULL ;
//static
void LLImage::initClass()
{
sMutex = new LLMutex;
LLImageJ2C::openDSO();
LLImageBase::createPrivatePool() ;
}
//static
@@ -67,6 +70,8 @@ void LLImage::cleanupClass()
LLImageJ2C::closeDSO();
delete sMutex;
sMutex = NULL;
LLImageBase::destroyPrivatePool() ;
}
//static
@@ -105,6 +110,25 @@ LLImageBase::~LLImageBase()
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
void LLImageBase::dump()
{
@@ -138,7 +162,7 @@ void LLImageBase::sanityCheck()
// virtual
void LLImageBase::deleteData()
{
delete[] mData;
FREE_MEM(sPrivatePoolp, mData) ;
mData = NULL;
mDataSize = 0;
}
@@ -164,14 +188,14 @@ U8* LLImageBase::allocateData(S32 size)
if (!mData || size != mDataSize)
{
deleteData(); // virtual
mBadBufferAllocation = FALSE ;
mData = new (std::nothrow) U8[size];
mBadBufferAllocation = false ;
mData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
if (!mData)
{
llwarns << "allocate image data: " << size << llendl;
size = 0 ;
mWidth = mHeight = 0 ;
mBadBufferAllocation = TRUE ;
mBadBufferAllocation = true ;
}
mDataSize = size;
}
@@ -186,7 +210,7 @@ U8* LLImageBase::reallocateData(S32 size)
return mData;
LLMemType mt1((LLMemType::EMemType)mMemType);
U8 *new_datap = new (std::nothrow) U8[size];
U8 *new_datap = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
if (!new_datap)
{
llwarns << "Out of memory in LLImageBase::reallocateData" << llendl;
@@ -196,7 +220,7 @@ U8* LLImageBase::reallocateData(S32 size)
{
S32 bytes = llmin(mDataSize, size);
memcpy(new_datap, mData, bytes); /* Flawfinder: ignore */
delete[] mData;
FREE_MEM(sPrivatePoolp, mData) ;
}
mData = new_datap;
mDataSize = size;
@@ -276,11 +300,11 @@ LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
++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)
{
createFromFile(filename, j2c_lowest_mip_only);
}
}*/
LLImageRaw::~LLImageRaw()
{
@@ -346,10 +370,11 @@ BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
return TRUE;
}
#if 0
U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const
{
LLMemType mt1((LLMemType::EMemType)mMemType);
U8 *data = new (std::nothrow) U8[width*height*getComponents()];
LLMemType mt1(mMemType);
U8 *data = new U8[width*height*getComponents()];
// Should do some simple bounds checking
if (!data)
@@ -366,6 +391,7 @@ U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const
}
return data;
}
#endif
BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
const U8 *data, U32 stride, BOOL reverse_y)
@@ -856,11 +882,11 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
delete[] temp_buffer;
}
#if 0
//scale down image by not blending a pixel with its neighbors.
BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height)
{
LLMemType mt1((LLMemType::EMemType)mMemType);
LLMemType mt1(mMemType);
S8 c = getComponents() ;
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_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) ;
U8* old_data = getData() ;
@@ -902,6 +928,7 @@ BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height)
return TRUE ;
}
#endif
BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
{
@@ -1222,7 +1249,7 @@ file_extensions[] =
{ "png", IMG_CODEC_PNG }
};
#define NUM_FILE_EXTENSIONS LL_ARRAY_SIZE(file_extensions)
#if 0
static std::string find_file(std::string &name, S8 *codec)
{
std::string tname;
@@ -1240,7 +1267,7 @@ static std::string find_file(std::string &name, S8 *codec)
}
return std::string("");
}
#endif
EImageCodec LLImageBase::getCodecFromExtension(const std::string& exten)
{
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;
}
#if 0
bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip_only)
{
std::string name = filename;
@@ -1336,7 +1363,7 @@ bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip
return true;
}
#endif
//---------------------------------------------------------------------------
// LLImageFormatted
//---------------------------------------------------------------------------
@@ -1568,7 +1595,7 @@ void LLImageFormatted::appendData(U8 *data, S32 size)
S32 newsize = cursize + size;
reallocateData(newsize);
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 LLImageRaw;
class LLColor4U;
class LLPrivateMemoryPool;
typedef enum e_image_codec
{
@@ -144,6 +145,9 @@ public:
static EImageCodec getCodecFromExtension(const std::string& exten);
static void createPrivatePool() ;
static void destroyPrivatePool() ;
static LLPrivateMemoryPool* getPrivatePool() {return sPrivatePoolp;}
private:
U8 *mData;
S32 mDataSize;
@@ -155,6 +159,8 @@ private:
bool mBadBufferAllocation ;
bool mAllowOverSize ;
static LLPrivateMemoryPool* sPrivatePoolp ;
public:
S16 mMemType; // debug
};
@@ -170,7 +176,7 @@ public:
LLImageRaw(U16 width, U16 height, S8 components);
LLImageRaw(U8 *data, U16 width, U16 height, S8 components);
// 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*/ U8* allocateData(S32 size = -1);
@@ -178,7 +184,7 @@ public:
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,
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 biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
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
void fill( const LLColor4U& color );
@@ -232,7 +238,7 @@ public:
protected:
// 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 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 total_bytes = getDataSize();
U8* olddata = getData();
U8* newdata = new (std::nothrow) U8[total_bytes];
U8* newdata = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), total_bytes);
if (!newdata)
{
llerrs << "Out of memory in LLImageDXT::convertToDXR()" << llendl;

View File

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

View File

@@ -226,7 +226,7 @@ BOOL LLInventoryObject::importLegacyStream(std::istream& input_stream)
}
// 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
{
std::string uuid_str;

View File

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

View File

@@ -60,7 +60,7 @@ inline void LLMatrix3a::setTranspose(const LLMatrix3a& src)
const LLQuad srcCol1 = src.mColumns[1];
const LLQuad unpacklo = _mm_unpacklo_ps( srcCol0, srcCol1 );
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) );
}

View File

@@ -104,25 +104,45 @@ public:
mMatrix[2].setAdd(a.mMatrix[2],d2);
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));
res.mul(mMatrix[0]);
LLVector4a y;
y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
y.mul(mMatrix[1]);
LLVector4a x,y,z;
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));
x.mul(mMatrix[0]);
y.mul(mMatrix[1]);
z.mul(mMatrix[2]);
res.add(y);
res.add(z);
x.add(y);
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;

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,13 @@ LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL ge
mFaceMask = 0x0;
mDetail = detail;
mSculptLevel = -2;
#if MESH_ENABLED
mIsMeshAssetLoaded = FALSE;
mLODScaleBias.setVec(1,1,1);
mHullPoints = NULL;
mHullIndices = NULL;
mNumHullPoints = 0;
mNumHullIndices = 0;
#endif //MESH_ENABLED
// set defaults
if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE)
{
@@ -2139,12 +2137,10 @@ LLVolume::~LLVolume()
mProfilep = NULL;
mVolumeFaces.clear();
#if MESH_ENABLED
ll_aligned_free_16(mHullPoints);
mHullPoints = NULL;
ll_aligned_free_16(mHullIndices);
mHullIndices = NULL;
#endif //MESH_ENABLED
}
BOOL LLVolume::generate()
@@ -2406,7 +2402,6 @@ bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs
return retval;
}
#if MESH_ENABLED
bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
{
//input stream is now pointing at a zlib compressed block of LLSD
@@ -2736,7 +2731,7 @@ void LLVolume::cacheOptimize()
mVolumeFaces[i].cacheOptimize();
}
}
#endif //MESH_ENABLED
S32 LLVolume::getNumFaces() const
{
@@ -3205,12 +3200,10 @@ bool LLVolumeParams::isSculpt() const
return mSculptID.notNull();
}
#if MESH_ENABLED
bool LLVolumeParams::isMeshSculpt() const
{
return isSculpt() && ((mSculptType & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH);
}
#endif //MESH_ENABLED
bool LLVolumeParams::operator==(const LLVolumeParams &params) const
{
@@ -4320,15 +4313,25 @@ S32 LLVolume::getNumTriangleIndices() const
}
S32 LLVolume::getNumTriangles() const
S32 LLVolume::getNumTriangles(S32* vcount) const
{
U32 triangle_count = 0;
U32 vertex_count = 0;
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;
}
@@ -4357,13 +4360,11 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
vertices.clear();
normals.clear();
#if MESH_ENABLED
if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
{
return;
}
#endif //MESH_ENABLED
S32 cur_index = 0;
//for each face
for (face_list_t::iterator iter = mVolumeFaces.begin();
@@ -5414,9 +5415,7 @@ LLVolumeFace::LLVolumeFace() :
mBinormals(NULL),
mTexCoords(NULL),
mIndices(NULL),
#if MESH_ENABLED
mWeights(NULL),
#endif //MESH_ENABLED
mOctree(NULL)
{
mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
@@ -5439,9 +5438,7 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)
mBinormals(NULL),
mTexCoords(NULL),
mIndices(NULL),
#if MESH_ENABLED
mWeights(NULL),
#endif //MESH_ENABLED
mOctree(NULL)
{
mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
@@ -5507,7 +5504,6 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
mBinormals = NULL;
}
#if MESH_ENABLED
if (src.mWeights)
{
allocateWeights(src.mNumVertices);
@@ -5518,8 +5514,8 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
ll_aligned_free_16(mWeights);
mWeights = NULL;
}
#endif //MESH_ENABLED
}
if (mNumIndices)
{
S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF;
@@ -5551,10 +5547,8 @@ void LLVolumeFace::freeData()
mIndices = NULL;
ll_aligned_free_16(mBinormals);
mBinormals = NULL;
#if MESH_ENABLED
ll_aligned_free_16(mWeights);
mWeights = NULL;
#endif //MESH_ENABLED
delete mOctree;
mOctree = NULL;
@@ -6125,13 +6119,11 @@ void LLVolumeFace::cacheOptimize()
S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
LLVector2* tc = (LLVector2*) ll_aligned_malloc_16(size);
#if MESH_ENABLED
LLVector4a* wght = NULL;
if (mWeights)
{
wght = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
}
#endif //MESH_ENABLED
LLVector4a* binorm = NULL;
if (mBinormals)
@@ -6155,12 +6147,10 @@ void LLVolumeFace::cacheOptimize()
pos[cur_idx] = mPositions[idx];
norm[cur_idx] = mNormals[idx];
tc[cur_idx] = mTexCoords[idx];
#if MESH_ENABLED
if (mWeights)
{
wght[cur_idx] = mWeights[idx];
}
#endif //MESH_ENABLED
if (mBinormals)
{
binorm[cur_idx] = mBinormals[idx];
@@ -6178,17 +6168,13 @@ void LLVolumeFace::cacheOptimize()
ll_aligned_free_16(mPositions);
ll_aligned_free_16(mNormals);
ll_aligned_free_16(mTexCoords);
#if MESH_ENABLED
ll_aligned_free_16(mWeights);
#endif //MESH_ENABLED
ll_aligned_free_16(mBinormals);
mPositions = pos;
mNormals = norm;
mTexCoords = tc;
#if MESH_ENABLED
mWeights = wght;
#endif //MESH_ENABLED
mBinormals = binorm;
//std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks);
@@ -6276,6 +6262,7 @@ void LLVolumeFace::swapData(LLVolumeFace& rhs)
llswap(rhs.mNumVertices, mNumVertices);
llswap(rhs.mNumIndices, mNumIndices);
}
void LerpPlanarVertex(LLVolumeFace::VertexData& v0,
LLVolumeFace::VertexData& v1,
LLVolumeFace::VertexData& v2,
@@ -6971,14 +6958,11 @@ void LLVolumeFace::allocateBinormals(S32 num_verts)
mBinormals = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
}
#if MESH_ENABLED
void LLVolumeFace::allocateWeights(S32 num_verts)
{
ll_aligned_free_16(mWeights);
mWeights = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
}
#endif //MESH_ENABLED
void LLVolumeFace::resizeIndices(S32 num_indices)
{
@@ -7141,9 +7125,8 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
{
resizeVertices(num_vertices);
resizeIndices(num_indices);
#if MESH_ENABLED
if (!volume->isMeshAssetLoaded())
#endif //MESH_ENABLED
{
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_PLANE = 3;
const U8 LL_SCULPT_TYPE_CYLINDER = 4;
#if MESH_ENABLED
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 |
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_MIRROR = 128;
#if MESH_ENABLED
const S32 LL_SCULPT_MESH_MAX_FACES = 8;
#endif //MESH_ENABLED
class LLProfileParams
{
@@ -655,9 +648,7 @@ public:
const LLUUID& getSculptID() const { return mSculptID; }
const U8& getSculptType() const { return mSculptType; }
bool isSculpt() const;
#if MESH_ENABLED
bool isMeshSculpt() const;
#endif //MESH_ENABLED
bool isMeshSculpt() const;
BOOL isConvex() const;
// 'begin' and 'end' should be in range [0, 1] (they will be clamped)
@@ -865,9 +856,7 @@ public:
void resizeVertices(S32 num_verts);
void allocateBinormals(S32 num_verts);
#if MESH_ENABLED
void allocateWeights(S32 num_verts);
#endif //MESH_ENABLED
void resizeIndices(S32 num_indices);
void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx);
@@ -939,12 +928,10 @@ public:
std::vector<S32> mEdge;
#if MESH_ENABLED
//list of skin weights for rigged volumes
// format is mWeights[vertex_index].mV[influence] = <joint_index>.<weight>
// mWeights.size() should be empty or match mVertices.size()
LLVector4a* mWeights;
#endif //MESH_ENABLED
LLOctreeNode<LLVolumeTriangle>* mOctree;
@@ -958,12 +945,7 @@ class LLVolume : public LLRefCount
{
friend class LLVolumeLODGroup;
#if MESH_ENABLED
protected:
#endif //MESH_ENABLED
#if !MESH_ENABLED
private:
#endif //!MESH_ENABLED
LLVolume(const LLVolume&); // Don't implement
~LLVolume(); // use unref
@@ -1016,7 +998,7 @@ public:
S32 getNumTriangleIndices() const;
static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);
S32 getNumTriangles() const;
S32 getNumTriangles(S32* vcount = NULL) const;
void generateSilhouetteVertices(std::vector<LLVector3> &vertices,
std::vector<LLVector3> &normals,
@@ -1081,37 +1063,32 @@ private:
protected:
BOOL generate();
void createVolumeFaces();
#if MESH_ENABLED
public:
virtual bool unpackVolumeFaces(std::istream& is, S32 size);
virtual void setMeshAssetLoaded(BOOL loaded);
virtual BOOL isMeshAssetLoaded();
#endif //MESH_ENABLED
protected:
BOOL mUnique;
F32 mDetail;
S32 mSculptLevel;
#if MESH_ENABLED
BOOL mIsMeshAssetLoaded;
#endif //MESH_ENABLED
LLVolumeParams mParams;
LLPath *mPathp;
LLProfile *mProfilep;
std::vector<Point> mMesh;
BOOL mGenerateSingleFace;
typedef std::vector<LLVolumeFace> face_list_t;
face_list_t mVolumeFaces;
#if MESH_ENABLED
public:
LLVector4a* mHullPoints;
U16* mHullIndices;
S32 mNumHullPoints;
S32 mNumHullIndices;
#endif //MESH_ENABLED
};
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);
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)
{
mDataMutex->unlock();

View File

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

View File

@@ -39,13 +39,10 @@
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 DEFAULT_MAX_PRIM_SCALE = 256.f;
#if MESH_ENABLED
const F32 DEFAULT_MAX_PRIM_SCALE_NO_MESH = DEFAULT_MAX_PRIM_SCALE;
#endif //MESH_ENABLED
const F32 MIN_PRIM_SCALE = 0.01f;
const F32 MAX_PRIM_SCALE = 65536.f; // something very high but not near FLT_MAX
class LLXform
{
protected:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -90,7 +90,7 @@ int LLPluginInstance::load(std::string &plugin_file)
#if LL_LINUX && defined(LL_STANDALONE)
void *dso_handle = dlopen(plugin_file.c_str(), RTLD_NOW | RTLD_GLOBAL);
int result = (!dso_handle)?APR_EDSOOPEN:apr_os_dso_handle_put(&mDSOHandle,
dso_handle, AIAPRRootPool::get()());
dso_handle, LLAPRRootPool::get()());
#else
int result = apr_dso_load(&mDSOHandle,
plugin_file.c_str(),

View File

@@ -277,6 +277,14 @@ LLPluginSharedMemoryPlatformImpl::~LLPluginSharedMemoryPlatformImpl()
bool LLPluginSharedMemory::map(void)
{
llassert(mSize);
if (!mSize)
{
LL_DEBUGS("Plugin") << "Tried to mmap zero length" << LL_ENDL;
return false;
}
llassert(mImpl->mSharedMemoryFD != -1);
llassert(fcntl(mImpl->mSharedMemoryFD, F_GETFL) != -1);
mMappedAddress = ::mmap(NULL, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, mImpl->mSharedMemoryFD, 0);
if(mMappedAddress == NULL)
{

View File

@@ -82,10 +82,6 @@ if (DARWIN)
)
endif (DARWIN)
if (LINUX)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lrt")
endif (LINUX)
if (WINDOWS)
set_target_properties(SLPlugin
PROPERTIES

View File

@@ -26,7 +26,6 @@
#include "linden_common.h"
#if MESH_ENABLED
#include "llmodel.h"
#include "llmemory.h"
#if MESH_IMPORT
@@ -1020,16 +1019,10 @@ void LLModel::setVolumeFaceData(
face.resizeVertices(num_verts);
face.resizeIndices(num_indices);
if(!pos.isStrided())
LLVector4a::memcpyNonAliased16((F32*) face.mPositions, (F32*) pos.get(), num_verts*4*sizeof(F32));
else
for(U32 i=0;i<num_verts;++i) face.mPositions[i].load3(pos[i].mV);
LLVector4a::memcpyNonAliased16((F32*) face.mPositions, (F32*) pos.get(), num_verts*4*sizeof(F32));
if (norm.get())
{
if(!norm.isStrided())
LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32));
else
for(U32 i=0;i<num_verts;++i) face.mNormals[i].load3(norm[i].mV);
LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32));
}
else
{
@@ -1039,10 +1032,7 @@ void LLModel::setVolumeFaceData(
if (tc.get())
{
if(!tc.isStrided())
LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32));
else
for(U32 i=0;i<num_verts;++i) face.mTexCoords[i] = tc[i].mV;
LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32));
}
else
{
@@ -2471,4 +2461,4 @@ void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs)
mPhysicsShapeMesh = rhs->mPhysicsShapeMesh;
}
}
#endif //MESH_ENABLED

View File

@@ -109,10 +109,8 @@ public:
PARAMS_LIGHT = 0x20,
PARAMS_SCULPT = 0x30,
PARAMS_LIGHT_IMAGE = 0x40,
#if MESH_ENABLED
PARAMS_RESERVED = 0x50, // Used on server-side
PARAMS_MESH = 0x60,
#endif //MESH_ENABLED
};
public:

View File

@@ -174,8 +174,8 @@ void LLTextureAnim::unpackTAMessage(LLDataPacker &dp)
mMode = data[0];
mFace = data[1];
mSizeX = llmax((U8)1, data[2]);
mSizeY = llmax((U8)1, data[3]);
mSizeX = data[2];
mSizeY = data[3];
htonmemcpy(&mStart, data + 4, MVT_F32, sizeof(F32));
htonmemcpy(&mLength, data + 8, MVT_F32, sizeof(F32));
htonmemcpy(&mRate, data + 12, MVT_F32, sizeof(F32));

View File

@@ -42,6 +42,7 @@
#include "m4math.h"
#include "llrender.h"
#include "llglslshader.h"
#include "llglheaders.h"
@@ -201,7 +202,7 @@ void LLCubeMap::enableTexture(S32 stage)
void LLCubeMap::enableTextureCoords(S32 stage)
{
mTextureCoordStage = stage;
if (gGLManager.mHasCubeMap && stage >= 0 && LLCubeMap::sUseCubeMaps)
if (!LLGLSLShader::sNoFixedFunction && gGLManager.mHasCubeMap && stage >= 0 && LLCubeMap::sUseCubeMaps)
{
if (stage > 0)
{
@@ -243,7 +244,7 @@ void LLCubeMap::disableTexture(void)
void LLCubeMap::disableTextureCoords(void)
{
if (gGLManager.mHasCubeMap && mTextureCoordStage >= 0 && LLCubeMap::sUseCubeMaps)
if (!LLGLSLShader::sNoFixedFunction && gGLManager.mHasCubeMap && mTextureCoordStage >= 0 && LLCubeMap::sUseCubeMaps)
{
if (mTextureCoordStage > 0)
{
@@ -265,47 +266,47 @@ void LLCubeMap::setMatrix(S32 stage)
if (mMatrixStage < 0) return;
//if (stage > 0)
if (stage > 0)
{
gGL.getTexUnit(stage)->activate();
}
LLVector3 x(LLVector3d(gGLModelView+0));
LLVector3 y(LLVector3d(gGLModelView+4));
LLVector3 z(LLVector3d(gGLModelView+8));
LLVector3 x(gGLModelView+0);
LLVector3 y(gGLModelView+4);
LLVector3 z(gGLModelView+8);
LLMatrix3 mat3;
mat3.setRows(x,y,z);
LLMatrix4 trans(mat3);
trans.transpose();
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadMatrixf((F32 *)trans.mMatrix);
glMatrixMode(GL_MODELVIEW);
gGL.matrixMode(LLRender::MM_TEXTURE);
gGL.pushMatrix();
gGL.loadMatrix((F32 *)trans.mMatrix);
gGL.matrixMode(LLRender::MM_MODELVIEW);
/*if (stage > 0)
if (stage > 0)
{
gGL.getTexUnit(0)->activate();
}*/
}
}
void LLCubeMap::restoreMatrix()
{
if (mMatrixStage < 0) return;
//if (mMatrixStage > 0)
if (mMatrixStage > 0)
{
gGL.getTexUnit(mMatrixStage)->activate();
}
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
gGL.matrixMode(LLRender::MM_TEXTURE);
gGL.popMatrix();
gGL.matrixMode(LLRender::MM_MODELVIEW);
/*if (mMatrixStage > 0)
if (mMatrixStage > 0)
{
gGL.getTexUnit(0)->activate();
}*/
}
}
void LLCubeMap::setReflection (void)

View File

@@ -83,48 +83,12 @@ F32 llfont_round_y(F32 y)
return y;
}
// static
U8 LLFontGL::getStyleFromString(const std::string &style)
{
S32 ret = 0;
if (style.find("NORMAL") != style.npos)
{
ret |= NORMAL;
}
if (style.find("BOLD") != style.npos)
{
ret |= BOLD;
}
if (style.find("ITALIC") != style.npos)
{
ret |= ITALIC;
}
if (style.find("UNDERLINE") != style.npos)
{
ret |= UNDERLINE;
}
if (style.find("SHADOW") != style.npos)
{
ret |= DROP_SHADOW;
}
if (style.find("SOFT_SHADOW") != style.npos)
{
ret |= DROP_SHADOW_SOFT;
}
return ret;
}
LLFontGL::LLFontGL()
: LLFont()
{
clearEmbeddedChars();
}
LLFontGL::LLFontGL(const LLFontGL &source)
{
llerrs << "Not implemented!" << llendl;
}
LLFontGL::~LLFontGL()
{
clearEmbeddedChars();
@@ -153,60 +117,6 @@ void LLFontGL::reset()
resetBitmapCache();
}
// static
std::string LLFontGL::getFontPathSystem()
{
std::string system_path;
// Try to figure out where the system's font files are stored.
char *system_root = NULL;
#if LL_WINDOWS
system_root = getenv("SystemRoot"); /* Flawfinder: ignore */
if (!system_root)
{
llwarns << "SystemRoot not found, attempting to load fonts from default path." << llendl;
}
#endif
if (system_root)
{
system_path = llformat("%s/fonts/", system_root);
}
else
{
#if LL_WINDOWS
// HACK for windows 98/Me
system_path = "/WINDOWS/FONTS/";
#elif LL_DARWIN
// HACK for Mac OS X
system_path = "/System/Library/Fonts/";
#endif
}
return system_path;
}
// static
std::string LLFontGL::getFontPathLocal()
{
std::string local_path;
// Backup files if we can't load from system fonts directory.
// We could store this in an end-user writable directory to allow
// end users to switch fonts.
if (LLFontGL::sAppDir.length())
{
// use specified application dir to look for fonts
local_path = LLFontGL::sAppDir + "/fonts/";
}
else
{
// assume working directory is executable directory
local_path = "./fonts/";
}
return local_path;
}
bool findOrCreateFont(LLFontGL*& fontp, const LLFontDescriptor& desc)
{
// Don't delete existing fonts, if any, here, because they've
@@ -215,86 +125,13 @@ bool findOrCreateFont(LLFontGL*& fontp, const LLFontDescriptor& desc)
return (fontp != NULL);
}
// static
BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale,
const std::string& app_dir,
const std::vector<std::string>& xui_paths,
bool create_gl_textures)
{
bool succ = true;
sVertDPI = (F32)llfloor(screen_dpi * y_scale);
sHorizDPI = (F32)llfloor(screen_dpi * x_scale);
sScaleX = x_scale;
sScaleY = y_scale;
sAppDir = app_dir;
// Font registry init
if (!sFontRegistry)
{
sFontRegistry = new LLFontRegistry(xui_paths,create_gl_textures);
sFontRegistry->parseFontInfo("fonts.xml");
}
else
{
sFontRegistry->reset();
}
// Force standard fonts to get generated up front.
// This is primarily for error detection purposes.
succ &= (NULL != getFontSansSerifSmall());
succ &= (NULL != getFontSansSerif());
succ &= (NULL != getFontSansSerifBig());
succ &= (NULL != getFontSansSerifHuge());
succ &= (NULL != getFontSansSerifBold());
succ &= (NULL != getFontMonospace());
succ &= (NULL != getFontExtChar());
return succ;
}
// static
void LLFontGL::destroyDefaultFonts()
{
// Remove the actual fonts.
delete sFontRegistry;
sFontRegistry = NULL;
}
//static
void LLFontGL::destroyAllGL()
{
if (sFontRegistry)
{
if (LLFont::sOpenGLcrashOnRestart)
{
// This will leak memory but will prevent a crash...
sFontRegistry = NULL;
}
else
{
sFontRegistry->destroyGL();
}
}
}
void LLFontGL::destroyGL()
{
mFontBitmapCachep->destroyGL();
}
LLFontGL &LLFontGL::operator=(const LLFontGL &source)
{
llerrs << "Not implemented" << llendl;
return *this;
}
BOOL LLFontGL::loadFace(const std::string& filename,
const F32 point_size, const F32 vert_dpi, const F32 horz_dpi,
const S32 components, BOOL is_fallback)
BOOL LLFontGL::loadFace(const std::string& filename, const F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback)
{
if (!LLFont::loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback))
{
@@ -303,53 +140,6 @@ BOOL LLFontGL::loadFace(const std::string& filename,
return TRUE;
}
//static
LLFontGL* LLFontGL::getFontMonospace()
{
return getFont(LLFontDescriptor("Monospace","Monospace",0));
}
//static
LLFontGL* LLFontGL::getFontSansSerifSmall()
{
return getFont(LLFontDescriptor("SansSerif","Small",0));
}
//static
LLFontGL* LLFontGL::getFontSansSerif()
{
return getFont(LLFontDescriptor("SansSerif","Medium",0));
}
//static
LLFontGL* LLFontGL::getFontSansSerifBig()
{
return getFont(LLFontDescriptor("SansSerif","Large",0));
}
//static
LLFontGL* LLFontGL::getFontSansSerifHuge()
{
return getFont(LLFontDescriptor("SansSerif","Huge",0));
}
//static
LLFontGL* LLFontGL::getFontSansSerifBold()
{
return getFont(LLFontDescriptor("SansSerif","Medium",BOLD));
}
//static
LLFontGL* LLFontGL::getFontExtChar()
{
return getFontSansSerif();
}
//static
LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc)
{
return sFontRegistry->getFont(desc);
}
BOOL LLFontGL::addChar(const llwchar wch) const
{
@@ -368,30 +158,33 @@ BOOL LLFontGL::addChar(const llwchar wch) const
return TRUE;
}
S32 LLFontGL::renderUTF8(const std::string &text, const S32 offset,
const F32 x, const F32 y,
const LLColor4 &color,
const HAlign halign, const VAlign valign,
U8 style,
const S32 max_chars, const S32 max_pixels,
F32* right_x,
BOOL use_ellipses) const
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_embedded, BOOL use_ellipses) const
{
LLWString wstr = utf8str_to_wstring(text);
return render(wstr, offset, x, y, color, halign, valign, style, max_chars, max_pixels, right_x, FALSE, use_ellipses);
F32 x = rect.mLeft;
F32 y = 0.f;
switch(valign)
{
case TOP:
y = rect.mTop;
break;
case VCENTER:
y = rect.getCenterY();
break;
case BASELINE:
case BOTTOM:
y = rect.mBottom;
break;
default:
y = rect.mBottom;
break;
}
return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, rect.getWidth(), right_x, use_embedded, use_ellipses);
}
S32 LLFontGL::render(const LLWString &wstr,
const S32 begin_offset,
const F32 x, const F32 y,
const LLColor4 &color,
const HAlign halign, const VAlign valign,
U8 style,
const S32 max_chars, S32 max_pixels,
F32* right_x,
BOOL use_embedded,
BOOL use_ellipses) const
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_embedded, BOOL use_ellipses) const
{
if(!sDisplayFont) //do not display texts
{
@@ -411,19 +204,19 @@ S32 LLFontGL::render(const LLWString &wstr,
style = style & (~getFontDesc().getStyle());
F32 drop_shadow_strength = 0.f;
if (style & (DROP_SHADOW | DROP_SHADOW_SOFT))
if (shadow != NO_SHADOW)
{
F32 luminance;
color.calcHSL(NULL, NULL, &luminance);
drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, 1.f);
if (luminance < 0.35f)
{
style = style & ~(DROP_SHADOW | DROP_SHADOW_SOFT);
shadow = NO_SHADOW;
}
}
gGL.pushMatrix();
glLoadIdentity();
gGL.loadIdentity();
gGL.translatef(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ);
// this code snaps the text origin to a pixel grid to start with
@@ -557,19 +350,19 @@ S32 LLFontGL::render(const LLWString &wstr,
LLRectf uv_rect(0.f, 1.f, 1.f, 0.f);
LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y);
drawGlyph(screen_rect, uv_rect, LLColor4::white, style, drop_shadow_strength);
drawGlyph(screen_rect, uv_rect, LLColor4::white, style, shadow, drop_shadow_strength);
if (!label.empty())
{
gGL.pushMatrix();
//glLoadIdentity();
//gGL.loadIdentity();
//gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f);
//glScalef(sScaleX, sScaleY, 1.f);
//gGL.scalef(sScaleX, sScaleY, 1.f);
getFontExtChar()->render(label, 0,
/*llfloor*/((ext_x + (F32)ext_image->getWidth() + EXT_X_BEARING) / sScaleX),
/*llfloor*/(cur_y / sScaleY),
color,
halign, BASELINE, NORMAL, S32_MAX, S32_MAX, NULL,
halign, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL,
TRUE );
gGL.popMatrix();
}
@@ -623,7 +416,7 @@ S32 LLFontGL::render(const LLWString &wstr,
llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,
llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);
drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength);
drawGlyph(screen_rect, uv_rect, color, style, shadow, drop_shadow_strength);
chars_drawn++;
cur_x += fgi->mXAdvance;
@@ -672,15 +465,16 @@ S32 LLFontGL::render(const LLWString &wstr,
// recursively render ellipses at end of string
// we've already reserved enough room
gGL.pushMatrix();
//glLoadIdentity();
//gGL.loadIdentity();
//gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f);
//glScalef(sScaleX, sScaleY, 1.f);
//gGL.scalef(sScaleX, sScaleY, 1.f);
renderUTF8(std::string("..."),
0,
cur_x / sScaleX, (F32)y,
color,
LEFT, valign,
style,
LLFontGL::NO_SHADOW,
S32_MAX, max_pixels,
right_x,
FALSE);
@@ -692,6 +486,25 @@ S32 LLFontGL::render(const LLWString &wstr,
return chars_drawn;
}
S32 LLFontGL::render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const
{
return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
}
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const
{
return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses);
}
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const
{
return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
}
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow) const
{
return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, halign, valign, style, shadow, S32_MAX, S32_MAX, NULL, FALSE);
}
S32 LLFontGL::getWidth(const std::string& utf8text) const
{
@@ -781,7 +594,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S
// Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels
S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars,
BOOL end_on_word_boundary, const BOOL use_embedded,
EWordWrapStyle end_on_word_boundary, const BOOL use_embedded,
F32* drawn_pixels) const
{
if (!wchars || !wchars[0] || max_chars == 0)
@@ -882,10 +695,27 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
drawn_x = cur_x;
}
if( clip && end_on_word_boundary && (start_of_last_word != 0) )
if( clip )
{
i = start_of_last_word;
switch (end_on_word_boundary)
{
case ONLY_WORD_BOUNDARIES:
i = start_of_last_word;
break;
case WORD_BOUNDARY_IF_POSSIBLE:
if (start_of_last_word != 0)
{
i = start_of_last_word;
}
break;
default:
case ANYWHERE:
// do nothing
break;
}
}
if (drawn_pixels)
{
*drawn_pixels = drawn_x;
@@ -1101,100 +931,115 @@ void LLFontGL::removeEmbeddedChar( llwchar wc ) const
}
}
void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const
// static
void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector<std::string>& xui_paths, bool create_gl_textures)
{
gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
gGL.vertex2f(llfont_round_x(screen_rect.mRight),
llfont_round_y(screen_rect.mTop));
sVertDPI = (F32)llfloor(screen_dpi * y_scale);
sHorizDPI = (F32)llfloor(screen_dpi * x_scale);
sScaleX = x_scale;
sScaleY = y_scale;
sAppDir = app_dir;
gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
gGL.vertex2f(llfont_round_x(screen_rect.mLeft),
llfont_round_y(screen_rect.mTop));
gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
gGL.vertex2f(llfont_round_x(screen_rect.mLeft + slant_amt),
llfont_round_y(screen_rect.mBottom));
gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
gGL.vertex2f(llfont_round_x(screen_rect.mRight + slant_amt),
llfont_round_y(screen_rect.mBottom));
}
void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, F32 drop_shadow_strength) const
{
F32 slant_offset;
slant_offset = ((style & ITALIC) ? ( -mAscender * 0.2f) : 0.f);
gGL.begin(LLRender::QUADS);
// Font registry init
if (!sFontRegistry)
{
//FIXME: bold and drop shadow are mutually exclusive only for convenience
//Allow both when we need them.
if (style & BOLD)
{
gGL.color4fv(color.mV);
for (S32 pass = 0; pass < 2; pass++)
{
LLRectf screen_rect_offset = screen_rect;
screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f);
renderQuad(screen_rect_offset, uv_rect, slant_offset);
}
}
else if (style & DROP_SHADOW_SOFT)
{
LLColor4 shadow_color = LLFontGL::sShadowColor;
shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH;
gGL.color4fv(shadow_color.mV);
for (S32 pass = 0; pass < 5; pass++)
{
LLRectf screen_rect_offset = screen_rect;
switch(pass)
{
case 0:
screen_rect_offset.translate(-1.f, -1.f);
break;
case 1:
screen_rect_offset.translate(1.f, -1.f);
break;
case 2:
screen_rect_offset.translate(1.f, 1.f);
break;
case 3:
screen_rect_offset.translate(-1.f, 1.f);
break;
case 4:
screen_rect_offset.translate(0, -2.f);
break;
}
renderQuad(screen_rect_offset, uv_rect, slant_offset);
}
gGL.color4fv(color.mV);
renderQuad(screen_rect, uv_rect, slant_offset);
}
else if (style & DROP_SHADOW)
{
LLColor4 shadow_color = LLFontGL::sShadowColor;
shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength;
gGL.color4fv(shadow_color.mV);
LLRectf screen_rect_shadow = screen_rect;
screen_rect_shadow.translate(1.f, -1.f);
renderQuad(screen_rect_shadow, uv_rect, slant_offset);
gGL.color4fv(color.mV);
renderQuad(screen_rect, uv_rect, slant_offset);
}
else // normal rendering
{
gGL.color4fv(color.mV);
renderQuad(screen_rect, uv_rect, slant_offset);
}
sFontRegistry = new LLFontRegistry(xui_paths,create_gl_textures);
sFontRegistry->parseFontInfo("fonts.xml");
}
else
{
sFontRegistry->reset();
}
gGL.end();
}
// Force standard fonts to get generated up front.
// This is primarily for error detection purposes.
// Don't do this during initClass because it can be slow and we want to get
// the viewer window on screen first. JC
// static
bool LLFontGL::loadDefaultFonts()
{
bool succ = true;
succ &= (NULL != getFontSansSerifSmall());
succ &= (NULL != getFontSansSerif());
succ &= (NULL != getFontSansSerifBig());
succ &= (NULL != getFontSansSerifHuge());
succ &= (NULL != getFontSansSerifBold());
succ &= (NULL != getFontMonospace());
succ &= (NULL != getFontExtChar());
return succ;
}
// static
void LLFontGL::destroyDefaultFonts()
{
// Remove the actual fonts.
delete sFontRegistry;
sFontRegistry = NULL;
}
//static
void LLFontGL::destroyAllGL()
{
if (sFontRegistry)
{
if (LLFont::sOpenGLcrashOnRestart)
{
// This will leak memory but will prevent a crash...
sFontRegistry = NULL;
}
else
{
sFontRegistry->destroyGL();
}
}
}
// static
U8 LLFontGL::getStyleFromString(const std::string &style)
{
S32 ret = 0;
if (style.find("NORMAL") != style.npos)
{
ret |= NORMAL;
}
if (style.find("BOLD") != style.npos)
{
ret |= BOLD;
}
if (style.find("ITALIC") != style.npos)
{
ret |= ITALIC;
}
if (style.find("UNDERLINE") != style.npos)
{
ret |= UNDERLINE;
}
return ret;
}
// static
std::string LLFontGL::getStringFromStyle(U8 style)
{
std::string style_string;
if (style & NORMAL)
{
style_string += "|NORMAL";
}
if (style & BOLD)
{
style_string += "|BOLD";
}
if (style & ITALIC)
{
style_string += "|ITALIC";
}
if (style & UNDERLINE)
{
style_string += "|UNDERLINE";
}
return style_string;
}
std::string LLFontGL::nameFromFont(const LLFontGL* fontp)
{
return fontp->getFontDesc().getName();
@@ -1262,3 +1107,214 @@ LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name)
//else leave baseline
return gl_vfont_align;
}
//static
LLFontGL* LLFontGL::getFontMonospace()
{
static LLFontGL* fontp = getFont(LLFontDescriptor("Monospace","Monospace",0));
return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerifSmall()
{
static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Small",0));
return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerif()
{
static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",0));
return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerifBig()
{
static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0));
return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerifHuge()
{
static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0));
return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerifBold()
{
static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",BOLD));
return fontp;
}
//static
LLFontGL* LLFontGL::getFontExtChar()
{
return getFontSansSerif();
}
//static
LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc)
{
return sFontRegistry->getFont(desc);
}
// static
std::string LLFontGL::getFontPathSystem()
{
std::string system_path;
// Try to figure out where the system's font files are stored.
char *system_root = NULL;
#if LL_WINDOWS
system_root = getenv("SystemRoot"); /* Flawfinder: ignore */
if (!system_root)
{
llwarns << "SystemRoot not found, attempting to load fonts from default path." << llendl;
}
#endif
if (system_root)
{
system_path = llformat("%s/fonts/", system_root);
}
else
{
#if LL_WINDOWS
// HACK for windows 98/Me
system_path = "/WINDOWS/FONTS/";
#elif LL_DARWIN
// HACK for Mac OS X
system_path = "/System/Library/Fonts/";
#endif
}
return system_path;
}
// static
std::string LLFontGL::getFontPathLocal()
{
std::string local_path;
// Backup files if we can't load from system fonts directory.
// We could store this in an end-user writable directory to allow
// end users to switch fonts.
if (LLFontGL::sAppDir.length())
{
// use specified application dir to look for fonts
local_path = LLFontGL::sAppDir + "/fonts/";
}
else
{
// assume working directory is executable directory
local_path = "./fonts/";
}
return local_path;
}
LLFontGL::LLFontGL(const LLFontGL &source)
{
llerrs << "Not implemented!" << llendl;
}
LLFontGL &LLFontGL::operator=(const LLFontGL &source)
{
llerrs << "Not implemented" << llendl;
return *this;
}
void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const
{
gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
gGL.vertex2f(llfont_round_x(screen_rect.mRight),
llfont_round_y(screen_rect.mTop));
gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
gGL.vertex2f(llfont_round_x(screen_rect.mLeft),
llfont_round_y(screen_rect.mTop));
gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
gGL.vertex2f(llfont_round_x(screen_rect.mLeft + slant_amt),
llfont_round_y(screen_rect.mBottom));
gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
gGL.vertex2f(llfont_round_x(screen_rect.mRight + slant_amt),
llfont_round_y(screen_rect.mBottom));
}
void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const
{
F32 slant_offset;
slant_offset = ((style & ITALIC) ? ( -mAscender * 0.2f) : 0.f);
gGL.begin(LLRender::QUADS);
{
//FIXME: bold and drop shadow are mutually exclusive only for convenience
//Allow both when we need them.
if (style & BOLD)
{
gGL.color4fv(color.mV);
for (S32 pass = 0; pass < 2; pass++)
{
LLRectf screen_rect_offset = screen_rect;
screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f);
renderQuad(screen_rect_offset, uv_rect, slant_offset);
}
}
else if (shadow == DROP_SHADOW_SOFT)
{
LLColor4 shadow_color = LLFontGL::sShadowColor;
shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH;
gGL.color4fv(shadow_color.mV);
for (S32 pass = 0; pass < 5; pass++)
{
LLRectf screen_rect_offset = screen_rect;
switch(pass)
{
case 0:
screen_rect_offset.translate(-1.f, -1.f);
break;
case 1:
screen_rect_offset.translate(1.f, -1.f);
break;
case 2:
screen_rect_offset.translate(1.f, 1.f);
break;
case 3:
screen_rect_offset.translate(-1.f, 1.f);
break;
case 4:
screen_rect_offset.translate(0, -2.f);
break;
}
renderQuad(screen_rect_offset, uv_rect, slant_offset);
}
gGL.color4fv(color.mV);
renderQuad(screen_rect, uv_rect, slant_offset);
}
else if (shadow == DROP_SHADOW)
{
LLColor4 shadow_color = LLFontGL::sShadowColor;
shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength;
gGL.color4fv(shadow_color.mV);
LLRectf screen_rect_shadow = screen_rect;
screen_rect_shadow.translate(1.f, -1.f);
renderQuad(screen_rect_shadow, uv_rect, slant_offset);
gGL.color4fv(color.mV);
renderQuad(screen_rect, uv_rect, slant_offset);
}
else // normal rendering
{
gGL.color4fv(color.mV);
renderQuad(screen_rect, uv_rect, slant_offset);
}
}
gGL.end();
}

View File

@@ -73,126 +73,93 @@ public:
enum StyleFlags
{
// text style to render. May be combined (these are bit flags)
NORMAL = 0,
BOLD = 1,
ITALIC = 2,
UNDERLINE = 4,
DROP_SHADOW = 8,
DROP_SHADOW_SOFT = 16
// text style to render. May be combined (these are bit flags)
NORMAL = 0x00,
BOLD = 0x01,
ITALIC = 0x02,
UNDERLINE = 0x04,
};
enum ShadowType
{
NO_SHADOW,
DROP_SHADOW,
DROP_SHADOW_SOFT
};
// Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC"
static U8 getStyleFromString(const std::string &style);
LLFontGL();
LLFontGL(const LLFontGL &source);
~LLFontGL();
void init(); // Internal init, or reinitialization
void reset(); // Reset a font after GL cleanup. ONLY works on an already loaded font.
LLFontGL &operator=(const LLFontGL &source);
static BOOL initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale,
const std::string& app_dir,
const std::vector<std::string>& xui_paths,
bool create_gl_textures = true);
static void destroyDefaultFonts();
static void destroyAllGL();
void destroyGL();
/* virtual*/ BOOL loadFace(const std::string& filename,
const F32 point_size, const F32 vert_dpi, const F32 horz_dpi,
const S32 components, BOOL is_fallback);
/* virtual*/ BOOL loadFace(const std::string& filename, const F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback);
S32 render(const LLWString &text, S32 begin_offset,
const LLRect& rect,
const LLColor4 &color,
HAlign halign = LEFT, VAlign valign = BASELINE,
U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
S32 max_chars = S32_MAX,
F32* right_x=NULL,
BOOL use_embedded = FALSE,
BOOL use_ellipses = FALSE) const;
S32 render(const LLWString &text, S32 begin_offset,
F32 x, F32 y,
const LLColor4 &color,
HAlign halign = LEFT, VAlign valign = BASELINE,
U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX,
F32* right_x=NULL,
BOOL use_embedded = FALSE,
BOOL use_ellipses = FALSE) const;
S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const;
S32 renderUTF8(const std::string &text, const S32 begin_offset,
S32 x, S32 y,
const LLColor4 &color) const
{
return renderUTF8(text, begin_offset, (F32)x, (F32)y, color,
LEFT, BASELINE, NORMAL,
S32_MAX, S32_MAX, NULL, FALSE);
}
S32 renderUTF8(const std::string &text, const S32 begin_offset,
S32 x, S32 y,
const LLColor4 &color,
HAlign halign, VAlign valign, U8 style = NORMAL) const
{
return renderUTF8(text, begin_offset, (F32)x, (F32)y, color,
halign, valign, style,
S32_MAX, S32_MAX, NULL, FALSE);
}
// renderUTF8 does a conversion, so is slower!
S32 renderUTF8(const std::string &text,
S32 begin_offset,
F32 x, F32 y,
const LLColor4 &color,
HAlign halign,
VAlign valign,
U8 style,
S32 max_chars,
S32 max_pixels,
F32* right_x,
BOOL use_ellipses) const;
S32 render(const LLWString &text, const S32 begin_offset,
F32 x, F32 y,
const LLColor4 &color) const
{
return render(text, begin_offset, x, y, color,
LEFT, BASELINE, NORMAL,
S32_MAX, S32_MAX, NULL, FALSE, FALSE);
}
S32 render(const LLWString &text,
S32 begin_offset,
F32 x, F32 y,
const LLColor4 &color,
HAlign halign = LEFT,
VAlign valign = BASELINE,
U8 style = NORMAL,
S32 max_chars = S32_MAX,
S32 max_pixels = S32_MAX,
F32* right_x=NULL,
BOOL use_embedded = FALSE,
BOOL use_ellipses = FALSE) const;
S32 renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const;
S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const;
S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const;
// font metrics - override for LLFont that returns units of virtual pixels
/*virtual*/ F32 getLineHeight() const { return (F32)llround(mLineHeight / sScaleY); }
/*virtual*/ F32 getAscenderHeight() const { return (F32)llround(mAscender / sScaleY); }
/*virtual*/ F32 getDescenderHeight() const { return (F32)llround(mDescender / sScaleY); }
virtual S32 getWidth(const std::string& utf8text) const;
virtual S32 getWidth(const llwchar* wchars) const;
virtual S32 getWidth(const std::string& utf8text, const S32 offset, const S32 max_chars ) const;
virtual S32 getWidth(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE) const;
S32 getWidth(const std::string& utf8text) const;
S32 getWidth(const llwchar* wchars) const;
S32 getWidth(const std::string& utf8text, const S32 offset, const S32 max_chars ) const;
S32 getWidth(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE) const;
virtual F32 getWidthF32(const std::string& utf8text) const;
virtual F32 getWidthF32(const llwchar* wchars) const;
virtual F32 getWidthF32(const std::string& text, const S32 offset, const S32 max_chars ) const;
virtual F32 getWidthF32(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE ) const;
F32 getWidthF32(const std::string& utf8text) const;
F32 getWidthF32(const llwchar* wchars) const;
F32 getWidthF32(const std::string& text, const S32 offset, const S32 max_chars ) const;
F32 getWidthF32(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE ) const;
// The following are called often, frequently with large buffers, so do not use a string interface
// Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels
virtual S32 maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX,
BOOL end_on_word_boundary = FALSE, const BOOL use_embedded = FALSE,
F32* drawn_pixels = NULL) const;
typedef enum e_word_wrap_style
{
ONLY_WORD_BOUNDARIES,
WORD_BOUNDARY_IF_POSSIBLE,
ANYWHERE
} EWordWrapStyle ;
S32 maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, EWordWrapStyle end_on_word_boundary = ANYWHERE,
const BOOL use_embedded = FALSE, F32* drawn_pixels = NULL) const;
// Returns the index of the first complete characters from text that can be drawn in max_pixels
// given that the character at start_pos should be the last character (or as close to last as possible).
virtual S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const;
S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const;
// Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars)
virtual S32 charFromPixelOffset(const llwchar* wchars, const S32 char_offset,
F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX,
BOOL round = TRUE, BOOL use_embedded = FALSE) const;
S32 charFromPixelOffset(const llwchar* wchars, const S32 char_offset, F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, BOOL round = TRUE, BOOL use_embedded = FALSE) const;
const LLFontDescriptor &getFontDesc() const { return mFontDesc; }
void setFontDesc(const LLFontDescriptor& font_desc) { mFontDesc = font_desc; }
LLTexture *getTexture() const;
@@ -200,6 +167,17 @@ public:
void addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& label) const;
void removeEmbeddedChar( llwchar wc ) const;
static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector<std::string>& xui_paths, bool create_gl_textures = true);
// Load sans-serif, sans-serif-small, etc.
// Slow, requires multiple seconds to load fonts.
static bool loadDefaultFonts();
static void destroyDefaultFonts();
static void destroyAllGL();
// Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC"
static U8 getStyleFromString(const std::string &style);
static std::string getStringFromStyle(U8 style);
static std::string nameFromFont(const LLFontGL* fontp);
static std::string nameFromHAlign(LLFontGL::HAlign align);
@@ -220,16 +198,7 @@ protected:
const embedded_data_t* getEmbeddedCharData(const llwchar wch) const;
F32 getEmbeddedCharAdvance(const embedded_data_t* ext_data) const;
void clearEmbeddedChars();
void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const;
void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, F32 drop_shadow_fade) const;
public:
static F32 sVertDPI;
static F32 sHorizDPI;
static F32 sScaleX;
static F32 sScaleY;
static BOOL sDisplayFont ;
static std::string sAppDir; // For loading fonts
static LLFontGL* getFontMonospace();
static LLFontGL* getFontSansSerifSmall();
@@ -240,11 +209,25 @@ public:
static LLFontGL* getFontExtChar();
static LLFontGL* getFont(const LLFontDescriptor& desc);
static std::string getFontPathLocal();
static std::string getFontPathSystem();
static LLCoordFont sCurOrigin;
static std::vector<LLCoordFont> sOriginStack;
static LLColor4 sShadowColor;
static F32 sVertDPI;
static F32 sHorizDPI;
static F32 sScaleX;
static F32 sScaleY;
static BOOL sDisplayFont ;
static std::string sAppDir; // For loading fonts
friend class LLTextBillboard;
friend class LLHUDText;
LLFontGL(const LLFontGL &source);
LLFontGL &operator=(const LLFontGL &source);
protected:
/*virtual*/ BOOL addChar(const llwchar wch) const;
@@ -254,18 +237,12 @@ protected:
LLFontDescriptor mFontDesc;
void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const;
void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const;
// Registry holds all instantiated fonts.
static LLFontRegistry* sFontRegistry;
public:
static std::string getFontPathLocal();
static std::string getFontPathSystem();
static LLCoordFont sCurOrigin;
static std::vector<LLCoordFont> sOriginStack;
const LLFontDescriptor &getFontDesc() const { return mFontDesc; }
void setFontDesc(const LLFontDescriptor& font_desc) { mFontDesc = font_desc; }
};
#endif

View File

@@ -68,6 +68,7 @@ BOOL gGLActive = FALSE;
std::ofstream gFailLog;
#if !LL_DARWIN //Darwin doesn't load extensions that way! -SG
void* gl_get_proc_address(const char *pStr)
{
void* pPtr = (void*)GLH_EXT_GET_PROC_ADDRESS(pStr);
@@ -77,6 +78,37 @@ void* gl_get_proc_address(const char *pStr)
}
#undef GLH_EXT_GET_PROC_ADDRESS
#define GLH_EXT_GET_PROC_ADDRESS(p) gl_get_proc_address(p)
#endif //!LL_DARWIN
#if GL_ARB_debug_output
#ifndef APIENTRY
#define APIENTRY
#endif
void APIENTRY gl_debug_callback(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
GLvoid* userParam)
{
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
{
llwarns << "----- GL ERROR --------" << llendl;
}
else
{
llwarns << "----- GL WARNING -------" << llendl;
}
llwarns << "Type: " << std::hex << type << llendl;
llwarns << "ID: " << std::hex << id << llendl;
llwarns << "Severity: " << std::hex << severity << llendl;
llwarns << "Message: " << message << llendl;
llwarns << "-----------------------" << llendl;
}
#endif
void ll_init_fail_log(std::string filename)
{
@@ -112,6 +144,7 @@ void ll_close_fail_log()
{
gFailLog.close();
}
LLMatrix4 gGLObliqueProjectionInverse;
#define LL_GL_NAME_POOLING 0
@@ -120,6 +153,11 @@ std::list<LLGLUpdate*> LLGLUpdate::sGLQ;
#if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS
// ATI prototypes
#if LL_WINDOWS
PFNGLGETSTRINGIPROC glGetStringi = NULL;
#endif
// vertex blending prototypes
PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB = NULL;
PFNGLVERTEXBLENDARBPROC glVertexBlendARB = NULL;
@@ -138,6 +176,12 @@ PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB = NULL;
PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB = NULL;
//GL_ARB_vertex_array_object
PFNGLBINDVERTEXARRAYPROC glBindVertexArray = NULL;
PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = NULL;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = NULL;
PFNGLISVERTEXARRAYPROC glIsVertexArray = NULL;
// GL_ARB_map_buffer_range
PFNGLMAPBUFFERRANGEPROC glMapBufferRange = NULL;
PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange = NULL;
@@ -207,10 +251,16 @@ PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = NULL;
PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = NULL;
//GL_ARB_texture_multisample
PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
PFNGLSAMPLEMASKIPROC glSampleMaski;
PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample = NULL;
PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample = NULL;
PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv = NULL;
PFNGLSAMPLEMASKIPROC glSampleMaski = NULL;
//GL_ARB_debug_output
PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL;
PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB = NULL;
PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB = NULL;
PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB = NULL;
// GL_EXT_blend_func_separate
PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL;
@@ -259,6 +309,10 @@ PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB = NULL;
PFNGLGETUNIFORMIVARBPROC glGetUniformivARB = NULL;
PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL;
#if LL_WINDOWS
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
#endif
// vertex shader prototypes
#if LL_LINUX || LL_SOLARIS
PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB = NULL;
@@ -331,7 +385,7 @@ PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB = NULL;
PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL;
#if LL_WINDOWS
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
#endif
#if LL_LINUX_NV_GL_HEADERS
@@ -360,6 +414,7 @@ LLGLManager::LLGLManager() :
mHasBlendFuncSeparate(FALSE),
mHasSync(FALSE),
mHasVertexBufferObject(FALSE),
mHasVertexArrayObject(FALSE),
mHasMapBufferRange(FALSE),
mHasFlushBufferRange(FALSE),
mHasPBuffer(FALSE),
@@ -381,6 +436,7 @@ LLGLManager::LLGLManager() :
mHasAnisotropic(FALSE),
mHasARBEnvCombine(FALSE),
mHasCubeMap(FALSE),
mHasDebugOutput(FALSE),
mIsATI(FALSE),
mIsNVIDIA(FALSE),
@@ -420,6 +476,15 @@ void LLGLManager::initWGL()
LL_WARNS("RenderInit") << "No ARB pixel format extensions" << LL_ENDL;
}
if (ExtensionExists("WGL_ARB_create_context",gGLHExts.mSysExts))
{
GLH_EXT_NAME(wglCreateContextAttribsARB) = (PFNWGLCREATECONTEXTATTRIBSARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreateContextAttribsARB");
}
else
{
LL_WARNS("RenderInit") << "No ARB create context extensions" << LL_ENDL;
}
if (ExtensionExists("WGL_EXT_swap_control", gGLHExts.mSysExts))
{
GLH_EXT_NAME(wglSwapIntervalEXT) = (PFNWGLSWAPINTERVALEXTPROC)GLH_EXT_GET_PROC_ADDRESS("wglSwapIntervalEXT");
@@ -449,13 +514,45 @@ bool LLGLManager::initGL()
LL_ERRS("RenderInit") << "Calling init on LLGLManager after already initialized!" << LL_ENDL;
}
GLint alpha_bits;
glGetIntegerv( GL_ALPHA_BITS, &alpha_bits );
if( 8 != alpha_bits )
stop_glerror();
#if LL_WINDOWS
if (!glGetStringi)
{
LL_WARNS("RenderInit") << "Frame buffer has less than 8 bits of alpha. Avatar texture compositing will fail." << LL_ENDL;
glGetStringi = (PFNGLGETSTRINGIPROC) GLH_EXT_GET_PROC_ADDRESS("glGetStringi");
}
//reload extensions string (may have changed after using wglCreateContextAttrib)
if (glGetStringi)
{
std::stringstream str;
GLint count = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &count);
for (GLint i = 0; i < count; ++i)
{
std::string ext((const char*) glGetStringi(GL_EXTENSIONS, i));
str << ext << " ";
LL_DEBUGS("GLExtensions") << ext << llendl;
}
{
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = 0;
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
if(wglGetExtensionsStringARB)
{
str << (const char*) wglGetExtensionsStringARB(wglGetCurrentDC());
}
}
free(gGLHExts.mSysExts);
std::string extensions = str.str();
gGLHExts.mSysExts = strdup(extensions.c_str());
}
#endif
stop_glerror();
// Extract video card strings and convert to upper case to
// work around driver-to-driver variation in capitalization.
mGLVendor = std::string((const char *)glGetString(GL_VENDOR));
@@ -470,7 +567,7 @@ bool LLGLManager::initGL()
&mDriverVersionVendorString );
mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f;
// Trailing space necessary to keep "nVidia Corpor_ati_on" cards
// from being recognized as ATI.
if (mGLVendor.substr(0,4) == "ATI ")
@@ -542,8 +639,10 @@ bool LLGLManager::initGL()
mGLVendorShort = "MISC";
}
stop_glerror();
// This is called here because it depends on the setting of mIsGF2or4MX, and sets up mHasMultitexture.
initExtensions();
stop_glerror();
S32 old_vram = mVRAM;
@@ -565,13 +664,23 @@ bool LLGLManager::initGL()
{ //something likely went wrong using the above extensions, fall back to old method
mVRAM = old_vram;
}
stop_glerror();
stop_glerror();
if (mHasFragmentShader)
{
GLint num_tex_image_units;
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units);
mNumTextureImageUnits = llmin(num_tex_image_units, 32);
}
if (mHasMultitexture)
if (LLRender::sGLCoreProfile)
{
mNumTextureUnits = llmin(mNumTextureImageUnits, MAX_GL_TEXTURE_UNITS);
}
else if (mHasMultitexture)
{
GLint num_tex_units;
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &num_tex_units);
@@ -590,6 +699,7 @@ bool LLGLManager::initGL()
return false;
}
stop_glerror();
if (mHasTextureMultisample)
{
@@ -599,6 +709,16 @@ bool LLGLManager::initGL()
glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
}
stop_glerror();
#if LL_WINDOWS
if (mHasDebugOutput && gDebugGL)
{ //setup debug output callback
glDebugMessageCallbackARB((GLDEBUGPROCARB) gl_debug_callback, NULL);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
}
#endif
stop_glerror();
mHasTextureMultisample = FALSE;
#if LL_WINDOWS
if (mIsATI)
{ //using multisample textures on ATI results in black screen for some reason
@@ -610,10 +730,17 @@ bool LLGLManager::initGL()
{
glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
}
stop_glerror();
setToDebugGPU();
stop_glerror();
initGLStates();
stop_glerror();
return true;
}
@@ -712,47 +839,47 @@ void LLGLManager::initExtensions()
mHasMultitexture = TRUE;
# else
mHasMultitexture = FALSE;
# endif
# endif // GL_ARB_multitexture
# ifdef GL_ARB_texture_env_combine
mHasARBEnvCombine = TRUE;
# else
mHasARBEnvCombine = FALSE;
# endif
# endif // GL_ARB_texture_env_combine
# ifdef GL_ARB_texture_compression
mHasCompressedTextures = TRUE;
# else
mHasCompressedTextures = FALSE;
# endif
# endif // GL_ARB_texture_compression
# ifdef GL_ARB_vertex_buffer_object
mHasVertexBufferObject = TRUE;
# else
mHasVertexBufferObject = FALSE;
# endif
# endif // GL_ARB_vertex_buffer_object
# ifdef GL_EXT_framebuffer_object
mHasFramebufferObject = TRUE;
# else
mHasFramebufferObject = FALSE;
# endif
# endif // GL_EXT_framebuffer_object
# ifdef GL_EXT_framebuffer_multisample
mHasFramebufferMultisample = TRUE;
# else
mHasFramebufferMultisample = FALSE;
# endif
# endif // GL_EXT_framebuffer_multisample
# ifdef GL_ARB_draw_buffers
mHasDrawBuffers = TRUE;
#else
mHasDrawBuffers = FALSE;
# endif
# endif // GL_ARB_draw_buffers
# if defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
mHasDepthClamp = TRUE;
#else
mHasDepthClamp = FALSE;
#endif
#endif // defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
# if GL_EXT_blend_func_separate
mHasBlendFuncSeparate = TRUE;
#else
mHasBlendFuncSeparate = FALSE;
# endif
# endif // GL_EXT_blend_func_separate
mHasMipMapGeneration = FALSE;
mHasSeparateSpecularColor = FALSE;
mHasAnisotropic = FALSE;
@@ -763,7 +890,7 @@ void LLGLManager::initExtensions()
mHasVertexShader = FALSE;
mHasFragmentShader = FALSE;
mHasTextureRectangle = FALSE;
#else // LL_MESA_HEADLESS
#else // LL_MESA_HEADLESS //important, gGLHExts.mSysExts is uninitialized until after glh_init_extensions is called
mHasMultitexture = glh_init_extensions("GL_ARB_multitexture");
mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts);
mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts);
@@ -777,11 +904,12 @@ void LLGLManager::initExtensions()
mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);
mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts);
mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts);
mHasVertexArrayObject = ExtensionExists("GL_ARB_vertex_array_object", gGLHExts.mSysExts);
mHasSync = ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts);
mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts);
mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", gGLHExts.mSysExts);
mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts);
// mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
// mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
#ifdef GL_ARB_framebuffer_object
mHasFramebufferObject = ExtensionExists("GL_ARB_framebuffer_object", gGLHExts.mSysExts);
#else
@@ -795,13 +923,14 @@ void LLGLManager::initExtensions()
mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);
mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts);
#if !LL_DARWIN
mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
#endif
mHasShaderObjects = ExtensionExists("GL_ARB_shader_objects", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts);
mHasShaderObjects = ExtensionExists("GL_ARB_shader_objects", gGLHExts.mSysExts) && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts));
mHasVertexShader = ExtensionExists("GL_ARB_vertex_program", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_vertex_shader", gGLHExts.mSysExts)
&& ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts);
mHasFragmentShader = ExtensionExists("GL_ARB_fragment_shader", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts);
&& (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts));
mHasFragmentShader = ExtensionExists("GL_ARB_fragment_shader", gGLHExts.mSysExts) && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts));
#endif
#if LL_LINUX || LL_SOLARIS
@@ -976,6 +1105,13 @@ void LLGLManager::initExtensions()
mHasVertexBufferObject = FALSE;
}
}
if (mHasVertexArrayObject)
{
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) GLH_EXT_GET_PROC_ADDRESS("glBindVertexArray");
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteVertexArrays");
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) GLH_EXT_GET_PROC_ADDRESS("glGenVertexArrays");
glIsVertexArray = (PFNGLISVERTEXARRAYPROC) GLH_EXT_GET_PROC_ADDRESS("glIsVertexArray");
}
if (mHasSync)
{
glFenceSync = (PFNGLFENCESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glFenceSync");
@@ -1030,6 +1166,13 @@ void LLGLManager::initExtensions()
glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");
glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski");
}
if (mHasDebugOutput)
{
glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageControlARB");
glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageInsertARB");
glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageCallbackARB");
glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetDebugMessageLogARB");
}
#if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS
// This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah
glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements");
@@ -1184,7 +1327,7 @@ void rotate_quat(LLQuaternion& rotation)
{
F32 angle_radians, x, y, z;
rotation.getAngleAxis(&angle_radians, &x, &y, &z);
glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z);
}
void flush_glerror()
@@ -1221,10 +1364,6 @@ void log_glerror()
void do_assert_glerror()
{
if (LL_UNLIKELY(!gGLManager.mInited))
{
LL_ERRS("RenderInit") << "GL not initialized" << LL_ENDL;
}
// Create or update texture to be used with this data
GLenum error;
error = glGetError();
@@ -1319,8 +1458,6 @@ void LLGLState::initClass()
//make sure multisample defaults to disabled
sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE;
glDisable(GL_MULTISAMPLE_ARB);
glEnableClientState(GL_VERTEX_ARRAY);
}
//static
@@ -1370,6 +1507,8 @@ void LLGLState::checkStates(const std::string& msg)
glGetIntegerv(GL_BLEND_SRC, &src);
glGetIntegerv(GL_BLEND_DST, &dst);
stop_glerror();
BOOL error = FALSE;
if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA)
@@ -1390,7 +1529,9 @@ void LLGLState::checkStates(const std::string& msg)
{
LLGLenum state = iter->first;
LLGLboolean cur_state = iter->second;
stop_glerror();
LLGLboolean gl_state = glIsEnabled(state);
stop_glerror();
if(cur_state != gl_state)
{
dumpStates();
@@ -1601,7 +1742,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
error = TRUE;
}
glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &active_texture);
/*glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &active_texture);
if (active_texture != GL_TEXTURE0_ARB)
{
llwarns << "Active texture corrupted: " << active_texture << llendl;
@@ -1610,7 +1751,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
gFailLog << "Active texture corrupted: " << active_texture << std::endl;
}
error = TRUE;
}
}*/
static const char* label[] =
{
@@ -1637,7 +1778,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
};
for (S32 j = 0; j < 4; j++)
for (S32 j = 1; j < 4; j++)
{
if (glIsEnabled(value[j]))
{
@@ -1748,7 +1889,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
}
else
{
LL_GL_ERRS << "GL client array corruption detected. " << msg << LL_ENDL;
LL_GL_ERRS << "GL client array corruption detected. " << msg << LL_ENDL;
}
}
}
@@ -1759,17 +1900,26 @@ LLGLState::LLGLState(LLGLenum state, S32 enabled) :
mState(state), mWasEnabled(FALSE), mIsEnabled(FALSE)
{
if (LLGLSLShader::sNoFixedFunction)
{ //always disable state that's deprecated post GL 3.0
{ //always ignore state that's deprecated post GL 3.0
switch (state)
{
case GL_ALPHA_TEST:
enabled = 0;
break;
case GL_NORMALIZE:
case GL_TEXTURE_GEN_R:
case GL_TEXTURE_GEN_S:
case GL_TEXTURE_GEN_T:
case GL_TEXTURE_GEN_Q:
case GL_LIGHTING:
case GL_COLOR_MATERIAL:
case GL_FOG:
case GL_LINE_STIPPLE:
mState = 0;
break;
}
}
stop_glerror();
if (state)
if (mState)
{
mWasEnabled = sStateMap[state];
llassert(mWasEnabled == glIsEnabled(state));
@@ -1812,7 +1962,7 @@ LLGLState::~LLGLState()
{
if (!gDebugSession)
{
llassert_always(sStateMap[mState] == glIsEnabled(mState));
llassert_always(sStateMap[mState] == glIsEnabled(mState));
}
else
{
@@ -1851,79 +2001,6 @@ void LLGLManager::initGLStates()
////////////////////////////////////////////////////////////////////////////////
void enable_vertex_weighting(const S32 index)
{
#if GL_ARB_vertex_program
if (index > 0) glEnableVertexAttribArrayARB(index); // vertex weights
#endif
}
void disable_vertex_weighting(const S32 index)
{
#if GL_ARB_vertex_program
if (index > 0) glDisableVertexAttribArrayARB(index); // vertex weights
#endif
}
void enable_binormals(const S32 index)
{
#if GL_ARB_vertex_program
if (index > 0)
{
glEnableVertexAttribArrayARB(index); // binormals
}
#endif
}
void disable_binormals(const S32 index)
{
#if GL_ARB_vertex_program
if (index > 0)
{
glDisableVertexAttribArrayARB(index); // binormals
}
#endif
}
void enable_cloth_weights(const S32 index)
{
#if GL_ARB_vertex_program
if (index > 0) glEnableVertexAttribArrayARB(index);
#endif
}
void disable_cloth_weights(const S32 index)
{
#if GL_ARB_vertex_program
if (index > 0) glDisableVertexAttribArrayARB(index);
#endif
}
void set_vertex_weights(const S32 index, const U32 stride, const F32 *weights)
{
#if GL_ARB_vertex_program
if (index > 0) glVertexAttribPointerARB(index, 1, GL_FLOAT, FALSE, stride, weights);
stop_glerror();
#endif
}
void set_vertex_clothing_weights(const S32 index, const U32 stride, const LLVector4 *weights)
{
#if GL_ARB_vertex_program
if (index > 0) glVertexAttribPointerARB(index, 4, GL_FLOAT, TRUE, stride, weights);
stop_glerror();
#endif
}
void set_binormals(const S32 index, const U32 stride,const LLVector3 *binormals)
{
#if GL_ARB_vertex_program
if (index > 0) glVertexAttribPointerARB(index, 3, GL_FLOAT, FALSE, stride, binormals);
stop_glerror();
#endif
}
void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific )
{
// GL_VERSION returns a null-terminated string with the format:
@@ -2036,20 +2113,20 @@ void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
glh::matrix4f suffix;
suffix.set_row(2, cplane);
glh::matrix4f newP = suffix * P;
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadMatrixf(newP.m);
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
gGL.loadMatrix(newP.m);
gGLObliqueProjectionInverse = LLMatrix4(newP.inverse().transpose().m);
glMatrixMode(GL_MODELVIEW);
gGL.matrixMode(LLRender::MM_MODELVIEW);
}
LLGLUserClipPlane::~LLGLUserClipPlane()
{
if (mApply)
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.popMatrix();
gGL.matrixMode(LLRender::MM_MODELVIEW);
}
}
@@ -2238,16 +2315,16 @@ LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f P, U32 layer)
P.element(2, i) = P.element(3, i) * depth;
}
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadMatrixf(P.m);
glMatrixMode(GL_MODELVIEW);
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
gGL.loadMatrix(P.m);
gGL.matrixMode(LLRender::MM_MODELVIEW);
}
LLGLSquashToFarClip::~LLGLSquashToFarClip()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.popMatrix();
gGL.matrixMode(LLRender::MM_MODELVIEW);
}

View File

@@ -95,6 +95,7 @@ public:
// ARB Extensions
BOOL mHasVertexBufferObject;
BOOL mHasVertexArrayObject;
BOOL mHasSync;
BOOL mHasMapBufferRange;
BOOL mHasFlushBufferRange;
@@ -119,6 +120,7 @@ public:
BOOL mHasAnisotropic;
BOOL mHasARBEnvCombine;
BOOL mHasCubeMap;
BOOL mHasDebugOutput;
// Vendor-specific extensions
BOOL mIsATI;
@@ -259,7 +261,7 @@ public:
static void dumpStates();
static void checkStates(const std::string& msg = "");
static void checkTextureChannels(const std::string& msg = "");
static void checkClientArrays(const std::string& msg = "", U32 data_mask = 0x0001);
static void checkClientArrays(const std::string& msg = "", U32 data_mask = 0);
protected:
static boost::unordered_map<LLGLenum, LLGLboolean> sStateMap;
@@ -426,15 +428,7 @@ extern LLMatrix4 gGLObliqueProjectionInverse;
#include "llglstates.h"
void init_glstates();
void enable_vertex_weighting(const S32 index);
void disable_vertex_weighting(const S32 index);
void enable_binormals(const S32 index);
void disable_binormals(const S32 index);
void enable_cloth_weights(const S32 index);
void disable_cloth_weights(const S32 index);
void set_vertex_weights(const S32 index, const U32 stride, const F32 *weights);
void set_vertex_clothing_weights(const S32 index, const U32 stride, const LLVector4 *weights);
void set_binormals(const S32 index, const U32 stride, const LLVector3 *binormals);
void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific );
extern BOOL gClothRipple;

View File

@@ -76,6 +76,12 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
// GL_ARB_vertex_array_object
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
extern PFNGLISVERTEXARRAYPROC glIsVertexArray;
// GL_ARB_sync
extern PFNGLFENCESYNCPROC glFenceSync;
extern PFNGLISSYNCPROC glIsSync;
@@ -316,6 +322,12 @@ extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB;
extern PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements;
#endif // LL_LINUX_NV_GL_HEADERS
// GL_ARB_vertex_array_object
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
extern PFNGLISVERTEXARRAYPROC glIsVertexArray;
// GL_ARB_vertex_buffer_object
extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
@@ -537,6 +549,9 @@ extern PFNGLSAMPLEMASKIPROC glSampleMaski;
#include "GL/glext.h"
#include "GL/glh_extensions.h"
// WGL_ARB_create_context
extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
extern PFNGLGETSTRINGIPROC glGetStringi;
// GL_ARB_vertex_buffer_object
extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
@@ -551,6 +566,12 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
// GL_ARB_vertex_array_object
extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
extern PFNGLISVERTEXARRAYPROC glIsVertexArray;
// GL_ARB_sync
extern PFNGLFENCESYNCPROC glFenceSync;
extern PFNGLISSYNCPROC glIsSync;
@@ -741,6 +762,11 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
extern PFNGLSAMPLEMASKIPROC glSampleMaski;
//GL_ARB_debug_output
extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB;
extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB;
extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
extern PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB;
#elif LL_DARWIN
//----------------------------------------------------------------------------
// LL_DARWIN
@@ -904,6 +930,31 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
#endif /* GL_GLEXT_FUNCTION_POINTERS */
#endif
#ifndef GL_ARB_texture_rg
#define GL_RG 0x8227
#define GL_RG_INTEGER 0x8228
#define GL_R8 0x8229
#define GL_R16 0x822A
#define GL_RG8 0x822B
#define GL_RG16 0x822C
#define GL_R16F 0x822D
#define GL_R32F 0x822E
#define GL_RG16F 0x822F
#define GL_RG32F 0x8230
#define GL_R8I 0x8231
#define GL_R8UI 0x8232
#define GL_R16I 0x8233
#define GL_R16UI 0x8234
#define GL_R32I 0x8235
#define GL_R32UI 0x8236
#define GL_RG8I 0x8237
#define GL_RG8UI 0x8238
#define GL_RG16I 0x8239
#define GL_RG16UI 0x823A
#define GL_RG32I 0x823B
#define GL_RG32UI 0x823C
#endif
// May be needed for DARWIN...
// #ifndef GL_ARB_compressed_tex_image
// #define GL_ARB_compressed_tex_image 1

View File

@@ -58,6 +58,7 @@ using std::string;
GLhandleARB LLGLSLShader::sCurBoundShader = 0;
LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL;
S32 LLGLSLShader::sIndexedTextureChannels = 0;
bool LLGLSLShader::sNoFixedFunction = false;
//UI shader -- declared here so llui_libtest will link properly
@@ -73,12 +74,9 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
LLShaderFeatures::LLShaderFeatures()
: calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
hasTransport(false), hasSkinning(false), hasAtmospherics(false), isSpecular(false),
hasGamma(false), hasLighting(false), calculatesAtmospherics(false)
, mIndexedTextureChannels(0), disableTextureIndex(false), hasAlphaMask(false)
#if MESH_ENABLED
, hasObjectSkinning(false)
#endif //MESH_ENABLED
hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false),
hasGamma(false), hasLighting(false), isAlphaLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false),
hasAlphaMask(false)
{
}
@@ -125,6 +123,12 @@ void LLGLSLShader::unload()
BOOL LLGLSLShader::createShader(vector<string> * attributes,
vector<string> * uniforms)
{
//reloading, reset matrix hash values
for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i)
{
mMatHash[i] = 0xFFFFFFFF;
}
mLightHash = 0xFFFFFFFF;
llassert_always(!mShaderFiles.empty());
BOOL success = TRUE;
@@ -134,8 +138,8 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
mProgramObject = glCreateProgramObjectARB();
static const LLCachedControl<bool> no_texture_indexing("ShyotlUseLegacyTextureBatching",false);
static const LLCachedControl<bool> use_legacy_path("ShyotlUseLegacyRenderPath", false); //Legacy does not jive with new batching.
if (gGLManager.mGLVersion < 3.1f || no_texture_indexing || use_legacy_path)
//static const LLCachedControl<bool> use_legacy_path("ShyotlUseLegacyRenderPath", false); //Legacy does not jive with new batching.
if (gGLManager.mGLVersion < 3.1f || no_texture_indexing /*|| use_legacy_path*/)
{ //force indexed texture channels to 1 if GL version is old (performance improvement for drivers with poor branching shader model support)
mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1);
}
@@ -262,11 +266,11 @@ void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count)
BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes)
{
//before linking, make sure reserved attributes always have consistent locations
/*for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
{
const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str();
glBindAttribLocationARB(mProgramObject, i, (const GLcharARB *) name);
}*/
}
//link the program
BOOL res = link();
@@ -807,13 +811,17 @@ GLint LLGLSLShader::getUniformLocation(const string& uniform)
}
}
/*if (gDebugGL)
return ret;
}
GLint LLGLSLShader::getUniformLocation(U32 index)
{
GLint ret = -1;
if (mProgramObject > 0)
{
if (ret == -1 && ret != glGetUniformLocationARB(mProgramObject, uniform.c_str()))
{
llerrs << "Uniform map invalid." << llendl;
}
}*/
llassert(index < mUniform.size());
return mUniform[index];
}
return ret;
}
@@ -969,7 +977,9 @@ void LLGLSLShader::uniform4fv(const string& uniform, U32 count, const GLfloat* v
std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
{
stop_glerror();
glUniform4fvARB(location, count, v);
stop_glerror();
mValue[location] = vec;
}
}
@@ -1007,12 +1017,6 @@ void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean
}
}
void LLGLSLShader::setAlphaRange(F32 minimum, F32 maximum)
{
uniform1f("minimum_alpha", minimum);
uniform1f("maximum_alpha", maximum);
}
void LLGLSLShader::vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
@@ -1029,3 +1033,9 @@ void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v)
glVertexAttrib4fvARB(mAttribute[index], v);
}
}
void LLGLSLShader::setMinimumAlpha(F32 minimum)
{
gGL.flush();
uniform1f(LLShaderMgr::MINIMUM_ALPHA, minimum);
}

View File

@@ -42,15 +42,14 @@ public:
bool calculatesLighting;
bool calculatesAtmospherics;
bool hasLighting; // implies no transport (it's possible to have neither though)
bool isAlphaLighting; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions
bool isShiny;
bool isFullbright; // implies no lighting
bool isSpecular;
bool hasWaterFog; // implies no gamma
bool hasTransport; // implies no lighting (it's possible to have neither though)
bool hasSkinning;
#if MESH_ENABLED
bool hasObjectSkinning;
#endif //MESH_ENABLED
bool hasAtmospherics;
bool hasGamma;
S32 mIndexedTextureChannels;
@@ -77,6 +76,7 @@ public:
static GLhandleARB sCurBoundShader;
static LLGLSLShader* sCurBoundShaderPtr;
static S32 sIndexedTextureChannels;
static bool sNoFixedFunction;
void unload();
@@ -115,16 +115,17 @@ public:
void uniformMatrix3fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
void uniformMatrix4fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
void setAlphaRange(F32 minimum, F32 maximum);
void setMinimumAlpha(F32 minimum);
void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void vertexAttrib4fv(U32 index, GLfloat* v);
GLint getUniformLocation(const std::string& uniform);
GLint getUniformLocation(U32 index);
GLint getAttribLocation(U32 attrib);
GLint mapUniformTextureChannel(GLint location, GLenum type);
//enable/disable texture channel for specified uniform
//if given texture uniform is active in the shader,
//the corresponding channel will be active upon return
@@ -139,6 +140,9 @@ public:
// Unbinds any previously bound shader by explicitly binding no shader.
static void bindNoShader(void);
U32 mMatHash[LLRender::NUM_MATRIX_MODES];
U32 mLightHash;
GLhandleARB mProgramObject;
std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel
std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location

View File

@@ -116,6 +116,7 @@ void LLImageGL::checkTexSize(bool forced) const
glGetIntegerv(GL_VIEWPORT, vp) ;
llcallstacks << "viewport: " << vp[0] << " : " << vp[1] << " : " << vp[2] << " : " << vp[3] << llcallstacksendl ;
}
GLint texname;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname);
BOOL error = FALSE;
@@ -741,7 +742,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
{
if (mAutoGenMips)
{
glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE);
if (!gGLManager.mHasFramebufferObject)
{
glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE);
}
stop_glerror();
{
// LLFastTimer t2(LLFastTimer::FTM_TEMP4);
@@ -770,6 +774,12 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
stop_glerror();
}
}
if (gGLManager.mHasFramebufferObject)
{
//GL_EXT_framebuffer_object implies glGenerateMipmap
glGenerateMipmap(LLTexUnit::getInternalType(mBindTarget));
}
}
else
{
@@ -1031,8 +1041,75 @@ void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate)
// static
void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels)
{
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels);
bool use_scratch = false;
U32* scratch = NULL;
if (LLRender::sGLCoreProfile)
{
if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE)
{ //GL_ALPHA is deprecated, convert to RGBA
use_scratch = true;
scratch = new U32[width*height];
U32 pixel_count = (U32) (width*height);
for (U32 i = 0; i < pixel_count; i++)
{
U8* pix = (U8*) &scratch[i];
pix[0] = pix[1] = pix[2] = 0;
pix[3] = ((U8*) pixels)[i];
}
pixformat = GL_RGBA;
intformat = GL_RGBA8;
}
if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE)
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA
use_scratch = true;
scratch = new U32[width*height];
U32 pixel_count = (U32) (width*height);
for (U32 i = 0; i < pixel_count; i++)
{
U8 lum = ((U8*) pixels)[i*2+0];
U8 alpha = ((U8*) pixels)[i*2+1];
U8* pix = (U8*) &scratch[i];
pix[0] = pix[1] = pix[2] = lum;
pix[3] = alpha;
}
pixformat = GL_RGBA;
intformat = GL_RGBA8;
}
if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE)
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGB
use_scratch = true;
scratch = new U32[width*height];
U32 pixel_count = (U32) (width*height);
for (U32 i = 0; i < pixel_count; i++)
{
U8 lum = ((U8*) pixels)[i];
U8* pix = (U8*) &scratch[i];
pix[0] = pix[1] = pix[2] = lum;
pix[3] = 255;
}
pixformat = GL_RGBA;
intformat = GL_RGB8;
}
}
stop_glerror();
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels);
stop_glerror();
if (use_scratch)
{
delete [] scratch;
}
}
//create an empty GL texture: just create a texture name
@@ -1144,6 +1221,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename)
{
llassert(data_in);
stop_glerror();
if (discard_level < 0)
{
@@ -1171,10 +1249,12 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
LLImageGL::generateTextures(1, &mTexName);
stop_glerror();
{
// LLFastTimer t1(LLFastTimer::FTM_TEMP6);
llverify(gGL.getTexUnit(0)->bind(this));
stop_glerror();
glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0);
stop_glerror();
glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel-discard_level);
stop_glerror();
}
}
if (!mTexName)
@@ -1740,7 +1820,7 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
// this to be an intentional effect and don't treat as a mask.
U32 midrangetotal = 0;
for (U32 i = 4; i < 11; i++)
for (U32 i = 2; i < 13; i++)
{
midrangetotal += sample[i];
}
@@ -1755,7 +1835,7 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
upperhalftotal += sample[i];
}
if (midrangetotal > length/16 || // lots of midrange, or
if (midrangetotal > length/48 || // lots of midrange, or
(lowerhalftotal == length && alphatotal != 0) || // all close to transparent but not all totally transparent, or
(upperhalftotal == length && alphatotal != 255*length)) // all close to opaque but not all totally opaque
{

View File

@@ -76,13 +76,14 @@ public:
static S32 updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category) ;
static bool checkSize(S32 width, S32 height);
//for server side use only.
// Not currently necessary for LLImageGL, but required in some derived classes,
// so include for compatability
static BOOL create(LLPointer<LLImageGL>& dest, BOOL usemipmaps = TRUE);
static BOOL create(LLPointer<LLImageGL>& dest, U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE);
static BOOL create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, BOOL usemipmaps = TRUE);
public:
LLImageGL(BOOL usemipmaps = TRUE);
LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE);

View File

@@ -36,15 +36,13 @@
#include "llglslshader.h"
#include "llsdserialize.h"
#include "llrender.h"
#include "llvertexbuffer.h"
#include "lldir.h"
extern LLGLSLShader gPostColorFilterProgram;
extern LLGLSLShader gPostNightVisionProgram;
extern LLGLSLShader gPostGaussianBlurProgram;
LLPostProcess * gPostProcess = NULL;
static const unsigned int NOISE_SIZE = 512;
/// CALCULATING LUMINANCE (Using NTSC lum weights)
@@ -56,13 +54,12 @@ static const float LUMINANCE_B = 0.114f;
static const char * const XML_FILENAME = "postprocesseffects.xml";
LLPostProcess::LLPostProcess(void) :
initialized(false),
mVBO(NULL),
mAllEffects(LLSD::emptyMap()),
screenW(1), screenH(1)
mScreenWidth(1), mScreenHeight(1)
{
mSceneRenderTexture = NULL ;
mNoiseTexture = NULL ;
mTempBloomTexture = NULL ;
/* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.*/
std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
@@ -82,7 +79,6 @@ LLPostProcess::LLPostProcess(void) :
LLSD & defaultEffect = (mAllEffects["default"] = LLSD::emptyMap());
/*defaultEffect["enable_night_vision"] = LLSD::Boolean(false);
defaultEffect["enable_bloom"] = LLSD::Boolean(false);
defaultEffect["enable_color_filter"] = LLSD::Boolean(false);*/
/// NVG Defaults
@@ -91,13 +87,7 @@ LLPostProcess::LLPostProcess(void) :
defaultEffect["noise_strength"] = 0.4;
// TODO BTest potentially add this to tweaks?
noiseTextureScale = 1.0f;
/// Bloom Defaults
defaultEffect["extract_low"] = 0.95;
defaultEffect["extract_high"] = 1.0;
defaultEffect["bloom_width"] = 2.25;
defaultEffect["bloom_strength"] = 1.5;
mNoiseTextureScale = 1.0f;
/// Color Filter Defaults
defaultEffect["gamma"] = 1.0;
@@ -123,25 +113,10 @@ LLPostProcess::~LLPostProcess(void)
invalidate() ;
}
// static
void LLPostProcess::initClass(void)
/*static*/void LLPostProcess::cleanupClass()
{
//this will cause system to crash at second time login
//if first time login fails due to network connection --- bao
//***llassert_always(gPostProcess == NULL);
//replaced by the following line:
if(gPostProcess)
return ;
gPostProcess = new LLPostProcess();
}
// static
void LLPostProcess::cleanupClass()
{
delete gPostProcess;
gPostProcess = NULL;
if(instanceExists())
getInstance()->invalidate() ;
}
void LLPostProcess::setSelectedEffect(std::string const & effectName)
@@ -152,7 +127,6 @@ void LLPostProcess::setSelectedEffect(std::string const & effectName)
void LLPostProcess::saveEffect(std::string const & effectName)
{
/* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.*/
mAllEffects[effectName] = tweaks;
std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
@@ -163,38 +137,57 @@ void LLPostProcess::saveEffect(std::string const & effectName)
LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
formatter->format(mAllEffects, effectsXML);
//*/
}
void LLPostProcess::invalidate()
{
mSceneRenderTexture = NULL ;
mNoiseTexture = NULL ;
mTempBloomTexture = NULL ;
initialized = FALSE ;
mVBO = NULL ;
}
void LLPostProcess::apply(unsigned int width, unsigned int height)
{
if (!initialized || width != screenW || height != screenH){
initialize(width, height);
}
if (shadersEnabled()){
if(shadersEnabled())
{
if (mVBO.isNull() || width != mScreenWidth || height != mScreenHeight)
{
initialize(width, height);
}
doEffects();
}
}
void LLPostProcess::initialize(unsigned int width, unsigned int height)
{
screenW = width;
screenH = height;
createTexture(mSceneRenderTexture, screenW, screenH);
initialized = true;
invalidate();
mScreenWidth = width;
mScreenHeight = height;
createScreenTexture();
//Setup our VBO.
{
mVBO = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1,3);
mVBO->allocateBuffer(4,0,TRUE);
LLStrider<LLVector3> v;
LLStrider<LLVector2> uv1;
LLStrider<LLVector2> uv2;
mVBO->getVertexStrider(v);
mVBO->getTexCoord0Strider(uv1);
mVBO->getTexCoord1Strider(uv2);
v[0] = LLVector3( uv2[0] = uv1[0] = LLVector2(0, 0) );
v[1] = LLVector3( uv2[1] = uv1[1] = LLVector2(0, mScreenHeight) );
v[2] = LLVector3( uv2[2] = uv1[2] = LLVector2(mScreenWidth, 0) );
v[3] = LLVector3( uv2[3] = uv1[3] = LLVector2(mScreenWidth, mScreenHeight) );
mVBO->flush();
}
checkError();
createNightVisionShader();
//createBloomShader();
createColorFilterShader();
createGaussBlurShader();
createNoiseTexture();
checkError();
}
@@ -202,9 +195,7 @@ inline bool LLPostProcess::shadersEnabled(void)
{
return (tweaks.useColorFilter().asBoolean() ||
tweaks.useNightVisionShader().asBoolean() ||
/*tweaks.useBloomShader().asBoolean() ||*/
tweaks.useGaussBlurFilter().asBoolean() );
}
void LLPostProcess::applyShaders(void)
@@ -220,7 +211,7 @@ void LLPostProcess::applyShaders(void)
{
/// If any of the above shaders have been called update the frame buffer;
if (copy_buffer)
copyFrameBuffer(mSceneRenderTexture->getTexName(), screenW, screenH);
copyFrameBuffer();
applyGaussBlurShader();
checkError();
copy_buffer = true;
@@ -229,143 +220,65 @@ void LLPostProcess::applyShaders(void)
{
/// If any of the above shaders have been called update the frame buffer;
if (copy_buffer)
copyFrameBuffer(mSceneRenderTexture->getTexName(), screenW, screenH);
copyFrameBuffer();
applyNightVisionShader();
checkError();
copy_buffer = true;
}
/*if (tweaks.useBloomShader())
{
/// If any of the above shaders have been called update the frame buffer;
if (copy_buffer)
copyFrameBuffer(mSceneRenderTexture->getTexName(), screenW, screenH);
applyBloomShader();
checkError();
copy_buffer = true;
}*/
}
void LLPostProcess::applyColorFilterShader(void)
{
if(gPostColorFilterProgram.mProgramObject == 0)
return;
/* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.*/
gPostColorFilterProgram.bind();
gGL.getTexUnit(0)->activate();
gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
gGL.getTexUnit(0)->bind(mSceneRenderTexture);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, mSceneRenderTexture.get()->getTexName());
getShaderUniforms(colorFilterUniforms, gPostColorFilterProgram.mProgramObject);
glUniform1iARB(colorFilterUniforms["RenderTexture"], 0);
glUniform1fARB(colorFilterUniforms["gamma"], tweaks.getGamma());
glUniform1fARB(colorFilterUniforms["brightness"], tweaks.getBrightness());
glUniform1fARB(colorFilterUniforms["contrast"], tweaks.getContrast());
gPostColorFilterProgram.uniform1f("gamma", tweaks.getGamma());
gPostColorFilterProgram.uniform1f("brightness", tweaks.getBrightness());
gPostColorFilterProgram.uniform1f("contrast", tweaks.getContrast());
float baseI = (tweaks.getContrastBaseR() + tweaks.getContrastBaseG() + tweaks.getContrastBaseB()) / 3.0f;
baseI = tweaks.getContrastBaseIntensity() / ((baseI < 0.001f) ? 0.001f : baseI);
float baseR = tweaks.getContrastBaseR() * baseI;
float baseG = tweaks.getContrastBaseG() * baseI;
float baseB = tweaks.getContrastBaseB() * baseI;
glUniform3fARB(colorFilterUniforms["contrastBase"], baseR, baseG, baseB);
glUniform1fARB(colorFilterUniforms["saturation"], tweaks.getSaturation());
glUniform3fARB(colorFilterUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
gPostColorFilterProgram.uniform3fv("contrastBase", 1, LLVector3(baseR, baseG, baseB).mV);
gPostColorFilterProgram.uniform1f("saturation", tweaks.getSaturation());
gPostColorFilterProgram.uniform3fv("lumWeights", 1, LLVector3(LUMINANCE_R, LUMINANCE_G, LUMINANCE_B).mV);
LLGLEnable blend(GL_BLEND);
gGL.setSceneBlendType(LLRender::BT_REPLACE);
LLGLDepthTest depth(GL_FALSE);
/// Draw a screen space quad
drawOrthoQuad(screenW, screenH, QUAD_NORMAL);
drawOrthoQuad(QUAD_NORMAL);
gPostColorFilterProgram.unbind();
//*/
}
void LLPostProcess::createColorFilterShader(void)
{
/// Define uniform names
colorFilterUniforms["RenderTexture"] = 0;
colorFilterUniforms["gamma"] = 0;
colorFilterUniforms["brightness"] = 0;
colorFilterUniforms["contrast"] = 0;
colorFilterUniforms["contrastBase"] = 0;
colorFilterUniforms["saturation"] = 0;
colorFilterUniforms["lumWeights"] = 0;
}
void LLPostProcess::applyNightVisionShader(void)
{
if(gPostNightVisionProgram.mProgramObject == 0)
return;
/* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.*/
gPostNightVisionProgram.bind();
gGL.getTexUnit(0)->activate();
gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
getShaderUniforms(nightVisionUniforms, gPostNightVisionProgram.mProgramObject);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, mSceneRenderTexture.get()->getTexName());
glUniform1iARB(nightVisionUniforms["RenderTexture"], 0);
gGL.getTexUnit(1)->activate();
gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(1)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseTexture.get()->getTexName());
glUniform1iARB(nightVisionUniforms["NoiseTexture"], 1);
gGL.getTexUnit(0)->bind(mSceneRenderTexture);
gGL.getTexUnit(1)->bind(mNoiseTexture);
glUniform1fARB(nightVisionUniforms["brightMult"], tweaks.getBrightMult());
glUniform1fARB(nightVisionUniforms["noiseStrength"], tweaks.getNoiseStrength());
noiseTextureScale = 0.01f + ((101.f - tweaks.getNoiseSize()) / 100.f);
noiseTextureScale *= (screenH / NOISE_SIZE);
gPostNightVisionProgram.uniform1f("brightMult", tweaks.getBrightMult());
gPostNightVisionProgram.uniform1f("noiseStrength", tweaks.getNoiseStrength());
mNoiseTextureScale = 0.001f + ((100.f - tweaks.getNoiseSize()) / 100.f);
mNoiseTextureScale *= (mScreenHeight / NOISE_SIZE);
glUniform3fARB(nightVisionUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
LLGLEnable blend(GL_BLEND);
gGL.setSceneBlendType(LLRender::BT_REPLACE);
LLGLDepthTest depth(GL_FALSE);
/// Draw a screen space quad
drawOrthoQuad(screenW, screenH, QUAD_NOISE);
drawOrthoQuad(QUAD_NOISE);
gPostNightVisionProgram.unbind();
gGL.getTexUnit(0)->activate();
//*/
}
void LLPostProcess::createNightVisionShader(void)
{
/// Define uniform names
nightVisionUniforms["RenderTexture"] = 0;
nightVisionUniforms["NoiseTexture"] = 0;
nightVisionUniforms["brightMult"] = 0;
nightVisionUniforms["noiseStrength"] = 0;
nightVisionUniforms["lumWeights"] = 0;
createNoiseTexture(mNoiseTexture);
}
void LLPostProcess::applyBloomShader(void)
{
}
void LLPostProcess::createBloomShader(void)
{
//createTexture(mTempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5));
/// Create Bloom Extract Shader
bloomExtractUniforms["RenderTexture"] = 0;
bloomExtractUniforms["extractLow"] = 0;
bloomExtractUniforms["extractHigh"] = 0;
bloomExtractUniforms["lumWeights"] = 0;
/// Create Bloom Blur Shader
bloomBlurUniforms["RenderTexture"] = 0;
bloomBlurUniforms["bloomStrength"] = 0;
bloomBlurUniforms["texelSize"] = 0;
bloomBlurUniforms["blurDirection"] = 0;
bloomBlurUniforms["blurWidth"] = 0;
}
void LLPostProcess::applyGaussBlurShader(void)
@@ -374,56 +287,33 @@ void LLPostProcess::applyGaussBlurShader(void)
if(!pass_count || gPostGaussianBlurProgram.mProgramObject == 0)
return;
getShaderUniforms(gaussBlurUniforms, gPostGaussianBlurProgram.mProgramObject);
gPostGaussianBlurProgram.bind();
gGL.getTexUnit(0)->activate();
gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, mSceneRenderTexture.get()->getTexName());
gGL.getTexUnit(0)->bind(mSceneRenderTexture);
LLGLEnable blend(GL_BLEND);
LLGLDepthTest depth(GL_FALSE);
gGL.setSceneBlendType(LLRender::BT_REPLACE);
glUniform1iARB(gaussBlurUniforms["RenderTexture"], 0);
GLint horiz_pass = gaussBlurUniforms["horizontalPass"];
GLint horiz_pass = gPostGaussianBlurProgram.getUniformLocation("horizontalPass");
for(int i = 0;i<pass_count;++i)
{
for(int j = 0;j<2;++j)
{
if(i || j)
copyFrameBuffer(mSceneRenderTexture->getTexName(), screenW, screenH);
copyFrameBuffer();
glUniform1iARB(horiz_pass, j);
drawOrthoQuad(screenW, screenH, QUAD_NORMAL);
drawOrthoQuad(QUAD_NORMAL);
}
}
gPostGaussianBlurProgram.unbind();
}
void LLPostProcess::createGaussBlurShader(void)
{
gaussBlurUniforms["RenderTexture"] = 0;
gaussBlurUniforms["horizontalPass"] = 0;
}
void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog)
{
/// Find uniform locations and insert into map
std::map<const char *, GLuint>::iterator i;
for (i = uniforms.begin(); i != uniforms.end(); ++i){
i->second = glGetUniformLocationARB(prog, i->first);
}
}
void LLPostProcess::doEffects(void)
{
/// Save GL State
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushClientAttrib(GL_ALL_ATTRIB_BITS);
LLVertexBuffer::unbind();
/// Copy the screen buffer to the render texture
{
copyFrameBuffer(mSceneRenderTexture->getTexName(), screenW, screenH);
}
copyFrameBuffer();
/// Clear the frame buffer.
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
@@ -431,146 +321,73 @@ void LLPostProcess::doEffects(void)
LLGLDisable(GL_DEPTH_TEST);
/// Change to an orthogonal view
viewOrthogonal(screenW, screenH);
gGL.matrixMode(LLRender::MM_PROJECTION);
gGL.pushMatrix();
gGL.loadIdentity();
gGL.ortho( 0.f, (GLdouble) mScreenWidth, 0.f, (GLdouble) mScreenHeight, -1.f, 1.f );
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.pushMatrix();
gGL.loadIdentity();
checkError();
applyShaders();
LLGLSLShader::bindNoShader();
checkError();
LLGLSLShader::bindNoShader();
/// Change to a perspective view
viewPerspective();
gGL.flush();
gGL.matrixMode( LLRender::MM_PROJECTION );
gGL.popMatrix();
gGL.matrixMode( LLRender::MM_MODELVIEW );
gGL.popMatrix();
/// Reset GL State
glPopClientAttrib();
glPopAttrib();
gGL.getTexUnit(1)->disable();
checkError();
}
void LLPostProcess::copyFrameBuffer(LLGLuint texture, unsigned int width, unsigned int height)
void LLPostProcess::copyFrameBuffer()
{
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture);
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0);
gGL.getTexUnit(0)->bindManual(mSceneRenderTexture->getTarget(), mSceneRenderTexture->getTexName());
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, mScreenWidth, mScreenHeight, 0);
}
inline void InitQuadArray(F32 *arr, const F32 x, const F32 y, const F32 width, const F32 height)
void LLPostProcess::drawOrthoQuad(QuadType type)
{
//Lower left
*(arr++)=x;
*(arr++)=y;
//Upper left
*(arr++)=x;
*(arr++)=y+height;
//Upper right
*(arr++)=x+width;
*(arr++)=y+height;
//Lower right
*(arr++)=x+width;
*(arr++)=y;
}
void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadType type)
{
#if 1
//Redid the logic here. Less cases. No longer using immediate mode.
bool second_tex = true;
//Vertex array used for all post-processing effects
static F32 verts[8];
//Texture coord array used for all post-processing effects
static F32 tex0[8];
//Texture coord array used for relevant post processing effects
static F32 tex1[8];
//Set up vertex array
InitQuadArray(verts, 0.f, 0.f, width, height);
//Set up first texture coords
if(type == QUAD_BLOOM_EXTRACT)
if(type == QUAD_NOISE)
{
InitQuadArray(tex0, 0.f, 0.f, width*2.f, height*2.f);
second_tex = false;
//This could also be done through uniforms.
LLStrider<LLVector2> uv2;
mVBO->getTexCoord1Strider(uv2);
float offs[2] = {(float) rand() / (float) RAND_MAX, (float) rand() / (float) RAND_MAX};
float scale[2] = {mScreenWidth * mNoiseTextureScale / mScreenHeight, mNoiseTextureScale};
uv2[0] = LLVector2(offs[0],offs[1]);
uv2[1] = LLVector2(offs[0],offs[1]+scale[1]);
uv2[2] = LLVector2(offs[0]+scale[0],offs[1]);
uv2[3] = LLVector2(uv2[2].mV[0],uv2[1].mV[1]);
mVBO->flush();
}
else
{
InitQuadArray(tex0, 0.f, 0.f, width, height);
//Set up second texture coords
if( type == QUAD_BLOOM_COMBINE)
InitQuadArray(tex1, 0.f, 0.f, width*.5, height*.5);
else if( type == QUAD_NOISE )
InitQuadArray(tex1, ((float) rand() / (float) RAND_MAX), ((float) rand() / (float) RAND_MAX),
width * noiseTextureScale / height, noiseTextureScale);
else
second_tex = false;
}
//Prepare to render
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer(2, GL_FLOAT, sizeof(F32)*2, verts);
if(second_tex) //tex1 setup
{
glClientActiveTextureARB(GL_TEXTURE1);
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, sizeof(F32)*2, tex1);
}
glClientActiveTextureARB(GL_TEXTURE0);
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, sizeof(F32)*2, tex0);
//Render
glDrawArrays(GL_QUADS, 0, sizeof(verts)/sizeof(verts[0]));
//Cleanup
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY ); //for tex0
if(second_tex)
{
glClientActiveTextureARB(GL_TEXTURE1);
glDisableClientState( GL_TEXTURE_COORD_ARRAY ); //for tex1
}
#endif
U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | (type == QUAD_NOISE ? LLVertexBuffer::MAP_TEXCOORD1 : 0);
mVBO->setBuffer(mask);
mVBO->drawArrays(LLRender::TRIANGLE_STRIP, 0, 4);
}
void LLPostProcess::viewOrthogonal(unsigned int width, unsigned int height)
void LLPostProcess::createScreenTexture()
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho( 0.f, (GLdouble) width, 0.f, (GLdouble) height, -1.f, 1.f );
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
}
std::vector<GLubyte> data(mScreenWidth * mScreenHeight * 3, 0) ;
void LLPostProcess::viewPerspective(void)
{
glMatrixMode( GL_PROJECTION );
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
}
void LLPostProcess::changeOrthogonal(unsigned int width, unsigned int height)
{
viewPerspective();
viewOrthogonal(width, height);
}
void LLPostProcess::createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height)
{
std::vector<GLubyte> data(width * height * 4, 0) ;
texture = new LLImageGL(FALSE) ;
if(texture->createGLTexture())
mSceneRenderTexture = new LLImageGL(FALSE) ;
if(mSceneRenderTexture->createGLTexture())
{
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture->getTexName());
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, mSceneRenderTexture->getTexName());
LLImageGL::setManualImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, mScreenWidth, mScreenHeight, GL_RGB, GL_UNSIGNED_BYTE, &data[0]);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
}
}
void LLPostProcess::createNoiseTexture(LLPointer<LLImageGL>& texture)
void LLPostProcess::createNoiseTexture()
{
std::vector<GLubyte> buffer(NOISE_SIZE * NOISE_SIZE);
for (unsigned int i = 0; i < NOISE_SIZE; i++){
@@ -579,10 +396,10 @@ void LLPostProcess::createNoiseTexture(LLPointer<LLImageGL>& texture)
}
}
texture = new LLImageGL(FALSE) ;
if(texture->createGLTexture())
mNoiseTexture = new LLImageGL(FALSE) ;
if(mNoiseTexture->createGLTexture())
{
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName());
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseTexture->getTexName());
LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
@@ -617,30 +434,3 @@ bool LLPostProcess::checkError(void)
return retCode;
}
void LLPostProcess::checkShaderError(GLhandleARB shader)
{
GLint infologLength = 0;
GLint charsWritten = 0;
GLchar *infoLog;
checkError(); // Check for OpenGL errors
glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);
checkError(); // Check for OpenGL errors
if (infologLength > 0)
{
infoLog = (GLchar *)malloc(infologLength);
if (infoLog == NULL)
{
/// Could not allocate infolog buffer
return;
}
glGetInfoLogARB(shader, infologLength, &charsWritten, infoLog);
// shaderErrorLog << (char *) infoLog << std::endl;
mShaderErrorString = (char *) infoLog;
free(infoLog);
}
checkError(); // Check for OpenGL errors
}

View File

@@ -38,19 +38,17 @@
#include "llgl.h"
#include "llglheaders.h"
class LLPostProcess
class LLPostProcess : public LLSingleton<LLPostProcess>
{
public:
typedef enum _QuadType {
QUAD_NORMAL,
QUAD_NOISE,
QUAD_BLOOM_EXTRACT,
QUAD_BLOOM_COMBINE
QUAD_NOISE
} QuadType;
/// GLSL Shader Encapsulation Struct
typedef std::map<const char *, GLuint> glslUniforms;
//typedef std::map<const char *, GLuint> glslUniforms;
struct PostProcessTweaks : public LLSD {
inline PostProcessTweaks() : LLSD(LLSD::emptyMap())
@@ -69,22 +67,6 @@ public:
return (*this)["noise_size"];
}
inline LLSD & extractLow() {
return (*this)["extract_low"];
}
inline LLSD & extractHigh() {
return (*this)["extract_high"];
}
inline LLSD & bloomWidth() {
return (*this)["bloom_width"];
}
inline LLSD & bloomStrength() {
return (*this)["bloom_strength"];
}
inline LLSD & brightness() {
return (*this)["brightness"];
}
@@ -117,10 +99,6 @@ public:
return (*this)["enable_night_vision"];
}
/*inline LLSD & useBloomShader() {
return (*this)["enable_bloom"];
}*/
inline LLSD & useColorFilter() {
return (*this)["enable_color_filter"];
}
@@ -141,22 +119,6 @@ public:
return F32((*this)["noise_size"].asReal());
}
inline F32 getExtractLow() const {
return F32((*this)["extract_low"].asReal());
}
inline F32 getExtractHigh() const {
return F32((*this)["extract_high"].asReal());
}
inline F32 getBloomWidth() const {
return F32((*this)["bloom_width"].asReal());
}
inline F32 getBloomStrength() const {
return F32((*this)["bloom_strength"].asReal());
}
inline F32 getGamma() const {
return F32((*this)["gamma"].asReal());
}
@@ -193,17 +155,16 @@ public:
return (*this)["gauss_blur_passes"];
}
};
bool initialized;
PostProcessTweaks tweaks;
// the map of all availible effects
LLSD mAllEffects;
private:
LLPointer<LLVertexBuffer> mVBO;
LLPointer<LLImageGL> mSceneRenderTexture ;
LLPointer<LLImageGL> mNoiseTexture ;
LLPointer<LLImageGL> mTempBloomTexture ;
public:
LLPostProcess(void);
@@ -213,9 +174,6 @@ public:
void apply(unsigned int width, unsigned int height);
void invalidate() ;
/// Perform global initialization for this class.
static void initClass(void);
// Cleanup of global data that's only inited once per class.
static void cleanupClass();
@@ -230,18 +188,11 @@ public:
private:
/// read in from file
std::string mShaderErrorString;
unsigned int screenW;
unsigned int screenH;
unsigned int mScreenWidth;
unsigned int mScreenHeight;
float noiseTextureScale;
float mNoiseTextureScale;
/// Shader Uniforms
glslUniforms nightVisionUniforms;
glslUniforms bloomExtractUniforms;
glslUniforms bloomBlurUniforms;
glslUniforms colorFilterUniforms;
glslUniforms gaussBlurUniforms;
// the name of currently selected effect in mAllEffects
// invariant: tweaks == mAllEffects[mSelectedEffectName]
std::string mSelectedEffectName;
@@ -253,35 +204,19 @@ private:
bool shadersEnabled(void);
/// Night Vision Functions
void createNightVisionShader(void);
void applyNightVisionShader(void);
/// Bloom Functions
void createBloomShader(void);
void applyBloomShader(void);
/// Color Filter Functions
void createColorFilterShader(void);
void applyColorFilterShader(void);
/// Gaussian blur Filter Functions
void createGaussBlurShader(void);
void applyGaussBlurShader(void);
/// OpenGL Helper Functions
void getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog);
void createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height);
void copyFrameBuffer(LLGLuint texture, unsigned int width, unsigned int height);
void createNoiseTexture(LLPointer<LLImageGL>& texture);
void copyFrameBuffer();
void createScreenTexture();
void createNoiseTexture();
bool checkError(void);
void checkShaderError(GLhandleARB shader);
void drawOrthoQuad(unsigned int width, unsigned int height, QuadType type);
void viewOrthogonal(unsigned int width, unsigned int height);
void changeOrthogonal(unsigned int width, unsigned int height);
void viewPerspective(void);
void drawOrthoQuad(QuadType type);
};
extern LLPostProcess * gPostProcess;
#endif // LL_POSTPROCESS_H

File diff suppressed because it is too large Load Diff

View File

@@ -45,8 +45,10 @@
#include "v4coloru.h"
#include "v4math.h"
#include "llstrider.h"
#include "llmemory.h"
#include "llpointer.h"
#include "llglheaders.h"
#include "llmatrix4a.h"
#include "glh/glh_linear.h"
class LLVertexBuffer;
class LLCubeMap;
@@ -54,11 +56,14 @@ class LLImageGL;
class LLRenderTarget;
class LLTexture ;
#define LL_MATRIX_STACK_DEPTH 32
class LLTexUnit
{
friend class LLRender;
public:
static U32 sWhiteTexture;
typedef enum
{
TT_TEXTURE = 0, // Standard 2D Texture
@@ -240,6 +245,8 @@ public:
void setSpotDirection(const LLVector3& direction);
protected:
friend class LLRender;
S32 mIndex;
bool mEnabled;
LLColor4 mDiffuse;
@@ -312,6 +319,18 @@ public:
BF_UNDEF
} eBlendFactor;
typedef enum
{
MM_MODELVIEW = 0,
MM_PROJECTION,
MM_TEXTURE0,
MM_TEXTURE1,
MM_TEXTURE2,
MM_TEXTURE3,
NUM_MATRIX_MODES,
MM_TEXTURE
} eMatrixMode;
LLRender();
~LLRender();
void init() ;
@@ -323,8 +342,29 @@ public:
void translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
void scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
void rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z);
void ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar);
void pushMatrix();
void popMatrix();
void loadMatrix(const GLfloat* m);
void loadIdentity();
void multMatrix(const GLfloat* m);
void matrixMode(U32 mode);
const glh::matrix4f& getModelviewMatrix();
const glh::matrix4f& getProjectionMatrix();
void syncMatrices();
void syncLightState();
void translateUI(F32 x, F32 y, F32 z);
void scaleUI(F32 x, F32 y, F32 z);
void pushUIMatrix();
void popUIMatrix();
void loadUIIdentity();
LLVector3 getUITranslation();
LLVector3 getUIScale();
void flush();
@@ -347,9 +387,16 @@ public:
void color3fv(const GLfloat* c);
void color4ubv(const GLubyte* c);
void diffuseColor3f(F32 r, F32 g, F32 b);
void diffuseColor3fv(const F32* c);
void diffuseColor4f(F32 r, F32 g, F32 b, F32 a);
void diffuseColor4fv(const F32* c);
void diffuseColor4ubv(const U8* c);
void vertexBatchPreTransformed(LLVector3* verts, S32 vert_count);
void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count);
void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLColor4U*, S32 vert_count);
void setColorMask(bool writeColor, bool writeAlpha);
void setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha);
void setSceneBlendType(eBlendType type);
@@ -363,6 +410,7 @@ public:
eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor);
LLLightState* getLight(U32 index);
void setAmbientLightColor(const LLColor4& color);
LLTexUnit* getTexUnit(U32 index);
@@ -382,9 +430,23 @@ public:
};
public:
static U32 sUICalls;
static U32 sUIVerts;
static bool sGLCoreProfile;
private:
bool mDirty;
friend class LLLightState;
U32 mMatrixMode;
U32 mMatIdx[NUM_MATRIX_MODES];
U32 mMatHash[NUM_MATRIX_MODES];
glh::matrix4f mMatrix[NUM_MATRIX_MODES][LL_MATRIX_STACK_DEPTH];
U32 mCurMatHash[NUM_MATRIX_MODES];
U32 mLightHash;
LLColor4 mAmbientLightColor;
bool mDirty;
U32 mQuadCycle;
U32 mCount;
U32 mMode;
U32 mCurrTextureUnitIndex;
@@ -406,12 +468,16 @@ private:
eBlendFactor mCurrBlendAlphaDFactor;
F32 mMaxAnisotropy;
std::vector<LLVector3> mUIOffset;
std::vector<LLVector3> mUIScale;
};
extern F64 gGLModelView[16];
extern F64 gGLLastModelView[16];
extern F64 gGLLastProjection[16];
extern F64 gGLProjection[16];
extern F32 gGLModelView[16];
extern F32 gGLLastModelView[16];
extern F32 gGLLastProjection[16];
extern F32 gGLProjection[16];
extern S32 gGLViewport[4];
extern LLRender gGL;

View File

@@ -41,106 +41,12 @@
#include "llglheaders.h"
GLUquadricObj *gQuadObj2 = NULL;
LLRenderSphere gSphere;
void drawSolidSphere(GLdouble radius, GLint slices, GLint stacks);
void drawSolidSphere(GLdouble radius, GLint slices, GLint stacks)
{
if (!gQuadObj2)
{
gQuadObj2 = gluNewQuadric();
if (!gQuadObj2)
{
llwarns << "drawSolidSphere couldn't allocate quadric" << llendl;
return;
}
}
gluQuadricDrawStyle(gQuadObj2, GLU_FILL);
gluQuadricNormals(gQuadObj2, GLU_SMOOTH);
// If we ever changed/used the texture or orientation state
// of quadObj, we'd need to change it to the defaults here
// with gluQuadricTexture and/or gluQuadricOrientation.
gluQuadricTexture(gQuadObj2, GL_TRUE);
gluSphere(gQuadObj2, radius, slices, stacks);
}
// A couple thoughts on sphere drawing:
// 1) You need more slices than stacks, but little less than 2:1
// 2) At low LOD, setting stacks to an odd number avoids a "band" around the equator, making things look smoother
void LLRenderSphere::prerender()
{
// Create a series of display lists for different LODs
mDList[0] = glGenLists(1);
glNewList(mDList[0], GL_COMPILE);
drawSolidSphere(1.0, 30, 20);
glEndList();
mDList[1] = glGenLists(1);
glNewList(mDList[1], GL_COMPILE);
drawSolidSphere(1.0, 20, 15);
glEndList();
mDList[2] = glGenLists(1);
glNewList(mDList[2], GL_COMPILE);
drawSolidSphere(1.0, 12, 8);
glEndList();
mDList[3] = glGenLists(1);
glNewList(mDList[3], GL_COMPILE);
drawSolidSphere(1.0, 8, 5);
glEndList();
}
void LLRenderSphere::cleanupGL()
{
for (S32 detail = 0; detail < 4; detail++)
{
glDeleteLists(mDList[detail], 1);
mDList[detail] = 0;
}
if (gQuadObj2)
{
gluDeleteQuadric(gQuadObj2);
gQuadObj2 = NULL;
}
}
// Constants here are empirically derived from my eyeballs, JNC
//
// The toughest adjustment is the cutoff for the lowest LOD
// Maybe we should have more LODs at the low end?
void LLRenderSphere::render(F32 pixel_area)
{
S32 level_of_detail;
if (pixel_area > 10000.f)
{
level_of_detail = 0;
}
else if (pixel_area > 800.f)
{
level_of_detail = 1;
}
else if (pixel_area > 100.f)
{
level_of_detail = 2;
}
else
{
level_of_detail = 3;
}
glCallList(mDList[level_of_detail]);
}
void LLRenderSphere::render()
{
glCallList(mDList[0]);
renderGGL();
gGL.flush();
}
inline LLVector3 polar_to_cart(F32 latitude, F32 longitude)

View File

@@ -46,11 +46,6 @@ void lat2xyz(LLVector3 * result, F32 lat, F32 lon); // utility routine
class LLRenderSphere
{
public:
LLGLuint mDList[5];
void prerender();
void cleanupGL();
void render(F32 pixel_area); // of a box of size 1.0 at that position
void render(); // render at highest LOD
void renderGGL(); // render using LLRender

View File

@@ -37,8 +37,7 @@
#include "llgl.h"
LLRenderTarget* LLRenderTarget::sBoundTarget = NULL;
U32 LLRenderTarget::sBytesAllocated = 0;
void check_framebuffer_status()
{
@@ -69,7 +68,6 @@ LLRenderTarget::LLRenderTarget() :
mUseDepth(false),
mRenderDepth(false),
mUsage(LLTexUnit::TT_TEXTURE),
mSamples(0),
mSampleBuffer(NULL)
{
}
@@ -156,6 +154,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
stop_glerror();
{
clear_glerror();
LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
@@ -165,32 +164,33 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
return false;
}
}
sBytesAllocated += mResX*mResY*4;
stop_glerror();
{
if (offset == 0)
{ //use bilinear filtering on single texture render targets that aren't multisampled
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
stop_glerror();
}
else
{ //don't filter data attachments
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
stop_glerror();
}
if (offset == 0)
{ //use bilinear filtering on single texture render targets that aren't multisampled
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
stop_glerror();
}
else
{ //don't filter data attachments
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
stop_glerror();
}
if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
{
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
stop_glerror();
}
else
{
// ATI doesn't support mirrored repeat for rectangular textures.
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
stop_glerror();
}
if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
{
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
stop_glerror();
}
else
{
// ATI doesn't support mirrored repeat for rectangular textures.
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
stop_glerror();
}
if (mFBO)
@@ -233,13 +233,16 @@ bool LLRenderTarget::allocateDepth()
{
LLImageGL::generateTextures(1, &mDepth);
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
U32 internal_type = LLTexUnit::getInternalType(mUsage);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
stop_glerror();
clear_glerror();
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
sBytesAllocated += mResX*mResY*4;
if (glGetError() != GL_NO_ERROR)
{
llwarns << "Unable to allocate depth buffer for render target." << llendl;
@@ -309,14 +312,16 @@ void LLRenderTarget::release()
stop_glerror();
}
mDepth = 0;
sBytesAllocated -= mResX*mResY*4;
}
else if (mUseDepth && mFBO)
{ //detach shared depth buffer
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
if (mStencil)
{ //attached as a renderbuffer
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
mStencil = false;
}
else
@@ -334,6 +339,7 @@ void LLRenderTarget::release()
if (mTex.size() > 0)
{
sBytesAllocated -= mResX*mResY*4*mTex.size();
LLImageGL::deleteTextures(mTex.size(), &mTex[0], true);
mTex.clear();
}
@@ -520,7 +526,8 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
gGL.flush();
if (!source.mFBO || !mFBO)
{
llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
llwarns << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
return;
}
if (mSampleBuffer)
@@ -574,7 +581,8 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0
{
if (!source.mFBO)
{
llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
llwarns << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
return;
}
{
GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE;
@@ -616,7 +624,8 @@ void LLRenderTarget::getViewport(S32* viewport)
//==================================================
// LLMultisampleBuffer implementation
//==================================================
LLMultisampleBuffer::LLMultisampleBuffer()
LLMultisampleBuffer::LLMultisampleBuffer() :
mSamples(0)
{
}
@@ -636,12 +645,15 @@ void LLMultisampleBuffer::release()
if (mTex.size() > 0)
{
sBytesAllocated -= mResX*mResY*4*mResX*mResY*4*mTex.size();
glDeleteRenderbuffers(mTex.size(), (GLuint *) &mTex[0]);
mTex.clear();
}
if (mDepth)
{
sBytesAllocated -= mResX*mResY*4;
glDeleteRenderbuffers(1, (GLuint *) &mDepth);
mDepth = 0;
}
@@ -736,6 +748,8 @@ bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
stop_glerror();
}
return addColorAttachment(color_fmt);
@@ -766,6 +780,9 @@ bool LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
llwarns << "Unable to allocate color buffer for multisample render target." << llendl;
return false;
}
sBytesAllocated += mResX*mResY*4;
if (mFBO)
{
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
@@ -797,6 +814,9 @@ bool LLMultisampleBuffer::allocateDepth()
llwarns << "Unable to allocate depth buffer for multisample render target." << llendl;
return false;
}
sBytesAllocated += mResX*mResY*4;
return true;
}

View File

@@ -70,6 +70,7 @@ class LLRenderTarget
public:
//whether or not to use FBO implementation
static bool sUseFBO;
static U32 sBytesAllocated;
LLRenderTarget();
virtual ~LLRenderTarget();
@@ -157,7 +158,6 @@ protected:
bool mUseDepth;
bool mRenderDepth;
LLTexUnit::eTextureType mUsage;
U32 mSamples;
LLMultisampleBuffer* mSampleBuffer;
static LLRenderTarget* sBoundTarget;
@@ -166,6 +166,7 @@ protected:
class LLMultisampleBuffer : public LLRenderTarget
{
U32 mSamples;
public:
LLMultisampleBuffer();
virtual ~LLMultisampleBuffer();

View File

@@ -2,31 +2,25 @@
* @file llshadermgr.cpp
* @brief Shader manager implementation.
*
* $LicenseInfo:firstyear=2005&license=viewergpl$
*
* Copyright (c) 2005-2009, Linden Research, Inc.
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* 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
* Copyright (C) 2010, Linden Research, Inc.
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
* This 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.
*
* 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.
* 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.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* 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$
*/
@@ -36,6 +30,8 @@
#include "llfile.h"
#include "llrender.h"
#include "llcontrol.h" //for LLCachedControl
#include "lldir.h" //for gDirUtilp
#if LL_DARWIN
#include "OpenGL/OpenGL.h"
@@ -87,7 +83,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
// NOTE order of shader object attaching is VERY IMPORTANT!!!
if (features->calculatesAtmospherics)
{
if (!shader->attachObject("windlight/atmosphericsVarsV.glsl"))
if (features->hasWaterFog)
{
if (!shader->attachObject("windlight/atmosphericsVarsWaterV.glsl"))
{
return FALSE;
}
}
else if (!shader->attachObject("windlight/atmosphericsVarsV.glsl"))
{
return FALSE;
}
@@ -107,9 +110,13 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
return FALSE;
}
if (!shader->attachObject("lighting/sumLightsSpecularV.glsl"))
if (!features->isAlphaLighting)
{
return FALSE;
if (!shader->attachObject("lighting/sumLightsSpecularV.glsl"))
{
return FALSE;
}
}
if (!shader->attachObject("lighting/lightSpecularV.glsl"))
@@ -124,9 +131,12 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
return FALSE;
}
if (!shader->attachObject("lighting/sumLightsV.glsl"))
if (!features->isAlphaLighting)
{
return FALSE;
if (!shader->attachObject("lighting/sumLightsV.glsl"))
{
return FALSE;
}
}
if (!shader->attachObject("lighting/lightV.glsl"))
@@ -153,7 +163,6 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
#if MESH_ENABLED
if (features->hasObjectSkinning)
{
if (!shader->attachObject("avatar/objectSkinV.glsl"))
@@ -161,7 +170,6 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
return FALSE;
}
}
#endif //MESH_ENABLED
///////////////////////////////////////
// Attach Fragment Shader Features Next
@@ -169,7 +177,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
if(features->calculatesAtmospherics)
{
if (!shader->attachObject("windlight/atmosphericsVarsF.glsl"))
if (features->hasWaterFog)
{
if (!shader->attachObject("windlight/atmosphericsVarsWaterF.glsl"))
{
return FALSE;
}
}
else if (!shader->attachObject("windlight/atmosphericsVarsF.glsl"))
{
return FALSE;
}
@@ -250,7 +265,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
return FALSE;
}
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
}
}
@@ -289,7 +304,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
return FALSE;
}
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
}
}
}
@@ -313,7 +328,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
{
return FALSE;
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
}
}
else if (features->hasWaterFog)
@@ -345,7 +360,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
{
return FALSE;
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
}
}
@@ -364,7 +379,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
{
return FALSE;
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
}
}
@@ -404,7 +419,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
return FALSE;
}
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
}
}
}
@@ -428,7 +443,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
{
return FALSE;
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
}
}
@@ -447,10 +462,26 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
{
return FALSE;
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
}
}
}
if (features->mIndexedTextureChannels <= 1)
{
if (!shader->attachObject("objects/nonindexedTextureV.glsl"))
{
return FALSE;
}
}
else
{
if (!shader->attachObject("objects/indexedTextureV.glsl"))
{
return FALSE;
}
}
return TRUE;
}
@@ -540,23 +571,69 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
}
//we can't have any lines longer than 1024 characters
//or any shaders longer than 1024 lines... deal - DaveP
GLcharARB buff[1024] = {0};
GLcharARB* text[1024] = {0};
//or any shaders longer than 4096 lines... deal - DaveP
GLcharARB buff[1024];
GLcharARB* text[4096];
GLuint count = 0;
if (gGLManager.mGLVersion < 2.1f)
F32 version = gGLManager.mGLVersion;
//hack to never use GLSL > 1.20 on OSX
#if LL_DARWIN
version = llmin(version, 2.9f);
#endif
if (version < 2.1f)
{
text[count++] = strdup("#version 110\n");
text[count++] = strdup("#define ATTRIBUTE attribute\n");
text[count++] = strdup("#define VARYING varying\n");
}
else if (gGLManager.mGLVersion < 3.f)
else if (version < 3.3f)
{
//set version to 1.20
text[count++] = strdup("#version 120\n");
text[count++] = strdup("#define FXAA_GLSL_120 1\n");
text[count++] = strdup("#define FXAA_FAST_PIXEL_OFFSET 0\n");
text[count++] = strdup("#define ATTRIBUTE attribute\n");
text[count++] = strdup("#define VARYING varying\n");
}
else
{ //set version to 1.30
text[count++] = strdup("#version 130\n");
{
if (version < 4.f)
{
//set version to 1.30
text[count++] = strdup("#version 130\n");
}
else
{ //set version to 400
text[count++] = strdup("#version 400\n");
}
text[count++] = strdup("#define DEFINE_GL_FRAGCOLOR 1\n");
text[count++] = strdup("#define FXAA_GLSL_130 1\n");
text[count++] = strdup("#define ATTRIBUTE in\n");
if (type == GL_VERTEX_SHADER_ARB)
{ //"varying" state is "out" in a vertex program, "in" in a fragment program
// ("varying" is deprecated after version 1.20)
text[count++] = strdup("#define VARYING out\n");
}
else
{
text[count++] = strdup("#define VARYING in\n");
}
//backwards compatibility with legacy texture lookup syntax
text[count++] = strdup("#define textureCube texture\n");
text[count++] = strdup("#define texture2DLod textureLod\n");
text[count++] = strdup("#define shadow2D(a,b) vec2(texture(a,b))\n"); //Shadow lookups only return a single float.
//Also deprecated:
text[count++] = strdup("#define texture2D texture\n");
text[count++] = strdup("#define texture2DRect texture\n");
text[count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n");
}
//copy preprocessor definitions into buffer
@@ -606,7 +683,11 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
text[count++] = strdup(decl.c_str());
}
text[count++] = strdup("varying float vary_texture_index;\n");
if (texture_index_channels > 1)
{
text[count++] = strdup("VARYING float vary_texture_index;\n");
}
text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n");
text[count++] = strdup("{\n");
@@ -629,7 +710,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
}
text[count++] = strdup("\t}\n");
text[count++] = strdup("\treturn vec4(0,0,0,0);\n");
text[count++] = strdup("\treturn vec4(1,0,1,1);\n");
text[count++] = strdup("}\n");
}
else
@@ -652,12 +733,13 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
text[count++] = strdup(if_str.c_str());
}
text[count++] = strdup("\treturn vec4(0,0,0,0);\n");
text[count++] = strdup("\treturn vec4(1,0,1,1);\n");
text[count++] = strdup("}\n");
}
}
//copy file into memory
while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(buff) )
while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(text) )
{
text[count++] = (GLcharARB *)strdup((char *)buff);
}
@@ -672,35 +754,46 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
{
LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL;
glDeleteObjectARB(ret); //no longer need handle
ret=0;
}
}
//load source
glShaderSourceARB(ret, count, (const GLcharARB**) text, NULL);
if (gDebugGL)
if(ret)
{
error = glGetError();
if (error != GL_NO_ERROR)
glShaderSourceARB(ret, count, (const GLcharARB**) text, NULL);
if (gDebugGL)
{
LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << LL_ENDL;
glDeleteObjectARB(ret); //no longer need handle
error = glGetError();
if (error != GL_NO_ERROR)
{
LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << LL_ENDL;
glDeleteObjectARB(ret); //no longer need handle
ret=0;
}
}
}
//compile source
glCompileShaderARB(ret);
if (gDebugGL)
if(ret)
{
error = glGetError();
if (error != GL_NO_ERROR)
glCompileShaderARB(ret);
if (gDebugGL)
{
LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL;
glDeleteObjectARB(ret); //no longer need handle
error = glGetError();
if (error != GL_NO_ERROR)
{
LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL;
glDeleteObjectARB(ret); //no longer need handle
ret=0;
}
}
}
std::string error_str;
if (error == GL_NO_ERROR)
{
//check for errors
@@ -714,23 +807,60 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
//an error occured, print log
LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL;
dumpObjectLog(ret);
error_str = get_object_log(ret);
#if LL_WINDOWS
std::stringstream ostr;
//dump shader source for debugging
for (GLuint i = 0; i < count; i++)
{
ostr << i << ": " << text[i];
if (i % 128 == 0)
{ //dump every 128 lines
LL_WARNS("ShaderLoading") << "\n" << ostr.str() << llendl;
ostr.str("");
ostr.clear();
}
}
LL_WARNS("ShaderLoading") << "\n" << ostr.str() << llendl;
#endif // LL_WINDOWS
glDeleteObjectARB(ret); //no longer need handle
ret = 0;
}
}
if(ret)
dumpObjectLog(ret,false);
}
else
static const LLCachedControl<bool> dump_raw_shaders("ShyotlDumpRawShaders",false);
if(dump_raw_shaders || !ret)
{
ret = 0;
std::stringstream ostr;
for (GLuint i = 0; i < count; i++)
{
ostr << text[i];
}
std::string delim = gDirUtilp->getDirDelimiter();
std::string shader_name = filename.substr(filename.find_last_of("/")+1); //shader_name.glsl
shader_name = shader_name.substr(0,shader_name.find_last_of(".")); //shader_name
std::string maindir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"shader_dump"+delim);
//mkdir is NOT recursive. Step through the folders one by one.
LLFile::mkdir(maindir); //..Roaming/SecondLife/logs/shader_dump/
LLFile::mkdir(maindir+="class" + llformat("%i",gpu_class) + delim); //..shader_dump/class1/
LLFile::mkdir(maindir+=filename.substr(0,filename.find_last_of("/")+1)); //..shader_dump/class1/windlight/
LLAPRFile file(maindir + shader_name + (ret ? "" : llformat("_FAILED(%i)",error)) + ".glsl", LL_APR_W);
file.write(ostr.str().c_str(),ostr.str().length());
if(!error_str.empty())
{
LLAPRFile file2(maindir + shader_name + "_ERROR.txt", LL_APR_W);
file2.write(error_str.c_str(),error_str.length());
}
}
stop_glerror();
@@ -771,28 +901,42 @@ BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors)
LL_WARNS("ShaderLoading") << "GLSL Linker Error:" << LL_ENDL;
}
// NOTE: Removing LL_DARWIN block as it doesn't seem to actually give the correct answer,
// but want it for reference once I move it.
#if 0
// Force an evaluation of the gl state so the driver can tell if the shader will run in hardware or software
// per Apple's suggestion
glBegin(gGL.mMode);
glEnd();
#if LL_DARWIN
// Query whether the shader can or cannot run in hardware
// http://developer.apple.com/qa/qa2007/qa1502.html
long vertexGPUProcessing;
CGLContextObj ctx = CGLGetCurrentContext();
CGLGetParameter (ctx, kCGLCPGPUVertexProcessing, &vertexGPUProcessing);
long fragmentGPUProcessing;
CGLGetParameter (ctx, kCGLCPGPUFragmentProcessing, &fragmentGPUProcessing);
if (!fragmentGPUProcessing || !vertexGPUProcessing)
// For some reason this absolutely kills the frame rate when VBO's are enabled
if (0)
{
LL_WARNS("ShaderLoading") << "GLSL Linker: Running in Software:" << LL_ENDL;
success = GL_FALSE;
suppress_errors = FALSE;
// Force an evaluation of the gl state so the driver can tell if the shader will run in hardware or software
// per Apple's suggestion
LLGLSLShader::sNoFixedFunction = false;
glUseProgramObjectARB(obj);
gGL.begin(LLRender::TRIANGLES);
gGL.vertex3f(0.0f, 0.0f, 0.0f);
gGL.vertex3f(0.0f, 0.0f, 0.0f);
gGL.vertex3f(0.0f, 0.0f, 0.0f);
gGL.end();
gGL.flush();
glUseProgramObjectARB(0);
LLGLSLShader::sNoFixedFunction = true;
// Query whether the shader can or cannot run in hardware
// http://developer.apple.com/qa/qa2007/qa1502.html
GLint vertexGPUProcessing, fragmentGPUProcessing;
CGLContextObj ctx = CGLGetCurrentContext();
CGLGetParameter(ctx, kCGLCPGPUVertexProcessing, &vertexGPUProcessing);
CGLGetParameter(ctx, kCGLCPGPUFragmentProcessing, &fragmentGPUProcessing);
if (!fragmentGPUProcessing || !vertexGPUProcessing)
{
LL_WARNS("ShaderLoading") << "GLSL Linker: Running in Software:" << LL_ENDL;
success = GL_FALSE;
suppress_errors = FALSE;
}
}
#else
std::string log = get_object_log(obj);
LLStringUtil::toLower(log);
@@ -830,3 +974,181 @@ BOOL LLShaderMgr::validateProgramObject(GLhandleARB obj)
return success;
}
//virtual
void LLShaderMgr::initAttribsAndUniforms()
{
//MUST match order of enum in LLVertexBuffer.h
mReservedAttribs.push_back("position");
mReservedAttribs.push_back("normal");
mReservedAttribs.push_back("texcoord0");
mReservedAttribs.push_back("texcoord1");
mReservedAttribs.push_back("texcoord2");
mReservedAttribs.push_back("texcoord3");
mReservedAttribs.push_back("diffuse_color");
mReservedAttribs.push_back("emissive");
mReservedAttribs.push_back("binormal");
mReservedAttribs.push_back("weight");
mReservedAttribs.push_back("weight4");
mReservedAttribs.push_back("clothing");
mReservedAttribs.push_back("texture_index");
//matrix state
mReservedUniforms.push_back("modelview_matrix");
mReservedUniforms.push_back("projection_matrix");
mReservedUniforms.push_back("inv_proj");
mReservedUniforms.push_back("modelview_projection_matrix");
mReservedUniforms.push_back("normal_matrix");
mReservedUniforms.push_back("texture_matrix0");
mReservedUniforms.push_back("texture_matrix1");
mReservedUniforms.push_back("texture_matrix2");
mReservedUniforms.push_back("texture_matrix3");
llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_MATRIX3+1);
mReservedUniforms.push_back("viewport");
mReservedUniforms.push_back("light_position");
mReservedUniforms.push_back("light_direction");
mReservedUniforms.push_back("light_attenuation");
mReservedUniforms.push_back("light_diffuse");
mReservedUniforms.push_back("light_ambient");
mReservedUniforms.push_back("light_count");
mReservedUniforms.push_back("light");
mReservedUniforms.push_back("light_col");
mReservedUniforms.push_back("far_z");
llassert(mReservedUniforms.size() == LLShaderMgr::MULTI_LIGHT_FAR_Z+1);
mReservedUniforms.push_back("proj_mat");
mReservedUniforms.push_back("proj_near");
mReservedUniforms.push_back("proj_p");
mReservedUniforms.push_back("proj_n");
mReservedUniforms.push_back("proj_origin");
mReservedUniforms.push_back("proj_range");
mReservedUniforms.push_back("proj_ambiance");
mReservedUniforms.push_back("proj_shadow_idx");
mReservedUniforms.push_back("shadow_fade");
mReservedUniforms.push_back("proj_focus");
mReservedUniforms.push_back("proj_lod");
mReservedUniforms.push_back("proj_ambient_lod");
llassert(mReservedUniforms.size() == LLShaderMgr::PROJECTOR_AMBIENT_LOD+1);
mReservedUniforms.push_back("color");
mReservedUniforms.push_back("diffuseMap");
mReservedUniforms.push_back("specularMap");
mReservedUniforms.push_back("bumpMap");
mReservedUniforms.push_back("environmentMap");
mReservedUniforms.push_back("cloude_noise_texture");
mReservedUniforms.push_back("fullbright");
mReservedUniforms.push_back("lightnorm");
mReservedUniforms.push_back("sunlight_color_copy");
mReservedUniforms.push_back("ambient");
mReservedUniforms.push_back("blue_horizon");
mReservedUniforms.push_back("blue_density");
mReservedUniforms.push_back("haze_horizon");
mReservedUniforms.push_back("haze_density");
mReservedUniforms.push_back("cloud_shadow");
mReservedUniforms.push_back("density_multiplier");
mReservedUniforms.push_back("distance_multiplier");
mReservedUniforms.push_back("max_y");
mReservedUniforms.push_back("glow");
mReservedUniforms.push_back("cloud_color");
mReservedUniforms.push_back("cloud_pos_density1");
mReservedUniforms.push_back("cloud_pos_density2");
mReservedUniforms.push_back("cloud_scale");
mReservedUniforms.push_back("gamma");
mReservedUniforms.push_back("scene_light_strength");
llassert(mReservedUniforms.size() == LLShaderMgr::SCENE_LIGHT_STRENGTH+1);
mReservedUniforms.push_back("center");
mReservedUniforms.push_back("size");
mReservedUniforms.push_back("falloff");
mReservedUniforms.push_back("minLuminance");
mReservedUniforms.push_back("maxExtractAlpha");
mReservedUniforms.push_back("lumWeights");
mReservedUniforms.push_back("warmthWeights");
mReservedUniforms.push_back("warmthAmount");
mReservedUniforms.push_back("glowStrength");
mReservedUniforms.push_back("glowDelta");
llassert(mReservedUniforms.size() == LLShaderMgr::GLOW_DELTA+1);
mReservedUniforms.push_back("minimum_alpha");
mReservedUniforms.push_back("shadow_matrix");
mReservedUniforms.push_back("env_mat");
mReservedUniforms.push_back("shadow_clip");
mReservedUniforms.push_back("sun_wash");
mReservedUniforms.push_back("shadow_noise");
mReservedUniforms.push_back("blur_size");
mReservedUniforms.push_back("ssao_radius");
mReservedUniforms.push_back("ssao_max_radius");
mReservedUniforms.push_back("ssao_factor");
mReservedUniforms.push_back("ssao_factor_inv");
mReservedUniforms.push_back("ssao_effect_mat");
mReservedUniforms.push_back("screen_res");
mReservedUniforms.push_back("near_clip");
mReservedUniforms.push_back("shadow_offset");
mReservedUniforms.push_back("shadow_bias");
mReservedUniforms.push_back("spot_shadow_bias");
mReservedUniforms.push_back("spot_shadow_offset");
mReservedUniforms.push_back("sun_dir");
mReservedUniforms.push_back("shadow_res");
mReservedUniforms.push_back("proj_shadow_res");
mReservedUniforms.push_back("depth_cutoff");
mReservedUniforms.push_back("norm_cutoff");
llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_NORM_CUTOFF+1);
mReservedUniforms.push_back("tc_scale");
mReservedUniforms.push_back("rcp_screen_res");
mReservedUniforms.push_back("rcp_frame_opt");
mReservedUniforms.push_back("rcp_frame_opt2");
mReservedUniforms.push_back("focal_distance");
mReservedUniforms.push_back("blur_constant");
mReservedUniforms.push_back("tan_pixel_angle");
mReservedUniforms.push_back("magnification");
mReservedUniforms.push_back("max_cof");
mReservedUniforms.push_back("res_scale");
mReservedUniforms.push_back("depthMap");
mReservedUniforms.push_back("shadowMap0");
mReservedUniforms.push_back("shadowMap1");
mReservedUniforms.push_back("shadowMap2");
mReservedUniforms.push_back("shadowMap3");
mReservedUniforms.push_back("shadowMap4");
mReservedUniforms.push_back("shadowMap5");
llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW5+1);
mReservedUniforms.push_back("normalMap");
mReservedUniforms.push_back("positionMap");
mReservedUniforms.push_back("diffuseRect");
mReservedUniforms.push_back("specularRect");
mReservedUniforms.push_back("noiseMap");
mReservedUniforms.push_back("lightFunc");
mReservedUniforms.push_back("lightMap");
mReservedUniforms.push_back("bloomMap");
mReservedUniforms.push_back("projectionMap");
llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);
std::set<std::string> dupe_check;
for (U32 i = 0; i < mReservedUniforms.size(); ++i)
{
if (dupe_check.find(mReservedUniforms[i]) != dupe_check.end())
{
llerrs << "Duplicate reserved uniform name found: " << mReservedUniforms[i] << llendl;
}
dupe_check.insert(mReservedUniforms[i]);
}
}

View File

@@ -42,9 +42,137 @@ public:
LLShaderMgr();
virtual ~LLShaderMgr();
typedef enum
{
MODELVIEW_MATRIX = 0,
PROJECTION_MATRIX,
INVERSE_PROJECTION_MATRIX,
MODELVIEW_PROJECTION_MATRIX,
NORMAL_MATRIX,
TEXTURE_MATRIX0,
TEXTURE_MATRIX1,
TEXTURE_MATRIX2,
TEXTURE_MATRIX3,
VIEWPORT,
LIGHT_POSITION,
LIGHT_DIRECTION,
LIGHT_ATTENUATION,
LIGHT_DIFFUSE,
LIGHT_AMBIENT,
MULTI_LIGHT_COUNT,
MULTI_LIGHT,
MULTI_LIGHT_COL,
MULTI_LIGHT_FAR_Z,
PROJECTOR_MATRIX,
PROJECTOR_NEAR,
PROJECTOR_P,
PROJECTOR_N,
PROJECTOR_ORIGIN,
PROJECTOR_RANGE,
PROJECTOR_AMBIANCE,
PROJECTOR_SHADOW_INDEX,
PROJECTOR_SHADOW_FADE,
PROJECTOR_FOCUS,
PROJECTOR_LOD,
PROJECTOR_AMBIENT_LOD,
DIFFUSE_COLOR,
DIFFUSE_MAP,
SPECULAR_MAP,
BUMP_MAP,
ENVIRONMENT_MAP,
CLOUD_NOISE_MAP,
FULLBRIGHT,
LIGHTNORM,
SUNLIGHT_COLOR,
AMBIENT,
BLUE_HORIZON,
BLUE_DENSITY,
HAZE_HORIZON,
HAZE_DENSITY,
CLOUD_SHADOW,
DENSITY_MULTIPLIER,
DISTANCE_MULTIPLIER,
MAX_Y,
GLOW,
CLOUD_COLOR,
CLOUD_POS_DENSITY1,
CLOUD_POS_DENSITY2,
CLOUD_SCALE,
GAMMA,
SCENE_LIGHT_STRENGTH,
LIGHT_CENTER,
LIGHT_SIZE,
LIGHT_FALLOFF,
GLOW_MIN_LUMINANCE,
GLOW_MAX_EXTRACT_ALPHA,
GLOW_LUM_WEIGHTS,
GLOW_WARMTH_WEIGHTS,
GLOW_WARMTH_AMOUNT,
GLOW_STRENGTH,
GLOW_DELTA,
MINIMUM_ALPHA,
DEFERRED_SHADOW_MATRIX,
DEFERRED_ENV_MAT,
DEFERRED_SHADOW_CLIP,
DEFERRED_SUN_WASH,
DEFERRED_SHADOW_NOISE,
DEFERRED_BLUR_SIZE,
DEFERRED_SSAO_RADIUS,
DEFERRED_SSAO_MAX_RADIUS,
DEFERRED_SSAO_FACTOR,
DEFERRED_SSAO_FACTOR_INV,
DEFERRED_SSAO_EFFECT_MAT,
DEFERRED_SCREEN_RES,
DEFERRED_NEAR_CLIP,
DEFERRED_SHADOW_OFFSET,
DEFERRED_SHADOW_BIAS,
DEFERRED_SPOT_SHADOW_BIAS,
DEFERRED_SPOT_SHADOW_OFFSET,
DEFERRED_SUN_DIR,
DEFERRED_SHADOW_RES,
DEFERRED_PROJ_SHADOW_RES,
DEFERRED_DEPTH_CUTOFF,
DEFERRED_NORM_CUTOFF,
FXAA_TC_SCALE,
FXAA_RCP_SCREEN_RES,
FXAA_RCP_FRAME_OPT,
FXAA_RCP_FRAME_OPT2,
DOF_FOCAL_DISTANCE,
DOF_BLUR_CONSTANT,
DOF_TAN_PIXEL_ANGLE,
DOF_MAGNIFICATION,
DOF_MAX_COF,
DOF_RES_SCALE,
DEFERRED_DEPTH,
DEFERRED_SHADOW0,
DEFERRED_SHADOW1,
DEFERRED_SHADOW2,
DEFERRED_SHADOW3,
DEFERRED_SHADOW4,
DEFERRED_SHADOW5,
DEFERRED_NORMAL,
DEFERRED_POSITION,
DEFERRED_DIFFUSE,
DEFERRED_SPECULAR,
DEFERRED_NOISE,
DEFERRED_LIGHTFUNC,
DEFERRED_LIGHT,
DEFERRED_BLOOM,
DEFERRED_PROJECTION,
END_RESERVED_UNIFORMS
} eGLSLReservedUniforms;
// singleton pattern implementation
static LLShaderMgr * instance();
virtual void initAttribsAndUniforms(void);
BOOL attachShaderFeatures(LLGLSLShader * shader);
void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE);
BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);

File diff suppressed because it is too large Load Diff

View File

@@ -45,6 +45,8 @@
#include <vector>
#include <list>
#define LL_MAX_VERTEX_ATTRIB_LOCATION 64
//============================================================================
// NOTES
// Threading:
@@ -56,12 +58,32 @@
//============================================================================
// gl name pools for dynamic and streaming buffers
class LLVBOPool : public LLGLNamePool
class LLVBOPool
{
protected:
virtual GLuint allocateName();
virtual void releaseName(GLuint name);
public:
static U32 sBytesPooled;
U32 mUsage;
U32 mType;
//size MUST be a power of 2
U8* allocate(U32& name, U32 size);
//size MUST be the size provided to allocate that returned the given name
void release(U32 name, U8* buffer, U32 size);
//destroy all records in mFreeList
void cleanup();
class Record
{
public:
U32 mGLName;
U8* mClientData;
};
typedef std::list<Record> record_list_t;
std::vector<record_list_t> mFreeList;
};
class LLGLFence
@@ -72,11 +94,21 @@ public:
};
//============================================================================
// base class
// base class
class LLPrivateMemoryPool ;
class LLVertexBuffer : public LLRefCount
{
public:
class MappedRegion
{
public:
S32 mType;
S32 mIndex;
S32 mCount;
MappedRegion(S32 type, S32 index, S32 count);
};
LLVertexBuffer(const LLVertexBuffer& rhs)
{
*this = rhs;
@@ -93,20 +125,17 @@ public:
static LLVBOPool sStreamIBOPool;
static LLVBOPool sDynamicIBOPool;
static S32 sWeight4Loc;
static BOOL sUseStreamDraw;
static U32 sForceStrideMode;
static BOOL sOmitBlank;
static BOOL sUseVAO;
static BOOL sPreferStreamDraw;
static void initClass(bool use_vbo, bool no_vbo_mapping);
static void cleanupClass();
static void setupClientArrays(U32 data_mask);
static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm);
static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp);
static void clientCopy(F64 max_time = 0.005); //copy data from client to GL
static void unbind(); //unbind any bound vertex buffer
static void unbind(); //unbind any bound vertex buffer
//get the size of a vertex with the given typemask
static S32 calcVertexSize(const U32& typemask);
@@ -114,28 +143,32 @@ public:
//get the size of a buffer with the given typemask and vertex count
//fill offsets with the offset of each vertex component array into the buffer
// indexed by the following enum
//If strided, num_vertices will be ignored.
S32 calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices);
static S32 calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices);
//WARNING -- when updating these enums you MUST
// 1 - update LLVertexBuffer::sTypeSize
// 2 - add a strider accessor
// 3 - modify LLVertexBuffer::setupVertexBuffer
// 4 - modify LLVertexBuffer::setupClientArray
// 5 - modify LLViewerShaderMgr::mReservedAttribs
// 6 - update LLVertexBuffer::setupVertexArray
enum {
TYPE_VERTEX,
TYPE_VERTEX = 0,
TYPE_NORMAL,
TYPE_TEXCOORD0,
TYPE_TEXCOORD1,
TYPE_TEXCOORD2,
TYPE_TEXCOORD3,
TYPE_COLOR,
// These use VertexAttribPointer and should possibly be made generic
TYPE_EMISSIVE,
TYPE_BINORMAL,
TYPE_WEIGHT,
TYPE_WEIGHT4,
TYPE_CLOTHWEIGHT,
TYPE_MAX,
TYPE_INDEX,
//no actual additional data, but indicates position.w is texture index
TYPE_TEXTURE_INDEX,
TYPE_MAX,
TYPE_INDEX,
};
enum {
MAP_VERTEX = (1<<TYPE_VERTEX),
@@ -145,6 +178,7 @@ public:
MAP_TEXCOORD2 = (1<<TYPE_TEXCOORD2),
MAP_TEXCOORD3 = (1<<TYPE_TEXCOORD3),
MAP_COLOR = (1<<TYPE_COLOR),
MAP_EMISSIVE = (1<<TYPE_EMISSIVE),
// These use VertexAttribPointer and should possibly be made generic
MAP_BINORMAL = (1<<TYPE_BINORMAL),
MAP_WEIGHT = (1<<TYPE_WEIGHT),
@@ -158,37 +192,39 @@ protected:
virtual ~LLVertexBuffer(); // use unref()
virtual void setupVertexBuffer(U32 data_mask) const; // pure virtual, called from mapBuffer()
virtual void setupVertexBuffer(U32 data_mask); // pure virtual, called from mapBuffer()
void setupVertexArray();
void genBuffer();
void genIndices();
void genBuffer(U32 size);
void genIndices(U32 size);
bool bindGLBuffer(bool force_bind = false);
bool bindGLIndices(bool force_bind = false);
bool bindGLArray();
void releaseBuffer();
void releaseIndices();
void createGLBuffer();
void createGLIndices();
void createGLBuffer(U32 size);
void createGLIndices(U32 size);
void destroyGLBuffer();
void destroyGLIndices();
void updateNumVerts(S32 nverts);
void updateNumIndices(S32 nindices);
virtual BOOL useVBOs() const;
void unmapBuffer(S32 type);
void freeClientBuffer() ;
void allocateClientVertexBuffer() ;
void allocateClientIndexBuffer() ;
void unmapBuffer();
public:
LLVertexBuffer(U32 typemask, S32 usage, bool strided=true);
LLVertexBuffer(U32 typemask, S32 usage);
// map for data access
volatile U8* mapVertexBuffer(S32 type, S32 index);
volatile U8* mapIndexBuffer(S32 index);
/*volatile */U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range);
/*volatile */U8* mapIndexBuffer(S32 index, S32 count, bool map_range);
// set for rendering
virtual void setBuffer(U32 data_mask, S32 type = -1); // calls setupVertexBuffer() if data_mask is not 0
virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0
void flush(); //flush pending data to GL memory
// allocate buffer
void allocateBuffer(S32 nverts, S32 nindices, bool create);
virtual void resizeBuffer(S32 newnverts, S32 newnindices);
// Only call each getVertexPointer, etc, once before calling unmapBuffer()
// call unmapBuffer() after calls to getXXXStrider() before any cals to setBuffer()
// example:
@@ -196,33 +232,33 @@ public:
// vb->getNormalStrider(norms);
// setVertsNorms(verts, norms);
// vb->unmapBuffer();
bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0);
bool getIndexStrider(LLStrider<U16>& strider, S32 index=0);
bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0);
bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0);
bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0);
bool getWeightStrider(LLStrider<F32>& strider, S32 index=0);
bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0);
bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0);
bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getVertexStrider(LLStrider<LLVector4a>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getIndexStrider(LLStrider<U16>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
BOOL isEmpty() const { return mEmpty; }
BOOL isLocked() const { return mVertexLocked || mIndexLocked; }
S32 getNumVerts() const { return mNumVerts; }
S32 getNumIndices() const { return mNumIndices; }
S32 getRequestedVerts() const { return mRequestedNumVerts; }
S32 getRequestedIndices() const { return mRequestedNumIndices; }
volatile U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; }
volatile U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; }
S32 getStride(S32 type) const { return mIsStrided ? mStride : sTypeSize[type]; }
/*volatile */U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; }
/*volatile */U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; }
U32 getTypeMask() const { return mTypeMask; }
bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); }
S32 getSize() const;
S32 getIndicesSize() const { return mNumIndices * sizeof(U16); }
volatile U8* getMappedData() const { return mMappedData; }
volatile U8* getMappedIndices() const { return mMappedIndexData; }
S32 getIndicesSize() const { return mIndicesSize; }
/*volatile */U8* getMappedData() const { return mMappedData; }
/*volatile */U8* getMappedIndices() const { return mMappedIndexData; }
S32 getOffset(S32 type) const { return mOffsets[type]; }
S32 getUsage() const { return mUsage; }
@@ -238,41 +274,42 @@ public:
protected:
S32 mNumVerts; // Number of vertices allocated
S32 mNumIndices; // Number of indices allocated
S32 mRequestedNumVerts; // Number of vertices requested
S32 mRequestedNumIndices; // Number of indices requested
ptrdiff_t mAlignedOffset;
ptrdiff_t mAlignedIndexOffset;
bool mIsStrided;
S32 mStride; // Vertex size.
S32 mSize; // Full array size
S32 mSize;
S32 mIndicesSize;
U32 mTypeMask;
S32 mUsage; // GL usage
U32 mGLBuffer; // GL VBO handle
U32 mGLIndices; // GL IBO handle
volatile U8* mMappedData; // pointer to currently mapped data (NULL if unmapped)
volatile U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped)
U32 mGLArray; // GL VAO handle
/*volatile */U8* mMappedData; // pointer to currently mapped data (NULL if unmapped)
/*volatile */U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped)
BOOL mVertexLocked; // if TRUE, vertex buffer is being or has been written to in client memory
BOOL mIndexLocked; // if TRUE, index buffer is being or has been written to in client memory
BOOL mFinal; // if TRUE, buffer can not be mapped again
BOOL mFilthy; // if TRUE, entire buffer must be copied (used to prevent redundant dirty flags)
BOOL mEmpty; // if TRUE, client buffer is empty (or NULL). Old values have been discarded.
BOOL mResized; // if TRUE, client buffer has been resized and GL buffer has not
BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded)
S32 mOffsets[TYPE_MAX];
std::vector<MappedRegion> mMappedVertexRegions;
std::vector<MappedRegion> mMappedIndexRegions;
mutable LLGLFence* mFence;
void placeFence() const;
void waitFence() const;
private:
static LLPrivateMemoryPool* sPrivatePoolp ;
public:
static S32 sCount;
static S32 sGLCount;
static S32 sMappedCount;
static BOOL sMapped;
static std::vector<U32> sDeleteList;
typedef std::list<LLVertexBuffer*> buffer_list_t;
static BOOL sDisableVBOMapping; //disable glMapBufferARB
@@ -280,6 +317,7 @@ public:
static S32 sTypeSize[TYPE_MAX];
static U32 sGLMode[LLRender::NUM_MODES];
static U32 sGLRenderBuffer;
static U32 sGLRenderArray;
static U32 sGLRenderIndices;
static BOOL sVBOActive;
static BOOL sIBOActive;

View File

@@ -41,6 +41,7 @@ set(llui_SOURCE_FILES
lllineeditor.cpp
llmenugl.cpp
llmodaldialog.cpp
llmultifloater.cpp
llmultislider.cpp
llmultisliderctrl.cpp
llnotifications.cpp
@@ -68,6 +69,7 @@ set(llui_SOURCE_FILES
llui.cpp
lluictrl.cpp
lluictrlfactory.cpp
lluiimage.cpp
lluistring.cpp
lluitrans.cpp
llundo.cpp
@@ -92,6 +94,7 @@ set(llui_HEADER_FILES
llfloater.h
llfocusmgr.h
llfunctorregistry.h
llhandle.h
llhtmlhelp.h
lliconctrl.h
llkeywords.h
@@ -99,6 +102,7 @@ set(llui_HEADER_FILES
llmemberlistener.h
llmenugl.h
llmodaldialog.h
llmultifloater.h
llmultisliderctrl.h
llmultislider.h
llnotificationptr.h
@@ -129,6 +133,7 @@ set(llui_HEADER_FILES
lluictrl.h
lluifwd.h
llui.h
lluiimage.h
lluistring.h
lluitrans.h
lluixmltags.h

View File

@@ -423,7 +423,7 @@ void LLButton::draw()
// Unselected image assignments
S32 local_mouse_x;
S32 local_mouse_y;
LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y);
LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y);
BOOL pressed = pressed_by_keyboard
|| (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y))
@@ -688,7 +688,7 @@ void LLButton::draw()
x = text_right;
break;
case LLFontGL::HCENTER:
x = getRect().getWidth() / 2;
x = text_left + (text_width / 2);
break;
case LLFontGL::LEFT:
default:
@@ -704,10 +704,13 @@ void LLButton::draw()
x++;
}
mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset),
mGLFont->render(label, 0,
(F32)x,
(F32)(LLBUTTON_V_PAD + y_offset),
label_color,
mHAlign, LLFontGL::BOTTOM,
mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NORMAL,
LLFontGL::NORMAL,
mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW,
U32_MAX, text_width,
NULL, FALSE, FALSE);
}

View File

@@ -39,7 +39,7 @@
#include "v4color.h"
#include "llframetimer.h"
#include "llfontgl.h"
#include "llimage.h"
#include "lluiimage.h"
#include "lluistring.h"
//

View File

@@ -117,7 +117,7 @@ void LLDragHandleTop::setTitle(const std::string& title)
const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
LLTextBox* titlebox = new LLTextBox( std::string("Drag Handle Title"), getRect(), trimmed_title, font );
titlebox->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT);
titlebox->setFontStyle(LLFontGL::DROP_SHADOW_SOFT);
titlebox->setFontShadow(LLFontGL::DROP_SHADOW_SOFT);
setTitleBox(titlebox);
reshapeTitleBox();

View File

@@ -35,7 +35,7 @@
#include "linden_common.h"
#include "llfloater.h"
#include "llmultifloater.h"
#include "llfocusmgr.h"
@@ -2480,519 +2480,7 @@ void LLFloaterView::popVisibleAll(const skip_list_t& skip_list)
}
}
//
// LLMultiFloater
//
LLMultiFloater::LLMultiFloater() :
mTabContainer(NULL),
mTabPos(LLTabContainer::TOP),
mAutoResize(TRUE),
mOrigMinWidth(0),
mOrigMinHeight(0)
{
}
LLMultiFloater::LLMultiFloater(LLTabContainer::TabPosition tab_pos) :
mTabContainer(NULL),
mTabPos(tab_pos),
mAutoResize(TRUE),
mOrigMinWidth(0),
mOrigMinHeight(0)
{
}
LLMultiFloater::LLMultiFloater(const std::string &name) :
LLFloater(name),
mTabContainer(NULL),
mTabPos(LLTabContainer::TOP),
mAutoResize(FALSE),
mOrigMinWidth(0),
mOrigMinHeight(0)
{
}
LLMultiFloater::LLMultiFloater(
const std::string& name,
const LLRect& rect,
LLTabContainer::TabPosition tab_pos,
BOOL auto_resize) :
LLFloater(name, rect, name),
mTabContainer(NULL),
mTabPos(LLTabContainer::TOP),
mAutoResize(auto_resize),
mOrigMinWidth(0),
mOrigMinHeight(0)
{
mTabContainer = new LLTabContainer(std::string("Preview Tabs"),
LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - LLFLOATER_HEADER_SIZE, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0),
mTabPos,
FALSE,
FALSE);
mTabContainer->setFollowsAll();
if (isResizable())
{
mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
}
addChild(mTabContainer);
}
LLMultiFloater::LLMultiFloater(
const std::string& name,
const std::string& rect_control,
LLTabContainer::TabPosition tab_pos,
BOOL auto_resize) :
LLFloater(name, rect_control, name),
mTabContainer(NULL),
mTabPos(tab_pos),
mAutoResize(auto_resize),
mOrigMinWidth(0),
mOrigMinHeight(0)
{
mTabContainer = new LLTabContainer(std::string("Preview Tabs"),
LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - LLFLOATER_HEADER_SIZE, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0),
mTabPos,
FALSE,
FALSE);
mTabContainer->setFollowsAll();
if (isResizable() && mTabPos == LLTabContainer::BOTTOM)
{
mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
}
addChild(mTabContainer);
}
// virtual
LLXMLNodePtr LLMultiFloater::getXML(bool save_children) const
{
LLXMLNodePtr node = LLFloater::getXML();
node->setName(LL_MULTI_FLOATER_TAG);
return node;
}
void LLMultiFloater::open() /* Flawfinder: ignore */
{
if (mTabContainer->getTabCount() > 0)
{
LLFloater::open(); /* Flawfinder: ignore */
}
else
{
// for now, don't allow multifloaters
// without any child floaters
close();
}
}
void LLMultiFloater::onClose(bool app_quitting)
{
if(closeAllFloaters() == TRUE)
{
LLFloater::onClose(app_quitting);
}//else not all tabs could be closed...
}
void LLMultiFloater::draw()
{
if (mTabContainer->getTabCount() == 0)
{
//RN: could this potentially crash in draw hierarchy?
close();
}
else
{
for (S32 i = 0; i < mTabContainer->getTabCount(); i++)
{
LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(i);
if (floaterp->getShortTitle() != mTabContainer->getPanelTitle(i))
{
mTabContainer->setPanelTitle(i, floaterp->getShortTitle());
}
}
LLFloater::draw();
}
}
BOOL LLMultiFloater::closeAllFloaters()
{
S32 tabToClose = 0;
S32 lastTabCount = mTabContainer->getTabCount();
while (tabToClose < mTabContainer->getTabCount())
{
LLFloater* first_floater = (LLFloater*)mTabContainer->getPanelByIndex(tabToClose);
first_floater->close();
if(lastTabCount == mTabContainer->getTabCount())
{
//Tab did not actually close, possibly due to a pending Save Confirmation dialog..
//so try and close the next one in the list...
tabToClose++;
}else
{
//Tab closed ok.
lastTabCount = mTabContainer->getTabCount();
}
}
if( mTabContainer->getTabCount() != 0 )
return FALSE; // Couldn't close all the tabs (pending save dialog?) so return FALSE.
return TRUE; //else all tabs were successfully closed...
}
void LLMultiFloater::growToFit(S32 content_width, S32 content_height)
{
S32 new_width = llmax(getRect().getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2);
S32 new_height = llmax(getRect().getHeight(), content_height + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
if (isMinimized())
{
LLRect newrect;
newrect.setLeftTopAndSize(getExpandedRect().mLeft, getExpandedRect().mTop, new_width, new_height);
setExpandedRect(newrect);
}
else
{
S32 old_height = getRect().getHeight();
reshape(new_width, new_height);
// keep top left corner in same position
translate(0, old_height - new_height);
}
}
/**
void addFloater(LLFloater* floaterp, BOOL select_added_floater)
Adds the LLFloater pointed to by floaterp to this.
If floaterp is already hosted by this, then it is re-added to get
new titles, etc.
If select_added_floater is true, the LLFloater pointed to by floaterp will
become the selected tab in this
Affects: mTabContainer, floaterp
**/
void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point)
{
if (!floaterp)
{
return;
}
if (!mTabContainer)
{
llerrs << "Tab Container used without having been initialized." << llendl;
return;
}
if (floaterp->getHost() == this)
{
// already hosted by me, remove
// do this so we get updated title, etc.
mFloaterDataMap.erase(floaterp->getHandle());
mTabContainer->removeTabPanel(floaterp);
}
else if (floaterp->getHost())
{
// floaterp is hosted by somebody else and
// this is adding it, so remove it from it's old host
floaterp->getHost()->removeFloater(floaterp);
}
else if (floaterp->getParent() == gFloaterView)
{
// rehost preview floater as child panel
gFloaterView->removeChild(floaterp);
}
// store original configuration
LLFloaterData floater_data;
floater_data.mWidth = floaterp->getRect().getWidth();
floater_data.mHeight = floaterp->getRect().getHeight();
floater_data.mCanMinimize = floaterp->isMinimizeable();
floater_data.mCanResize = floaterp->isResizable();
// remove minimize and close buttons
floaterp->setCanMinimize(FALSE);
floaterp->setCanResize(FALSE);
floaterp->setCanDrag(FALSE);
floaterp->storeRectControl();
// avoid double rendering of floater background (makes it more opaque)
floaterp->setBackgroundVisible(FALSE);
if (mAutoResize)
{
growToFit(floater_data.mWidth, floater_data.mHeight);
}
//add the panel, add it to proper maps
mTabContainer->addTabPanel(floaterp, floaterp->getShortTitle(), FALSE, onTabSelected, this, 0, FALSE, insertion_point);
mFloaterDataMap[floaterp->getHandle()] = floater_data;
updateResizeLimits();
if ( select_added_floater )
{
mTabContainer->selectTabPanel(floaterp);
}
else
{
// reassert visible tab (hiding new floater if necessary)
mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex());
}
floaterp->setHost(this);
if (isMinimized())
{
floaterp->setVisible(FALSE);
}
}
/**
BOOL selectFloater(LLFloater* floaterp)
If the LLFloater pointed to by floaterp is hosted by this,
then its tab is selected and returns true. Otherwise returns false.
Affects: mTabContainer
**/
BOOL LLMultiFloater::selectFloater(LLFloater* floaterp)
{
return mTabContainer->selectTabPanel(floaterp);
}
// virtual
void LLMultiFloater::selectNextFloater()
{
mTabContainer->selectNextTab();
}
// virtual
void LLMultiFloater::selectPrevFloater()
{
mTabContainer->selectPrevTab();
}
void LLMultiFloater::showFloater(LLFloater* floaterp)
{
// we won't select a panel that already is selected
// it is hard to do this internally to tab container
// as tab selection is handled via index and the tab at a given
// index might have changed
if (floaterp != mTabContainer->getCurrentPanel() &&
!mTabContainer->selectTabPanel(floaterp))
{
addFloater(floaterp, TRUE);
}
}
void LLMultiFloater::removeFloater(LLFloater* floaterp)
{
if ( floaterp->getHost() != this )
return;
floater_data_map_t::iterator found_data_it = mFloaterDataMap.find(floaterp->getHandle());
if (found_data_it != mFloaterDataMap.end())
{
LLFloaterData& floater_data = found_data_it->second;
floaterp->setCanMinimize(floater_data.mCanMinimize);
if (!floater_data.mCanResize)
{
// restore original size
floaterp->reshape(floater_data.mWidth, floater_data.mHeight);
}
floaterp->setCanResize(floater_data.mCanResize);
mFloaterDataMap.erase(found_data_it);
}
mTabContainer->removeTabPanel(floaterp);
floaterp->setBackgroundVisible(TRUE);
floaterp->setCanDrag(TRUE);
floaterp->setHost(NULL);
floaterp->applyRectControl();
updateResizeLimits();
tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false);
}
void LLMultiFloater::tabOpen(LLFloater* opened_floater, bool from_click)
{
// default implementation does nothing
}
void LLMultiFloater::tabClose()
{
if (mTabContainer->getTabCount() == 0)
{
// no more children, close myself
close();
}
}
void LLMultiFloater::setVisible(BOOL visible)
{
// *FIX: shouldn't have to do this, fix adding to minimized multifloater
LLFloater::setVisible(visible);
if (mTabContainer)
{
LLPanel* cur_floaterp = mTabContainer->getCurrentPanel();
if (cur_floaterp)
{
cur_floaterp->setVisible(visible);
}
// if no tab selected, and we're being shown,
// select last tab to be added
if (visible && !cur_floaterp)
{
mTabContainer->selectLastTab();
}
}
}
BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask)
{
if (key == 'W' && mask == MASK_CONTROL)
{
LLFloater* floater = getActiveFloater();
// is user closeable and is system closeable
if (floater && floater->canClose() && floater->isCloseable())
{
floater->close();
}
return TRUE;
}
return LLFloater::handleKeyHere(key, mask);
}
LLFloater* LLMultiFloater::getActiveFloater()
{
return (LLFloater*)mTabContainer->getCurrentPanel();
}
S32 LLMultiFloater::getFloaterCount()
{
return mTabContainer->getTabCount();
}
/**
BOOL isFloaterFlashing(LLFloater* floaterp)
Returns true if the LLFloater pointed to by floaterp
is currently in a flashing state and is hosted by this.
False otherwise.
Requires: floaterp != NULL
**/
BOOL LLMultiFloater::isFloaterFlashing(LLFloater* floaterp)
{
if ( floaterp && floaterp->getHost() == this )
return mTabContainer->getTabPanelFlashing(floaterp);
return FALSE;
}
/**
BOOL setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
Sets the current flashing state of the LLFloater pointed
to by floaterp to be the BOOL flashing if the LLFloater pointed
to by floaterp is hosted by this.
Requires: floaterp != NULL
**/
void LLMultiFloater::setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
{
if ( floaterp && floaterp->getHost() == this )
mTabContainer->setTabPanelFlashing(floaterp, flashing);
}
//static
void LLMultiFloater::onTabSelected(void* userdata, bool from_click)
{
LLMultiFloater* floaterp = (LLMultiFloater*)userdata;
floaterp->tabOpen((LLFloater*)floaterp->mTabContainer->getCurrentPanel(), from_click);
}
void LLMultiFloater::setCanResize(BOOL can_resize)
{
LLFloater::setCanResize(can_resize);
if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM)
{
mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
}
else
{
mTabContainer->setRightTabBtnOffset(0);
}
}
BOOL LLMultiFloater::postBuild()
{
// remember any original xml minimum size
getResizeLimits(&mOrigMinWidth, &mOrigMinHeight);
if (mTabContainer)
{
return TRUE;
}
requires<LLTabContainer>("Preview Tabs");
if (checkRequirements())
{
mTabContainer = getChild<LLTabContainer>("Preview Tabs");
return TRUE;
}
return FALSE;
}
void LLMultiFloater::updateResizeLimits()
{
// initialize minimum size constraint to the original xml values.
S32 new_min_width = mOrigMinWidth;
S32 new_min_height = mOrigMinHeight;
// possibly increase minimum size constraint due to children's minimums.
for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
{
LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
if (floaterp)
{
new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
new_min_height = llmax(new_min_height, floaterp->getMinHeight() + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
}
}
setResizeLimits(new_min_width, new_min_height);
S32 cur_height = getRect().getHeight();
S32 new_width = llmax(getRect().getWidth(), new_min_width);
S32 new_height = llmax(getRect().getHeight(), new_min_height);
if (isMinimized())
{
const LLRect& expanded = getExpandedRect();
LLRect newrect;
newrect.setLeftTopAndSize(expanded.mLeft, expanded.mTop, llmax(expanded.getWidth(), new_width), llmax(expanded.getHeight(), new_height));
setExpandedRect(newrect);
}
else
{
reshape(new_width, new_height);
// make sure upper left corner doesn't move
translate(0, cur_height - getRect().getHeight());
// make sure this window is visible on screen when it has been modified
// (tab added, etc)
gFloaterView->adjustToFitScreen(this, TRUE);
}
}
// virtual
LLXMLNodePtr LLFloater::getXML(bool save_children) const
@@ -3129,3 +2617,15 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
moveResizeHandlesToFront();
}
/*static */void VisibilityPolicy<LLFloater>::show(LLFloater* instance, const LLSD& key)
{
if (instance)
{
instance->open();
if (instance->getHost())
{
instance->getHost()->open();
}
}
}

View File

@@ -90,7 +90,8 @@ private:
class LLFloater : public LLPanel
{
friend class LLFloaterView;
friend class LLFloaterView;
friend class LLMultiFloater;
public:
enum EFloaterButtons
{
@@ -395,69 +396,6 @@ private:
S32 mSnapOffsetBottom;
};
// https://wiki.lindenlab.com/mediawiki/index.php?title=LLMultiFloater&oldid=81376
class LLMultiFloater : public LLFloater
{
public:
LLMultiFloater();
LLMultiFloater(LLTabContainer::TabPosition tab_pos);
LLMultiFloater(const std::string& name);
LLMultiFloater(const std::string& name, const LLRect& rect, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE);
LLMultiFloater(const std::string& name, const std::string& rect_control, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE);
virtual ~LLMultiFloater() {};
virtual BOOL postBuild();
virtual LLXMLNodePtr getXML(bool save_children = true) const;
/*virtual*/ void open(); /* Flawfinder: ignore */
/*virtual*/ void onClose(bool app_quitting);
/*virtual*/ void draw();
/*virtual*/ void setVisible(BOOL visible);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
virtual void setCanResize(BOOL can_resize);
virtual void growToFit(S32 content_width, S32 content_height);
virtual void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END);
virtual void showFloater(LLFloater* floaterp);
virtual void removeFloater(LLFloater* floaterp);
virtual void tabOpen(LLFloater* opened_floater, bool from_click);
virtual void tabClose();
virtual BOOL selectFloater(LLFloater* floaterp);
virtual void selectNextFloater();
virtual void selectPrevFloater();
virtual LLFloater* getActiveFloater();
virtual BOOL isFloaterFlashing(LLFloater* floaterp);
virtual S32 getFloaterCount();
virtual void setFloaterFlashing(LLFloater* floaterp, BOOL flashing);
virtual BOOL closeAllFloaters(); //Returns FALSE if the floater could not be closed due to pending confirmation dialogs
void setTabContainer(LLTabContainer* tab_container) { if (!mTabContainer) mTabContainer = tab_container; }
static void onTabSelected(void* userdata, bool);
virtual void updateResizeLimits();
protected:
struct LLFloaterData
{
S32 mWidth;
S32 mHeight;
BOOL mCanMinimize;
BOOL mCanResize;
};
LLTabContainer* mTabContainer;
typedef std::map<LLHandle<LLFloater>, LLFloaterData> floater_data_map_t;
floater_data_map_t mFloaterDataMap;
LLTabContainer::TabPosition mTabPos;
BOOL mAutoResize;
S32 mOrigMinWidth, mOrigMinHeight; // logically const but initialized late
};
// visibility policy specialized for floaters
template<>
class VisibilityPolicy<LLFloater>
@@ -473,17 +411,7 @@ public:
return FALSE;
}
static void show(LLFloater* instance, const LLSD& key)
{
if (instance)
{
instance->open();
if (instance->getHost())
{
instance->getHost()->open();
}
}
}
static void show(LLFloater* instance, const LLSD& key);
static void hide(LLFloater* instance, const LLSD& key)
{

View File

@@ -38,6 +38,7 @@
#include "llstring.h"
#include "llframetimer.h"
#include "llui.h"
#include "llhandle.h"
class LLUICtrl;
class LLMouseHandler;

164
indra/llui/llhandle.h Normal file
View File

@@ -0,0 +1,164 @@
/**
* @file llhandle.h
* @brief "Handle" to an object (usually a floater) whose lifetime you don't
* control.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLHANDLE_H
#define LLHANDLE_H
#include "llpointer.h"
template <typename T>
class LLTombStone : public LLRefCount
{
public:
LLTombStone(T* target = NULL) : mTarget(target) {}
void setTarget(T* target) { mTarget = target; }
T* getTarget() const { return mTarget; }
private:
T* mTarget;
};
// LLHandles are used to refer to objects whose lifetime you do not control or influence.
// Calling get() on a handle will return a pointer to the referenced object or NULL,
// if the object no longer exists. Note that during the lifetime of the returned pointer,
// you are assuming that the object will not be deleted by any action you perform,
// or any other thread, as normal when using pointers, so avoid using that pointer outside of
// the local code block.
//
// https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669
template <typename T>
class LLHandle
{
public:
LLHandle() : mTombStone(getDefaultTombStone()) {}
const LLHandle<T>& operator =(const LLHandle<T>& other)
{
mTombStone = other.mTombStone;
return *this;
}
bool isDead() const
{
return mTombStone->getTarget() == NULL;
}
void markDead()
{
mTombStone = getDefaultTombStone();
}
T* get() const
{
return mTombStone->getTarget();
}
friend bool operator== (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
{
return lhs.mTombStone == rhs.mTombStone;
}
friend bool operator!= (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
{
return !(lhs == rhs);
}
friend bool operator< (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
{
return lhs.mTombStone < rhs.mTombStone;
}
friend bool operator> (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
{
return lhs.mTombStone > rhs.mTombStone;
}
protected:
LLPointer<LLTombStone<T> > mTombStone;
private:
static LLPointer<LLTombStone<T> >& getDefaultTombStone()
{
static LLPointer<LLTombStone<T> > sDefaultTombStone = new LLTombStone<T>;
return sDefaultTombStone;
}
};
template <typename T>
class LLRootHandle : public LLHandle<T>
{
public:
LLRootHandle(T* object) { bind(object); }
LLRootHandle() {};
~LLRootHandle() { unbind(); }
// this is redundant, since a LLRootHandle *is* an LLHandle
LLHandle<T> getHandle() { return LLHandle<T>(*this); }
void bind(T* object)
{
// unbind existing tombstone
if (LLHandle<T>::mTombStone.notNull())
{
if (LLHandle<T>::mTombStone->getTarget() == object) return;
LLHandle<T>::mTombStone->setTarget(NULL);
}
// tombstone reference counted, so no paired delete
LLHandle<T>::mTombStone = new LLTombStone<T>(object);
}
void unbind()
{
LLHandle<T>::mTombStone->setTarget(NULL);
}
//don't allow copying of root handles, since there should only be one
private:
LLRootHandle(const LLRootHandle& other) {};
};
// Use this as a mixin for simple classes that need handles and when you don't
// want handles at multiple points of the inheritance hierarchy
template <typename T>
class LLHandleProvider
{
protected:
typedef LLHandle<T> handle_type_t;
LLHandleProvider()
{
// provided here to enforce T deriving from LLHandleProvider<T>
}
LLHandle<T> getHandle()
{
// perform lazy binding to avoid small tombstone allocations for handle
// providers whose handles are never referenced
mHandle.bind(static_cast<T*>(this));
return mHandle;
}
private:
LLRootHandle<T> mHandle;
};
#endif

View File

@@ -1964,6 +1964,7 @@ void LLLineEditor::draw()
text_color,
LLFontGL::LEFT, LLFontGL::BOTTOM,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
select_left - mScrollHPos,
mMaxHPixels - llround(rendered_pixels_right),
&rendered_pixels_right);
@@ -1983,6 +1984,7 @@ void LLLineEditor::draw()
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
LLFontGL::LEFT, LLFontGL::BOTTOM,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
select_right - mScrollHPos - rendered_text,
mMaxHPixels - llround(rendered_pixels_right),
&rendered_pixels_right);
@@ -1997,6 +1999,7 @@ void LLLineEditor::draw()
text_color,
LLFontGL::LEFT, LLFontGL::BOTTOM,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
S32_MAX,
mMaxHPixels - llround(rendered_pixels_right),
&rendered_pixels_right);
@@ -2010,6 +2013,7 @@ void LLLineEditor::draw()
text_color,
LLFontGL::LEFT, LLFontGL::BOTTOM,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
S32_MAX,
mMaxHPixels - llround(rendered_pixels_right),
&rendered_pixels_right);
@@ -2050,6 +2054,7 @@ void LLLineEditor::draw()
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
LLFontGL::LEFT, LLFontGL::BOTTOM,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
1);
}
@@ -2075,6 +2080,7 @@ void LLLineEditor::draw()
LLFontGL::LEFT,
LLFontGL::BOTTOM,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
S32_MAX,
mMaxHPixels - llround(rendered_pixels_right),
&rendered_pixels_right, FALSE);
@@ -2099,6 +2105,7 @@ void LLLineEditor::draw()
LLFontGL::LEFT,
LLFontGL::BOTTOM,
LLFontGL::NORMAL,
LLFontGL::NO_SHADOW,
S32_MAX,
mMaxHPixels - llround(rendered_pixels_right),
&rendered_pixels_right, FALSE);
@@ -2547,9 +2554,8 @@ BOOL LLLineEditor::evaluateFloat()
else
{
// Replace the expression with the result
std::ostringstream result_str;
result_str << result;
setText(result_str.str());
std::string result_str = llformat("%f", result);
setText(result_str);
selectAll();
}

View File

@@ -47,6 +47,7 @@
#include "lleditmenuhandler.h"
#include "lluictrl.h"
#include "lluiimage.h"
#include "lluistring.h"
#include "llviewborder.h"

View File

@@ -447,10 +447,10 @@ void LLMenuItemGL::draw( void )
LLColor4 color;
U8 font_style = mStyle;
LLFontGL::ShadowType font_shadow = LLFontGL::NO_SHADOW;
if (getEnabled() && !mDrawTextDisabled )
{
font_style |= LLFontGL::DROP_SHADOW_SOFT;
font_shadow = LLFontGL::DROP_SHADOW_SOFT;
}
if ( getEnabled() && getHighlight() )
@@ -470,26 +470,26 @@ void LLMenuItemGL::draw( void )
if (mBriefItem)
{
mFont->render( mLabel, 0, BRIEF_PAD_PIXELS / 2, 0, color,
LLFontGL::LEFT, LLFontGL::BOTTOM, font_style );
LLFontGL::LEFT, LLFontGL::BOTTOM, mStyle );
}
else
{
if( !mDrawBoolLabel.empty() )
{
mFont->render( mDrawBoolLabel.getWString(), 0, (F32)LEFT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color,
LLFontGL::LEFT, LLFontGL::BOTTOM, font_style, S32_MAX, S32_MAX, NULL, FALSE );
LLFontGL::LEFT, LLFontGL::BOTTOM, mStyle, font_shadow, S32_MAX, S32_MAX, NULL, FALSE );
}
mFont->render( mLabel.getWString(), 0, (F32)LEFT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color,
LLFontGL::LEFT, LLFontGL::BOTTOM, font_style, S32_MAX, S32_MAX, NULL, FALSE );
LLFontGL::LEFT, LLFontGL::BOTTOM, mStyle, font_shadow, S32_MAX, S32_MAX, NULL, FALSE );
if( !mDrawAccelLabel.empty() )
{
mFont->render( mDrawAccelLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color,
LLFontGL::RIGHT, LLFontGL::BOTTOM, font_style, S32_MAX, S32_MAX, NULL, FALSE );
LLFontGL::RIGHT, LLFontGL::BOTTOM, mStyle, font_shadow, S32_MAX, S32_MAX, NULL, FALSE );
}
if( !mDrawBranchLabel.empty() )
{
mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color,
LLFontGL::RIGHT, LLFontGL::BOTTOM, font_style, S32_MAX, S32_MAX, NULL, FALSE );
LLFontGL::RIGHT, LLFontGL::BOTTOM, mStyle, font_shadow, S32_MAX, S32_MAX, NULL, FALSE );
}
}
@@ -1638,10 +1638,10 @@ void LLMenuItemBranchDownGL::draw( void )
gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 );
}
U8 font_style = getFontStyle();
LLFontGL::ShadowType font_shadow = LLFontGL::NO_SHADOW;
if (getEnabled() && !getDrawTextDisabled() )
{
font_style |= LLFontGL::DROP_SHADOW_SOFT;
font_shadow = LLFontGL::DROP_SHADOW_SOFT;
}
LLColor4 color;
@@ -1658,7 +1658,7 @@ void LLMenuItemBranchDownGL::draw( void )
color = getDisabledColor();
}
getFont()->render( mLabel.getWString(), 0, (F32)getRect().getWidth() / 2.f, (F32)LABEL_BOTTOM_PAD_PIXELS, color,
LLFontGL::HCENTER, LLFontGL::BOTTOM, font_style );
LLFontGL::HCENTER, LLFontGL::BOTTOM, getFontStyle(), font_shadow );
// underline navigation key only when keyboard navigation has been initiated
@@ -3858,7 +3858,7 @@ void LLPieMenu::show(S32 x, S32 y, BOOL mouse_down)
center.mX = (getRect().mLeft + getRect().mRight) / 2;
center.mY = (getRect().mTop + getRect().mBottom) / 2;
LLUI::setCursorPositionLocal(getParent(), center.mX, center.mY);
LLUI::setMousePositionLocal(getParent(), center.mX, center.mY);
}
// *FIX: what happens when mouse buttons reversed?

View File

@@ -0,0 +1,547 @@
/**
* @file llmultifloater.cpp
* @brief LLFloater that hosts other floaters
*
* $LicenseInfo:firstyear=2002&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$
*/
// Floating "windows" within the GL display, like the inventory floater,
// mini-map floater, etc.
#include "linden_common.h"
#include "llmultifloater.h"
#include "llresizehandle.h"
//
// LLMultiFloater
//
LLMultiFloater::LLMultiFloater() :
mTabContainer(NULL),
mTabPos(LLTabContainer::TOP),
mAutoResize(TRUE),
mOrigMinWidth(0),
mOrigMinHeight(0)
{
}
LLMultiFloater::LLMultiFloater(LLTabContainer::TabPosition tab_pos) :
mTabContainer(NULL),
mTabPos(tab_pos),
mAutoResize(TRUE),
mOrigMinWidth(0),
mOrigMinHeight(0)
{
}
LLMultiFloater::LLMultiFloater(const std::string &name) :
LLFloater(name),
mTabContainer(NULL),
mTabPos(LLTabContainer::TOP),
mAutoResize(FALSE),
mOrigMinWidth(0),
mOrigMinHeight(0)
{
}
LLMultiFloater::LLMultiFloater(
const std::string& name,
const LLRect& rect,
LLTabContainer::TabPosition tab_pos,
BOOL auto_resize) :
LLFloater(name, rect, name),
mTabContainer(NULL),
mTabPos(LLTabContainer::TOP),
mAutoResize(auto_resize),
mOrigMinWidth(0),
mOrigMinHeight(0)
{
mTabContainer = new LLTabContainer(std::string("Preview Tabs"),
LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - LLFLOATER_HEADER_SIZE, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0),
mTabPos,
FALSE,
FALSE);
mTabContainer->setFollowsAll();
if (isResizable())
{
mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
}
addChild(mTabContainer);
}
LLMultiFloater::LLMultiFloater(
const std::string& name,
const std::string& rect_control,
LLTabContainer::TabPosition tab_pos,
BOOL auto_resize) :
LLFloater(name, rect_control, name),
mTabContainer(NULL),
mTabPos(tab_pos),
mAutoResize(auto_resize),
mOrigMinWidth(0),
mOrigMinHeight(0)
{
mTabContainer = new LLTabContainer(std::string("Preview Tabs"),
LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - LLFLOATER_HEADER_SIZE, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0),
mTabPos,
FALSE,
FALSE);
mTabContainer->setFollowsAll();
if (isResizable() && mTabPos == LLTabContainer::BOTTOM)
{
mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
}
addChild(mTabContainer);
}
// virtual
LLXMLNodePtr LLMultiFloater::getXML(bool save_children) const
{
LLXMLNodePtr node = LLFloater::getXML();
node->setName(LL_MULTI_FLOATER_TAG);
return node;
}
void LLMultiFloater::open() /* Flawfinder: ignore */
{
if (mTabContainer->getTabCount() > 0)
{
LLFloater::open(); /* Flawfinder: ignore */
}
else
{
// for now, don't allow multifloaters
// without any child floaters
close();
}
}
void LLMultiFloater::onClose(bool app_quitting)
{
if(closeAllFloaters() == TRUE)
{
LLFloater::onClose(app_quitting);
}//else not all tabs could be closed...
}
void LLMultiFloater::draw()
{
if (mTabContainer->getTabCount() == 0)
{
//RN: could this potentially crash in draw hierarchy?
close();
}
else
{
for (S32 i = 0; i < mTabContainer->getTabCount(); i++)
{
LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(i);
if (floaterp->getShortTitle() != mTabContainer->getPanelTitle(i))
{
mTabContainer->setPanelTitle(i, floaterp->getShortTitle());
}
}
LLFloater::draw();
}
}
BOOL LLMultiFloater::closeAllFloaters()
{
S32 tabToClose = 0;
S32 lastTabCount = mTabContainer->getTabCount();
while (tabToClose < mTabContainer->getTabCount())
{
LLFloater* first_floater = (LLFloater*)mTabContainer->getPanelByIndex(tabToClose);
first_floater->close();
if(lastTabCount == mTabContainer->getTabCount())
{
//Tab did not actually close, possibly due to a pending Save Confirmation dialog..
//so try and close the next one in the list...
tabToClose++;
}else
{
//Tab closed ok.
lastTabCount = mTabContainer->getTabCount();
}
}
if( mTabContainer->getTabCount() != 0 )
return FALSE; // Couldn't close all the tabs (pending save dialog?) so return FALSE.
return TRUE; //else all tabs were successfully closed...
}
void LLMultiFloater::growToFit(S32 content_width, S32 content_height)
{
S32 new_width = llmax(getRect().getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2);
S32 new_height = llmax(getRect().getHeight(), content_height + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
if (isMinimized())
{
LLRect newrect;
newrect.setLeftTopAndSize(getExpandedRect().mLeft, getExpandedRect().mTop, new_width, new_height);
setExpandedRect(newrect);
}
else
{
S32 old_height = getRect().getHeight();
reshape(new_width, new_height);
// keep top left corner in same position
translate(0, old_height - new_height);
}
}
/**
void addFloater(LLFloater* floaterp, BOOL select_added_floater)
Adds the LLFloater pointed to by floaterp to this.
If floaterp is already hosted by this, then it is re-added to get
new titles, etc.
If select_added_floater is true, the LLFloater pointed to by floaterp will
become the selected tab in this
Affects: mTabContainer, floaterp
**/
void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point)
{
if (!floaterp)
{
return;
}
if (!mTabContainer)
{
llerrs << "Tab Container used without having been initialized." << llendl;
return;
}
if (floaterp->getHost() == this)
{
// already hosted by me, remove
// do this so we get updated title, etc.
mFloaterDataMap.erase(floaterp->getHandle());
mTabContainer->removeTabPanel(floaterp);
}
else if (floaterp->getHost())
{
// floaterp is hosted by somebody else and
// this is adding it, so remove it from it's old host
floaterp->getHost()->removeFloater(floaterp);
}
else if (floaterp->getParent() == gFloaterView)
{
// rehost preview floater as child panel
gFloaterView->removeChild(floaterp);
}
// store original configuration
LLFloaterData floater_data;
floater_data.mWidth = floaterp->getRect().getWidth();
floater_data.mHeight = floaterp->getRect().getHeight();
floater_data.mCanMinimize = floaterp->isMinimizeable();
floater_data.mCanResize = floaterp->isResizable();
// remove minimize and close buttons
floaterp->setCanMinimize(FALSE);
floaterp->setCanResize(FALSE);
floaterp->setCanDrag(FALSE);
floaterp->storeRectControl();
// avoid double rendering of floater background (makes it more opaque)
floaterp->setBackgroundVisible(FALSE);
if (mAutoResize)
{
growToFit(floater_data.mWidth, floater_data.mHeight);
}
//add the panel, add it to proper maps
mTabContainer->addTabPanel(floaterp, floaterp->getShortTitle(), FALSE, onTabSelected, this, 0, FALSE, insertion_point);
mFloaterDataMap[floaterp->getHandle()] = floater_data;
updateResizeLimits();
if ( select_added_floater )
{
mTabContainer->selectTabPanel(floaterp);
}
else
{
// reassert visible tab (hiding new floater if necessary)
mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex());
}
floaterp->setHost(this);
if (isMinimized())
{
floaterp->setVisible(FALSE);
}
}
/**
BOOL selectFloater(LLFloater* floaterp)
If the LLFloater pointed to by floaterp is hosted by this,
then its tab is selected and returns true. Otherwise returns false.
Affects: mTabContainer
**/
BOOL LLMultiFloater::selectFloater(LLFloater* floaterp)
{
return mTabContainer->selectTabPanel(floaterp);
}
// virtual
void LLMultiFloater::selectNextFloater()
{
mTabContainer->selectNextTab();
}
// virtual
void LLMultiFloater::selectPrevFloater()
{
mTabContainer->selectPrevTab();
}
void LLMultiFloater::showFloater(LLFloater* floaterp)
{
// we won't select a panel that already is selected
// it is hard to do this internally to tab container
// as tab selection is handled via index and the tab at a given
// index might have changed
if (floaterp != mTabContainer->getCurrentPanel() &&
!mTabContainer->selectTabPanel(floaterp))
{
addFloater(floaterp, TRUE);
}
}
void LLMultiFloater::removeFloater(LLFloater* floaterp)
{
if (!floaterp || floaterp->getHost() != this )
return;
floater_data_map_t::iterator found_data_it = mFloaterDataMap.find(floaterp->getHandle());
if (found_data_it != mFloaterDataMap.end())
{
LLFloaterData& floater_data = found_data_it->second;
floaterp->setCanMinimize(floater_data.mCanMinimize);
if (!floater_data.mCanResize)
{
// restore original size
floaterp->reshape(floater_data.mWidth, floater_data.mHeight);
}
floaterp->setCanResize(floater_data.mCanResize);
mFloaterDataMap.erase(found_data_it);
}
mTabContainer->removeTabPanel(floaterp);
floaterp->setBackgroundVisible(TRUE);
floaterp->setCanDrag(TRUE);
floaterp->setHost(NULL);
floaterp->applyRectControl();
updateResizeLimits();
tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false);
}
void LLMultiFloater::tabOpen(LLFloater* opened_floater, bool from_click)
{
// default implementation does nothing
}
void LLMultiFloater::tabClose()
{
if (mTabContainer->getTabCount() == 0)
{
// no more children, close myself
close();
}
}
void LLMultiFloater::setVisible(BOOL visible)
{
// *FIX: shouldn't have to do this, fix adding to minimized multifloater
LLFloater::setVisible(visible);
if (mTabContainer)
{
LLPanel* cur_floaterp = mTabContainer->getCurrentPanel();
if (cur_floaterp)
{
cur_floaterp->setVisible(visible);
}
// if no tab selected, and we're being shown,
// select last tab to be added
if (visible && !cur_floaterp)
{
mTabContainer->selectLastTab();
}
}
}
BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask)
{
if (key == 'W' && mask == MASK_CONTROL)
{
LLFloater* floater = getActiveFloater();
// is user closeable and is system closeable
if (floater && floater->canClose() && floater->isCloseable())
{
floater->close();
}
return TRUE;
}
return LLFloater::handleKeyHere(key, mask);
}
LLFloater* LLMultiFloater::getActiveFloater()
{
return (LLFloater*)mTabContainer->getCurrentPanel();
}
S32 LLMultiFloater::getFloaterCount()
{
return mTabContainer->getTabCount();
}
/**
BOOL isFloaterFlashing(LLFloater* floaterp)
Returns true if the LLFloater pointed to by floaterp
is currently in a flashing state and is hosted by this.
False otherwise.
Requires: floaterp != NULL
**/
BOOL LLMultiFloater::isFloaterFlashing(LLFloater* floaterp)
{
if ( floaterp && floaterp->getHost() == this )
return mTabContainer->getTabPanelFlashing(floaterp);
return FALSE;
}
/**
BOOL setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
Sets the current flashing state of the LLFloater pointed
to by floaterp to be the BOOL flashing if the LLFloater pointed
to by floaterp is hosted by this.
Requires: floaterp != NULL
**/
void LLMultiFloater::setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
{
if ( floaterp && floaterp->getHost() == this )
mTabContainer->setTabPanelFlashing(floaterp, flashing);
}
//static
void LLMultiFloater::onTabSelected(void* userdata, bool from_click)
{
LLMultiFloater* floaterp = (LLMultiFloater*)userdata;
floaterp->tabOpen((LLFloater*)floaterp->mTabContainer->getCurrentPanel(), from_click);
}
void LLMultiFloater::setCanResize(BOOL can_resize)
{
LLFloater::setCanResize(can_resize);
if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM)
{
mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
}
else
{
mTabContainer->setRightTabBtnOffset(0);
}
}
BOOL LLMultiFloater::postBuild()
{
// remember any original xml minimum size
getResizeLimits(&mOrigMinWidth, &mOrigMinHeight);
if (mTabContainer)
{
return TRUE;
}
requires<LLTabContainer>("Preview Tabs");
if (checkRequirements())
{
mTabContainer = getChild<LLTabContainer>("Preview Tabs");
return TRUE;
}
return FALSE;
}
void LLMultiFloater::updateResizeLimits()
{
// initialize minimum size constraint to the original xml values.
S32 new_min_width = mOrigMinWidth;
S32 new_min_height = mOrigMinHeight;
// possibly increase minimum size constraint due to children's minimums.
for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
{
LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
if (floaterp)
{
new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
new_min_height = llmax(new_min_height, floaterp->getMinHeight() + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
}
}
setResizeLimits(new_min_width, new_min_height);
S32 cur_height = getRect().getHeight();
S32 new_width = llmax(getRect().getWidth(), new_min_width);
S32 new_height = llmax(getRect().getHeight(), new_min_height);
if (isMinimized())
{
const LLRect& expanded = getExpandedRect();
LLRect newrect;
newrect.setLeftTopAndSize(expanded.mLeft, expanded.mTop, llmax(expanded.getWidth(), new_width), llmax(expanded.getHeight(), new_height));
setExpandedRect(newrect);
}
else
{
reshape(new_width, new_height);
// make sure upper left corner doesn't move
translate(0, cur_height - getRect().getHeight());
// make sure this window is visible on screen when it has been modified
// (tab added, etc)
gFloaterView->adjustToFitScreen(this, TRUE);
}
}

103
indra/llui/llmultifloater.h Normal file
View File

@@ -0,0 +1,103 @@
/**
* @file llmultifloater.h
* @brief LLFloater that hosts other floaters
*
* $LicenseInfo:firstyear=2002&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$
*/
// Floating "windows" within the GL display, like the inventory floater,
// mini-map floater, etc.
#ifndef LL_MULTI_FLOATER_H
#define LL_MULTI_FLOATER_H
#include "llfloater.h"
#include "lltabcontainer.h" // for LLTabContainer::eInsertionPoint
// https://wiki.lindenlab.com/mediawiki/index.php?title=LLMultiFloater&oldid=81376
class LLMultiFloater : public LLFloater
{
public:
LLMultiFloater();
LLMultiFloater(LLTabContainer::TabPosition tab_pos);
LLMultiFloater(const std::string& name);
LLMultiFloater(const std::string& name, const LLRect& rect, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE);
LLMultiFloater(const std::string& name, const std::string& rect_control, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE);
virtual ~LLMultiFloater() {};
virtual BOOL postBuild();
virtual LLXMLNodePtr getXML(bool save_children = true) const;
/*virtual*/ void open(); /* Flawfinder: ignore */
/*virtual*/ void onClose(bool app_quitting);
/*virtual*/ void draw();
/*virtual*/ void setVisible(BOOL visible);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
virtual void setCanResize(BOOL can_resize);
virtual void growToFit(S32 content_width, S32 content_height);
virtual void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END);
virtual void showFloater(LLFloater* floaterp);
virtual void removeFloater(LLFloater* floaterp);
virtual void tabOpen(LLFloater* opened_floater, bool from_click);
virtual void tabClose();
virtual BOOL selectFloater(LLFloater* floaterp);
virtual void selectNextFloater();
virtual void selectPrevFloater();
virtual LLFloater* getActiveFloater();
virtual BOOL isFloaterFlashing(LLFloater* floaterp);
virtual S32 getFloaterCount();
virtual void setFloaterFlashing(LLFloater* floaterp, BOOL flashing);
virtual BOOL closeAllFloaters(); //Returns FALSE if the floater could not be closed due to pending confirmation dialogs
void setTabContainer(LLTabContainer* tab_container) { if (!mTabContainer) mTabContainer = tab_container; }
static void onTabSelected(void* userdata, bool);
virtual void updateResizeLimits();
protected:
struct LLFloaterData
{
S32 mWidth;
S32 mHeight;
BOOL mCanMinimize;
BOOL mCanResize;
};
LLTabContainer* mTabContainer;
typedef std::map<LLHandle<LLFloater>, LLFloaterData> floater_data_map_t;
floater_data_map_t mFloaterDataMap;
LLTabContainer::TabPosition mTabPos;
BOOL mAutoResize;
S32 mOrigMinWidth, mOrigMinHeight; // logically const but initialized late
};
#endif // LL_MULTI_FLOATER_H

View File

@@ -40,7 +40,7 @@
#include "llfocusmgr.h"
#include "llkeyboard.h" // for the MASK constants
#include "llcontrol.h"
#include "llimagegl.h"
#include "lluiimage.h"
#include <sstream>

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