summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llcharacter/llanimationstates.cpp278
-rw-r--r--indra/llcommon/llavatarconstants.h8
-rw-r--r--indra/llcommon/lllslconstants.h2
-rw-r--r--indra/llcommon/llmemory.cpp1649
-rw-r--r--indra/llcommon/llmemory.h283
-rw-r--r--indra/llcommon/llmetricperformancetester.h2
-rw-r--r--indra/llcommon/llsys.cpp8
-rw-r--r--indra/llcommon/llsys.h2
-rw-r--r--indra/llcommon/llversionviewer.h2
-rw-r--r--indra/llimage/llimage.cpp70
-rw-r--r--indra/llimage/llimage.h15
-rw-r--r--indra/llimage/llimagedxt.cpp2
-rw-r--r--indra/llimage/llimagej2c.cpp4
-rw-r--r--indra/llmath/llcamera.cpp1
-rw-r--r--indra/llmath/llcamera.h9
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp5
-rw-r--r--indra/llplugin/llpluginclassmedia.h1
-rw-r--r--indra/llplugin/llplugininstance.cpp20
-rw-r--r--indra/llplugin/llplugininstance.h2
-rw-r--r--indra/llplugin/llpluginprocesschild.cpp3
-rw-r--r--indra/llplugin/llpluginprocesschild.h1
-rw-r--r--indra/llplugin/llpluginprocessparent.cpp4
-rw-r--r--indra/llplugin/llpluginprocessparent.h2
-rw-r--r--indra/llrender/llvertexbuffer.cpp110
-rw-r--r--indra/llrender/llvertexbuffer.h15
-rw-r--r--indra/llxml/llcontrol.h3
-rw-r--r--indra/newview/app_settings/settings.xml44
-rw-r--r--indra/newview/llappviewer.cpp129
-rw-r--r--indra/newview/llappviewer.h8
-rw-r--r--indra/newview/llchathistory.cpp19
-rw-r--r--indra/newview/llcolorswatch.cpp4
-rw-r--r--indra/newview/lldynamictexture.cpp3
-rw-r--r--indra/newview/llfloatermemleak.cpp5
-rw-r--r--indra/newview/llimview.cpp9
-rw-r--r--indra/newview/llnamelistctrl.cpp24
-rw-r--r--indra/newview/lltexturecache.cpp30
-rw-r--r--indra/newview/lltexturefetch.cpp14
-rw-r--r--indra/newview/lltoastnotifypanel.cpp10
-rw-r--r--indra/newview/llviewercontrol.cpp10
-rw-r--r--indra/newview/llviewerdisplay.cpp7
-rw-r--r--indra/newview/llviewermedia.cpp5
-rw-r--r--indra/newview/llviewerobject.cpp15
-rw-r--r--indra/newview/llviewerobjectlist.cpp21
-rw-r--r--indra/newview/llviewerobjectlist.h1
-rw-r--r--indra/newview/llviewertexture.cpp12
-rw-r--r--indra/newview/llviewertexture.h2
-rw-r--r--indra/newview/llviewerwindow.cpp26
-rw-r--r--indra/newview/llvoavatar.cpp16
-rw-r--r--indra/newview/llvosky.cpp35
-rw-r--r--indra/newview/llvosky.h44
-rw-r--r--indra/newview/llworld.cpp2
-rw-r--r--indra/newview/pipeline.cpp40
-rw-r--r--indra/newview/pipeline.h6
-rw-r--r--indra/newview/skins/default/xui/en/floater_about_land.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml22
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml14
-rw-r--r--indra/test_apps/llplugintest/llmediaplugintest.cpp4
57 files changed, 2722 insertions, 364 deletions
diff --git a/indra/llcharacter/llanimationstates.cpp b/indra/llcharacter/llanimationstates.cpp
index a30113a478..155226cf17 100644
--- a/indra/llcharacter/llanimationstates.cpp
+++ b/indra/llcharacter/llanimationstates.cpp
@@ -33,145 +33,145 @@
#include "llanimationstates.h"
#include "llstring.h"
-const LLUUID ANIM_AGENT_AFRAID = LLUUID("6b61c8e8-4747-0d75-12d7-e49ff207a4ca");
-const LLUUID ANIM_AGENT_AIM_BAZOOKA_R = LLUUID("b5b4a67d-0aee-30d2-72cd-77b333e932ef");
-const LLUUID ANIM_AGENT_AIM_BOW_L = LLUUID("46bb4359-de38-4ed8-6a22-f1f52fe8f506");
-const LLUUID ANIM_AGENT_AIM_HANDGUN_R = LLUUID("3147d815-6338-b932-f011-16b56d9ac18b");
-const LLUUID ANIM_AGENT_AIM_RIFLE_R = LLUUID("ea633413-8006-180a-c3ba-96dd1d756720");
-const LLUUID ANIM_AGENT_ANGRY = LLUUID("5747a48e-073e-c331-f6f3-7c2149613d3e");
-const LLUUID ANIM_AGENT_AWAY = LLUUID("fd037134-85d4-f241-72c6-4f42164fedee");
-const LLUUID ANIM_AGENT_BACKFLIP = LLUUID("c4ca6188-9127-4f31-0158-23c4e2f93304");
-const LLUUID ANIM_AGENT_BELLY_LAUGH = LLUUID("18b3a4b5-b463-bd48-e4b6-71eaac76c515");
-const LLUUID ANIM_AGENT_BLOW_KISS = LLUUID("db84829b-462c-ee83-1e27-9bbee66bd624");
-const LLUUID ANIM_AGENT_BORED = LLUUID("b906c4ba-703b-1940-32a3-0c7f7d791510");
-const LLUUID ANIM_AGENT_BOW = LLUUID("82e99230-c906-1403-4d9c-3889dd98daba");
-const LLUUID ANIM_AGENT_BRUSH = LLUUID("349a3801-54f9-bf2c-3bd0-1ac89772af01");
-const LLUUID ANIM_AGENT_BUSY = LLUUID("efcf670c-2d18-8128-973a-034ebc806b67");
-const LLUUID ANIM_AGENT_CLAP = LLUUID("9b0c1c4e-8ac7-7969-1494-28c874c4f668");
-const LLUUID ANIM_AGENT_COURTBOW = LLUUID("9ba1c942-08be-e43a-fb29-16ad440efc50");
-const LLUUID ANIM_AGENT_CROUCH = LLUUID("201f3fdf-cb1f-dbec-201f-7333e328ae7c");
-const LLUUID ANIM_AGENT_CROUCHWALK = LLUUID("47f5f6fb-22e5-ae44-f871-73aaaf4a6022");
-const LLUUID ANIM_AGENT_CRY = LLUUID("92624d3e-1068-f1aa-a5ec-8244585193ed");
-const LLUUID ANIM_AGENT_CUSTOMIZE = LLUUID("038fcec9-5ebd-8a8e-0e2e-6e71a0a1ac53");
-const LLUUID ANIM_AGENT_CUSTOMIZE_DONE = LLUUID("6883a61a-b27b-5914-a61e-dda118a9ee2c");
-const LLUUID ANIM_AGENT_DANCE1 = LLUUID("b68a3d7c-de9e-fc87-eec8-543d787e5b0d");
-const LLUUID ANIM_AGENT_DANCE2 = LLUUID("928cae18-e31d-76fd-9cc9-2f55160ff818");
-const LLUUID ANIM_AGENT_DANCE3 = LLUUID("30047778-10ea-1af7-6881-4db7a3a5a114");
-const LLUUID ANIM_AGENT_DANCE4 = LLUUID("951469f4-c7b2-c818-9dee-ad7eea8c30b7");
-const LLUUID ANIM_AGENT_DANCE5 = LLUUID("4bd69a1d-1114-a0b4-625f-84e0a5237155");
-const LLUUID ANIM_AGENT_DANCE6 = LLUUID("cd28b69b-9c95-bb78-3f94-8d605ff1bb12");
-const LLUUID ANIM_AGENT_DANCE7 = LLUUID("a54d8ee2-28bb-80a9-7f0c-7afbbe24a5d6");
-const LLUUID ANIM_AGENT_DANCE8 = LLUUID("b0dc417c-1f11-af36-2e80-7e7489fa7cdc");
-const LLUUID ANIM_AGENT_DEAD = LLUUID("57abaae6-1d17-7b1b-5f98-6d11a6411276");
-const LLUUID ANIM_AGENT_DRINK = LLUUID("0f86e355-dd31-a61c-fdb0-3a96b9aad05f");
-const LLUUID ANIM_AGENT_EMBARRASSED = LLUUID("514af488-9051-044a-b3fc-d4dbf76377c6");
-const LLUUID ANIM_AGENT_EXPRESS_AFRAID = LLUUID("aa2df84d-cf8f-7218-527b-424a52de766e");
-const LLUUID ANIM_AGENT_EXPRESS_ANGER = LLUUID("1a03b575-9634-b62a-5767-3a679e81f4de");
-const LLUUID ANIM_AGENT_EXPRESS_BORED = LLUUID("214aa6c1-ba6a-4578-f27c-ce7688f61d0d");
-const LLUUID ANIM_AGENT_EXPRESS_CRY = LLUUID("d535471b-85bf-3b4d-a542-93bea4f59d33");
-const LLUUID ANIM_AGENT_EXPRESS_DISDAIN = LLUUID("d4416ff1-09d3-300f-4183-1b68a19b9fc1");
-const LLUUID ANIM_AGENT_EXPRESS_EMBARRASSED = LLUUID("0b8c8211-d78c-33e8-fa28-c51a9594e424");
-const LLUUID ANIM_AGENT_EXPRESS_FROWN = LLUUID("fee3df48-fa3d-1015-1e26-a205810e3001");
-const LLUUID ANIM_AGENT_EXPRESS_KISS = LLUUID("1e8d90cc-a84e-e135-884c-7c82c8b03a14");
-const LLUUID ANIM_AGENT_EXPRESS_LAUGH = LLUUID("62570842-0950-96f8-341c-809e65110823");
-const LLUUID ANIM_AGENT_EXPRESS_OPEN_MOUTH = LLUUID("d63bc1f9-fc81-9625-a0c6-007176d82eb7");
-const LLUUID ANIM_AGENT_EXPRESS_REPULSED = LLUUID("f76cda94-41d4-a229-2872-e0296e58afe1");
-const LLUUID ANIM_AGENT_EXPRESS_SAD = LLUUID("eb6ebfb2-a4b3-a19c-d388-4dd5c03823f7");
-const LLUUID ANIM_AGENT_EXPRESS_SHRUG = LLUUID("a351b1bc-cc94-aac2-7bea-a7e6ebad15ef");
-const LLUUID ANIM_AGENT_EXPRESS_SMILE = LLUUID("b7c7c833-e3d3-c4e3-9fc0-131237446312");
-const LLUUID ANIM_AGENT_EXPRESS_SURPRISE = LLUUID("728646d9-cc79-08b2-32d6-937f0a835c24");
-const LLUUID ANIM_AGENT_EXPRESS_TONGUE_OUT = LLUUID("835965c6-7f2f-bda2-5deb-2478737f91bf");
-const LLUUID ANIM_AGENT_EXPRESS_TOOTHSMILE = LLUUID("b92ec1a5-e7ce-a76b-2b05-bcdb9311417e");
-const LLUUID ANIM_AGENT_EXPRESS_WINK = LLUUID("da020525-4d94-59d6-23d7-81fdebf33148");
-const LLUUID ANIM_AGENT_EXPRESS_WORRY = LLUUID("9c05e5c7-6f07-6ca4-ed5a-b230390c3950");
-const LLUUID ANIM_AGENT_FALLDOWN = LLUUID("666307d9-a860-572d-6fd4-c3ab8865c094");
-const LLUUID ANIM_AGENT_FEMALE_RUN_NEW = LLUUID("85995026-eade-5d78-d364-94a64512cb66");
-const LLUUID ANIM_AGENT_FEMALE_WALK = LLUUID("f5fc7433-043d-e819-8298-f519a119b688");
-const LLUUID ANIM_AGENT_FEMALE_WALK_NEW = LLUUID("d60c41d2-7c24-7074-d3fa-6101cea22a51");
-const LLUUID ANIM_AGENT_FINGER_WAG = LLUUID("c1bc7f36-3ba0-d844-f93c-93be945d644f");
-const LLUUID ANIM_AGENT_FIST_PUMP = LLUUID("7db00ccd-f380-f3ee-439d-61968ec69c8a");
-const LLUUID ANIM_AGENT_FLY = LLUUID("aec4610c-757f-bc4e-c092-c6e9caf18daf");
-const LLUUID ANIM_AGENT_FLYSLOW = LLUUID("2b5a38b2-5e00-3a97-a495-4c826bc443e6");
-const LLUUID ANIM_AGENT_HELLO = LLUUID("9b29cd61-c45b-5689-ded2-91756b8d76a9");
-const LLUUID ANIM_AGENT_HOLD_BAZOOKA_R = LLUUID("ef62d355-c815-4816-2474-b1acc21094a6");
-const LLUUID ANIM_AGENT_HOLD_BOW_L = LLUUID("8b102617-bcba-037b-86c1-b76219f90c88");
-const LLUUID ANIM_AGENT_HOLD_HANDGUN_R = LLUUID("efdc1727-8b8a-c800-4077-975fc27ee2f2");
-const LLUUID ANIM_AGENT_HOLD_RIFLE_R = LLUUID("3d94bad0-c55b-7dcc-8763-033c59405d33");
-const LLUUID ANIM_AGENT_HOLD_THROW_R = LLUUID("7570c7b5-1f22-56dd-56ef-a9168241bbb6");
-const LLUUID ANIM_AGENT_HOVER = LLUUID("4ae8016b-31b9-03bb-c401-b1ea941db41d");
-const LLUUID ANIM_AGENT_HOVER_DOWN = LLUUID("20f063ea-8306-2562-0b07-5c853b37b31e");
-const LLUUID ANIM_AGENT_HOVER_UP = LLUUID("62c5de58-cb33-5743-3d07-9e4cd4352864");
-const LLUUID ANIM_AGENT_IMPATIENT = LLUUID("5ea3991f-c293-392e-6860-91dfa01278a3");
-const LLUUID ANIM_AGENT_JUMP = LLUUID("2305bd75-1ca9-b03b-1faa-b176b8a8c49e");
-const LLUUID ANIM_AGENT_JUMP_FOR_JOY = LLUUID("709ea28e-1573-c023-8bf8-520c8bc637fa");
-const LLUUID ANIM_AGENT_KISS_MY_BUTT = LLUUID("19999406-3a3a-d58c-a2ac-d72e555dcf51");
-const LLUUID ANIM_AGENT_LAND = LLUUID("7a17b059-12b2-41b1-570a-186368b6aa6f");
-const LLUUID ANIM_AGENT_LAUGH_SHORT = LLUUID("ca5b3f14-3194-7a2b-c894-aa699b718d1f");
-const LLUUID ANIM_AGENT_MEDIUM_LAND = LLUUID("f4f00d6e-b9fe-9292-f4cb-0ae06ea58d57");
-const LLUUID ANIM_AGENT_MOTORCYCLE_SIT = LLUUID("08464f78-3a8e-2944-cba5-0c94aff3af29");
-const LLUUID ANIM_AGENT_MUSCLE_BEACH = LLUUID("315c3a41-a5f3-0ba4-27da-f893f769e69b");
-const LLUUID ANIM_AGENT_NO = LLUUID("5a977ed9-7f72-44e9-4c4c-6e913df8ae74");
-const LLUUID ANIM_AGENT_NO_UNHAPPY = LLUUID("d83fa0e5-97ed-7eb2-e798-7bd006215cb4");
-const LLUUID ANIM_AGENT_NYAH_NYAH = LLUUID("f061723d-0a18-754f-66ee-29a44795a32f");
-const LLUUID ANIM_AGENT_ONETWO_PUNCH = LLUUID("eefc79be-daae-a239-8c04-890f5d23654a");
-const LLUUID ANIM_AGENT_PEACE = LLUUID("b312b10e-65ab-a0a4-8b3c-1326ea8e3ed9");
-const LLUUID ANIM_AGENT_POINT_ME = LLUUID("17c024cc-eef2-f6a0-3527-9869876d7752");
-const LLUUID ANIM_AGENT_POINT_YOU = LLUUID("ec952cca-61ef-aa3b-2789-4d1344f016de");
-const LLUUID ANIM_AGENT_PRE_JUMP = LLUUID("7a4e87fe-de39-6fcb-6223-024b00893244");
-const LLUUID ANIM_AGENT_PUNCH_LEFT = LLUUID("f3300ad9-3462-1d07-2044-0fef80062da0");
-const LLUUID ANIM_AGENT_PUNCH_RIGHT = LLUUID("c8e42d32-7310-6906-c903-cab5d4a34656");
-const LLUUID ANIM_AGENT_REPULSED = LLUUID("36f81a92-f076-5893-dc4b-7c3795e487cf");
-const LLUUID ANIM_AGENT_ROUNDHOUSE_KICK = LLUUID("49aea43b-5ac3-8a44-b595-96100af0beda");
-const LLUUID ANIM_AGENT_RPS_COUNTDOWN = LLUUID("35db4f7e-28c2-6679-cea9-3ee108f7fc7f");
-const LLUUID ANIM_AGENT_RPS_PAPER = LLUUID("0836b67f-7f7b-f37b-c00a-460dc1521f5a");
-const LLUUID ANIM_AGENT_RPS_ROCK = LLUUID("42dd95d5-0bc6-6392-f650-777304946c0f");
-const LLUUID ANIM_AGENT_RPS_SCISSORS = LLUUID("16803a9f-5140-e042-4d7b-d28ba247c325");
-const LLUUID ANIM_AGENT_RUN = LLUUID("05ddbff8-aaa9-92a1-2b74-8fe77a29b445");
-const LLUUID ANIM_AGENT_RUN_NEW = LLUUID("1ab1b236-cd08-21e6-0cbc-0d923fc6eca2");
-const LLUUID ANIM_AGENT_SAD = LLUUID("0eb702e2-cc5a-9a88-56a5-661a55c0676a");
-const LLUUID ANIM_AGENT_SALUTE = LLUUID("cd7668a6-7011-d7e2-ead8-fc69eff1a104");
-const LLUUID ANIM_AGENT_SHOOT_BOW_L = LLUUID("e04d450d-fdb5-0432-fd68-818aaf5935f8");
-const LLUUID ANIM_AGENT_SHOUT = LLUUID("6bd01860-4ebd-127a-bb3d-d1427e8e0c42");
-const LLUUID ANIM_AGENT_SHRUG = LLUUID("70ea714f-3a97-d742-1b01-590a8fcd1db5");
-const LLUUID ANIM_AGENT_SIT = LLUUID("1a5fe8ac-a804-8a5d-7cbd-56bd83184568");
-const LLUUID ANIM_AGENT_SIT_FEMALE = LLUUID("b1709c8d-ecd3-54a1-4f28-d55ac0840782");
-const LLUUID ANIM_AGENT_SIT_GENERIC = LLUUID("245f3c54-f1c0-bf2e-811f-46d8eeb386e7");
-const LLUUID ANIM_AGENT_SIT_GROUND = LLUUID("1c7600d6-661f-b87b-efe2-d7421eb93c86");
-const LLUUID ANIM_AGENT_SIT_GROUND_CONSTRAINED = LLUUID("1a2bd58e-87ff-0df8-0b4c-53e047b0bb6e");
-const LLUUID ANIM_AGENT_SIT_TO_STAND = LLUUID("a8dee56f-2eae-9e7a-05a2-6fb92b97e21e");
-const LLUUID ANIM_AGENT_SLEEP = LLUUID("f2bed5f9-9d44-39af-b0cd-257b2a17fe40");
-const LLUUID ANIM_AGENT_SMOKE_IDLE = LLUUID("d2f2ee58-8ad1-06c9-d8d3-3827ba31567a");
-const LLUUID ANIM_AGENT_SMOKE_INHALE = LLUUID("6802d553-49da-0778-9f85-1599a2266526");
-const LLUUID ANIM_AGENT_SMOKE_THROW_DOWN = LLUUID("0a9fb970-8b44-9114-d3a9-bf69cfe804d6");
-const LLUUID ANIM_AGENT_SNAPSHOT = LLUUID("eae8905b-271a-99e2-4c0e-31106afd100c");
-const LLUUID ANIM_AGENT_STAND = LLUUID("2408fe9e-df1d-1d7d-f4ff-1384fa7b350f");
-const LLUUID ANIM_AGENT_STANDUP = LLUUID("3da1d753-028a-5446-24f3-9c9b856d9422");
-const LLUUID ANIM_AGENT_STAND_1 = LLUUID("15468e00-3400-bb66-cecc-646d7c14458e");
-const LLUUID ANIM_AGENT_STAND_2 = LLUUID("370f3a20-6ca6-9971-848c-9a01bc42ae3c");
-const LLUUID ANIM_AGENT_STAND_3 = LLUUID("42b46214-4b44-79ae-deb8-0df61424ff4b");
-const LLUUID ANIM_AGENT_STAND_4 = LLUUID("f22fed8b-a5ed-2c93-64d5-bdd8b93c889f");
-const LLUUID ANIM_AGENT_STRETCH = LLUUID("80700431-74ec-a008-14f8-77575e73693f");
-const LLUUID ANIM_AGENT_STRIDE = LLUUID("1cb562b0-ba21-2202-efb3-30f82cdf9595");
-const LLUUID ANIM_AGENT_SURF = LLUUID("41426836-7437-7e89-025d-0aa4d10f1d69");
-const LLUUID ANIM_AGENT_SURPRISE = LLUUID("313b9881-4302-73c0-c7d0-0e7a36b6c224");
-const LLUUID ANIM_AGENT_SWORD_STRIKE = LLUUID("85428680-6bf9-3e64-b489-6f81087c24bd");
-const LLUUID ANIM_AGENT_TALK = LLUUID("5c682a95-6da4-a463-0bf6-0f5b7be129d1");
-const LLUUID ANIM_AGENT_TANTRUM = LLUUID("11000694-3f41-adc2-606b-eee1d66f3724");
-const LLUUID ANIM_AGENT_THROW_R = LLUUID("aa134404-7dac-7aca-2cba-435f9db875ca");
-const LLUUID ANIM_AGENT_TRYON_SHIRT = LLUUID("83ff59fe-2346-f236-9009-4e3608af64c1");
-const LLUUID ANIM_AGENT_TURNLEFT = LLUUID("56e0ba0d-4a9f-7f27-6117-32f2ebbf6135");
-const LLUUID ANIM_AGENT_TURNRIGHT = LLUUID("2d6daa51-3192-6794-8e2e-a15f8338ec30");
-const LLUUID ANIM_AGENT_TYPE = LLUUID("c541c47f-e0c0-058b-ad1a-d6ae3a4584d9");
-const LLUUID ANIM_AGENT_WALK = LLUUID("6ed24bd8-91aa-4b12-ccc7-c97c857ab4e0");
-const LLUUID ANIM_AGENT_WALK_NEW = LLUUID("33339176-7ddc-9397-94a4-bf3403cbc8f5");
-const LLUUID ANIM_AGENT_WHISPER = LLUUID("7693f268-06c7-ea71-fa21-2b30d6533f8f");
-const LLUUID ANIM_AGENT_WHISTLE = LLUUID("b1ed7982-c68e-a982-7561-52a88a5298c0");
-const LLUUID ANIM_AGENT_WINK = LLUUID("869ecdad-a44b-671e-3266-56aef2e3ac2e");
-const LLUUID ANIM_AGENT_WINK_HOLLYWOOD = LLUUID("c0c4030f-c02b-49de-24ba-2331f43fe41c");
-const LLUUID ANIM_AGENT_WORRY = LLUUID("9f496bd2-589a-709f-16cc-69bf7df1d36c");
-const LLUUID ANIM_AGENT_YES = LLUUID("15dd911d-be82-2856-26db-27659b142875");
-const LLUUID ANIM_AGENT_YES_HAPPY = LLUUID("b8c8b2a3-9008-1771-3bfc-90924955ab2d");
-const LLUUID ANIM_AGENT_YOGA_FLOAT = LLUUID("42ecd00b-9947-a97c-400a-bbc9174c7aeb");
+LLUUID const ANIM_AGENT_AFRAID ("6b61c8e8-4747-0d75-12d7-e49ff207a4ca");
+LLUUID const ANIM_AGENT_AIM_BAZOOKA_R ("b5b4a67d-0aee-30d2-72cd-77b333e932ef");
+LLUUID const ANIM_AGENT_AIM_BOW_L ("46bb4359-de38-4ed8-6a22-f1f52fe8f506");
+LLUUID const ANIM_AGENT_AIM_HANDGUN_R ("3147d815-6338-b932-f011-16b56d9ac18b");
+LLUUID const ANIM_AGENT_AIM_RIFLE_R ("ea633413-8006-180a-c3ba-96dd1d756720");
+LLUUID const ANIM_AGENT_ANGRY ("5747a48e-073e-c331-f6f3-7c2149613d3e");
+LLUUID const ANIM_AGENT_AWAY ("fd037134-85d4-f241-72c6-4f42164fedee");
+LLUUID const ANIM_AGENT_BACKFLIP ("c4ca6188-9127-4f31-0158-23c4e2f93304");
+LLUUID const ANIM_AGENT_BELLY_LAUGH ("18b3a4b5-b463-bd48-e4b6-71eaac76c515");
+LLUUID const ANIM_AGENT_BLOW_KISS ("db84829b-462c-ee83-1e27-9bbee66bd624");
+LLUUID const ANIM_AGENT_BORED ("b906c4ba-703b-1940-32a3-0c7f7d791510");
+LLUUID const ANIM_AGENT_BOW ("82e99230-c906-1403-4d9c-3889dd98daba");
+LLUUID const ANIM_AGENT_BRUSH ("349a3801-54f9-bf2c-3bd0-1ac89772af01");
+LLUUID const ANIM_AGENT_BUSY ("efcf670c-2d18-8128-973a-034ebc806b67");
+LLUUID const ANIM_AGENT_CLAP ("9b0c1c4e-8ac7-7969-1494-28c874c4f668");
+LLUUID const ANIM_AGENT_COURTBOW ("9ba1c942-08be-e43a-fb29-16ad440efc50");
+LLUUID const ANIM_AGENT_CROUCH ("201f3fdf-cb1f-dbec-201f-7333e328ae7c");
+LLUUID const ANIM_AGENT_CROUCHWALK ("47f5f6fb-22e5-ae44-f871-73aaaf4a6022");
+LLUUID const ANIM_AGENT_CRY ("92624d3e-1068-f1aa-a5ec-8244585193ed");
+LLUUID const ANIM_AGENT_CUSTOMIZE ("038fcec9-5ebd-8a8e-0e2e-6e71a0a1ac53");
+LLUUID const ANIM_AGENT_CUSTOMIZE_DONE ("6883a61a-b27b-5914-a61e-dda118a9ee2c");
+LLUUID const ANIM_AGENT_DANCE1 ("b68a3d7c-de9e-fc87-eec8-543d787e5b0d");
+LLUUID const ANIM_AGENT_DANCE2 ("928cae18-e31d-76fd-9cc9-2f55160ff818");
+LLUUID const ANIM_AGENT_DANCE3 ("30047778-10ea-1af7-6881-4db7a3a5a114");
+LLUUID const ANIM_AGENT_DANCE4 ("951469f4-c7b2-c818-9dee-ad7eea8c30b7");
+LLUUID const ANIM_AGENT_DANCE5 ("4bd69a1d-1114-a0b4-625f-84e0a5237155");
+LLUUID const ANIM_AGENT_DANCE6 ("cd28b69b-9c95-bb78-3f94-8d605ff1bb12");
+LLUUID const ANIM_AGENT_DANCE7 ("a54d8ee2-28bb-80a9-7f0c-7afbbe24a5d6");
+LLUUID const ANIM_AGENT_DANCE8 ("b0dc417c-1f11-af36-2e80-7e7489fa7cdc");
+LLUUID const ANIM_AGENT_DEAD ("57abaae6-1d17-7b1b-5f98-6d11a6411276");
+LLUUID const ANIM_AGENT_DRINK ("0f86e355-dd31-a61c-fdb0-3a96b9aad05f");
+LLUUID const ANIM_AGENT_EMBARRASSED ("514af488-9051-044a-b3fc-d4dbf76377c6");
+LLUUID const ANIM_AGENT_EXPRESS_AFRAID ("aa2df84d-cf8f-7218-527b-424a52de766e");
+LLUUID const ANIM_AGENT_EXPRESS_ANGER ("1a03b575-9634-b62a-5767-3a679e81f4de");
+LLUUID const ANIM_AGENT_EXPRESS_BORED ("214aa6c1-ba6a-4578-f27c-ce7688f61d0d");
+LLUUID const ANIM_AGENT_EXPRESS_CRY ("d535471b-85bf-3b4d-a542-93bea4f59d33");
+LLUUID const ANIM_AGENT_EXPRESS_DISDAIN ("d4416ff1-09d3-300f-4183-1b68a19b9fc1");
+LLUUID const ANIM_AGENT_EXPRESS_EMBARRASSED ("0b8c8211-d78c-33e8-fa28-c51a9594e424");
+LLUUID const ANIM_AGENT_EXPRESS_FROWN ("fee3df48-fa3d-1015-1e26-a205810e3001");
+LLUUID const ANIM_AGENT_EXPRESS_KISS ("1e8d90cc-a84e-e135-884c-7c82c8b03a14");
+LLUUID const ANIM_AGENT_EXPRESS_LAUGH ("62570842-0950-96f8-341c-809e65110823");
+LLUUID const ANIM_AGENT_EXPRESS_OPEN_MOUTH ("d63bc1f9-fc81-9625-a0c6-007176d82eb7");
+LLUUID const ANIM_AGENT_EXPRESS_REPULSED ("f76cda94-41d4-a229-2872-e0296e58afe1");
+LLUUID const ANIM_AGENT_EXPRESS_SAD ("eb6ebfb2-a4b3-a19c-d388-4dd5c03823f7");
+LLUUID const ANIM_AGENT_EXPRESS_SHRUG ("a351b1bc-cc94-aac2-7bea-a7e6ebad15ef");
+LLUUID const ANIM_AGENT_EXPRESS_SMILE ("b7c7c833-e3d3-c4e3-9fc0-131237446312");
+LLUUID const ANIM_AGENT_EXPRESS_SURPRISE ("728646d9-cc79-08b2-32d6-937f0a835c24");
+LLUUID const ANIM_AGENT_EXPRESS_TONGUE_OUT ("835965c6-7f2f-bda2-5deb-2478737f91bf");
+LLUUID const ANIM_AGENT_EXPRESS_TOOTHSMILE ("b92ec1a5-e7ce-a76b-2b05-bcdb9311417e");
+LLUUID const ANIM_AGENT_EXPRESS_WINK ("da020525-4d94-59d6-23d7-81fdebf33148");
+LLUUID const ANIM_AGENT_EXPRESS_WORRY ("9c05e5c7-6f07-6ca4-ed5a-b230390c3950");
+LLUUID const ANIM_AGENT_FALLDOWN ("666307d9-a860-572d-6fd4-c3ab8865c094");
+LLUUID const ANIM_AGENT_FEMALE_RUN_NEW ("85995026-eade-5d78-d364-94a64512cb66");
+LLUUID const ANIM_AGENT_FEMALE_WALK ("f5fc7433-043d-e819-8298-f519a119b688");
+LLUUID const ANIM_AGENT_FEMALE_WALK_NEW ("d60c41d2-7c24-7074-d3fa-6101cea22a51");
+LLUUID const ANIM_AGENT_FINGER_WAG ("c1bc7f36-3ba0-d844-f93c-93be945d644f");
+LLUUID const ANIM_AGENT_FIST_PUMP ("7db00ccd-f380-f3ee-439d-61968ec69c8a");
+LLUUID const ANIM_AGENT_FLY ("aec4610c-757f-bc4e-c092-c6e9caf18daf");
+LLUUID const ANIM_AGENT_FLYSLOW ("2b5a38b2-5e00-3a97-a495-4c826bc443e6");
+LLUUID const ANIM_AGENT_HELLO ("9b29cd61-c45b-5689-ded2-91756b8d76a9");
+LLUUID const ANIM_AGENT_HOLD_BAZOOKA_R ("ef62d355-c815-4816-2474-b1acc21094a6");
+LLUUID const ANIM_AGENT_HOLD_BOW_L ("8b102617-bcba-037b-86c1-b76219f90c88");
+LLUUID const ANIM_AGENT_HOLD_HANDGUN_R ("efdc1727-8b8a-c800-4077-975fc27ee2f2");
+LLUUID const ANIM_AGENT_HOLD_RIFLE_R ("3d94bad0-c55b-7dcc-8763-033c59405d33");
+LLUUID const ANIM_AGENT_HOLD_THROW_R ("7570c7b5-1f22-56dd-56ef-a9168241bbb6");
+LLUUID const ANIM_AGENT_HOVER ("4ae8016b-31b9-03bb-c401-b1ea941db41d");
+LLUUID const ANIM_AGENT_HOVER_DOWN ("20f063ea-8306-2562-0b07-5c853b37b31e");
+LLUUID const ANIM_AGENT_HOVER_UP ("62c5de58-cb33-5743-3d07-9e4cd4352864");
+LLUUID const ANIM_AGENT_IMPATIENT ("5ea3991f-c293-392e-6860-91dfa01278a3");
+LLUUID const ANIM_AGENT_JUMP ("2305bd75-1ca9-b03b-1faa-b176b8a8c49e");
+LLUUID const ANIM_AGENT_JUMP_FOR_JOY ("709ea28e-1573-c023-8bf8-520c8bc637fa");
+LLUUID const ANIM_AGENT_KISS_MY_BUTT ("19999406-3a3a-d58c-a2ac-d72e555dcf51");
+LLUUID const ANIM_AGENT_LAND ("7a17b059-12b2-41b1-570a-186368b6aa6f");
+LLUUID const ANIM_AGENT_LAUGH_SHORT ("ca5b3f14-3194-7a2b-c894-aa699b718d1f");
+LLUUID const ANIM_AGENT_MEDIUM_LAND ("f4f00d6e-b9fe-9292-f4cb-0ae06ea58d57");
+LLUUID const ANIM_AGENT_MOTORCYCLE_SIT ("08464f78-3a8e-2944-cba5-0c94aff3af29");
+LLUUID const ANIM_AGENT_MUSCLE_BEACH ("315c3a41-a5f3-0ba4-27da-f893f769e69b");
+LLUUID const ANIM_AGENT_NO ("5a977ed9-7f72-44e9-4c4c-6e913df8ae74");
+LLUUID const ANIM_AGENT_NO_UNHAPPY ("d83fa0e5-97ed-7eb2-e798-7bd006215cb4");
+LLUUID const ANIM_AGENT_NYAH_NYAH ("f061723d-0a18-754f-66ee-29a44795a32f");
+LLUUID const ANIM_AGENT_ONETWO_PUNCH ("eefc79be-daae-a239-8c04-890f5d23654a");
+LLUUID const ANIM_AGENT_PEACE ("b312b10e-65ab-a0a4-8b3c-1326ea8e3ed9");
+LLUUID const ANIM_AGENT_POINT_ME ("17c024cc-eef2-f6a0-3527-9869876d7752");
+LLUUID const ANIM_AGENT_POINT_YOU ("ec952cca-61ef-aa3b-2789-4d1344f016de");
+LLUUID const ANIM_AGENT_PRE_JUMP ("7a4e87fe-de39-6fcb-6223-024b00893244");
+LLUUID const ANIM_AGENT_PUNCH_LEFT ("f3300ad9-3462-1d07-2044-0fef80062da0");
+LLUUID const ANIM_AGENT_PUNCH_RIGHT ("c8e42d32-7310-6906-c903-cab5d4a34656");
+LLUUID const ANIM_AGENT_REPULSED ("36f81a92-f076-5893-dc4b-7c3795e487cf");
+LLUUID const ANIM_AGENT_ROUNDHOUSE_KICK ("49aea43b-5ac3-8a44-b595-96100af0beda");
+LLUUID const ANIM_AGENT_RPS_COUNTDOWN ("35db4f7e-28c2-6679-cea9-3ee108f7fc7f");
+LLUUID const ANIM_AGENT_RPS_PAPER ("0836b67f-7f7b-f37b-c00a-460dc1521f5a");
+LLUUID const ANIM_AGENT_RPS_ROCK ("42dd95d5-0bc6-6392-f650-777304946c0f");
+LLUUID const ANIM_AGENT_RPS_SCISSORS ("16803a9f-5140-e042-4d7b-d28ba247c325");
+LLUUID const ANIM_AGENT_RUN ("05ddbff8-aaa9-92a1-2b74-8fe77a29b445");
+LLUUID const ANIM_AGENT_RUN_NEW ("1ab1b236-cd08-21e6-0cbc-0d923fc6eca2");
+LLUUID const ANIM_AGENT_SAD ("0eb702e2-cc5a-9a88-56a5-661a55c0676a");
+LLUUID const ANIM_AGENT_SALUTE ("cd7668a6-7011-d7e2-ead8-fc69eff1a104");
+LLUUID const ANIM_AGENT_SHOOT_BOW_L ("e04d450d-fdb5-0432-fd68-818aaf5935f8");
+LLUUID const ANIM_AGENT_SHOUT ("6bd01860-4ebd-127a-bb3d-d1427e8e0c42");
+LLUUID const ANIM_AGENT_SHRUG ("70ea714f-3a97-d742-1b01-590a8fcd1db5");
+LLUUID const ANIM_AGENT_SIT ("1a5fe8ac-a804-8a5d-7cbd-56bd83184568");
+LLUUID const ANIM_AGENT_SIT_FEMALE ("b1709c8d-ecd3-54a1-4f28-d55ac0840782");
+LLUUID const ANIM_AGENT_SIT_GENERIC ("245f3c54-f1c0-bf2e-811f-46d8eeb386e7");
+LLUUID const ANIM_AGENT_SIT_GROUND ("1c7600d6-661f-b87b-efe2-d7421eb93c86");
+LLUUID const ANIM_AGENT_SIT_GROUND_CONSTRAINED("1a2bd58e-87ff-0df8-0b4c-53e047b0bb6e");
+LLUUID const ANIM_AGENT_SIT_TO_STAND ("a8dee56f-2eae-9e7a-05a2-6fb92b97e21e");
+LLUUID const ANIM_AGENT_SLEEP ("f2bed5f9-9d44-39af-b0cd-257b2a17fe40");
+LLUUID const ANIM_AGENT_SMOKE_IDLE ("d2f2ee58-8ad1-06c9-d8d3-3827ba31567a");
+LLUUID const ANIM_AGENT_SMOKE_INHALE ("6802d553-49da-0778-9f85-1599a2266526");
+LLUUID const ANIM_AGENT_SMOKE_THROW_DOWN ("0a9fb970-8b44-9114-d3a9-bf69cfe804d6");
+LLUUID const ANIM_AGENT_SNAPSHOT ("eae8905b-271a-99e2-4c0e-31106afd100c");
+LLUUID const ANIM_AGENT_STAND ("2408fe9e-df1d-1d7d-f4ff-1384fa7b350f");
+LLUUID const ANIM_AGENT_STANDUP ("3da1d753-028a-5446-24f3-9c9b856d9422");
+LLUUID const ANIM_AGENT_STAND_1 ("15468e00-3400-bb66-cecc-646d7c14458e");
+LLUUID const ANIM_AGENT_STAND_2 ("370f3a20-6ca6-9971-848c-9a01bc42ae3c");
+LLUUID const ANIM_AGENT_STAND_3 ("42b46214-4b44-79ae-deb8-0df61424ff4b");
+LLUUID const ANIM_AGENT_STAND_4 ("f22fed8b-a5ed-2c93-64d5-bdd8b93c889f");
+LLUUID const ANIM_AGENT_STRETCH ("80700431-74ec-a008-14f8-77575e73693f");
+LLUUID const ANIM_AGENT_STRIDE ("1cb562b0-ba21-2202-efb3-30f82cdf9595");
+LLUUID const ANIM_AGENT_SURF ("41426836-7437-7e89-025d-0aa4d10f1d69");
+LLUUID const ANIM_AGENT_SURPRISE ("313b9881-4302-73c0-c7d0-0e7a36b6c224");
+LLUUID const ANIM_AGENT_SWORD_STRIKE ("85428680-6bf9-3e64-b489-6f81087c24bd");
+LLUUID const ANIM_AGENT_TALK ("5c682a95-6da4-a463-0bf6-0f5b7be129d1");
+LLUUID const ANIM_AGENT_TANTRUM ("11000694-3f41-adc2-606b-eee1d66f3724");
+LLUUID const ANIM_AGENT_THROW_R ("aa134404-7dac-7aca-2cba-435f9db875ca");
+LLUUID const ANIM_AGENT_TRYON_SHIRT ("83ff59fe-2346-f236-9009-4e3608af64c1");
+LLUUID const ANIM_AGENT_TURNLEFT ("56e0ba0d-4a9f-7f27-6117-32f2ebbf6135");
+LLUUID const ANIM_AGENT_TURNRIGHT ("2d6daa51-3192-6794-8e2e-a15f8338ec30");
+LLUUID const ANIM_AGENT_TYPE ("c541c47f-e0c0-058b-ad1a-d6ae3a4584d9");
+LLUUID const ANIM_AGENT_WALK ("6ed24bd8-91aa-4b12-ccc7-c97c857ab4e0");
+LLUUID const ANIM_AGENT_WALK_NEW ("33339176-7ddc-9397-94a4-bf3403cbc8f5");
+LLUUID const ANIM_AGENT_WHISPER ("7693f268-06c7-ea71-fa21-2b30d6533f8f");
+LLUUID const ANIM_AGENT_WHISTLE ("b1ed7982-c68e-a982-7561-52a88a5298c0");
+LLUUID const ANIM_AGENT_WINK ("869ecdad-a44b-671e-3266-56aef2e3ac2e");
+LLUUID const ANIM_AGENT_WINK_HOLLYWOOD ("c0c4030f-c02b-49de-24ba-2331f43fe41c");
+LLUUID const ANIM_AGENT_WORRY ("9f496bd2-589a-709f-16cc-69bf7df1d36c");
+LLUUID const ANIM_AGENT_YES ("15dd911d-be82-2856-26db-27659b142875");
+LLUUID const ANIM_AGENT_YES_HAPPY ("b8c8b2a3-9008-1771-3bfc-90924955ab2d");
+LLUUID const ANIM_AGENT_YOGA_FLOAT ("42ecd00b-9947-a97c-400a-bbc9174c7aeb");
LLUUID AGENT_WALK_ANIMS[] = {ANIM_AGENT_WALK, ANIM_AGENT_RUN, ANIM_AGENT_CROUCHWALK, ANIM_AGENT_TURNLEFT, ANIM_AGENT_TURNRIGHT};
S32 NUM_AGENT_WALK_ANIMS = LL_ARRAY_SIZE(AGENT_WALK_ANIMS);
diff --git a/indra/llcommon/llavatarconstants.h b/indra/llcommon/llavatarconstants.h
index 596b0643ef..f47f447b45 100644
--- a/indra/llcommon/llavatarconstants.h
+++ b/indra/llcommon/llavatarconstants.h
@@ -46,10 +46,10 @@ const U32 AVATAR_TRANSACTED = 0x1 << 3; // whether avatar has actively used p
const U32 AVATAR_ONLINE = 0x1 << 4; // the online status of this avatar, if known.
const U32 AVATAR_AGEVERIFIED = 0x1 << 5; // whether avatar has been age-verified
-static const std::string VISIBILITY_DEFAULT("default");
-static const std::string VISIBILITY_HIDDEN("hidden");
-static const std::string VISIBILITY_VISIBLE("visible");
-static const std::string VISIBILITY_INVISIBLE("invisible");
+char const* const VISIBILITY_DEFAULT = "default";
+char const* const VISIBILITY_HIDDEN = "hidden";
+char const* const VISIBILITY_VISIBLE = "visible";
+char const* const VISIBILITY_INVISIBLE = "invisible";
#endif
diff --git a/indra/llcommon/lllslconstants.h b/indra/llcommon/lllslconstants.h
index 539c807020..9f32598e61 100644
--- a/indra/llcommon/lllslconstants.h
+++ b/indra/llcommon/lllslconstants.h
@@ -181,7 +181,7 @@ const S32 OBJECT_GROUP = 7;
const S32 OBJECT_CREATOR = 8;
// llTextBox() magic token string - yes this is a hack. sue me.
-const std::string TEXTBOX_MAGIC_TOKEN = "!!llTextBox!!";
+char const* const TEXTBOX_MAGIC_TOKEN = "!!llTextBox!!";
// changed() event flags
const U32 CHANGED_NONE = 0x0;
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 51fcd5b717..08fc1ddfe5 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -26,14 +26,13 @@
#include "linden_common.h"
-#include "llmemory.h"
-#if MEM_TRACK_MEM
+//#if MEM_TRACK_MEM
#include "llthread.h"
-#endif
+//#endif
#if defined(LL_WINDOWS)
-# include <windows.h>
+//# include <windows.h>
# include <psapi.h>
#elif defined(LL_DARWIN)
# include <sys/types.h>
@@ -43,10 +42,20 @@
# include <unistd.h>
#endif
+#include "llmemory.h"
+
+#include "llsys.h"
+#include "llframetimer.h"
//----------------------------------------------------------------------------
//static
char* LLMemory::reserveMem = 0;
+U32 LLMemory::sAvailPhysicalMemInKB = U32_MAX ;
+U32 LLMemory::sMaxPhysicalMemInKB = 0;
+U32 LLMemory::sAllocatedMemInKB = 0;
+U32 LLMemory::sAllocatedPageSizeInKB = 0 ;
+U32 LLMemory::sMaxHeapSizeInKB = U32_MAX ;
+BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;
//static
void LLMemory::initClass()
@@ -71,6 +80,131 @@ void LLMemory::freeReserve()
reserveMem = NULL;
}
+//static
+void LLMemory::initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure)
+{
+ sMaxHeapSizeInKB = (U32)(max_heap_size_gb * 1024 * 1024) ;
+ sEnableMemoryFailurePrevention = prevent_heap_failure ;
+}
+
+//static
+void LLMemory::updateMemoryInfo()
+{
+#if LL_WINDOWS
+ HANDLE self = GetCurrentProcess();
+ PROCESS_MEMORY_COUNTERS counters;
+
+ if (!GetProcessMemoryInfo(self, &counters, sizeof(counters)))
+ {
+ llwarns << "GetProcessMemoryInfo failed" << llendl;
+ return ;
+ }
+
+ sAllocatedMemInKB = (U32)(counters.WorkingSetSize / 1024) ;
+ sAllocatedPageSizeInKB = (U32)(counters.PagefileUsage / 1024) ;
+ sMaxPhysicalMemInKB = llmin(LLMemoryInfo::getAvailableMemoryKB() + sAllocatedMemInKB, sMaxHeapSizeInKB);
+
+ if(sMaxPhysicalMemInKB > sAllocatedMemInKB)
+ {
+ sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ;
+ }
+ else
+ {
+ sAvailPhysicalMemInKB = 0 ;
+ }
+#else
+ //not valid for other systems for now.
+ sAllocatedMemInKB = (U32)(LLMemory::getCurrentRSS() / 1024) ;
+ sMaxPhysicalMemInKB = U32_MAX ;
+ sAvailPhysicalMemInKB = U32_MAX ;
+#endif
+
+ return ;
+}
+
+//
+//this function is to test if there is enough space with the size in the virtual address space.
+//it does not do any real allocation
+//if success, it returns the address where the memory chunk can fit in;
+//otherwise it returns NULL.
+//
+//static
+void* LLMemory::tryToAlloc(void* address, U32 size)
+{
+#if LL_WINDOWS
+ address = VirtualAlloc(address, size, MEM_RESERVE | MEM_TOP_DOWN, PAGE_NOACCESS) ;
+ if(address)
+ {
+ if(!VirtualFree(address, 0, MEM_RELEASE))
+ {
+ llerrs << "error happens when free some memory reservation." << llendl ;
+ }
+ }
+#else
+#endif
+
+ return address ;
+}
+
+//static
+void LLMemory::logMemoryInfo(BOOL update)
+{
+ if(update)
+ {
+ updateMemoryInfo() ;
+ }
+
+ llinfos << "Current allocated physical memory(KB): " << sAllocatedMemInKB << llendl ;
+ llinfos << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << llendl ;
+ llinfos << "Current availabe physical memory(KB): " << sAvailPhysicalMemInKB << llendl ;
+ llinfos << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << llendl ;
+}
+
+//return 0: everything is normal;
+//return 1: the memory pool is low, but not in danger;
+//return -1: the memory pool is in danger, is about to crash.
+//static
+S32 LLMemory::isMemoryPoolLow()
+{
+ static const U32 LOW_MEMEOY_POOL_THRESHOLD_KB = 64 * 1024 ; //64 MB for emergency use
+
+ if(!sEnableMemoryFailurePrevention)
+ {
+ return 0 ; //no memory failure prevention.
+ }
+
+ if(sAvailPhysicalMemInKB < (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2)) //out of physical memory
+ {
+ return -1 ;
+ }
+
+ if(sAllocatedPageSizeInKB + (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2) > sMaxHeapSizeInKB) //out of virtual address space.
+ {
+ return -1 ;
+ }
+
+ return (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB ||
+ sAllocatedPageSizeInKB + LOW_MEMEOY_POOL_THRESHOLD_KB > sMaxHeapSizeInKB) ;
+}
+
+//static
+U32 LLMemory::getAvailableMemKB()
+{
+ return sAvailPhysicalMemInKB ;
+}
+
+//static
+U32 LLMemory::getMaxMemKB()
+{
+ return sMaxPhysicalMemInKB ;
+}
+
+//static
+U32 LLMemory::getAllocatedMemKB()
+{
+ return sAllocatedMemInKB ;
+}
+
void* ll_allocate (size_t size)
{
if (size == 0)
@@ -256,7 +390,7 @@ U64 LLMemory::getCurrentRSS()
U32 LLMemory::getWorkingSetSize()
{
- return 0 ;
+ return 0;
}
#endif
@@ -395,3 +529,1508 @@ const char* LLMemTracker::getNextLine()
#endif //MEM_TRACK_MEM
//--------------------------------------------------------------------------------------------------
+
+//--------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------
+//minimum block sizes (page size) for small allocation, medium allocation, large allocation
+const U32 MIN_BLOCK_SIZES[LLPrivateMemoryPool::SUPER_ALLOCATION] = {2 << 10, 4 << 10, 16 << 10} ; //
+
+//maximum block sizes for small allocation, medium allocation, large allocation
+const U32 MAX_BLOCK_SIZES[LLPrivateMemoryPool::SUPER_ALLOCATION] = {64 << 10, 1 << 20, 4 << 20} ;
+
+//minimum slot sizes for small allocation, medium allocation, large allocation
+const U32 MIN_SLOT_SIZES[LLPrivateMemoryPool::SUPER_ALLOCATION] = {8, 2 << 10, 512 << 10};
+
+//maximum slot sizes for small allocation, medium allocation, large allocation
+const U32 MAX_SLOT_SIZES[LLPrivateMemoryPool::SUPER_ALLOCATION] = {(2 << 10) - 8, (512 - 2) << 10, 4 << 20};
+
+//size of a block with multiple slots can not exceed CUT_OFF_SIZE
+const U32 CUT_OFF_SIZE = (64 << 10) ; //64 KB
+
+//-------------------------------------------------------------
+//class LLPrivateMemoryPool::LLMemoryBlock
+//-------------------------------------------------------------
+//
+//each memory block could fit for two page sizes: 0.75 * mSlotSize, which starts from the beginning of the memory chunk and grow towards the end of the
+//the block; another is mSlotSize, which starts from the end of the block and grows towards the beginning of the block.
+//
+LLPrivateMemoryPool::LLMemoryBlock::LLMemoryBlock()
+{
+ //empty
+}
+
+LLPrivateMemoryPool::LLMemoryBlock::~LLMemoryBlock()
+{
+ //empty
+}
+
+//create and initialize a memory block
+void LLPrivateMemoryPool::LLMemoryBlock::init(char* buffer, U32 buffer_size, U32 slot_size)
+{
+ mBuffer = buffer ;
+ mBufferSize = buffer_size ;
+ mSlotSize = slot_size ;
+ mTotalSlots = buffer_size / mSlotSize ;
+
+ llassert_always(mTotalSlots <= 256) ; //max number is 256
+
+ mAllocatedSlots = 0 ;
+
+ //init the bit map.
+ //mark free bits
+ S32 usage_bit_len = (mTotalSlots + 31) / 32 ;
+ mDummySize = usage_bit_len - 1 ; //if the mTotalSlots more than 32, needs extra space for bit map
+ if(mDummySize > 0) //reserve extra space from mBuffer to store bitmap if needed.
+ {
+ mTotalSlots -= (mDummySize * sizeof(mUsageBits) + mSlotSize - 1) / mSlotSize ;
+ usage_bit_len = (mTotalSlots + 31) / 32 ;
+ mDummySize = usage_bit_len - 1 ;//number of 32bits reserved from mBuffer for bitmap
+
+ if(mDummySize > 0)
+ {
+ mUsageBits = 0 ;
+ for(S32 i = 0 ; i < mDummySize ; i++)
+ {
+ *((U32*)mBuffer + i) = 0 ;
+ }
+ if(mTotalSlots & 31)
+ {
+ *((U32*)mBuffer + mDummySize - 1) = (0xffffffff << (mTotalSlots & 31)) ;
+ }
+ }
+ }
+
+ if(mDummySize < 1)//no extra bitmap space reserved
+ {
+ mUsageBits = 0 ;
+ if(mTotalSlots & 31)
+ {
+ mUsageBits = (0xffffffff << (mTotalSlots & 31)) ;
+ }
+ }
+
+ mSelf = this ;
+ mNext = NULL ;
+ mPrev = NULL ;
+
+ llassert_always(mTotalSlots > 0) ;
+}
+
+//mark this block to be free with the memory [mBuffer, mBuffer + mBufferSize).
+void LLPrivateMemoryPool::LLMemoryBlock::setBuffer(char* buffer, U32 buffer_size)
+{
+ mBuffer = buffer ;
+ mBufferSize = buffer_size ;
+ mSelf = NULL ;
+ mTotalSlots = 0 ; //set the block is free.
+}
+
+//reserve a slot
+char* LLPrivateMemoryPool::LLMemoryBlock::allocate()
+{
+ llassert_always(mAllocatedSlots < mTotalSlots) ;
+
+ //find a free slot
+ U32* bits = NULL ;
+ U32 k = 0 ;
+ if(mUsageBits != 0xffffffff)
+ {
+ bits = &mUsageBits ;
+ }
+ else if(mDummySize > 0)//go to extra space
+ {
+ for(S32 i = 0 ; i < mDummySize; i++)
+ {
+ if(*((U32*)mBuffer + i) != 0xffffffff)
+ {
+ bits = (U32*)mBuffer + i ;
+ k = i + 1 ;
+ break ;
+ }
+ }
+ }
+ S32 idx = 0 ;
+ U32 tmp = *bits ;
+ for(; tmp & 1 ; tmp >>= 1, idx++) ;
+
+ //set the slot reserved
+ if(!idx)
+ {
+ *bits |= 1 ;
+ }
+ else
+ {
+ *bits |= (1 << idx) ;
+ }
+
+ mAllocatedSlots++ ;
+
+ return mBuffer + mDummySize * sizeof(U32) + (k * 32 + idx) * mSlotSize ;
+}
+
+//free a slot
+void LLPrivateMemoryPool::LLMemoryBlock::free(void* addr)
+{
+ //bit index
+ U32 idx = ((U32)addr - (U32)mBuffer - mDummySize * sizeof(U32)) / mSlotSize ;
+
+ U32* bits = &mUsageBits ;
+ if(idx >= 32)
+ {
+ bits = (U32*)mBuffer + (idx - 32) / 32 ;
+ }
+
+ //reset the bit
+ if(idx & 31)
+ {
+ *bits &= ~(1 << (idx & 31)) ;
+ }
+ else
+ {
+ *bits &= ~1 ;
+ }
+
+ mAllocatedSlots-- ;
+}
+
+//for debug use: reset the entire bitmap.
+void LLPrivateMemoryPool::LLMemoryBlock::resetBitMap()
+{
+ for(S32 i = 0 ; i < mDummySize ; i++)
+ {
+ *((U32*)mBuffer + i) = 0 ;
+ }
+ mUsageBits = 0 ;
+}
+//-------------------------------------------------------------------
+//class LLMemoryChunk
+//--------------------------------------------------------------------
+LLPrivateMemoryPool::LLMemoryChunk::LLMemoryChunk()
+{
+ //empty
+}
+
+LLPrivateMemoryPool::LLMemoryChunk::~LLMemoryChunk()
+{
+ //empty
+}
+
+//create and init a memory chunk
+void LLPrivateMemoryPool::LLMemoryChunk::init(char* buffer, U32 buffer_size, U32 min_slot_size, U32 max_slot_size, U32 min_block_size, U32 max_block_size)
+{
+ mBuffer = buffer ;
+ mBufferSize = buffer_size ;
+ mAlloatedSize = 0 ;
+
+ mMetaBuffer = mBuffer + sizeof(LLMemoryChunk) ;
+
+ mMinBlockSize = min_block_size; //page size
+ mMinSlotSize = min_slot_size;
+ mMaxSlotSize = max_slot_size ;
+ mBlockLevels = mMaxSlotSize / mMinSlotSize ;
+ mPartitionLevels = max_block_size / mMinBlockSize + 1 ;
+
+ S32 max_num_blocks = (buffer_size - sizeof(LLMemoryChunk) - mBlockLevels * sizeof(LLMemoryBlock*) - mPartitionLevels * sizeof(LLMemoryBlock*)) /
+ (mMinBlockSize + sizeof(LLMemoryBlock)) ;
+ //meta data space
+ mBlocks = (LLMemoryBlock*)mMetaBuffer ; //space reserved for all memory blocks.
+ mAvailBlockList = (LLMemoryBlock**)((char*)mBlocks + sizeof(LLMemoryBlock) * max_num_blocks) ;
+ mFreeSpaceList = (LLMemoryBlock**)((char*)mAvailBlockList + sizeof(LLMemoryBlock*) * mBlockLevels) ;
+
+ //data buffer, which can be used for allocation
+ mDataBuffer = (char*)mFreeSpaceList + sizeof(LLMemoryBlock*) * mPartitionLevels ;
+
+ //init
+ for(U32 i = 0 ; i < mBlockLevels; i++)
+ {
+ mAvailBlockList[i] = NULL ;
+ }
+ for(U32 i = 0 ; i < mPartitionLevels ; i++)
+ {
+ mFreeSpaceList[i] = NULL ;
+ }
+
+ //assign the entire chunk to the first block
+ mBlocks[0].mPrev = NULL ;
+ mBlocks[0].mNext = NULL ;
+ mBlocks[0].setBuffer(mDataBuffer, buffer_size - (mDataBuffer - mBuffer)) ;
+ addToFreeSpace(&mBlocks[0]) ;
+
+ mHashNext = NULL ;
+ mNext = NULL ;
+ mPrev = NULL ;
+}
+
+//static
+U32 LLPrivateMemoryPool::LLMemoryChunk::getMaxOverhead(U32 data_buffer_size, U32 min_slot_size,
+ U32 max_slot_size, U32 min_block_size, U32 max_block_size)
+{
+ //for large allocations, reserve some extra memory for meta data to avoid wasting much
+ if(data_buffer_size / min_slot_size < 64) //large allocations
+ {
+ U32 overhead = sizeof(LLMemoryChunk) + (data_buffer_size / min_block_size) * sizeof(LLMemoryBlock) +
+ sizeof(LLMemoryBlock*) * (max_slot_size / min_slot_size) + sizeof(LLMemoryBlock*) * (max_block_size / min_block_size + 1) ;
+
+ //round to integer times of min_block_size
+ overhead = ((overhead + min_block_size - 1) / min_block_size) * min_block_size ;
+ return overhead ;
+ }
+ else
+ {
+ return 0 ; //do not reserve extra overhead if for small allocations
+ }
+}
+
+char* LLPrivateMemoryPool::LLMemoryChunk::allocate(U32 size)
+{
+ if(mMinSlotSize > size)
+ {
+ size = mMinSlotSize ;
+ }
+ if(mAlloatedSize + size > mBufferSize - (mDataBuffer - mBuffer))
+ {
+ return NULL ; //no enough space in this chunk.
+ }
+
+ char* p = NULL ;
+ U32 blk_idx = getBlockLevel(size);
+
+ LLMemoryBlock* blk = NULL ;
+
+ //check if there is free block available
+ if(mAvailBlockList[blk_idx])
+ {
+ blk = mAvailBlockList[blk_idx] ;
+ p = blk->allocate() ;
+
+ if(blk->isFull())
+ {
+ popAvailBlockList(blk_idx) ;
+ }
+ }
+
+ //ask for a new block
+ if(!p)
+ {
+ blk = addBlock(blk_idx) ;
+ if(blk)
+ {
+ p = blk->allocate() ;
+
+ if(blk->isFull())
+ {
+ popAvailBlockList(blk_idx) ;
+ }
+ }
+ }
+
+ //ask for space from larger blocks
+ if(!p)
+ {
+ for(S32 i = blk_idx + 1 ; i < mBlockLevels; i++)
+ {
+ if(mAvailBlockList[i])
+ {
+ blk = mAvailBlockList[i] ;
+ p = blk->allocate() ;
+
+ if(blk->isFull())
+ {
+ popAvailBlockList(i) ;
+ }
+ break ;
+ }
+ }
+ }
+
+ if(p && blk)
+ {
+ mAlloatedSize += blk->getSlotSize() ;
+ }
+ return p ;
+}
+
+void LLPrivateMemoryPool::LLMemoryChunk::free(void* addr)
+{
+ U32 blk_idx = getPageIndex((U32)addr) ;
+ LLMemoryBlock* blk = (LLMemoryBlock*)(mMetaBuffer + blk_idx * sizeof(LLMemoryBlock)) ;
+ blk = blk->mSelf ;
+
+ bool was_full = blk->isFull() ;
+ blk->free(addr) ;
+ mAlloatedSize -= blk->getSlotSize() ;
+
+ if(blk->empty())
+ {
+ removeBlock(blk) ;
+ }
+ else if(was_full)
+ {
+ addToAvailBlockList(blk) ;
+ }
+}
+
+bool LLPrivateMemoryPool::LLMemoryChunk::empty()
+{
+ return !mAlloatedSize ;
+}
+
+bool LLPrivateMemoryPool::LLMemoryChunk::containsAddress(const char* addr) const
+{
+ return (U32)mBuffer <= (U32)addr && (U32)mBuffer + mBufferSize > (U32)addr ;
+}
+
+//debug use
+void LLPrivateMemoryPool::LLMemoryChunk::dump()
+{
+#if 0
+ //sanity check
+ //for(S32 i = 0 ; i < mBlockLevels ; i++)
+ //{
+ // LLMemoryBlock* blk = mAvailBlockList[i] ;
+ // while(blk)
+ // {
+ // blk_list.push_back(blk) ;
+ // blk = blk->mNext ;
+ // }
+ //}
+ for(S32 i = 0 ; i < mPartitionLevels ; i++)
+ {
+ LLMemoryBlock* blk = mFreeSpaceList[i] ;
+ while(blk)
+ {
+ blk_list.push_back(blk) ;
+ blk = blk->mNext ;
+ }
+ }
+
+ std::sort(blk_list.begin(), blk_list.end(), LLMemoryBlock::CompareAddress());
+
+ U32 total_size = blk_list[0]->getBufferSize() ;
+ for(U32 i = 1 ; i < blk_list.size(); i++)
+ {
+ total_size += blk_list[i]->getBufferSize() ;
+ if((U32)blk_list[i]->getBuffer() < (U32)blk_list[i-1]->getBuffer() + blk_list[i-1]->getBufferSize())
+ {
+ llerrs << "buffer corrupted." << llendl ;
+ }
+ }
+
+ llassert_always(total_size + mMinBlockSize >= mBufferSize - ((U32)mDataBuffer - (U32)mBuffer)) ;
+
+ U32 blk_num = (mBufferSize - (mDataBuffer - mBuffer)) / mMinBlockSize ;
+ for(U32 i = 0 ; i < blk_num ; )
+ {
+ LLMemoryBlock* blk = &mBlocks[i] ;
+ if(blk->mSelf)
+ {
+ U32 end = blk->getBufferSize() / mMinBlockSize ;
+ for(U32 j = 0 ; j < end ; j++)
+ {
+ llassert_always(blk->mSelf == blk || !blk->mSelf) ;
+ }
+ i += end ;
+ }
+ else
+ {
+ llerrs << "gap happens" << llendl ;
+ }
+ }
+#endif
+#if 0
+ llinfos << "---------------------------" << llendl ;
+ llinfos << "Chunk buffer: " << (U32)getBuffer() << " size: " << getBufferSize() << llendl ;
+
+ llinfos << "available blocks ... " << llendl ;
+ for(S32 i = 0 ; i < mBlockLevels ; i++)
+ {
+ LLMemoryBlock* blk = mAvailBlockList[i] ;
+ while(blk)
+ {
+ llinfos << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << llendl ;
+ blk = blk->mNext ;
+ }
+ }
+
+ llinfos << "free blocks ... " << llendl ;
+ for(S32 i = 0 ; i < mPartitionLevels ; i++)
+ {
+ LLMemoryBlock* blk = mFreeSpaceList[i] ;
+ while(blk)
+ {
+ llinfos << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << llendl ;
+ blk = blk->mNext ;
+ }
+ }
+#endif
+}
+
+//compute the size for a block, the size is round to integer times of mMinBlockSize.
+U32 LLPrivateMemoryPool::LLMemoryChunk::calcBlockSize(U32 slot_size)
+{
+ //
+ //Note: we try to make a block to have 32 slots if the size is not over 32 pages
+ //32 is the number of bits of an integer in a 32-bit system
+ //
+
+ U32 block_size;
+ U32 cut_off_size = llmin(CUT_OFF_SIZE, (U32)(mMinBlockSize << 5)) ;
+
+ if((slot_size << 5) <= mMinBlockSize)//for small allocations, return one page
+ {
+ block_size = mMinBlockSize ;
+ }
+ else if(slot_size >= cut_off_size)//for large allocations, return one-slot block
+ {
+ block_size = (slot_size / mMinBlockSize) * mMinBlockSize ;
+ if(block_size < slot_size)
+ {
+ block_size += mMinBlockSize ;
+ }
+ }
+ else //medium allocations
+ {
+ if((slot_size << 5) >= cut_off_size)
+ {
+ block_size = cut_off_size ;
+ }
+ else
+ {
+ block_size = ((slot_size << 5) / mMinBlockSize) * mMinBlockSize ;
+ }
+ }
+
+ llassert_always(block_size >= slot_size) ;
+
+ return block_size ;
+}
+
+//create a new block in the chunk
+LLPrivateMemoryPool::LLMemoryBlock* LLPrivateMemoryPool::LLMemoryChunk::addBlock(U32 blk_idx)
+{
+ U32 slot_size = mMinSlotSize * (blk_idx + 1) ;
+ U32 preferred_block_size = calcBlockSize(slot_size) ;
+ U16 idx = getPageLevel(preferred_block_size);
+ LLMemoryBlock* blk = NULL ;
+
+ if(mFreeSpaceList[idx])//if there is free slot for blk_idx
+ {
+ blk = createNewBlock(mFreeSpaceList[idx], preferred_block_size, slot_size, blk_idx) ;
+ }
+ else if(mFreeSpaceList[mPartitionLevels - 1]) //search free pool
+ {
+ blk = createNewBlock(mFreeSpaceList[mPartitionLevels - 1], preferred_block_size, slot_size, blk_idx) ;
+ }
+ else //search for other non-preferred but enough space slot.
+ {
+ S32 min_idx = 0 ;
+ if(slot_size > mMinBlockSize)
+ {
+ min_idx = getPageLevel(slot_size) ;
+ }
+ for(S32 i = (S32)idx - 1 ; i >= min_idx ; i--) //search the small slots first
+ {
+ if(mFreeSpaceList[i])
+ {
+ U32 new_preferred_block_size = mFreeSpaceList[i]->getBufferSize();
+ new_preferred_block_size = (new_preferred_block_size / mMinBlockSize) * mMinBlockSize ; //round to integer times of mMinBlockSize.
+
+ //create a NEW BLOCK THERE.
+ if(new_preferred_block_size >= slot_size) //at least there is space for one slot.
+ {
+
+ blk = createNewBlock(mFreeSpaceList[i], new_preferred_block_size, slot_size, blk_idx) ;
+ }
+ break ;
+ }
+ }
+
+ if(!blk)
+ {
+ for(U16 i = idx + 1 ; i < mPartitionLevels - 1; i++) //search the large slots
+ {
+ if(mFreeSpaceList[i])
+ {
+ //create a NEW BLOCK THERE.
+ blk = createNewBlock(mFreeSpaceList[i], preferred_block_size, slot_size, blk_idx) ;
+ break ;
+ }
+ }
+ }
+ }
+
+ return blk ;
+}
+
+//create a new block at the designed location
+LLPrivateMemoryPool::LLMemoryBlock* LLPrivateMemoryPool::LLMemoryChunk::createNewBlock(LLMemoryBlock* blk, U32 buffer_size, U32 slot_size, U32 blk_idx)
+{
+ //unlink from the free space
+ removeFromFreeSpace(blk) ;
+
+ //check the rest space
+ U32 new_free_blk_size = blk->getBufferSize() - buffer_size ;
+ if(new_free_blk_size < mMinBlockSize) //can not partition the memory into size smaller than mMinBlockSize
+ {
+ new_free_blk_size = 0 ; //discard the last small extra space.
+ }
+
+ //add the rest space back to the free list
+ if(new_free_blk_size > 0) //blk still has free space
+ {
+ LLMemoryBlock* next_blk = blk + (buffer_size / mMinBlockSize) ;
+ next_blk->setBuffer(blk->getBuffer() + buffer_size, new_free_blk_size) ;
+ addToFreeSpace(next_blk) ;
+ }
+
+ blk->init(blk->getBuffer(), buffer_size, slot_size) ;
+ //insert to the available block list...
+ mAvailBlockList[blk_idx] = blk ;
+
+ //mark the address map: all blocks covered by this block space pointing back to this block.
+ U32 end = (buffer_size / mMinBlockSize) ;
+ for(U32 i = 1 ; i < end ; i++)
+ {
+ (blk + i)->mSelf = blk ;
+ }
+
+ return blk ;
+}
+
+//delete a block, release the block to the free pool.
+void LLPrivateMemoryPool::LLMemoryChunk::removeBlock(LLMemoryBlock* blk)
+{
+ //remove from the available block list
+ if(blk->mPrev)
+ {
+ blk->mPrev->mNext = blk->mNext ;
+ }
+ if(blk->mNext)
+ {
+ blk->mNext->mPrev = blk->mPrev ;
+ }
+ U32 blk_idx = getBlockLevel(blk->getSlotSize());
+ if(mAvailBlockList[blk_idx] == blk)
+ {
+ mAvailBlockList[blk_idx] = blk->mNext ;
+ }
+
+ blk->mNext = NULL ;
+ blk->mPrev = NULL ;
+
+ //mark it free
+ blk->setBuffer(blk->getBuffer(), blk->getBufferSize()) ;
+
+#if 1
+ //merge blk with neighbors if possible
+ if(blk->getBuffer() > mDataBuffer) //has the left neighbor
+ {
+ if((blk - 1)->mSelf->isFree())
+ {
+ LLMemoryBlock* left_blk = (blk - 1)->mSelf ;
+ removeFromFreeSpace((blk - 1)->mSelf);
+ left_blk->setBuffer(left_blk->getBuffer(), left_blk->getBufferSize() + blk->getBufferSize()) ;
+ blk = left_blk ;
+ }
+ }
+ if(blk->getBuffer() + blk->getBufferSize() <= mBuffer + mBufferSize - mMinBlockSize) //has the right neighbor
+ {
+ U32 d = blk->getBufferSize() / mMinBlockSize ;
+ if((blk + d)->isFree())
+ {
+ LLMemoryBlock* right_blk = blk + d ;
+ removeFromFreeSpace(blk + d) ;
+ blk->setBuffer(blk->getBuffer(), blk->getBufferSize() + right_blk->getBufferSize()) ;
+ }
+ }
+#endif
+
+ addToFreeSpace(blk) ;
+
+ return ;
+}
+
+//the top block in the list is full, pop it out of the list
+void LLPrivateMemoryPool::LLMemoryChunk::popAvailBlockList(U32 blk_idx)
+{
+ if(mAvailBlockList[blk_idx])
+ {
+ LLMemoryBlock* next = mAvailBlockList[blk_idx]->mNext ;
+ if(next)
+ {
+ next->mPrev = NULL ;
+ }
+ mAvailBlockList[blk_idx]->mPrev = NULL ;
+ mAvailBlockList[blk_idx]->mNext = NULL ;
+ mAvailBlockList[blk_idx] = next ;
+ }
+}
+
+//add the block back to the free pool
+void LLPrivateMemoryPool::LLMemoryChunk::addToFreeSpace(LLMemoryBlock* blk)
+{
+ llassert_always(!blk->mPrev) ;
+ llassert_always(!blk->mNext) ;
+
+ U16 free_idx = blk->getBufferSize() / mMinBlockSize - 1;
+
+ (blk + free_idx)->mSelf = blk ; //mark the end pointing back to the head.
+ free_idx = llmin(free_idx, (U16)(mPartitionLevels - 1)) ;
+
+ blk->mNext = mFreeSpaceList[free_idx] ;
+ if(mFreeSpaceList[free_idx])
+ {
+ mFreeSpaceList[free_idx]->mPrev = blk ;
+ }
+ mFreeSpaceList[free_idx] = blk ;
+ blk->mPrev = NULL ;
+ blk->mSelf = blk ;
+
+ return ;
+}
+
+//remove the space from the free pool
+void LLPrivateMemoryPool::LLMemoryChunk::removeFromFreeSpace(LLMemoryBlock* blk)
+{
+ U16 free_idx = blk->getBufferSize() / mMinBlockSize - 1;
+ free_idx = llmin(free_idx, (U16)(mPartitionLevels - 1)) ;
+
+ if(mFreeSpaceList[free_idx] == blk)
+ {
+ mFreeSpaceList[free_idx] = blk->mNext ;
+ }
+ if(blk->mPrev)
+ {
+ blk->mPrev->mNext = blk->mNext ;
+ }
+ if(blk->mNext)
+ {
+ blk->mNext->mPrev = blk->mPrev ;
+ }
+ blk->mNext = NULL ;
+ blk->mPrev = NULL ;
+ blk->mSelf = NULL ;
+
+ return ;
+}
+
+void LLPrivateMemoryPool::LLMemoryChunk::addToAvailBlockList(LLMemoryBlock* blk)
+{
+ llassert_always(!blk->mPrev) ;
+ llassert_always(!blk->mNext) ;
+
+ U32 blk_idx = getBlockLevel(blk->getSlotSize());
+
+ blk->mNext = mAvailBlockList[blk_idx] ;
+ if(blk->mNext)
+ {
+ blk->mNext->mPrev = blk ;
+ }
+ blk->mPrev = NULL ;
+ mAvailBlockList[blk_idx] = blk ;
+
+ return ;
+}
+
+U32 LLPrivateMemoryPool::LLMemoryChunk::getPageIndex(U32 addr)
+{
+ return (addr - (U32)mDataBuffer) / mMinBlockSize ;
+}
+
+//for mAvailBlockList
+U32 LLPrivateMemoryPool::LLMemoryChunk::getBlockLevel(U32 size)
+{
+ llassert(size >= mMinSlotSize && size <= mMaxSlotSize) ;
+
+ //start from 0
+ return (size + mMinSlotSize - 1) / mMinSlotSize - 1 ;
+}
+
+//for mFreeSpaceList
+U16 LLPrivateMemoryPool::LLMemoryChunk::getPageLevel(U32 size)
+{
+ //start from 0
+ U16 level = size / mMinBlockSize - 1 ;
+ if(level >= mPartitionLevels)
+ {
+ level = mPartitionLevels - 1 ;
+ }
+ return level ;
+}
+
+//-------------------------------------------------------------------
+//class LLPrivateMemoryPool
+//--------------------------------------------------------------------
+const U32 CHUNK_SIZE = 4 << 20 ; //4 MB
+const U32 LARGE_CHUNK_SIZE = 4 * CHUNK_SIZE ; //16 MB
+LLPrivateMemoryPool::LLPrivateMemoryPool(U32 max_size, bool threaded) :
+ mMutexp(NULL),
+ mMaxPoolSize(max_size),
+ mReservedPoolSize(0),
+ mHashFactor(1)
+{
+ if(threaded)
+ {
+ mMutexp = new LLMutex(NULL) ;
+ }
+
+ for(S32 i = 0 ; i < SUPER_ALLOCATION ; i++)
+ {
+ mChunkList[i] = NULL ;
+ }
+
+ mNumOfChunks = 0 ;
+}
+
+LLPrivateMemoryPool::~LLPrivateMemoryPool()
+{
+ destroyPool();
+ delete mMutexp ;
+}
+
+char* LLPrivateMemoryPool::allocate(U32 size)
+{
+ if(!size)
+ {
+ return NULL ;
+ }
+
+ //if the asked size larger than MAX_BLOCK_SIZE, fetch from heap directly, the pool does not manage it
+ if(size >= CHUNK_SIZE)
+ {
+ return new char[size] ;
+ }
+
+ char* p = NULL ;
+
+ //find the appropriate chunk
+ S32 chunk_idx = getChunkIndex(size) ;
+
+ lock() ;
+
+ LLMemoryChunk* chunk = mChunkList[chunk_idx];
+ while(chunk)
+ {
+ if((p = chunk->allocate(size)))
+ {
+ break ;
+ }
+ chunk = chunk->mNext ;
+ }
+
+ //fetch new memory chunk
+ if(!p)
+ {
+ if(mReservedPoolSize + CHUNK_SIZE > mMaxPoolSize)
+ {
+ chunk = mChunkList[chunk_idx];
+ while(chunk)
+ {
+ if((p = chunk->allocate(size)))
+ {
+ break ;
+ }
+ chunk = chunk->mNext ;
+ }
+ }
+
+ chunk = addChunk(chunk_idx) ;
+ if(chunk)
+ {
+ p = chunk->allocate(size) ;
+ }
+ }
+
+ unlock() ;
+
+ return p ;
+}
+
+void LLPrivateMemoryPool::free(void* addr)
+{
+ if(!addr)
+ {
+ return ;
+ }
+
+ lock() ;
+
+ LLMemoryChunk* chunk = findChunk((char*)addr) ;
+
+ if(!chunk)
+ {
+ delete[] (char*)addr ; //release from heap
+ }
+ else
+ {
+ chunk->free(addr) ;
+
+ if(chunk->empty())
+ {
+ removeChunk(chunk) ;
+ }
+ }
+
+ unlock() ;
+}
+
+void LLPrivateMemoryPool::dump()
+{
+}
+
+U32 LLPrivateMemoryPool::getTotalAllocatedSize()
+{
+ U32 total_allocated = 0 ;
+
+ LLMemoryChunk* chunk ;
+ for(S32 i = 0 ; i < SUPER_ALLOCATION ; i++)
+ {
+ chunk = mChunkList[i];
+ while(chunk)
+ {
+ total_allocated += chunk->getAllocatedSize() ;
+ chunk = chunk->mNext ;
+ }
+ }
+
+ return total_allocated ;
+}
+
+void LLPrivateMemoryPool::lock()
+{
+ if(mMutexp)
+ {
+ mMutexp->lock() ;
+ }
+}
+
+void LLPrivateMemoryPool::unlock()
+{
+ if(mMutexp)
+ {
+ mMutexp->unlock() ;
+ }
+}
+
+S32 LLPrivateMemoryPool::getChunkIndex(U32 size)
+{
+ S32 i ;
+ for(i = 0 ; size > MAX_SLOT_SIZES[i]; i++);
+
+ llassert_always(i < SUPER_ALLOCATION);
+
+ return i ;
+}
+
+//destroy the entire pool
+void LLPrivateMemoryPool::destroyPool()
+{
+ lock() ;
+ if(mNumOfChunks > 0)
+ {
+ for(U32 i = 0 ; i < mHashFactor; i++)
+ {
+ while(mChunkHashList[i])
+ {
+ removeChunk(mChunkHashList[i]) ;
+ }
+ }
+ }
+ mChunkHashList.clear() ;
+ mHashFactor = 1 ;
+ llassert_always(mNumOfChunks == 0) ;
+ llassert_always(mReservedPoolSize == 0) ;
+
+ for(S32 i = 0 ; i < SUPER_ALLOCATION ; i++)
+ {
+ mChunkList[i] = NULL ;
+ }
+
+ unlock() ;
+}
+
+void LLPrivateMemoryPool::checkSize(U32 asked_size)
+{
+ if(mReservedPoolSize + asked_size > mMaxPoolSize)
+ {
+ llinfos << "Max pool size: " << mMaxPoolSize << llendl ;
+ llinfos << "Total reserved size: " << mReservedPoolSize + asked_size << llendl ;
+ llinfos << "Total_allocated Size: " << getTotalAllocatedSize() << llendl ;
+
+ llerrs << "The pool is overflowing..." << llendl ;
+ }
+}
+
+LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::addChunk(S32 chunk_index)
+{
+ U32 preferred_size ;
+ U32 overhead ;
+ if(chunk_index < LARGE_ALLOCATION)
+ {
+ preferred_size = CHUNK_SIZE ; //4MB
+ overhead = LLMemoryChunk::getMaxOverhead(preferred_size, MIN_SLOT_SIZES[chunk_index],
+ MAX_SLOT_SIZES[chunk_index], MIN_BLOCK_SIZES[chunk_index], MAX_BLOCK_SIZES[chunk_index]) ;
+ }
+ else
+ {
+ preferred_size = LARGE_CHUNK_SIZE ; //16MB
+ overhead = LLMemoryChunk::getMaxOverhead(preferred_size, MIN_SLOT_SIZES[chunk_index],
+ MAX_SLOT_SIZES[chunk_index], MIN_BLOCK_SIZES[chunk_index], MAX_BLOCK_SIZES[chunk_index]) ;
+ }
+
+ checkSize(preferred_size + overhead) ;
+ mReservedPoolSize += preferred_size + overhead ;
+
+ char* buffer = new(std::nothrow) char[preferred_size + overhead] ;
+ if(!buffer)
+ {
+ return NULL ;
+ }
+
+ LLMemoryChunk* chunk = new (buffer) LLMemoryChunk() ;
+ chunk->init(buffer, preferred_size + overhead, MIN_SLOT_SIZES[chunk_index],
+ MAX_SLOT_SIZES[chunk_index], MIN_BLOCK_SIZES[chunk_index], MAX_BLOCK_SIZES[chunk_index]) ;
+
+ //add to the tail of the linked list
+ {
+ if(!mChunkList[chunk_index])
+ {
+ mChunkList[chunk_index] = chunk ;
+ }
+ else
+ {
+ LLMemoryChunk* cur = mChunkList[chunk_index] ;
+ while(cur->mNext)
+ {
+ cur = cur->mNext ;
+ }
+ cur->mNext = chunk ;
+ chunk->mPrev = cur ;
+ }
+ }
+
+ //insert into the hash table
+ addToHashTable(chunk) ;
+
+ mNumOfChunks++;
+
+ return chunk ;
+}
+
+void LLPrivateMemoryPool::removeChunk(LLMemoryChunk* chunk)
+{
+ if(!chunk)
+ {
+ return ;
+ }
+
+ //remove from the linked list
+ for(S32 i = 0 ; i < SUPER_ALLOCATION ; i++)
+ {
+ if(mChunkList[i] == chunk)
+ {
+ mChunkList[i] = chunk->mNext ;
+ }
+ }
+
+ if(chunk->mPrev)
+ {
+ chunk->mPrev->mNext = chunk->mNext ;
+ }
+ if(chunk->mNext)
+ {
+ chunk->mNext->mPrev = chunk->mPrev ;
+ }
+
+ //remove from the hash table
+ removeFromHashTable(chunk) ;
+
+ mNumOfChunks--;
+ mReservedPoolSize -= chunk->getBufferSize() ;
+
+ //release memory
+ delete[] chunk->getBuffer() ;
+}
+
+U16 LLPrivateMemoryPool::findHashKey(const char* addr)
+{
+ return (((U32)addr) / CHUNK_SIZE) % mHashFactor ;
+}
+
+LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::findChunk(const char* addr)
+{
+ U16 key = findHashKey(addr) ;
+ if(mChunkHashList.size() <= key)
+ {
+ return NULL ;
+ }
+
+ //check the hash value "key"
+ LLMemoryChunk* chunk = mChunkHashList[key] ;
+ while(chunk && !chunk->containsAddress(addr))
+ {
+ chunk = chunk->mHashNext ;
+ }
+
+ return chunk ;
+}
+
+void LLPrivateMemoryPool::addToHashTable(LLMemoryChunk* chunk)
+{
+ static const U16 HASH_FACTORS[] = {41, 83, 193, 317, 419, 523, 0xFFFF};
+
+ U16 i ;
+ if(mChunkHashList.empty())
+ {
+ mHashFactor = HASH_FACTORS[0] ;
+ rehash() ;
+ }
+
+ U16 start_key = findHashKey(chunk->getBuffer()) ;
+ U16 end_key = findHashKey(chunk->getBuffer() + chunk->getBufferSize() - 1) ;
+ bool need_rehash = false ;
+
+ if(mChunkHashList[start_key])
+ {
+ if(mChunkHashList[start_key] == chunk)
+ {
+ return; //already inserted.
+ }
+
+ llassert_always(!chunk->mHashNext) ;
+
+ chunk->mHashNext = mChunkHashList[start_key] ;
+ mChunkHashList[start_key] = chunk ;
+ }
+ else
+ {
+ mChunkHashList[start_key] = chunk ;
+ }
+
+ if(!need_rehash)
+ {
+ if(mChunkHashList[end_key])
+ {
+ llassert_always(mChunkHashList[end_key] != chunk)
+
+ need_rehash = mChunkHashList[end_key]->mHashNext != NULL || mChunkHashList[end_key] == chunk->mHashNext;
+ if(!need_rehash)
+ {
+ mChunkHashList[end_key]->mHashNext = chunk ;
+ }
+ }
+ else
+ {
+ mChunkHashList[end_key] = chunk ;
+ }
+ }
+
+ if(!need_rehash)
+ {
+ if(end_key < start_key)
+ {
+ need_rehash = fillHashTable(start_key + 1, mHashFactor, chunk) ;
+ if(!need_rehash)
+ {
+ need_rehash = fillHashTable(0, end_key, chunk) ;
+ }
+ }
+ else
+ {
+ need_rehash = fillHashTable(start_key + 1, end_key, chunk) ;
+ }
+ }
+
+ if(need_rehash)
+ {
+ i = 0 ;
+ while(HASH_FACTORS[i] <= mHashFactor) i++;
+
+ mHashFactor = HASH_FACTORS[i] ;
+ llassert_always(mHashFactor != 0xFFFF) ;//stop point to prevent endlessly recursive calls
+
+ rehash() ;
+ }
+}
+
+void LLPrivateMemoryPool::removeFromHashTable(LLMemoryChunk* chunk)
+{
+ U16 start_key = findHashKey(chunk->getBuffer()) ;
+ U16 end_key = findHashKey(chunk->getBuffer() + chunk->getBufferSize() - 1) ;
+
+ mChunkHashList[start_key] = chunk->mHashNext ;
+ chunk->mHashNext = NULL ;
+
+ if(mChunkHashList[end_key] != chunk)
+ {
+ mChunkHashList[end_key]->mHashNext = NULL ;
+ }
+ else
+ {
+ mChunkHashList[end_key] = NULL ;
+ }
+
+ if(end_key < start_key)
+ {
+ for(U16 i = start_key + 1 ; i < mHashFactor; i++)
+ {
+ mChunkHashList[i] = NULL ;
+ }
+ for(U16 i = 0 ; i < end_key; i++)
+ {
+ mChunkHashList[i] = NULL ;
+ }
+ }
+ else
+ {
+ for(U16 i = start_key + 1 ; i < end_key; i++)
+ {
+ mChunkHashList[i] = NULL ;
+ }
+ }
+}
+
+void LLPrivateMemoryPool::rehash()
+{
+ llinfos << "new hash factor: " << mHashFactor << llendl ;
+
+ mChunkHashList.clear() ;
+ mChunkHashList.resize(mHashFactor, NULL) ;
+
+ LLMemoryChunk* chunk ;
+ for(U16 i = 0 ; i < SUPER_ALLOCATION ; i++)
+ {
+ chunk = mChunkList[i] ;
+ while(chunk)
+ {
+ chunk->mHashNext = NULL ;
+ addToHashTable(chunk) ;
+ chunk = chunk->mNext ;
+ }
+ }
+}
+
+bool LLPrivateMemoryPool::fillHashTable(U16 start, U16 end, LLMemoryChunk* chunk)
+{
+ for(U16 i = start; i < end; i++)
+ {
+ if(mChunkHashList[i]) //the slot is occupied.
+ {
+ llassert_always(mChunkHashList[i] != chunk) ;
+ return true ;
+ }
+ else
+ {
+ mChunkHashList[i] = chunk ;
+ }
+ }
+
+ return false ;
+}
+
+//--------------------------------------------------------------------
+//class LLPrivateMemoryPoolManager
+//--------------------------------------------------------------------
+LLPrivateMemoryPoolManager* LLPrivateMemoryPoolManager::sInstance = NULL ;
+
+LLPrivateMemoryPoolManager::LLPrivateMemoryPoolManager()
+{
+}
+
+LLPrivateMemoryPoolManager::~LLPrivateMemoryPoolManager()
+{
+ //all private pools should be released by their owners before reaching here.
+ llassert_always(mPoolList.empty()) ;
+
+#if 0
+ if(!mPoolList.empty())
+ {
+ for(std::set<LLPrivateMemoryPool*>::iterator iter = mPoolList.begin(); iter != mPoolList.end(); ++iter)
+ {
+ delete *iter;
+ }
+ mPoolList.clear() ;
+ }
+#endif
+}
+
+//static
+LLPrivateMemoryPoolManager* LLPrivateMemoryPoolManager::getInstance()
+{
+ if(!sInstance)
+ {
+ sInstance = new LLPrivateMemoryPoolManager() ;
+ }
+ return sInstance ;
+}
+
+//static
+void LLPrivateMemoryPoolManager::destroyClass()
+{
+ if(sInstance)
+ {
+ delete sInstance ;
+ sInstance = NULL ;
+ }
+}
+
+LLPrivateMemoryPool* LLPrivateMemoryPoolManager::newPool(U32 max_size, bool threaded)
+{
+ LLPrivateMemoryPool* pool = new LLPrivateMemoryPool(max_size, threaded) ;
+ mPoolList.insert(pool) ;
+
+ return pool ;
+}
+
+void LLPrivateMemoryPoolManager::deletePool(LLPrivateMemoryPool* pool)
+{
+ mPoolList.erase(pool) ;
+ delete pool;
+}
+
+//debug
+void LLPrivateMemoryPoolManager::updateStatistics()
+{
+ mTotalReservedSize = 0 ;
+ mTotalAllocatedSize = 0 ;
+
+ for(std::set<LLPrivateMemoryPool*>::iterator iter = mPoolList.begin(); iter != mPoolList.end(); ++iter)
+ {
+ mTotalReservedSize += (*iter)->getTotalReservedSize() ;
+ mTotalAllocatedSize += (*iter)->getTotalAllocatedSize() ;
+ }
+}
+
+//--------------------------------------------------------------------
+//class LLPrivateMemoryPoolTester
+//--------------------------------------------------------------------
+LLPrivateMemoryPoolTester* LLPrivateMemoryPoolTester::sInstance = NULL ;
+LLPrivateMemoryPool* LLPrivateMemoryPoolTester::sPool = NULL ;
+LLPrivateMemoryPoolTester::LLPrivateMemoryPoolTester()
+{
+}
+
+LLPrivateMemoryPoolTester::~LLPrivateMemoryPoolTester()
+{
+}
+
+//static
+LLPrivateMemoryPoolTester* LLPrivateMemoryPoolTester::getInstance()
+{
+ if(!sInstance)
+ {
+ sInstance = ::new LLPrivateMemoryPoolTester() ;
+ }
+ return sInstance ;
+}
+
+//static
+void LLPrivateMemoryPoolTester::destroy()
+{
+ if(sInstance)
+ {
+ ::delete sInstance ;
+ sInstance = NULL ;
+ }
+
+ if(sPool)
+ {
+ LLPrivateMemoryPoolManager::getInstance()->deletePool(sPool) ;
+ sPool = NULL ;
+ }
+}
+
+void LLPrivateMemoryPoolTester::run(bool threaded)
+{
+ const U32 max_pool_size = 1024 << 20 ;
+
+ if(sPool)
+ {
+ LLPrivateMemoryPoolManager::getInstance()->deletePool(sPool) ;
+ }
+ sPool = LLPrivateMemoryPoolManager::getInstance()->newPool(max_pool_size, threaded) ;
+
+ //run the test
+ correctnessTest() ;
+ performanceTest() ;
+ //fragmentationtest() ;
+
+ //release pool.
+ LLPrivateMemoryPoolManager::getInstance()->deletePool(sPool) ;
+ sPool = NULL ;
+}
+
+void LLPrivateMemoryPoolTester::test(U32 min_size, U32 max_size, U32 stride, U32 times,
+ bool random_deletion, bool output_statistics)
+{
+ U32 levels = (max_size - min_size) / stride + 1 ;
+ char*** p ;
+ U32 i, j ;
+ U32 total_allocated_size = 0 ;
+
+ //allocate space for p ;
+ if(!(p = ::new char**[times]) || !(*p = ::new char*[times * levels]))
+ {
+ llerrs << "memory initialization for p failed" << llendl ;
+ }
+
+ //init
+ for(i = 0 ; i < times; i++)
+ {
+ p[i] = *p + i * levels ;
+ for(j = 0 ; j < levels; j++)
+ {
+ p[i][j] = NULL ;
+ }
+ }
+
+ //allocation
+ U32 size ;
+ for(i = 0 ; i < times ; i++)
+ {
+ for(j = 0 ; j < levels; j++)
+ {
+ size = min_size + j * stride ;
+ p[i][j] = sPool->allocate(size) ;
+
+ total_allocated_size+= size ;
+
+ *(U32*)p[i][j] = i ;
+ *((U32*)p[i][j] + 1) = j ;
+ //p[i][j][size - 1] = '\0' ; //access the last element to verify the success of the allocation.
+
+ //randomly release memory
+ if(random_deletion)
+ {
+ S32 k = rand() % levels ;
+
+ if(p[i][k])
+ {
+ llassert_always(*(U32*)p[i][k] == i && *((U32*)p[i][k] + 1) == k) ;
+ sPool->free(p[i][k]) ;
+ total_allocated_size -= min_size + k * stride ;
+ p[i][k] = NULL ;
+ }
+ }
+ }
+ }
+
+ //output pool allocation statistics
+ if(output_statistics)
+ {
+ }
+
+ //release all memory allocations
+ for(i = 0 ; i < times; i++)
+ {
+ for(j = 0 ; j < levels; j++)
+ {
+ if(p[i][j])
+ {
+ llassert_always(*(U32*)p[i][j] == i && *((U32*)p[i][j] + 1) == j) ;
+ sPool->free(p[i][j]) ;
+ total_allocated_size -= min_size + j * stride ;
+ p[i][j] = NULL ;
+ }
+ }
+ }
+
+ ::delete[] *p ;
+ ::delete[] p ;
+}
+
+void LLPrivateMemoryPoolTester::testAndTime(U32 size, U32 times)
+{
+ LLTimer timer ;
+
+ llinfos << " -**********************- " << llendl ;
+ llinfos << "test size: " << size << " test times: " << times << llendl ;
+
+ timer.reset() ;
+ char** p = new char*[times] ;
+
+ //using the customized memory pool
+ //allocation
+ for(U32 i = 0 ; i < times; i++)
+ {
+ p[i] = sPool->allocate(size) ;
+ if(!p[i])
+ {
+ llerrs << "allocation failed" << llendl ;
+ }
+ }
+ //de-allocation
+ for(U32 i = 0 ; i < times; i++)
+ {
+ sPool->free(p[i]) ;
+ p[i] = NULL ;
+ }
+ llinfos << "time spent using customized memory pool: " << timer.getElapsedTimeF32() << llendl ;
+
+ timer.reset() ;
+
+ //using the standard allocator/de-allocator:
+ //allocation
+ for(U32 i = 0 ; i < times; i++)
+ {
+ p[i] = ::new char[size] ;
+ if(!p[i])
+ {
+ llerrs << "allocation failed" << llendl ;
+ }
+ }
+ //de-allocation
+ for(U32 i = 0 ; i < times; i++)
+ {
+ ::delete[] p[i] ;
+ p[i] = NULL ;
+ }
+ llinfos << "time spent using standard allocator/de-allocator: " << timer.getElapsedTimeF32() << llendl ;
+
+ delete[] p;
+}
+
+void LLPrivateMemoryPoolTester::correctnessTest()
+{
+ //try many different sized allocation, and all kinds of edge cases, access the allocated memory
+ //to see if allocation is right.
+
+ //edge case
+ char* p = sPool->allocate(0) ;
+ sPool->free(p) ;
+
+ //small sized
+ // [8 bytes, 2KB), each asks for 256 allocations and deallocations
+ test(8, 2040, 8, 256, true, true) ;
+
+ //medium sized
+ //[2KB, 512KB), each asks for 16 allocations and deallocations
+ test(2048, 512 * 1024 - 2048, 2048, 16, true, true) ;
+
+ //large sized
+ //[512KB, 4MB], each asks for 8 allocations and deallocations
+ test(512 * 1024, 4 * 1024 * 1024, 64 * 1024, 6, true, true) ;
+}
+
+void LLPrivateMemoryPoolTester::performanceTest()
+{
+ U32 test_size[3] = {768, 3* 1024, 3* 1024 * 1024};
+
+ //small sized
+ testAndTime(test_size[0], 8) ;
+
+ //medium sized
+ testAndTime(test_size[1], 8) ;
+
+ //large sized
+ testAndTime(test_size[2], 8) ;
+}
+
+void LLPrivateMemoryPoolTester::fragmentationtest()
+{
+ //for internal fragmentation statistics:
+ //every time when asking for a new chunk during correctness test, and performance test,
+ //print out the chunk usage statistices.
+}
+
+//--------------------------------------------------------------------
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 11406f59b0..4474df6f86 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -27,7 +27,6 @@
#define LLMEMORY_H
#include "llmemtype.h"
-
extern S32 gTotalDAlloc;
extern S32 gTotalDAUse;
extern S32 gDACount;
@@ -45,8 +44,24 @@ 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 S32 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;
};
//----------------------------------------------------------------------------
@@ -93,6 +108,272 @@ private:
//----------------------------------------------------------------------------
+
+//
+//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 free(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 U32 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 free(void* addr) ;
+
+ const 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 ;
+
+ LLMemoryChunk* mHashNext ;
+ } ;
+
+private:
+ LLPrivateMemoryPool(U32 max_size, bool threaded) ;
+ ~LLPrivateMemoryPool() ;
+
+public:
+ char *allocate(U32 size) ;
+ void free(void* addr) ;
+
+ void dump() ;
+ U32 getTotalAllocatedSize() ;
+ U32 getTotalReservedSize() {return mReservedPoolSize;}
+
+private:
+ void lock() ;
+ void unlock() ;
+ S32 getChunkIndex(U32 size) ;
+ LLMemoryChunk* addChunk(S32 chunk_index) ;
+ void 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.
+ };
+
+private:
+ LLMutex* mMutexp ;
+ U32 mMaxPoolSize;
+ U32 mReservedPoolSize ;
+
+ LLMemoryChunk* mChunkList[SUPER_ALLOCATION] ; //all memory chunks reserved by this pool, sorted by address
+ std::vector<LLMemoryChunk*> mChunkHashList ;
+ U16 mNumOfChunks ;
+ U16 mHashFactor ;
+};
+
+class LL_COMMON_API LLPrivateMemoryPoolManager
+{
+private:
+ LLPrivateMemoryPoolManager() ;
+ ~LLPrivateMemoryPoolManager() ;
+
+public:
+ static LLPrivateMemoryPoolManager* getInstance() ;
+ static void destroyClass() ;
+
+ LLPrivateMemoryPool* newPool(U32 max_size, bool threaded) ;
+ void deletePool(LLPrivateMemoryPool* pool) ;
+
+private:
+ static LLPrivateMemoryPoolManager* sInstance ;
+ std::set<LLPrivateMemoryPool*> mPoolList ;
+
+public:
+ //debug and statistics info.
+ void updateStatistics() ;
+
+ U32 mTotalReservedSize ;
+ U32 mTotalAllocatedSize ;
+};
+
+//
+//the below singleton is used to test the private memory pool.
+//
+class LL_COMMON_API LLPrivateMemoryPoolTester
+{
+private:
+ LLPrivateMemoryPoolTester() ;
+ ~LLPrivateMemoryPoolTester() ;
+
+public:
+ static LLPrivateMemoryPoolTester* getInstance() ;
+ static void destroy() ;
+
+ void run(bool threaded) ;
+
+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) ;
+
+public:
+ void* operator new(size_t size)
+ {
+ return (void*)sPool->allocate(size) ;
+ }
+ void operator delete(void* addr)
+ {
+ sPool->free(addr) ;
+ }
+ void* operator new[](size_t size)
+ {
+ return (void*)sPool->allocate(size) ;
+ }
+ void operator delete[](void* addr)
+ {
+ sPool->free(addr) ;
+ }
+
+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
// LLRefCount moved to llrefcount.h
// LLPointer moved to llpointer.h
diff --git a/indra/llcommon/llmetricperformancetester.h b/indra/llcommon/llmetricperformancetester.h
index 925010ac96..1372f48dcf 100644
--- a/indra/llcommon/llmetricperformancetester.h
+++ b/indra/llcommon/llmetricperformancetester.h
@@ -27,7 +27,7 @@
#ifndef LL_METRICPERFORMANCETESTER_H
#define LL_METRICPERFORMANCETESTER_H
-const std::string DEFAULT_METRIC_NAME("metric");
+char const* const DEFAULT_METRIC_NAME = "metric";
/**
* @class LLMetricPerformanceTesterBasic
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 10cdc7087b..7968e53c13 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -636,22 +636,20 @@ U32 LLMemoryInfo::getPhysicalMemoryClamped() const
}
//static
-void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb)
+U32 LLMemoryInfo::getAvailableMemoryKB()
{
#if LL_WINDOWS
MEMORYSTATUSEX state;
state.dwLength = sizeof(state);
GlobalMemoryStatusEx(&state);
- avail_physical_mem_kb = (U32)(state.ullAvailPhys/1024) ;
- avail_virtual_mem_kb = (U32)(state.ullAvailVirtual/1024) ;
+ return (U32)(state.ullAvailPhys/1024) ;
#else
//do not know how to collect available memory info for other systems.
//leave it blank here for now.
- avail_physical_mem_kb = -1 ;
- avail_virtual_mem_kb = -1 ;
+ return -1;
#endif
}
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index 41a4f25000..580eee4e8d 100644
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -116,7 +116,7 @@ public:
U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
//get the available memory infomation in KiloBytes.
- static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb);
+ static U32 getAvailableMemoryKB();
};
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 7d5afe92dc..7703132d90 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -28,7 +28,7 @@
#define LL_LLVERSIONVIEWER_H
const S32 LL_VERSION_MAJOR = 2;
-const S32 LL_VERSION_MINOR = 6;
+const S32 LL_VERSION_MINOR = 7;
const S32 LL_VERSION_PATCH = 0;
const S32 LL_VERSION_BUILD = 0;
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index f4399d4ed4..706231307d 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -39,6 +39,7 @@
#include "llimagepng.h"
#include "llimagedxt.h"
#include "llimageworker.h"
+#include "llmemory.h"
//---------------------------------------------------------------------------
// LLImage
@@ -47,11 +48,14 @@
//static
std::string LLImage::sLastErrorMessage;
LLMutex* LLImage::sMutex = NULL;
+LLPrivateMemoryPool* LLImageBase::sPrivatePoolp = NULL ;
//static
void LLImage::initClass()
{
sMutex = new LLMutex;
+
+ LLImageBase::createPrivatePool() ;
}
//static
@@ -59,6 +63,8 @@ void LLImage::cleanupClass()
{
delete sMutex;
sMutex = NULL;
+
+ LLImageBase::destroyPrivatePool() ;
}
//static
@@ -97,6 +103,53 @@ LLImageBase::~LLImageBase()
deleteData(); // virtual
}
+//static
+void LLImageBase::createPrivatePool()
+{
+ const U32 MAX_POOL_SIZE = 512 * 1024 * 1024 ; //512 MB
+
+ if(!sPrivatePoolp)
+ {
+ sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(MAX_POOL_SIZE, true) ;
+ }
+}
+
+//static
+void LLImageBase::destroyPrivatePool()
+{
+ if(sPrivatePoolp)
+ {
+ LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp) ;
+ sPrivatePoolp = NULL ;
+ }
+}
+
+//static
+char* LLImageBase::allocateMemory(S32 size)
+{
+ if(sPrivatePoolp)
+ {
+ return sPrivatePoolp->allocate(size) ;
+ }
+ else
+ {
+ return new char[size];
+ }
+}
+
+//static
+void LLImageBase::deleteMemory(void* p)
+{
+ if(sPrivatePoolp)
+ {
+ sPrivatePoolp->free(p) ;
+ }
+ else
+ {
+ delete[] (char*)p ;
+ }
+}
+
// virtual
void LLImageBase::dump()
{
@@ -130,7 +183,7 @@ void LLImageBase::sanityCheck()
// virtual
void LLImageBase::deleteData()
{
- delete[] mData;
+ deleteMemory(mData) ;
mData = NULL;
mDataSize = 0;
}
@@ -167,7 +220,7 @@ U8* LLImageBase::allocateData(S32 size)
{
deleteData(); // virtual
mBadBufferAllocation = false ;
- mData = new U8[size];
+ mData = (U8*)allocateMemory(size);
if (!mData)
{
llwarns << "allocate image data: " << size << llendl;
@@ -185,7 +238,7 @@ U8* LLImageBase::allocateData(S32 size)
U8* LLImageBase::reallocateData(S32 size)
{
LLMemType mt1(mMemType);
- U8 *new_datap = new U8[size];
+ U8 *new_datap = (U8*)allocateMemory(size);
if (!new_datap)
{
llwarns << "Out of memory in LLImageBase::reallocateData" << llendl;
@@ -195,7 +248,7 @@ U8* LLImageBase::reallocateData(S32 size)
{
S32 bytes = llmin(mDataSize, size);
memcpy(new_datap, mData, bytes); /* Flawfinder: ignore */
- delete[] mData;
+ deleteMemory(mData) ;
}
mData = new_datap;
mDataSize = size;
@@ -341,6 +394,7 @@ 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(mMemType);
@@ -361,6 +415,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)
@@ -830,6 +885,7 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
}
}
+#if 0
//scale down image by not blending a pixel with its neighbors.
BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height)
{
@@ -853,7 +909,7 @@ BOOL LLImageRaw::scaleDownWithoutBlending( S32 new_width, S32 new_height)
ratio_x -= 1.0f ;
ratio_y -= 1.0f ;
- U8* new_data = new U8[new_data_size] ;
+ U8* new_data = allocateMemory(new_data_size) ;
llassert_always(new_data != NULL) ;
U8* old_data = getData() ;
@@ -875,6 +931,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 )
{
@@ -1527,6 +1584,7 @@ void LLImageFormatted::setData(U8 *data, S32 size)
{
deleteData();
setDataAndSize(data, size); // Access private LLImageBase members
+
sGlobalFormattedMemory += getDataSize();
}
}
@@ -1545,7 +1603,7 @@ void LLImageFormatted::appendData(U8 *data, S32 size)
S32 newsize = cursize + size;
reallocateData(newsize);
memcpy(getData() + cursize, data, size);
- delete[] data;
+ deleteMemory(data);
}
}
}
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 825b9aab1a..ab20ccda9e 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -29,7 +29,6 @@
#include "lluuid.h"
#include "llstring.h"
-//#include "llmemory.h"
#include "llthread.h"
#include "llmemtype.h"
@@ -56,6 +55,7 @@ const S32 MAX_IMG_PACKET_SIZE = 1000;
class LLImageFormatted;
class LLImageRaw;
class LLColor4U;
+class LLPrivateMemoryPool;
typedef enum e_image_codec
{
@@ -127,7 +127,7 @@ public:
protected:
// special accessor to allow direct setting of mData and mDataSize by LLImageFormatted
- void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; }
+ void setDataAndSize(U8 *data, S32 size) { mData = data; mDataSize = size; }
public:
static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels);
@@ -138,6 +138,11 @@ public:
static EImageCodec getCodecFromExtension(const std::string& exten);
+ static void createPrivatePool() ;
+ static void destroyPrivatePool() ;
+ static char* allocateMemory(S32 size) ;
+ static void deleteMemory(void* p) ;
+
private:
U8 *mData;
S32 mDataSize;
@@ -149,6 +154,8 @@ private:
bool mBadBufferAllocation ;
bool mAllowOverSize ;
+
+ static LLPrivateMemoryPool* sPrivatePoolp ;
public:
LLMemType::DeclareMemType& mMemType; // debug
};
@@ -172,7 +179,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);
@@ -184,7 +191,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 );
diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp
index 4bd3efddaa..81be09a412 100644
--- a/indra/llimage/llimagedxt.cpp
+++ b/indra/llimage/llimagedxt.cpp
@@ -429,7 +429,7 @@ bool LLImageDXT::convertToDXR()
S32 nmips = calcNumMips(width,height);
S32 total_bytes = getDataSize();
U8* olddata = getData();
- U8* newdata = new U8[total_bytes];
+ U8* newdata = (U8*)allocateMemory(total_bytes);
if (!newdata)
{
llerrs << "Out of memory in LLImageDXT::convertToDXR()" << llendl;
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 5f488a6764..1bdcba6eb5 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -372,14 +372,14 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
}
else
{
- U8 *data = new U8[file_size];
+ U8 *data = (U8*)allocateMemory(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;
+ deleteMemory(data);
setLastError("Unable to read entire file");
res = FALSE;
}
diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp
index bad4d00fd6..687c1a7d45 100644
--- a/indra/llmath/llcamera.cpp
+++ b/indra/llmath/llcamera.cpp
@@ -703,6 +703,7 @@ void LLCamera::calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom)
mLocalPlanes[PLANE_BOTTOM].setVec( a, c, b);
//calculate center and radius squared of frustum in world absolute coordinates
+ static LLVector3 const X_AXIS(1.f, 0.f, 0.f);
mFrustCenter = X_AXIS*mFarPlane*0.5f;
mFrustCenter = transformToAbsolute(mFrustCenter);
mFrustRadiusSquared = mFarPlane*0.5f;
diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h
index 922d6f9fac..531144db39 100644
--- a/indra/llmath/llcamera.h
+++ b/indra/llmath/llcamera.h
@@ -50,15 +50,6 @@ const F32 MIN_FAR_PLANE = 0.2f;
static const F32 MIN_FIELD_OF_VIEW = 5.0f * DEG_TO_RAD;
static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD;
-static const LLVector3 X_AXIS(1.f,0.f,0.f);
-static const LLVector3 Y_AXIS(0.f,1.f,0.f);
-static const LLVector3 Z_AXIS(0.f,0.f,1.f);
-
-static const LLVector3 NEG_X_AXIS(-1.f,0.f,0.f);
-static const LLVector3 NEG_Y_AXIS(0.f,-1.f,0.f);
-static const LLVector3 NEG_Z_AXIS(0.f,0.f,-1.f);
-
-
// An LLCamera is an LLCoorFrame with a view frustum.
// This means that it has several methods for moving it around
// that are inherited from the LLCoordFrame() class :
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 595c470a19..26a20cede8 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -64,9 +64,10 @@ LLPluginClassMedia::~LLPluginClassMedia()
reset();
}
-bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug)
+bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
{
LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
+ LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
mPlugin = new LLPluginProcessParent(this);
@@ -77,7 +78,7 @@ bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::s
message.setValue("target", mTarget);
sendMessage(message);
- mPlugin->init(launcher_filename, plugin_filename, debug);
+ mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
return true;
}
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index c826e13c40..618e928a08 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -45,6 +45,7 @@ public:
// local initialization, called by the media manager when creating a source
virtual bool init(const std::string &launcher_filename,
+ const std::string &plugin_dir,
const std::string &plugin_filename,
bool debug);
diff --git a/indra/llplugin/llplugininstance.cpp b/indra/llplugin/llplugininstance.cpp
index 9c9909a017..e8efb233ff 100644
--- a/indra/llplugin/llplugininstance.cpp
+++ b/indra/llplugin/llplugininstance.cpp
@@ -31,6 +31,10 @@
#include "llplugininstance.h"
#include "llthread.h" // Needed for LLThread::tldata().mRootPool
+#if LL_WINDOWS
+#include "direct.h" // needed for _chdir()
+#endif
+
/** Virtual destructor. */
LLPluginInstanceMessageListener::~LLPluginInstanceMessageListener()
{
@@ -73,10 +77,24 @@ LLPluginInstance::~LLPluginInstance()
* @param[in] plugin_file Name of plugin dll/dylib/so. TODO:DOC is this correct? see .h
* @return 0 if successful, APR error code or error code from the plugin's init function on failure.
*/
-int LLPluginInstance::load(std::string &plugin_file)
+int LLPluginInstance::load(const std::string& plugin_dir, std::string &plugin_file)
{
pluginInitFunction init_function = NULL;
+ if ( plugin_dir.length() )
+ {
+#if LL_WINDOWS
+ // VWR-21275:
+ // *SOME* Windows systems fail to load the Qt plugins if the current working
+ // directory is not the same as the directory with the Qt DLLs in.
+ // This should not cause any run time issues since we are changing the cwd for the
+ // plugin shell process and not the viewer.
+ // Changing back to the previous directory is not necessary since the plugin shell
+ // quits once the plugin exits.
+ _chdir( plugin_dir.c_str() );
+#endif
+ };
+
int result = apr_dso_load(&mDSOHandle,
plugin_file.c_str(),
mDSOHandlePool());
diff --git a/indra/llplugin/llplugininstance.h b/indra/llplugin/llplugininstance.h
index 1c3898e2e7..3c1cd12546 100644
--- a/indra/llplugin/llplugininstance.h
+++ b/indra/llplugin/llplugininstance.h
@@ -57,7 +57,7 @@ public:
// Load a plugin dll/dylib/so
// Returns 0 if successful, APR error code or error code returned from the plugin's init function on failure.
- int load(std::string &plugin_file);
+ int load(const std::string& plugin_dir, std::string &plugin_file);
// Sends a message to the plugin.
void sendMessage(const std::string &message);
diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp
index 2fa5dcdd01..a7cdf14f0d 100644
--- a/indra/llplugin/llpluginprocesschild.cpp
+++ b/indra/llplugin/llpluginprocesschild.cpp
@@ -139,7 +139,7 @@ void LLPluginProcessChild::idle(void)
if(!mPluginFile.empty())
{
mInstance = new LLPluginInstance(this);
- if(mInstance->load(mPluginFile) == 0)
+ if(mInstance->load(mPluginDir, mPluginFile) == 0)
{
mHeartbeat.start();
mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS);
@@ -348,6 +348,7 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message)
if(message_name == "load_plugin")
{
mPluginFile = parsed.getValue("file");
+ mPluginDir = parsed.getValue("dir");
}
else if(message_name == "shm_add")
{
diff --git a/indra/llplugin/llpluginprocesschild.h b/indra/llplugin/llpluginprocesschild.h
index 22ff403ad6..a9d6794e40 100644
--- a/indra/llplugin/llpluginprocesschild.h
+++ b/indra/llplugin/llpluginprocesschild.h
@@ -92,6 +92,7 @@ private:
LLSocket::ptr_t mSocket;
std::string mPluginFile;
+ std::string mPluginDir;
LLPluginInstance *mInstance;
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index eaf7ec4bf3..8b7e8635cf 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -159,10 +159,11 @@ void LLPluginProcessParent::errorState(void)
setState(STATE_ERROR);
}
-void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug)
+void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
{
mProcess.setExecutable(launcher_filename);
mPluginFile = plugin_filename;
+ mPluginDir = plugin_dir;
mCPUUsage = 0.0f;
mDebug = debug;
setState(STATE_INITIALIZED);
@@ -431,6 +432,7 @@ void LLPluginProcessParent::idle(void)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin");
message.setValue("file", mPluginFile);
+ message.setValue("dir", mPluginDir);
sendMessage(message);
}
diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h
index 6beeb64c7e..29995647d5 100644
--- a/indra/llplugin/llpluginprocessparent.h
+++ b/indra/llplugin/llpluginprocessparent.h
@@ -57,6 +57,7 @@ public:
~LLPluginProcessParent();
void init(const std::string &launcher_filename,
+ const std::string &plugin_dir,
const std::string &plugin_filename,
bool debug);
@@ -151,6 +152,7 @@ private:
LLProcessLauncher mProcess;
std::string mPluginFile;
+ std::string mPluginDir;
LLPluginProcessParentOwner *mOwner;
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 02160b09c4..03befe6818 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -33,6 +33,7 @@
#include "llglheaders.h"
#include "llmemtype.h"
#include "llrender.h"
+#include "llmemory.h"
//============================================================================
@@ -47,6 +48,7 @@ U32 LLVertexBuffer::sSetCount = 0;
S32 LLVertexBuffer::sCount = 0;
S32 LLVertexBuffer::sGLCount = 0;
S32 LLVertexBuffer::sMappedCount = 0;
+BOOL LLVertexBuffer::sDisableVBOMapping = FALSE ;
BOOL LLVertexBuffer::sEnableVBOs = TRUE;
U32 LLVertexBuffer::sGLRenderBuffer = 0;
U32 LLVertexBuffer::sGLRenderIndices = 0;
@@ -212,6 +214,11 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
{
llassert(mRequestedNumVerts >= 0);
+ if(mDirty)
+ {
+ postUpdate() ;
+ }
+
if (start >= (U32) mRequestedNumVerts ||
end >= (U32) mRequestedNumVerts)
{
@@ -251,6 +258,12 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
{
llassert(mRequestedNumIndices >= 0);
+
+ if(mDirty)
+ {
+ postUpdate() ;
+ }
+
if (indices_offset >= (U32) mRequestedNumIndices ||
indices_offset + count > (U32) mRequestedNumIndices)
{
@@ -282,6 +295,12 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
{
llassert(mRequestedNumVerts >= 0);
+
+ if(mDirty)
+ {
+ postUpdate() ;
+ }
+
if (first >= (U32) mRequestedNumVerts ||
first + count > (U32) mRequestedNumVerts)
{
@@ -305,9 +324,10 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
}
//static
-void LLVertexBuffer::initClass(bool use_vbo)
+void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
{
sEnableVBOs = use_vbo;
+ sDisableVBOMapping = no_vbo_mapping ;
LLGLNamePool::registerPool(&sDynamicVBOPool);
LLGLNamePool::registerPool(&sDynamicIBOPool);
LLGLNamePool::registerPool(&sStreamVBOPool);
@@ -369,7 +389,8 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
mFilthy(FALSE),
mEmpty(TRUE),
mResized(FALSE),
- mDynamicSize(FALSE)
+ mDynamicSize(FALSE),
+ mDirty(FALSE)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
if (!sEnableVBOs)
@@ -567,6 +588,8 @@ void LLVertexBuffer::destroyGLBuffer()
{
if (useVBOs())
{
+ freeClientBuffer() ;
+
if (mMappedData || mMappedIndexData)
{
llerrs << "Vertex buffer destroyed while mapped!" << llendl;
@@ -594,11 +617,13 @@ void LLVertexBuffer::destroyGLIndices()
{
if (useVBOs())
{
+ freeClientBuffer() ;
+
if (mMappedData || mMappedIndexData)
{
llerrs << "Vertex buffer destroyed while mapped." << llendl;
}
- releaseIndices();
+ releaseIndices();
}
else
{
@@ -799,6 +824,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
if (mResized && useVBOs())
{
+ freeClientBuffer() ;
setBuffer(0);
}
}
@@ -822,6 +848,60 @@ BOOL LLVertexBuffer::useVBOs() const
}
//----------------------------------------------------------------------------
+void LLVertexBuffer::freeClientBuffer()
+{
+ if(useVBOs() && sDisableVBOMapping && (mMappedData || mMappedIndexData))
+ {
+ delete[] mMappedData ;
+ delete[] mMappedIndexData ;
+ mMappedData = NULL ;
+ mMappedIndexData = NULL ;
+ }
+}
+
+void LLVertexBuffer::preUpdate()
+{
+ if(!useVBOs() || !sDisableVBOMapping)
+ {
+ return ;
+ }
+
+ if(!mMappedData)
+ {
+ U32 size = getSize() ;
+ mMappedData = new U8[size];
+ memset(mMappedData, 0, size);
+ }
+
+ if(!mMappedIndexData)
+ {
+ U32 size = getIndicesSize();
+ mMappedIndexData = new U8[size];
+ memset(mMappedIndexData, 0, size);
+ }
+
+ mDirty = TRUE ;
+}
+
+void LLVertexBuffer::postUpdate() const
+{
+ if(!useVBOs() || !sDisableVBOMapping)
+ {
+ return ;
+ }
+
+ llassert_always(mMappedData && mMappedIndexData) ;
+
+ //release the existing buffers
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, 0, NULL, mUsage);
+ glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, NULL, mUsage);
+
+ //update to the new buffers
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), mMappedData, mUsage);
+ glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), mMappedIndexData, mUsage);
+
+ mDirty = FALSE ;
+}
// Map for data access
U8* LLVertexBuffer::mapBuffer(S32 access)
@@ -836,6 +916,12 @@ U8* LLVertexBuffer::mapBuffer(S32 access)
llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl;
}
+ if(useVBOs() && sDisableVBOMapping)
+ {
+ preUpdate() ;
+ return mMappedData ;
+ }
+
if (!mLocked && useVBOs())
{
{
@@ -857,11 +943,8 @@ U8* LLVertexBuffer::mapBuffer(S32 access)
log_glerror();
//check the availability of memory
- U32 avail_phy_mem, avail_vir_mem;
- LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ;
- llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ;
- llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl;
-
+ LLMemory::logMemoryInfo(TRUE) ;
+
//--------------------
//print out more debug info before crash
llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
@@ -884,6 +967,7 @@ U8* LLVertexBuffer::mapBuffer(S32 access)
if (!mMappedIndexData)
{
log_glerror();
+ LLMemory::logMemoryInfo(TRUE) ;
GLint buff;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
@@ -906,7 +990,11 @@ void LLVertexBuffer::unmapBuffer()
LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER);
if (mMappedData || mMappedIndexData)
{
- if (useVBOs() && mLocked)
+ if(sDisableVBOMapping && useVBOs())
+ {
+ return ;
+ }
+ else if (useVBOs() && mLocked)
{
stop_glerror();
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
@@ -1152,13 +1240,13 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
}
}
- if (mGLBuffer)
+ if (mGLBuffer && !sDisableVBOMapping)
{
stop_glerror();
glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), NULL, mUsage);
stop_glerror();
}
- if (mGLIndices)
+ if (mGLIndices && !sDisableVBOMapping)
{
stop_glerror();
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), NULL, mUsage);
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 94fa790957..18d50c87bb 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -80,7 +80,7 @@ public:
static BOOL sUseStreamDraw;
- static void initClass(bool use_vbo);
+ static void initClass(bool use_vbo, bool no_vbo_mapping);
static void cleanupClass();
static void setupClientArrays(U32 data_mask);
static void clientCopy(F64 max_time = 0.005); //copy data from client to GL
@@ -152,6 +152,11 @@ public:
void allocateBuffer(S32 nverts, S32 nindices, bool create);
virtual void resizeBuffer(S32 newnverts, S32 newnindices);
+ void preUpdate() ;
+ void postUpdate() const ;
+ void freeClientBuffer() ;
+ void dirty() {mDirty = TRUE;}
+
// Only call each getVertexPointer, etc, once before calling unmapBuffer()
// call unmapBuffer() after calls to getXXXStrider() before any cals to setBuffer()
// example:
@@ -216,6 +221,7 @@ protected:
S32 mOffsets[TYPE_MAX];
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)
+ mutable BOOL mDirty ;
class DirtyRegion
{
@@ -240,13 +246,14 @@ public:
static std::vector<U32> sDeleteList;
typedef std::list<LLVertexBuffer*> buffer_list_t;
+ static BOOL sDisableVBOMapping; //disable glMapBufferARB
static BOOL sEnableVBOs;
+ static BOOL sVBOActive;
+ static BOOL sIBOActive;
static S32 sTypeOffsets[TYPE_MAX];
static U32 sGLMode[LLRender::NUM_MODES];
static U32 sGLRenderBuffer;
- static U32 sGLRenderIndices;
- static BOOL sVBOActive;
- static BOOL sIBOActive;
+ static U32 sGLRenderIndices;
static U32 sLastMask;
static U32 sAllocatedBytes;
static U32 sBindCount;
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index 93975579cc..70749b8ee9 100644
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -385,7 +385,8 @@ class LLCachedControl
{
public:
LLCachedControl(LLControlGroup& group,
- const std::string& name,
+ const std::string& name,
+
const T& default_value,
const std::string& comment = "Declared In Code")
{
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 6630d8f400..fac4cfbef9 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1841,6 +1841,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>DebugShowPrivateMem</key>
+ <map>
+ <key>Comment</key>
+ <string>Show Private Mem Info</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>DebugShowRenderInfo</key>
<map>
<key>Comment</key>
@@ -5220,6 +5231,17 @@
<key>Value</key>
<real>48.0</real>
</map>
+ <key>MaxHeapSize</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum heap size (GB)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.6</real>
+ </map>
<key>MaxSelectDistance</key>
<map>
<key>Comment</key>
@@ -5341,6 +5363,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>MemeoyFailurePreventionEnabled</key>
+ <map>
+ <key>Comment</key>
+ <string>If set, the viewer will quit to avoid crash when memory failure happens</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>MemoryLogFrequency</key>
<map>
<key>Comment</key>
@@ -8451,6 +8484,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>RenderVBOMappingDisable</key>
+ <map>
+ <key>Comment</key>
+ <string>Disable VBO glMapBufferARB</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>RenderUseStreamVBO</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 1f76e2af40..e29588214d 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -619,7 +619,7 @@ LLAppViewer::~LLAppViewer()
}
bool LLAppViewer::init()
-{
+{
//
// Start of the application
//
@@ -647,6 +647,9 @@ bool LLAppViewer::init()
if (!initConfiguration())
return false;
+ //set the max heap size.
+ initMaxHeapSize() ;
+
// write Google Breakpad minidump files to our log directory
std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
logdir += gDirUtilp->getDirDelimiter();
@@ -996,9 +999,97 @@ bool LLAppViewer::init()
LLAgentLanguage::init();
+ return true;
+}
+void LLAppViewer::initMaxHeapSize()
+{
+ //set the max heap size.
+ //here is some info regarding to the max heap size:
+ //------------------------------------------------------------------------------------------
+ // OS | setting | SL address bits | max manageable memory space | max heap size
+ // Win 32 | default | 32-bit | 2GB | < 1.7GB
+ // Win 32 | /3G | 32-bit | 3GB | < 1.7GB or 2.7GB
+ //Linux 32 | default | 32-bit | 3GB | < 2.7GB
+ //Linux 32 |HUGEMEM | 32-bit | 4GB | < 3.7GB
+ //64-bit OS |default | 32-bit | 4GB | < 3.7GB
+ //64-bit OS |default | 64-bit | N/A (> 4GB) | N/A (> 4GB)
+ //------------------------------------------------------------------------------------------
+ //currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB.
+
+ //F32 max_heap_size_gb = llmin(1.6f, (F32)gSavedSettings.getF32("MaxHeapSize")) ;
+ F32 max_heap_size_gb = gSavedSettings.getF32("MaxHeapSize") ;
+ BOOL enable_mem_failure_prevention = (BOOL)gSavedSettings.getBOOL("MemeoyFailurePreventionEnabled") ;
+
+ LLMemory::initMaxHeapSizeGB(max_heap_size_gb, enable_mem_failure_prevention) ;
+}
- return true;
+void LLAppViewer::checkMemory()
+{
+ const static F32 MEMORY_CHECK_INTERVAL = 1.0f ; //second
+ //const static F32 MAX_QUIT_WAIT_TIME = 30.0f ; //seconds
+ const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB
+ //static F32 force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ;
+ static void* last_reserved_address = NULL ;
+
+ if(MEMORY_CHECK_INTERVAL > mMemCheckTimer.getElapsedTimeF32())
+ {
+ return ;
+ }
+ mMemCheckTimer.reset() ;
+
+ if(gGLManager.mDebugGPU)
+ {
+ //update the availability of memory
+ LLMemory::updateMemoryInfo() ;
+ }
+
+ //check the virtual address space fragmentation
+ if(!last_reserved_address)
+ {
+ last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+ }
+ else
+ {
+ last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+ if(!last_reserved_address) //failed, try once more
+ {
+ last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+ }
+ }
+
+ S32 is_low = !last_reserved_address || LLMemory::isMemoryPoolLow() ;
+
+ //if(is_low < 0) //to force quit
+ //{
+ // if(force_quit_timer > MAX_QUIT_WAIT_TIME) //just hit the limit for the first time
+ // {
+ // //send out the notification to tell the viewer is about to quit in 30 seconds.
+ // LLNotification::Params params("ForceQuitDueToLowMemory");
+ // LLNotifications::instance().add(params);
+
+ // force_quit_timer = MAX_QUIT_WAIT_TIME - MEMORY_CHECK_INTERVAL ;
+ // }
+ // else
+ // {
+ // force_quit_timer -= MEMORY_CHECK_INTERVAL ;
+ // if(force_quit_timer < 0.f)
+ // {
+ // forceQuit() ; //quit
+ // }
+ // }
+ //}
+ //else
+ //{
+ // force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ;
+ //}
+
+ LLPipeline::throttleNewMemoryAllocation(!is_low ? FALSE : TRUE) ;
+
+ if(is_low)
+ {
+ LLMemory::logMemoryInfo() ;
+ }
}
static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages");
@@ -1036,7 +1127,6 @@ bool LLAppViewer::mainLoop()
LLVoiceClient::getInstance()->init(gServicePump);
LLTimer frameTimer,idleTimer;
LLTimer debugTime;
- LLFrameTimer memCheckTimer;
LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
joystick->setNeedsReset(true);
@@ -1047,7 +1137,9 @@ bool LLAppViewer::mainLoop()
// point of posting.
LLSD newFrame;
- const F32 memory_check_interval = 1.0f ; //second
+ //LLPrivateMemoryPoolTester::getInstance()->run(false) ;
+ //LLPrivateMemoryPoolTester::getInstance()->run(true) ;
+ //LLPrivateMemoryPoolTester::destroy() ;
// Handle messages
while (!LLApp::isExiting())
@@ -1058,18 +1150,8 @@ bool LLAppViewer::mainLoop()
llclearcallstacks;
//check memory availability information
- {
- if(memory_check_interval < memCheckTimer.getElapsedTimeF32())
- {
- memCheckTimer.reset() ;
-
- //update the availability of memory
- LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ;
- }
- llcallstacks << "Available physical mem(KB): " << mAvailPhysicalMemInKB << llcallstacksendl ;
- llcallstacks << "Available virtual mem(KB): " << mAvailVirtualMemInKB << llcallstacksendl ;
- }
-
+ checkMemory() ;
+
try
{
pingMainloopTimeout("Main:MiscNativeWindowEvents");
@@ -1233,7 +1315,7 @@ bool LLAppViewer::mainLoop()
idleTimer.reset();
bool is_slow = (frameTimer.getElapsedTimeF64() > FRAME_SLOW_THRESHOLD) ;
S32 total_work_pending = 0;
- S32 total_io_pending = 0;
+ S32 total_io_pending = 0;
while(!is_slow)//do not unpause threads if the frame rates are very low.
{
S32 work_pending = 0;
@@ -1300,15 +1382,7 @@ bool LLAppViewer::mainLoop()
}
catch(std::bad_alloc)
{
- {
- llinfos << "Availabe physical memory(KB) at the beginning of the frame: " << mAvailPhysicalMemInKB << llendl ;
- llinfos << "Availabe virtual memory(KB) at the beginning of the frame: " << mAvailVirtualMemInKB << llendl ;
-
- LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ;
-
- llinfos << "Current availabe physical memory(KB): " << mAvailPhysicalMemInKB << llendl ;
- llinfos << "Current availabe virtual memory(KB): " << mAvailVirtualMemInKB << llendl ;
- }
+ LLMemory::logMemoryInfo(TRUE) ;
//stop memory leaking simulation
LLFloaterMemLeak* mem_leak_instance =
@@ -1777,6 +1851,9 @@ bool LLAppViewer::cleanup()
LLMainLoopRepeater::instance().stop();
+ //release all private memory pools.
+ LLPrivateMemoryPoolManager::destroyClass() ;
+
ll_close_fail_log();
MEM_TRACK_RELEASE
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 00b12d50ae..512887cb1a 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -168,7 +168,7 @@ public:
// mute/unmute the system's master audio
virtual void setMasterSystemAudioMute(bool mute);
- virtual bool getMasterSystemAudioMute();
+ virtual bool getMasterSystemAudioMute();
// Metrics policy helper statics.
static void metricsUpdateRegion(U64 region_handle);
@@ -190,11 +190,12 @@ protected:
private:
+ void initMaxHeapSize();
bool initThreads(); // Initialize viewer threads, return false on failure.
bool initConfiguration(); // Initialize settings from the command line/config file.
void initUpdater(); // Initialize the updater service.
bool initCache(); // Initialize local client cache.
-
+ void checkMemory() ;
// We have switched locations of both Mac and Windows cache, make sure
// files migrate and old cache is cleared out.
@@ -268,8 +269,7 @@ private:
std::map<apr_dso_handle_t*, boost::shared_ptr<LLAPRPool> > mPlugins;
- U32 mAvailPhysicalMemInKB ;
- U32 mAvailVirtualMemInKB ;
+ LLFrameTimer mMemCheckTimer;
boost::scoped_ptr<LLUpdaterService> mUpdater;
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index c98bcbda45..5ff22f89ab 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -899,31 +899,14 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
}
}
- LLTextEditor* text_editor = notify_box->getChild<LLTextEditor>("text_editor_box", TRUE);
- S32 text_heigth = 0;
- if(text_editor != NULL)
- {
- text_heigth = text_editor->getTextBoundingRect().getHeight();
- }
-
//Prepare the rect for the view
LLRect target_rect = mEditor->getDocumentView()->getRect();
// squeeze down the widget by subtracting padding off left and right
target_rect.mLeft += mLeftWidgetPad + mEditor->getHPad();
target_rect.mRight -= mRightWidgetPad;
- notify_box->reshape(target_rect.getWidth(),
- notify_box->getRect().getHeight());
+ notify_box->reshape(target_rect.getWidth(), notify_box->getRect().getHeight());
notify_box->setOrigin(target_rect.mLeft, notify_box->getRect().mBottom);
- if (text_editor != NULL)
- {
- S32 text_heigth_delta =
- text_editor->getTextBoundingRect().getHeight()
- - text_heigth;
- notify_box->reshape(target_rect.getWidth(),
- notify_box->getRect().getHeight() + text_heigth_delta);
- }
-
LLInlineViewSegment::Params params;
params.view = notify_box;
params.left_pad = mLeftWidgetPad;
diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp
index 6f02192d0a..d77ebc5367 100644
--- a/indra/newview/llcolorswatch.cpp
+++ b/indra/newview/llcolorswatch.cpp
@@ -185,6 +185,10 @@ BOOL LLColorSwatchCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
llassert(getEnabled());
llassert(getVisible());
+ // Focus the widget now in order to return the focus
+ // after the color picker is closed.
+ setFocus(TRUE);
+
showPicker(FALSE);
}
}
diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp
index f781d5f3ff..fb9958ee9d 100644
--- a/indra/newview/lldynamictexture.cpp
+++ b/indra/newview/lldynamictexture.cpp
@@ -40,6 +40,7 @@
#include "llvertexbuffer.h"
#include "llviewerdisplay.h"
#include "llrender.h"
+#include "pipeline.h"
// static
LLViewerDynamicTexture::instance_list_t LLViewerDynamicTexture::sInstances[ LLViewerDynamicTexture::ORDER_COUNT ];
@@ -201,7 +202,7 @@ void LLViewerDynamicTexture::postRender(BOOL success)
BOOL LLViewerDynamicTexture::updateAllInstances()
{
sNumRenders = 0;
- if (gGLManager.mIsDisabled)
+ if (gGLManager.mIsDisabled || LLPipeline::sMemAllocationThrottled)
{
return TRUE;
}
diff --git a/indra/newview/llfloatermemleak.cpp b/indra/newview/llfloatermemleak.cpp
index 58931d112e..9edfe1e354 100644
--- a/indra/newview/llfloatermemleak.cpp
+++ b/indra/newview/llfloatermemleak.cpp
@@ -90,6 +90,11 @@ LLFloaterMemLeak::~LLFloaterMemLeak()
void LLFloaterMemLeak::release()
{
+ if(mLeakedMem.empty())
+ {
+ return ;
+ }
+
for(S32 i = 0 ; i < (S32)mLeakedMem.size() ; i++)
{
delete[] mLeakedMem[i] ;
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 9623554200..0ef502b81b 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -2719,6 +2719,15 @@ void LLIMMgr::inviteToSession(
{
LLFloaterReg::showInstance("incoming_call", payload, FALSE);
}
+
+ // Add the caller to the Recent List here (at this point
+ // "incoming_call" floater is shown and the recipient can
+ // reject the call), because even if a recipient will reject
+ // the call, the caller should be added to the recent list
+ // anyway. STORM-507.
+ if(type == IM_SESSION_P2P_INVITE)
+ LLRecentPeople::instance().add(caller_id);
+
mPendingInvitations[session_id.asString()] = LLSD();
}
}
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index 38100aa6c5..afceb58ccf 100644
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -143,6 +143,30 @@ void LLNameListCtrl::mouseOverHighlightNthItem( S32 target_index )
S32 cur_index = getHighlightedItemInx();
if (cur_index != target_index)
{
+ bool is_mouse_over_name_cell = false;
+
+ S32 mouse_x, mouse_y;
+ LLUI::getMousePositionLocal(this, &mouse_x, &mouse_y);
+
+ S32 column_index = getColumnIndexFromOffset(mouse_x);
+ LLScrollListItem* hit_item = hitItem(mouse_x, mouse_y);
+ if (hit_item && column_index == mNameColumnIndex)
+ {
+ // Get the name cell which is currently under the mouse pointer.
+ LLScrollListCell* hit_cell = hit_item->getColumn(column_index);
+ if (hit_cell)
+ {
+ is_mouse_over_name_cell = getCellRect(cur_index, column_index).pointInRect(mouse_x, mouse_y);
+ }
+ }
+
+ // If the tool tip is visible and the mouse is over the currently highlighted item's name cell,
+ // we should not reset the highlighted item index i.e. set mHighlightedItem = -1
+ // and should not increase the width of the text inside the cell because it may
+ // overlap the tool tip icon.
+ if (LLToolTipMgr::getInstance()->toolTipVisible() && is_mouse_over_name_cell)
+ return;
+
if(0 <= cur_index && cur_index < (S32)getItemList().size())
{
LLScrollListItem* item = getItemList()[cur_index];
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index a47ea8581a..11dff69e0c 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -113,7 +113,7 @@ public:
~LLTextureCacheWorker()
{
llassert_always(!haveWork());
- delete[] mReadData;
+ LLImageBase::deleteMemory(mReadData);
}
// override this interface
@@ -215,7 +215,7 @@ bool LLTextureCacheLocalFileWorker::doRead()
mDataSize = 0;
return true;
}
- mReadData = new U8[mDataSize];
+ mReadData = (U8*)LLImageBase::allocateMemory(mDataSize);
mBytesRead = -1;
mBytesToRead = mDataSize;
setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
@@ -233,7 +233,7 @@ bool LLTextureCacheLocalFileWorker::doRead()
// << " Bytes: " << mDataSize << " Offset: " << mOffset
// << " / " << mDataSize << llendl;
mDataSize = 0; // failed
- delete[] mReadData;
+ LLImageBase::deleteMemory(mReadData);
mReadData = NULL;
}
return true;
@@ -248,7 +248,7 @@ bool LLTextureCacheLocalFileWorker::doRead()
{
mDataSize = local_size;
}
- mReadData = new U8[mDataSize];
+ mReadData = (U8*)LLImageBase::allocateMemory(mDataSize);
S32 bytes_read = LLAPRFile::readEx(mFileName, mReadData, mOffset, mDataSize);
@@ -258,7 +258,7 @@ bool LLTextureCacheLocalFileWorker::doRead()
// << " Bytes: " << mDataSize << " Offset: " << mOffset
// << " / " << mDataSize << llendl;
mDataSize = 0;
- delete[] mReadData;
+ LLImageBase::deleteMemory(mReadData);
mReadData = NULL;
}
else
@@ -377,7 +377,7 @@ bool LLTextureCacheRemoteWorker::doRead()
mDataSize = local_size;
}
// Allocate read buffer
- mReadData = new U8[mDataSize];
+ mReadData = (U8*)LLImageBase::allocateMemory(mDataSize);
S32 bytes_read = LLAPRFile::readEx(local_filename, mReadData, mOffset, mDataSize);
if (bytes_read != mDataSize)
{
@@ -385,7 +385,7 @@ bool LLTextureCacheRemoteWorker::doRead()
<< " Bytes: " << mDataSize << " Offset: " << mOffset
<< " / " << mDataSize << llendl;
mDataSize = 0;
- delete[] mReadData;
+ LLImageBase::deleteMemory(mReadData);
mReadData = NULL;
}
else
@@ -428,14 +428,14 @@ bool LLTextureCacheRemoteWorker::doRead()
S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
size = llmin(size, mDataSize);
// Allocate the read buffer
- mReadData = new U8[size];
+ mReadData = (U8*)LLImageBase::allocateMemory(size);
S32 bytes_read = LLAPRFile::readEx(mCache->mHeaderDataFileName, mReadData, offset, size);
if (bytes_read != size)
{
llwarns << "LLTextureCacheWorker: " << mID
<< " incorrect number of bytes read from header: " << bytes_read
<< " / " << size << llendl;
- delete[] mReadData;
+ LLImageBase::deleteMemory(mReadData);
mReadData = NULL;
mDataSize = -1; // failed
done = true;
@@ -465,7 +465,7 @@ bool LLTextureCacheRemoteWorker::doRead()
S32 data_offset, file_size, file_offset;
// Reserve the whole data buffer first
- U8* data = new U8[mDataSize];
+ U8* data = (U8*)LLImageBase::allocateMemory(mDataSize);
// Set the data file pointers taking the read offset into account. 2 cases:
if (mOffset < TEXTURE_CACHE_ENTRY_SIZE)
@@ -478,7 +478,7 @@ bool LLTextureCacheRemoteWorker::doRead()
// Copy the raw data we've been holding from the header cache into the new sized buffer
llassert_always(mReadData);
memcpy(data, mReadData, data_offset);
- delete[] mReadData;
+ LLImageBase::deleteMemory(mReadData);
mReadData = NULL;
}
else
@@ -503,7 +503,7 @@ bool LLTextureCacheRemoteWorker::doRead()
llwarns << "LLTextureCacheWorker: " << mID
<< " incorrect number of bytes read from body: " << bytes_read
<< " / " << file_size << llendl;
- delete[] mReadData;
+ LLImageBase::deleteMemory(mReadData);
mReadData = NULL;
mDataSize = -1; // failed
done = true;
@@ -595,11 +595,11 @@ bool LLTextureCacheRemoteWorker::doWrite()
{
// We need to write a full record in the header cache so, if the amount of data is smaller
// than a record, we need to transfer the data to a buffer padded with 0 and write that
- U8* padBuffer = new U8[TEXTURE_CACHE_ENTRY_SIZE];
+ U8* padBuffer = (U8*)LLImageBase::allocateMemory(TEXTURE_CACHE_ENTRY_SIZE);
memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE); // Init with zeros
memcpy(padBuffer, mWriteData, mDataSize); // Copy the write buffer
bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size);
- delete [] padBuffer;
+ LLImageBase::deleteMemory(padBuffer);
}
else
{
@@ -694,7 +694,7 @@ void LLTextureCacheWorker::finishWork(S32 param, bool completed)
}
else
{
- delete[] mReadData;
+ LLImageBase::deleteMemory(mReadData);
mReadData = NULL;
}
}
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 139b434aeb..806f130486 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -816,7 +816,7 @@ void LLTextureFetchWorker::setImagePriority(F32 priority)
void LLTextureFetchWorker::resetFormattedData()
{
- delete[] mBuffer;
+ LLImageBase::deleteMemory(mBuffer);
mBuffer = NULL;
mBufferSize = 0;
if (mFormattedImage.notNull())
@@ -887,7 +887,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
mSentRequest = UNSENT;
mDecoded = FALSE;
mWritten = FALSE;
- delete[] mBuffer;
+ LLImageBase::deleteMemory(mBuffer);
mBuffer = NULL;
mBufferSize = 0;
mHaveAllData = FALSE;
@@ -1283,7 +1283,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
llassert_always(mBufferSize == cur_size + mRequestedSize);
if(!mBufferSize)//no data received.
{
- delete[] mBuffer;
+ LLImageBase::deleteMemory(mBuffer);
mBuffer = NULL;
//abort.
@@ -1311,7 +1311,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
mFileSize = mBufferSize + 1 ; //flag the file is not fully loaded.
}
- U8* buffer = new U8[mBufferSize];
+ U8* buffer = (U8*)LLImageBase::allocateMemory(mBufferSize);
if (cur_size > 0)
{
memcpy(buffer, mFormattedImage->getData(), cur_size);
@@ -1320,7 +1320,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
// NOTE: setData releases current data and owns new data (buffer)
mFormattedImage->setData(buffer, mBufferSize);
// delete temp data
- delete[] mBuffer; // Note: not 'buffer' (assigned in setData())
+ LLImageBase::deleteMemory(mBuffer); // Note: not 'buffer' (assigned in setData())
mBuffer = NULL;
mBufferSize = 0;
mLoadedDiscard = mRequestedDiscard;
@@ -1617,7 +1617,7 @@ bool LLTextureFetchWorker::processSimulatorPackets()
if (buffer_size > cur_size)
{
/// We have new data
- U8* buffer = new U8[buffer_size];
+ U8* buffer = (U8*)LLImageBase::allocateMemory(buffer_size);
S32 offset = 0;
if (cur_size > 0 && mFirstPacket > 0)
{
@@ -1669,7 +1669,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
if (data_size > 0)
{
// *TODO: set the formatted image data here directly to avoid the copy
- mBuffer = new U8[data_size];
+ mBuffer = (U8*)LLImageBase::allocateMemory(data_size);
buffer->readAfter(channels.in(), NULL, mBuffer, data_size);
mBufferSize += data_size;
if (data_size < mRequestedSize && mRequestedDiscard == 0)
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 3f7dc24ade..fa91f129b8 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -563,7 +563,17 @@ void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_paren
height = rc.getHeight();
width = rc.getWidth();
+ bool is_width_changed = width != getRect().getWidth();
+
LLToastPanel::reshape(width, height, called_from_parent);
+
+ // Notification height required to display the text message depends on
+ // the width of the text box thus if panel width is changed the text box
+ // width is also changed then reshape() is called to adjust proper height.
+ if (is_width_changed)
+ {
+ reshape(width, height, called_from_parent);
+ }
}
// EOF
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 8c5a52c187..3c53e54203 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -309,6 +309,15 @@ static bool handleRenderUseVBOChanged(const LLSD& newvalue)
return true;
}
+static bool handleRenderUseVBOMappingChanged(const LLSD& newvalue)
+{
+ if (gPipeline.isInit())
+ {
+ gPipeline.setDisableVBOMapping(newvalue.asBoolean());
+ }
+ return true;
+}
+
static bool handleWLSkyDetailChanged(const LLSD&)
{
if (gSky.mVOWLSkyp.notNull())
@@ -589,6 +598,7 @@ void settings_setup_listeners()
gSavedSettings.getControl("MuteAmbient")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));
gSavedSettings.getControl("MuteUI")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _2));
gSavedSettings.getControl("RenderVBOEnable")->getSignal()->connect(boost::bind(&handleRenderUseVBOChanged, _2));
+ gSavedSettings.getControl("RenderVBOMappingDisable")->getSignal()->connect(boost::bind(&handleRenderUseVBOMappingChanged, _2));
gSavedSettings.getControl("RenderUseStreamVBO")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
gSavedSettings.getControl("WLSkyDetail")->getSignal()->connect(boost::bind(&handleWLSkyDetailChanged, _2));
gSavedSettings.getControl("NumpadControl")->getSignal()->connect(boost::bind(&handleNumpadControlChanged, _2));
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 41b7c13826..b9d81a76ff 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -203,6 +203,7 @@ void display_stats()
gMemoryAllocated = LLMemory::getCurrentRSS();
U32 memory = (U32)(gMemoryAllocated / (1024*1024));
llinfos << llformat("MEMORY: %d MB", memory) << llendl;
+ LLMemory::logMemoryInfo() ;
gRecentMemoryTime.reset();
}
}
@@ -690,7 +691,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
glh::matrix4f mod = glh_get_current_modelview();
glViewport(0,0,512,512);
LLVOAvatar::updateFreezeCounter() ;
- LLVOAvatar::updateImpostors();
+
+ if(!LLPipeline::sMemAllocationThrottled)
+ {
+ LLVOAvatar::updateImpostors();
+ }
glh_set_current_projection(proj);
glh_set_current_modelview(mod);
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index f16d8814dd..900081b8c6 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -53,7 +53,7 @@
#include "llwebsharing.h" // For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this!
#include "llfilepicker.h"
#include "llnotifications.h"
-
+#include "lldir.h"
#include "llevent.h" // LLSimpleListener
#include "llnotificationsutil.h"
#include "lluuid.h"
@@ -1766,7 +1766,8 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
media_source->setTarget(target);
- if (media_source->init(launcher_name, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")))
+ const std::string plugin_dir = gDirUtilp->getLLPluginDir();
+ if (media_source->init(launcher_name, plugin_dir, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")))
{
return media_source;
}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 090d3cadd4..32cd8dbb39 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -477,7 +477,6 @@ void LLViewerObject::initVOClasses()
llinfos << "Viewer Object size: " << sizeof(LLViewerObject) << llendl;
LLVOGrass::initClass();
LLVOWater::initClass();
- LLVOSky::initClass();
LLVOVolume::initClass();
}
@@ -3009,6 +3008,8 @@ void LLViewerObject::setScale(const LLVector3 &scale, BOOL damped)
{
if (!mOnMap)
{
+ llassert_always(LLWorld::getInstance()->getRegionFromHandle(getRegion()->getHandle()));
+
gObjectList.addToMap(this);
mOnMap = TRUE;
}
@@ -3536,8 +3537,8 @@ void LLViewerObject::setPositionParent(const LLVector3 &pos_parent, BOOL damped)
// Set position relative to parent, if no parent, relative to region
if (!isRoot())
{
- LLViewerObject::setPosition(pos_parent);
- updateDrawable(damped);
+ LLViewerObject::setPosition(pos_parent, damped);
+ //updateDrawable(damped);
}
else
{
@@ -3578,6 +3579,7 @@ void LLViewerObject::setPositionEdit(const LLVector3 &pos_edit, BOOL damped)
LLVector3 position_offset = getPosition() * getParent()->getRotation();
((LLViewerObject *)getParent())->setPositionEdit(pos_edit - position_offset);
+ updateDrawable(damped);
}
else if (isJointChild())
{
@@ -3586,15 +3588,14 @@ void LLViewerObject::setPositionEdit(const LLVector3 &pos_edit, BOOL damped)
LLQuaternion inv_parent_rot = parent->getRotation();
inv_parent_rot.transQuat();
LLVector3 pos_parent = (pos_edit - parent->getPositionRegion()) * inv_parent_rot;
- LLViewerObject::setPosition(pos_parent);
+ LLViewerObject::setPosition(pos_parent, damped);
}
else
{
- LLViewerObject::setPosition(pos_edit);
+ LLViewerObject::setPosition(pos_edit, damped);
mPositionRegion = pos_edit;
mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion);
- }
- updateDrawable(damped);
+ }
}
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 970cc2e2a7..82bc164021 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -1124,6 +1124,22 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset)
LLWorld::getInstance()->shiftRegions(offset);
}
+//debug code
+bool LLViewerObjectList::hasMapObjectInRegion(LLViewerRegion* regionp)
+{
+ for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter)
+ {
+ LLViewerObject* objectp = *iter;
+
+ if(objectp->isDead() || objectp->getRegion() == regionp)
+ {
+ return true ;
+ }
+ }
+
+ return false ;
+}
+
void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap)
{
LLColor4 above_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnAboveWater" );
@@ -1142,6 +1158,9 @@ void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap)
for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter)
{
LLViewerObject* objectp = *iter;
+
+ llassert_always(!objectp->isDead());
+
if (!objectp->getRegion() || objectp->isOrphaned() || objectp->isAttachment())
{
continue;
@@ -1429,7 +1448,7 @@ LLViewerObject *LLViewerObjectList::replaceObject(const LLUUID &id, const LLPCod
LLViewerObject *old_instance = findObject(id);
if (old_instance)
{
- cleanupReferences(old_instance);
+ //cleanupReferences(old_instance);
old_instance->markDead();
return createObject(pcode, regionp, id, old_instance->getLocalID(), LLHost());
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index fda3d6899d..8cff8e988a 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -87,6 +87,7 @@ public:
void shiftObjects(const LLVector3 &offset);
+ bool hasMapObjectInRegion(LLViewerRegion* regionp) ;
void renderObjectsForMap(LLNetMap &netmap);
void renderObjectBounds(const LLVector3 &center);
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index cd16b15e3e..23d6ca1ae2 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -3080,9 +3080,16 @@ void LLViewerLODTexture::processTextureStats()
{
mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel) ;
}
+ else if(LLPipeline::sMemAllocationThrottled)//release memory of large textures by decrease their resolutions.
+ {
+ if(scaleDown())
+ {
+ mDesiredDiscardLevel = mCachedRawDiscardLevel ;
+ }
+ }
}
-void LLViewerLODTexture::scaleDown()
+bool LLViewerLODTexture::scaleDown()
{
if(hasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel())
{
@@ -3093,7 +3100,10 @@ void LLViewerLODTexture::scaleDown()
{
tester->setStablizingTime() ;
}
+
+ return true ;
}
+ return false ;
}
//----------------------------------------------------------------------------------------------
//end of LLViewerLODTexture
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index b5636bbdc7..07b91c2071 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -595,7 +595,7 @@ public:
private:
void init(bool firstinit) ;
- void scaleDown() ;
+ bool scaleDown() ;
private:
F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 274dbe2cc8..dfdf429455 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -561,6 +561,17 @@ public:
addText(xpos, ypos, llformat("%d %d %d %d", color[0], color[1], color[2], color[3]));
ypos += y_inc;
}
+
+ if (gSavedSettings.getBOOL("DebugShowPrivateMem"))
+ {
+ LLPrivateMemoryPoolManager::getInstance()->updateStatistics() ;
+ addText(xpos, ypos, llformat("Total Reserved(KB): %d", LLPrivateMemoryPoolManager::getInstance()->mTotalReservedSize / 1024));
+ ypos += y_inc;
+
+ addText(xpos, ypos, llformat("Total Allocated(KB): %d", LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024));
+ ypos += y_inc;
+ }
+
// only display these messages if we are actually rendering beacons at this moment
if (LLPipeline::getRenderBeacons(NULL) && LLFloaterReg::instanceVisible("beacons"))
{
@@ -1477,7 +1488,7 @@ LLViewerWindow::LLViewerWindow(
{
gSavedSettings.setBOOL("RenderVBOEnable", FALSE);
}
- LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"));
+ LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable"));
if (LLFeatureManager::getInstance()->isSafe()
|| (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion())
@@ -3978,6 +3989,19 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
{
return FALSE;
}
+ //check if there is enough memory for the snapshot image
+ if(LLPipeline::sMemAllocationThrottled)
+ {
+ return FALSE ; //snapshot taking is disabled due to memory restriction.
+ }
+ if(image_width * image_height > (1 << 22)) //if snapshot image is larger than 2K by 2K
+ {
+ if(!LLMemory::tryToAlloc(NULL, image_width * image_height * 3))
+ {
+ llwarns << "No enough memory to take the snapshot with size (w : h): " << image_width << " : " << image_height << llendl ;
+ return FALSE ; //there is no enough memory for taking this snapshot.
+ }
+ }
// PRE SNAPSHOT
gDisplaySwapBuffers = FALSE;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 2cd9b09932..d58628942e 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -599,16 +599,16 @@ F32 LLVOAvatar::sRenderDistance = 256.f;
S32 LLVOAvatar::sNumVisibleAvatars = 0;
S32 LLVOAvatar::sNumLODChangesThisFrame = 0;
-const LLUUID LLVOAvatar::sStepSoundOnLand = LLUUID("e8af4a28-aa83-4310-a7c4-c047e15ea0df");
+const LLUUID LLVOAvatar::sStepSoundOnLand("e8af4a28-aa83-4310-a7c4-c047e15ea0df");
const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] =
{
- LLUUID(SND_STONE_RUBBER),
- LLUUID(SND_METAL_RUBBER),
- LLUUID(SND_GLASS_RUBBER),
- LLUUID(SND_WOOD_RUBBER),
- LLUUID(SND_FLESH_RUBBER),
- LLUUID(SND_RUBBER_PLASTIC),
- LLUUID(SND_RUBBER_RUBBER)
+ SND_STONE_RUBBER,
+ SND_METAL_RUBBER,
+ SND_GLASS_RUBBER,
+ SND_WOOD_RUBBER,
+ SND_FLESH_RUBBER,
+ SND_RUBBER_PLASTIC,
+ SND_RUBBER_RUBBER
};
S32 LLVOAvatar::sRenderName = RENDER_NAME_ALWAYS;
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 7ae8c2c07d..80f43e51d2 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -77,9 +77,6 @@ static const LLVector2 TEX11 = LLVector2(1.f, 1.f);
LLUUID gSunTextureID = IMG_SUN;
LLUUID gMoonTextureID = IMG_MOON;
-//static
-LLColor3 LLHaze::sAirScaSeaLevel;
-
class LLFastLn
{
public:
@@ -182,6 +179,23 @@ inline void color_gamma_correct(LLColor3 &col)
}
}
+static LLColor3 calc_air_sca_sea_level()
+{
+ static LLColor3 WAVE_LEN(675, 520, 445);
+ static LLColor3 refr_ind = refr_ind_calc(WAVE_LEN);
+ static LLColor3 n21 = refr_ind * refr_ind - LLColor3(1, 1, 1);
+ static LLColor3 n4 = n21 * n21;
+ static LLColor3 wl2 = WAVE_LEN * WAVE_LEN * 1e-6f;
+ static LLColor3 wl4 = wl2 * wl2;
+ static LLColor3 mult_const = fsigma * 2.0f/ 3.0f * 1e24f * (F_PI * F_PI) * n4;
+ static F32 dens_div_N = F32( ATM_SEA_LEVEL_NDENS / Ndens2);
+ return dens_div_N * color_div ( mult_const, wl4 );
+}
+
+// static constants.
+LLColor3 const LLHaze::sAirScaSeaLevel = calc_air_sca_sea_level();
+F32 const LLHaze::sAirScaIntense = color_intens(LLHaze::sAirScaSeaLevel);
+F32 const LLHaze::sAirScaAvg = LLHaze::sAirScaIntense / 3.f;
/***************************************
@@ -394,12 +408,6 @@ LLVOSky::~LLVOSky()
mCubeMap = NULL;
}
-void LLVOSky::initClass()
-{
- LLHaze::initClass();
-}
-
-
void LLVOSky::init()
{
const F32 haze_int = color_intens(mHaze.calcSigSca(0));
@@ -2147,17 +2155,8 @@ void LLVOSky::updateFog(const F32 distance)
stop_glerror();
}
-// static
-void LLHaze::initClass()
-{
- sAirScaSeaLevel = LLHaze::calcAirScaSeaLevel();
-}
-
-
// Functions used a lot.
-
-
F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply)
{
F32 mv = color_max(col);
diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h
index 6b3e7873a1..d3a42583ea 100644
--- a/indra/newview/llvosky.h
+++ b/indra/newview/llvosky.h
@@ -292,23 +292,6 @@ LL_FORCE_INLINE LLColor3 refr_ind_calc(const LLColor3 &wave_length)
}
-LL_FORCE_INLINE LLColor3 calc_air_sca_sea_level()
-{
- const static LLColor3 WAVE_LEN(675, 520, 445);
- const static LLColor3 refr_ind = refr_ind_calc(WAVE_LEN);
- const static LLColor3 n21 = refr_ind * refr_ind - LLColor3(1, 1, 1);
- const static LLColor3 n4 = n21 * n21;
- const static LLColor3 wl2 = WAVE_LEN * WAVE_LEN * 1e-6f;
- const static LLColor3 wl4 = wl2 * wl2;
- const static LLColor3 mult_const = fsigma * 2.0f/ 3.0f * 1e24f * (F_PI * F_PI) * n4;
- const static F32 dens_div_N = F32( ATM_SEA_LEVEL_NDENS / Ndens2);
- return dens_div_N * color_div ( mult_const, wl4 );
-}
-
-const LLColor3 gAirScaSeaLevel = calc_air_sca_sea_level();
-const F32 AIR_SCA_INTENS = color_intens(gAirScaSeaLevel);
-const F32 AIR_SCA_AVG = AIR_SCA_INTENS / 3.f;
-
class LLHaze
{
public:
@@ -316,18 +299,15 @@ public:
LLHaze(const F32 g, const LLColor3& sca, const F32 fo = 2.f) :
mG(g), mSigSca(0.25f/F_PI * sca), mFalloff(fo), mAbsCoef(0.f)
{
- mAbsCoef = color_intens(mSigSca) / AIR_SCA_INTENS;
+ mAbsCoef = color_intens(mSigSca) / sAirScaIntense;
}
LLHaze(const F32 g, const F32 sca, const F32 fo = 2.f) : mG(g),
mSigSca(0.25f/F_PI * LLColor3(sca, sca, sca)), mFalloff(fo)
{
- mAbsCoef = 0.01f * sca / AIR_SCA_AVG;
+ mAbsCoef = 0.01f * sca / sAirScaAvg;
}
- static void initClass();
-
-
F32 getG() const { return mG; }
void setG(const F32 g)
@@ -343,12 +323,12 @@ public:
void setSigSca(const LLColor3& s)
{
mSigSca = s;
- mAbsCoef = 0.01f * color_intens(mSigSca) / AIR_SCA_INTENS;
+ mAbsCoef = 0.01f * color_intens(mSigSca) / sAirScaIntense;
}
void setSigSca(const F32 s0, const F32 s1, const F32 s2)
{
- mSigSca = AIR_SCA_AVG * LLColor3 (s0, s1, s2);
+ mSigSca = sAirScaAvg * LLColor3 (s0, s1, s2);
mAbsCoef = 0.01f * (s0 + s1 + s2) / 3;
}
@@ -392,10 +372,11 @@ public:
static inline LLColor3 calcAirSca(const F32 h);
static inline void calcAirSca(const F32 h, LLColor3 &result);
- static LLColor3 calcAirScaSeaLevel() { return gAirScaSeaLevel; }
- static const LLColor3 &getAirScaSeaLevel() { return sAirScaSeaLevel; }
-public:
- static LLColor3 sAirScaSeaLevel;
+
+private:
+ static LLColor3 const sAirScaSeaLevel;
+ static F32 const sAirScaIntense;
+ static F32 const sAirScaAvg;
protected:
F32 mG;
@@ -473,7 +454,6 @@ public:
LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
// Initialize/delete data that's only inited once per class.
- static void initClass();
void init();
void initCubeMap();
void initEmpty();
@@ -654,14 +634,12 @@ F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply = FALSE);
inline LLColor3 LLHaze::calcAirSca(const F32 h)
{
- static const LLColor3 air_sca_sea_level = calcAirScaSeaLevel();
- return calcFalloff(h) * air_sca_sea_level;
+ return calcFalloff(h) * sAirScaSeaLevel;
}
inline void LLHaze::calcAirSca(const F32 h, LLColor3 &result)
{
- static const LLColor3 air_sca_sea_level = calcAirScaSeaLevel();
- result = air_sca_sea_level;
+ result = sAirScaSeaLevel;
result *= calcFalloff(h);
}
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 399442e5c4..9db6d5e08c 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -281,6 +281,8 @@ void LLWorld::removeRegion(const LLHost &host)
delete regionp;
updateWaterObjects();
+
+ llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ;
}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 39bc354250..53564ec0f8 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -100,6 +100,7 @@
#include "llspatialpartition.h"
#include "llmutelist.h"
#include "lltoolpie.h"
+#include "llnotifications.h"
#ifdef _DEBUG
@@ -281,6 +282,7 @@ BOOL LLPipeline::sRenderAttachedLights = TRUE;
BOOL LLPipeline::sRenderAttachedParticles = TRUE;
BOOL LLPipeline::sRenderDeferred = FALSE;
BOOL LLPipeline::sAllowRebuildPriorityGroup = FALSE ;
+BOOL LLPipeline::sMemAllocationThrottled = FALSE;
S32 LLPipeline::sVisibleLightCount = 0;
F32 LLPipeline::sMinRenderSize = 0.f;
@@ -513,6 +515,24 @@ void LLPipeline::destroyGL()
static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture");
+//static
+void LLPipeline::throttleNewMemoryAllocation(BOOL disable)
+{
+ if(sMemAllocationThrottled != disable)
+ {
+ sMemAllocationThrottled = disable ;
+
+ if(sMemAllocationThrottled)
+ {
+ //send out notification
+ LLNotification::Params params("LowMemory");
+ LLNotifications::instance().add(params);
+
+ //release some memory.
+ }
+ }
+}
+
void LLPipeline::resizeScreenTexture()
{
LLFastTimer ft(FTM_RESIZE_SCREEN_TEXTURE);
@@ -5313,7 +5333,25 @@ void LLPipeline::setUseVBO(BOOL use_vbo)
}
resetVertexBuffers();
- LLVertexBuffer::initClass(use_vbo);
+ LLVertexBuffer::initClass(use_vbo, gSavedSettings.getBOOL("RenderVBOMappingDisable"));
+ }
+}
+
+void LLPipeline::setDisableVBOMapping(BOOL no_vbo_mapping)
+{
+ if (LLVertexBuffer::sEnableVBOs && no_vbo_mapping != LLVertexBuffer::sDisableVBOMapping)
+ {
+ if (no_vbo_mapping)
+ {
+ llinfos << "Disabling VBO glMapBufferARB." << llendl;
+ }
+ else
+ {
+ llinfos << "Enabling VBO glMapBufferARB." << llendl;
+ }
+
+ resetVertexBuffers();
+ LLVertexBuffer::initClass(true, no_vbo_mapping);
}
}
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index cef3d87f36..4a7cc77bde 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -111,6 +111,7 @@ public:
void resetVertexBuffers(LLDrawable* drawable);
void setUseVBO(BOOL use_vbo);
+ void setDisableVBOMapping(BOOL no_vbo_mapping);
void generateImpostor(LLVOAvatar* avatar);
void bindScreenToTexture();
void renderBloom(BOOL for_snapshot, F32 zoom_factor = 1.f, int subfield = 0);
@@ -333,6 +334,8 @@ public:
static void updateRenderDeferred();
+ static void throttleNewMemoryAllocation(BOOL disable);
+
private:
void unloadShaders();
void addToQuickLookup( LLDrawPool* new_poolp );
@@ -478,8 +481,9 @@ public:
static BOOL sRenderAttachedParticles;
static BOOL sRenderDeferred;
static BOOL sAllowRebuildPriorityGroup;
+ static BOOL sMemAllocationThrottled;
static S32 sVisibleLightCount;
- static F32 sMinRenderSize;
+ static F32 sMinRenderSize;
//screen texture
U32 mScreenWidth;
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 3dd6c60095..937a97797d 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -1905,7 +1905,7 @@ Only large parcels can be listed in search.
</panel.string>
<panel.string
name="allow_public_access">
- Allow Public Access ([MATURITY])
+ Allow Public Access ([MATURITY]) (Note: Unchecking this will create ban lines)
</panel.string>
<panel.string
name="estate_override">
@@ -1932,7 +1932,7 @@ Only large parcels can be listed in search.
name="public_access"
top_pad="5"
label_text.valign="center"
- label_text.v_pad="-7"
+ label_text.v_pad="-2"
width="278" />
<text
type="string"
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 08ae0c233e..6963b5bb45 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2000,6 +2000,16 @@
function="ToggleControl"
parameter="DebugShowMemory" />
</menu_item_check>
+ <menu_item_check
+ label="Show Private Mem Info"
+ name="Show Private Mem Info">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugShowPrivateMem" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugShowPrivateMem" />
+ </menu_item_check>
<menu_item_separator/>
@@ -2747,18 +2757,6 @@
function="Floater.Toggle"
parameter="region_debug_console" />
</menu_item_check>
- <menu_item_check
- label="Region Debug Console"
- name="Region Debug Console"
- shortcut="control|shift|`"
- use_mac_ctrl="true">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="region_debug_console" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="region_debug_console" />
- </menu_item_check>
<menu_item_separator />
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index f008042a81..fcb4123b2e 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6680,6 +6680,20 @@ Mute everyone?
Here's your current balance of L$. Click Buy L$ to purchase more Linden Dollars.
</notification>
+ <notification
+ icon="alertmodal.tga"
+ name="LowMemory"
+ type="alertmodal">
+ Your memory pool is low. Some functions of SL are disabled to avoid crash. Please close other applications. Restart SL if this persists.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ForceQuitDueToLowMemory"
+ type="alertmodal">
+ SL will quit in 30 seconds due to out of memory.
+ </notification>
+
<notification
name="PopupAttempt"
icon="Popup_Caution"
diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp
index fd46626ff1..30fa832c7d 100644
--- a/indra/test_apps/llplugintest/llmediaplugintest.cpp
+++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp
@@ -1616,7 +1616,7 @@ mediaPanel* LLMediaPluginTest::addMediaPanel( std::string url )
std::string user_data_path = std::string( cwd ) + "/";
#endif
media_source->setUserDataPath(user_data_path);
- media_source->init( launcher_name, plugin_name, false );
+ media_source->init( launcher_name, user_data_path, plugin_name, false );
media_source->setDisableTimeout(mDisableTimeout);
// make a new panel and save parameters
@@ -1856,7 +1856,7 @@ mediaPanel* LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string
#endif
media_source->setUserDataPath(user_data_path);
- media_source->init( launcher_name, plugin_name, false );
+ media_source->init( launcher_name, user_data_path, plugin_name, false );
media_source->setDisableTimeout(mDisableTimeout);
// make a new panel and save parameters